add clear_applications function to batch mode 94/205894/4
authorRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Fri, 10 May 2019 07:07:45 +0000 (09:07 +0200)
committerRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Thu, 16 May 2019 09:31:20 +0000 (11:31 +0200)
Change-Id: Iccc6f0b4b79582043834023f0e4b5ecdc76cdaa3

CMakeLists.txt
org.tizen.universal-switch.xml
packaging/org.tizen.universal-switch.spec
src/AppControlActivity.cpp
src/batch/BatchRunner.cpp
src/batch/BatchRunner.hpp
src/utils.hpp

index 87da61805c78d58d2f8d0718a4e0d5aea86b42cb..fbf4ba388234a8be69106ebeebabc48864d63ccd 100644 (file)
@@ -15,6 +15,7 @@ pkg_check_modules(pkgs REQUIRED
     atspi-2
     capi-appfw-service-application
     capi-appfw-application
+    capi-appfw-app-manager
     capi-media-player
     capi-media-sound-manager
     capi-telephony
@@ -32,6 +33,7 @@ pkg_check_modules(pkgs REQUIRED
     storage
     syspopup-caller
     tzsh-screensaver-service
+       rua
 )
 # TODO remove cairo dependency, when there will be available screenshot service.
 
index 586c7c4e4e8b8d724e6ce685291e9a0d25b04def..9cc120ebd6f1bba6f3a19c6f55befebc20d0226e 100644 (file)
@@ -18,6 +18,8 @@
         <privilege>http://tizen.org/privilege/telephony</privilege>
         <privilege>http://tizen.org/privilege/systemsettings.admin</privilege>
         <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
+        <privilege>http://tizen.org/privilege/appmanager.kill</privilege>
+        <privilege>http://tizen.org/privilege/appmanager.kill.bgapp</privilege>
         <privilege>http://tizen.org/privilege/keygrab</privilege>
         <privilege>http://tizen.org/privilege/inputgenerator</privilege>
         <privilege>http://tizen.org/privilege/volume.set</privilege>
index f7b2cd15f16d8ecbbe72252683ef52e4203694fc..ad7b264d8943b72eefce557dba66ddd544e8e85c 100644 (file)
@@ -16,6 +16,7 @@ BuildRequires:  tts
 BuildRequires:  tts-devel
 BuildRequires:  pkgconfig(capi-appfw-service-application)
 BuildRequires:  pkgconfig(capi-appfw-application)
+BuildRequires:  pkgconfig(capi-appfw-app-manager)
 BuildRequires:  pkgconfig(capi-media-player)
 BuildRequires:  pkgconfig(capi-media-sound-manager)
 BuildRequires:  pkgconfig(capi-telephony)
@@ -33,6 +34,8 @@ BuildRequires:  pkgconfig(tzsh-quickpanel)
 BuildRequires:  pkgconfig(cairo)
 BuildRequires:  pkgconfig(storage)
 BuildRequires:  pkgconfig(syspopup-caller)
+BuildRequires:  pkgconfig(rua)
+BuildRequires:  pkgconfig(pkgmgr-info)
 BuildRequires:  gtest-devel
 BuildRequires:  pkgconfig(tzsh-screensaver-service)
 #Required for tests
index 0297bd34f0d41acda9bbff6438a8ba01d35ce0a9..12875363f36f474fecd742e29d24ab574b63bd0a 100644 (file)
@@ -69,7 +69,9 @@ private:
                RETURN_IF(status != APP_CONTROL_ERROR_NONE);
 
                status = app_control_send_launch_request(appControlHandle, NULL, NULL);
-               PRINT_ERROR_IF(status != APP_CONTROL_ERROR_NONE);
+               if (status != APP_CONTROL_ERROR_NONE) {
+                       ERROR("launching '%s' failed with error code %d", DerivedType::appToLaunch, status);
+               }
        }
 };
 
index bc0f0f0721a2b4ab63f87bcd0c6ba46241f357d9..cc7ef4b178bdcd723a1d4b38d63c22c6ab2e62aa 100644 (file)
@@ -36,7 +36,8 @@
 #include <fstream>
 #include <cmath>
 #include <type_traits>
