Merge "[Calendar] Enable calendar module in wearable profile" 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 <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       ret = app_control_send_launch_request(app_control_ptr.get(), callback, user_data);
623
624       if (APP_CONTROL_ERROR_NONE == ret) {
625         break;
626       }
627
628       // delay 300ms for each retry
629       struct timespec sleep_time = { 0, 300L * 1000L * 1000L };
630       nanosleep(&sleep_time, nullptr);
631       ++retry;
632
633       LoggerD("Retry launch request: %d", 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
664     ReportSuccess(response->get<picojson::object>());
665   };
666
667   auto launch_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
668     Instance::PostMessage(&this->instance_, response->serialize().c_str());
669   };
670
671   TaskQueue::GetInstance().Queue<picojson::value>(launch, launch_response, response);
672 }
673
674 //internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
675 //public CAPI did not handling APP_CONTROL_ERROR_APP_NOT_FOUND
676 int app_control_foreach_app_matched_internal(app_control_h app_control, app_control_app_matched_cb callback, void* user_data){
677   typedef struct {
678     app_control_h app_control;
679     app_control_app_matched_cb callback;
680     void *user_data;
681     bool foreach_break;
682    } foreach_context_launchable_app_t_internal;
683
684   //internal impl of app_control_cb_broker_foreach_app_matched()
685   auto app_control_cb_broker_foreach_app_matched_internal = [](const char *package, void *data) -> int {
686     foreach_context_launchable_app_t_internal *foreach_context;
687     app_control_app_matched_cb app_matched_cb;
688
689     if (package == NULL || data == NULL) {
690       LoggerE("APP_CONTROL_ERROR_INVALID_PARAMETER");
691       return -1;
692     }
693
694     foreach_context = (foreach_context_launchable_app_t_internal *)data;
695     if (foreach_context->foreach_break == true)
696       return -1;
697
698     app_matched_cb = foreach_context->callback;
699     if (app_matched_cb != NULL) {
700       bool stop_foreach = false;
701
702       stop_foreach = !app_matched_cb(foreach_context->app_control, package, foreach_context->user_data);
703
704       foreach_context->foreach_break = stop_foreach;
705     }
706
707     return 0;
708   };
709
710   foreach_context_launchable_app_t_internal foreach_context = {
711     .app_control = app_control,
712     .callback = callback,
713     .user_data = user_data,
714     .foreach_break = false
715   };
716
717   bundle *bundle_data = NULL;
718   app_control_to_bundle(app_control, &bundle_data);
719
720   int ret = appsvc_usr_get_list(bundle_data, app_control_cb_broker_foreach_app_matched_internal, &foreach_context, getuid());
721
722   if (ret < 0 ){
723     switch (ret){
724       case APPSVC_RET_EINVAL:
725         return APP_CONTROL_ERROR_INVALID_PARAMETER;
726
727       case APPSVC_RET_ENOMATCH:
728         return APP_CONTROL_ERROR_APP_NOT_FOUND;
729
730       default:
731         return APP_CONTROL_ERROR_LAUNCH_FAILED;
732      }
733   }
734
735   return APP_CONTROL_ERROR_NONE;
736 }
737
738
739 void ApplicationManager::FindAppControl(const picojson::value& args) {
740   LoggerD("Entered");
741
742   int callback_id = -1;
743   const auto& callback = args.get(kCallbackId);
744   if (callback.is<double>()) {
745     callback_id = static_cast<int>(callback.get<double>());
746   }
747
748   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
749   picojson::object& response_obj = response->get<picojson::object>();
750   response_obj.insert(
751       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
752
753   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
754   const auto& control = args.get("appControl");
755   if (!control.is<picojson::object>()) {
756     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
757     AsyncResponse(result, &response);
758     return;
759   }
760
761   const picojson::object& app_control_obj = control.get<picojson::object>();
762
763   app_control_h app_control = nullptr;
764   result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
765   std::shared_ptr<std::remove_pointer<app_control_h>::type>
766   app_control_ptr(app_control, &app_control_destroy); // automatically release the memory
767
768   if (result.IsError()) {
769     LoggerE("Application control to service failed.");
770     AsyncResponse(result, &response);
771     return;
772   }
773
774   auto find = [app_control_ptr](const std::shared_ptr<picojson::value>& response) -> void {
775     auto app_control_matched = [](app_control_h app_control, const char* appid, void* user_data) -> bool {
776       if (nullptr == appid) {
777         LoggerD("appid is NULL");
778         return false;
779       }
780
781       pkgmgrinfo_appinfo_h handle;
782       int ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, getuid(), &handle);
783       if (PMINFO_R_OK != ret) {
784         LoggerE("Failed to get appInfo: %d (%s)", ret, get_error_message(ret));
785       } else {
786         picojson::array* array = static_cast<picojson::array*>(user_data);
787         array->push_back(picojson::value(picojson::object()));
788
789         ApplicationUtils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
790         pkgmgrinfo_appinfo_destroy_appinfo(handle);
791       }
792
793       return true;
794     };
795
796     picojson::object& response_obj = response->get<picojson::object>();
797     auto it_result = response_obj.find("result");
798     picojson::object& result_obj = it_result->second.get<picojson::object>();
799     auto array = result_obj.insert(
800         std::make_pair("informationArray", picojson::value(picojson::array())));
801
802     int ret = app_control_foreach_app_matched_internal(
803         app_control_ptr.get(), app_control_matched, &array.first->second.get<picojson::array>());
804
805     if (APP_CONTROL_ERROR_NONE != ret) {
806       if(APP_CONTROL_ERROR_APP_NOT_FOUND == ret){
807         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR,"Matched Application not found"), &response_obj,
808                         ("app_control_foreach_app_matched error: %d (%s)", ret, get_error_message(ret)));
809       }else if(APP_CONTROL_ERROR_LAUNCH_FAILED == ret){
810         LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,"Unknown error"), &response_obj,
811                         ("app_control_foreach_app_matched error: %d (%s)", ret, get_error_message(ret)));
812       }else if(APP_CONTROL_ERROR_INVALID_PARAMETER == ret){
813         LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR,"Invalid parameter passed"), &response_obj,
814                         ("app_control_foreach_app_matched error: %d (%s)", ret, get_error_message(ret)));
815       }
816       // remove copied ApplicationControl from result
817       response_obj.erase(it_result);
818     } else {
819       ReportSuccess(response_obj);
820     }
821   };
822
823   auto find_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
824     Instance::PostMessage(&this->instance_, response->serialize().c_str());
825   };
826
827   // prepare result object, we need to do that here, as input parameter is passed to result callback
828   auto ret = response_obj.insert(std::make_pair("result", picojson::value(picojson::object())));
829   // reinsert application control
830   ret.first->second.get<picojson::object>().insert(std::make_pair("appControl", args.get("appControl")));
831
832   TaskQueue::GetInstance().Queue<picojson::value>(find, find_response, response);
833 }
834
835 void ApplicationManager::GetAppsContext(const picojson::value& args) {
836   LoggerD("Entered");
837
838   int callback_id = -1;
839   const auto& callback = args.get(kCallbackId);
840   if (callback.is<double>()) {
841     callback_id = static_cast<int>(callback.get<double>());
842   }
843
844   auto get_apps_context = [](const std::shared_ptr<picojson::value>& response) -> void {
845     picojson::object& response_obj = response->get<picojson::object>();
846     picojson::value result = picojson::value(picojson::object());
847     picojson::object& result_obj = result.get<picojson::object>();
848     picojson::array& array =
849         result_obj.insert(std::make_pair("contexts", picojson::value(
850             picojson::array()))).first->second.get<picojson::array>();
851
852     auto app_context_cb = [](app_context_h app_context, void* user_data) -> bool {
853       if (nullptr == user_data) {
854         return false;
855       }
856
857       picojson::array* array = static_cast<picojson::array*>(user_data);
858       array->push_back(picojson::value(picojson::object()));
859
860       if (!ApplicationUtils::CreateApplicationContext(
861           app_context, &array->back().get<picojson::object>())) {
862         array->pop_back();
863         return false;
864       }
865
866       return true;
867     };
868
869     int ret = app_manager_foreach_app_context(app_context_cb, &array);
870
871     if (APP_MANAGER_ERROR_NONE != ret) {
872       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
873                         ("app_manager_foreach_app_context error: %d (%s)", ret, get_error_message(ret)));
874     } else {
875       ReportSuccess(result, response_obj);
876     }
877   };
878
879   auto get_apps_context_response = [this, callback_id](
880       const std::shared_ptr<picojson::value>& response) -> void {
881     picojson::object& obj = response->get<picojson::object>();
882     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
883     Instance::PostMessage(&this->instance_, response->serialize().c_str());
884   };
885
886   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
887
888   TaskQueue::GetInstance().Queue<picojson::value>(
889       get_apps_context,
890       get_apps_context_response,
891       data);
892 }
893
894 void ApplicationManager::GetAppContext(const picojson::value& args, picojson::object* out) {
895   LoggerD("Entered");
896   pid_t pid = 0;
897
898   const auto& context_id = args.get("contextId");
899   if (context_id.is<std::string>()) {
900     try {
901       pid = std::stoi(context_id.get<std::string>());
902     } catch(...) {
903       LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert context id."), out);
904       return;
905     }
906   } else {
907     pid = CurrentApplication::GetInstance().GetProcessId();
908   }
909
910   char* app_id = nullptr;
911
912   int ret = app_manager_get_app_id(pid, &app_id);
913   // automatically release the memory
914   std::unique_ptr<char, void(*)(void*)> app_id_ptr(app_id, &std::free);
915
916   if (APP_MANAGER_ERROR_NONE != ret || nullptr == app_id) {
917     switch(ret) {
918       case APP_MANAGER_ERROR_NO_SUCH_APP:
919         LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "No such application exist."), out,
920                     ("app_manager_get_app_id returned: APP_MANAGER_ERROR_NO_SUCH_APP"));
921         return;
922
923       case APP_MANAGER_ERROR_INVALID_PARAMETER:
924         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Application not found."), out,
925                     ("app_manager_get_app_id returned: APP_MANAGER_ERROR_INVALID_PARAMETER"));
926         return;
927
928       default:
929         LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), out,
930                           ("app_manager_get_app_id returned: %d (%s)", ret, get_error_message(ret)));
931         return;
932     }
933   }
934
935   picojson::value result = picojson::value(picojson::object());
936   ApplicationUtils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
937
938   ReportSuccess(result, *out);
939 }
940
941 void ApplicationManager::GetAppsInfo(const picojson::value& args) {
942   LoggerD("Entered");
943
944   int callback_id = -1;
945   const auto& callback = args.get(kCallbackId);
946   if (callback.is<double>()) {
947     callback_id = static_cast<int>(callback.get<double>());
948   }
949
950   auto get_apps_info = [](const std::shared_ptr<picojson::value>& response) -> void {
951     picojson::object& response_obj = response->get<picojson::object>();
952     picojson::value result = picojson::value(picojson::object());
953     picojson::object& result_obj = result.get<picojson::object>();
954     picojson::array& array =
955         result_obj.insert(std::make_pair("informationArray", picojson::value(
956             picojson::array()))).first->second.get<picojson::array>();
957
958     auto app_info_cb = [](pkgmgrinfo_appinfo_h handle, void* user_data) -> int {
959       if (nullptr == user_data) {
960         return -1;
961       }
962
963       picojson::array* array = static_cast<picojson::array*>(user_data);
964       array->push_back(picojson::value(picojson::object()));
965
966       ApplicationUtils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
967
968       return 0;
969     };
970
971     int ret = pkgmgrinfo_appinfo_get_usr_installed_list(app_info_cb, getuid(), &array);
972
973     if (APP_MANAGER_ERROR_NONE != ret) {
974       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
975                         ("pkgmgrinfo_appinfo_get_usr_installed_list error"));
976     } else {
977       ReportSuccess(result, response_obj);
978     }
979   };
980
981   auto get_apps_info_response = [this, callback_id](
982       const std::shared_ptr<picojson::value>& response) -> void {
983     picojson::object& obj = response->get<picojson::object>();
984     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
985     Instance::PostMessage(&this->instance_, response->serialize().c_str());
986   };
987
988   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
989
990   TaskQueue::GetInstance().Queue<picojson::value>(
991       get_apps_info,
992       get_apps_info_response,
993       data);
994 }
995
996 void ApplicationManager::GetAppInfo(const std::string& app_id, picojson::object* out) {
997   LoggerD("Entered");
998
999   pkgmgrinfo_appinfo_h handle = nullptr;
1000
1001   if (PMINFO_R_OK != pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1002     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out);
1003     return;
1004   }
1005
1006   picojson::value result = picojson::value(picojson::object());
1007   ApplicationUtils::CreateApplicationInformation(handle, &result.get<picojson::object>());
1008   pkgmgrinfo_appinfo_destroy_appinfo(handle);
1009
1010   ReportSuccess(result, *out);
1011 }
1012
1013 char* ApplicationManager::GetPackageId(const std::string& app_id) {
1014   LoggerD("Entered");
1015   app_info_h handle;
1016   char* pkg_id = nullptr;
1017
1018   int ret = app_manager_get_app_info(app_id.c_str(), &handle);
1019   if (APP_MANAGER_ERROR_NONE != ret) {
1020     LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
1021     return nullptr;
1022   }
1023
1024   ret = app_info_get_package(handle, &pkg_id);
1025   if (APP_MANAGER_ERROR_NONE != ret) {
1026     LoggerE("Failed to get package id: %d (%s)", ret, get_error_message(ret));
1027     pkg_id = nullptr;
1028   }
1029
1030   ret = app_info_destroy(handle);
1031   if (APP_MANAGER_ERROR_NONE != ret) {
1032     LoggerE("Failed to destroy app info: %d (%s)", ret, get_error_message(ret));
1033   }
1034
1035   return pkg_id;
1036 }
1037
1038 void ApplicationManager::GetAppCerts(const std::string& app_id, picojson::object* out) {
1039   LoggerD("Entered");
1040
1041   char* package_id = nullptr;
1042
1043   package_id = GetPackageId(app_id);
1044   // automatically release the memory
1045   std::unique_ptr<char, void(*)(void*)> package_id_ptr(package_id, &std::free);
1046
1047   if (!package_id) {
1048     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
1049     return;
1050   }
1051
1052   package_info_h pkg_info = nullptr;
1053   int ret = package_info_create(package_id, &pkg_info);
1054
1055   std::unique_ptr<std::remove_pointer<package_info_h>::type, int(*)(package_info_h)>
1056   pkg_info_ptr(pkg_info, &package_info_destroy); // automatically release the memory
1057
1058   if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1059     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out,
1060                 ("Failed to get package info: %d (%s)", ret, get_error_message(ret)));
1061     return;
1062   }
1063
1064   auto cert_info_cb = [](package_info_h handle, package_cert_type_e cert_type,
1065       const char* cert_value, void* user_data) -> bool {
1066     const char* cert_name = nullptr;
1067
1068     switch(cert_type) {
1069       case PACKAGE_INFO_AUTHOR_ROOT_CERT:
1070         cert_name = "AUTHOR_ROOT";
1071         break;
1072       case PACKAGE_INFO_AUTHOR_INTERMEDIATE_CERT:
1073         cert_name = "AUTHOR_INTERMEDIATE";
1074         break;
1075       case PACKAGE_INFO_AUTHOR_SIGNER_CERT:
1076         cert_name = "AUTHOR_SIGNER";
1077         break;
1078       case PACKAGE_INFO_DISTRIBUTOR_ROOT_CERT:
1079         cert_name = "DISTRIBUTOR_ROOT";
1080         break;
1081       case PACKAGE_INFO_DISTRIBUTOR_INTERMEDIATE_CERT:
1082         cert_name = "DISTRIBUTOR_INTERMEDIATE";
1083         break;
1084       case PACKAGE_INFO_DISTRIBUTOR_SIGNER_CERT:
1085         cert_name = "DISTRIBUTOR_SIGNER";
1086         break;
1087       case PACKAGE_INFO_DISTRIBUTOR2_ROOT_CERT:
1088         cert_name = "DISTRIBUTOR2_ROOT";
1089         break;
1090       case PACKAGE_INFO_DISTRIBUTOR2_INTERMEDIATE_CERT:
1091         cert_name = "DISTRIBUTOR2_INTERMEDIATE";
1092         break;
1093       case PACKAGE_INFO_DISTRIBUTOR2_SIGNER_CERT:
1094         cert_name = "DISTRIBUTOR2_SIGNER";
1095         break;
1096       default:
1097         LoggerD("Unknown certificate type: %d", cert_type);
1098         break;
1099     }
1100
1101     picojson::array* array = static_cast<picojson::array*>(user_data);
1102     array->push_back(picojson::value(picojson::object()));
1103
1104     ApplicationUtils::CreateApplicationCertificate(
1105         cert_name, cert_value, &array->back().get<picojson::object>());
1106
1107     return true;
1108   };
1109
1110   picojson::value result = picojson::value(picojson::array());
1111
1112   ret = package_info_foreach_cert_info(pkg_info, cert_info_cb, &result.get<picojson::array>());
1113
1114   if ((PACKAGE_MANAGER_ERROR_NONE != ret) && (PACKAGE_MANAGER_ERROR_IO_ERROR != ret)) {
1115     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificates info."), out,
1116                 ("Failed to get certificates info: %d (%s)", ret, get_error_message(ret)));
1117     return;
1118   }
1119
1120   ReportSuccess(result, *out);
1121 }
1122
1123 void ApplicationManager::GetAppSharedUri(const std::string& app_id, picojson::object* out) {
1124   LoggerD("Entered");
1125
1126   char* package_id = nullptr;
1127
1128   package_id = GetPackageId(app_id);
1129   // automatically release the memory
1130   std::unique_ptr<char, void(*)(void*)> package_id_ptr(package_id, &std::free);
1131
1132   if (!package_id) {
1133     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
1134     return;
1135   }
1136
1137   pkgmgrinfo_pkginfo_h pkg_info = nullptr;
1138
1139   int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(package_id, getuid(), &pkg_info);
1140   std::unique_ptr<std::remove_pointer<pkgmgrinfo_pkginfo_h>::type, int(*)(pkgmgrinfo_pkginfo_h)>
1141   pkg_info_ptr(pkg_info, &pkgmgrinfo_pkginfo_destroy_pkginfo); // automatically release the memory
1142
1143   if (PMINFO_R_OK != ret) {
1144     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out,
1145                 ("Failed to get package info: %d (%s)", ret, get_error_message(ret)));
1146     return;
1147   }
1148
1149   char* root_path = nullptr;
1150   ret = pkgmgrinfo_pkginfo_get_root_path(pkg_info, &root_path);
1151
1152   if (PMINFO_R_OK != ret || nullptr == root_path) {
1153     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get root path."), out,
1154                 ("Failed to get root path: %d (%s)", ret, get_error_message(ret)));
1155     return;
1156   }
1157
1158   picojson::value result = picojson::value(kTizenApisFileScheme +
1159                                            root_path +
1160                                            kTizenApisAppSlash +
1161                                            kTizenApisAppShared +
1162                                            kTizenApisAppSlash);
1163   ReportSuccess(result, *out);
1164 }
1165
1166 #ifdef TIZEN_MOBILE
1167 PlatformResult ApplicationManager::BatteryUsageFilter(const picojson::value& args, const context_history_filter_h filter,
1168                                                       context_history_data_e* data_type_out) {
1169   LoggerD("Entered");
1170   int ret = CONTEXT_HISTORY_ERROR_NONE;
1171   int limit = kMaximumBatteryRetrievedObjects;
1172   if (args.contains("limit")) {
1173     limit = static_cast<int>(args.get("limit").get<double>());
1174   }
1175
1176   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1177
1178   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1179     return LogAndCreateResult(
1180         ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1181         ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1182   }
1183
1184   context_history_data_e data_type_in = CONTEXT_HISTORY_RECENT_BATTERY_USAGE;
1185
1186   if (args.contains("days")) {
1187     const int days = static_cast<int>(args.get("days").get<double>());
1188     data_type_in = CONTEXT_HISTORY_BATTERY_USAGE;
1189     ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, days);
1190
1191     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1192       return LogAndCreateResult(
1193           ErrorCode::INVALID_VALUES_ERR, "days given with invalid value.",
1194           ("days given with invalid value: %d (%s)", ret, get_error_message(ret)));
1195     }
1196   }
1197
1198   *data_type_out = data_type_in;
1199
1200   return PlatformResult(ErrorCode::NO_ERROR);
1201 }
1202
1203 PlatformResult ApplicationManager::BatteryUsageAttributes(const context_history_record_h record, picojson::object* object) {
1204   LoggerD("Entered");
1205
1206   int ret = CONTEXT_HISTORY_ERROR_NONE;
1207   double amount = 0.0;
1208   char* app_id = nullptr;
1209   SCOPE_EXIT {
1210     free(app_id);
1211   };
1212
1213   ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1214   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1215     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1216         ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1217   }
1218
1219   ret = context_history_record_get_double(record, CONTEXT_HISTORY_TOTAL_AMOUNT, &amount);
1220   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1221     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get amount.",
1222         ("Failed to get amount: %d (%s)", ret, get_error_message(ret)));
1223   }
1224
1225   object->insert(std::make_pair("appId", picojson::value(app_id)));
1226   object->insert(std::make_pair("batteryUsage", picojson::value(amount)));
1227
1228   return PlatformResult(ErrorCode::NO_ERROR);
1229 }
1230
1231 PlatformResult ApplicationManager::AppsUsageFilter(const picojson::value& args,
1232                                                    const context_history_filter_h filter,
1233                                                    context_history_data_e* data_type_out) {
1234   LoggerD("Entered");
1235   int ret = CONTEXT_HISTORY_ERROR_NONE;
1236   int limit = kMaximumAppsRetrievedObjects;
1237   if (args.contains("limit")) {
1238     limit = static_cast<int>(args.get("limit").get<double>());
1239   }
1240
1241   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1242   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1243     return LogAndCreateResult(
1244         ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1245         ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1246   }
1247
1248   context_history_data_e data_type_in = CONTEXT_HISTORY_FREQUENTLY_USED_APP;
1249   if (args.contains("mode") && kAppUsageModeRecently == args.get("mode").get<std::string>()) {
1250     data_type_in = CONTEXT_HISTORY_RECENTLY_USED_APP;
1251   }
1252
1253   int time_span = kDefaultPeriodOfTime;
1254   const picojson::object &JS_filter = args.get("filter").get<picojson::object>();
1255   auto time_span_iter = JS_filter.find("timeSpan");
1256   if (JS_filter.end() != time_span_iter
1257       || (JS_filter.end() == JS_filter.find("startTime")
1258           && JS_filter.end() == JS_filter.find("endTime"))) {
1259     //In the second case, we treat the filter object just like an empty object.
1260     //The default value of filter will be used instead.
1261     if (JS_filter.end() != time_span_iter) {
1262       time_span = static_cast<int>(time_span_iter->second.get<double>());
1263     }
1264     ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, time_span);
1265     //context_history_filter_set_int may return only success or CONTEXT_HISTORY_ERROR_INVALID_PARAMETER
1266     //Although this should never happen, it's better to check ret's value
1267     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1268       return LogAndCreateResult(
1269           ErrorCode::ABORT_ERR, "Error while setting the default TIME_SPAN value.",
1270           ("Error while setting the default TIME_SPAN value: %d (%s)", ret, get_error_message(ret)));
1271     }
1272   } else {
1273     auto start_time_iter = JS_filter.find("startTime");
1274     auto end_time_iter = JS_filter.find("endTime");
1275     if (start_time_iter != JS_filter.end()) {
1276       int start_time = static_cast<int>(start_time_iter->second.get<double>());
1277       ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_START_TIME, start_time);
1278       if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1279         return LogAndCreateResult(
1280             ErrorCode::INVALID_VALUES_ERR, "startTime given with invalid value.",
1281             ("startTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1282       }
1283     }
1284     if (end_time_iter != JS_filter.end()) {
1285       int end_time = static_cast<int>(end_time_iter->second.get<double>());
1286       ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_END_TIME, end_time);
1287       if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1288         return LogAndCreateResult(
1289             ErrorCode::INVALID_VALUES_ERR, "endTime given with invalid value.",
1290             ("endTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1291       }
1292     }
1293   }
1294
1295   *data_type_out = data_type_in;
1296
1297   return PlatformResult(ErrorCode::NO_ERROR);
1298 }
1299
1300 PlatformResult ApplicationManager::AppsUsageAttributes(const context_history_record_h record,
1301                                                        picojson::object* object) {
1302   LoggerD("Entered");
1303
1304   int ret = CONTEXT_HISTORY_ERROR_NONE;
1305   int total_count = 0;
1306   int total_duration = 0;
1307   int last_time = 0;
1308   char* app_id = nullptr;
1309   SCOPE_EXIT {
1310     free(app_id);
1311   };
1312
1313   ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1314   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1315     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1316                               ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1317   }
1318
1319   ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_COUNT, &total_count);
1320   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1321     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get total count.",
1322                               ("Failed to get total count: %d (%s)", ret, get_error_message(ret)));
1323   }
1324
1325   ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_DURATION, &total_duration);
1326   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1327     return LogAndCreateResult(
1328         ErrorCode::ABORT_ERR, "Failed to get total duration.",
1329         ("Failed to get total duration: %d (%s)", ret, get_error_message(ret)));
1330   }
1331
1332   ret = context_history_record_get_int(record, CONTEXT_HISTORY_LAST_TIME, &last_time);
1333   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1334     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get last time.",
1335                               ("Failed to get last time: %d (%s)", ret, get_error_message(ret)));
1336   }
1337
1338   object->insert(std::make_pair("appId", picojson::value(app_id)));
1339   object->insert(std::make_pair("totalCount", picojson::value(static_cast<double>(total_count))));
1340   object->insert(
1341       std::make_pair("totalDuration", picojson::value(static_cast<double>(total_duration))));
1342   object->insert(std::make_pair("lastTime", picojson::value(static_cast<double>(last_time))));
1343
1344   return PlatformResult(ErrorCode::NO_ERROR);
1345 }
1346 #endif
1347
1348 void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojson::object* out) {
1349   LoggerD("Entered");
1350
1351 #ifdef TIZEN_MOBILE
1352   int callback_id = -1;
1353   const auto& callback = args.get(kCallbackId);
1354   if (callback.is<double>()) {
1355     callback_id = static_cast<int>(callback.get<double>());
1356   }
1357
1358   auto get_battery_usage = [args](const std::shared_ptr<picojson::value>& response)-> void {
1359     LoggerD("Entered");
1360     PlatformResult result = ApplicationManager::GetContextHistory(args, &response.get()->get<picojson::object>(),
1361                                                                   &ApplicationManager::BatteryUsageFilter,
1362                                                                   &ApplicationManager::BatteryUsageAttributes);
1363     if (!result) {
1364       LogAndReportError(result, &response.get()->get<picojson::object>());
1365     }
1366   };
1367
1368   auto get_battery_usage_response = [this, callback_id](
1369       const std::shared_ptr<picojson::value>& response) -> void {
1370     LoggerD("Entered");
1371     picojson::object& obj = response->get<picojson::object>();
1372     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1373     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1374   };
1375
1376   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1377
1378   TaskQueue::GetInstance().Queue<picojson::value>(
1379     get_battery_usage,
1380     get_battery_usage_response,
1381     data);
1382 #else
1383   // 20170510 Context API is supported only for mobile profile, other ones would result with NotSupportedError
1384   LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "This feature is not supported on this profile."), out,
1385                     ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1386 #endif
1387 }
1388
1389 void ApplicationManager::GetAppsUsageInfo(const picojson::value& args, picojson::object* out) {
1390   LoggerD("Entered");
1391
1392 #ifdef TIZEN_MOBILE
1393   int callback_id = static_cast<int>(args.get(kCallbackId).get<double>());
1394
1395   auto get_apps_usage = [args](const std::shared_ptr<picojson::value>& response)-> void {
1396     LoggerD("Entered");
1397     PlatformResult result = ApplicationManager::GetContextHistory(args, &response.get()->get<picojson::object>(),
1398                                                                   &ApplicationManager::AppsUsageFilter,
1399                                                                   &ApplicationManager::AppsUsageAttributes);
1400     if (!result) {
1401       LogAndReportError(result, &response.get()->get<picojson::object>());
1402     }
1403   };
1404
1405   auto get_apps_usage_response = [this, callback_id](
1406       const std::shared_ptr<picojson::value>& response) -> void {
1407     LoggerD("Entered");
1408     picojson::object& obj = response->get<picojson::object>();
1409     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1410     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1411   };
1412
1413   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1414
1415   TaskQueue::GetInstance().Queue<picojson::value>(
1416     get_apps_usage,
1417     get_apps_usage_response,
1418     data);
1419 #else
1420   // Context API is supported only for mobile profile, other ones would result with NotSupportedError
1421   LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "This feature is not supported on this profile."), out,
1422                     ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1423 #endif
1424 }
1425
1426 void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) {
1427   LoggerD("Entered");
1428
1429   pkgmgrinfo_appinfo_h handle = nullptr;
1430
1431   int ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle);
1432   std::unique_ptr<std::remove_pointer<pkgmgrinfo_appinfo_h>::type, int(*)(pkgmgrinfo_appinfo_h)>
1433   pkg_info_ptr(handle, &pkgmgrinfo_appinfo_destroy_appinfo); // automatically release the memory
1434
1435   if (PMINFO_R_OK != ret) {
1436     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out,
1437                 ("Failed to get app info: %d (%s)", ret, get_error_message(ret)));
1438     return;
1439   }
1440
1441   auto meta_data_cb = [](const char* meta_key, const char* meta_value, void* user_data) -> int {
1442     if (nullptr == meta_key || nullptr == meta_value) {
1443       LoggerE("meta_key or meta_value is null");
1444       return 0;
1445     }
1446
1447     picojson::array* array = static_cast<picojson::array*>(user_data);
1448     array->push_back(picojson::value(picojson::object()));
1449
1450     ApplicationUtils::CreateApplicationMetaData(meta_key, meta_value,
1451                                                 &array->back().get<picojson::object>());
1452     return 0;
1453   };
1454
1455   picojson::value result = picojson::value(picojson::array());
1456   ret = pkgmgrinfo_appinfo_foreach_metadata(handle, meta_data_cb, &result.get<picojson::array>());
1457
1458   if (PMINFO_R_OK != ret) {
1459     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get metadata."), out,
1460                       ("Failed to get metadata: %d (%s)", ret, get_error_message(ret)));
1461     return;
1462   }
1463
1464   ReportSuccess(result, *out);
1465 }
1466
1467 class ApplicationListChangedBroker {
1468  public:
1469     ApplicationListChangedBroker() : event_type_() {}
1470   enum class Event {
1471     kInstalled,
1472     kUpdated,
1473     kUninstalled,
1474   };
1475
1476   static int ClientStatusListener(unsigned int target_uid, int id,
1477                                   const char* type, const char* package,
1478                                   const char* key,
1479                                   const char* val, const void* msg,
1480                                   void* data) {
1481     LoggerD("Entered");
1482     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1483
1484     if (0 == strcasecmp(key, kStartKey)) {
1485       that->HandleStart(val, package);
1486     } else if (0 == strcasecmp(key, kEndKey) && 0 == strcasecmp(val, kOkValue)) {
1487       that->HandleEnd(package);
1488     } else {
1489       LoggerD("Ignored key: %s", key);
1490     }
1491
1492     return 0;
1493   }
1494
1495   static int AppUninstallListener(uid_t target_uid, int id, const char* type, const char* package, const char* key,
1496                                   const char* val, const void* msg, void* data) {
1497     LoggerD("Entered");
1498
1499     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1500
1501     if (0 == strcasecmp(key, kStartKey)) {
1502       that->HandleUninstallStart();
1503     } else if (0 == strcasecmp(key, kAppidKey)) {
1504       that->AddUninstalledAppId(val);
1505     } else if (0 == strcasecmp(key, kEndKey)) {
1506       that->HandleUninstallEnd();
1507     } else {
1508       LoggerD("Ignored key: %s", key);
1509     }
1510
1511     return 0;
1512   }
1513
1514   void AddApplicationInstance(ApplicationInstance* app_instance) {
1515     LoggerD("Entered");
1516       app_instance_list_.push_back(app_instance);
1517   }
1518
1519   void RemoveApplicationInstance(ApplicationInstance* app_instance) {
1520     LoggerD("Entered");
1521     for (auto it = app_instance_list_.begin(); it != app_instance_list_.end(); it++) {
1522       if (*it == app_instance) {
1523        app_instance_list_.erase(it);
1524        return;
1525       }
1526     }
1527   }
1528  private:
1529   void HandleStart(const char* event_type, const char* package) {
1530     LoggerD("Entered");
1531     app_list_.clear();
1532     set_event_type(event_type);
1533   }
1534
1535   void HandleEnd(const char* package) {
1536     LoggerD("Entered");
1537
1538     if (Event::kUninstalled == event_type_) {
1539       return;
1540     }
1541
1542     GetApplicationIdsFromPackage(package);
1543
1544     for (auto& app_id : app_list_) {
1545       picojson::value value = picojson::value(picojson::object());
1546       picojson::object& data_obj = value.get<picojson::object>();
1547
1548       switch (event_type_) {
1549         case Event::kInstalled:
1550           data_obj.insert(std::make_pair(kAction, picojson::value(kOnInstalled)));
1551           break;
1552
1553         case Event::kUpdated:
1554           data_obj.insert(std::make_pair(kAction, picojson::value(kOnUpdated)));
1555           break;
1556         case Event::kUninstalled:
1557           LoggerD("Uninstalled called");
1558           break;
1559       }
1560
1561       switch (event_type_) {
1562         case Event::kInstalled:
1563         case Event::kUpdated:
1564         {
1565           pkgmgrinfo_appinfo_h handle = nullptr;
1566           if (PMINFO_R_OK != pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1567             LoggerE("Failed to get application information handle.");
1568             continue;
1569           }
1570           auto info = data_obj.insert(std::make_pair(kData, picojson::value(picojson::object())));
1571           ApplicationUtils::CreateApplicationInformation(
1572               handle, &info.first->second.get<picojson::object>());
1573           pkgmgrinfo_appinfo_destroy_appinfo(handle);
1574         }
1575         break;
1576         case Event::kUninstalled:
1577           LoggerD("Uninstalled called");
1578           break;
1579       }
1580
1581       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1582
1583       for (auto instance : app_instance_list_) {
1584         Instance::PostMessage(instance, value.serialize().c_str());
1585       }
1586     }
1587   }
1588
1589   void GetApplicationIdsFromPackage(const char* package) {
1590     LoggerD("Entered");
1591     package_info_h package_info = nullptr;
1592
1593     int ret = package_info_create(package, &package_info);
1594     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1595       LoggerE("Failed to create package info: %d (%s)", ret, get_error_message(ret));
1596       return;
1597     }
1598
1599     ret = package_info_foreach_app_from_package(package_info,
1600                                                 PACKAGE_INFO_ALLAPP,
1601                                                 ApplicationIdCallback,
1602                                                 this);
1603     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1604       LoggerE("Failed to get application IDs: %d (%s)", ret, get_error_message(ret));
1605     }
1606
1607     ret = package_info_destroy(package_info);
1608     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1609       LoggerE("Failed to destroy package info: %d (%s)", ret, get_error_message(ret));
1610     }
1611   }
1612
1613   void set_event_type(const char* type) {
1614     LoggerD("Entered");
1615     if (0 == strcasecmp(type, kInstallEvent)) {
1616       event_type_ = Event::kInstalled;
1617     } else if (0 == strcasecmp(type, kUpdateEvent)) {
1618       event_type_ = Event::kUpdated;
1619     } else if (0 == strcasecmp(type, kUninstallEvent)) {
1620       event_type_ = Event::kUninstalled;
1621     }
1622   }
1623
1624   static bool ApplicationIdCallback(package_info_app_component_type_e comp_type,
1625                                     const char* app_id, void* user_data) {
1626     LoggerD("Entered");
1627     if (nullptr != app_id) {
1628       static_cast<ApplicationListChangedBroker*>(user_data)->app_list_.push_back(app_id);
1629     }
1630     return true;
1631   }
1632
1633   void HandleUninstallStart() {
1634     LoggerD("Entered");
1635     app_list_.clear();
1636     set_event_type(kUninstallEvent);
1637   }
1638
1639   void AddUninstalledAppId(const char* app_id) {
1640     LoggerD("Entered");
1641     if (nullptr != app_id) {
1642       app_list_.push_back(app_id);
1643     }
1644   }
1645
1646   void HandleUninstallEnd() {
1647     LoggerD("Entered");
1648     for (auto& app_id : app_list_) {
1649       picojson::value value = picojson::value(picojson::object());
1650       picojson::object& data_obj = value.get<picojson::object>();
1651
1652       data_obj.insert(std::make_pair(kAction, picojson::value(kOnUninstalled)));
1653       data_obj.insert(std::make_pair(kData, picojson::value(app_id)));
1654
1655       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1656
1657       for (auto instance : app_instance_list_) {
1658         Instance::PostMessage(instance, value.serialize().c_str());
1659       }
1660     }
1661   }
1662
1663   Event event_type_;
1664   std::vector<std::string> app_list_;
1665   std::vector<ApplicationInstance*> app_instance_list_;
1666 };
1667
1668 static ApplicationListChangedBroker g_application_list_changed_broker;
1669
1670 void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
1671   LoggerD("Entered");
1672
1673   if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgr_client_uninstall_handle_) {
1674     if(nullptr == pkgmgr_client_handle_) {
1675       pkgmgr_client_handle_ = pkgmgr_client_new(PC_LISTENING);
1676     }
1677     if(nullptr == pkgmgr_client_uninstall_handle_) {
1678       pkgmgr_client_uninstall_handle_ = pkgmgr_client_new(PC_LISTENING);
1679     }
1680
1681     if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgr_client_uninstall_handle_) {
1682       if(nullptr != pkgmgr_client_handle_) {
1683         pkgmgr_client_free(pkgmgr_client_handle_);
1684         pkgmgr_client_handle_ = nullptr;
1685       }
1686       if(nullptr != pkgmgr_client_uninstall_handle_) {
1687         pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1688         pkgmgr_client_uninstall_handle_ = nullptr;
1689       }
1690       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."), out);
1691       return;
1692     }
1693
1694     g_application_list_changed_broker.AddApplicationInstance(&instance_);
1695
1696     pkgmgr_client_set_status_type(pkgmgr_client_handle_,
1697                                   PACKAGE_MANAGER_STATUS_TYPE_INSTALL | PACKAGE_MANAGER_STATUS_TYPE_UPGRADE);
1698     pkgmgr_client_set_status_type(pkgmgr_client_uninstall_handle_,
1699                                   PACKAGE_MANAGER_STATUS_TYPE_UNINSTALL);
1700
1701     pkgmgr_client_listen_status(pkgmgr_client_handle_,
1702                                 ApplicationListChangedBroker::ClientStatusListener,
1703                                 &g_application_list_changed_broker);
1704     pkgmgr_client_listen_status(pkgmgr_client_uninstall_handle_,
1705                                 ApplicationListChangedBroker::AppUninstallListener,
1706                                 &g_application_list_changed_broker);
1707
1708   } else {
1709     LoggerD("Broker callback is already registered.");
1710   }
1711
1712   ReportSuccess(*out);
1713 }
1714
1715 void ApplicationManager::StopAppInfoEventListener() {
1716   LoggerD("Entered");
1717
1718   if (nullptr != pkgmgr_client_handle_ || nullptr != pkgmgr_client_uninstall_handle_) {
1719     if(nullptr != pkgmgr_client_handle_) {
1720       pkgmgr_client_free(pkgmgr_client_handle_);
1721       pkgmgr_client_handle_ = nullptr;
1722     }
1723     if(nullptr != pkgmgr_client_uninstall_handle_) {
1724       pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1725       pkgmgr_client_uninstall_handle_ = nullptr;
1726     }
1727     g_application_list_changed_broker.RemoveApplicationInstance(&instance_);
1728   } else {
1729     LoggerD("Broker callback is already unregistered.");
1730   }
1731 }
1732
1733 void ApplicationManager::GetApplicationInformationSize(const picojson::value& args,
1734                                                        picojson::object* out) {
1735   LoggerD("Entered");
1736
1737   const auto& package_id = args.get("packageId");
1738   if (!package_id.is<std::string>()) {
1739     LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."), out);
1740     return;
1741   }
1742
1743   const std::string& package_id_str = package_id.get<std::string>();
1744
1745   // get installed size from package server (to solve smack issue)
1746   pkgmgr_client* pc = pkgmgr_client_new(PC_REQUEST);
1747   int size = -1;
1748
1749   if (nullptr == pc) {
1750     LoggerE("Failed to create pkgmgr client");
1751   } else {
1752     size = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_TOTAL_SIZE, pc, NULL,
1753                                          package_id_str.c_str(), NULL, NULL, NULL);
1754
1755     if (size < 0) {
1756       LoggerE("Failed to get installed size: %d (%s)", size, get_error_message(size));
1757     }
1758
1759     pkgmgr_client_free(pc);
1760   }
1761
1762
1763   picojson::value result = picojson::value(picojson::object());
1764   picojson::object& result_obj = result.get<picojson::object>();
1765   result_obj.insert(std::make_pair("size", picojson::value(static_cast<double>(size))));
1766
1767   ReportSuccess(result, *out);
1768 }
1769
1770 void ApplicationManager::BroadcastEventHelper(
1771     const picojson::value& args,
1772     picojson::object& out, bool trusted) {
1773
1774   LoggerD("Entered");
1775
1776   int ret;
1777   std::string event_str = args.get("name").get<std::string>();
1778   const char* event_name = event_str.c_str();
1779
1780   bundle* data = bundle_create();
1781   SCOPE_EXIT {
1782     bundle_free(data);
1783   };
1784
1785   ret = bundle_add(data, "data", args.get("data").serialize().c_str());
1786
1787   if (ret != EVENT_ERROR_NONE) {
1788     LoggerE("bundle_add failed, error: %d (%s)", ret, get_error_message(ret));
1789     ReportError(out);
1790     return;
1791   }
1792
1793   if (trusted) {
1794     ret = event_publish_trusted_app_event(event_name, data);
1795   } else {
1796     ret = event_publish_app_event(event_name, data);
1797   }
1798
1799   if (ret == EVENT_ERROR_NONE) {
1800     ReportSuccess(out);
1801   } else {
1802     LoggerE("event_publish_app_event failed, error: %d (%s)", ret, get_error_message(ret));
1803     ReportError(out);
1804   }
1805 }
1806
1807 void ApplicationManager::OnEvent(const char* event_name,
1808                                  bundle* event_data,
1809                                  void* user_data) {
1810   LoggerD("Entered");
1811   LOGGER(DEBUG) << event_name;
1812
1813   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1814
1815   if (!manager->event_callback_) {
1816     LOGGER(DEBUG) << "No event listener registered, skipping.";
1817     return;
1818   }
1819
1820   picojson::value event = picojson::value(picojson::object());
1821   picojson::object& event_o = event.get<picojson::object>();
1822
1823   int ret;
1824   char* val = nullptr;
1825
1826   if (event_map_.count(event_name)) { // system event
1827     const std::string& key = event_map_.at(event_name);
1828     std::string state = "true";
1829     if (key != "") {
1830       ret = bundle_get_str(event_data, key.c_str(), &val);
1831       if (EVENT_ERROR_NONE != ret) {
1832         LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1833         return;
1834       }
1835
1836       state = std::string(val);
1837     }
1838
1839     LoggerD("State is %s", state.c_str());
1840     event_o["value"] = picojson::value(state);
1841
1842   } else { // user event
1843     ret = bundle_get_str(event_data, "data", &val);
1844     if (EVENT_ERROR_NONE != ret) {
1845       LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1846       return;
1847     }
1848
1849     picojson::value data;
1850     std::string err;
1851     picojson::parse(data, val, val + strlen(val), &err);
1852     if (!err.empty()) {
1853       LOGGER(ERROR) << "Failed to parse bundle data: " << err;
1854       return;
1855     }
1856
1857     event_o["data"] = data;
1858   }
1859
1860   LOGGER(DEBUG) << "event_name is: " << event_name;
1861   event_o["name"] = picojson::value(event_name);
1862
1863   manager->event_callback_(&event);
1864 }
1865
1866 PlatformResult ApplicationManager::StartEventListener(const std::string& event_name,
1867                                                       const JsonCallback& callback) {
1868   LoggerD("Entered");
1869
1870   int ret;
1871   event_handler_h event_handler;
1872
1873   ret = event_add_event_handler(event_name.c_str(), OnEvent, this, &event_handler);
1874   LoggerD("event_add_event_handler() result: %d (%s)", ret, get_error_message(ret));
1875   if (EVENT_ERROR_PERMISSION_DENIED == ret) {
1876     return LogAndCreateResult(ErrorCode::SECURITY_ERR, "The privilege is required",
1877                               ("event_add_event_handler failed, error: %d", ret));
1878   } else if (EVENT_ERROR_NONE != ret) {
1879     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error setting event listener",
1880                               ("event_add_event_handler failed, error: %d", ret));
1881   }
1882
1883   event_handler_map_[event_name] = event_handler;
1884
1885   event_callback_ = callback;
1886   LOGGER(DEBUG) << "event_add_event_handler success";
1887   return PlatformResult(ErrorCode::NO_ERROR);
1888 }
1889
1890 void ApplicationManager::StopEventListener(const std::string& event_name) {
1891   LoggerD("Entered");
1892
1893   int ret;
1894   event_handler_h event_handler;
1895
1896   if (event_handler_map_.find(event_name) != event_handler_map_.end()) {
1897     event_handler = event_handler_map_[event_name];
1898
1899     ret = event_remove_event_handler(event_handler);
1900     if (EVENT_ERROR_NONE != ret) {
1901       LoggerE("event_remove_event_handler failed, error: %d (%s)", ret, get_error_message(ret));
1902       return;
1903     }
1904
1905     event_handler_map_.erase(event_name);
1906   }
1907 }
1908
1909 void ApplicationManager::OnStatusEvent(const char *type, const char *app_id,
1910                                        app_manager_event_type_e event_type,
1911                                        app_manager_event_state_e event_state,
1912                                        app_manager_event_h handle, void *user_data) {
1913   LoggerD("Entered");
1914
1915   if (APP_MANAGER_EVENT_STATE_COMPLETED != event_state) {
1916     LoggerD("State different from completed");
1917     return;
1918   }
1919
1920   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1921
1922   if (!manager || !manager->status_callback_) {
1923     LoggerD("No event listener registered, skipping.");
1924     return;
1925   }
1926
1927   bool status_type;
1928   switch (event_type) {
1929     case APP_MANAGER_EVENT_ENABLE_APP:
1930       status_type = true;
1931       break;
1932     case APP_MANAGER_EVENT_DISABLE_APP:
1933       status_type = false;
1934       break;
1935     default:
1936       LoggerD("Uknown status type skipping.");
1937       return;
1938   }
1939
1940   picojson::value event = picojson::value(picojson::object());
1941   picojson::object& event_o = event.get<picojson::object>();
1942
1943   event_o[kStatusType] = picojson::value(status_type);
1944   event_o[kAppId] = picojson::value(app_id);
1945   event_o[kListenerId] = picojson::value(kAppStatusChangeListener);
1946
1947   manager->status_callback_(&event);
1948 }
1949
1950 #ifdef TIZEN_MOBILE
1951 PlatformResult ApplicationManager::GetContextHistory(const picojson::value& args, picojson::object* out,
1952                                                      common::PlatformResult (*modify_filter_cb)(const picojson::value&, const context_history_filter_h, context_history_data_e* data_type),
1953                                                      common::PlatformResult (*add_attributes_to_object)(const context_history_record_h, picojson::object*)) {
1954   LoggerD("Entered");
1955   context_history_list_h list = nullptr;
1956   context_history_h handle = nullptr;
1957   context_history_filter_h filter = nullptr;
1958
1959   SCOPE_EXIT {
1960     context_history_list_destroy(list);
1961     context_history_destroy(handle);
1962     context_history_filter_destroy(filter);
1963   };
1964
1965   int ret = context_history_create(&handle);
1966   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1967     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to create context handle.",
1968         ("Failed to create context handle: %d (%s)", ret, get_error_message(ret)));
1969   }
1970
1971   ret = context_history_filter_create(&filter);
1972   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1973     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to create filter handle.",
1974         ("Failed to create filter handle: %d (%s)", ret, get_error_message(ret)));
1975   }
1976
1977   context_history_data_e data_type;
1978
1979   PlatformResult result = modify_filter_cb(args, filter, &data_type);
1980   if (!result) {
1981     return result;
1982   }
1983
1984   picojson::value result_array = picojson::value(picojson::array());
1985   picojson::array& array_obj = result_array.get<picojson::array>();
1986
1987   ret = context_history_get_list(handle, data_type, filter, &list);
1988   if (CONTEXT_HISTORY_ERROR_NO_DATA == ret) {
1989     ReportSuccess(result_array, *out);
1990     return PlatformResult(ErrorCode::NO_ERROR);
1991   } else if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1992     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list.",
1993         ("Failed to get list: %d (%s)", ret, get_error_message(ret)));
1994   }
1995
1996   int size = 0;
1997   ret = context_history_list_get_count(list, &size);
1998   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1999     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list size.",
2000         ("Failed to get list size: %d (%s)", ret, get_error_message(ret)));
2001   }
2002
2003   array_obj.resize(size, picojson::value(picojson::object()));
2004
2005   for (int i = 0; i < size; ++i) {
2006     context_history_record_h record = nullptr;
2007     SCOPE_EXIT {
2008       context_history_record_destroy(record);
2009     };
2010
2011     ret = context_history_list_get_current(list, &record);
2012     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2013       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get current record.",
2014           ("Failed to get current record: %d (%s)", ret, get_error_message(ret)));
2015     }
2016
2017     result = add_attributes_to_object(record, &array_obj[i].get<picojson::object>());
2018     if (!result) {
2019       return result;
2020     }
2021
2022     ret = context_history_list_move_next(list);
2023     if (CONTEXT_HISTORY_ERROR_NONE != ret && CONTEXT_HISTORY_ERROR_NO_DATA != ret) {
2024       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to move iterator.",
2025           ("Failed to move iterator: %d (%s)", ret, get_error_message(ret)));
2026     }
2027   }
2028
2029   ReportSuccess(result_array, *out);
2030   return PlatformResult(ErrorCode::NO_ERROR);
2031 }
2032 #endif
2033
2034 PlatformResult ApplicationManager::StartStatusListener(const JsonCallback& callback) {
2035   LoggerD("Entered");
2036
2037   int ret = APP_MANAGER_ERROR_NONE;
2038
2039   if (!app_status_handle_) {
2040     ret = app_manager_event_create(&app_status_handle_);
2041     if (APP_MANAGER_ERROR_NONE != ret) {
2042       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while creating event handle",
2043                                 ("app_manager_event_create failed, error: %d", ret));
2044     }
2045
2046     ret = app_manager_event_set_status(app_status_handle_, APP_MANAGER_EVENT_STATUS_TYPE_ALL);
2047     if (APP_MANAGER_ERROR_NONE != ret) {
2048       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status type",
2049                                 ("app_manager_event_set_status failed, error: %d", ret));
2050     }
2051   }
2052
2053   status_callback_ = callback;
2054   ret = app_manager_set_event_cb(app_status_handle_, OnStatusEvent, this);
2055   if (APP_MANAGER_ERROR_NONE != ret) {
2056     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status listener",
2057                               ("app_manager_set_event_cb failed, error: %d", ret));
2058   }
2059
2060   return PlatformResult(ErrorCode::NO_ERROR);
2061 }
2062
2063 PlatformResult ApplicationManager::StopStatusChangeListener() {
2064   LoggerD("Entered");
2065
2066   if (app_status_handle_) {
2067     int ret = app_manager_unset_event_cb(app_status_handle_);
2068     if (APP_MANAGER_ERROR_NONE != ret) {
2069       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while removing status listener",
2070                                 ("app_manager_unset_event_cb failed, error: %d", ret));
2071     }
2072   }
2073
2074   return PlatformResult(ErrorCode::NO_ERROR);
2075 }
2076
2077 } // namespace application
2078 } // namespace extension