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