[Application] Application uninstall fix
authorPiotr Czaja <p.czaja@samsung.com>
Thu, 16 Jul 2015 06:37:11 +0000 (08:37 +0200)
committerTomasz Iwanek <t.iwanek@samsung.com>
Wed, 16 Sep 2015 13:00:25 +0000 (15:00 +0200)
Change-Id: I1769fffb46b4aa84d8094e4d0fc1853ed1ddc105
Signed-off-by: Piotr Czaja <p.czaja@samsung.com>
src/application/application_manager.cc
src/application/application_manager.h

index 806b2480bf103655fd4e189116dca973ad00c6a2..dc3f180b84b14efe659bf20a410cf68c250b9d36 100755 (executable)
@@ -53,6 +53,8 @@ const char* kInstallEvent = PKGMGR_INSTALLER_INSTALL_EVENT_STR;
 const char* kUpdateEvent = PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
 const char* kUninstallEvent = PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
 
+const char* kAppidKey = "appid";
+
 const std::string kAction = "action";
 const std::string kCallbackId = "callbackId";
 const std::string kOnInstalled = "oninstalled";
@@ -63,15 +65,14 @@ const std::string kData = "data";
 
 ApplicationManager::ApplicationManager(ApplicationInstance& instance) :
   pkgmgr_client_handle_(nullptr),
+  pkgmgrinfo_client_handle_(nullptr),
   instance_(instance) {
     LoggerD("Enter");
 }
 
 ApplicationManager::~ApplicationManager() {
   LoggerD("Enter");
-  if (pkgmgr_client_handle_) {
-    StopAppInfoEventListener();
-  }
+  StopAppInfoEventListener();
 }
 
 void ApplicationManager::GetCurrentApplication(const std::string& app_id,
@@ -1108,6 +1109,25 @@ class ApplicationListChangedBroker {
     return 0;
   }
 
+  static int AppUninstallListener(uid_t target_uid, int id, const char* type, const char* package, const char* key,
+                                  const char* val, const void* msg, void* data) {
+    LoggerD("Entered");
+
+    ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
+
+    if (0 == strcasecmp(key, kStartKey)) {
+      that->HandleUninstallStart();
+    } else if (0 == strcasecmp(key, kAppidKey)) {
+      that->AddUninstalledAppId(val);
+    } else if (0 == strcasecmp(key, kEndKey)) {
+      that->HandleUninstallEnd();
+    } else {
+      LoggerD("Ignored key: %s", key);
+    }
+
+    return 0;
+  }
+
   void AddApplicationInstance(ApplicationInstance* app_instance) {
     LoggerD("Entered");
       app_instance_list_.push_back(app_instance);
@@ -1122,26 +1142,22 @@ class ApplicationListChangedBroker {
       }
     }
   }
