Merge branch 'tizen_3.0' into tizen_4.0
[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 <unistd.h>
20 #include <type_traits>
21
22 #include <app_control_internal.h>
23 #include <app_info.h>
24 #include <app_manager_extension.h>
25 #include <appsvc.h>
26 #include <aul.h>
27 #include <bundle.h>
28 #include <bundle_internal.h>
29 #include <package_manager.h>
30 #include <pkgmgr-info.h>
31 #include <pkgmgr_installer.h>
32
33 #include "common/current_application.h"
34 #include "common/logger.h"
35 #include "common/platform_result.h"
36 #include "common/scope_exit.h"
37 #include "common/task-queue.h"
38 #include "common/tools.h"
39
40 #include "application/application_instance.h"
41 #include "application/application_utils.h"
42
43 using namespace common;
44 using namespace tools;
45
46 namespace extension {
47 namespace application {
48
49 namespace {
50 const std::string kTizenApisFileScheme = "file://";
51 const std::string kTizenApisAppSlash = "/";
52 const std::string kTizenApisAppShared = "shared";
53
54 const char* kStartKey = PKGMGR_INSTALLER_START_KEY_STR;
55 const char* kEndKey = PKGMGR_INSTALLER_END_KEY_STR;
56 const char* kOkValue = PKGMGR_INSTALLER_OK_EVENT_STR;
57 const char* kInstallEvent = PKGMGR_INSTALLER_INSTALL_EVENT_STR;
58 const char* kUpdateEvent = PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
59 const char* kUninstallEvent = PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
60
61 const char* kAppidKey = "appid";
62
63 const std::string kAction = "action";
64 const std::string kCallbackId = "callbackId";
65 const std::string kOnInstalled = "oninstalled";
66 const std::string kOnUpdated = "onupdated";
67 const std::string kOnUninstalled = "onuninstalled";
68 const std::string kData = "data";
69 const std::string kStatusType = "statusType";
70 const std::string kAppId = "appId";
71 const std::string kListenerId = "listenerId";
72 const std::string kAppStatusChangeListener = "AppStatusChangeListener";
73 const std::string kAppUsageModeFrequently = "FREQUENTLY";
74 const std::string kAppUsageModeRecently = "RECENTLY";
75
76 const std::map<std::string, std::string> event_map_ = {
77     {SYSTEM_EVENT_BATTERY_CHARGER_STATUS, EVENT_KEY_BATTERY_CHARGER_STATUS},
78     {SYSTEM_EVENT_BATTERY_LEVEL_STATUS, EVENT_KEY_BATTERY_LEVEL_STATUS},
79     {SYSTEM_EVENT_USB_STATUS, EVENT_KEY_USB_STATUS},
80     {SYSTEM_EVENT_EARJACK_STATUS, EVENT_KEY_EARJACK_STATUS},
81     {SYSTEM_EVENT_DISPLAY_STATE, EVENT_KEY_DISPLAY_STATE},
82     {SYSTEM_EVENT_LOW_MEMORY, EVENT_KEY_LOW_MEMORY},
83     {SYSTEM_EVENT_WIFI_STATE, EVENT_KEY_WIFI_STATE},
84     {SYSTEM_EVENT_BT_STATE, EVENT_KEY_BT_STATE},
85     {SYSTEM_EVENT_LOCATION_ENABLE_STATE, EVENT_KEY_LOCATION_ENABLE_STATE},
86     {SYSTEM_EVENT_GPS_ENABLE_STATE, EVENT_KEY_GPS_ENABLE_STATE},
87     {SYSTEM_EVENT_NPS_ENABLE_STATE, EVENT_KEY_NPS_ENABLE_STATE},
88     {SYSTEM_EVENT_INCOMING_MSG, EVENT_KEY_MSG_TYPE},
89     {SYSTEM_EVENT_TIME_ZONE, EVENT_KEY_TIME_ZONE},
90     {SYSTEM_EVENT_HOUR_FORMAT, EVENT_KEY_HOUR_FORMAT},
91     {SYSTEM_EVENT_LANGUAGE_SET, EVENT_KEY_LANGUAGE_SET},
92     {SYSTEM_EVENT_REGION_FORMAT, EVENT_KEY_REGION_FORMAT},
93     {SYSTEM_EVENT_SILENT_MODE, EVENT_KEY_SILENT_MODE},
94     {SYSTEM_EVENT_VIBRATION_STATE, EVENT_KEY_VIBRATION_STATE},
95     {SYSTEM_EVENT_SCREEN_AUTOROTATE_STATE, EVENT_KEY_SCREEN_AUTOROTATE_STATE},
96     {SYSTEM_EVENT_MOBILE_DATA_STATE, EVENT_KEY_MOBILE_DATA_STATE},
97     {SYSTEM_EVENT_DATA_ROAMING_STATE, EVENT_KEY_DATA_ROAMING_STATE},
98     {SYSTEM_EVENT_FONT_SET, EVENT_KEY_FONT_SET}};
99
100 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
101 const int kMaximumBatteryRetrievedObjects = 30;
102 const int kMaximumAppsRetrievedObjects = 10;
103 const int kDefaultPeriodOfTime = 30;
104 #endif
105 }
106
107 ApplicationManager::ApplicationManager(ApplicationInstance& instance)
108     : pkgmgr_client_handle_(nullptr),
109       pkgmgr_client_uninstall_handle_(nullptr),
110       instance_(instance),
111       app_status_handle_(nullptr) {
112   ScopeLogger();
113 }
114
115 ApplicationManager::~ApplicationManager() {
116   ScopeLogger();
117   StopAppInfoEventListener();
118   StopStatusChangeListener();
119
120   if (app_status_handle_) {
121     int ret = app_manager_event_destroy(app_status_handle_);
122     if (APP_MANAGER_ERROR_NONE != ret) {
123       LoggerE("app_manager_event_destroy failed, error: %d", ret);
124     }
125   }
126 }
127
128 void ApplicationManager::GetCurrentApplication(const std::string& app_id, picojson::object* out) {
129   ScopeLogger();
130
131   // obtain handle to application info
132   pkgmgrinfo_appinfo_h handle;
133   int ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle);
134   if (PMINFO_R_OK != ret) {
135     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get app info."), out,
136                       ("Failed to get app info: %d (%s)", ret, get_error_message(ret)));
137     return;
138   }
139
140   picojson::value app_info = picojson::value(picojson::object());
141   picojson::object& app_info_obj = app_info.get<picojson::object>();
142
143   ApplicationUtils::CreateApplicationInformation(handle, &app_info_obj);
144   pkgmgrinfo_appinfo_destroy_appinfo(handle);
145
146   picojson::value result = picojson::value(picojson::object());
147   picojson::object& result_obj = result.get<picojson::object>();
148
149   result_obj.insert(std::make_pair(
150       "contextId",
151       picojson::value(std::to_string(CurrentApplication::GetInstance().GetProcessId()))));
152   result_obj.insert(std::make_pair("appInfo", app_info));
153
154   ReportSuccess(result, *out);
155 }
156
157 class TerminateHandler {
158  public:
159   TerminateHandler(int callback_id, ApplicationInstance* app_instance)
160       : callback_handle_(callback_id), pid_(-1), timeout_id_(0), app_instance_(app_instance) {
161   }
162
163   void set_pid(pid_t pid) {
164     pid_ = pid;
165   }
166
167   pid_t pid() const {
168     return pid_;
169   }
170
171   void Invoke(const std::shared_ptr<picojson::value>& response) {
172     ScopeLogger();
173
174     if (timeout_id_ > 0) {
175       // cancel terminate callback
176       g_source_remove(timeout_id_);
177       timeout_id_ = 0;
178     }
179
180     ApplicationInstance* app_instance = this->app_instance_;
181     int callback_id = this->callback_handle_;
182     TaskQueue::GetInstance().Async<picojson::value>(
183         [callback_id, app_instance](const std::shared_ptr<picojson::value>& response) {
184           picojson::object& obj = response->get<picojson::object>();
185           obj.insert(
186               std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
187           Instance::PostMessage(app_instance, response->serialize().c_str());
188         },
189         response);
190   }
191
192  private:
193   int callback_handle_;
194   pid_t pid_;
195   guint timeout_id_;
196   ApplicationInstance* app_instance_;
197 };
198
199 #define CHECK_RESULT(result, response, handler)                    \
200   if (result.IsError()) {                                          \
201     LogAndReportError(result, &response->get<picojson::object>()); \
202     handler->Invoke(response);                                     \
203     delete handler;                                                \
204     return;                                                        \
205   }
206
207 void ApplicationManager::AsyncResponse(PlatformResult& result,
208                                        std::shared_ptr<picojson::value>* response) {
209   ScopeLogger();
210   LogAndReportError(result, &(*response)->get<picojson::object>());
211
212   TaskQueue::GetInstance().Async<picojson::value>(
213       [this](const std::shared_ptr<picojson::value>& response) {
214         Instance::PostMessage(&this->instance_, response->serialize().c_str());
215       },
216       *response);
217 }
218
219 void ApplicationManager::Kill(const picojson::value& args) {
220   ScopeLogger();
221
222   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
223
224   int callback_id = -1;
225   const auto& callback = args.get(kCallbackId);
226   if (callback.is<double>()) {
227     callback_id = static_cast<int>(callback.get<double>());
228   }
229
230   const auto& context = args.get("contextId");
231   if (!context.is<std::string>()) {
232     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
233   }
234
235   const std::string& context_id = context.get<std::string>();
236
237   if (context_id.empty() && result.IsSuccess()) {
238     result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Context ID is empty.");
239   }
240
241   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
242   picojson::object& obj = response->get<picojson::object>();
243   obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
244
245   if (result.IsError()) {
246     LoggerE("Failed args.get");
247     AsyncResponse(result, &response);
248     return;
249   }
250
251   auto kill = [this, callback_id, context_id]() -> void {
252     ScopeLogger("Kill");
253
254     std::shared_ptr<picojson::value> response =
255         std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
256
257     TerminateHandler* handler = new TerminateHandler(callback_id, &this->instance_);
258     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
259
260     pid_t pid = -1;
261     try {
262       pid = std::stoi(context_id);
263     } catch (...) {
264       result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert string to int.");
265       CHECK_RESULT(result, response, handler)
266     }
267
268     if (pid <= 0) {
269       result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Context ID cannot be negative value.");
270       CHECK_RESULT(result, response, handler)
271     }
272
273     // if kill request comes for current context, throw InvalidValuesException
274     if (CurrentApplication::GetInstance().GetProcessId() == pid) {
275       result =
276           LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Cannot kill current application.");
277       CHECK_RESULT(result, response, handler)
278     }
279
280     LoggerD("Kill, pid: %d", pid);
281
282     char* app_id = nullptr;
283     int ret = app_manager_get_app_id(pid, &app_id);
284     // automatically release the memory
285     std::unique_ptr<char, void (*)(void*)> app_id_ptr(app_id, &std::free);
286
287     if (APP_MANAGER_ERROR_NONE != ret) {
288       result = LogAndCreateResult(
289           ErrorCode::NOT_FOUND_ERR, "Failed to get application ID.",
290           ("Failed to get application ID, error: %d (%s)", ret, get_error_message(ret)));
291       CHECK_RESULT(result, response, handler)
292     }
293
294     LoggerD("Kill, app ID: %s", app_id);
295
296     // acquire application context
297     app_context_h app_context = nullptr;
298
299     ret = app_manager_get_app_context(app_id, &app_context);
300     std::unique_ptr<std::remove_pointer<app_context_h>::type, int (*)(app_context_h)>
301         app_context_ptr(app_context, &app_context_destroy);  // automatically release the memory
302
303     if (APP_MANAGER_ERROR_NONE != ret) {
304       result = LogAndCreateResult(
305           ErrorCode::NOT_FOUND_ERR, "Failed to get application ID.",
306           ("Failed to get application context handle: %d (%s)", ret, get_error_message(ret)));
307       CHECK_RESULT(result, response, handler)
308     }
309
310     auto terminate_callback = [](app_context_h app_context, app_context_event_e event,
311                                  void* user_data) {
312       LoggerD("terminate_callback: %d", event);
313
314       if (APP_CONTEXT_EVENT_TERMINATED != event) {
315         LoggerD("ignoring event");
316         return;
317       }
318
319       int pid = 0;
320       int ret = app_context_get_pid(app_context, &pid);
321
322       if (APP_MANAGER_ERROR_NONE != ret) {
323         LoggerE("Failed to get pid of terminated app: %d (%s)", ret, get_error_message(ret));
324         return;
325       }
326
327       TerminateHandler* handler = static_cast<TerminateHandler*>(user_data);
328
329       LoggerD("Expected PID: %d, got: %d", handler->pid(), pid);
330
331       if (handler->pid() == pid) {
332         std::shared_ptr<picojson::value> response =
333             std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
334         ReportSuccess(response->get<picojson::object>());
335         handler->Invoke(response);
336         delete handler;
337       }
338     };
339
340     LoggerD("Kill, setting callback");
341     handler->set_pid(pid);
342     ret = app_manager_set_app_context_event_cb(terminate_callback, handler);
343
344     if (APP_MANAGER_ERROR_NONE != ret) {
345       result = LogAndCreateResult(
346           ErrorCode::UNKNOWN_ERR, "Failed to register termination callback.",
347           ("Error while registering app context event: %d (%s)", ret, get_error_message(ret)));
348       CHECK_RESULT(result, response, handler)
349     }
350
351     LoggerD("Kill, calling native function");
352
353     // terminate application
354     ret = app_manager_terminate_app(app_context);
355
356     if (APP_MANAGER_ERROR_NONE != ret) {
357       result = LogAndCreateResult(
358           ErrorCode::UNKNOWN_ERR, "Failed to terminate application.",
359           ("Failed to terminate application: %d (%s)", ret, get_error_message(ret)));
360       CHECK_RESULT(result, response, handler)
361     }
362
363     LoggerD("Kill, end, waiting for notification");
364   };
365
366   kill();
367 }
368
369 void ApplicationManager::Launch(const picojson::value& args) {
370   ScopeLogger();
371
372   int callback_id = -1;
373   const auto& callback = args.get(kCallbackId);
374   if (callback.is<double>()) {
375     callback_id = static_cast<int>(callback.get<double>());
376   }
377
378   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
379   picojson::object& obj = response->get<picojson::object>();
380   obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
381
382   const auto& app_id = args.get("id");
383   if (!app_id.is<std::string>()) {
384     PlatformResult ret =
385         LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
386     AsyncResponse(ret, &response);
387     return;
388   }
389   const std::string& id = app_id.get<std::string>();
390
391   auto launch = [id](const std::shared_ptr<picojson::value>& response) -> void {
392     ScopeLogger("launch");
393     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
394     const char* app_id = id.c_str();
395     const int retry_count = 3;
396
397     int retry = 0;
398     int ret = 0;
399
400     while (retry < retry_count) {
401       ret = aul_open_app(app_id);
402
403       if (ret >= 0) {
404         break;
405       }
406
407       // delay 300ms for each retry
408       struct timespec sleep_time = {0, 300L * 1000L * 1000L};
409       nanosleep(&sleep_time, nullptr);
410       ++retry;
411
412       LoggerD("Retry launch request: %d", retry);
413     }
414
415     if (ret < 0) {
416       result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error has occurred.");
417
418       LoggerD("Aul open return: %d (%s)", ret, get_error_message(ret));
419       switch (ret) {
420         case AUL_R_EINVAL:
421         case AUL_R_ERROR:
422         case AUL_R_ENOAPP:
423           result =
424               LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Launchpad returns not found error.",
425                                  ("aul_open_app returns Not Found error"));
426           break;
427
428         case AUL_R_ECOMM:
429           result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Internal IPC error has occurred.",
430                                       ("aul_open_app returns internal IPC error"));
431           break;
432       }
433
434       LogAndReportError(result, &response->get<picojson::object>());
435     } else {
436       LoggerD("Launch request success");
437       ReportSuccess(response->get<picojson::object>());
438     }
439   };
440
441   launch(response);
442   Instance::PostMessage(&this->instance_, response->serialize().c_str());
443 }
444
445 void ApplicationManager::LaunchAppControl(const picojson::value& args) {
446   ScopeLogger();
447
448   int callback_id = -1;
449   const auto& callback = args.get(kCallbackId);
450   if (callback.is<double>()) {
451     callback_id = static_cast<int>(callback.get<double>());
452   }
453
454   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
455   picojson::object& response_obj = response->get<picojson::object>();
456   response_obj.insert(
457       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
458
459   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
460   const auto& control = args.get("appControl");
461   if (!control.is<picojson::object>()) {
462     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
463     AsyncResponse(result, &response);
464     return;
465   }
466   const picojson::object& app_control_obj = control.get<picojson::object>();
467
468   std::string launch_mode_str;
469   const auto& launch_mode = control.get("launchMode");
470   if (launch_mode.is<std::string>()) {
471     launch_mode_str = launch_mode.get<std::string>();
472   }
473
474   app_control_h app_control = nullptr;
475   result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
476   std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_ptr(
477       app_control, &app_control_destroy);  // automatically release the memory
478
479   if (result.IsError()) {
480     LoggerE("Application control to service failed.");
481     AsyncResponse(result, &response);
482     return;
483   }
484
485   std::string app_id;
486   const auto& id = args.get("id");
487   if (id.is<std::string>()) {
488     app_id = id.get<std::string>();
489   }
490
491   std::string reply_callback;
492   const auto& reply = args.get("replyCallback");
493   if (reply.is<std::string>()) {
494     reply_callback = reply.get<std::string>();
495   }
496
497   auto launch = [this, app_control_ptr, app_id, launch_mode_str,
498                  reply_callback](const std::shared_ptr<picojson::value>& response) -> void {
499     ScopeLogger("Entered into asynchronous function, launch");
500
501     if (!app_id.empty()) {
502       LoggerD("app_id: %s", app_id.c_str());
503
504       int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
505
506       if (APP_CONTROL_ERROR_NONE != ret) {
507         LogAndReportError(
508             PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
509             &response->get<picojson::object>(),
510             ("Failed to set app id: %d (%s)", ret, get_error_message(ret)));
511         return;
512       }
513     }
514
515     if (!launch_mode_str.empty()) {
516       app_control_launch_mode_e launch_mode;
517
518       if ("SINGLE" == launch_mode_str) {
519         launch_mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
520       } else if ("GROUP" == launch_mode_str) {
521         launch_mode = APP_CONTROL_LAUNCH_MODE_GROUP;
522       } else {
523         ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
524                     &response->get<picojson::object>());
525         return;
526       }
527
528       int ret = app_control_set_launch_mode(app_control_ptr.get(), launch_mode);
529       if (APP_CONTROL_ERROR_NONE != ret) {
530         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Setting launch mode failed."),
531                           &response->get<picojson::object>(),
532                           ("Setting launch mode failed: %d (%s)", ret, get_error_message(ret)));
533         return;
534       }
535     }
536
537     app_control_reply_cb callback = nullptr;
538     struct ReplayCallbackData {
539       ApplicationInstance* app_instance;
540       std::string reply_callback;
541     };
542
543     ReplayCallbackData* user_data = nullptr;
544
545     if (!reply_callback.empty()) {
546       user_data = new ReplayCallbackData();
547       user_data->app_instance = &this->instance_;
548       user_data->reply_callback = reply_callback;
549
550       callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
551                     void* user_data) {
552         LoggerD("send_launch_request callback");
553
554         picojson::value return_value = picojson::value(picojson::object());
555         picojson::object& return_value_obj = return_value.get<picojson::object>();
556         ReplayCallbackData* reply_callback = static_cast<ReplayCallbackData*>(user_data);
557
558         if (APP_CONTROL_RESULT_SUCCEEDED == result) {
559           const std::string data = "data";
560           return_value_obj.insert(std::make_pair(data, picojson::value(picojson::array())));
561           if (!ApplicationUtils::ServiceToApplicationControlDataArray(
562                   reply, &return_value_obj.find(data)->second.get<picojson::array>())) {
563             return_value_obj.erase(data);
564           }
565           ReportSuccess(return_value_obj);
566         } else {
567           ReportError(return_value_obj);
568         }
569
570         return_value_obj.insert(
571             std::make_pair("listenerId", picojson::value(reply_callback->reply_callback)));
572         Instance::PostMessage(reply_callback->app_instance, return_value.serialize().c_str());
573         delete reply_callback;
574       };
575     }
576
577     const int retry_count = 3;
578
579     int retry = 0;
580     int ret = 0;
581
582     while (retry < retry_count) {
583       LoggerD("Calling launch request. Attempt number: %d", retry);
584
585       ret = app_control_send_launch_request(app_control_ptr.get(), callback, user_data);
586       LoggerD("App control launch request returned: %d, %s", ret, get_error_message(ret));
587       if (APP_CONTROL_ERROR_NONE == ret) {
588         break;
589       }
590
591       // delay 300ms for each retry
592       struct timespec sleep_time = {0, 300L * 1000L * 1000L};
593       nanosleep(&sleep_time, nullptr);
594       ++retry;
595     }
596
597     if (APP_CONTROL_ERROR_NONE != ret) {
598       delete user_data;
599
600       switch (ret) {
601         case APP_CONTROL_ERROR_INVALID_PARAMETER:
602           LogAndReportError(
603               PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter returned."),
604               &response->get<picojson::object>(),
605               ("app_control_send_launch_request returns APP_CONTROL_ERROR_INVALID_PARAMETER"));
606           return;
607         case APP_CONTROL_ERROR_OUT_OF_MEMORY:
608           LogAndReportError(
609               PlatformResult(ErrorCode::UNKNOWN_ERR, "Out of memory."),
610               &response->get<picojson::object>(),
611               ("app_control_send_launch_request returns APP_CONTROL_ERROR_OUT_OF_MEMORY"));
612           return;
613         case APP_CONTROL_ERROR_LAUNCH_REJECTED:
614         case APP_CONTROL_ERROR_APP_NOT_FOUND:
615           LogAndReportError(
616               PlatformResult(ErrorCode::NOT_FOUND_ERR, "No matched application found."),
617               &response->get<picojson::object>(),
618               ("app_control_send_launch_request returns APP_CONTROL_ERROR_APP_NOT_FOUND"));
619           return;
620         default:
621           LogAndReportError(
622               PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."),
623               &response->get<picojson::object>(),
624               ("app_control_send_launch_request returns: %d (%s)", ret, get_error_message(ret)));
625           return;
626       }
627     }
628     ReportSuccess(response->get<picojson::object>());
629   };
630
631   launch(response);
632   Instance::PostMessage(&this->instance_, response->serialize().c_str());
633 }
634
635 // internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
636 // public CAPI did not handling APP_CONTROL_ERROR_APP_NOT_FOUND
637 int app_control_foreach_app_matched_internal(app_control_h app_control,
638                                              app_control_app_matched_cb callback, void* user_data) {
639   ScopeLogger();
640   typedef struct {
641     app_control_h app_control;
642     app_control_app_matched_cb callback;
643     void* user_data;
644     bool foreach_break;
645   } foreach_context_launchable_app_t_internal;
646
647   // internal impl of app_control_cb_broker_foreach_app_matched()
648   auto app_control_cb_broker_foreach_app_matched_internal = [](const char* package,
649                                                                void* data) -> int {
650     ScopeLogger(
651         "Entered into asynchronous function, app_control_cb_broker_foreach_app_matched_internal's "
652         "argument");
653     foreach_context_launchable_app_t_internal* foreach_context;
654     app_control_app_matched_cb app_matched_cb;
655
656     if (package == NULL || data == NULL) {
657       LoggerE("APP_CONTROL_ERROR_INVALID_PARAMETER");
658       return -1;
659     }
660
661     foreach_context = (foreach_context_launchable_app_t_internal*)data;
662     if (foreach_context->foreach_break == true) return -1;
663
664     app_matched_cb = foreach_context->callback;
665     if (app_matched_cb != NULL) {
666       bool stop_foreach = false;
667
668       stop_foreach =
669           !app_matched_cb(foreach_context->app_control, package, foreach_context->user_data);
670
671       foreach_context->foreach_break = stop_foreach;
672     }
673
674     return 0;
675   };
676
677   foreach_context_launchable_app_t_internal foreach_context = {.app_control = app_control,
678                                                                .callback = callback,
679                                                                .user_data = user_data,
680                                                                .foreach_break = false};
681
682   bundle* bundle_data = NULL;
683   app_control_to_bundle(app_control, &bundle_data);
684
685   int ret = appsvc_usr_get_list(bundle_data, app_control_cb_broker_foreach_app_matched_internal,
686                                 &foreach_context, getuid());
687
688   if (ret < 0) {
689     switch (ret) {
690       case APPSVC_RET_EINVAL:
691         return APP_CONTROL_ERROR_INVALID_PARAMETER;
692
693       case APPSVC_RET_ENOMATCH:
694         return APP_CONTROL_ERROR_APP_NOT_FOUND;
695
696       default:
697         return APP_CONTROL_ERROR_LAUNCH_FAILED;
698     }
699   }
700
701   return APP_CONTROL_ERROR_NONE;
702 }
703
704 void ApplicationManager::FindAppControl(const picojson::value& args) {
705   ScopeLogger();
706
707   int callback_id = -1;
708   const auto& callback = args.get(kCallbackId);
709   if (callback.is<double>()) {
710     callback_id = static_cast<int>(callback.get<double>());
711   }
712
713   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
714   picojson::object& response_obj = response->get<picojson::object>();
715   response_obj.insert(
716       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
717
718   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
719   const auto& control = args.get("appControl");
720   if (!control.is<picojson::object>()) {
721     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
722     AsyncResponse(result, &response);
723     return;
724   }
725
726   const picojson::object& app_control_obj = control.get<picojson::object>();
727
728   app_control_h app_control = nullptr;
729   result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
730   std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_ptr(
731       app_control, &app_control_destroy);  // automatically release the memory
732
733   if (result.IsError()) {
734     LoggerE("Application control to service failed.");
735     AsyncResponse(result, &response);
736     return;
737   }
738
739   auto find = [app_control_ptr](const std::shared_ptr<picojson::value>& response) -> void {
740     ScopeLogger("Entered into asynchronous function, find");
741     auto app_control_matched = [](app_control_h app_control, const char* appid,
742                                   void* user_data) -> bool {
743       ScopeLogger("Entered into asynchronous function, app_control_matched");
744       if (nullptr == appid) {
745         LoggerD("appid is NULL");
746         return false;
747       }
748
749       pkgmgrinfo_appinfo_h handle;
750       int ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, getuid(), &handle);
751       if (PMINFO_R_OK != ret) {
752         LoggerE("Failed to get appInfo: %d (%s)", ret, get_error_message(ret));
753       } else {
754         picojson::array* array = static_cast<picojson::array*>(user_data);
755         array->push_back(picojson::value(picojson::object()));
756
757         ApplicationUtils::CreateApplicationInformation(handle,
758                                                        &array->back().get<picojson::object>());
759         pkgmgrinfo_appinfo_destroy_appinfo(handle);
760       }
761
762       return true;
763     };
764
765     picojson::object& response_obj = response->get<picojson::object>();
766     auto it_result = response_obj.find("result");
767     picojson::object& result_obj = it_result->second.get<picojson::object>();
768     auto array =
769         result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())));
770
771     int ret = app_control_foreach_app_matched_internal(app_control_ptr.get(), app_control_matched,
772                                                        &array.first->second.get<picojson::array>());
773
774     if (APP_CONTROL_ERROR_NONE != ret) {
775       if (APP_CONTROL_ERROR_APP_NOT_FOUND == ret) {
776         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Matched Application not found"),
777                           &response_obj, ("app_control_foreach_app_matched error: %d (%s)", ret,
778                                           get_error_message(ret)));
779       } else if (APP_CONTROL_ERROR_LAUNCH_FAILED == ret) {
780         LogAndReportError(
781             PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), &response_obj,
782             ("app_control_foreach_app_matched error: %d (%s)", ret, get_error_message(ret)));
783       } else if (APP_CONTROL_ERROR_INVALID_PARAMETER == ret) {
784         LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed"),
785                           &response_obj, ("app_control_foreach_app_matched error: %d (%s)", ret,
786                                           get_error_message(ret)));
787       }
788       // remove copied ApplicationControl from result
789       response_obj.erase(it_result);
790     } else {
791       ReportSuccess(response_obj);
792     }
793   };
794
795   auto find_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
796     ScopeLogger("Entered into asynchronous function, find_response");
797     Instance::PostMessage(&this->instance_, response->serialize().c_str());
798   };
799
800   // prepare result object, we need to do that here, as input parameter is passed to result callback
801   auto ret = response_obj.insert(std::make_pair("result", picojson::value(picojson::object())));
802   // reinsert application control
803   ret.first->second.get<picojson::object>().insert(
804       std::make_pair("appControl", args.get("appControl")));
805
806   TaskQueue::GetInstance().Queue<picojson::value>(find, find_response, response);
807 }
808
809 void ApplicationManager::GetAppsContext(const picojson::value& args) {
810   ScopeLogger();
811
812   int callback_id = -1;
813   const auto& callback = args.get(kCallbackId);
814   if (callback.is<double>()) {
815     callback_id = static_cast<int>(callback.get<double>());
816   }
817
818   auto get_apps_context = [](const std::shared_ptr<picojson::value>& response) -> void {
819     picojson::object& response_obj = response->get<picojson::object>();
820     picojson::value result = picojson::value(picojson::object());
821     picojson::object& result_obj = result.get<picojson::object>();
822     picojson::array& array =
823         result_obj.insert(std::make_pair("contexts", picojson::value(picojson::array())))
824             .first->second.get<picojson::array>();
825
826     auto app_context_cb = [](app_context_h app_context, void* user_data) -> bool {
827       if (nullptr == user_data) {
828         return false;
829       }
830
831       picojson::array* array = static_cast<picojson::array*>(user_data);
832       array->push_back(picojson::value(picojson::object()));
833
834       if (!ApplicationUtils::CreateApplicationContext(app_context,
835                                                       &array->back().get<picojson::object>())) {
836         array->pop_back();
837         return false;
838       }
839
840       return true;
841     };
842
843     int ret = app_manager_foreach_app_context(app_context_cb, &array);
844
845     if (APP_MANAGER_ERROR_NONE != ret) {
846       LogAndReportError(
847           PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
848           ("app_manager_foreach_app_context error: %d (%s)", ret, get_error_message(ret)));
849     } else {
850       ReportSuccess(result, response_obj);
851     }
852   };
853
854   auto get_apps_context_response =
855       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
856     picojson::object& obj = response->get<picojson::object>();
857     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
858     Instance::PostMessage(&this->instance_, response->serialize().c_str());
859   };
860
861   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
862
863   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_context, get_apps_context_response,
864                                                   data);
865 }
866
867 void ApplicationManager::GetAppContext(const picojson::value& args, picojson::object* out) {
868   ScopeLogger();
869   pid_t pid = 0;
870
871   const auto& context_id = args.get("contextId");
872   if (context_id.is<std::string>()) {
873     try {
874       pid = std::stoi(context_id.get<std::string>());
875     } catch (...) {
876       LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert context id."),
877                         out);
878       return;
879     }
880   } else {
881     pid = CurrentApplication::GetInstance().GetProcessId();
882   }
883
884   char* app_id = nullptr;
885
886   int ret = app_manager_get_app_id(pid, &app_id);
887   // automatically release the memory
888   std::unique_ptr<char, void (*)(void*)> app_id_ptr(app_id, &std::free);
889
890   if (APP_MANAGER_ERROR_NONE != ret || nullptr == app_id) {
891     switch (ret) {
892       case APP_MANAGER_ERROR_NO_SUCH_APP:
893         LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "No such application exist."), out,
894                           ("app_manager_get_app_id returned: APP_MANAGER_ERROR_NO_SUCH_APP"));
895         return;
896
897       case APP_MANAGER_ERROR_INVALID_PARAMETER:
898         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Application not found."), out,
899                           ("app_manager_get_app_id returned: APP_MANAGER_ERROR_INVALID_PARAMETER"));
900         return;
901
902       default:
903         LogAndReportError(
904             PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), out,
905             ("app_manager_get_app_id returned: %d (%s)", ret, get_error_message(ret)));
906         return;
907     }
908   }
909
910   picojson::value result = picojson::value(picojson::object());
911   ApplicationUtils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
912
913   ReportSuccess(result, *out);
914 }
915
916 void ApplicationManager::GetAppsInfo(const picojson::value& args) {
917   ScopeLogger();
918
919   int callback_id = -1;
920   const auto& callback = args.get(kCallbackId);
921   if (callback.is<double>()) {
922     callback_id = static_cast<int>(callback.get<double>());
923   }
924
925   auto get_apps_info = [](const std::shared_ptr<picojson::value>& response) -> void {
926     ScopeLogger("Entered into asynchronous function, get_apps_info");
927     picojson::object& response_obj = response->get<picojson::object>();
928     picojson::value result = picojson::value(picojson::object());
929     picojson::object& result_obj = result.get<picojson::object>();
930     picojson::array& array =
931         result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())))
932             .first->second.get<picojson::array>();
933
934     auto app_info_cb = [](pkgmgrinfo_appinfo_h handle, void* user_data) -> int {
935       ScopeLogger("Entered into asynchronous function, app_info_cb");
936       if (nullptr == user_data) {
937         return -1;
938       }
939
940       picojson::array* array = static_cast<picojson::array*>(user_data);
941       array->push_back(picojson::value(picojson::object()));
942
943       ApplicationUtils::CreateApplicationInformation(handle,
944                                                      &array->back().get<picojson::object>());
945
946       return 0;
947     };
948
949     int ret = pkgmgrinfo_appinfo_get_usr_installed_list(app_info_cb, getuid(), &array);
950
951     if (APP_MANAGER_ERROR_NONE != ret) {
952       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
953                         ("pkgmgrinfo_appinfo_get_usr_installed_list error"));
954     } else {
955       ReportSuccess(result, response_obj);
956     }
957   };
958
959   auto get_apps_info_response =
960       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
961     ScopeLogger("Entered into asynchronous function, get_apps_info_response");
962     picojson::object& obj = response->get<picojson::object>();
963     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
964     Instance::PostMessage(&this->instance_, response->serialize().c_str());
965   };
966
967   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
968
969   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_info, get_apps_info_response, data);
970 }
971
972 void ApplicationManager::GetAppInfo(const std::string& app_id, picojson::object* out) {
973   ScopeLogger();
974
975   pkgmgrinfo_appinfo_h handle = nullptr;
976
977   if (PMINFO_R_OK != pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
978     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out);
979     return;
980   }
981
982   picojson::value result = picojson::value(picojson::object());
983   ApplicationUtils::CreateApplicationInformation(handle, &result.get<picojson::object>());
984   pkgmgrinfo_appinfo_destroy_appinfo(handle);
985
986   ReportSuccess(result, *out);
987 }
988
989 char* ApplicationManager::GetPackageId(const std::string& app_id) {
990   ScopeLogger();
991   app_info_h handle;
992   char* pkg_id = nullptr;
993
994   int ret = app_manager_get_app_info(app_id.c_str(), &handle);
995   if (APP_MANAGER_ERROR_NONE != ret) {
996     LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
997     return nullptr;
998   }
999
1000   ret = app_info_get_package(handle, &pkg_id);
1001   if (APP_MANAGER_ERROR_NONE != ret) {
1002     LoggerE("Failed to get package id: %d (%s)", ret, get_error_message(ret));
1003     pkg_id = nullptr;
1004   }
1005
1006   ret = app_info_destroy(handle);
1007   if (APP_MANAGER_ERROR_NONE != ret) {
1008     LoggerE("Failed to destroy app info: %d (%s)", ret, get_error_message(ret));
1009   }
1010
1011   return pkg_id;
1012 }
1013
1014 void ApplicationManager::GetAppCerts(const std::string& app_id, picojson::object* out) {
1015   ScopeLogger();
1016
1017   char* package_id = nullptr;
1018
1019   package_id = GetPackageId(app_id);
1020   // automatically release the memory
1021   std::unique_ptr<char, void (*)(void*)> package_id_ptr(package_id, &std::free);
1022
1023   if (!package_id) {
1024     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
1025     return;
1026   }
1027
1028   package_info_h pkg_info = nullptr;
1029   int ret = package_info_create(package_id, &pkg_info);
1030
1031   std::unique_ptr<std::remove_pointer<package_info_h>::type, int (*)(package_info_h)> pkg_info_ptr(
1032       pkg_info, &package_info_destroy);  // automatically release the memory
1033
1034   if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1035     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out,
1036                       ("Failed to get package info: %d (%s)", ret, get_error_message(ret)));
1037     return;
1038   }
1039
1040   auto cert_info_cb = [](package_info_h handle, package_cert_type_e cert_type,
1041                          const char* cert_value, void* user_data) -> bool {
1042     const char* cert_name = nullptr;
1043
1044     switch (cert_type) {
1045       case PACKAGE_INFO_AUTHOR_ROOT_CERT:
1046         cert_name = "AUTHOR_ROOT";
1047         break;
1048       case PACKAGE_INFO_AUTHOR_INTERMEDIATE_CERT:
1049         cert_name = "AUTHOR_INTERMEDIATE";
1050         break;
1051       case PACKAGE_INFO_AUTHOR_SIGNER_CERT:
1052         cert_name = "AUTHOR_SIGNER";
1053         break;
1054       case PACKAGE_INFO_DISTRIBUTOR_ROOT_CERT:
1055         cert_name = "DISTRIBUTOR_ROOT";
1056         break;
1057       case PACKAGE_INFO_DISTRIBUTOR_INTERMEDIATE_CERT:
1058         cert_name = "DISTRIBUTOR_INTERMEDIATE";
1059         break;
1060       case PACKAGE_INFO_DISTRIBUTOR_SIGNER_CERT:
1061         cert_name = "DISTRIBUTOR_SIGNER";
1062         break;
1063       case PACKAGE_INFO_DISTRIBUTOR2_ROOT_CERT:
1064         cert_name = "DISTRIBUTOR2_ROOT";
1065         break;
1066       case PACKAGE_INFO_DISTRIBUTOR2_INTERMEDIATE_CERT:
1067         cert_name = "DISTRIBUTOR2_INTERMEDIATE";
1068         break;
1069       case PACKAGE_INFO_DISTRIBUTOR2_SIGNER_CERT:
1070         cert_name = "DISTRIBUTOR2_SIGNER";
1071         break;
1072       default:
1073         LoggerD("Unknown certificate type: %d", cert_type);
1074         break;
1075     }
1076
1077     picojson::array* array = static_cast<picojson::array*>(user_data);
1078     array->push_back(picojson::value(picojson::object()));
1079
1080     ApplicationUtils::CreateApplicationCertificate(cert_name, cert_value,
1081                                                    &array->back().get<picojson::object>());
1082
1083     return true;
1084   };
1085
1086   picojson::value result = picojson::value(picojson::array());
1087
1088   ret = package_info_foreach_cert_info(pkg_info, cert_info_cb, &result.get<picojson::array>());
1089
1090   if ((PACKAGE_MANAGER_ERROR_NONE != ret) && (PACKAGE_MANAGER_ERROR_IO_ERROR != ret)) {
1091     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificates info."),
1092                       out,
1093                       ("Failed to get certificates info: %d (%s)", ret, get_error_message(ret)));
1094     return;
1095   }
1096
1097   ReportSuccess(result, *out);
1098 }
1099
1100 void ApplicationManager::GetAppSharedUri(const std::string& app_id, picojson::object* out) {
1101   ScopeLogger();
1102
1103   char* package_id = nullptr;
1104
1105   package_id = GetPackageId(app_id);
1106   // automatically release the memory
1107   std::unique_ptr<char, void (*)(void*)> package_id_ptr(package_id, &std::free);
1108
1109   if (!package_id) {
1110     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
1111     return;
1112   }
1113
1114   pkgmgrinfo_pkginfo_h pkg_info = nullptr;
1115
1116   int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(package_id, getuid(), &pkg_info);
1117   std::unique_ptr<std::remove_pointer<pkgmgrinfo_pkginfo_h>::type, int (*)(pkgmgrinfo_pkginfo_h)>
1118       pkg_info_ptr(pkg_info,
1119                    &pkgmgrinfo_pkginfo_destroy_pkginfo);  // automatically release the memory
1120
1121   if (PMINFO_R_OK != ret) {
1122     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out,
1123                       ("Failed to get package info: %d (%s)", ret, get_error_message(ret)));
1124     return;
1125   }
1126
1127   char* root_path = nullptr;
1128   ret = pkgmgrinfo_pkginfo_get_root_path(pkg_info, &root_path);
1129
1130   if (PMINFO_R_OK != ret || nullptr == root_path) {
1131     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get root path."), out,
1132                       ("Failed to get root path: %d (%s)", ret, get_error_message(ret)));
1133     return;
1134   }
1135
1136   picojson::value result = picojson::value(kTizenApisFileScheme + root_path + kTizenApisAppSlash +
1137                                            kTizenApisAppShared + kTizenApisAppSlash);
1138   ReportSuccess(result, *out);
1139 }
1140
1141 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1142 PlatformResult ApplicationManager::BatteryUsageFilter(const picojson::value& args,
1143                                                       const context_history_filter_h filter,
1144                                                       context_history_data_e* data_type_out) {
1145   ScopeLogger();
1146   int ret = CONTEXT_HISTORY_ERROR_NONE;
1147   int limit = kMaximumBatteryRetrievedObjects;
1148   if (args.contains("limit")) {
1149     limit = static_cast<int>(args.get("limit").get<double>());
1150   }
1151
1152   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1153
1154   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1155     return LogAndCreateResult(
1156         ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1157         ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1158   }
1159
1160   context_history_data_e data_type_in = CONTEXT_HISTORY_RECENT_BATTERY_USAGE;
1161
1162   if (args.contains("days")) {
1163     const int days = static_cast<int>(args.get("days").get<double>());
1164     data_type_in = CONTEXT_HISTORY_BATTERY_USAGE;
1165     ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, days);
1166
1167     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1168       return LogAndCreateResult(
1169           ErrorCode::INVALID_VALUES_ERR, "days given with invalid value.",
1170           ("days given with invalid value: %d (%s)", ret, get_error_message(ret)));
1171     }
1172   }
1173
1174   *data_type_out = data_type_in;
1175
1176   return PlatformResult(ErrorCode::NO_ERROR);
1177 }
1178
1179 PlatformResult ApplicationManager::BatteryUsageAttributes(const context_history_record_h record,
1180                                                           picojson::object* object) {
1181   ScopeLogger();
1182
1183   int ret = CONTEXT_HISTORY_ERROR_NONE;
1184   double amount = 0.0;
1185   char* app_id = nullptr;
1186   SCOPE_EXIT {
1187     free(app_id);
1188   };
1189
1190   ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1191   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1192     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1193                               ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1194   }
1195
1196   ret = context_history_record_get_double(record, CONTEXT_HISTORY_TOTAL_AMOUNT, &amount);
1197   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1198     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get amount.",
1199                               ("Failed to get amount: %d (%s)", ret, get_error_message(ret)));
1200   }
1201
1202   object->insert(std::make_pair("appId", picojson::value(app_id)));
1203   object->insert(std::make_pair("batteryUsage", picojson::value(amount)));
1204
1205   return PlatformResult(ErrorCode::NO_ERROR);
1206 }
1207
1208 PlatformResult ApplicationManager::AppsUsageFilter(const picojson::value& args,
1209                                                    const context_history_filter_h filter,
1210                                                    context_history_data_e* data_type_out) {
1211   ScopeLogger();
1212   int ret = CONTEXT_HISTORY_ERROR_NONE;
1213   int limit = kMaximumAppsRetrievedObjects;
1214   if (args.contains("limit")) {
1215     limit = static_cast<int>(args.get("limit").get<double>());
1216   }
1217
1218   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1219   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1220     return LogAndCreateResult(
1221         ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1222         ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1223   }
1224
1225   context_history_data_e data_type_in = CONTEXT_HISTORY_FREQUENTLY_USED_APP;
1226   if (args.contains("mode") && kAppUsageModeRecently == args.get("mode").get<std::string>()) {
1227     data_type_in = CONTEXT_HISTORY_RECENTLY_USED_APP;
1228   }
1229
1230   int time_span = kDefaultPeriodOfTime;
1231   const picojson::object& JS_filter = args.get("filter").get<picojson::object>();
1232   auto time_span_iter = JS_filter.find("timeSpan");
1233   if (JS_filter.end() != time_span_iter || (JS_filter.end() == JS_filter.find("startTime") &&
1234                                             JS_filter.end() == JS_filter.find("endTime"))) {
1235     // In the second case, we treat the filter object just like an empty object.
1236     // The default value of filter will be used instead.
1237     if (JS_filter.end() != time_span_iter) {
1238       time_span = static_cast<int>(time_span_iter->second.get<double>());
1239     }
1240     ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, time_span);
1241     // context_history_filter_set_int may return only success or
1242     // CONTEXT_HISTORY_ERROR_INVALID_PARAMETER
1243     // Although this should never happen, it's better to check ret's value
1244     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1245       return LogAndCreateResult(ErrorCode::ABORT_ERR,
1246                                 "Error while setting the default TIME_SPAN value.",
1247                                 ("Error while setting the default TIME_SPAN value: %d (%s)", ret,
1248                                  get_error_message(ret)));
1249     }
1250   } else {
1251     auto start_time_iter = JS_filter.find("startTime");
1252     auto end_time_iter = JS_filter.find("endTime");
1253     if (start_time_iter != JS_filter.end()) {
1254       int start_time = static_cast<int>(start_time_iter->second.get<double>());
1255       ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_START_TIME, start_time);
1256       if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1257         return LogAndCreateResult(
1258             ErrorCode::INVALID_VALUES_ERR, "startTime given with invalid value.",
1259             ("startTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1260       }
1261     }
1262     if (end_time_iter != JS_filter.end()) {
1263       int end_time = static_cast<int>(end_time_iter->second.get<double>());
1264       ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_END_TIME, end_time);
1265       if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1266         return LogAndCreateResult(
1267             ErrorCode::INVALID_VALUES_ERR, "endTime given with invalid value.",
1268             ("endTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1269       }
1270     }
1271   }
1272
1273   *data_type_out = data_type_in;
1274
1275   return PlatformResult(ErrorCode::NO_ERROR);
1276 }
1277
1278 PlatformResult ApplicationManager::AppsUsageAttributes(const context_history_record_h record,
1279                                                        picojson::object* object) {
1280   ScopeLogger();
1281
1282   int ret = CONTEXT_HISTORY_ERROR_NONE;
1283   int total_count = 0;
1284   int total_duration = 0;
1285   int last_time = 0;
1286   char* app_id = nullptr;
1287   SCOPE_EXIT {
1288     free(app_id);
1289   };
1290
1291   ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1292   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1293     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1294                               ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1295   }
1296
1297   ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_COUNT, &total_count);
1298   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1299     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get total count.",
1300                               ("Failed to get total count: %d (%s)", ret, get_error_message(ret)));
1301   }
1302
1303   ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_DURATION, &total_duration);
1304   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1305     return LogAndCreateResult(
1306         ErrorCode::ABORT_ERR, "Failed to get total duration.",
1307         ("Failed to get total duration: %d (%s)", ret, get_error_message(ret)));
1308   }
1309
1310   ret = context_history_record_get_int(record, CONTEXT_HISTORY_LAST_TIME, &last_time);
1311   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1312     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get last time.",
1313                               ("Failed to get last time: %d (%s)", ret, get_error_message(ret)));
1314   }
1315
1316   object->insert(std::make_pair("appId", picojson::value(app_id)));
1317   object->insert(std::make_pair("totalCount", picojson::value(static_cast<double>(total_count))));
1318   object->insert(
1319       std::make_pair("totalDuration", picojson::value(static_cast<double>(total_duration))));
1320   object->insert(std::make_pair("lastTime", picojson::value(static_cast<double>(last_time))));
1321
1322   return PlatformResult(ErrorCode::NO_ERROR);
1323 }
1324 #endif
1325
1326 void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojson::object* out) {
1327   ScopeLogger();
1328
1329 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1330   int callback_id = -1;
1331   const auto& callback = args.get(kCallbackId);
1332   if (callback.is<double>()) {
1333     callback_id = static_cast<int>(callback.get<double>());
1334   }
1335
1336   auto get_battery_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1337     ScopeLogger();
1338     PlatformResult result = ApplicationManager::GetContextHistory(
1339         args, &response.get()->get<picojson::object>(), &ApplicationManager::BatteryUsageFilter,
1340         &ApplicationManager::BatteryUsageAttributes);
1341     if (!result) {
1342       LogAndReportError(result, &response.get()->get<picojson::object>());
1343     }
1344   };
1345
1346   auto get_battery_usage_response =
1347       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1348     ScopeLogger();
1349     picojson::object& obj = response->get<picojson::object>();
1350     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1351     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1352   };
1353
1354   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1355
1356   TaskQueue::GetInstance().Queue<picojson::value>(get_battery_usage, get_battery_usage_response,
1357                                                   data);
1358 #else
1359   // 20170510 Context API is supported only for mobile profile, other ones would result with
1360   // NotSupportedError
1361   LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
1362                                    "This feature is not supported on this profile."),
1363                     out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1364 #endif
1365 }
1366
1367 void ApplicationManager::GetAppsUsageInfo(const picojson::value& args, picojson::object* out) {
1368   ScopeLogger();
1369
1370 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1371   int callback_id = static_cast<int>(args.get(kCallbackId).get<double>());
1372
1373   auto get_apps_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1374     ScopeLogger();
1375     PlatformResult result = ApplicationManager::GetContextHistory(
1376         args, &response.get()->get<picojson::object>(), &ApplicationManager::AppsUsageFilter,
1377         &ApplicationManager::AppsUsageAttributes);
1378     if (!result) {
1379       LogAndReportError(result, &response.get()->get<picojson::object>());
1380     }
1381   };
1382
1383   auto get_apps_usage_response =
1384       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1385     ScopeLogger();
1386     picojson::object& obj = response->get<picojson::object>();
1387     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1388     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1389   };
1390
1391   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1392
1393   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_usage, get_apps_usage_response, data);
1394 #else
1395   // Context API is supported only for mobile profile, other ones would result with
1396   // NotSupportedError
1397   LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
1398                                    "This feature is not supported on this profile."),
1399                     out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1400 #endif
1401 }
1402
1403 void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) {
1404   ScopeLogger();
1405
1406   pkgmgrinfo_appinfo_h handle = nullptr;
1407
1408   int ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle);
1409   std::unique_ptr<std::remove_pointer<pkgmgrinfo_appinfo_h>::type, int (*)(pkgmgrinfo_appinfo_h)>
1410       pkg_info_ptr(handle,
1411                    &pkgmgrinfo_appinfo_destroy_appinfo);  // automatically release the memory
1412
1413   if (PMINFO_R_OK != ret) {
1414     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out,
1415                       ("Failed to get app info: %d (%s)", ret, get_error_message(ret)));
1416     return;
1417   }
1418
1419   auto meta_data_cb = [](const char* meta_key, const char* meta_value, void* user_data) -> int {
1420     if (nullptr == meta_key || nullptr == meta_value) {
1421       LoggerE("meta_key or meta_value is null");
1422       return 0;
1423     }
1424
1425     picojson::array* array = static_cast<picojson::array*>(user_data);
1426     array->push_back(picojson::value(picojson::object()));
1427
1428     ApplicationUtils::CreateApplicationMetaData(meta_key, meta_value,
1429                                                 &array->back().get<picojson::object>());
1430     return 0;
1431   };
1432
1433   picojson::value result = picojson::value(picojson::array());
1434   ret = pkgmgrinfo_appinfo_foreach_metadata(handle, meta_data_cb, &result.get<picojson::array>());
1435
1436   if (PMINFO_R_OK != ret) {
1437     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get metadata."), out,
1438                       ("Failed to get metadata: %d (%s)", ret, get_error_message(ret)));
1439     return;
1440   }
1441
1442   ReportSuccess(result, *out);
1443 }
1444
1445 class ApplicationListChangedBroker {
1446  public:
1447   ApplicationListChangedBroker() : event_type_() {
1448   }
1449   enum class Event {
1450     kInstalled,
1451     kUpdated,
1452     kUninstalled,
1453   };
1454
1455   static int ClientStatusListener(unsigned int target_uid, int id, const char* type,
1456                                   const char* package, const char* key, const char* val,
1457                                   const void* msg, void* data) {
1458     ScopeLogger();
1459     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1460
1461     if (0 == strcasecmp(key, kStartKey)) {
1462       that->HandleStart(val, package);
1463     } else if (0 == strcasecmp(key, kEndKey) && 0 == strcasecmp(val, kOkValue)) {
1464       that->HandleEnd(package);
1465     } else {
1466       LoggerD("Ignored key: %s", key);
1467     }
1468
1469     return 0;
1470   }
1471
1472   static int AppUninstallListener(uid_t target_uid, int id, const char* type, const char* package,
1473                                   const char* key, const char* val, const void* msg, void* data) {
1474     ScopeLogger();
1475
1476     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1477
1478     if (0 == strcasecmp(key, kStartKey)) {
1479       that->HandleUninstallStart();
1480     } else if (0 == strcasecmp(key, kAppidKey)) {
1481       that->AddUninstalledAppId(val);
1482     } else if (0 == strcasecmp(key, kEndKey)) {
1483       that->HandleUninstallEnd();
1484     } else {
1485       LoggerD("Ignored key: %s", key);
1486     }
1487
1488     return 0;
1489   }
1490
1491   void AddApplicationInstance(ApplicationInstance* app_instance) {
1492     ScopeLogger();
1493     app_instance_list_.push_back(app_instance);
1494   }
1495
1496   void RemoveApplicationInstance(ApplicationInstance* app_instance) {
1497     ScopeLogger();
1498     for (auto it = app_instance_list_.begin(); it != app_instance_list_.end(); it++) {
1499       if (*it == app_instance) {
1500         app_instance_list_.erase(it);
1501         return;
1502       }
1503     }
1504   }
1505
1506  private:
1507   void HandleStart(const char* event_type, const char* package) {
1508     ScopeLogger();
1509     app_list_.clear();
1510     set_event_type(event_type);
1511   }
1512
1513   void HandleEnd(const char* package) {
1514     ScopeLogger();
1515
1516     if (Event::kUninstalled == event_type_) {
1517       return;
1518     }
1519
1520     GetApplicationIdsFromPackage(package);
1521
1522     for (auto& app_id : app_list_) {
1523       picojson::value value = picojson::value(picojson::object());
1524       picojson::object& data_obj = value.get<picojson::object>();
1525
1526       switch (event_type_) {
1527         case Event::kInstalled:
1528           data_obj.insert(std::make_pair(kAction, picojson::value(kOnInstalled)));
1529           break;
1530
1531         case Event::kUpdated:
1532           data_obj.insert(std::make_pair(kAction, picojson::value(kOnUpdated)));
1533           break;
1534         case Event::kUninstalled:
1535           LoggerD("Uninstalled called");
1536           break;
1537       }
1538
1539       switch (event_type_) {
1540         case Event::kInstalled:
1541         case Event::kUpdated: {
1542           pkgmgrinfo_appinfo_h handle = nullptr;
1543           if (PMINFO_R_OK !=
1544               pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1545             LoggerE("Failed to get application information handle.");
1546             continue;
1547           }
1548           auto info = data_obj.insert(std::make_pair(kData, picojson::value(picojson::object())));
1549           ApplicationUtils::CreateApplicationInformation(
1550               handle, &info.first->second.get<picojson::object>());
1551           pkgmgrinfo_appinfo_destroy_appinfo(handle);
1552         } break;
1553         case Event::kUninstalled:
1554           LoggerD("Uninstalled called");
1555           break;
1556       }
1557
1558       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1559
1560       for (auto instance : app_instance_list_) {
1561         Instance::PostMessage(instance, value.serialize().c_str());
1562       }
1563     }
1564   }
1565
1566   void GetApplicationIdsFromPackage(const char* package) {
1567     ScopeLogger();
1568     package_info_h package_info = nullptr;
1569
1570     int ret = package_info_create(package, &package_info);
1571     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1572       LoggerE("Failed to create package info: %d (%s)", ret, get_error_message(ret));
1573       return;
1574     }
1575
1576     ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_ALLAPP,
1577                                                 ApplicationIdCallback, this);
1578     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1579       LoggerE("Failed to get application IDs: %d (%s)", ret, get_error_message(ret));
1580     }
1581
1582     ret = package_info_destroy(package_info);
1583     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1584       LoggerE("Failed to destroy package info: %d (%s)", ret, get_error_message(ret));
1585     }
1586   }
1587
1588   void set_event_type(const char* type) {
1589     ScopeLogger();
1590     if (0 == strcasecmp(type, kInstallEvent)) {
1591       event_type_ = Event::kInstalled;
1592     } else if (0 == strcasecmp(type, kUpdateEvent)) {
1593       event_type_ = Event::kUpdated;
1594     } else if (0 == strcasecmp(type, kUninstallEvent)) {
1595       event_type_ = Event::kUninstalled;
1596     }
1597   }
1598
1599   static bool ApplicationIdCallback(package_info_app_component_type_e comp_type, const char* app_id,
1600                                     void* user_data) {
1601     ScopeLogger();
1602     if (nullptr != app_id) {
1603       static_cast<ApplicationListChangedBroker*>(user_data)->app_list_.push_back(app_id);
1604     }
1605     return true;
1606   }
1607
1608   void HandleUninstallStart() {
1609     ScopeLogger();
1610     app_list_.clear();
1611     set_event_type(kUninstallEvent);
1612   }
1613
1614   void AddUninstalledAppId(const char* app_id) {
1615     ScopeLogger();
1616     if (nullptr != app_id) {
1617       app_list_.push_back(app_id);
1618     }
1619   }
1620
1621   void HandleUninstallEnd() {
1622     ScopeLogger();
1623     for (auto& app_id : app_list_) {
1624       picojson::value value = picojson::value(picojson::object());
1625       picojson::object& data_obj = value.get<picojson::object>();
1626
1627       data_obj.insert(std::make_pair(kAction, picojson::value(kOnUninstalled)));
1628       data_obj.insert(std::make_pair(kData, picojson::value(app_id)));
1629
1630       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1631
1632       for (auto instance : app_instance_list_) {
1633         Instance::PostMessage(instance, value.serialize().c_str());
1634       }
1635     }
1636   }
1637
1638   Event event_type_;
1639   std::vector<std::string> app_list_;
1640   std::vector<ApplicationInstance*> app_instance_list_;
1641 };
1642
1643 static ApplicationListChangedBroker g_application_list_changed_broker;
1644
1645 void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
1646   ScopeLogger();
1647
1648   if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgr_client_uninstall_handle_) {
1649     if (nullptr == pkgmgr_client_handle_) {
1650       pkgmgr_client_handle_ = pkgmgr_client_new(PC_LISTENING);
1651     }
1652     if (nullptr == pkgmgr_client_uninstall_handle_) {
1653       pkgmgr_client_uninstall_handle_ = pkgmgr_client_new(PC_LISTENING);
1654     }
1655
1656     if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgr_client_uninstall_handle_) {
1657       if (nullptr != pkgmgr_client_handle_) {
1658         pkgmgr_client_free(pkgmgr_client_handle_);
1659         pkgmgr_client_handle_ = nullptr;
1660       }
1661       if (nullptr != pkgmgr_client_uninstall_handle_) {
1662         pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1663         pkgmgr_client_uninstall_handle_ = nullptr;
1664       }
1665       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."),
1666                         out);
1667       return;
1668     }
1669
1670     g_application_list_changed_broker.AddApplicationInstance(&instance_);
1671
1672     pkgmgr_client_set_status_type(pkgmgr_client_handle_, PACKAGE_MANAGER_STATUS_TYPE_INSTALL |
1673                                                              PACKAGE_MANAGER_STATUS_TYPE_UPGRADE);
1674     pkgmgr_client_set_status_type(pkgmgr_client_uninstall_handle_,
1675                                   PACKAGE_MANAGER_STATUS_TYPE_UNINSTALL);
1676
1677     pkgmgr_client_listen_status(pkgmgr_client_handle_,
1678                                 ApplicationListChangedBroker::ClientStatusListener,
1679                                 &g_application_list_changed_broker);
1680     pkgmgr_client_listen_status(pkgmgr_client_uninstall_handle_,
1681                                 ApplicationListChangedBroker::AppUninstallListener,
1682                                 &g_application_list_changed_broker);
1683
1684   } else {
1685     LoggerD("Broker callback is already registered.");
1686   }
1687
1688   ReportSuccess(*out);
1689 }
1690
1691 void ApplicationManager::StopAppInfoEventListener() {
1692   ScopeLogger();
1693
1694   if (nullptr != pkgmgr_client_handle_ || nullptr != pkgmgr_client_uninstall_handle_) {
1695     if (nullptr != pkgmgr_client_handle_) {
1696       pkgmgr_client_free(pkgmgr_client_handle_);
1697       pkgmgr_client_handle_ = nullptr;
1698     }
1699     if (nullptr != pkgmgr_client_uninstall_handle_) {
1700       pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1701       pkgmgr_client_uninstall_handle_ = nullptr;
1702     }
1703     g_application_list_changed_broker.RemoveApplicationInstance(&instance_);
1704   } else {
1705     LoggerD("Broker callback is already unregistered.");
1706   }
1707 }
1708
1709 void ApplicationManager::GetApplicationInformationSize(const picojson::value& args,
1710                                                        picojson::object* out) {
1711   ScopeLogger();
1712
1713   const auto& package_id = args.get("packageId");
1714   if (!package_id.is<std::string>()) {
1715     LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
1716                       out);
1717     return;
1718   }
1719
1720   const std::string& package_id_str = package_id.get<std::string>();
1721
1722   // get installed size from package server (to solve smack issue)
1723   pkgmgr_client* pc = pkgmgr_client_new(PC_REQUEST);
1724   int size = -1;
1725
1726   if (nullptr == pc) {
1727     LoggerE("Failed to create pkgmgr client");
1728   } else {
1729     size = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_TOTAL_SIZE, pc, NULL,
1730                                          package_id_str.c_str(), NULL, NULL, NULL);
1731
1732     if (size < 0) {
1733       LoggerE("Failed to get installed size: %d (%s)", size, get_error_message(size));
1734     }
1735
1736     pkgmgr_client_free(pc);
1737   }
1738
1739   picojson::value result = picojson::value(picojson::object());
1740   picojson::object& result_obj = result.get<picojson::object>();
1741   result_obj.insert(std::make_pair("size", picojson::value(static_cast<double>(size))));
1742
1743   ReportSuccess(result, *out);
1744 }
1745
1746 void ApplicationManager::BroadcastEventHelper(const picojson::value& args, picojson::object& out,
1747                                               bool trusted) {
1748   ScopeLogger();
1749
1750   int ret;
1751   std::string event_str = args.get("name").get<std::string>();
1752   const char* event_name = event_str.c_str();
1753
1754   bundle* data = bundle_create();
1755   SCOPE_EXIT {
1756     bundle_free(data);
1757   };
1758
1759   ret = bundle_add(data, "data", args.get("data").serialize().c_str());
1760
1761   if (ret != EVENT_ERROR_NONE) {
1762     LoggerE("bundle_add failed, error: %d (%s)", ret, get_error_message(ret));
1763     ReportError(out);
1764     return;
1765   }
1766
1767   if (trusted) {
1768     ret = event_publish_trusted_app_event(event_name, data);
1769   } else {
1770     ret = event_publish_app_event(event_name, data);
1771   }
1772
1773   if (ret == EVENT_ERROR_NONE) {
1774     ReportSuccess(out);
1775   } else {
1776     LoggerE("event_publish_app_event failed, error: %d (%s)", ret, get_error_message(ret));
1777     ReportError(out);
1778   }
1779 }
1780
1781 void ApplicationManager::OnEvent(const char* event_name, bundle* event_data, void* user_data) {
1782   ScopeLogger("Event name is: '%s'", event_name);
1783
1784   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1785
1786   if (!manager->event_callback_) {
1787     LoggerD("No event listener registered, skipping.");
1788     return;
1789   }
1790
1791   picojson::value event = picojson::value(picojson::object());
1792   picojson::object& event_o = event.get<picojson::object>();
1793
1794   int ret;
1795   char* val = nullptr;
1796
1797   if (event_map_.count(event_name)) {  // system event
1798     const std::string& key = event_map_.at(event_name);
1799     std::string state = "true";
1800     if (key != "") {
1801       ret = bundle_get_str(event_data, key.c_str(), &val);
1802       if (EVENT_ERROR_NONE != ret) {
1803         LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1804         return;
1805       }
1806
1807       state = std::string(val);
1808     }
1809
1810     LoggerD("State is %s", state.c_str());
1811     event_o["value"] = picojson::value(state);
1812
1813   } else {  // user event
1814     ret = bundle_get_str(event_data, "data", &val);
1815     if (EVENT_ERROR_NONE != ret) {
1816       LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1817       return;
1818     }
1819
1820     picojson::value data;
1821     std::string err;
1822     picojson::parse(data, val, val + strlen(val), &err);
1823     if (!err.empty()) {
1824       LoggerE("Failed to parse bundle data: %s", err.c_str());
1825       return;
1826     }
1827
1828     event_o["data"] = data;
1829   }
1830
1831   LoggerD("event_name is: %s", event_name);
1832   event_o["name"] = picojson::value(event_name);
1833
1834   manager->event_callback_(&event);
1835 }
1836
1837 PlatformResult ApplicationManager::StartEventListener(const std::string& event_name,
1838                                                       const JsonCallback& callback) {
1839   ScopeLogger();
1840
1841   int ret;
1842   event_handler_h event_handler;
1843
1844   ret = event_add_event_handler(event_name.c_str(), OnEvent, this, &event_handler);
1845   LoggerD("event_add_event_handler() result: %d (%s)", ret, get_error_message(ret));
1846   if (EVENT_ERROR_PERMISSION_DENIED == ret) {
1847     return LogAndCreateResult(ErrorCode::SECURITY_ERR, "The privilege is required",
1848                               ("event_add_event_handler failed, error: %d", ret));
1849   } else if (EVENT_ERROR_NONE != ret) {
1850     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error setting event listener",
1851                               ("event_add_event_handler failed, error: %d", ret));
1852   }
1853
1854   event_handler_map_[event_name] = event_handler;
1855
1856   event_callback_ = callback;
1857   LoggerD("event_add_event_handler success");
1858   return PlatformResult(ErrorCode::NO_ERROR);
1859 }
1860
1861 void ApplicationManager::StopEventListener(const std::string& event_name) {
1862   ScopeLogger();
1863
1864   int ret;
1865   event_handler_h event_handler;
1866
1867   if (event_handler_map_.find(event_name) != event_handler_map_.end()) {
1868     event_handler = event_handler_map_[event_name];
1869
1870     ret = event_remove_event_handler(event_handler);
1871     if (EVENT_ERROR_NONE != ret) {
1872       LoggerE("event_remove_event_handler failed, error: %d (%s)", ret, get_error_message(ret));
1873       return;
1874     }
1875
1876     event_handler_map_.erase(event_name);
1877   }
1878 }
1879
1880 void ApplicationManager::OnStatusEvent(const char* type, const char* app_id,
1881                                        app_manager_event_type_e event_type,
1882                                        app_manager_event_state_e event_state,
1883                                        app_manager_event_h handle, void* user_data) {
1884   ScopeLogger();
1885
1886   if (APP_MANAGER_EVENT_STATE_COMPLETED != event_state) {
1887     LoggerD("State different from completed");
1888     return;
1889   }
1890
1891   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1892
1893   if (!manager || !manager->status_callback_) {
1894     LoggerD("No event listener registered, skipping.");
1895     return;
1896   }
1897
1898   bool status_type;
1899   switch (event_type) {
1900     case APP_MANAGER_EVENT_ENABLE_APP:
1901       status_type = true;
1902       break;
1903     case APP_MANAGER_EVENT_DISABLE_APP:
1904       status_type = false;
1905       break;
1906     default:
1907       LoggerD("Uknown status type skipping.");
1908       return;
1909   }
1910
1911   picojson::value event = picojson::value(picojson::object());
1912   picojson::object& event_o = event.get<picojson::object>();
1913
1914   event_o[kStatusType] = picojson::value(status_type);
1915   event_o[kAppId] = picojson::value(app_id);
1916   event_o[kListenerId] = picojson::value(kAppStatusChangeListener);
1917
1918   manager->status_callback_(&event);
1919 }
1920
1921 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1922 PlatformResult ApplicationManager::GetContextHistory(
1923     const picojson::value& args, picojson::object* out,
1924     common::PlatformResult (*modify_filter_cb)(const picojson::value&,
1925                                                const context_history_filter_h,
1926                                                context_history_data_e* data_type),
1927     common::PlatformResult (*add_attributes_to_object)(const context_history_record_h,
1928                                                        picojson::object*)) {
1929   ScopeLogger();
1930   context_history_list_h list = nullptr;
1931   context_history_h handle = nullptr;
1932   context_history_filter_h filter = nullptr;
1933
1934   SCOPE_EXIT {
1935     context_history_list_destroy(list);
1936     context_history_destroy(handle);
1937     context_history_filter_destroy(filter);
1938   };
1939
1940   int ret = context_history_create(&handle);
1941   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1942     return LogAndCreateResult(
1943         ErrorCode::ABORT_ERR, "Failed to create context handle.",
1944         ("Failed to create context handle: %d (%s)", ret, get_error_message(ret)));
1945   }
1946
1947   ret = context_history_filter_create(&filter);
1948   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1949     return LogAndCreateResult(
1950         ErrorCode::ABORT_ERR, "Failed to create filter handle.",
1951         ("Failed to create filter handle: %d (%s)", ret, get_error_message(ret)));
1952   }
1953
1954   context_history_data_e data_type;
1955
1956   PlatformResult result = modify_filter_cb(args, filter, &data_type);
1957   if (!result) {
1958     return result;
1959   }
1960
1961   picojson::value result_array = picojson::value(picojson::array());
1962   picojson::array& array_obj = result_array.get<picojson::array>();
1963
1964   ret = context_history_get_list(handle, data_type, filter, &list);
1965   if (CONTEXT_HISTORY_ERROR_NO_DATA == ret) {
1966     ReportSuccess(result_array, *out);
1967     return PlatformResult(ErrorCode::NO_ERROR);
1968   } else if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1969     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list.",
1970                               ("Failed to get list: %d (%s)", ret, get_error_message(ret)));
1971   }
1972
1973   int size = 0;
1974   ret = context_history_list_get_count(list, &size);
1975   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1976     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list size.",
1977                               ("Failed to get list size: %d (%s)", ret, get_error_message(ret)));
1978   }
1979
1980   array_obj.resize(size, picojson::value(picojson::object()));
1981
1982   for (int i = 0; i < size; ++i) {
1983     context_history_record_h record = nullptr;
1984     SCOPE_EXIT {
1985       context_history_record_destroy(record);
1986     };
1987
1988     ret = context_history_list_get_current(list, &record);
1989     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1990       return LogAndCreateResult(
1991           ErrorCode::ABORT_ERR, "Failed to get current record.",
1992           ("Failed to get current record: %d (%s)", ret, get_error_message(ret)));
1993     }
1994
1995     result = add_attributes_to_object(record, &array_obj[i].get<picojson::object>());
1996     if (!result) {
1997       return result;
1998     }
1999
2000     ret = context_history_list_move_next(list);
2001     if (CONTEXT_HISTORY_ERROR_NONE != ret && CONTEXT_HISTORY_ERROR_NO_DATA != ret) {
2002       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to move iterator.",
2003                                 ("Failed to move iterator: %d (%s)", ret, get_error_message(ret)));
2004     }
2005   }
2006
2007   ReportSuccess(result_array, *out);
2008   return PlatformResult(ErrorCode::NO_ERROR);
2009 }
2010 #endif
2011
2012 PlatformResult ApplicationManager::StartStatusListener(const JsonCallback& callback) {
2013   ScopeLogger();
2014
2015   int ret = APP_MANAGER_ERROR_NONE;
2016
2017   if (!app_status_handle_) {
2018     ret = app_manager_event_create(&app_status_handle_);
2019     if (APP_MANAGER_ERROR_NONE != ret) {
2020       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while creating event handle",
2021                                 ("app_manager_event_create failed, error: %d", ret));
2022     }
2023
2024     ret = app_manager_event_set_status(app_status_handle_, APP_MANAGER_EVENT_STATUS_TYPE_ALL);
2025     if (APP_MANAGER_ERROR_NONE != ret) {
2026       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status type",
2027                                 ("app_manager_event_set_status failed, error: %d", ret));
2028     }
2029   }
2030
2031   status_callback_ = callback;
2032   ret = app_manager_set_event_cb(app_status_handle_, OnStatusEvent, this);
2033   if (APP_MANAGER_ERROR_NONE != ret) {
2034     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status listener",
2035                               ("app_manager_set_event_cb failed, error: %d", ret));
2036   }
2037
2038   return PlatformResult(ErrorCode::NO_ERROR);
2039 }
2040
2041 PlatformResult ApplicationManager::StopStatusChangeListener() {
2042   ScopeLogger();
2043
2044   if (app_status_handle_) {
2045     int ret = app_manager_unset_event_cb(app_status_handle_);
2046     if (APP_MANAGER_ERROR_NONE != ret) {
2047       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while removing status listener",
2048                                 ("app_manager_unset_event_cb failed, error: %d", ret));
2049     }
2050   }
2051
2052   return PlatformResult(ErrorCode::NO_ERROR);
2053 }
2054
2055 }  // namespace application
2056 }  // namespace extension