[ham] Fixed sleep recorder, returned value
[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(const 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 namespace {
380
381 PlatformResult PrepareAppControlForLaunchAppControl(const picojson::value& args,
382                                                     app_control_h* app_control) {
383   ScopeLogger();
384
385   const auto& control = args.get("appControl");
386   if (!control.is<picojson::object>()) {
387     return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
388   }
389   const picojson::object& app_control_obj = control.get<picojson::object>();
390
391   app_control_h tmp_app_control = nullptr;
392   auto result = ApplicationUtils::ApplicationControlToService(app_control_obj, &tmp_app_control);
393   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
394       app_control_ptr(tmp_app_control, &app_control_destroy);
395
396   if (result.IsError()) {
397     LoggerE("Application control to service failed.");
398     return result;
399   }
400
401   std::string app_id;
402   const auto& id = args.get("id");
403   if (id.is<std::string>()) {
404     app_id = id.get<std::string>();
405   }
406
407   if (!app_id.empty()) {
408     LoggerD("app_id: %s", app_id.c_str());
409
410     int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
411
412     if (APP_CONTROL_ERROR_NONE != ret) {
413       LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
414       return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
415     }
416   }
417
418   *app_control = app_control_ptr.release();
419
420   return PlatformResult(ErrorCode::NO_ERROR);
421 }
422
423 }  // namespace
424
425 void ApplicationManager::LaunchAppControl(const picojson::value& args) {
426   ScopeLogger();
427
428   int callback_id = -1;
429   const auto& callback = args.get(kCallbackId);
430   if (callback.is<double>()) {
431     callback_id = static_cast<int>(callback.get<double>());
432   }
433
434   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
435   picojson::object& response_obj = response->get<picojson::object>();
436   response_obj.insert(
437       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
438
439   app_control_h app_control = nullptr;
440   auto prepare_app_control_result = PrepareAppControlForLaunchAppControl(args, &app_control);
441   if (prepare_app_control_result.IsError()) {
442     AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
443     return;
444   }
445
446   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
447       app_control_ptr(app_control, &app_control_destroy);
448
449   std::string reply_callback_id;
450   const auto& reply = args.get("replyCallback");
451   if (reply.is<std::string>()) {
452     reply_callback_id = reply.get<std::string>();
453   }
454
455   struct LaunchAppControlCallbackData {
456     ApplicationInstance* instance;
457     std::shared_ptr<picojson::value> response;
458     std::string reply_callback_id;
459   }* launch_app_user_data = new (std::nothrow)
460       LaunchAppControlCallbackData{&this->instance_, response, reply_callback_id};
461
462   if (!launch_app_user_data) {
463     LoggerE("Memory allocation fail!");
464     AsyncResponse(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response);
465     return;
466   }
467
468   app_control_reply_cb reply_callback = nullptr;
469   if (!reply_callback_id.empty()) {
470     launch_app_user_data->reply_callback_id = reply_callback_id;
471
472     reply_callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
473                         void* user_data) {
474       ScopeLogger("reply_callback");
475
476       LaunchAppControlCallbackData* callback_data =
477           static_cast<LaunchAppControlCallbackData*>(user_data);
478       if (!callback_data) {
479         LoggerD("reply_callback failed: user_data is nullptr");
480         return;
481       }
482
483       picojson::value return_value = picojson::value(picojson::object());
484       picojson::object& return_value_obj = return_value.get<picojson::object>();
485       return_value_obj.insert(
486           std::make_pair(kListenerId, picojson::value(callback_data->reply_callback_id)));
487
488       if (APP_CONTROL_RESULT_SUCCEEDED == result) {
489         LoggerD("App started");
490         return_value_obj.insert(std::make_pair("data", picojson::value(picojson::array())));
491         if (!ApplicationUtils::ServiceToApplicationControlDataArray(
492                 reply, &return_value_obj.find("data")->second.get<picojson::array>())) {
493           return_value_obj.erase("data");
494         }
495         ReportSuccess(return_value_obj);
496       } else {
497         ReportError(return_value_obj);
498       }
499
500       Instance::PostMessage(callback_data->instance, return_value.serialize().c_str());
501       delete callback_data;
502     };
503   }
504
505   app_control_result_cb result_callback = [](app_control_h launch_request,
506                                              app_control_error_e launch_result, void* user_data) {
507     ScopeLogger("LaunchAppControl result_callback");
508
509     LaunchAppControlCallbackData* callback_data =
510         static_cast<LaunchAppControlCallbackData*>(user_data);
511
512     auto result = ApplicationUtils::TranslateAppControlError(launch_result);
513
514     if (result.IsError()) {
515       LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
516     } else {
517       ReportSuccess(callback_data->response->get<picojson::object>());
518     }
519
520     Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
521
522     if (result.IsError() || (callback_data->reply_callback_id).empty()) {
523       delete callback_data;
524     }
525   };
526
527   /*
528    * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
529    * Previous implementation, using synchronous app_control_send_launch_request,
530    * tries to launch the application 3 times, before reporting an error.
531    * New implementation, using app_control_send_launch_request_async makes only one attempt.
532    * If problems, such as failed application start occur, multiple attempts may solve the problem.
533    */
534   auto launch_result =
535       ApplicationUtils::TranslateAppControlError(static_cast<app_control_error_e>(app_control_send_launch_request_async(
536           app_control_ptr.get(), result_callback, reply_callback, launch_app_user_data)));
537
538   if (launch_result.IsError()) {
539     delete launch_app_user_data;
540     AsyncResponse(launch_result, &response);
541   } else {
542     LoggerD("App launched");
543   }
544 }
545
546 namespace {
547
548 PlatformResult TranslateLaunchError(app_control_error_e return_code) {
549   ScopeLogger();
550
551   auto result = ApplicationUtils::TranslateAppControlError(return_code);
552   if (ErrorCode::SECURITY_ERR == result.error_code()) {
553     result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
554   }
555
556   return result;
557 }
558
559 PlatformResult PrepareAppControlForLaunch(const picojson::value& args, app_control_h* app_control) {
560   ScopeLogger();
561
562   const auto& app_id = args.get("id");
563   if (!app_id.is<std::string>()) {
564     return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
565   }
566   const auto app_id_str = app_id.get<std::string>();
567
568   app_control_h tmp_app_control = nullptr;
569   int result = app_control_create(&tmp_app_control);
570   if (APP_CONTROL_ERROR_NONE != result) {
571     LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result));
572     return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
573   }
574
575   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
576       app_control_ptr(tmp_app_control, &app_control_destroy);
577
578   if (!app_id_str.empty()) {
579     LoggerD("app_id: %s", app_id_str.c_str());
580
581     int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str());
582
583     if (APP_CONTROL_ERROR_NONE != ret) {
584       LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
585       return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
586     }
587   }
588
589   *app_control = app_control_ptr.release();
590
591   return PlatformResult(ErrorCode::NO_ERROR);
592 }
593
594 }  // namespace
595 void ApplicationManager::Launch(const picojson::value& args) {
596   ScopeLogger();
597
598   int callback_id = -1;
599   const auto& callback = args.get(kCallbackId);
600   if (callback.is<double>()) {
601     callback_id = static_cast<int>(callback.get<double>());
602   }
603
604   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
605   picojson::object& response_obj = response->get<picojson::object>();
606   response_obj.insert(
607       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
608
609   app_control_h app_control = nullptr;
610   auto prepare_app_control_result = PrepareAppControlForLaunch(args, &app_control);
611   if (prepare_app_control_result.IsError()) {
612     AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
613     return;
614   }
615
616   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
617       app_control_ptr(app_control, &app_control_destroy);
618
619   struct LaunchCallbackData {
620     ApplicationInstance* instance;
621     std::shared_ptr<picojson::value> response;
622   }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response};
623
624   app_control_result_cb result_callback = [](app_control_h launch_request,
625                                              app_control_error_e launch_result, void* user_data) {
626     ScopeLogger("Launch result_callback");
627
628     LaunchCallbackData* callback_data = static_cast<LaunchCallbackData*>(user_data);
629
630     auto result = TranslateLaunchError(launch_result);
631
632     if (result.IsError()) {
633       LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
634     } else {
635       ReportSuccess(callback_data->response->get<picojson::object>());
636     }
637
638     Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
639
640     delete callback_data;
641   };
642
643   /*
644    * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
645    * Previous implementation, using synchronous app_control_send_launch_request,
646    * tries to launch the application 3 times, before reporting an error.
647    * New implementation, using app_control_send_launch_request_async makes only one attempt.
648    * If problems, such as failed application start occur, multiple attempts may solve the problem.
649    */
650   auto launch_result = TranslateLaunchError(static_cast<app_control_error_e>(app_control_send_launch_request_async(
651       app_control_ptr.get(), result_callback, nullptr, launch_user_data)));
652
653   if (launch_result.IsError()) {
654     delete launch_user_data;
655     AsyncResponse(launch_result, &response);
656   } else {
657     LoggerD("App launched");
658   }
659 }
660
661 // internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
662 // public CAPI did not handling APP_CONTROL_ERROR_APP_NOT_FOUND
663 int app_control_foreach_app_matched_internal(app_control_h app_control,
664                                              app_control_app_matched_cb callback, void* user_data) {
665   ScopeLogger();
666   typedef struct {
667     app_control_h app_control;
668     app_control_app_matched_cb callback;
669     void* user_data;
670     bool foreach_break;
671   } foreach_context_launchable_app_t_internal;
672
673   // internal impl of app_control_cb_broker_foreach_app_matched()
674   auto app_control_cb_broker_foreach_app_matched_internal = [](const char* package,
675                                                                void* data) -> int {
676     ScopeLogger(
677         "Entered into asynchronous function, app_control_cb_broker_foreach_app_matched_internal's "
678         "argument");
679     foreach_context_launchable_app_t_internal* foreach_context;
680     app_control_app_matched_cb app_matched_cb;
681
682     if (package == NULL || data == NULL) {
683       LoggerE("APP_CONTROL_ERROR_INVALID_PARAMETER");
684       return -1;
685     }
686
687     foreach_context = (foreach_context_launchable_app_t_internal*)data;
688     if (foreach_context->foreach_break == true) return -1;
689
690     app_matched_cb = foreach_context->callback;
691     if (app_matched_cb != NULL) {
692       bool stop_foreach = false;
693
694       stop_foreach =
695           !app_matched_cb(foreach_context->app_control, package, foreach_context->user_data);
696
697       foreach_context->foreach_break = stop_foreach;
698     }
699
700     return 0;
701   };
702
703   foreach_context_launchable_app_t_internal foreach_context = {.app_control = app_control,
704                                                                .callback = callback,
705                                                                .user_data = user_data,
706                                                                .foreach_break = false};
707
708   bundle* bundle_data = NULL;
709   app_control_to_bundle(app_control, &bundle_data);
710
711   int ret = appsvc_usr_get_list(bundle_data, app_control_cb_broker_foreach_app_matched_internal,
712                                 &foreach_context, getuid());
713
714   if (ret < 0) {
715     switch (ret) {
716       case APPSVC_RET_EINVAL:
717         return APP_CONTROL_ERROR_INVALID_PARAMETER;
718
719       case APPSVC_RET_ENOMATCH:
720         return APP_CONTROL_ERROR_APP_NOT_FOUND;
721
722       default:
723         return APP_CONTROL_ERROR_LAUNCH_FAILED;
724     }
725   }
726
727   return APP_CONTROL_ERROR_NONE;
728 }
729
730 void ApplicationManager::FindAppControl(const picojson::value& args) {
731   ScopeLogger();
732
733   int callback_id = -1;
734   const auto& callback = args.get(kCallbackId);
735   if (callback.is<double>()) {
736     callback_id = static_cast<int>(callback.get<double>());
737   }
738
739   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
740   picojson::object& response_obj = response->get<picojson::object>();
741   response_obj.insert(
742       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
743
744   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
745   const auto& control = args.get("appControl");
746   if (!control.is<picojson::object>()) {
747     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
748     AsyncResponse(result, &response);
749     return;
750   }
751
752   const picojson::object& app_control_obj = control.get<picojson::object>();
753
754   app_control_h app_control = nullptr;
755   result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
756   std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_ptr(
757       app_control, &app_control_destroy);  // automatically release the memory
758
759   if (result.IsError()) {
760     LoggerE("Application control to service failed.");
761     AsyncResponse(result, &response);
762     return;
763   }
764
765   auto find = [app_control_ptr](const std::shared_ptr<picojson::value>& response) -> void {
766     ScopeLogger("Entered into asynchronous function, find");
767     auto app_control_matched = [](app_control_h app_control, const char* appid,
768                                   void* user_data) -> bool {
769       ScopeLogger("Entered into asynchronous function, app_control_matched");
770       if (nullptr == appid) {
771         LoggerD("appid is NULL");
772         return false;
773       }
774
775       pkgmgrinfo_appinfo_h handle;
776       int ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, getuid(), &handle);
777       if (PMINFO_R_OK != ret) {
778         LoggerE("Failed to get appInfo: %d (%s)", ret, get_error_message(ret));
779       } else {
780         picojson::array* array = static_cast<picojson::array*>(user_data);
781         array->push_back(picojson::value(picojson::object()));
782
783         ApplicationUtils::CreateApplicationInformation(handle,
784                                                        &array->back().get<picojson::object>());
785         pkgmgrinfo_appinfo_destroy_appinfo(handle);
786       }
787
788       return true;
789     };
790
791     picojson::object& response_obj = response->get<picojson::object>();
792     auto it_result = response_obj.find("result");
793     picojson::object& result_obj = it_result->second.get<picojson::object>();
794     auto array =
795         result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())));
796
797     int ret = app_control_foreach_app_matched_internal(app_control_ptr.get(), app_control_matched,
798                                                        &array.first->second.get<picojson::array>());
799
800     if (APP_CONTROL_ERROR_NONE != ret) {
801       if (APP_CONTROL_ERROR_APP_NOT_FOUND == ret) {
802         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Matched Application not found"),
803                           &response_obj, ("app_control_foreach_app_matched error: %d (%s)", ret,
804                                           get_error_message(ret)));
805       } else if (APP_CONTROL_ERROR_LAUNCH_FAILED == ret) {
806         LogAndReportError(
807             PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), &response_obj,
808             ("app_control_foreach_app_matched error: %d (%s)", ret, get_error_message(ret)));
809       } else if (APP_CONTROL_ERROR_INVALID_PARAMETER == ret) {
810         LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed"),
811                           &response_obj, ("app_control_foreach_app_matched error: %d (%s)", ret,
812                                           get_error_message(ret)));
813       }
814       // remove copied ApplicationControl from result
815       response_obj.erase(it_result);
816     } else {
817       ReportSuccess(response_obj);
818     }
819   };
820
821   auto find_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
822     ScopeLogger("Entered into asynchronous function, find_response");
823     Instance::PostMessage(&this->instance_, response->serialize().c_str());
824   };
825
826   // prepare result object, we need to do that here, as input parameter is passed to result callback
827   auto ret = response_obj.insert(std::make_pair("result", picojson::value(picojson::object())));
828   // reinsert application control
829   ret.first->second.get<picojson::object>().insert(
830       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   ScopeLogger();
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(picojson::array())))
850             .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(app_context,
861                                                       &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(
873           PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
874           ("app_manager_foreach_app_context error: %d (%s)", ret, get_error_message(ret)));
875     } else {
876       ReportSuccess(result, response_obj);
877     }
878   };
879
880   auto get_apps_context_response =
881       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
882     picojson::object& obj = response->get<picojson::object>();
883     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
884     Instance::PostMessage(&this->instance_, response->serialize().c_str());
885   };
886
887   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
888
889   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_context, get_apps_context_response,
890                                                   data);
891 }
892
893 void ApplicationManager::GetAppContext(const picojson::value& args, picojson::object* out) {
894   ScopeLogger();
895   pid_t pid = 0;
896
897   const auto& context_id = args.get("contextId");
898   if (context_id.is<std::string>()) {
899     try {
900       pid = std::stoi(context_id.get<std::string>());
901     } catch (...) {
902       LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert context id."),
903                         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(
930             PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), out,
931             ("app_manager_get_app_id returned: %d (%s)", ret, get_error_message(ret)));
932         return;
933     }
934   }
935
936   picojson::value result = picojson::value(picojson::object());
937   ApplicationUtils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
938
939   ReportSuccess(result, *out);
940 }
941
942 void ApplicationManager::GetAppsInfo(const picojson::value& args) {
943   ScopeLogger();
944
945   int callback_id = -1;
946   const auto& callback = args.get(kCallbackId);
947   if (callback.is<double>()) {
948     callback_id = static_cast<int>(callback.get<double>());
949   }
950
951   auto get_apps_info = [](const std::shared_ptr<picojson::value>& response) -> void {
952     ScopeLogger("Entered into asynchronous function, get_apps_info");
953     picojson::object& response_obj = response->get<picojson::object>();
954     picojson::value result = picojson::value(picojson::object());
955     picojson::object& result_obj = result.get<picojson::object>();
956     picojson::array& array =
957         result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())))
958             .first->second.get<picojson::array>();
959
960     auto app_info_cb = [](pkgmgrinfo_appinfo_h handle, void* user_data) -> int {
961       ScopeLogger("Entered into asynchronous function, app_info_cb");
962       if (nullptr == user_data) {
963         return -1;
964       }
965
966       picojson::array* array = static_cast<picojson::array*>(user_data);
967       array->push_back(picojson::value(picojson::object()));
968
969       ApplicationUtils::CreateApplicationInformation(handle,
970                                                      &array->back().get<picojson::object>());
971
972       return 0;
973     };
974
975     int ret = pkgmgrinfo_appinfo_get_usr_installed_list(app_info_cb, getuid(), &array);
976
977     if (APP_MANAGER_ERROR_NONE != ret) {
978       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
979                         ("pkgmgrinfo_appinfo_get_usr_installed_list error"));
980     } else {
981       ReportSuccess(result, response_obj);
982     }
983   };
984
985   auto get_apps_info_response =
986       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
987     ScopeLogger("Entered into asynchronous function, get_apps_info_response");
988     picojson::object& obj = response->get<picojson::object>();
989     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
990     Instance::PostMessage(&this->instance_, response->serialize().c_str());
991   };
992
993   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
994
995   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_info, get_apps_info_response, data);
996 }
997
998 void ApplicationManager::GetAppInfo(const std::string& app_id, picojson::object* out) {
999   ScopeLogger();
1000
1001   pkgmgrinfo_appinfo_h handle = nullptr;
1002
1003   if (PMINFO_R_OK != pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1004     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out);
1005     return;
1006   }
1007
1008   picojson::value result = picojson::value(picojson::object());
1009   ApplicationUtils::CreateApplicationInformation(handle, &result.get<picojson::object>());
1010   pkgmgrinfo_appinfo_destroy_appinfo(handle);
1011
1012   ReportSuccess(result, *out);
1013 }
1014
1015 char* ApplicationManager::GetPackageId(const std::string& app_id) {
1016   ScopeLogger();
1017   app_info_h handle;
1018   char* pkg_id = nullptr;
1019
1020   int ret = app_manager_get_app_info(app_id.c_str(), &handle);
1021   if (APP_MANAGER_ERROR_NONE != ret) {
1022     LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
1023     return nullptr;
1024   }
1025
1026   ret = app_info_get_package(handle, &pkg_id);
1027   if (APP_MANAGER_ERROR_NONE != ret) {
1028     LoggerE("Failed to get package id: %d (%s)", ret, get_error_message(ret));
1029     pkg_id = nullptr;
1030   }
1031
1032   ret = app_info_destroy(handle);
1033   if (APP_MANAGER_ERROR_NONE != ret) {
1034     LoggerE("Failed to destroy app info: %d (%s)", ret, get_error_message(ret));
1035   }
1036
1037   return pkg_id;
1038 }
1039
1040 void ApplicationManager::GetAppCerts(const std::string& app_id, picojson::object* out) {
1041   ScopeLogger();
1042
1043   char* package_id = nullptr;
1044
1045   package_id = GetPackageId(app_id);
1046   // automatically release the memory
1047   std::unique_ptr<char, void (*)(void*)> package_id_ptr(package_id, &std::free);
1048
1049   if (!package_id) {
1050     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
1051     return;
1052   }
1053
1054   package_info_h pkg_info = nullptr;
1055   int ret = package_info_create(package_id, &pkg_info);
1056
1057   std::unique_ptr<std::remove_pointer<package_info_h>::type, int (*)(package_info_h)> pkg_info_ptr(
1058       pkg_info, &package_info_destroy);  // automatically release the memory
1059
1060   if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1061     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out,
1062                       ("Failed to get package info: %d (%s)", ret, get_error_message(ret)));
1063     return;
1064   }
1065
1066   auto cert_info_cb = [](package_info_h handle, package_cert_type_e cert_type,
1067                          const char* cert_value, void* user_data) -> bool {
1068     const char* cert_name = nullptr;
1069
1070     switch (cert_type) {
1071       case PACKAGE_INFO_AUTHOR_ROOT_CERT:
1072         cert_name = "AUTHOR_ROOT";
1073         break;
1074       case PACKAGE_INFO_AUTHOR_INTERMEDIATE_CERT:
1075         cert_name = "AUTHOR_INTERMEDIATE";
1076         break;
1077       case PACKAGE_INFO_AUTHOR_SIGNER_CERT:
1078         cert_name = "AUTHOR_SIGNER";
1079         break;
1080       case PACKAGE_INFO_DISTRIBUTOR_ROOT_CERT:
1081         cert_name = "DISTRIBUTOR_ROOT";
1082         break;
1083       case PACKAGE_INFO_DISTRIBUTOR_INTERMEDIATE_CERT:
1084         cert_name = "DISTRIBUTOR_INTERMEDIATE";
1085         break;
1086       case PACKAGE_INFO_DISTRIBUTOR_SIGNER_CERT:
1087         cert_name = "DISTRIBUTOR_SIGNER";
1088         break;
1089       case PACKAGE_INFO_DISTRIBUTOR2_ROOT_CERT:
1090         cert_name = "DISTRIBUTOR2_ROOT";
1091         break;
1092       case PACKAGE_INFO_DISTRIBUTOR2_INTERMEDIATE_CERT:
1093         cert_name = "DISTRIBUTOR2_INTERMEDIATE";
1094         break;
1095       case PACKAGE_INFO_DISTRIBUTOR2_SIGNER_CERT:
1096         cert_name = "DISTRIBUTOR2_SIGNER";
1097         break;
1098       default:
1099         LoggerD("Unknown certificate type: %d", cert_type);
1100         break;
1101     }
1102
1103     picojson::array* array = static_cast<picojson::array*>(user_data);
1104     array->push_back(picojson::value(picojson::object()));
1105
1106     ApplicationUtils::CreateApplicationCertificate(cert_name, cert_value,
1107                                                    &array->back().get<picojson::object>());
1108
1109     return true;
1110   };
1111
1112   picojson::value result = picojson::value(picojson::array());
1113
1114   ret = package_info_foreach_cert_info(pkg_info, cert_info_cb, &result.get<picojson::array>());
1115
1116   if ((PACKAGE_MANAGER_ERROR_NONE != ret) && (PACKAGE_MANAGER_ERROR_IO_ERROR != ret)) {
1117     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificates info."),
1118                       out,
1119                       ("Failed to get certificates info: %d (%s)", ret, get_error_message(ret)));
1120     return;
1121   }
1122
1123   ReportSuccess(result, *out);
1124 }
1125
1126 void ApplicationManager::GetAppSharedUri(const std::string& app_id, picojson::object* out) {
1127   ScopeLogger();
1128   // this implementation assumes that shared/trusted path is the obligatory member of application
1129   // and it is used to extract the parent directory 'shared'
1130   char* path = nullptr;
1131   int ret = app_manager_get_shared_trusted_path(app_id.c_str(), &path);
1132   if (APP_MANAGER_ERROR_NONE != ret) {
1133     // if the application does not exist, there is no need to check "res" directory
1134     if (APP_MANAGER_ERROR_NO_SUCH_APP == ret) {
1135       LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get shared URI."), out);
1136       return;
1137     }
1138
1139     // if the shared_trusted directory is not properly returned, gathering the shared/res path,
1140     // which is the obligatory member. The global path could be different then:
1141     // e.g. instead of path: /opt/usr/home/owner/apps_rw/org.example.basic/shared/
1142     // returned path is:     /opt/usr/globalapps/org.example.basic/shared/
1143     LoggerW(
1144         "app_manager_get_shared_trusted_path failed(), trying "
1145         "app_manager_get_shared_resource_path() to gather path");
1146     int ret = app_manager_get_shared_resource_path(app_id.c_str(), &path);
1147     if (APP_MANAGER_ERROR_NONE != ret) {
1148       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get shared URI."), out);
1149       return;
1150     }
1151   }
1152
1153   std::string path_str = path;
1154   free(path);
1155
1156   std::string shared_path = path_str.substr(0, path_str.rfind("/", path_str.length() - 2));
1157
1158   // checking if path is valid
1159   struct stat stat_res;
1160   if (0 != stat(shared_path.c_str(), &stat_res)) {
1161     LoggerW("Path %s does not exist", shared_path.c_str());
1162     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get shared URI."), out);
1163     return;
1164   }
1165
1166   picojson::value result = picojson::value(kTizenApisFileScheme + shared_path);
1167   ReportSuccess(result, *out);
1168 }
1169
1170 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1171 PlatformResult ApplicationManager::BatteryUsageFilter(const picojson::value& args,
1172                                                       const context_history_filter_h filter,
1173                                                       context_history_data_e* data_type_out) {
1174   ScopeLogger();
1175   int ret = CONTEXT_HISTORY_ERROR_NONE;
1176   int limit = kMaximumBatteryRetrievedObjects;
1177   if (args.contains("limit")) {
1178     limit = static_cast<int>(args.get("limit").get<double>());
1179   }
1180
1181   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1182
1183   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1184     return LogAndCreateResult(
1185         ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1186         ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1187   }
1188
1189   context_history_data_e data_type_in = CONTEXT_HISTORY_RECENT_BATTERY_USAGE;
1190
1191   if (args.contains("days")) {
1192     const int days = static_cast<int>(args.get("days").get<double>());
1193     data_type_in = CONTEXT_HISTORY_BATTERY_USAGE;
1194     ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, days);
1195
1196     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1197       return LogAndCreateResult(
1198           ErrorCode::INVALID_VALUES_ERR, "days given with invalid value.",
1199           ("days given with invalid value: %d (%s)", ret, get_error_message(ret)));
1200     }
1201   }
1202
1203   *data_type_out = data_type_in;
1204
1205   return PlatformResult(ErrorCode::NO_ERROR);
1206 }
1207
1208 PlatformResult ApplicationManager::BatteryUsageAttributes(const context_history_record_h record,
1209                                                           picojson::object* object) {
1210   ScopeLogger();
1211
1212   int ret = CONTEXT_HISTORY_ERROR_NONE;
1213   double amount = 0.0;
1214   char* app_id = nullptr;
1215   SCOPE_EXIT {
1216     free(app_id);
1217   };
1218
1219   ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1220   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1221     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1222                               ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1223   }
1224
1225   ret = context_history_record_get_double(record, CONTEXT_HISTORY_TOTAL_AMOUNT, &amount);
1226   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1227     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get amount.",
1228                               ("Failed to get amount: %d (%s)", ret, get_error_message(ret)));
1229   }
1230
1231   object->insert(std::make_pair("appId", picojson::value(app_id)));
1232   object->insert(std::make_pair("batteryUsage", picojson::value(amount)));
1233
1234   return PlatformResult(ErrorCode::NO_ERROR);
1235 }
1236
1237 PlatformResult ApplicationManager::AppsUsageFilter(const picojson::value& args,
1238                                                    const context_history_filter_h filter,
1239                                                    context_history_data_e* data_type_out) {
1240   ScopeLogger();
1241   int ret = CONTEXT_HISTORY_ERROR_NONE;
1242   int limit = kMaximumAppsRetrievedObjects;
1243   if (args.contains("limit")) {
1244     limit = static_cast<int>(args.get("limit").get<double>());
1245   }
1246
1247   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1248   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1249     return LogAndCreateResult(
1250         ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1251         ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1252   }
1253
1254   context_history_data_e data_type_in = CONTEXT_HISTORY_FREQUENTLY_USED_APP;
1255   if (args.contains("mode") && kAppUsageModeRecently == args.get("mode").get<std::string>()) {
1256     data_type_in = CONTEXT_HISTORY_RECENTLY_USED_APP;
1257   }
1258
1259   int time_span = kDefaultPeriodOfTime;
1260   const picojson::object& JS_filter = args.get("filter").get<picojson::object>();
1261   auto time_span_iter = JS_filter.find("timeSpan");
1262   if (JS_filter.end() != time_span_iter || (JS_filter.end() == JS_filter.find("startTime") &&
1263                                             JS_filter.end() == JS_filter.find("endTime"))) {
1264     // In the second case, we treat the filter object just like an empty object.
1265     // The default value of filter will be used instead.
1266     if (JS_filter.end() != time_span_iter) {
1267       time_span = static_cast<int>(time_span_iter->second.get<double>());
1268     }
1269     ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, time_span);
1270     // context_history_filter_set_int may return only success or
1271     // CONTEXT_HISTORY_ERROR_INVALID_PARAMETER
1272     // Although this should never happen, it's better to check ret's value
1273     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1274       return LogAndCreateResult(ErrorCode::ABORT_ERR,
1275                                 "Error while setting the default TIME_SPAN value.",
1276                                 ("Error while setting the default TIME_SPAN value: %d (%s)", ret,
1277                                  get_error_message(ret)));
1278     }
1279   } else {
1280     auto start_time_iter = JS_filter.find("startTime");
1281     auto end_time_iter = JS_filter.find("endTime");
1282     if (start_time_iter != JS_filter.end()) {
1283       int start_time = static_cast<int>(start_time_iter->second.get<double>());
1284       ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_START_TIME, start_time);
1285       if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1286         return LogAndCreateResult(
1287             ErrorCode::INVALID_VALUES_ERR, "startTime given with invalid value.",
1288             ("startTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1289       }
1290     }
1291     if (end_time_iter != JS_filter.end()) {
1292       int end_time = static_cast<int>(end_time_iter->second.get<double>());
1293       ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_END_TIME, end_time);
1294       if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1295         return LogAndCreateResult(
1296             ErrorCode::INVALID_VALUES_ERR, "endTime given with invalid value.",
1297             ("endTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1298       }
1299     }
1300   }
1301
1302   *data_type_out = data_type_in;
1303
1304   return PlatformResult(ErrorCode::NO_ERROR);
1305 }
1306
1307 PlatformResult ApplicationManager::AppsUsageAttributes(const context_history_record_h record,
1308                                                        picojson::object* object) {
1309   ScopeLogger();
1310
1311   int ret = CONTEXT_HISTORY_ERROR_NONE;
1312   int total_count = 0;
1313   int total_duration = 0;
1314   int last_time = 0;
1315   char* app_id = nullptr;
1316   SCOPE_EXIT {
1317     free(app_id);
1318   };
1319
1320   ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1321   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1322     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1323                               ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1324   }
1325
1326   ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_COUNT, &total_count);
1327   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1328     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get total count.",
1329                               ("Failed to get total count: %d (%s)", ret, get_error_message(ret)));
1330   }
1331
1332   ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_DURATION, &total_duration);
1333   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1334     return LogAndCreateResult(
1335         ErrorCode::ABORT_ERR, "Failed to get total duration.",
1336         ("Failed to get total duration: %d (%s)", ret, get_error_message(ret)));
1337   }
1338
1339   ret = context_history_record_get_int(record, CONTEXT_HISTORY_LAST_TIME, &last_time);
1340   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1341     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get last time.",
1342                               ("Failed to get last time: %d (%s)", ret, get_error_message(ret)));
1343   }
1344
1345   object->insert(std::make_pair("appId", picojson::value(app_id)));
1346   object->insert(std::make_pair("totalCount", picojson::value(static_cast<double>(total_count))));
1347   object->insert(
1348       std::make_pair("totalDuration", picojson::value(static_cast<double>(total_duration))));
1349   object->insert(std::make_pair("lastTime", picojson::value(static_cast<double>(last_time))));
1350
1351   return PlatformResult(ErrorCode::NO_ERROR);
1352 }
1353 #endif
1354
1355 void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojson::object* out) {
1356   ScopeLogger();
1357
1358 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1359   int callback_id = -1;
1360   const auto& callback = args.get(kCallbackId);
1361   if (callback.is<double>()) {
1362     callback_id = static_cast<int>(callback.get<double>());
1363   }
1364
1365   auto get_battery_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1366     ScopeLogger();
1367     PlatformResult result = ApplicationManager::GetContextHistory(
1368         args, &response.get()->get<picojson::object>(), &ApplicationManager::BatteryUsageFilter,
1369         &ApplicationManager::BatteryUsageAttributes);
1370     if (!result) {
1371       LogAndReportError(result, &response.get()->get<picojson::object>());
1372     }
1373   };
1374
1375   auto get_battery_usage_response =
1376       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1377     ScopeLogger();
1378     picojson::object& obj = response->get<picojson::object>();
1379     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1380     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1381   };
1382
1383   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1384
1385   TaskQueue::GetInstance().Queue<picojson::value>(get_battery_usage, get_battery_usage_response,
1386                                                   data);
1387 #else
1388   LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
1389                                    "This feature is not supported on this profile."),
1390                     out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1391 #endif
1392 }
1393
1394 void ApplicationManager::GetAppsUsageInfo(const picojson::value& args, picojson::object* out) {
1395   ScopeLogger();
1396
1397 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1398   int callback_id = static_cast<int>(args.get(kCallbackId).get<double>());
1399
1400   auto get_apps_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1401     ScopeLogger();
1402     PlatformResult result = ApplicationManager::GetContextHistory(
1403         args, &response.get()->get<picojson::object>(), &ApplicationManager::AppsUsageFilter,
1404         &ApplicationManager::AppsUsageAttributes);
1405     if (!result) {
1406       LogAndReportError(result, &response.get()->get<picojson::object>());
1407     }
1408   };
1409
1410   auto get_apps_usage_response =
1411       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1412     ScopeLogger();
1413     picojson::object& obj = response->get<picojson::object>();
1414     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1415     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1416   };
1417
1418   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1419
1420   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_usage, get_apps_usage_response, data);
1421 #else
1422   LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
1423                                    "This feature is not supported on this profile."),
1424                     out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1425 #endif
1426 }
1427
1428 void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) {
1429   ScopeLogger();
1430
1431   pkgmgrinfo_appinfo_h handle = nullptr;
1432
1433   int ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle);
1434   std::unique_ptr<std::remove_pointer<pkgmgrinfo_appinfo_h>::type, int (*)(pkgmgrinfo_appinfo_h)>
1435       pkg_info_ptr(handle,
1436                    &pkgmgrinfo_appinfo_destroy_appinfo);  // automatically release the memory
1437
1438   if (PMINFO_R_OK != ret) {
1439     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out,
1440                       ("Failed to get app info: %d (%s)", ret, get_error_message(ret)));
1441     return;
1442   }
1443
1444   auto meta_data_cb = [](const char* meta_key, const char* meta_value, void* user_data) -> int {
1445     if (nullptr == meta_key || nullptr == meta_value) {
1446       LoggerE("meta_key or meta_value is null");
1447       return 0;
1448     }
1449
1450     picojson::array* array = static_cast<picojson::array*>(user_data);
1451     array->push_back(picojson::value(picojson::object()));
1452
1453     ApplicationUtils::CreateApplicationMetaData(meta_key, meta_value,
1454                                                 &array->back().get<picojson::object>());
1455     return 0;
1456   };
1457
1458   picojson::value result = picojson::value(picojson::array());
1459   ret = pkgmgrinfo_appinfo_foreach_metadata(handle, meta_data_cb, &result.get<picojson::array>());
1460
1461   if (PMINFO_R_OK != ret) {
1462     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get metadata."), out,
1463                       ("Failed to get metadata: %d (%s)", ret, get_error_message(ret)));
1464     return;
1465   }
1466
1467   ReportSuccess(result, *out);
1468 }
1469
1470 class ApplicationListChangedBroker {
1471  public:
1472   ApplicationListChangedBroker() : event_type_() {
1473   }
1474   enum class Event {
1475     kInstalled,
1476     kUpdated,
1477     kUninstalled,
1478   };
1479
1480   static int ClientStatusListener(unsigned int target_uid, int id, const char* type,
1481                                   const char* package, const char* key, const char* val,
1482                                   const void* msg, void* data) {
1483     ScopeLogger();
1484     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1485
1486     if (0 == strcasecmp(key, kStartKey)) {
1487       that->HandleStart(val, package);
1488     } else if (0 == strcasecmp(key, kEndKey) && 0 == strcasecmp(val, kOkValue)) {
1489       that->HandleEnd(package);
1490     } else {
1491       LoggerD("Ignored key: %s", key);
1492     }
1493
1494     return 0;
1495   }
1496
1497   static int AppUninstallListener(uid_t target_uid, int id, const char* type, const char* package,
1498                                   const char* key, const char* val, const void* msg, void* data) {
1499     ScopeLogger();
1500
1501     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1502
1503     if (0 == strcasecmp(key, kStartKey)) {
1504       that->HandleUninstallStart();
1505     } else if (0 == strcasecmp(key, kAppidKey)) {
1506       that->AddUninstalledAppId(val);
1507     } else if (0 == strcasecmp(key, kEndKey)) {
1508       that->HandleUninstallEnd();
1509     } else {
1510       LoggerD("Ignored key: %s", key);
1511     }
1512
1513     return 0;
1514   }
1515
1516   void AddApplicationInstance(ApplicationInstance* app_instance) {
1517     ScopeLogger();
1518     app_instance_list_.push_back(app_instance);
1519   }
1520
1521   void RemoveApplicationInstance(ApplicationInstance* app_instance) {
1522     ScopeLogger();
1523     for (auto it = app_instance_list_.begin(); it != app_instance_list_.end(); it++) {
1524       if (*it == app_instance) {
1525         app_instance_list_.erase(it);
1526         return;
1527       }
1528     }
1529   }
1530
1531  private:
1532   void HandleStart(const char* event_type, const char* package) {
1533     ScopeLogger();
1534     app_list_.clear();
1535     set_event_type(event_type);
1536   }
1537
1538   void HandleEnd(const char* package) {
1539     ScopeLogger();
1540
1541     if (Event::kUninstalled == event_type_) {
1542       return;
1543     }
1544
1545     GetApplicationIdsFromPackage(package);
1546
1547     for (auto& app_id : app_list_) {
1548       picojson::value value = picojson::value(picojson::object());
1549       picojson::object& data_obj = value.get<picojson::object>();
1550
1551       switch (event_type_) {
1552         case Event::kInstalled:
1553           data_obj.insert(std::make_pair(kAction, picojson::value(kOnInstalled)));
1554           break;
1555
1556         case Event::kUpdated:
1557           data_obj.insert(std::make_pair(kAction, picojson::value(kOnUpdated)));
1558           break;
1559         case Event::kUninstalled:
1560           LoggerD("Uninstalled called");
1561           break;
1562       }
1563
1564       switch (event_type_) {
1565         case Event::kInstalled:
1566         case Event::kUpdated: {
1567           pkgmgrinfo_appinfo_h handle = nullptr;
1568           if (PMINFO_R_OK !=
1569               pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1570             LoggerE("Failed to get application information handle.");
1571             continue;
1572           }
1573           auto info = data_obj.insert(std::make_pair(kData, picojson::value(picojson::object())));
1574           ApplicationUtils::CreateApplicationInformation(
1575               handle, &info.first->second.get<picojson::object>());
1576           pkgmgrinfo_appinfo_destroy_appinfo(handle);
1577         } break;
1578         case Event::kUninstalled:
1579           LoggerD("Uninstalled called");
1580           break;
1581       }
1582
1583       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1584
1585       for (auto instance : app_instance_list_) {
1586         Instance::PostMessage(instance, value.serialize().c_str());
1587       }
1588     }
1589   }
1590
1591   void GetApplicationIdsFromPackage(const char* package) {
1592     ScopeLogger();
1593     package_info_h package_info = nullptr;
1594
1595     int ret = package_info_create(package, &package_info);
1596     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1597       LoggerE("Failed to create package info: %d (%s)", ret, get_error_message(ret));
1598       return;
1599     }
1600
1601     ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_ALLAPP,
1602                                                 ApplicationIdCallback, 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     ScopeLogger();
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, const char* app_id,
1625                                     void* user_data) {
1626     ScopeLogger();
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     ScopeLogger();
1635     app_list_.clear();
1636     set_event_type(kUninstallEvent);
1637   }
1638
1639   void AddUninstalledAppId(const char* app_id) {
1640     ScopeLogger();
1641     if (nullptr != app_id) {
1642       app_list_.push_back(app_id);
1643     }
1644   }
1645
1646   void HandleUninstallEnd() {
1647     ScopeLogger();
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   ScopeLogger();
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."),
1691                         out);
1692       return;
1693     }
1694
1695 #define CHECK_APPLICATION_EVENT_ERROR(result, function_name)                                \
1696   if (PKGMGR_R_OK > result) {                                                               \
1697     StopAppInfoEventListener();                                                             \
1698     LogAndReportError(                                                                      \
1699         PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."), out,        \
1700         ("Function %s failed: %s (%d)", function_name, get_error_message(result), result)); \
1701     return;                                                                                 \
1702   }
1703
1704     g_application_list_changed_broker.AddApplicationInstance(&instance_);
1705
1706     int result = pkgmgr_client_set_status_type(
1707         pkgmgr_client_handle_,
1708         PACKAGE_MANAGER_STATUS_TYPE_INSTALL | PACKAGE_MANAGER_STATUS_TYPE_UPGRADE);
1709     CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_set_status_type")
1710
1711     result = pkgmgr_client_set_status_type(pkgmgr_client_uninstall_handle_,
1712                                            PACKAGE_MANAGER_STATUS_TYPE_UNINSTALL);
1713     CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_set_status_type")
1714
1715     result = pkgmgr_client_listen_status(pkgmgr_client_handle_,
1716                                          ApplicationListChangedBroker::ClientStatusListener,
1717                                          &g_application_list_changed_broker);
1718     CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_listen_status")
1719
1720     result = pkgmgr_client_listen_status(pkgmgr_client_uninstall_handle_,
1721                                          ApplicationListChangedBroker::AppUninstallListener,
1722                                          &g_application_list_changed_broker);
1723     CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_listen_status")
1724
1725 #undef CHECK_APPLICATION_EVENT_ERROR
1726   } else {
1727     LoggerD("Broker callback is already registered.");
1728   }
1729
1730   ReportSuccess(*out);
1731 }
1732
1733 void ApplicationManager::StopAppInfoEventListener() {
1734   ScopeLogger();
1735
1736   if (nullptr != pkgmgr_client_handle_ || nullptr != pkgmgr_client_uninstall_handle_) {
1737     if (nullptr != pkgmgr_client_handle_) {
1738       pkgmgr_client_free(pkgmgr_client_handle_);
1739       pkgmgr_client_handle_ = nullptr;
1740     }
1741     if (nullptr != pkgmgr_client_uninstall_handle_) {
1742       pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1743       pkgmgr_client_uninstall_handle_ = nullptr;
1744     }
1745     g_application_list_changed_broker.RemoveApplicationInstance(&instance_);
1746   } else {
1747     LoggerD("Broker callback is already unregistered.");
1748   }
1749 }
1750
1751 void ApplicationManager::GetApplicationInformationSize(const picojson::value& args,
1752                                                        picojson::object* out) {
1753   ScopeLogger();
1754
1755   const auto& package_id = args.get("packageId");
1756   if (!package_id.is<std::string>()) {
1757     LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
1758                       out);
1759     return;
1760   }
1761
1762   const std::string& package_id_str = package_id.get<std::string>();
1763
1764   // get installed size from package server (to solve smack issue)
1765   pkgmgr_client* pc = pkgmgr_client_new(PC_REQUEST);
1766   int size = -1;
1767
1768   if (nullptr == pc) {
1769     LoggerE("Failed to create pkgmgr client");
1770   } else {
1771     size = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_TOTAL_SIZE, pc, NULL,
1772                                          package_id_str.c_str(), NULL, NULL, NULL);
1773
1774     if (size < 0) {
1775       LoggerE("Failed to get installed size: %d (%s)", size, get_error_message(size));
1776     }
1777
1778     pkgmgr_client_free(pc);
1779   }
1780
1781   picojson::value result = picojson::value(picojson::object());
1782   picojson::object& result_obj = result.get<picojson::object>();
1783   result_obj.insert(std::make_pair("size", picojson::value(static_cast<double>(size))));
1784
1785   ReportSuccess(result, *out);
1786 }
1787
1788 void ApplicationManager::BroadcastEventHelper(const picojson::value& args, picojson::object& out,
1789                                               bool trusted) {
1790   ScopeLogger();
1791
1792   int ret;
1793   std::string event_str = args.get("name").get<std::string>();
1794   const char* event_name = event_str.c_str();
1795
1796   bundle* data = bundle_create();
1797   SCOPE_EXIT {
1798     bundle_free(data);
1799   };
1800
1801   ret = bundle_add(data, "data", args.get("data").serialize().c_str());
1802
1803   if (ret != EVENT_ERROR_NONE) {
1804     LoggerE("bundle_add failed, error: %d (%s)", ret, get_error_message(ret));
1805     ReportError(out);
1806     return;
1807   }
1808
1809   if (trusted) {
1810     ret = event_publish_trusted_app_event(event_name, data);
1811   } else {
1812     ret = event_publish_app_event(event_name, data);
1813   }
1814
1815   if (ret == EVENT_ERROR_NONE) {
1816     ReportSuccess(out);
1817   } else {
1818     LoggerE("event_publish_app_event failed, error: %d (%s)", ret, get_error_message(ret));
1819     ReportError(out);
1820   }
1821 }
1822
1823 void ApplicationManager::OnEvent(const char* event_name, bundle* event_data, void* user_data) {
1824   ScopeLogger("Event name is: '%s'", event_name);
1825
1826   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1827
1828   if (!manager->event_callback_) {
1829     LoggerD("No event listener registered, skipping.");
1830     return;
1831   }
1832
1833   picojson::value event = picojson::value(picojson::object());
1834   picojson::object& event_o = event.get<picojson::object>();
1835
1836   int ret;
1837   char* val = nullptr;
1838
1839   if (event_map_.count(event_name)) {  // system event
1840     const std::string& key = event_map_.at(event_name);
1841     std::string state = "true";
1842     if (key != "") {
1843       ret = bundle_get_str(event_data, key.c_str(), &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       state = std::string(val);
1850     }
1851
1852     LoggerD("State is %s", state.c_str());
1853     event_o["value"] = picojson::value(state);
1854
1855   } else {  // user event
1856     ret = bundle_get_str(event_data, "data", &val);
1857     if (EVENT_ERROR_NONE != ret) {
1858       LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1859       return;
1860     }
1861
1862     picojson::value data;
1863     std::string err;
1864     picojson::parse(data, val, val + strlen(val), &err);
1865     if (!err.empty()) {
1866       LoggerE("Failed to parse bundle data: %s", err.c_str());
1867       return;
1868     }
1869
1870     event_o["data"] = data;
1871   }
1872
1873   LoggerD("event_name is: %s", event_name);
1874   event_o["name"] = picojson::value(event_name);
1875
1876   manager->event_callback_(&event);
1877 }
1878
1879 PlatformResult ApplicationManager::StartEventListener(const std::string& event_name,
1880                                                       const JsonCallback& callback) {
1881   ScopeLogger();
1882
1883   int ret;
1884   event_handler_h event_handler;
1885
1886   ret = event_add_event_handler(event_name.c_str(), OnEvent, this, &event_handler);
1887   LoggerD("event_add_event_handler() result: %d (%s)", ret, get_error_message(ret));
1888   if (EVENT_ERROR_PERMISSION_DENIED == ret) {
1889     return LogAndCreateResult(ErrorCode::SECURITY_ERR, "The privilege is required",
1890                               ("event_add_event_handler failed, error: %d", ret));
1891   } else if (EVENT_ERROR_NONE != ret) {
1892     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error setting event listener",
1893                               ("event_add_event_handler failed, error: %d", ret));
1894   }
1895
1896   event_handler_map_[event_name] = event_handler;
1897
1898   event_callback_ = callback;
1899   LoggerD("event_add_event_handler success");
1900   return PlatformResult(ErrorCode::NO_ERROR);
1901 }
1902
1903 void ApplicationManager::StopEventListener(const std::string& event_name) {
1904   ScopeLogger();
1905
1906   int ret;
1907   event_handler_h event_handler;
1908
1909   if (event_handler_map_.find(event_name) != event_handler_map_.end()) {
1910     event_handler = event_handler_map_[event_name];
1911
1912     ret = event_remove_event_handler(event_handler);
1913     if (EVENT_ERROR_NONE != ret) {
1914       LoggerE("event_remove_event_handler failed, error: %d (%s)", ret, get_error_message(ret));
1915       return;
1916     }
1917
1918     event_handler_map_.erase(event_name);
1919   }
1920 }
1921
1922 void ApplicationManager::OnStatusEvent(const char* type, const char* app_id,
1923                                        app_manager_event_type_e event_type,
1924                                        app_manager_event_state_e event_state,
1925                                        app_manager_event_h handle, void* user_data) {
1926   ScopeLogger();
1927
1928   if (APP_MANAGER_EVENT_STATE_COMPLETED != event_state) {
1929     LoggerD("State different from completed");
1930     return;
1931   }
1932
1933   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1934
1935   if (!manager || !manager->status_callback_) {
1936     LoggerD("No event listener registered, skipping.");
1937     return;
1938   }
1939
1940   bool status_type;
1941   switch (event_type) {
1942     case APP_MANAGER_EVENT_ENABLE_APP:
1943       status_type = true;
1944       break;
1945     case APP_MANAGER_EVENT_DISABLE_APP:
1946       status_type = false;
1947       break;
1948     default:
1949       LoggerD("Uknown status type skipping.");
1950       return;
1951   }
1952
1953   picojson::value event = picojson::value(picojson::object());
1954   picojson::object& event_o = event.get<picojson::object>();
1955
1956   event_o[kStatusType] = picojson::value(status_type);
1957   event_o[kAppId] = picojson::value(app_id);
1958   event_o[kListenerId] = picojson::value(kAppStatusChangeListener);
1959
1960   manager->status_callback_(&event);
1961 }
1962
1963 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1964 PlatformResult ApplicationManager::GetContextHistory(
1965     const picojson::value& args, picojson::object* out,
1966     common::PlatformResult (*modify_filter_cb)(const picojson::value&,
1967                                                const context_history_filter_h,
1968                                                context_history_data_e* data_type),
1969     common::PlatformResult (*add_attributes_to_object)(const context_history_record_h,
1970                                                        picojson::object*)) {
1971   ScopeLogger();
1972   context_history_list_h list = nullptr;
1973   context_history_h handle = nullptr;
1974   context_history_filter_h filter = nullptr;
1975
1976   SCOPE_EXIT {
1977     context_history_list_destroy(list);
1978     context_history_destroy(handle);
1979     context_history_filter_destroy(filter);
1980   };
1981
1982   int ret = context_history_create(&handle);
1983   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1984     return LogAndCreateResult(
1985         ErrorCode::ABORT_ERR, "Failed to create context handle.",
1986         ("Failed to create context handle: %d (%s)", ret, get_error_message(ret)));
1987   }
1988
1989   ret = context_history_filter_create(&filter);
1990   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1991     return LogAndCreateResult(
1992         ErrorCode::ABORT_ERR, "Failed to create filter handle.",
1993         ("Failed to create filter handle: %d (%s)", ret, get_error_message(ret)));
1994   }
1995
1996   context_history_data_e data_type;
1997
1998   PlatformResult result = modify_filter_cb(args, filter, &data_type);
1999   if (!result) {
2000     return result;
2001   }
2002
2003   picojson::value result_array = picojson::value(picojson::array());
2004   picojson::array& array_obj = result_array.get<picojson::array>();
2005
2006   ret = context_history_get_list(handle, data_type, filter, &list);
2007   if (CONTEXT_HISTORY_ERROR_NO_DATA == ret) {
2008     ReportSuccess(result_array, *out);
2009     return PlatformResult(ErrorCode::NO_ERROR);
2010   } else if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2011     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list.",
2012                               ("Failed to get list: %d (%s)", ret, get_error_message(ret)));
2013   }
2014
2015   int size = 0;
2016   ret = context_history_list_get_count(list, &size);
2017   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2018     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list size.",
2019                               ("Failed to get list size: %d (%s)", ret, get_error_message(ret)));
2020   }
2021
2022   array_obj.resize(size, picojson::value(picojson::object()));
2023
2024   for (int i = 0; i < size; ++i) {
2025     context_history_record_h record = nullptr;
2026     SCOPE_EXIT {
2027       context_history_record_destroy(record);
2028     };
2029
2030     ret = context_history_list_get_current(list, &record);
2031     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2032       return LogAndCreateResult(
2033           ErrorCode::ABORT_ERR, "Failed to get current record.",
2034           ("Failed to get current record: %d (%s)", ret, get_error_message(ret)));
2035     }
2036
2037     result = add_attributes_to_object(record, &array_obj[i].get<picojson::object>());
2038     if (!result) {
2039       return result;
2040     }
2041
2042     ret = context_history_list_move_next(list);
2043     if (CONTEXT_HISTORY_ERROR_NONE != ret && CONTEXT_HISTORY_ERROR_NO_DATA != ret) {
2044       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to move iterator.",
2045                                 ("Failed to move iterator: %d (%s)", ret, get_error_message(ret)));
2046     }
2047   }
2048
2049   ReportSuccess(result_array, *out);
2050   return PlatformResult(ErrorCode::NO_ERROR);
2051 }
2052 #endif
2053
2054 PlatformResult ApplicationManager::StartStatusListener(const JsonCallback& callback) {
2055   ScopeLogger();
2056
2057   int ret = APP_MANAGER_ERROR_NONE;
2058
2059   if (!app_status_handle_) {
2060     ret = app_manager_event_create(&app_status_handle_);
2061     if (APP_MANAGER_ERROR_NONE != ret) {
2062       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while creating event handle",
2063                                 ("app_manager_event_create failed, error: %d", ret));
2064     }
2065
2066     ret = app_manager_event_set_status(app_status_handle_, APP_MANAGER_EVENT_STATUS_TYPE_ALL);
2067     if (APP_MANAGER_ERROR_NONE != ret) {
2068       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status type",
2069                                 ("app_manager_event_set_status failed, error: %d", ret));
2070     }
2071   }
2072
2073   status_callback_ = callback;
2074   ret = app_manager_set_event_cb(app_status_handle_, OnStatusEvent, this);
2075   if (APP_MANAGER_ERROR_NONE != ret) {
2076     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status listener",
2077                               ("app_manager_set_event_cb failed, error: %d", ret));
2078   }
2079
2080   return PlatformResult(ErrorCode::NO_ERROR);
2081 }
2082
2083 PlatformResult ApplicationManager::StopStatusChangeListener() {
2084   ScopeLogger();
2085
2086   if (app_status_handle_) {
2087     int ret = app_manager_unset_event_cb(app_status_handle_);
2088     if (APP_MANAGER_ERROR_NONE != ret) {
2089       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while removing status listener",
2090                                 ("app_manager_unset_event_cb failed, error: %d", ret));
2091     }
2092   }
2093
2094   return PlatformResult(ErrorCode::NO_ERROR);
2095 }
2096
2097 }  // namespace application
2098 }  // namespace extension