Add a new internal api 19/321319/9
authorChanggyu Choi <changyu.choi@samsung.com>
Wed, 19 Mar 2025 01:58:56 +0000 (10:58 +0900)
committerChanggyu Choi <changyu.choi@samsung.com>
Fri, 21 Mar 2025 01:23:59 +0000 (10:23 +0900)
Adds:
 - aul_app_is_running_async()

Change-Id: Ic1b23c1099930b3f41c77b898fe9bfa4419b8b40
Signed-off-by: Changgyu Choi <changyu.choi@samsung.com>
src/aul/include/aul.h
src/aul/pkginfo.cc
src/tool/aul_test/tests/aul_app_is_running_async_test.cc [new file with mode: 0644]
test/unit_tests/test_pkginfo.cc

index e91aa6f4807065590355a8f1836681d9d5aeebd9..d2aa75f3a525933929e1326016242a57240fb7c4 100644 (file)
@@ -771,17 +771,17 @@ typedef int (*aul_app_info_iter_fn)(const aul_app_info *ainfo, void *data);
 
 /**
  * @par Description:
- *     This API ask a application is running by application package name.
+ *     This API ask a application is running by application ID.
  * @par Purpose:
  *     To know whether some application is running or not, use this API
  * @par Typical use case:
  *     For example, If you want to know browser application running,
  *     you can check it by using this API.
  *
- * @param[in]  pkgname application package name
+ * @param[in]  appid   application ID
  * @return     true / false
- * @retval     1       app_name is running now.
- * @retval     0       app_name is NOT running now.
+ * @retval     1       application is running now.
+ * @retval     0       application is NOT running now.
  *
  * @code
  * #include <aul.h>
@@ -800,18 +800,18 @@ int aul_app_is_running(const char *appid);
 
 /**
  * @par Description:
- *     This API ask a application is running by application package name.
+ *     This API ask a application is running by application ID.
  * @par Purpose:
  *     To know whether some application is running or not, use this API
  * @par Typical use case:
  *     For example, If you want to know browser application running,
  *     you can check it by using this API.
  *
- * @param[in]  pkgname application package name
+ * @param[in]  appid   application ID
  * @param[in]  uid     User ID
  * @return     true / false
- * @retval     1       app_name is running now.
- * @retval     0       app_name is NOT running now.
+ * @retval     1       application is running now.
+ * @retval     0       application is NOT running now.
  *
  * @endcode
  * @remark
@@ -3451,6 +3451,38 @@ int aul_launch_app_fast_without_resinfo(const char *appid, bundle *bundle);
 
 int aul_launch_app_fast_without_resinfo_for_uid(const char *appid, bundle *bundle, uid_t uid);
 
+
+/**
+ * @brief This API ask a application is running asynchronously by application ID.
+ * @param[in] appid application ID
+ * @param[in] callback The callback function
+ * @param[in] data The user data passed to the callback function
+ * @return true / false
+ * @retval 1 application is running now.
+ * @retval 0 application is NOT running now.
+ *
+ * @code
+ * #include <aul.h>
+ *
+ * void result_cb(int result, void *data)
+ * {
+ *      if (ret == false) {
+ *          perror("app is not running");
+ *      }
+ *
+ *      ...
+ * }
+ *
+ * int main()
+ * {
+ *      int ret = aul_app_is_running_async("org.tizen.browser", result_cb);
+ * }
+ *
+ * @endcode
+ *
+ */
+int aul_app_is_running_async(const char *appid, aul_result_cb callback, void *data);
+
 #ifdef __cplusplus
         }
 #endif
index 8eb4db9f3eca25b5b34fd265d4a392c8f452d553..9077e10b70ac73f969155f7c1d1d2b3287bc4089 100644 (file)
@@ -129,6 +129,70 @@ class ResultInfo {
   guint source_ = 0;
 };
 
