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