-
+#include <app_manager.h>
+#include <app_manager_extension.h>
 
 namespace WrapDetails
 {
@@ -442,6 +443,264 @@ namespace
                }
                return file.substr(0, pos + 1) + relativePath;
        }
+
+       std::string errorToStr(int err)
+       {
+               std::ostringstream tmp;
+               bool first = true;
+#define Q(a) \
+       if (a == err) { \
+               if (first) first = false; \
+               else tmp << ", "; \
+               tmp << #a; \
+       }
+               Q(TIZEN_ERROR_NONE)
+               Q(TIZEN_ERROR_NOT_PERMITTED)
+               Q(TIZEN_ERROR_NO_SUCH_FILE)
+               Q(TIZEN_ERROR_NO_SUCH_PROCESS)
+               Q(TIZEN_ERROR_INTERRUPTED_SYS_CALL)
+               Q(TIZEN_ERROR_IO_ERROR)
+               Q(TIZEN_ERROR_NO_SUCH_DEVICE)
+               Q(TIZEN_ERROR_ARGUMENT_LIST_TOO_LONG)
+               Q(TIZEN_ERROR_EXEC_FORMAT_ERROR)
+               Q(TIZEN_ERROR_BAD_FILE_NUMBER)
+               Q(TIZEN_ERROR_TRY_AGAIN)
+               Q(TIZEN_ERROR_OUT_OF_MEMORY)
+               Q(TIZEN_ERROR_PERMISSION_DENIED)
+               Q(TIZEN_ERROR_BAD_ADDRESS)
+               Q(TIZEN_ERROR_BLOCK_DEVICE_REQUIRED)
+               Q(TIZEN_ERROR_RESOURCE_BUSY)
+               Q(TIZEN_ERROR_FILE_EXISTS)
+               Q(TIZEN_ERROR_CROSS_DEVICE_LINK)
+               Q(TIZEN_ERROR_NOT_A_DIRECTORY)
+               Q(TIZEN_ERROR_IS_A_DIRECTORY)
+               Q(TIZEN_ERROR_INVALID_PARAMETER)
+               Q(TIZEN_ERROR_FILE_TABLE_OVERFLOW)
+               Q(TIZEN_ERROR_TOO_MANY_OPEN_FILES)
+               Q(TIZEN_ERROR_TOO_NOT_A_TERMINAL)
+               Q(TIZEN_ERROR_TOO_TEXT_FILE_BUSY)
+               Q(TIZEN_ERROR_FILE_TOO_LARGE)
+               Q(TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE)
+               Q(TIZEN_ERROR_ILLEGAL_SEEK)
+               Q(TIZEN_ERROR_READ_ONLY_FILESYSTEM)
+               Q(TIZEN_ERROR_NO_DATA)
+               Q(TIZEN_ERROR_TOO_MANY_LINKS)
+               Q(TIZEN_ERROR_BROKEN_PIPE)
+               Q(TIZEN_ERROR_ARGUMENT_OUT_OF_DOMAIN)
+               Q(TIZEN_ERROR_RESULT_OUT_OF_RANGE)
+               Q(TIZEN_ERROR_WOULD_CAUSE_DEADLOCK)
+               Q(TIZEN_ERROR_FILE_NAME_TOO_LONG)
+               Q(TIZEN_ERROR_FILE_NO_LOCKS_AVAILABLE)
+               Q(TIZEN_ERROR_INVALID_OPERATION)
+               Q(TIZEN_ERROR_DIR_NOT_EMPTY)
+               Q(TIZEN_ERROR_TOO_MANY_SYMBOLIC_LINKS)
+               Q(TIZEN_ERROR_WOULD_BLOCK)
+               Q(TIZEN_ERROR_CORRUPTED_SHARED_LIB)
+               Q(TIZEN_ERROR_LIB_SECTION_CORRUPTED)
+               Q(TIZEN_ERROR_LINK_TOO_MANY_SHARED_LIB)
+               Q(TIZEN_ERROR_SHARED_LIB_EXEC)
+               Q(TIZEN_ERROR_ILLEGAL_BYTE_SEQ)
+               Q(TIZEN_ERROR_SYSTEM_CALL_RESTART)
+               Q(TIZEN_ERROR_STREAMS_PIPE)
+               Q(TIZEN_ERROR_TOO_MANY_USERS)
+               Q(TIZEN_ERROR_NON_SOCKET)
+               Q(TIZEN_ERROR_NO_DEST_ADDRESS)
+               Q(TIZEN_ERROR_MSG_TOO_LONG)
+               Q(TIZEN_ERROR_PROTOCOL_WRONG_TYPE)
+               Q(TIZEN_ERROR_PROTOCOL_NOT_AVALIABLE)
+               Q(TIZEN_ERROR_PROTOCOL_NOT_SUPPORTED)
+               Q(TIZEN_ERROR_SOCKET_TYPE_NOT_SUPPORTED)
+               Q(TIZEN_ERROR_ENDPOINT_OPERATIN_NOT_SUPPORTED)
+               Q(TIZEN_ERROR_PROTOCOL_FAMILY_NOT_SUPPORTED)
+               Q(TIZEN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED)
+               Q(TIZEN_ERROR_ADDRES_IN_USE)
+               Q(TIZEN_ERROR_CANNOT_ASSIGN_ADDRESS)
+               Q(TIZEN_ERROR_NETWORK_DOWN)
+               Q(TIZEN_ERROR_NETWORK_UNREACHABLE)
+               Q(TIZEN_ERROR_NETWORK_RESET)
+               Q(TIZEN_ERROR_CONNECTION_ABORTED)
+               Q(TIZEN_ERROR_CONNECTION_RESET_BY_PEER)
+               Q(TIZEN_ERROR_BUFFER_SPACE)
+               Q(TIZEN_ERROR_ENDPOINT_CONNECTED)
+               Q(TIZEN_ERROR_ENDPOINT_NOT_CONNECTED)
+               Q(TIZEN_ERROR_ENDPOINT_SHUTDOWN)
+               Q(TIZEN_ERROR_TOO_MANY_REFERENCES)
+               Q(TIZEN_ERROR_CONNECTION_TIME_OUT)
+               Q(TIZEN_ERROR_CONNECTION_REFUSED)
+               Q(TIZEN_ERROR_HOST_DOWN)
+               Q(TIZEN_ERROR_NO_ROUTE_TO_HOST)
+               Q(TIZEN_ERROR_ALREADY_IN_PROGRESS)
+               Q(TIZEN_ERROR_NOW_IN_PROGRESS)
+               Q(TIZEN_ERROR_STALE_NFS_FILE_HANDLE)
+               Q(TIZEN_ERROR_STRUCTURE_UNCLEAN)
+               Q(TIZEN_ERROR_NOT_XENIX_NAMED_TYPE_FILE)
+               Q(TIZEN_ERROR_NO_XENIX_SEMAPHORES_AVAILABLE)
+               Q(TIZEN_ERROR_IS_NAMED_TYPE_FILE)
+               Q(TIZEN_ERROR_REMOTE_IO)
+               Q(TIZEN_ERROR_QUOTA_EXCEEDED)
+               Q(TIZEN_ERROR_NO_MEDIUM)
+               Q(TIZEN_ERROR_WRONG_MEDIUM_TYPE)
+               Q(TIZEN_ERROR_CANCELED)
+               Q(TIZEN_ERROR_KEY_NOT_AVAILABLE)
+               Q(TIZEN_ERROR_KEY_EXPIRED)
+               Q(TIZEN_ERROR_KEY_REVOKED)
+               Q(TIZEN_ERROR_KEY_REJECTED)
+               Q(TIZEN_ERROR_OWNER_DEAD)
+               Q(TIZEN_ERROR_UNKNOWN)
+               Q(TIZEN_ERROR_TIMED_OUT)
+               Q(TIZEN_ERROR_NOT_SUPPORTED)
+               Q(TIZEN_ERROR_USER_NOT_CONSENTED)
+               Q(TIZEN_ERROR_DEVICE_POLICY_RESTRICTION)
+               Q(TIZEN_ERROR_END_OF_COLLECTION)
+#undef Q
+               return tmp.str();
+       }
+}
+
+void BatchExecutor::killApplication(const std::pair<std::string, std::string> &appInstance)
+{
+       auto &appid = appInstance.first;
+       auto &instance_id = appInstance.second;
+       app_context_h context = NULL;
+       int ret;
+
+       if (appid == "org.tizen.tts-engine-default-sr")
+               return;
+
+       output << "killing application " << appInstance.first << (appid.empty() ? "" : ":") << instance_id << "\n";
+       if (!instance_id.empty()) {
+               ret = app_manager_get_app_context_by_instance_id(appid.c_str(), instance_id.c_str(), &context);
+       } else {
+               bool running = false;
+               ret = app_manager_is_running(appid.c_str(), &running);
+               if (ret != APP_MANAGER_ERROR_NONE) {
+                       throw EvaluationFailure{} << "fail to app_manager_is_running[" << ret << "]: " << get_error_message(ret);
+               }
+
+               if (!running) {
+                       return;
+               }
+               ret = app_manager_get_app_context(appid.c_str(), &context);
+       }
+
+       if (ret != APP_MANAGER_ERROR_NONE) {
+               throw EvaluationFailure{} << "fail to app_manager_get_app_contextfailed[" << ret << "]: " << get_error_message(ret);
+       }
+
+       ret = app_manager_terminate_app(context);
+       app_context_destroy(context);
+
+       if (ret != APP_MANAGER_ERROR_NONE) {
+               throw EvaluationFailure{} << "fail to terminate_app '" << appid << ":" << instance_id << "'" <<
+                                                                 "[" << ret << "]: " << get_error_message(ret);
+       }
+}
+
+std::pair<std::string, std::string> BatchExecutor::getApplicationInfo(app_info_h app_info, struct rua_rec *record)
+{
+       if (!app_info) {
+               return {};
+       }
+
+       char *appid = "";
+       char *instanceid = "";
+
+       int ret = app_info_get_app_id(app_info, &appid);
+       if (ret != APP_MANAGER_ERROR_NONE) {
+               throw EvaluationFailure{} << "app_info_get_app_id failed[" << ret << "]: " << get_error_message(ret);
+       }
+
+       if (record->instance_id) {
+               instanceid = record->instance_id;
+       }
+       return { appid, instanceid };
+}
+
+using ApplicationInfoIterCbDataType =
+       std::tuple<struct rua_rec *, std::vector<std::pair<std::string, std::string>>, BatchExecutor *, std::string>;
+
+bool BatchExecutor::applicationInfoIterCb(app_info_h app_info, void *user_data)
+{
+       auto &data = *(ApplicationInfoIterCbDataType *)user_data;
+       return (std::get<2>(data))->applicationInfoIterCbImpl(app_info, user_data);
+}
+
+bool BatchExecutor::applicationInfoIterCbImpl(app_info_h app_info, void *user_data)
+{
+       auto &data = *(ApplicationInfoIterCbDataType *)user_data;
+
+       struct rua_rec *record = std::get<0>(data);
+
+       try {
+               std::get<1>(data).push_back(std::get<2>(data)->getApplicationInfo(app_info, record));
+       } catch (EvaluationFailure &ev) {
+               std::get<3>(data) = ev.message();
+               return true;
+       }
+       return false;
+}
+
+void BatchExecutor::clearApplications()
+{
+       char **table = nullptr;
+       int rows = 0, cols = 0;
+       struct rua_rec record;
+       app_info_filter_h filter = nullptr;
+
+       if (rua_init()) {
+               throw EvaluationFailure{} << "rua_init failed";
+       }
+
+       DefferedCall rua_init_cb{ [&]()
+       {
+               rua_fini();
+       } };
+
+       if (rua_history_load_db(&table, &rows, &cols) || !table) {
+               throw EvaluationFailure{} << "rua_history_load_db failed";
+       }
+       DefferedCall rua_history_load_db_cb{ [&]()
+       {
+               rua_history_unload_db(&table);
+       } };
+
+       int ret = app_info_filter_create(&filter);
+       if (ret != APP_MANAGER_ERROR_NONE) {
+               throw EvaluationFailure{} << "filter_create failed";
+       }
+       DefferedCall app_info_filter_create_cb{ [&]()
+       {
+               app_info_filter_destroy(filter);
+       } };
+
+       ret = app_info_filter_add_bool(filter, PACKAGE_INFO_PROP_APP_TASKMANAGE, true);
+       if (ret != APP_MANAGER_ERROR_NONE) {
+               throw EvaluationFailure{} << "app_info_filer_add_bool failed[" << ret << "]: " << get_error_message(ret);
+       }
+
+       auto data = ApplicationInfoIterCbDataType{ nullptr, {}, this, "" };
+
+       for (auto row = 0; row < rows; ++row) {
+               rua_history_get_rec(&record, table, rows, cols, row);
+               std::get<0>(data) = &record;
+
+               int ret = app_info_filter_add_string(filter, PACKAGE_INFO_PROP_APP_ID, record.pkg_name);
+               if (ret != APP_MANAGER_ERROR_NONE) {
+                       throw EvaluationFailure{} << "app_info_filter_add_string failed[" << ret << "]: " << get_error_message(ret);
+               }
+
+               ret = app_info_filter_foreach_appinfo(filter, applicationInfoIterCb, &data);
+               if (ret != APP_MANAGER_ERROR_NONE) {
+                       throw EvaluationFailure{} << "app_info_filter_foreach_app_info failed[" << ret << "]: " << get_error_message(ret);
+               }
+               if (!std::get<3>(data).empty()) {
+                       throw EvaluationFailure{} << std::get<3>(data);
+               }
+       }
+
+       for (auto &r : std::get<1>(data)) {
+               killApplication(r);
+       }
 }
 
 void BatchExecutor::insertMethods()
