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