2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "application_manager.h"
22 #include <type_traits>
24 #include <app_control_internal.h>
26 #include <app_manager_extension.h>
30 #include <bundle_internal.h>
31 #include <package_manager.h>
32 #include <pkgmgr-info.h>
33 #include <pkgmgr_installer.h>
35 #include "common/current_application.h"
36 #include "common/logger.h"
37 #include "common/platform_result.h"
38 #include "common/scope_exit.h"
39 #include "common/task-queue.h"
40 #include "common/tools.h"
42 #include "application/application_instance.h"
43 #include "application/application_utils.h"
45 using namespace common;
46 using namespace tools;
49 namespace application {
52 const std::string kTizenApisFileScheme = "file://";
53 const std::string kTizenApisAppSlash = "/";
54 const std::string kTizenApisAppShared = "shared";
56 const char* kStartKey = PKGMGR_INSTALLER_START_KEY_STR;
57 const char* kEndKey = PKGMGR_INSTALLER_END_KEY_STR;
58 const char* kOkValue = PKGMGR_INSTALLER_OK_EVENT_STR;
59 const char* kInstallEvent = PKGMGR_INSTALLER_INSTALL_EVENT_STR;
60 const char* kUpdateEvent = PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
61 const char* kUninstallEvent = PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
63 const char* kAppidKey = "appid";
65 const std::string kAction = "action";
66 const std::string kCallbackId = "callbackId";
67 const std::string kOnInstalled = "oninstalled";
68 const std::string kOnUpdated = "onupdated";
69 const std::string kOnUninstalled = "onuninstalled";
70 const std::string kData = "data";
71 const std::string kStatusType = "statusType";
72 const std::string kAppId = "appId";
73 const std::string kListenerId = "listenerId";
74 const std::string kAppStatusChangeListener = "AppStatusChangeListener";
75 const std::string kAppUsageModeFrequently = "FREQUENTLY";
76 const std::string kAppUsageModeRecently = "RECENTLY";
78 const std::map<std::string, std::string> event_map_ = {
79 {SYSTEM_EVENT_BATTERY_CHARGER_STATUS, EVENT_KEY_BATTERY_CHARGER_STATUS},
80 {SYSTEM_EVENT_BATTERY_LEVEL_STATUS, EVENT_KEY_BATTERY_LEVEL_STATUS},
81 {SYSTEM_EVENT_USB_STATUS, EVENT_KEY_USB_STATUS},
82 {SYSTEM_EVENT_EARJACK_STATUS, EVENT_KEY_EARJACK_STATUS},
83 {SYSTEM_EVENT_DISPLAY_STATE, EVENT_KEY_DISPLAY_STATE},
84 {SYSTEM_EVENT_LOW_MEMORY, EVENT_KEY_LOW_MEMORY},
85 {SYSTEM_EVENT_WIFI_STATE, EVENT_KEY_WIFI_STATE},
86 {SYSTEM_EVENT_BT_STATE, EVENT_KEY_BT_STATE},
87 {SYSTEM_EVENT_LOCATION_ENABLE_STATE, EVENT_KEY_LOCATION_ENABLE_STATE},
88 {SYSTEM_EVENT_GPS_ENABLE_STATE, EVENT_KEY_GPS_ENABLE_STATE},
89 {SYSTEM_EVENT_NPS_ENABLE_STATE, EVENT_KEY_NPS_ENABLE_STATE},
90 {SYSTEM_EVENT_INCOMING_MSG, EVENT_KEY_MSG_TYPE},
91 {SYSTEM_EVENT_TIME_ZONE, EVENT_KEY_TIME_ZONE},
92 {SYSTEM_EVENT_HOUR_FORMAT, EVENT_KEY_HOUR_FORMAT},
93 {SYSTEM_EVENT_LANGUAGE_SET, EVENT_KEY_LANGUAGE_SET},
94 {SYSTEM_EVENT_REGION_FORMAT, EVENT_KEY_REGION_FORMAT},
95 {SYSTEM_EVENT_SILENT_MODE, EVENT_KEY_SILENT_MODE},
96 {SYSTEM_EVENT_VIBRATION_STATE, EVENT_KEY_VIBRATION_STATE},
97 {SYSTEM_EVENT_SCREEN_AUTOROTATE_STATE, EVENT_KEY_SCREEN_AUTOROTATE_STATE},
98 {SYSTEM_EVENT_MOBILE_DATA_STATE, EVENT_KEY_MOBILE_DATA_STATE},
99 {SYSTEM_EVENT_DATA_ROAMING_STATE, EVENT_KEY_DATA_ROAMING_STATE},
100 {SYSTEM_EVENT_FONT_SET, EVENT_KEY_FONT_SET}};
102 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
103 const int kMaximumBatteryRetrievedObjects = 30;
104 const int kMaximumAppsRetrievedObjects = 10;
105 const int kDefaultPeriodOfTime = 30;
109 std::set<LaunchAppControlCallbackData*> ApplicationManager::launch_app_control_set_global_{};
110 std::mutex ApplicationManager::launch_app_control_set_mutex_{};
112 ApplicationManager::ApplicationManager(ApplicationInstance& instance)
113 : pkgmgr_client_handle_(nullptr),
114 pkgmgr_client_uninstall_handle_(nullptr),
116 app_status_handle_(nullptr) {
120 ApplicationManager::~ApplicationManager() {
122 StopAppInfoEventListener();
123 StopStatusChangeListener();
125 for (auto it = event_handler_map_.begin(); it != event_handler_map_.end();) {
126 int ret = event_remove_event_handler(it->second);
127 if (EVENT_ERROR_NONE != ret) {
128 LoggerE("event_remove_event_handler failed, error: %d (%s)", ret, get_error_message(ret));
130 it = event_handler_map_.erase(it);
133 if (app_status_handle_) {
134 int ret = app_manager_event_destroy(app_status_handle_);
135 if (APP_MANAGER_ERROR_NONE != ret) {
136 LoggerE("app_manager_event_destroy failed, error: %d", ret);
140 // Calling order of reply_callback and result_callback of launchAppControl
141 // cannot be determined, reply_callback depends on application scenario, which
142 // cannot be predicted. Moreover reply_callback is optional and can be called or not,
143 // thus callback_data is relesed here at the end of application lifetime.
144 std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
145 std::for_each(launch_app_control_set_.begin(), launch_app_control_set_.end(),
146 [](LaunchAppControlCallbackData* const& data) {
147 LoggerD("Releasing callback data: %p", data);
149 launch_app_control_set_global_.erase(data);
153 void ApplicationManager::GetCurrentApplication(const std::string& app_id, picojson::object* out) {
156 // obtain handle to application info
157 pkgmgrinfo_appinfo_h handle;
158 int ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle);
159 if (PMINFO_R_OK != ret) {
160 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get app info."), out,
161 ("Failed to get app info: %d (%s)", ret, get_error_message(ret)));
165 picojson::value app_info = picojson::value(picojson::object());
166 picojson::object& app_info_obj = app_info.get<picojson::object>();
168 utils::CreateApplicationInformation(handle, &app_info_obj);
169 pkgmgrinfo_appinfo_destroy_appinfo(handle);
171 picojson::value result = picojson::value(picojson::object());
172 picojson::object& result_obj = result.get<picojson::object>();
174 result_obj.insert(std::make_pair(
176 picojson::value(std::to_string(CurrentApplication::GetInstance().GetProcessId()))));
177 result_obj.insert(std::make_pair("appInfo", app_info));
179 ReportSuccess(result, *out);
182 class TerminateHandler {
184 TerminateHandler(int callback_id, ApplicationInstance* app_instance)
185 : callback_handle_(callback_id), pid_(-1), timeout_id_(0), app_instance_(app_instance) {
188 void set_pid(pid_t pid) {
196 void Invoke(const std::shared_ptr<picojson::value>& response) {
199 if (timeout_id_ > 0) {
200 // cancel terminate callback
201 g_source_remove(timeout_id_);
205 ApplicationInstance* app_instance = this->app_instance_;
206 int callback_id = this->callback_handle_;
207 TaskQueue::GetInstance().Async<picojson::value>(
208 [callback_id, app_instance](const std::shared_ptr<picojson::value>& response) {
209 picojson::object& obj = response->get<picojson::object>();
211 std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
212 Instance::PostMessage(app_instance, response->serialize().c_str());
218 int callback_handle_;
221 ApplicationInstance* app_instance_;
224 #define CHECK_RESULT(result, response, handler) \
225 if (result.IsError()) { \
226 LogAndReportError(result, &response->get<picojson::object>()); \
227 handler->Invoke(response); \
232 void ApplicationManager::AsyncResponse(const PlatformResult& result,
233 std::shared_ptr<picojson::value>* response) {
235 LogAndReportError(result, &(*response)->get<picojson::object>());
237 TaskQueue::GetInstance().Async<picojson::value>(
238 [this](const std::shared_ptr<picojson::value>& response) {
239 Instance::PostMessage(&this->instance_, response->serialize().c_str());
244 void ApplicationManager::Kill(const picojson::value& args) {
247 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
249 int callback_id = -1;
250 const auto& callback = args.get(kCallbackId);
251 if (callback.is<double>()) {
252 callback_id = static_cast<int>(callback.get<double>());
255 const auto& context = args.get("contextId");
256 if (!context.is<std::string>()) {
257 result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
260 const std::string& context_id = context.get<std::string>();
262 if (context_id.empty() && result.IsSuccess()) {
263 result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Context ID is empty.");
266 std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
267 picojson::object& obj = response->get<picojson::object>();
268 obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
270 if (result.IsError()) {
271 LoggerE("Failed args.get");
272 AsyncResponse(result, &response);
276 auto kill = [this, callback_id, context_id]() -> void {
279 std::shared_ptr<picojson::value> response =
280 std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
282 TerminateHandler* handler = new TerminateHandler(callback_id, &this->instance_);
283 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
287 pid = std::stoi(context_id);
289 result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert string to int.");
290 CHECK_RESULT(result, response, handler)
294 result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Context ID cannot be negative value.");
295 CHECK_RESULT(result, response, handler)
298 // if kill request comes for current context, throw InvalidValuesException
299 if (CurrentApplication::GetInstance().GetProcessId() == pid) {
301 LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Cannot kill current application.");
302 CHECK_RESULT(result, response, handler)
305 LoggerD("Kill, pid: %d", pid);
307 char* app_id = nullptr;
308 int ret = app_manager_get_app_id(pid, &app_id);
309 // automatically release the memory
310 std::unique_ptr<char, void (*)(void*)> app_id_ptr(app_id, &std::free);
312 if (APP_MANAGER_ERROR_NONE != ret) {
313 result = LogAndCreateResult(
314 ErrorCode::NOT_FOUND_ERR, "Failed to get application ID.",
315 ("Failed to get application ID, error: %d (%s)", ret, get_error_message(ret)));
316 CHECK_RESULT(result, response, handler)
319 LoggerD("Kill, app ID: %s", app_id);
321 // acquire application context
322 app_context_h app_context = nullptr;
324 ret = app_manager_get_app_context(app_id, &app_context);
325 std::unique_ptr<std::remove_pointer<app_context_h>::type, int (*)(app_context_h)>
326 app_context_ptr(app_context, &app_context_destroy); // automatically release the memory
328 if (APP_MANAGER_ERROR_NONE != ret) {
329 result = LogAndCreateResult(
330 ErrorCode::NOT_FOUND_ERR, "Failed to get application ID.",
331 ("Failed to get application context handle: %d (%s)", ret, get_error_message(ret)));
332 CHECK_RESULT(result, response, handler)
335 auto terminate_callback = [](app_context_h app_context, app_context_event_e event,
337 LoggerD("terminate_callback: %d", event);
339 if (APP_CONTEXT_EVENT_TERMINATED != event) {
340 LoggerD("ignoring event");
345 int ret = app_context_get_pid(app_context, &pid);
347 if (APP_MANAGER_ERROR_NONE != ret) {
348 LoggerE("Failed to get pid of terminated app: %d (%s)", ret, get_error_message(ret));
352 TerminateHandler* handler = static_cast<TerminateHandler*>(user_data);
354 LoggerD("Expected PID: %d, got: %d", handler->pid(), pid);
356 if (handler->pid() == pid) {
357 std::shared_ptr<picojson::value> response =
358 std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
359 ReportSuccess(response->get<picojson::object>());
360 handler->Invoke(response);
365 LoggerD("Kill, setting callback");
366 handler->set_pid(pid);
367 ret = app_manager_set_app_context_event_cb(terminate_callback, handler);
369 if (APP_MANAGER_ERROR_NONE != ret) {
370 result = LogAndCreateResult(
371 ErrorCode::UNKNOWN_ERR, "Failed to register termination callback.",
372 ("Error while registering app context event: %d (%s)", ret, get_error_message(ret)));
373 CHECK_RESULT(result, response, handler)
376 LoggerD("Kill, calling native function");
378 // terminate application
379 ret = app_manager_terminate_app(app_context);
381 if (APP_MANAGER_ERROR_NONE != ret) {
382 result = LogAndCreateResult(
383 ErrorCode::UNKNOWN_ERR, "Failed to terminate application.",
384 ("Failed to terminate application: %d (%s)", ret, get_error_message(ret)));
385 CHECK_RESULT(result, response, handler)
388 LoggerD("Kill, end, waiting for notification");
396 PlatformResult PrepareAppControlForLaunchAppControl(const picojson::value& args,
397 app_control_h* app_control) {
400 const auto& control = args.get("appControl");
401 if (!control.is<picojson::object>()) {
402 return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
404 const picojson::object& app_control_obj = control.get<picojson::object>();
406 app_control_h tmp_app_control = nullptr;
407 auto result = utils::ApplicationControlToService(app_control_obj, &tmp_app_control);
408 std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
409 app_control_ptr(tmp_app_control, &app_control_destroy);
411 if (result.IsError()) {
412 LoggerE("Application control to service failed.");
417 const auto& id = args.get("id");
418 if (id.is<std::string>()) {
419 app_id = id.get<std::string>();
422 if (!app_id.empty()) {
423 LoggerD("app_id: %s", app_id.c_str());
425 int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
427 if (APP_CONTROL_ERROR_NONE != ret) {
428 LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
429 return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
433 *app_control = app_control_ptr.release();
435 return PlatformResult(ErrorCode::NO_ERROR);
440 void ApplicationManager::LaunchAppControl(const picojson::value& args) {
443 int callback_id = -1;
444 const auto& callback = args.get(kCallbackId);
445 if (callback.is<double>()) {
446 callback_id = static_cast<int>(callback.get<double>());
449 std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
450 picojson::object& response_obj = response->get<picojson::object>();
452 std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
454 app_control_h app_control = nullptr;
455 auto prepare_app_control_result = PrepareAppControlForLaunchAppControl(args, &app_control);
456 if (prepare_app_control_result.IsError()) {
457 AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
461 std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
462 app_control_ptr(app_control, &app_control_destroy);
464 std::string reply_callback_id;
465 const auto& reply = args.get("replyCallback");
466 if (reply.is<std::string>()) {
467 reply_callback_id = reply.get<std::string>();
470 LaunchAppControlCallbackData* launch_app_user_data = new (std::nothrow)
471 LaunchAppControlCallbackData{&this->instance_, response, reply_callback_id};
473 if (!launch_app_user_data) {
474 LoggerE("Memory allocation fail!");
475 AsyncResponse(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response);
479 app_control_reply_cb reply_callback = nullptr;
480 if (!reply_callback_id.empty()) {
481 launch_app_user_data->reply_callback_id = reply_callback_id;
483 reply_callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
485 ScopeLogger("reply_callback");
487 LaunchAppControlCallbackData* callback_data =
488 static_cast<LaunchAppControlCallbackData*>(user_data);
490 std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
491 if (!launch_app_control_set_global_.count(callback_data)) {
492 LoggerE("Invalid callback_data: %p", callback_data);
496 picojson::value return_value = picojson::value(picojson::object());
497 picojson::object& return_value_obj = return_value.get<picojson::object>();
498 return_value_obj.insert(
499 std::make_pair(kListenerId, picojson::value(callback_data->reply_callback_id)));
501 if (APP_CONTROL_RESULT_SUCCEEDED == result) {
502 LoggerD("App started");
503 return_value_obj.insert(std::make_pair("data", picojson::value(picojson::array())));
504 if (!utils::ServiceToApplicationControlDataArray(
505 reply, &return_value_obj.find("data")->second.get<picojson::array>())) {
506 return_value_obj.erase("data");
508 ReportSuccess(return_value_obj);
510 ReportError(return_value_obj);
513 Instance::PostMessage(callback_data->instance, return_value.serialize().c_str());
514 // Calling order of reply_callback and result_callback cannot be determined,
515 // thus callback_data is not released here, but stored for release in destructor of
516 // ApplicationManager
520 app_control_result_cb result_callback = [](app_control_h launch_request,
521 app_control_error_e launch_result, void* user_data) {
522 ScopeLogger("LaunchAppControl result_callback");
524 LaunchAppControlCallbackData* callback_data =
525 static_cast<LaunchAppControlCallbackData*>(user_data);
527 std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
528 if (!launch_app_control_set_global_.count(callback_data)) {
529 LoggerE("Invalid callback_data: %p", callback_data);
533 auto result = utils::TranslateAppControlError(launch_result);
535 if (result.IsError()) {
536 LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
538 ReportSuccess(callback_data->response->get<picojson::object>());
541 Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
543 // Calling order of reply_callback and result_callback cannot be determined,
544 // thus callback_data is not released here, but stored for release in destructor of
545 // ApplicationManager
549 * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
550 * Previous implementation, using synchronous app_control_send_launch_request,
551 * tries to launch the application 3 times, before reporting an error.
552 * New implementation, using app_control_send_launch_request_async makes only one attempt.
553 * If problems, such as failed application start occur, multiple attempts may solve the problem.
555 auto launch_result = utils::TranslateAppControlError(
556 static_cast<app_control_error_e>(app_control_send_launch_request_async(
557 app_control_ptr.get(), result_callback, reply_callback, launch_app_user_data)));
559 if (launch_result.IsError()) {
560 delete launch_app_user_data;
561 AsyncResponse(launch_result, &response);
563 // Calling order of reply_callback and result_callback cannot be determined,
564 // reply_callback depends on application scenario, which cannot be predicted.
565 // Moreover reply_callback is optional and can be called or not,
566 // thus callback_data is stored for releasing in destructor of ApplicationManager
567 // at the end of application lifetime.
568 // We can not be sure whether callbach will not fire after instance destruction,
569 // we store all user_data pointers in static launch_app_control_set_global_ to check
570 // if they are still valid.
571 std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
572 launch_app_control_set_.insert(launch_app_user_data);
573 launch_app_control_set_global_.insert(launch_app_user_data);
574 LoggerD("App launched, data %p stored for later release", launch_app_user_data);
579 PlatformResult TranslateLaunchError(app_control_error_e return_code) {
582 auto result = utils::TranslateAppControlError(return_code);
583 if (ErrorCode::SECURITY_ERR == result.error_code()) {
584 result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
590 PlatformResult PrepareAppControlForLaunch(const picojson::value& args, app_control_h* app_control) {
593 const auto& app_id = args.get("id");
594 if (!app_id.is<std::string>()) {
595 return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
597 const auto app_id_str = app_id.get<std::string>();
599 app_control_h tmp_app_control = nullptr;
600 int result = app_control_create(&tmp_app_control);
601 if (APP_CONTROL_ERROR_NONE != result) {
602 LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result));
603 return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
606 std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
607 app_control_ptr(tmp_app_control, &app_control_destroy);
609 if (!app_id_str.empty()) {
610 LoggerD("app_id: %s", app_id_str.c_str());
612 int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str());
614 if (APP_CONTROL_ERROR_NONE != ret) {
615 LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
616 return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
620 *app_control = app_control_ptr.release();
622 return PlatformResult(ErrorCode::NO_ERROR);
626 void ApplicationManager::Launch(const picojson::value& args) {
629 int callback_id = -1;
630 const auto& callback = args.get(kCallbackId);
631 if (callback.is<double>()) {
632 callback_id = static_cast<int>(callback.get<double>());
635 std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
636 picojson::object& response_obj = response->get<picojson::object>();
638 std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
640 app_control_h app_control = nullptr;
641 auto prepare_app_control_result = PrepareAppControlForLaunch(args, &app_control);
642 if (prepare_app_control_result.IsError()) {
643 AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
647 std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
648 app_control_ptr(app_control, &app_control_destroy);
650 struct LaunchCallbackData {
651 ApplicationInstance* instance;
652 std::shared_ptr<picojson::value> response;
653 }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response};
655 app_control_result_cb result_callback = [](app_control_h launch_request,
656 app_control_error_e launch_result, void* user_data) {
657 ScopeLogger("Launch result_callback");
659 LaunchCallbackData* callback_data = static_cast<LaunchCallbackData*>(user_data);
661 auto result = TranslateLaunchError(launch_result);
663 if (result.IsError()) {
664 LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
666 ReportSuccess(callback_data->response->get<picojson::object>());
669 Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
671 delete callback_data;
675 * TODO: Observe how often app_control_send_resume_request tries to launch the application.
676 * Previous implementation, using synchronous app_control_send_launch_request,
677 * tries to launch the application 3 times, before reporting an error.
678 * New implementation, using app_control_send_resume_request makes only one attempt.
679 * If problems, such as failed application start occur, multiple attempts may solve the problem.
681 auto launch_result = TranslateLaunchError(static_cast<app_control_error_e>(
682 app_control_send_resume_request(app_control_ptr.get(), result_callback, launch_user_data)));
684 if (launch_result.IsError()) {
685 delete launch_user_data;
686 AsyncResponse(launch_result, &response);
688 LoggerD("App launched");
692 // internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
693 // public CAPI did not handling APP_CONTROL_ERROR_APP_NOT_FOUND
694 int app_control_foreach_app_matched_internal(app_control_h app_control,
695 app_control_app_matched_cb callback, void* user_data) {
698 app_control_h app_control;
699 app_control_app_matched_cb callback;
702 } foreach_context_launchable_app_t_internal;
704 // internal impl of app_control_cb_broker_foreach_app_matched()
705 auto app_control_cb_broker_foreach_app_matched_internal = [](const char* package,
708 "Entered into asynchronous function, app_control_cb_broker_foreach_app_matched_internal's "
710 foreach_context_launchable_app_t_internal* foreach_context;
711 app_control_app_matched_cb app_matched_cb;
713 if (package == NULL || data == NULL) {
714 LoggerE("APP_CONTROL_ERROR_INVALID_PARAMETER");
718 foreach_context = (foreach_context_launchable_app_t_internal*)data;
719 if (foreach_context->foreach_break == true) return -1;
721 app_matched_cb = foreach_context->callback;
722 if (app_matched_cb != NULL) {
723 bool stop_foreach = false;
726 !app_matched_cb(foreach_context->app_control, package, foreach_context->user_data);
728 foreach_context->foreach_break = stop_foreach;
734 foreach_context_launchable_app_t_internal foreach_context = {.app_control = app_control,
735 .callback = callback,
736 .user_data = user_data,
737 .foreach_break = false};
739 bundle* bundle_data = NULL;
740 app_control_to_bundle(app_control, &bundle_data);
742 int ret = appsvc_usr_get_list(bundle_data, app_control_cb_broker_foreach_app_matched_internal,
743 &foreach_context, getuid());
747 case APPSVC_RET_EINVAL:
748 return APP_CONTROL_ERROR_INVALID_PARAMETER;
750 case APPSVC_RET_ENOMATCH:
751 return APP_CONTROL_ERROR_APP_NOT_FOUND;
754 return APP_CONTROL_ERROR_LAUNCH_FAILED;
758 return APP_CONTROL_ERROR_NONE;
761 void ApplicationManager::FindAppControl(const picojson::value& args) {
764 int callback_id = -1;
765 const auto& callback = args.get(kCallbackId);
766 if (callback.is<double>()) {
767 callback_id = static_cast<int>(callback.get<double>());
770 std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
771 picojson::object& response_obj = response->get<picojson::object>();
773 std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
775 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
776 const auto& control = args.get("appControl");
777 if (!control.is<picojson::object>()) {
778 result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
779 AsyncResponse(result, &response);
783 const picojson::object& app_control_obj = control.get<picojson::object>();
785 app_control_h app_control = nullptr;
786 result = utils::ApplicationControlToService(app_control_obj, &app_control);
787 std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_ptr(
788 app_control, &app_control_destroy); // automatically release the memory
790 if (result.IsError()) {
791 LoggerE("Application control to service failed.");
792 AsyncResponse(result, &response);
796 auto find = [app_control_ptr](const std::shared_ptr<picojson::value>& response) -> void {
797 ScopeLogger("Entered into asynchronous function, find");
798 auto app_control_matched = [](app_control_h app_control, const char* appid,
799 void* user_data) -> bool {
800 ScopeLogger("Entered into asynchronous function, app_control_matched");
801 if (nullptr == appid) {
802 LoggerD("appid is NULL");
806 pkgmgrinfo_appinfo_h handle;
807 int ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, getuid(), &handle);
808 if (PMINFO_R_OK != ret) {
809 LoggerE("Failed to get appInfo: %d (%s)", ret, get_error_message(ret));
811 picojson::array* array = static_cast<picojson::array*>(user_data);
812 array->push_back(picojson::value(picojson::object()));
814 utils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
815 pkgmgrinfo_appinfo_destroy_appinfo(handle);
821 picojson::object& response_obj = response->get<picojson::object>();
822 auto it_result = response_obj.find("result");
823 picojson::object& result_obj = it_result->second.get<picojson::object>();
825 result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())));
827 int ret = app_control_foreach_app_matched_internal(app_control_ptr.get(), app_control_matched,
828 &array.first->second.get<picojson::array>());
830 if (APP_CONTROL_ERROR_NONE != ret) {
831 if (APP_CONTROL_ERROR_APP_NOT_FOUND == ret) {
832 LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Matched Application not found"),
833 &response_obj, ("app_control_foreach_app_matched error: %d (%s)", ret,
834 get_error_message(ret)));
835 } else if (APP_CONTROL_ERROR_LAUNCH_FAILED == ret) {
837 PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), &response_obj,
838 ("app_control_foreach_app_matched error: %d (%s)", ret, get_error_message(ret)));
839 } else if (APP_CONTROL_ERROR_INVALID_PARAMETER == ret) {
840 LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed"),
841 &response_obj, ("app_control_foreach_app_matched error: %d (%s)", ret,
842 get_error_message(ret)));
844 // remove copied ApplicationControl from result
845 response_obj.erase(it_result);
847 ReportSuccess(response_obj);
851 auto find_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
852 ScopeLogger("Entered into asynchronous function, find_response");
853 Instance::PostMessage(&this->instance_, response->serialize().c_str());
856 // prepare result object, we need to do that here, as input parameter is passed to result callback
857 auto ret = response_obj.insert(std::make_pair("result", picojson::value(picojson::object())));
858 // reinsert application control
859 ret.first->second.get<picojson::object>().insert(
860 std::make_pair("appControl", args.get("appControl")));
862 TaskQueue::GetInstance().Queue<picojson::value>(find, find_response, response);
865 void ApplicationManager::GetAppsContext(const picojson::value& args) {
868 int callback_id = -1;
869 const auto& callback = args.get(kCallbackId);
870 if (callback.is<double>()) {
871 callback_id = static_cast<int>(callback.get<double>());
874 auto get_apps_context = [](const std::shared_ptr<picojson::value>& response) -> void {
875 picojson::object& response_obj = response->get<picojson::object>();
876 picojson::value result = picojson::value(picojson::object());
877 picojson::object& result_obj = result.get<picojson::object>();
878 picojson::array& array =
879 result_obj.insert(std::make_pair("contexts", picojson::value(picojson::array())))
880 .first->second.get<picojson::array>();
882 auto app_context_cb = [](app_context_h app_context, void* user_data) -> bool {
883 if (nullptr == user_data) {
887 picojson::array* array = static_cast<picojson::array*>(user_data);
888 array->push_back(picojson::value(picojson::object()));
890 if (!utils::CreateApplicationContext(app_context, &array->back().get<picojson::object>())) {
898 int ret = app_manager_foreach_app_context(app_context_cb, &array);
900 if (APP_MANAGER_ERROR_NONE != ret) {
902 PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
903 ("app_manager_foreach_app_context error: %d (%s)", ret, get_error_message(ret)));
905 ReportSuccess(result, response_obj);
909 auto get_apps_context_response =
910 [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
911 picojson::object& obj = response->get<picojson::object>();
912 obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
913 Instance::PostMessage(&this->instance_, response->serialize().c_str());
916 auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
918 TaskQueue::GetInstance().Queue<picojson::value>(get_apps_context, get_apps_context_response,
922 void ApplicationManager::GetAppContext(const picojson::value& args, picojson::object* out) {
926 const auto& context_id = args.get("contextId");
927 if (context_id.is<std::string>()) {
929 pid = std::stoi(context_id.get<std::string>());
931 LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert context id."),
936 pid = CurrentApplication::GetInstance().GetProcessId();
939 char* app_id = nullptr;
941 int ret = app_manager_get_app_id(pid, &app_id);
942 // automatically release the memory
943 std::unique_ptr<char, void (*)(void*)> app_id_ptr(app_id, &std::free);
945 if (APP_MANAGER_ERROR_NONE != ret || nullptr == app_id) {
947 case APP_MANAGER_ERROR_NO_SUCH_APP:
948 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "No such application exist."), out,
949 ("app_manager_get_app_id returned: APP_MANAGER_ERROR_NO_SUCH_APP"));
952 case APP_MANAGER_ERROR_INVALID_PARAMETER:
953 LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Application not found."), out,
954 ("app_manager_get_app_id returned: APP_MANAGER_ERROR_INVALID_PARAMETER"));
959 PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), out,
960 ("app_manager_get_app_id returned: %d (%s)", ret, get_error_message(ret)));
965 picojson::value result = picojson::value(picojson::object());
966 utils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
968 ReportSuccess(result, *out);
971 void ApplicationManager::GetAppsInfo(const picojson::value& args) {
974 int callback_id = -1;
975 const auto& callback = args.get(kCallbackId);
976 if (callback.is<double>()) {
977 callback_id = static_cast<int>(callback.get<double>());
980 auto get_apps_info = [](const std::shared_ptr<picojson::value>& response) -> void {
981 ScopeLogger("Entered into asynchronous function, get_apps_info");
982 picojson::object& response_obj = response->get<picojson::object>();
983 picojson::value result = picojson::value(picojson::object());
984 picojson::object& result_obj = result.get<picojson::object>();
985 picojson::array& array =
986 result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())))
987 .first->second.get<picojson::array>();
989 auto app_info_cb = [](pkgmgrinfo_appinfo_h handle, void* user_data) -> int {
990 ScopeLogger("Entered into asynchronous function, app_info_cb");
991 if (nullptr == user_data) {
995 picojson::array* array = static_cast<picojson::array*>(user_data);
996 array->push_back(picojson::value(picojson::object()));
998 utils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
1003 int ret = pkgmgrinfo_appinfo_get_usr_installed_list(app_info_cb, getuid(), &array);
1005 if (APP_MANAGER_ERROR_NONE != ret) {
1006 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
1007 ("pkgmgrinfo_appinfo_get_usr_installed_list error"));
1009 ReportSuccess(result, response_obj);
1013 auto get_apps_info_response =
1014 [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1015 ScopeLogger("Entered into asynchronous function, get_apps_info_response");
1016 picojson::object& obj = response->get<picojson::object>();
1017 obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1018 Instance::PostMessage(&this->instance_, response->serialize().c_str());
1021 auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1023 TaskQueue::GetInstance().Queue<picojson::value>(get_apps_info, get_apps_info_response, data);
1026 void ApplicationManager::GetAppInfo(const std::string& app_id, picojson::object* out) {
1029 pkgmgrinfo_appinfo_h handle = nullptr;
1031 if (PMINFO_R_OK != pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1032 LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out);
1036 picojson::value result = picojson::value(picojson::object());
1037 utils::CreateApplicationInformation(handle, &result.get<picojson::object>());
1038 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1040 ReportSuccess(result, *out);
1043 char* ApplicationManager::GetPackageId(const std::string& app_id) {
1046 char* pkg_id = nullptr;
1048 int ret = app_manager_get_app_info(app_id.c_str(), &handle);
1049 if (APP_MANAGER_ERROR_NONE != ret) {
1050 LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
1054 ret = app_info_get_package(handle, &pkg_id);
1055 if (APP_MANAGER_ERROR_NONE != ret) {
1056 LoggerE("Failed to get package id: %d (%s)", ret, get_error_message(ret));
1060 ret = app_info_destroy(handle);
1061 if (APP_MANAGER_ERROR_NONE != ret) {
1062 LoggerE("Failed to destroy app info: %d (%s)", ret, get_error_message(ret));
1068 void ApplicationManager::GetAppCerts(const std::string& app_id, picojson::object* out) {
1071 char* package_id = nullptr;
1073 package_id = GetPackageId(app_id);
1074 // automatically release the memory
1075 std::unique_ptr<char, void (*)(void*)> package_id_ptr(package_id, &std::free);
1078 LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
1082 package_info_h pkg_info = nullptr;
1083 int ret = package_info_create(package_id, &pkg_info);
1085 std::unique_ptr<std::remove_pointer<package_info_h>::type, int (*)(package_info_h)> pkg_info_ptr(
1086 pkg_info, &package_info_destroy); // automatically release the memory
1088 if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1089 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out,
1090 ("Failed to get package info: %d (%s)", ret, get_error_message(ret)));
1094 auto cert_info_cb = [](package_info_h handle, package_cert_type_e cert_type,
1095 const char* cert_value, void* user_data) -> bool {
1096 const char* cert_name = nullptr;
1098 switch (cert_type) {
1099 case PACKAGE_INFO_AUTHOR_ROOT_CERT:
1100 cert_name = "AUTHOR_ROOT";
1102 case PACKAGE_INFO_AUTHOR_INTERMEDIATE_CERT:
1103 cert_name = "AUTHOR_INTERMEDIATE";
1105 case PACKAGE_INFO_AUTHOR_SIGNER_CERT:
1106 cert_name = "AUTHOR_SIGNER";
1108 case PACKAGE_INFO_DISTRIBUTOR_ROOT_CERT:
1109 cert_name = "DISTRIBUTOR_ROOT";
1111 case PACKAGE_INFO_DISTRIBUTOR_INTERMEDIATE_CERT:
1112 cert_name = "DISTRIBUTOR_INTERMEDIATE";
1114 case PACKAGE_INFO_DISTRIBUTOR_SIGNER_CERT:
1115 cert_name = "DISTRIBUTOR_SIGNER";
1117 case PACKAGE_INFO_DISTRIBUTOR2_ROOT_CERT:
1118 cert_name = "DISTRIBUTOR2_ROOT";
1120 case PACKAGE_INFO_DISTRIBUTOR2_INTERMEDIATE_CERT:
1121 cert_name = "DISTRIBUTOR2_INTERMEDIATE";
1123 case PACKAGE_INFO_DISTRIBUTOR2_SIGNER_CERT:
1124 cert_name = "DISTRIBUTOR2_SIGNER";
1127 LoggerD("Unknown certificate type: %d", cert_type);
1131 picojson::array* array = static_cast<picojson::array*>(user_data);
1132 array->push_back(picojson::value(picojson::object()));
1134 utils::CreateApplicationCertificate(cert_name, cert_value,
1135 &array->back().get<picojson::object>());
1140 picojson::value result = picojson::value(picojson::array());
1142 ret = package_info_foreach_cert_info(pkg_info, cert_info_cb, &result.get<picojson::array>());
1144 if ((PACKAGE_MANAGER_ERROR_NONE != ret) && (PACKAGE_MANAGER_ERROR_IO_ERROR != ret)) {
1145 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificates info."),
1147 ("Failed to get certificates info: %d (%s)", ret, get_error_message(ret)));
1151 ReportSuccess(result, *out);
1154 void ApplicationManager::GetAppSharedUri(const std::string& app_id, picojson::object* out) {
1156 // this implementation assumes that shared/trusted path is the obligatory member of application
1157 // and it is used to extract the parent directory 'shared'
1158 char* path = nullptr;
1159 int ret = app_manager_get_shared_trusted_path(app_id.c_str(), &path);
1160 if (APP_MANAGER_ERROR_NONE != ret) {
1161 // if the application does not exist, there is no need to check "res" directory
1162 if (APP_MANAGER_ERROR_NO_SUCH_APP == ret) {
1163 LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get shared URI."), out);
1167 // if the shared_trusted directory is not properly returned, gathering the shared/res path,
1168 // which is the obligatory member. The global path could be different then:
1169 // e.g. instead of path: /opt/usr/home/owner/apps_rw/org.example.basic/shared/
1170 // returned path is: /opt/usr/globalapps/org.example.basic/shared/
1172 "app_manager_get_shared_trusted_path failed(), trying "
1173 "app_manager_get_shared_resource_path() to gather path");
1174 int ret = app_manager_get_shared_resource_path(app_id.c_str(), &path);
1175 if (APP_MANAGER_ERROR_NONE != ret) {
1176 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get shared URI."), out);
1181 std::string path_str = path;
1184 std::string shared_path = path_str.substr(0, path_str.rfind("/", path_str.length() - 2));
1186 // checking if path is valid
1187 struct stat stat_res;
1188 if (0 != stat(shared_path.c_str(), &stat_res)) {
1189 LoggerW("Path %s does not exist", shared_path.c_str());
1190 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get shared URI."), out);
1194 picojson::value result = picojson::value(kTizenApisFileScheme + shared_path);
1195 ReportSuccess(result, *out);
1198 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
1199 PlatformResult ApplicationManager::BatteryUsageFilter(const picojson::value& args,
1200 const context_history_filter_h filter,
1201 context_history_data_e* data_type_out) {
1203 int ret = CONTEXT_HISTORY_ERROR_NONE;
1204 int limit = kMaximumBatteryRetrievedObjects;
1205 if (args.contains("limit")) {
1206 limit = static_cast<int>(args.get("limit").get<double>());
1209 ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1211 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1212 return LogAndCreateResult(
1213 ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1214 ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1217 context_history_data_e data_type_in = CONTEXT_HISTORY_RECENT_BATTERY_USAGE;
1219 if (args.contains("days")) {
1220 const int days = static_cast<int>(args.get("days").get<double>());
1221 data_type_in = CONTEXT_HISTORY_BATTERY_USAGE;
1222 ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, days);
1224 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1225 return LogAndCreateResult(
1226 ErrorCode::INVALID_VALUES_ERR, "days given with invalid value.",
1227 ("days given with invalid value: %d (%s)", ret, get_error_message(ret)));
1231 *data_type_out = data_type_in;
1233 return PlatformResult(ErrorCode::NO_ERROR);
1236 PlatformResult ApplicationManager::BatteryUsageAttributes(const context_history_record_h record,
1237 picojson::object* object) {
1240 int ret = CONTEXT_HISTORY_ERROR_NONE;
1241 double amount = 0.0;
1242 char* app_id = nullptr;
1247 ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1248 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1249 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1250 ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1253 ret = context_history_record_get_double(record, CONTEXT_HISTORY_TOTAL_AMOUNT, &amount);
1254 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1255 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get amount.",
1256 ("Failed to get amount: %d (%s)", ret, get_error_message(ret)));
1259 object->insert(std::make_pair("appId", picojson::value(app_id)));
1260 object->insert(std::make_pair("batteryUsage", picojson::value(amount)));
1262 return PlatformResult(ErrorCode::NO_ERROR);
1265 PlatformResult ApplicationManager::AppsUsageFilter(const picojson::value& args,
1266 const context_history_filter_h filter,
1267 context_history_data_e* data_type_out) {
1269 int ret = CONTEXT_HISTORY_ERROR_NONE;
1270 int limit = kMaximumAppsRetrievedObjects;
1271 if (args.contains("limit")) {
1272 limit = static_cast<int>(args.get("limit").get<double>());
1275 ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1276 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1277 return LogAndCreateResult(
1278 ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1279 ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1282 context_history_data_e data_type_in = CONTEXT_HISTORY_FREQUENTLY_USED_APP;
1283 if (args.contains("mode") && kAppUsageModeRecently == args.get("mode").get<std::string>()) {
1284 data_type_in = CONTEXT_HISTORY_RECENTLY_USED_APP;
1287 int time_span = kDefaultPeriodOfTime;
1288 const picojson::object& JS_filter = args.get("filter").get<picojson::object>();
1289 auto time_span_iter = JS_filter.find("timeSpan");
1290 if (JS_filter.end() != time_span_iter || (JS_filter.end() == JS_filter.find("startTime") &&
1291 JS_filter.end() == JS_filter.find("endTime"))) {
1292 // In the second case, we treat the filter object just like an empty object.
1293 // The default value of filter will be used instead.
1294 if (JS_filter.end() != time_span_iter) {
1295 time_span = static_cast<int>(time_span_iter->second.get<double>());
1297 ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, time_span);
1298 // context_history_filter_set_int may return only success or
1299 // CONTEXT_HISTORY_ERROR_INVALID_PARAMETER
1300 // Although this should never happen, it's better to check ret's value
1301 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1302 return LogAndCreateResult(ErrorCode::ABORT_ERR,
1303 "Error while setting the default TIME_SPAN value.",
1304 ("Error while setting the default TIME_SPAN value: %d (%s)", ret,
1305 get_error_message(ret)));
1308 auto start_time_iter = JS_filter.find("startTime");
1309 auto end_time_iter = JS_filter.find("endTime");
1310 if (start_time_iter != JS_filter.end()) {
1311 int start_time = static_cast<int>(start_time_iter->second.get<double>());
1312 ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_START_TIME, start_time);
1313 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1314 return LogAndCreateResult(
1315 ErrorCode::INVALID_VALUES_ERR, "startTime given with invalid value.",
1316 ("startTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1319 if (end_time_iter != JS_filter.end()) {
1320 int end_time = static_cast<int>(end_time_iter->second.get<double>());
1321 ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_END_TIME, end_time);
1322 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1323 return LogAndCreateResult(
1324 ErrorCode::INVALID_VALUES_ERR, "endTime given with invalid value.",
1325 ("endTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1330 *data_type_out = data_type_in;
1332 return PlatformResult(ErrorCode::NO_ERROR);
1335 PlatformResult ApplicationManager::AppsUsageAttributes(const context_history_record_h record,
1336 picojson::object* object) {
1339 int ret = CONTEXT_HISTORY_ERROR_NONE;
1340 int total_count = 0;
1341 int total_duration = 0;
1343 char* app_id = nullptr;
1348 ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1349 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1350 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1351 ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1354 ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_COUNT, &total_count);
1355 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1356 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get total count.",
1357 ("Failed to get total count: %d (%s)", ret, get_error_message(ret)));
1360 ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_DURATION, &total_duration);
1361 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1362 return LogAndCreateResult(
1363 ErrorCode::ABORT_ERR, "Failed to get total duration.",
1364 ("Failed to get total duration: %d (%s)", ret, get_error_message(ret)));
1367 ret = context_history_record_get_int(record, CONTEXT_HISTORY_LAST_TIME, &last_time);
1368 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1369 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get last time.",
1370 ("Failed to get last time: %d (%s)", ret, get_error_message(ret)));
1373 object->insert(std::make_pair("appId", picojson::value(app_id)));
1374 object->insert(std::make_pair("totalCount", picojson::value(static_cast<double>(total_count))));
1376 std::make_pair("totalDuration", picojson::value(static_cast<double>(total_duration))));
1377 object->insert(std::make_pair("lastTime", picojson::value(static_cast<double>(last_time))));
1379 return PlatformResult(ErrorCode::NO_ERROR);
1383 void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojson::object* out) {
1386 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
1387 int callback_id = -1;
1388 const auto& callback = args.get(kCallbackId);
1389 if (callback.is<double>()) {
1390 callback_id = static_cast<int>(callback.get<double>());
1393 auto get_battery_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1395 PlatformResult result = ApplicationManager::GetContextHistory(
1396 args, &response.get()->get<picojson::object>(), &ApplicationManager::BatteryUsageFilter,
1397 &ApplicationManager::BatteryUsageAttributes);
1399 LogAndReportError(result, &response.get()->get<picojson::object>());
1403 auto get_battery_usage_response =
1404 [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1406 picojson::object& obj = response->get<picojson::object>();
1407 obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1408 Instance::PostMessage(&this->instance_, response->serialize().c_str());
1411 auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1413 TaskQueue::GetInstance().Queue<picojson::value>(get_battery_usage, get_battery_usage_response,
1416 LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
1417 "This feature is not supported on this profile."),
1418 out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1422 void ApplicationManager::GetAppsUsageInfo(const picojson::value& args, picojson::object* out) {
1425 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
1426 int callback_id = static_cast<int>(args.get(kCallbackId).get<double>());
1428 auto get_apps_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1430 PlatformResult result = ApplicationManager::GetContextHistory(
1431 args, &response.get()->get<picojson::object>(), &ApplicationManager::AppsUsageFilter,
1432 &ApplicationManager::AppsUsageAttributes);
1434 LogAndReportError(result, &response.get()->get<picojson::object>());
1438 auto get_apps_usage_response =
1439 [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1441 picojson::object& obj = response->get<picojson::object>();
1442 obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1443 Instance::PostMessage(&this->instance_, response->serialize().c_str());
1446 auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1448 TaskQueue::GetInstance().Queue<picojson::value>(get_apps_usage, get_apps_usage_response, data);
1450 LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
1451 "This feature is not supported on this profile."),
1452 out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1456 void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) {
1459 pkgmgrinfo_appinfo_h handle = nullptr;
1461 int ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle);
1462 std::unique_ptr<std::remove_pointer<pkgmgrinfo_appinfo_h>::type, int (*)(pkgmgrinfo_appinfo_h)>
1463 pkg_info_ptr(handle,
1464 &pkgmgrinfo_appinfo_destroy_appinfo); // automatically release the memory
1466 if (PMINFO_R_OK != ret) {
1467 LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out,
1468 ("Failed to get app info: %d (%s)", ret, get_error_message(ret)));
1472 auto meta_data_cb = [](const char* meta_key, const char* meta_value, void* user_data) -> int {
1473 if (nullptr == meta_key || nullptr == meta_value) {
1474 LoggerE("meta_key or meta_value is null");
1478 picojson::array* array = static_cast<picojson::array*>(user_data);
1479 array->push_back(picojson::value(picojson::object()));
1481 utils::CreateApplicationMetaData(meta_key, meta_value, &array->back().get<picojson::object>());
1485 picojson::value result = picojson::value(picojson::array());
1486 ret = pkgmgrinfo_appinfo_foreach_metadata(handle, meta_data_cb, &result.get<picojson::array>());
1488 if (PMINFO_R_OK != ret) {
1489 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get metadata."), out,
1490 ("Failed to get metadata: %d (%s)", ret, get_error_message(ret)));
1494 ReportSuccess(result, *out);
1497 class ApplicationListChangedBroker {
1499 ApplicationListChangedBroker() : event_type_() {
1507 static int ClientStatusListener(unsigned int target_uid, int id, const char* type,
1508 const char* package, const char* key, const char* val,
1509 const void* msg, void* data) {
1511 ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1513 if (0 == strcasecmp(key, kStartKey)) {
1514 that->HandleStart(val, package);
1515 } else if (0 == strcasecmp(key, kEndKey) && 0 == strcasecmp(val, kOkValue)) {
1516 that->HandleEnd(package);
1518 LoggerD("Ignored key: %s", key);
1524 static int AppUninstallListener(uid_t target_uid, int id, const char* type, const char* package,
1525 const char* key, const char* val, const void* msg, void* data) {
1528 ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1530 if (0 == strcasecmp(key, kStartKey)) {
1531 that->HandleUninstallStart();
1532 } else if (0 == strcasecmp(key, kAppidKey)) {
1533 that->AddUninstalledAppId(val);
1534 } else if (0 == strcasecmp(key, kEndKey)) {
1535 that->HandleUninstallEnd();
1537 LoggerD("Ignored key: %s", key);
1543 void AddApplicationInstance(ApplicationInstance* app_instance) {
1545 app_instance_list_.push_back(app_instance);
1548 void RemoveApplicationInstance(ApplicationInstance* app_instance) {
1550 for (auto it = app_instance_list_.begin(); it != app_instance_list_.end(); it++) {
1551 if (*it == app_instance) {
1552 app_instance_list_.erase(it);
1559 void HandleStart(const char* event_type, const char* package) {
1562 set_event_type(event_type);
1565 void HandleEnd(const char* package) {
1568 if (Event::kUninstalled == event_type_) {
1572 GetApplicationIdsFromPackage(package);
1574 for (auto& app_id : app_list_) {
1575 picojson::value value = picojson::value(picojson::object());
1576 picojson::object& data_obj = value.get<picojson::object>();
1578 switch (event_type_) {
1579 case Event::kInstalled:
1580 data_obj.insert(std::make_pair(kAction, picojson::value(kOnInstalled)));
1583 case Event::kUpdated:
1584 data_obj.insert(std::make_pair(kAction, picojson::value(kOnUpdated)));
1586 case Event::kUninstalled:
1587 LoggerD("Uninstalled called");
1591 switch (event_type_) {
1592 case Event::kInstalled:
1593 case Event::kUpdated: {
1594 pkgmgrinfo_appinfo_h handle = nullptr;
1596 pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1597 LoggerE("Failed to get application information handle.");
1600 auto info = data_obj.insert(std::make_pair(kData, picojson::value(picojson::object())));
1601 utils::CreateApplicationInformation(handle, &info.first->second.get<picojson::object>());
1602 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1604 case Event::kUninstalled:
1605 LoggerD("Uninstalled called");
1609 data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1611 for (auto instance : app_instance_list_) {
1612 Instance::PostMessage(instance, value.serialize().c_str());
1617 void GetApplicationIdsFromPackage(const char* package) {
1619 package_info_h package_info = nullptr;
1621 int ret = package_info_create(package, &package_info);
1622 if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1623 LoggerE("Failed to create package info: %d (%s)", ret, get_error_message(ret));
1627 ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_APP_COMPONENT_TYPE_ALL,
1628 ApplicationIdCallback, this);
1629 if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1630 LoggerE("Failed to get application IDs: %d (%s)", ret, get_error_message(ret));
1633 ret = package_info_destroy(package_info);
1634 if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1635 LoggerE("Failed to destroy package info: %d (%s)", ret, get_error_message(ret));
1639 void set_event_type(const char* type) {
1641 if (0 == strcasecmp(type, kInstallEvent)) {
1642 event_type_ = Event::kInstalled;
1643 } else if (0 == strcasecmp(type, kUpdateEvent)) {
1644 event_type_ = Event::kUpdated;
1645 } else if (0 == strcasecmp(type, kUninstallEvent)) {
1646 event_type_ = Event::kUninstalled;
1650 static bool ApplicationIdCallback(package_info_app_component_type_e comp_type, const char* app_id,
1653 if (nullptr != app_id) {
1654 static_cast<ApplicationListChangedBroker*>(user_data)->app_list_.push_back(app_id);
1659 void HandleUninstallStart() {
1662 set_event_type(kUninstallEvent);
1665 void AddUninstalledAppId(const char* app_id) {
1667 if (nullptr != app_id) {
1668 app_list_.push_back(app_id);
1672 void HandleUninstallEnd() {
1674 for (auto& app_id : app_list_) {
1675 picojson::value value = picojson::value(picojson::object());
1676 picojson::object& data_obj = value.get<picojson::object>();
1678 data_obj.insert(std::make_pair(kAction, picojson::value(kOnUninstalled)));
1679 data_obj.insert(std::make_pair(kData, picojson::value(app_id)));
1681 data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1683 for (auto instance : app_instance_list_) {
1684 Instance::PostMessage(instance, value.serialize().c_str());
1690 std::vector<std::string> app_list_;
1691 std::vector<ApplicationInstance*> app_instance_list_;
1694 static ApplicationListChangedBroker g_application_list_changed_broker;
1696 void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
1699 if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgr_client_uninstall_handle_) {
1700 if (nullptr == pkgmgr_client_handle_) {
1701 pkgmgr_client_handle_ = pkgmgr_client_new(PC_LISTENING);
1703 if (nullptr == pkgmgr_client_uninstall_handle_) {
1704 pkgmgr_client_uninstall_handle_ = pkgmgr_client_new(PC_LISTENING);
1707 if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgr_client_uninstall_handle_) {
1708 if (nullptr != pkgmgr_client_handle_) {
1709 pkgmgr_client_free(pkgmgr_client_handle_);
1710 pkgmgr_client_handle_ = nullptr;
1712 if (nullptr != pkgmgr_client_uninstall_handle_) {
1713 pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1714 pkgmgr_client_uninstall_handle_ = nullptr;
1716 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."),
1721 #define CHECK_APPLICATION_EVENT_ERROR(result, function_name) \
1722 if (PKGMGR_R_OK > result) { \
1723 StopAppInfoEventListener(); \
1724 LogAndReportError( \
1725 PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."), out, \
1726 ("Function %s failed: %s (%d)", function_name, get_error_message(result), result)); \
1730 g_application_list_changed_broker.AddApplicationInstance(&instance_);
1732 int result = pkgmgr_client_set_status_type(
1733 pkgmgr_client_handle_,
1734 PACKAGE_MANAGER_STATUS_TYPE_INSTALL | PACKAGE_MANAGER_STATUS_TYPE_UPGRADE);
1735 CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_set_status_type")
1737 result = pkgmgr_client_set_status_type(pkgmgr_client_uninstall_handle_,
1738 PACKAGE_MANAGER_STATUS_TYPE_UNINSTALL);
1739 CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_set_status_type")
1741 result = pkgmgr_client_listen_status(pkgmgr_client_handle_,
1742 ApplicationListChangedBroker::ClientStatusListener,
1743 &g_application_list_changed_broker);
1744 CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_listen_status")
1746 result = pkgmgr_client_listen_status(pkgmgr_client_uninstall_handle_,
1747 ApplicationListChangedBroker::AppUninstallListener,
1748 &g_application_list_changed_broker);
1749 CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_listen_status")
1751 #undef CHECK_APPLICATION_EVENT_ERROR
1753 LoggerD("Broker callback is already registered.");
1756 ReportSuccess(*out);
1759 void ApplicationManager::StopAppInfoEventListener() {
1762 if (nullptr != pkgmgr_client_handle_ || nullptr != pkgmgr_client_uninstall_handle_) {
1763 if (nullptr != pkgmgr_client_handle_) {
1764 pkgmgr_client_free(pkgmgr_client_handle_);
1765 pkgmgr_client_handle_ = nullptr;
1767 if (nullptr != pkgmgr_client_uninstall_handle_) {
1768 pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1769 pkgmgr_client_uninstall_handle_ = nullptr;
1771 g_application_list_changed_broker.RemoveApplicationInstance(&instance_);
1773 LoggerD("Broker callback is already unregistered.");
1777 void ApplicationManager::GetApplicationInformationSize(const picojson::value& args,
1778 picojson::object* out) {
1781 const auto& package_id = args.get("packageId");
1782 if (!package_id.is<std::string>()) {
1783 LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
1788 const std::string& package_id_str = package_id.get<std::string>();
1790 // get installed size from package server (to solve smack issue)
1791 pkgmgr_client* pc = pkgmgr_client_new(PC_REQUEST);
1794 if (nullptr == pc) {
1795 LoggerE("Failed to create pkgmgr client");
1797 size = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_TOTAL_SIZE, pc, NULL,
1798 package_id_str.c_str(), NULL, NULL, NULL);
1801 LoggerE("Failed to get installed size: %d (%s)", size, get_error_message(size));
1804 pkgmgr_client_free(pc);
1807 picojson::value result = picojson::value(picojson::object());
1808 picojson::object& result_obj = result.get<picojson::object>();
1809 result_obj.insert(std::make_pair("size", picojson::value(static_cast<double>(size))));
1811 ReportSuccess(result, *out);
1814 void ApplicationManager::BroadcastEventHelper(const picojson::value& args, picojson::object& out,
1819 std::string event_str = args.get("name").get<std::string>();
1820 const char* event_name = event_str.c_str();
1822 bundle* data = bundle_create();
1827 ret = bundle_add(data, "data", args.get("data").serialize().c_str());
1829 if (ret != EVENT_ERROR_NONE) {
1830 LoggerE("bundle_add failed, error: %d (%s)", ret, get_error_message(ret));
1836 ret = event_publish_trusted_app_event(event_name, data);
1838 ret = event_publish_app_event(event_name, data);
1841 if (ret == EVENT_ERROR_NONE) {
1844 LoggerE("event_publish_app_event failed, error: %d (%s)", ret, get_error_message(ret));
1849 void ApplicationManager::OnEvent(const char* event_name, bundle* event_data, void* user_data) {
1850 ScopeLogger("Event name is: '%s'", event_name);
1852 ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1854 if (!manager->event_callback_) {
1855 LoggerD("No event listener registered, skipping.");
1859 picojson::value event = picojson::value(picojson::object());
1860 picojson::object& event_o = event.get<picojson::object>();
1863 char* val = nullptr;
1865 if (event_map_.count(event_name)) { // system event
1866 const std::string& key = event_map_.at(event_name);
1867 std::string state = "true";
1869 ret = bundle_get_str(event_data, key.c_str(), &val);
1870 if (EVENT_ERROR_NONE != ret) {
1871 LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1875 state = std::string(val);
1878 LoggerD("State is %s", state.c_str());
1879 event_o["value"] = picojson::value(state);
1881 } else { // user event
1882 ret = bundle_get_str(event_data, "data", &val);
1883 if (EVENT_ERROR_NONE != ret) {
1884 LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1888 picojson::value data;
1890 picojson::parse(data, val, val + strlen(val), &err);
1892 LoggerE("Failed to parse bundle data: %s", err.c_str());
1896 event_o["data"] = data;
1899 LoggerD("event_name is: %s", event_name);
1900 event_o["name"] = picojson::value(event_name);
1902 manager->event_callback_(&event);
1905 PlatformResult ApplicationManager::StartEventListener(const std::string& event_name,
1906 const JsonCallback& callback) {
1910 event_handler_h event_handler;
1912 ret = event_add_event_handler(event_name.c_str(), OnEvent, this, &event_handler);
1913 LoggerD("event_add_event_handler() result: %d (%s)", ret, get_error_message(ret));
1914 if (EVENT_ERROR_PERMISSION_DENIED == ret) {
1915 return LogAndCreateResult(ErrorCode::SECURITY_ERR, "The privilege is required",
1916 ("event_add_event_handler failed, error: %d", ret));
1917 } else if (EVENT_ERROR_NONE != ret) {
1918 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error setting event listener",
1919 ("event_add_event_handler failed, error: %d", ret));
1922 event_handler_map_[event_name] = event_handler;
1924 event_callback_ = callback;
1925 LoggerD("event_add_event_handler success");
1926 return PlatformResult(ErrorCode::NO_ERROR);
1929 void ApplicationManager::StopEventListener(const std::string& event_name) {
1933 event_handler_h event_handler;
1935 if (event_handler_map_.find(event_name) != event_handler_map_.end()) {
1936 event_handler = event_handler_map_[event_name];
1938 ret = event_remove_event_handler(event_handler);
1939 if (EVENT_ERROR_NONE != ret) {
1940 LoggerE("event_remove_event_handler failed, error: %d (%s)", ret, get_error_message(ret));
1944 event_handler_map_.erase(event_name);
1948 void ApplicationManager::OnStatusEvent(const char* type, const char* app_id,
1949 app_manager_event_type_e event_type,
1950 app_manager_event_state_e event_state,
1951 app_manager_event_h handle, void* user_data) {
1954 if (APP_MANAGER_EVENT_STATE_COMPLETED != event_state) {
1955 LoggerD("State different from completed");
1959 ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1961 if (!manager || !manager->status_callback_) {
1962 LoggerD("No event listener registered, skipping.");
1967 switch (event_type) {
1968 case APP_MANAGER_EVENT_ENABLE_APP:
1971 case APP_MANAGER_EVENT_DISABLE_APP:
1972 status_type = false;
1975 LoggerD("Uknown status type skipping.");
1979 picojson::value event = picojson::value(picojson::object());
1980 picojson::object& event_o = event.get<picojson::object>();
1982 event_o[kStatusType] = picojson::value(status_type);
1983 event_o[kAppId] = picojson::value(app_id);
1984 event_o[kListenerId] = picojson::value(kAppStatusChangeListener);
1986 manager->status_callback_(&event);
1989 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
1990 PlatformResult ApplicationManager::GetContextHistory(
1991 const picojson::value& args, picojson::object* out,
1992 common::PlatformResult (*modify_filter_cb)(const picojson::value&,
1993 const context_history_filter_h,
1994 context_history_data_e* data_type),
1995 common::PlatformResult (*add_attributes_to_object)(const context_history_record_h,
1996 picojson::object*)) {
1998 context_history_list_h list = nullptr;
1999 context_history_h handle = nullptr;
2000 context_history_filter_h filter = nullptr;
2003 context_history_list_destroy(list);
2004 context_history_destroy(handle);
2005 context_history_filter_destroy(filter);
2008 int ret = context_history_create(&handle);
2009 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2010 return LogAndCreateResult(
2011 ErrorCode::ABORT_ERR, "Failed to create context handle.",
2012 ("Failed to create context handle: %d (%s)", ret, get_error_message(ret)));
2015 ret = context_history_filter_create(&filter);
2016 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2017 return LogAndCreateResult(
2018 ErrorCode::ABORT_ERR, "Failed to create filter handle.",
2019 ("Failed to create filter handle: %d (%s)", ret, get_error_message(ret)));
2022 context_history_data_e data_type;
2024 PlatformResult result = modify_filter_cb(args, filter, &data_type);
2029 picojson::value result_array = picojson::value(picojson::array());
2030 picojson::array& array_obj = result_array.get<picojson::array>();
2032 ret = context_history_get_list(handle, data_type, filter, &list);
2033 if (CONTEXT_HISTORY_ERROR_NO_DATA == ret) {
2034 ReportSuccess(result_array, *out);
2035 return PlatformResult(ErrorCode::NO_ERROR);
2036 } else if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2037 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list.",
2038 ("Failed to get list: %d (%s)", ret, get_error_message(ret)));
2042 ret = context_history_list_get_count(list, &size);
2043 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2044 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list size.",
2045 ("Failed to get list size: %d (%s)", ret, get_error_message(ret)));
2048 array_obj.resize(size, picojson::value(picojson::object()));
2050 for (int i = 0; i < size; ++i) {
2051 context_history_record_h record = nullptr;
2053 context_history_record_destroy(record);
2056 ret = context_history_list_get_current(list, &record);
2057 if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2058 return LogAndCreateResult(
2059 ErrorCode::ABORT_ERR, "Failed to get current record.",
2060 ("Failed to get current record: %d (%s)", ret, get_error_message(ret)));
2063 result = add_attributes_to_object(record, &array_obj[i].get<picojson::object>());
2068 ret = context_history_list_move_next(list);
2069 if (CONTEXT_HISTORY_ERROR_NONE != ret && CONTEXT_HISTORY_ERROR_NO_DATA != ret) {
2070 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to move iterator.",
2071 ("Failed to move iterator: %d (%s)", ret, get_error_message(ret)));
2075 ReportSuccess(result_array, *out);
2076 return PlatformResult(ErrorCode::NO_ERROR);
2080 PlatformResult ApplicationManager::StartStatusListener(const JsonCallback& callback) {
2083 int ret = APP_MANAGER_ERROR_NONE;
2085 if (!app_status_handle_) {
2086 ret = app_manager_event_create(&app_status_handle_);
2087 if (APP_MANAGER_ERROR_NONE != ret) {
2088 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while creating event handle",
2089 ("app_manager_event_create failed, error: %d", ret));
2092 ret = app_manager_event_set_status(app_status_handle_, APP_MANAGER_EVENT_STATUS_TYPE_ALL);
2093 if (APP_MANAGER_ERROR_NONE != ret) {
2094 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status type",
2095 ("app_manager_event_set_status failed, error: %d", ret));
2099 status_callback_ = callback;
2100 ret = app_manager_set_event_cb(app_status_handle_, OnStatusEvent, this);
2101 if (APP_MANAGER_ERROR_NONE != ret) {
2102 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status listener",
2103 ("app_manager_set_event_cb failed, error: %d", ret));
2106 return PlatformResult(ErrorCode::NO_ERROR);
2109 PlatformResult ApplicationManager::StopStatusChangeListener() {
2112 if (app_status_handle_) {
2113 int ret = app_manager_unset_event_cb(app_status_handle_);
2114 if (APP_MANAGER_ERROR_NONE != ret) {
2115 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while removing status listener",
2116 ("app_manager_unset_event_cb failed, error: %d", ret));
2120 return PlatformResult(ErrorCode::NO_ERROR);
2123 } // namespace application
2124 } // namespace extension