+class AppIsRunningResultInfo {
+ public:
+ AppIsRunningResultInfo(int fd, aul_result_cb callback, void* user_data)
+      : fd_(fd), callback_(callback), user_data_(user_data) {}
+
+  AppIsRunningResultInfo(const AppIsRunningResultInfo&) = delete;
+  AppIsRunningResultInfo& operator = (const AppIsRunningResultInfo&) = delete;
+
+  ~AppIsRunningResultInfo() {
+    if (source_ != 0)
+      g_source_remove(source_);
+
+    if (fd_ > -1)
+      close(fd_);
+  }
+
+  bool Watch() {
+    source_ = g_unix_fd_add(fd_,
+        static_cast<GIOCondition>(G_IO_IN | G_IO_HUP | G_IO_ERR),
+        FdSourceFunc, this);
+    if (source_ == 0) {
+      _E("g_unix_fd_add() is failed");
+      return false;
+    }
+
+    return true;
+  }
+
+ private:
+  void ProcessReadEvent() {
+    int res = aul_sock_recv_result_with_fd(fd_);
+    if (res > 0)
+      res = 1;
+    else
+      res = 0;
+
+    callback_(res, user_data_);
+  }
+
+  void ProcessErrorEvent() {
+    callback_(AUL_R_ERROR, user_data_);
+  }
+
+  static gboolean FdSourceFunc(int fd, GIOCondition condition,
+      gpointer user_data) {
+    auto* info = static_cast<AppIsRunningResultInfo*>(user_data);
+    _E("GIOCondition: %d", static_cast<int>(condition));
+    if (condition & G_IO_IN)
+      info->ProcessReadEvent();
+    else
+      info->ProcessErrorEvent();
+
+    info->source_ = 0;
+    delete info;
+    return G_SOURCE_REMOVE;
+  }
+
+ private:
+  int fd_;
+  aul_result_cb callback_;
+  void* user_data_;
+  guint source_ = 0;
+};
+
 bool IsAmdReady() {
   static std::atomic<bool> amd_ready = false;
   if (amd_ready)
@@ -354,6 +418,33 @@ extern "C" API int aul_app_is_running_for_uid(const char* appid, uid_t uid) {
   return ret > 0;
 }
 
+extern "C" API int aul_app_is_running_async(const char* appid,
+  aul_result_cb callback, void* data) {
+  if (appid == nullptr || callback == nullptr) {
+    _E("Invalid parameter");
+    return AUL_R_EINVAL;
+  }
+
+  int fd = AppRequest(APP_IS_RUNNING, getuid())
+      .SetAppId(appid)
+      .SendSimply(AUL_SOCK_ASYNC);
+  if (fd < 0) {
+    _E("Failed to send request. error(%d)", fd);
+    return fd;
+  }
+
+  try {
+    auto* info = new AppIsRunningResultInfo(fd, callback, data);
+    info->Watch();
+  } catch (const std::exception& e) {
+    _E("Exception occurs. error: %s", e.what());
+    close(fd);
+    return AUL_R_ERROR;
+  }
+
+  return AUL_R_OK;
+}
+
 extern "C" API int aul_app_get_running_app_info(aul_app_info_iter_fn iter_fn,
     void* user_data) {
   return aul_app_get_running_app_info_for_uid(iter_fn, user_data, getuid());
diff --git a/src/tool/aul_test/tests/aul_app_is_running_async_test.cc b/src/tool/aul_test/tests/aul_app_is_running_async_test.cc
new file mode 100644 (file)
index 0000000..d759e47
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+
+#include "include/aul.h"
+
+#include "aul_test.hh"
+#include "log_private.hh"
+
+namespace aul_test {
+
+class AulAppIsRunningAsyncTest : public AulTest {
+ public:
+  AulAppIsRunningAsyncTest()
+      : AulTest("app_is_running_async", "aul_app_is_running_async",
+            "app_is_running_async <appid>", false) {}
+
+  virtual ~AulAppIsRunningAsyncTest() {}
+
+  void SetUp() override {}
+
+  void TearDown() override {}
+
+  int Test(int argc, char** argv) override {
+    if (argc < 3) {
+      Usage();
+      return -1;
+    }
+
+    _D("[aul_app_is_running_async test] %s", argv[2]);
+    return aul_app_is_running_async(argv[2], AppIsRunningResultCb,
+        this);
+  }
+
+ private:
+  static void AppIsRunningResultCb(int result, void* user_data) {
+    _D("Result: %s", result ? "true" : "false");
+  }
+};
+
+AUL_TEST_REGISTER(AulAppIsRunningAsyncTest, app_is_running_async_test);
+
+}  // namespace aul_test
index 7f2c89afca35ac35168c4c626431d504c9e62c33..d4f8d3bb3dd8be64551180ab99a84c4e3c2d75b5 100644 (file)
@@ -1140,3 +1140,44 @@ TEST_F(PkgInfoTest, aul_app_get_appid_bypid_async_P) {
   EXPECT_EQ(opt, (AUL_SOCK_BUNDLE | AUL_SOCK_ASYNC));
   EXPECT_EQ(b.GetString(AUL_K_PID), std::to_string(100));
 }
+
+TEST_F(PkgInfoTest, aul_app_is_running_async_P) {
+  int cmd = -1;
+  EXPECT_CALL(GetMock<SocketMock>(), socket(_, _, _))
+      .Times(1);
+  EXPECT_CALL(GetMock<SocketMock>(), connect(_, _, _))
+      .Times(1);
+  EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+      .Times(1)
+      .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+          -> ssize_t {
+        const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+        cmd = header->cmd;
+        return n;
+      }));
+  EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+      .Times(1)
+      .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags)
+          -> ssize_t {
+        int ret = 1000;  // test pid
+        memcpy(buf, &ret, sizeof(int));
+        return sizeof(int);
+      }));
+  EXPECT_CALL(GetMock<GlibMock>(), g_unix_fd_add(_, _, _, _))
+      .Times(1)
+      .WillOnce(Invoke([&](gint fd, GIOCondition condtion,
+          GUnixFDSourceFunc func, gpointer user_data) -> guint {
+        func(fd, G_IO_IN, user_data);
+        return 1;
+      }));
+
+  int res = -1;
+  int ret = aul_app_is_running_async("test_appid",
+      [](int result, void* user_data) {
+        int* res_ptr = static_cast<int*>(user_data);
+        *res_ptr = result;
+      }, &res);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(cmd, APP_IS_RUNNING);
+  EXPECT_EQ(res, true);
+}