[Common] Changed configuration for common profile build
[platform/core/api/webapi-plugins.git] / src / application / application_manager.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "application_manager.h"
18
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <thread>
22 #include <type_traits>
23
24 #include <app_control_internal.h>
25 #include <app_info.h>
26 #include <app_manager_extension.h>
27 #include <appsvc.h>
28 #include <aul.h>
29 #include <bundle.h>
30 #include <bundle_internal.h>
31 #include <package_manager.h>
32 #include <pkgmgr-info.h>
33 #include <pkgmgr_installer.h>
34
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"
41
42 #include "application/application_instance.h"
43 #include "application/application_utils.h"
44
45 using namespace common;
46 using namespace tools;
47
48 namespace extension {
49 namespace application {
50
51 namespace {
52 const std::string kTizenApisFileScheme = "file://";
53 const std::string kTizenApisAppSlash = "/";
54 const std::string kTizenApisAppShared = "shared";
55
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;
62
63 const char* kAppidKey = "appid";
64
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";
77
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}};
101
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;
106 #endif
107 }
108
109 std::set<LaunchAppControlCallbackData*> ApplicationManager::launch_app_control_set_global_{};
110 std::mutex ApplicationManager::launch_app_control_set_mutex_{};
111
112 ApplicationManager::ApplicationManager(ApplicationInstance& instance)
113     : pkgmgr_client_handle_(nullptr),
114       pkgmgr_client_uninstall_handle_(nullptr),
115       instance_(instance),
116       app_status_handle_(nullptr) {
117   ScopeLogger();
118 }
119
120 ApplicationManager::~ApplicationManager() {
121   ScopeLogger();
122   StopAppInfoEventListener();
123   StopStatusChangeListener();
124
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));
129     }
130     it = event_handler_map_.erase(it);
131   }
132
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);
137     }
138   }
139
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);
148                   delete data;
149                   launch_app_control_set_global_.erase(data);
150                 });
151 }
152
153 void ApplicationManager::GetCurrentApplication(const std::string& app_id, picojson::object* out) {
154   ScopeLogger();
155
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)));
162     return;
163   }
164
165   picojson::value app_info = picojson::value(picojson::object());
166   picojson::object& app_info_obj = app_info.get<picojson::object>();
167
168   utils::CreateApplicationInformation(handle, &app_info_obj);
169   pkgmgrinfo_appinfo_destroy_appinfo(handle);
170
171   picojson::value result = picojson::value(picojson::object());
172   picojson::object& result_obj = result.get<picojson::object>();
173
174   result_obj.insert(std::make_pair(
175       "contextId",
176       picojson::value(std::to_string(CurrentApplication::GetInstance().GetProcessId()))));
177   result_obj.insert(std::make_pair("appInfo", app_info));
178
179   ReportSuccess(result, *out);
180 }
181
182 class TerminateHandler {
183  public:
184   TerminateHandler(int callback_id, ApplicationInstance* app_instance)
185       : callback_handle_(callback_id), pid_(-1), timeout_id_(0), app_instance_(app_instance) {
186   }
187
188   void set_pid(pid_t pid) {
189     pid_ = pid;
190   }
191
192   pid_t pid() const {
193     return pid_;
194   }
195
196   void Invoke(const std::shared_ptr<picojson::value>& response) {
197     ScopeLogger();
198
199     if (timeout_id_ > 0) {
200       // cancel terminate callback
201       g_source_remove(timeout_id_);
202       timeout_id_ = 0;
203     }
204
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>();
210           obj.insert(
211               std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
212           Instance::PostMessage(app_instance, response->serialize().c_str());
213         },
214         response);
215   }
216
217  private:
218   int callback_handle_;
219   pid_t pid_;
220   guint timeout_id_;
221   ApplicationInstance* app_instance_;
222 };
223
224 #define CHECK_RESULT(result, response, handler)                    \
225   if (result.IsError()) {                                          \
226     LogAndReportError(result, &response->get<picojson::object>()); \
227     handler->Invoke(response);                                     \
228     delete handler;                                                \
229     return;                                                        \
230   }
231
232 void ApplicationManager::AsyncResponse(const PlatformResult& result,
233                                        std::shared_ptr<picojson::value>* response) {
234   ScopeLogger();
235   LogAndReportError(result, &(*response)->get<picojson::object>());
236
237   TaskQueue::GetInstance().Async<picojson::value>(
238       [this](const std::shared_ptr<picojson::value>& response) {
239         Instance::PostMessage(&this->instance_, response->serialize().c_str());
240       },
241       *response);
242 }
243
244 void ApplicationManager::Kill(const picojson::value& args) {
245   ScopeLogger();
246
247   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
248
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>());
253   }
254
255   const auto& context = args.get("contextId");
256   if (!context.is<std::string>()) {
257     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
258   }
259
260   const std::string& context_id = context.get<std::string>();
261
262   if (context_id.empty() && result.IsSuccess()) {
263     result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Context ID is empty.");
264   }
265
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))));
269
270   if (result.IsError()) {
271     LoggerE("Failed args.get");
272     AsyncResponse(result, &response);
273     return;
274   }
275
276   auto kill = [this, callback_id, context_id]() -> void {
277     ScopeLogger("Kill");
278
279     std::shared_ptr<picojson::value> response =
280         std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
281
282     TerminateHandler* handler = new TerminateHandler(callback_id, &this->instance_);
283     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
284
285     pid_t pid = -1;
286     try {
287       pid = std::stoi(context_id);
288     } catch (...) {
289       result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert string to int.");
290       CHECK_RESULT(result, response, handler)
291     }
292
293     if (pid <= 0) {
294       result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Context ID cannot be negative value.");
295       CHECK_RESULT(result, response, handler)
296     }
297
298     // if kill request comes for current context, throw InvalidValuesException
299     if (CurrentApplication::GetInstance().GetProcessId() == pid) {
300       result =
301           LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Cannot kill current application.");
302       CHECK_RESULT(result, response, handler)
303     }
304
305     LoggerD("Kill, pid: %d", pid);
306
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);
311
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)
317     }
318
319     LoggerD("Kill, app ID: %s", app_id);
320
321     // acquire application context
322     app_context_h app_context = nullptr;
323
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
327
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)
333     }
334
335     auto terminate_callback = [](app_context_h app_context, app_context_event_e event,
336                                  void* user_data) {
337       LoggerD("terminate_callback: %d", event);
338
339       if (APP_CONTEXT_EVENT_TERMINATED != event) {
340         LoggerD("ignoring event");
341         return;
342       }
343
344       int pid = 0;
345       int ret = app_context_get_pid(app_context, &pid);
346
347       if (APP_MANAGER_ERROR_NONE != ret) {
348         LoggerE("Failed to get pid of terminated app: %d (%s)", ret, get_error_message(ret));
349         return;
350       }
351
352       TerminateHandler* handler = static_cast<TerminateHandler*>(user_data);
353
354       LoggerD("Expected PID: %d, got: %d", handler->pid(), pid);
355
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);
361         delete handler;
362       }
363     };
364
365     LoggerD("Kill, setting callback");
366     handler->set_pid(pid);
367     ret = app_manager_set_app_context_event_cb(terminate_callback, handler);
368
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)
374     }
375
376     LoggerD("Kill, calling native function");
377
378     // terminate application
379     ret = app_manager_terminate_app(app_context);
380
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)
386     }
387
388     LoggerD("Kill, end, waiting for notification");
389   };
390
391   kill();
392 }
393
394 namespace {
395
396 PlatformResult PrepareAppControlForLaunchAppControl(const picojson::value& args,
397                                                     app_control_h* app_control) {
398   ScopeLogger();
399
400   const auto& control = args.get("appControl");
401   if (!control.is<picojson::object>()) {
402     return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
403   }
404   const picojson::object& app_control_obj = control.get<picojson::object>();
405
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);
410
411   if (result.IsError()) {
412     LoggerE("Application control to service failed.");
413     return result;
414   }
415
416   std::string app_id;
417   const auto& id = args.get("id");
418   if (id.is<std::string>()) {
419     app_id = id.get<std::string>();
420   }
421
422   if (!app_id.empty()) {
423     LoggerD("app_id: %s", app_id.c_str());
424
425     int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
426
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.");
430     }
431   }
432
433   *app_control = app_control_ptr.release();
434
435   return PlatformResult(ErrorCode::NO_ERROR);
436 }
437
438 }  // namespace
439
440 void ApplicationManager::LaunchAppControl(const picojson::value& args) {
441   ScopeLogger();
442
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>());
447   }
448
449   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
450   picojson::object& response_obj = response->get<picojson::object>();
451   response_obj.insert(
452       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
453
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);
458     return;
459   }
460
461   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
462       app_control_ptr(app_control, &app_control_destroy);
463
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>();
468   }
469
470   LaunchAppControlCallbackData* launch_app_user_data = new (std::nothrow)
471       LaunchAppControlCallbackData{&this->instance_, response, reply_callback_id};
472
473   if (!launch_app_user_data) {
474     LoggerE("Memory allocation fail!");
475     AsyncResponse(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response);
476     return;
477   }
478
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;
482
483     reply_callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
484                         void* user_data) {
485       ScopeLogger("reply_callback");
486
487       LaunchAppControlCallbackData* callback_data =
488           static_cast<LaunchAppControlCallbackData*>(user_data);
489
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);
493         return;
494       }
495
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)));
500
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");
507         }
508         ReportSuccess(return_value_obj);
509       } else {
510         ReportError(return_value_obj);
511       }
512
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
517     };
518   }
519
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");
523
524     LaunchAppControlCallbackData* callback_data =
525         static_cast<LaunchAppControlCallbackData*>(user_data);
526
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);
530       return;
531     }
532
533     auto result = utils::TranslateAppControlError(launch_result);
534
535     if (result.IsError()) {
536       LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
537     } else {
538       ReportSuccess(callback_data->response->get<picojson::object>());
539     }
540
541     Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
542
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
546   };
547
548   /*
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.
554    */
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)));
558
559   if (launch_result.IsError()) {
560     delete launch_app_user_data;
561     AsyncResponse(launch_result, &response);
562   } else {
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);
575   }
576 }
577 namespace {
578
579 PlatformResult TranslateLaunchError(app_control_error_e return_code) {
580   ScopeLogger();
581
582   auto result = utils::TranslateAppControlError(return_code);
583   if (ErrorCode::SECURITY_ERR == result.error_code()) {
584     result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
585   }
586
587   return result;
588 }
589
590 PlatformResult PrepareAppControlForLaunch(const picojson::value& args, app_control_h* app_control) {
591   ScopeLogger();
592
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.");
596   }
597   const auto app_id_str = app_id.get<std::string>();
598
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.");
604   }
605
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);
608
609   if (!app_id_str.empty()) {
610     LoggerD("app_id: %s", app_id_str.c_str());
611
612     int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str());
613
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.");
617     }
618   }
619
620   *app_control = app_control_ptr.release();
621
622   return PlatformResult(ErrorCode::NO_ERROR);
623 }
624
625 }  // namespace
626 void ApplicationManager::Launch(const picojson::value& args) {
627   ScopeLogger();
628
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>());
633   }
634
635   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
636   picojson::object& response_obj = response->get<picojson::object>();
637   response_obj.insert(
638       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
639
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);
644     return;
645   }
646
647   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
648       app_control_ptr(app_control, &app_control_destroy);
649
650   struct LaunchCallbackData {
651     ApplicationInstance* instance;
652     std::shared_ptr<picojson::value> response;
653   }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response};
654
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");
658
659     LaunchCallbackData* callback_data = static_cast<LaunchCallbackData*>(user_data);
660
661     auto result = TranslateLaunchError(launch_result);
662
663     if (result.IsError()) {
664       LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
665     } else {
666       ReportSuccess(callback_data->response->get<picojson::object>());
667     }
668
669     Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
670
671     delete callback_data;
672   };
673
674   /*
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.
680    */
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)));
683
684   if (launch_result.IsError()) {
685     delete launch_user_data;
686     AsyncResponse(launch_result, &response);
687   } else {
688     LoggerD("App launched");
689   }
690 }
691
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) {
696   ScopeLogger();
697   typedef struct {
698     app_control_h app_control;
699     app_control_app_matched_cb callback;
700     void* user_data;
701     bool foreach_break;
702   } foreach_context_launchable_app_t_internal;
703
704   // internal impl of app_control_cb_broker_foreach_app_matched()
705   auto app_control_cb_broker_foreach_app_matched_internal = [](const char* package,
706                                                                void* data) -> int {
707     ScopeLogger(
708         "Entered into asynchronous function, app_control_cb_broker_foreach_app_matched_internal's "
709         "argument");
710     foreach_context_launchable_app_t_internal* foreach_context;
711     app_control_app_matched_cb app_matched_cb;
712
713     if (package == NULL || data == NULL) {
714       LoggerE("APP_CONTROL_ERROR_INVALID_PARAMETER");
715       return -1;
716     }
717
718     foreach_context = (foreach_context_launchable_app_t_internal*)data;
719     if (foreach_context->foreach_break == true) return -1;
720
721     app_matched_cb = foreach_context->callback;
722     if (app_matched_cb != NULL) {
723       bool stop_foreach = false;
724
725       stop_foreach =
726           !app_matched_cb(foreach_context->app_control, package, foreach_context->user_data);
727
728       foreach_context->foreach_break = stop_foreach;
729     }
730
731     return 0;
732   };
733
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};
738
739   bundle* bundle_data = NULL;
740   app_control_to_bundle(app_control, &bundle_data);
741
742   int ret = appsvc_usr_get_list(bundle_data, app_control_cb_broker_foreach_app_matched_internal,
743                                 &foreach_context, getuid());
744
745   if (ret < 0) {
746     switch (ret) {
747       case APPSVC_RET_EINVAL:
748         return APP_CONTROL_ERROR_INVALID_PARAMETER;
749
750       case APPSVC_RET_ENOMATCH:
751         return APP_CONTROL_ERROR_APP_NOT_FOUND;
752
753       default:
754         return APP_CONTROL_ERROR_LAUNCH_FAILED;
755     }
756   }
757
758   return APP_CONTROL_ERROR_NONE;
759 }
760
761 void ApplicationManager::FindAppControl(const picojson::value& args) {
762   ScopeLogger();
763
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>());
768   }
769
770   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
771   picojson::object& response_obj = response->get<picojson::object>();
772   response_obj.insert(
773       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
774
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);
780     return;
781   }
782
783   const picojson::object& app_control_obj = control.get<picojson::object>();
784
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
789
790   if (result.IsError()) {
791     LoggerE("Application control to service failed.");
792     AsyncResponse(result, &response);
793     return;
794   }
795
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");
803         return false;
804       }
805
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));
810       } else {
811         picojson::array* array = static_cast<picojson::array*>(user_data);
812         array->push_back(picojson::value(picojson::object()));
813
814         utils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
815         pkgmgrinfo_appinfo_destroy_appinfo(handle);
816       }
817
818       return true;
819     };
820
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>();
824     auto array =
825         result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())));
826
827     int ret = app_control_foreach_app_matched_internal(app_control_ptr.get(), app_control_matched,
828                                                        &array.first->second.get<picojson::array>());
829
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) {
836         LogAndReportError(
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)));
843       }
844       // remove copied ApplicationControl from result
845       response_obj.erase(it_result);
846     } else {
847       ReportSuccess(response_obj);
848     }
849   };
850
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());
854   };
855
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")));
861
862   TaskQueue::GetInstance().Queue<picojson::value>(find, find_response, response);
863 }
864
865 void ApplicationManager::GetAppsContext(const picojson::value& args) {
866   ScopeLogger();
867
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>());
872   }
873
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>();
881
882     auto app_context_cb = [](app_context_h app_context, void* user_data) -> bool {
883       if (nullptr == user_data) {
884         return false;
885       }
886
887       picojson::array* array = static_cast<picojson::array*>(user_data);
888       array->push_back(picojson::value(picojson::object()));
889
890       if (!utils::CreateApplicationContext(app_context, &array->back().get<picojson::object>())) {
891         array->pop_back();
892         return false;
893       }
894
895       return true;
896     };
897
898     int ret = app_manager_foreach_app_context(app_context_cb, &array);
899
900     if (APP_MANAGER_ERROR_NONE != ret) {
901       LogAndReportError(
902           PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
903           ("app_manager_foreach_app_context error: %d (%s)", ret, get_error_message(ret)));
904     } else {
905       ReportSuccess(result, response_obj);
906     }
907   };
908
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());
914   };
915
916   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
917
918   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_context, get_apps_context_response,
919                                                   data);
920 }
921
922 void ApplicationManager::GetAppContext(const picojson::value& args, picojson::object* out) {
923   ScopeLogger();
924   pid_t pid = 0;
925
926   const auto& context_id = args.get("contextId");
927   if (context_id.is<std::string>()) {
928     try {
929       pid = std::stoi(context_id.get<std::string>());
930     } catch (...) {
931       LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert context id."),
932                         out);
933       return;
934     }
935   } else {
936     pid = CurrentApplication::GetInstance().GetProcessId();
937   }
938
939   char* app_id = nullptr;
940
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);
944
945   if (APP_MANAGER_ERROR_NONE != ret || nullptr == app_id) {
946     switch (ret) {
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"));
950         return;
951
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"));
955         return;
956
957       default:
958         LogAndReportError(
959             PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), out,
960             ("app_manager_get_app_id returned: %d (%s)", ret, get_error_message(ret)));
961         return;
962     }
963   }
964
965   picojson::value result = picojson::value(picojson::object());
966   utils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
967
968   ReportSuccess(result, *out);
969 }
970
971 void ApplicationManager::GetAppsInfo(const picojson::value& args) {
972   ScopeLogger();
973
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>());
978   }
979
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>();
988
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) {
992         return -1;
993       }
994
995       picojson::array* array = static_cast<picojson::array*>(user_data);
996       array->push_back(picojson::value(picojson::object()));
997
998       utils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
999
1000       return 0;
1001     };
1002
1003     int ret = pkgmgrinfo_appinfo_get_usr_installed_list(app_info_cb, getuid(), &array);
1004
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"));
1008     } else {
1009       ReportSuccess(result, response_obj);
1010     }
1011   };
1012
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());
1019   };
1020
1021   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1022
1023   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_info, get_apps_info_response, data);
1024 }
1025
1026 void ApplicationManager::GetAppInfo(const std::string& app_id, picojson::object* out) {
1027   ScopeLogger();
1028
1029   pkgmgrinfo_appinfo_h handle = nullptr;
1030
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);
1033     return;
1034   }
1035
1036   picojson::value result = picojson::value(picojson::object());
1037   utils::CreateApplicationInformation(handle, &result.get<picojson::object>());
1038   pkgmgrinfo_appinfo_destroy_appinfo(handle);
1039
1040   ReportSuccess(result, *out);
1041 }
1042
1043 char* ApplicationManager::GetPackageId(const std::string& app_id) {
1044   ScopeLogger();
1045   app_info_h handle;
1046   char* pkg_id = nullptr;
1047
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));
1051     return nullptr;
1052   }
1053
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));
1057     pkg_id = nullptr;
1058   }
1059
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));
1063   }
1064
1065   return pkg_id;
1066 }
1067
1068 void ApplicationManager::GetAppCerts(const std::string& app_id, picojson::object* out) {
1069   ScopeLogger();
1070
1071   char* package_id = nullptr;
1072
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);
1076
1077   if (!package_id) {
1078     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
1079     return;
1080   }
1081
1082   package_info_h pkg_info = nullptr;
1083   int ret = package_info_create(package_id, &pkg_info);
1084
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
1087
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)));
1091     return;
1092   }
1093
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;
1097
1098     switch (cert_type) {
1099       case PACKAGE_INFO_AUTHOR_ROOT_CERT:
1100         cert_name = "AUTHOR_ROOT";
1101         break;
1102       case PACKAGE_INFO_AUTHOR_INTERMEDIATE_CERT:
1103         cert_name = "AUTHOR_INTERMEDIATE";
1104         break;
1105       case PACKAGE_INFO_AUTHOR_SIGNER_CERT:
1106         cert_name = "AUTHOR_SIGNER";
1107         break;
1108       case PACKAGE_INFO_DISTRIBUTOR_ROOT_CERT:
1109         cert_name = "DISTRIBUTOR_ROOT";
1110         break;
1111       case PACKAGE_INFO_DISTRIBUTOR_INTERMEDIATE_CERT:
1112         cert_name = "DISTRIBUTOR_INTERMEDIATE";
1113         break;
1114       case PACKAGE_INFO_DISTRIBUTOR_SIGNER_CERT:
1115         cert_name = "DISTRIBUTOR_SIGNER";
1116         break;
1117       case PACKAGE_INFO_DISTRIBUTOR2_ROOT_CERT:
1118         cert_name = "DISTRIBUTOR2_ROOT";
1119         break;
1120       case PACKAGE_INFO_DISTRIBUTOR2_INTERMEDIATE_CERT:
1121         cert_name = "DISTRIBUTOR2_INTERMEDIATE";
1122         break;
1123       case PACKAGE_INFO_DISTRIBUTOR2_SIGNER_CERT:
1124         cert_name = "DISTRIBUTOR2_SIGNER";
1125         break;
1126       default:
1127         LoggerD("Unknown certificate type: %d", cert_type);
1128         break;
1129     }
1130
1131     picojson::array* array = static_cast<picojson::array*>(user_data);
1132     array->push_back(picojson::value(picojson::object()));
1133
1134     utils::CreateApplicationCertificate(cert_name, cert_value,
1135                                         &array->back().get<picojson::object>());
1136
1137     return true;
1138   };
1139
1140   picojson::value result = picojson::value(picojson::array());
1141
1142   ret = package_info_foreach_cert_info(pkg_info, cert_info_cb, &result.get<picojson::array>());
1143
1144   if ((PACKAGE_MANAGER_ERROR_NONE != ret) && (PACKAGE_MANAGER_ERROR_IO_ERROR != ret)) {
1145     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificates info."),
1146                       out,
1147                       ("Failed to get certificates info: %d (%s)", ret, get_error_message(ret)));
1148     return;
1149   }
1150
1151   ReportSuccess(result, *out);
1152 }
1153
1154 void ApplicationManager::GetAppSharedUri(const std::string& app_id, picojson::object* out) {
1155   ScopeLogger();
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);
1164       return;
1165     }
1166
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/
1171     LoggerW(
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);
1177       return;
1178     }
1179   }
1180
1181   std::string path_str = path;
1182   free(path);
1183
1184   std::string shared_path = path_str.substr(0, path_str.rfind("/", path_str.length() - 2));
1185
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);
1191     return;
1192   }
1193
1194   picojson::value result = picojson::value(kTizenApisFileScheme + shared_path);
1195   ReportSuccess(result, *out);
1196 }
1197
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) {
1202   ScopeLogger();
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>());
1207   }
1208
1209   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1210
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)));
1215   }
1216
1217   context_history_data_e data_type_in = CONTEXT_HISTORY_RECENT_BATTERY_USAGE;
1218
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);
1223
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)));
1228     }
1229   }
1230
1231   *data_type_out = data_type_in;
1232
1233   return PlatformResult(ErrorCode::NO_ERROR);
1234 }
1235
1236 PlatformResult ApplicationManager::BatteryUsageAttributes(const context_history_record_h record,
1237                                                           picojson::object* object) {
1238   ScopeLogger();
1239
1240   int ret = CONTEXT_HISTORY_ERROR_NONE;
1241   double amount = 0.0;
1242   char* app_id = nullptr;
1243   SCOPE_EXIT {
1244     free(app_id);
1245   };
1246
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)));
1251   }
1252
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)));
1257   }
1258
1259   object->insert(std::make_pair("appId", picojson::value(app_id)));
1260   object->insert(std::make_pair("batteryUsage", picojson::value(amount)));
1261
1262   return PlatformResult(ErrorCode::NO_ERROR);
1263 }
1264
1265 PlatformResult ApplicationManager::AppsUsageFilter(const picojson::value& args,
1266                                                    const context_history_filter_h filter,
1267                                                    context_history_data_e* data_type_out) {
1268   ScopeLogger();
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>());
1273   }
1274
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)));
1280   }
1281
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;
1285   }
1286
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>());
1296     }
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)));
1306     }
1307   } else {
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)));
1317       }
1318     }
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)));
1326       }
1327     }
1328   }
1329
1330   *data_type_out = data_type_in;
1331
1332   return PlatformResult(ErrorCode::NO_ERROR);
1333 }
1334
1335 PlatformResult ApplicationManager::AppsUsageAttributes(const context_history_record_h record,
1336                                                        picojson::object* object) {
1337   ScopeLogger();
1338
1339   int ret = CONTEXT_HISTORY_ERROR_NONE;
1340   int total_count = 0;
1341   int total_duration = 0;
1342   int last_time = 0;
1343   char* app_id = nullptr;
1344   SCOPE_EXIT {
1345     free(app_id);
1346   };
1347
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)));
1352   }
1353
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)));
1358   }
1359
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)));
1365   }
1366
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)));
1371   }
1372
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))));
1375   object->insert(
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))));
1378
1379   return PlatformResult(ErrorCode::NO_ERROR);
1380 }
1381 #endif
1382
1383 void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojson::object* out) {
1384   ScopeLogger();
1385
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>());
1391   }
1392
1393   auto get_battery_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1394     ScopeLogger();
1395     PlatformResult result = ApplicationManager::GetContextHistory(
1396         args, &response.get()->get<picojson::object>(), &ApplicationManager::BatteryUsageFilter,
1397         &ApplicationManager::BatteryUsageAttributes);
1398     if (!result) {
1399       LogAndReportError(result, &response.get()->get<picojson::object>());
1400     }
1401   };
1402
1403   auto get_battery_usage_response =
1404       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1405     ScopeLogger();
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());
1409   };
1410
1411   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1412
1413   TaskQueue::GetInstance().Queue<picojson::value>(get_battery_usage, get_battery_usage_response,
1414                                                   data);
1415 #else
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"));
1419 #endif
1420 }
1421
1422 void ApplicationManager::GetAppsUsageInfo(const picojson::value& args, picojson::object* out) {
1423   ScopeLogger();
1424
1425 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
1426   int callback_id = static_cast<int>(args.get(kCallbackId).get<double>());
1427
1428   auto get_apps_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1429     ScopeLogger();
1430     PlatformResult result = ApplicationManager::GetContextHistory(
1431         args, &response.get()->get<picojson::object>(), &ApplicationManager::AppsUsageFilter,
1432         &ApplicationManager::AppsUsageAttributes);
1433     if (!result) {
1434       LogAndReportError(result, &response.get()->get<picojson::object>());
1435     }
1436   };
1437
1438   auto get_apps_usage_response =
1439       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1440     ScopeLogger();
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());
1444   };
1445
1446   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1447
1448   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_usage, get_apps_usage_response, data);
1449 #else
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"));
1453 #endif
1454 }
1455
1456 void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) {
1457   ScopeLogger();
1458
1459   pkgmgrinfo_appinfo_h handle = nullptr;
1460
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
1465
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)));
1469     return;
1470   }
1471
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");
1475       return 0;
1476     }
1477
1478     picojson::array* array = static_cast<picojson::array*>(user_data);
1479     array->push_back(picojson::value(picojson::object()));
1480
1481     utils::CreateApplicationMetaData(meta_key, meta_value, &array->back().get<picojson::object>());
1482     return 0;
1483   };
1484
1485   picojson::value result = picojson::value(picojson::array());
1486   ret = pkgmgrinfo_appinfo_foreach_metadata(handle, meta_data_cb, &result.get<picojson::array>());
1487
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)));
1491     return;
1492   }
1493
1494   ReportSuccess(result, *out);
1495 }
1496
1497 class ApplicationListChangedBroker {
1498  public:
1499   ApplicationListChangedBroker() : event_type_() {
1500   }
1501   enum class Event {
1502     kInstalled,
1503     kUpdated,
1504     kUninstalled,
1505   };
1506
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) {
1510     ScopeLogger();
1511     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1512
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);
1517     } else {
1518       LoggerD("Ignored key: %s", key);
1519     }
1520
1521     return 0;
1522   }
1523
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) {
1526     ScopeLogger();
1527
1528     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1529
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();
1536     } else {
1537       LoggerD("Ignored key: %s", key);
1538     }
1539
1540     return 0;
1541   }
1542
1543   void AddApplicationInstance(ApplicationInstance* app_instance) {
1544     ScopeLogger();
1545     app_instance_list_.push_back(app_instance);
1546   }
1547
1548   void RemoveApplicationInstance(ApplicationInstance* app_instance) {
1549     ScopeLogger();
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);
1553         return;
1554       }
1555     }
1556   }
1557
1558  private:
1559   void HandleStart(const char* event_type, const char* package) {
1560     ScopeLogger();
1561     app_list_.clear();
1562     set_event_type(event_type);
1563   }
1564
1565   void HandleEnd(const char* package) {
1566     ScopeLogger();
1567
1568     if (Event::kUninstalled == event_type_) {
1569       return;
1570     }
1571
1572     GetApplicationIdsFromPackage(package);
1573
1574     for (auto& app_id : app_list_) {
1575       picojson::value value = picojson::value(picojson::object());
1576       picojson::object& data_obj = value.get<picojson::object>();
1577
1578       switch (event_type_) {
1579         case Event::kInstalled:
1580           data_obj.insert(std::make_pair(kAction, picojson::value(kOnInstalled)));
1581           break;
1582
1583         case Event::kUpdated:
1584           data_obj.insert(std::make_pair(kAction, picojson::value(kOnUpdated)));
1585           break;
1586         case Event::kUninstalled:
1587           LoggerD("Uninstalled called");
1588           break;
1589       }
1590
1591       switch (event_type_) {
1592         case Event::kInstalled:
1593         case Event::kUpdated: {
1594           pkgmgrinfo_appinfo_h handle = nullptr;
1595           if (PMINFO_R_OK !=
1596               pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1597             LoggerE("Failed to get application information handle.");
1598             continue;
1599           }
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);
1603         } break;
1604         case Event::kUninstalled:
1605           LoggerD("Uninstalled called");
1606           break;
1607       }
1608
1609       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1610
1611       for (auto instance : app_instance_list_) {
1612         Instance::PostMessage(instance, value.serialize().c_str());
1613       }
1614     }
1615   }
1616
1617   void GetApplicationIdsFromPackage(const char* package) {
1618     ScopeLogger();
1619     package_info_h package_info = nullptr;
1620
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));
1624       return;
1625     }
1626
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));
1631     }
1632
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));
1636     }
1637   }
1638
1639   void set_event_type(const char* type) {
1640     ScopeLogger();
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;
1647     }
1648   }
1649
1650   static bool ApplicationIdCallback(package_info_app_component_type_e comp_type, const char* app_id,
1651                                     void* user_data) {
1652     ScopeLogger();
1653     if (nullptr != app_id) {
1654       static_cast<ApplicationListChangedBroker*>(user_data)->app_list_.push_back(app_id);
1655     }
1656     return true;
1657   }
1658
1659   void HandleUninstallStart() {
1660     ScopeLogger();
1661     app_list_.clear();
1662     set_event_type(kUninstallEvent);
1663   }
1664
1665   void AddUninstalledAppId(const char* app_id) {
1666     ScopeLogger();
1667     if (nullptr != app_id) {
1668       app_list_.push_back(app_id);
1669     }
1670   }
1671
1672   void HandleUninstallEnd() {
1673     ScopeLogger();
1674     for (auto& app_id : app_list_) {
1675       picojson::value value = picojson::value(picojson::object());
1676       picojson::object& data_obj = value.get<picojson::object>();
1677
1678       data_obj.insert(std::make_pair(kAction, picojson::value(kOnUninstalled)));
1679       data_obj.insert(std::make_pair(kData, picojson::value(app_id)));
1680
1681       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1682
1683       for (auto instance : app_instance_list_) {
1684         Instance::PostMessage(instance, value.serialize().c_str());
1685       }
1686     }
1687   }
1688
1689   Event event_type_;
1690   std::vector<std::string> app_list_;
1691   std::vector<ApplicationInstance*> app_instance_list_;
1692 };
1693
1694 static ApplicationListChangedBroker g_application_list_changed_broker;
1695
1696 void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
1697   ScopeLogger();
1698
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);
1702     }
1703     if (nullptr == pkgmgr_client_uninstall_handle_) {
1704       pkgmgr_client_uninstall_handle_ = pkgmgr_client_new(PC_LISTENING);
1705     }
1706
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;
1711       }
1712       if (nullptr != pkgmgr_client_uninstall_handle_) {
1713         pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1714         pkgmgr_client_uninstall_handle_ = nullptr;
1715       }
1716       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."),
1717                         out);
1718       return;
1719     }
1720
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)); \
1727     return;                                                                                 \
1728   }
1729
1730     g_application_list_changed_broker.AddApplicationInstance(&instance_);
1731
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")
1736
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")
1740
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")
1745
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")
1750
1751 #undef CHECK_APPLICATION_EVENT_ERROR
1752   } else {
1753     LoggerD("Broker callback is already registered.");
1754   }
1755
1756   ReportSuccess(*out);
1757 }
1758
1759 void ApplicationManager::StopAppInfoEventListener() {
1760   ScopeLogger();
1761
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;
1766     }
1767     if (nullptr != pkgmgr_client_uninstall_handle_) {
1768       pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1769       pkgmgr_client_uninstall_handle_ = nullptr;
1770     }
1771     g_application_list_changed_broker.RemoveApplicationInstance(&instance_);
1772   } else {
1773     LoggerD("Broker callback is already unregistered.");
1774   }
1775 }
1776
1777 void ApplicationManager::GetApplicationInformationSize(const picojson::value& args,
1778                                                        picojson::object* out) {
1779   ScopeLogger();
1780
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."),
1784                       out);
1785     return;
1786   }
1787
1788   const std::string& package_id_str = package_id.get<std::string>();
1789
1790   // get installed size from package server (to solve smack issue)
1791   pkgmgr_client* pc = pkgmgr_client_new(PC_REQUEST);
1792   int size = -1;
1793
1794   if (nullptr == pc) {
1795     LoggerE("Failed to create pkgmgr client");
1796   } else {
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);
1799
1800     if (size < 0) {
1801       LoggerE("Failed to get installed size: %d (%s)", size, get_error_message(size));
1802     }
1803
1804     pkgmgr_client_free(pc);
1805   }
1806
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))));
1810
1811   ReportSuccess(result, *out);
1812 }
1813
1814 void ApplicationManager::BroadcastEventHelper(const picojson::value& args, picojson::object& out,
1815                                               bool trusted) {
1816   ScopeLogger();
1817
1818   int ret;
1819   std::string event_str = args.get("name").get<std::string>();
1820   const char* event_name = event_str.c_str();
1821
1822   bundle* data = bundle_create();
1823   SCOPE_EXIT {
1824     bundle_free(data);
1825   };
1826
1827   ret = bundle_add(data, "data", args.get("data").serialize().c_str());
1828
1829   if (ret != EVENT_ERROR_NONE) {
1830     LoggerE("bundle_add failed, error: %d (%s)", ret, get_error_message(ret));
1831     ReportError(out);
1832     return;
1833   }
1834
1835   if (trusted) {
1836     ret = event_publish_trusted_app_event(event_name, data);
1837   } else {
1838     ret = event_publish_app_event(event_name, data);
1839   }
1840
1841   if (ret == EVENT_ERROR_NONE) {
1842     ReportSuccess(out);
1843   } else {
1844     LoggerE("event_publish_app_event failed, error: %d (%s)", ret, get_error_message(ret));
1845     ReportError(out);
1846   }
1847 }
1848
1849 void ApplicationManager::OnEvent(const char* event_name, bundle* event_data, void* user_data) {
1850   ScopeLogger("Event name is: '%s'", event_name);
1851
1852   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1853
1854   if (!manager->event_callback_) {
1855     LoggerD("No event listener registered, skipping.");
1856     return;
1857   }
1858
1859   picojson::value event = picojson::value(picojson::object());
1860   picojson::object& event_o = event.get<picojson::object>();
1861
1862   int ret;
1863   char* val = nullptr;
1864
1865   if (event_map_.count(event_name)) {  // system event
1866     const std::string& key = event_map_.at(event_name);
1867     std::string state = "true";
1868     if (key != "") {
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));
1872         return;
1873       }
1874
1875       state = std::string(val);
1876     }
1877
1878     LoggerD("State is %s", state.c_str());
1879     event_o["value"] = picojson::value(state);
1880
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));
1885       return;
1886     }
1887
1888     picojson::value data;
1889     std::string err;
1890     picojson::parse(data, val, val + strlen(val), &err);
1891     if (!err.empty()) {
1892       LoggerE("Failed to parse bundle data: %s", err.c_str());
1893       return;
1894     }
1895
1896     event_o["data"] = data;
1897   }
1898
1899   LoggerD("event_name is: %s", event_name);
1900   event_o["name"] = picojson::value(event_name);
1901
1902   manager->event_callback_(&event);
1903 }
1904
1905 PlatformResult ApplicationManager::StartEventListener(const std::string& event_name,
1906                                                       const JsonCallback& callback) {
1907   ScopeLogger();
1908
1909   int ret;
1910   event_handler_h event_handler;
1911
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));
1920   }
1921
1922   event_handler_map_[event_name] = event_handler;
1923
1924   event_callback_ = callback;
1925   LoggerD("event_add_event_handler success");
1926   return PlatformResult(ErrorCode::NO_ERROR);
1927 }
1928
1929 void ApplicationManager::StopEventListener(const std::string& event_name) {
1930   ScopeLogger();
1931
1932   int ret;
1933   event_handler_h event_handler;
1934
1935   if (event_handler_map_.find(event_name) != event_handler_map_.end()) {
1936     event_handler = event_handler_map_[event_name];
1937
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));
1941       return;
1942     }
1943
1944     event_handler_map_.erase(event_name);
1945   }
1946 }
1947
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) {
1952   ScopeLogger();
1953
1954   if (APP_MANAGER_EVENT_STATE_COMPLETED != event_state) {
1955     LoggerD("State different from completed");
1956     return;
1957   }
1958
1959   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1960
1961   if (!manager || !manager->status_callback_) {
1962     LoggerD("No event listener registered, skipping.");
1963     return;
1964   }
1965
1966   bool status_type;
1967   switch (event_type) {
1968     case APP_MANAGER_EVENT_ENABLE_APP:
1969       status_type = true;
1970       break;
1971     case APP_MANAGER_EVENT_DISABLE_APP:
1972       status_type = false;
1973       break;
1974     default:
1975       LoggerD("Uknown status type skipping.");
1976       return;
1977   }
1978
1979   picojson::value event = picojson::value(picojson::object());
1980   picojson::object& event_o = event.get<picojson::object>();
1981
1982   event_o[kStatusType] = picojson::value(status_type);
1983   event_o[kAppId] = picojson::value(app_id);
1984   event_o[kListenerId] = picojson::value(kAppStatusChangeListener);
1985
1986   manager->status_callback_(&event);
1987 }
1988
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*)) {
1997   ScopeLogger();
1998   context_history_list_h list = nullptr;
1999   context_history_h handle = nullptr;
2000   context_history_filter_h filter = nullptr;
2001
2002   SCOPE_EXIT {
2003     context_history_list_destroy(list);
2004     context_history_destroy(handle);
2005     context_history_filter_destroy(filter);
2006   };
2007
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)));
2013   }
2014
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)));
2020   }
2021
2022   context_history_data_e data_type;
2023
2024   PlatformResult result = modify_filter_cb(args, filter, &data_type);
2025   if (!result) {
2026     return result;
2027   }
2028
2029   picojson::value result_array = picojson::value(picojson::array());
2030   picojson::array& array_obj = result_array.get<picojson::array>();
2031
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)));
2039   }
2040
2041   int size = 0;
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)));
2046   }
2047
2048   array_obj.resize(size, picojson::value(picojson::object()));
2049
2050   for (int i = 0; i < size; ++i) {
2051     context_history_record_h record = nullptr;
2052     SCOPE_EXIT {
2053       context_history_record_destroy(record);
2054     };
2055
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)));
2061     }
2062
2063     result = add_attributes_to_object(record, &array_obj[i].get<picojson::object>());
2064     if (!result) {
2065       return result;
2066     }
2067
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)));
2072     }
2073   }
2074
2075   ReportSuccess(result_array, *out);
2076   return PlatformResult(ErrorCode::NO_ERROR);
2077 }
2078 #endif
2079
2080 PlatformResult ApplicationManager::StartStatusListener(const JsonCallback& callback) {
2081   ScopeLogger();
2082
2083   int ret = APP_MANAGER_ERROR_NONE;
2084
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));
2090     }
2091
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));
2096     }
2097   }
2098
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));
2104   }
2105
2106   return PlatformResult(ErrorCode::NO_ERROR);
2107 }
2108
2109 PlatformResult ApplicationManager::StopStatusChangeListener() {
2110   ScopeLogger();
2111
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));
2117     }
2118   }
2119
2120   return PlatformResult(ErrorCode::NO_ERROR);
2121 }
2122
2123 }  // namespace application
2124 }  // namespace extension