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