-
  private:
   void HandleStart(const char* event_type, const char* package) {
     LoggerD("Entered");
     app_list_.clear();
     set_event_type(event_type);
-
-    if (Event::kUninstalled == event_type_) {
-      // we need to get information about application ID before it is uninstalled
-      GetApplicationIdsFromPackage(package);
-    }
   }
 
   void HandleEnd(const char* package) {
     LoggerD("Entered");
 
-    if (Event::kUninstalled != event_type_) {
-      GetApplicationIdsFromPackage(package);
+    if (Event::kUninstalled == event_type_) {
+      return;
     }
 
+    GetApplicationIdsFromPackage(package);
+
     for (auto& app_id : app_list_) {
       picojson::value value = picojson::value(picojson::object());
       picojson::object& data_obj = value.get<picojson::object>();
@@ -1154,10 +1170,6 @@ class ApplicationListChangedBroker {
         case Event::kUpdated:
           data_obj.insert(std::make_pair(kAction, picojson::value(kOnUpdated)));
           break;
-
-        case Event::kUninstalled:
-          data_obj.insert(std::make_pair(kAction, picojson::value(kOnUninstalled)));
-          break;
       }
 
       switch (event_type_) {
@@ -1175,10 +1187,6 @@ class ApplicationListChangedBroker {
           pkgmgrinfo_appinfo_destroy_appinfo(handle);
         }
         break;
-
-        case Event::kUninstalled:
-          data_obj.insert(std::make_pair(kData, picojson::value(app_id)));
-          break;
       }
 
       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
@@ -1233,6 +1241,36 @@ class ApplicationListChangedBroker {
     return true;
   }
 
+  void HandleUninstallStart() {
+    LoggerD("Entered");
+    app_list_.clear();
+    set_event_type(kUninstallEvent);
+  }
+
+  void AddUninstalledAppId(const char* app_id) {
+    LoggerD("Entered");
+    if (nullptr != app_id) {
+      app_list_.push_back(app_id);
+    }
+  }
+
+  void HandleUninstallEnd() {
+    LoggerD("Entered");
+    for (auto& app_id : app_list_) {
+      picojson::value value = picojson::value(picojson::object());
+      picojson::object& data_obj = value.get<picojson::object>();
+
+      data_obj.insert(std::make_pair(kAction, picojson::value(kOnUninstalled)));
+      data_obj.insert(std::make_pair(kData, picojson::value(app_id)));
+
+      data_obj["listenerId"] = picojson::value("ApplicationEventListener");
+
+      for (auto instance : app_instance_list_) {
+        instance->PostMessage(value.serialize().c_str());
+      }
+    }
+  }
+
   Event event_type_;
   std::vector<std::string> app_list_;
   std::vector<ApplicationInstance*> app_instance_list_;
@@ -1243,11 +1281,25 @@ static ApplicationListChangedBroker g_application_list_changed_broker;
 void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
   LoggerD("Entered");
 
-  if (nullptr == pkgmgr_client_handle_) {
-    pkgmgr_client_handle_ = pkgmgr_client_new(PC_LISTENING);
-
+  if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgrinfo_client_handle_) {
     if (nullptr == pkgmgr_client_handle_) {
+      pkgmgr_client_handle_ = pkgmgr_client_new(PC_LISTENING);
+    }
+
+    if (nullptr == pkgmgrinfo_client_handle_) {
+      pkgmgrinfo_client_handle_ = pkgmgrinfo_client_new(PMINFO_LISTENING);
+    }
+
+    if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgrinfo_client_handle_) {
       LoggerE("Failed to register listener.");
+      if (nullptr != pkgmgr_client_handle_) {
+        pkgmgr_client_free(pkgmgr_client_handle_);
+        pkgmgr_client_handle_ = nullptr;
+      }
+      else if (nullptr != pkgmgrinfo_client_handle_) {
+        pkgmgrinfo_client_free(pkgmgrinfo_client_handle_);
+        pkgmgrinfo_client_handle_ = nullptr;
+      }
       ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."), out);
       return;
     }
@@ -1256,6 +1308,12 @@ void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
     pkgmgr_client_listen_status(pkgmgr_client_handle_,
                                 ApplicationListChangedBroker::ClientStatusListener,
                                 &g_application_list_changed_broker);
+
+    pkgmgrinfo_client_set_status_type(pkgmgrinfo_client_handle_,
+                                      PACKAGE_MANAGER_STATUS_TYPE_UNINSTALL);
+    pkgmgrinfo_client_listen_status(pkgmgrinfo_client_handle_,
+                                ApplicationListChangedBroker::AppUninstallListener,
+                                &g_application_list_changed_broker);
   } else {
     LoggerD("Broker callback is already registered.");
   }
@@ -1266,9 +1324,15 @@ void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
 void ApplicationManager::StopAppInfoEventListener() {
   LoggerD("Entered");
 
-  if (nullptr != pkgmgr_client_handle_) {
-    pkgmgr_client_free(pkgmgr_client_handle_);
-    pkgmgr_client_handle_ = nullptr;
+  if (nullptr != pkgmgr_client_handle_ || nullptr != pkgmgrinfo_client_handle_) {
+    if (nullptr != pkgmgr_client_handle_) {
+      pkgmgr_client_free(pkgmgr_client_handle_);
+      pkgmgr_client_handle_ = nullptr;
+    }
+    if (nullptr != pkgmgrinfo_client_handle_) {
+      pkgmgrinfo_client_free(pkgmgrinfo_client_handle_);
+      pkgmgrinfo_client_handle_ = nullptr;
+    }
     g_application_list_changed_broker.RemoveApplicationInstance(&instance_);
   } else {
     LoggerD("Broker callback is already unregistered.");
index 1ef1abe6d3ad5484c1d47dc78d862bbb8124dfbf..6229c73b779b3ad3fd11fbe530ab8a42f4515a45 100755 (executable)
@@ -21,6 +21,8 @@
 #include <memory>
 
 #include <package-manager.h>
+#include <string>
+#include <pkgmgr-info.h>
 
 #include "common/picojson.h"
 #include "common/platform_result.h"
@@ -56,6 +58,7 @@ class ApplicationManager {
   char* GetPackageId(const std::string& app_id);
 
   pkgmgr_client* pkgmgr_client_handle_;
+  pkgmgrinfo_client* pkgmgrinfo_client_handle_;
   ApplicationInstance& instance_;
 };