@@ -515,6 +774,13 @@ void BatchExecutor::insertMethods()
                        if (!condition) throw EvaluationFailure{} << "assertion failed";
                        return {};
                }, { {"condition"} } };
+
+       variables["clear_applications"] = EvaluationValueFunction{
+               [&]() -> EvaluationValue {
+                       clearApplications();
+                       return {};
+               }, {} };
+
        variables["find_by_name"] = EvaluationValueFunction{ [&](std::string name, std::vector<int> roles, std::vector<int> states) -> EvaluationValue {
                        auto root = getVisibleRoot();
                        if (!root) throw EvaluationFailure{} << "no visible root (context changed didn't happen)";
index 91d1cd61347f8a2c2d4c6b8e21352d3bf0690e8b..2c64a9770d94f9ab86b209d1e8ac78ba2fd2c1a6 100644 (file)
 #include "EvaluationContext.hpp"
 #include "Evaluator.hpp"
 
+#include <app.h>
+#include <app_manager.h>
+#include <rua.h>
+
 template <typename T> class BatchValueOrError
 {
        Optional<T> data;
@@ -99,6 +103,11 @@ protected:
        void insertStateConstants();
        void insertRoleConstants();
 
+       void clearApplications();
+       void killApplication(const std::pair<std::string, std::string> &appInstance);
+       std::pair<std::string, std::string> getApplicationInfo(app_info_h app_info, struct rua_rec *record);
+       static bool applicationInfoIterCb(app_info_h app_info, void *user_data);
+       bool applicationInfoIterCbImpl(app_info_h app_info, void *user_data);
        void callActivity(const std::string &activityName, const EvaluationValueFunction::Args &args);
        void findByName(const std::vector<AtspiAccessiblePtr> &elems, std::string requestedName, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback);
        void getAllObjects(AtspiAccessiblePtr root, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback,
index c80bd8c3a6c4b4c04b6d55965132cce3aa628778..4b224b1f3a90c54f98867f90daca51956b2e01d5 100644 (file)
@@ -91,4 +91,33 @@ namespace utils
        };
 }
 
+class DefferedCall
+{
+       std::function<void()> f;
+public:
+       DefferedCall() = default;
+       DefferedCall(std::function<void()> f) : f(std::move(f)) { }
+       ~DefferedCall()
+       {
+               if (f) f();
+       }
+       DefferedCall(const DefferedCall &) = delete;
+       DefferedCall(DefferedCall &&o)
+       {
+               f = o.f;
+               o.f = {};
+       }
+
+       DefferedCall &operator = (const DefferedCall &) = delete;
+       DefferedCall &operator = (DefferedCall &&o)
+       {
+               if (this != &o) {
+                       if (f) f();
+                       f = o.f;
+                       o.f = {};
+               }
+               return *this;
+       }
+};
+
 #endif