tizen 2.3.1 release
[framework/web/wearable/wrt-plugins-tizen.git] / src / Application / AppManagerWrapper.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include "AppManagerWrapper.h"
19 #include "ApplicationUtil.h"
20 #include <Commons/Exception.h>
21 #include <Commons/Regex.h>
22
23 // To get package id from appId
24 #include <package_manager.h>
25 #include <TimeTracer.h>
26
27 #include <Logger.h>
28
29 namespace DeviceAPI {
30 namespace Application {
31
32 using namespace std;
33 using namespace WrtDeviceApis::Commons;
34
35
36 AppManagerWrapper::AppManagerWrapper() :
37     m_manager_handle(NULL),
38     m_watchIdAcc(0)
39 {
40     LOGD("Entered");
41 }
42
43 AppManagerWrapper::~AppManagerWrapper()
44 {
45     LOGD("Entered");
46     if (m_manager_handle != NULL)
47     {
48         unregisterAppListChangedCallbacks();
49     }
50 }
51
52 void AppManagerWrapper::registerAppListChangedCallbacks(
53         IAppManagerAppListChangedCallbacks *callbacks)
54 {
55     LOGD("Entered");
56     if (callbacks == NULL)
57     {
58         LOGE("callback cannot be set to NULL.");
59         return;
60     }
61
62     if (!m_manager_handle)
63     {
64         registerAppListChangedCallbacks();
65     }
66
67     m_callbacks.insert(callbacks);
68 }
69
70 void AppManagerWrapper::unregisterAppListChangedCallbacks(
71         IAppManagerAppListChangedCallbacks *callbacks)
72 {
73     LOGD("Entered");
74     if (callbacks == NULL)
75     {
76         LOGE("callback cannot be set to NULL.");
77         return;
78     }
79
80     if (m_callbacks.size() == 0)
81     {
82         LOGE("No callbacks are registered.");
83         return;
84     }
85
86     AppListChangedCallbacksSet::iterator iter = m_callbacks.find(callbacks);
87     if (iter == m_callbacks.end())
88     {
89         LOGE("Callback is not registered.");
90         return;
91     }
92
93     m_callbacks.erase(iter);
94
95     if (m_callbacks.size() == 0)
96     {
97         unregisterAppListChangedCallbacks();
98     }
99 }
100
101
102 long AppManagerWrapper::getWatchIdAndInc()
103 {
104     LOGD("Entered");
105     return ++m_watchIdAcc;
106 }
107
108
109 bool AppManagerWrapper::app_callback(package_info_app_component_type_e comp_type,
110         const char *app_id,
111         void *user_data)
112 {
113     LOGD("Entered");
114     if (app_id == NULL) {
115         LOGE("Callback is called. but no package name is passed. skip this request");
116         return true;
117     }
118
119     if (user_data == NULL) {
120         LOGE("user data is not exist. skip this request");
121         return true;
122     }
123
124     AppManagerWrapper *appManager = (AppManagerWrapper *)user_data;
125     appManager->applist.push_back(app_id);
126
127     return true;
128 }
129
130 void AppManagerWrapper::appListChangedCallback(app_info_event_e event_type,
131         const char *pkgId,
132         void *user_data)
133 {
134     LOGD("Entered");
135     if (user_data == NULL) {
136         LOGE("user data is not exist. skip this request");
137         return;
138     }
139
140     AppManagerWrapper *appManager = (AppManagerWrapper *)user_data;
141
142     if (event_type == APP_INFO_EVENT_UNINSTALLED) {
143         for (size_t i = 0; i < appManager->applist.size(); i++) {
144             appListAppUninstalled(appManager->applist.at(i).c_str());
145         }
146     } else {
147         package_info_h package_info;
148
149         int ret = package_info_create(pkgId, &package_info);
150         if (PACKAGE_MANAGER_ERROR_NONE != ret) {
151             LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
152                     "package_info_create()",
153                     ApplicationUtil::getApplicationPackageManagerMessage).c_str());
154             return;
155         }
156
157         ret = package_info_foreach_app_from_package(package_info,
158                 PACKAGE_INFO_ALLAPP,
159                 app_callback, user_data);
160         if (PACKAGE_MANAGER_ERROR_NONE != ret) {
161             LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
162                     "package_info_foreach_app_from_package()",
163                     ApplicationUtil::getApplicationPackageManagerMessage).c_str());
164
165             ret = package_info_destroy(package_info);
166             if (PACKAGE_MANAGER_ERROR_NONE != ret) {
167                 LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
168                         "package_info_destroy()",
169                         ApplicationUtil::getApplicationPackageManagerMessage).c_str());
170             }
171             return;
172         }
173
174         ret = package_info_destroy(package_info);
175         if (PACKAGE_MANAGER_ERROR_NONE != ret) {
176             LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
177                     "package_info_destroy()",
178                     ApplicationUtil::getApplicationPackageManagerMessage).c_str());
179         }
180
181         for (size_t i = 0; i < appManager->applist.size(); i++) {
182             switch(event_type)
183             {
184                 case APP_INFO_EVENT_INSTALLED:
185                     appListAppInstalled(appManager->applist.at(i).c_str());
186                     break;
187                 case APP_INFO_EVENT_UPDATED:
188                     appListAppUpdated(appManager->applist.at(i).c_str());
189                     break;
190                 default:
191                     LOGE("app_manager listener gave wrong event_type : %d", event_type);
192                     break;
193             }
194         }
195     }
196
197     // clean-up applist
198     appManager->applist.clear();
199 }
200
201
202 void AppManagerWrapper::appListAppInstalled(const char *appId)
203 {
204     LOGD("Entered");
205     AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
206     for (; iter != m_callbacks.end(); iter++)
207     {
208         (*iter)->onAppManagerEventInstalled(appId);
209     }
210 }
211
212 void AppManagerWrapper::appListAppUninstalled(const char *appId)
213 {
214     LOGD("Entered");
215     AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
216     for (; iter != m_callbacks.end(); iter++)
217     {
218         (*iter)->onAppManagerEventUninstalled(appId);
219     }
220 }
221
222 void AppManagerWrapper::appListAppUpdated(const char *appId)
223 {
224     LOGD("Entered");
225     AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
226     for (; iter != m_callbacks.end(); iter++)
227     {
228         (*iter)->onAppManagerEventUpdated(appId);
229     }
230 }
231
232
233 int AppManagerWrapper::app_list_changed_cb_broker(int id,
234         const char *type,
235         const char *package,
236         const char *key,
237         const char *val,
238         const void *msg,
239         void *data)
240 {
241     LOGD("Entered");
242     static app_info_event_e event_type;
243
244     if (!strcasecmp(key, "start")) {
245         if (!strcasecmp(val, "install")) {
246             event_type = APP_INFO_EVENT_INSTALLED;
247         } else if (!strcasecmp(val, "uninstall"))    {
248             // After uninstallation, we cannot get app ids from package name.
249             // So, we have to store app ids which is included to target package.
250             package_info_h package_info;
251
252             int ret = package_info_create(package, &package_info);
253             if (PACKAGE_MANAGER_ERROR_NONE != ret) {
254                 LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
255                         "package_info_create()",
256                         ApplicationUtil::getApplicationPackageManagerMessage).c_str());
257             }
258
259             ret = package_info_foreach_app_from_package(package_info,
260                     PACKAGE_INFO_ALLAPP, app_callback, data);
261             if (PACKAGE_MANAGER_ERROR_NONE != ret) {
262                 LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
263                         "package_info_foreach_app_from_package()",
264                         ApplicationUtil::getApplicationPackageManagerMessage).c_str());
265             }
266
267             ret = package_info_destroy(package_info);
268             if (PACKAGE_MANAGER_ERROR_NONE != ret) {
269                 LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
270                         "package_info_destroy()",
271                         ApplicationUtil::getApplicationPackageManagerMessage).c_str());
272             }
273             event_type = APP_INFO_EVENT_UNINSTALLED;
274         } else if (!strcasecmp(val, "update")) {
275             event_type = APP_INFO_EVENT_UPDATED;
276         }
277     } else if (!strcasecmp(key, "end") && !strcasecmp(val, "ok"))    {
278         if (event_type >= 0) {
279             if (data != NULL) {
280                 AppManagerWrapper *appManager = (AppManagerWrapper *)data;
281                 appManager->appListChangedCallback(event_type, package, data);
282             }
283         }
284     }
285
286     return APP_MANAGER_ERROR_NONE;
287 }
288
289
290 void AppManagerWrapper::registerAppListChangedCallbacks()
291 {
292     LOGD("Entered");
293     if (m_manager_handle != NULL) {
294         LOGW("Callback is already registered.");
295         return;
296     }
297
298     TIME_TRACER_ITEM_BEGIN("(addAppInfoEventListener)pkgmgr_client_new", 0);
299     m_manager_handle = pkgmgr_client_new(PC_LISTENING);
300     TIME_TRACER_ITEM_END("(addAppInfoEventListener)pkgmgr_client_new", 0);
301     if (NULL == m_manager_handle) {
302         LOGE("pkgmgr_client: NULL");
303         ApplicationUtil::throwApplicationException<InvalidArgumentException>(
304                 PKGMGR_R_ERROR,
305                 "pkgmgr_client_new()",
306                 ApplicationUtil::getApplicationPkgmgrinfoMessage);
307     }
308
309     TIME_TRACER_ITEM_BEGIN("(addAppInfoEventListener)pkgmgr_client_listen_status", 0);
310     int request_id = pkgmgr_client_listen_status(m_manager_handle,
311             app_list_changed_cb_broker,
312             this);
313     TIME_TRACER_ITEM_END("(addAppInfoEventListener)pkgmgr_client_listen_status", 0);
314     if (request_id < 0) {
315         LOGE("ret: %d", request_id);
316         ApplicationUtil::throwApplicationException<PlatformException>(request_id,
317                 "pkgmgr_client_listen_status()",
318                 ApplicationUtil::getApplicationPkgmgrinfoMessage);
319     }
320 }
321
322 void AppManagerWrapper::unregisterAppListChangedCallbacks()
323 {
324     LOGD("Entered");
325     if (m_manager_handle == NULL) {
326         LOGE("No callback is registered");
327         return;
328     }
329
330     TIME_TRACER_ITEM_BEGIN("(removeAppInfoEventListener)pkgmgr_client_free", 0);
331     int ret = pkgmgr_client_free(m_manager_handle);
332     if (PKGMGR_R_OK != ret) {
333         LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
334                 "pkgmgr_client_free()",
335                 ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
336     }
337     TIME_TRACER_ITEM_END("(removeAppInfoEventListener)pkgmgr_client_free", 0);
338     m_manager_handle = NULL;
339 }
340
341 bool AppManagerWrapper::initializeAppInfo(ApplicationInformationPtr &appInfo)
342 {
343     LOGD("Entered");
344     pkgmgr_client *pc = NULL;
345     int ret = 0;
346
347     do {
348         // get installed size from package server (to solve smack issue)
349         pc = pkgmgr_client_new(PC_REQUEST);
350         if (!pc) {
351             LOGE("pc: NULL");
352             LOGE("%s", ApplicationUtil::getApplicationErrorMessage(PKGMGR_R_ERROR,
353                     "pkgmgr_client_new()",
354                     ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
355             break;
356         }
357         ret = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE,
358             PM_GET_TOTAL_SIZE, pc, NULL, appInfo->getPackageId().c_str(),
359                 NULL, NULL, NULL);
360         if (ret < 0) {
361             LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
362                     "pkgmgr_client_request_service()",
363                     ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
364             break;
365         }
366         appInfo->setInstallSize(ret);
367     } while (false);
368
369     pkgmgr_client_free(pc);
370     appInfo->setInitialize();
371     return true;
372 }
373
374 SINGLETON_IMPLEMENTATION(AppManagerWrapper)
375
376 } // Application
377 } // DeviceAPI