Modify boot manager 16/302116/7
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 30 Nov 2023 10:44:55 +0000 (19:44 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Fri, 1 Dec 2023 03:45:14 +0000 (12:45 +0900)
The following changes are made to onboot option of amd:
- Apps with onboot set are launched by the boot manager.
- Only apps with boot-sequence set are managed by the boot sequencer.
- Onboot apps will run as before when a package is installed.
- Apps with boot-sequence set will not run until a reboot occurs even if
the package is installed.

Change-Id: I35589a7195043251efb69157b178139e6d62319b
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/lib/amd_boot_manager.cc
src/lib/boot_sequencer/boot_sequencer.cc
src/lib/boot_sequencer/boot_sequencer.hh
src/lib/common/display_state_manager.cc [new file with mode: 0644]
src/lib/common/display_state_manager.hh [new file with mode: 0644]

index 39cf87d..b1cc714 100644 (file)
@@ -22,6 +22,7 @@
 #include <bundle.h>
 #include <bundle_cpp.h>
 #include <bundle_internal.h>
+#include <glib.h>
 #include <sys/types.h>
 
 #include <cctype>
 #include <utility>
 #include <vector>
 
-#include "common/log_private.hh"
 #include "lib/amd_app_property.h"
+#include "lib/amd_app_status.h"
+#include "lib/amd_config.h"
 #include "lib/amd_cynara.h"
-#include "lib/request/request_manager.hh"
+#include "lib/amd_launch.h"
+#include "lib/amd_login_monitor.h"
+#include "lib/amd_noti.h"
 #include "lib/amd_socket.h"
 #include "lib/amd_util.h"
+#include "lib/app_info/app_info_manager.hh"
+#include "lib/app_property/app_property_manager.hh"
 #include "lib/boot_sequencer/boot_sequencer.hh"
+#include "lib/common/display_state_manager.hh"
+#include "lib/common/log_private.hh"
+#include "lib/request/request_manager.hh"
 
 namespace {
+
 constexpr const char METADATA_KEY_ONBOOT_PRIORITY[] =
     "http://tizen.org/metadata/on-boot/priority";
+const int kMinPriority = 1;
+const int kMaxPriority = 99;
+const guint kInterval = 500;
 
 std::string GetTimestampString(const time_t& timestamp) {
   if (timestamp == time_t {})
@@ -158,17 +171,186 @@ int DispatchBootSequenceReload(request_h request) {
   return 0;
 }
 
+int GetPriority(amd::AppProperty* app_property, const std::string& appid) {
+  if (app_property == nullptr)
+    return kMinPriority;
+
+  auto tag = std::make_pair(appid, METADATA_KEY_ONBOOT_PRIORITY);
+  auto found = app_property->GetMetadataEntities().find(tag);
+  if (found == app_property->GetMetadataEntities().end())
+    return kMinPriority;
+
+  int priority = kMinPriority;
+  auto& entity = found->second;
+  const auto& value = entity->GetValue();
+  if (std::isdigit(value[0]))
+    priority = std::stoi(value);
+
+  if (priority < kMinPriority)
+    priority = kMinPriority;
+  if (priority > kMaxPriority)
+    priority = kMaxPriority;
+
+  return priority;
+}
+
+class OnBootAppInfo : public std::enable_shared_from_this<OnBootAppInfo> {
+ public:
+  OnBootAppInfo(uid_t uid, int priority, std::shared_ptr<amd::AppInfo> app_info)
+      : uid_(uid), priority_(priority), app_info_(std::move(app_info)) {}
+
+  uid_t GetUid() const { return uid_; }
+
+  int GetPriority() const { return priority_; }
+
+  const std::shared_ptr<amd::AppInfo>& GetAppInfo() const { return app_info_; }
+
+  void RefSelf() { self_ = shared_from_this(); }
+
+  void UnrefSelf() { self_.reset(); }
+
+ private:
+  uid_t uid_;
+  int priority_;
+  std::shared_ptr<amd::AppInfo> app_info_;
+  std::shared_ptr<OnBootAppInfo> self_;
+};
+
+std::list<std::shared_ptr<OnBootAppInfo>> GetOnBootAppInfos(uid_t uid) {
+  auto chunk = amd::AppInfoManager::GetInst().FindAppInfoChunk(uid);
+  if (chunk == nullptr) {
+    _E("Failed to find app info. uid(%u)", uid);
+    return {};
+  }
+
+  auto* app_property = amd::AppPropertyManager::GetInst().Find(uid);
+  if (app_property == nullptr)
+    _E("Failed to find app property. uid(%u)", uid);
+
+  std::list<std::shared_ptr<OnBootAppInfo>> infos;
+  for (auto& iter : chunk->GetAll()) {
+    auto& app_info = iter.second;
+    if (app_info->GetComponentType().compare(APP_TYPE_SERVICE) != 0 ||
+        app_info->GetOnboot() != "true")
+      continue;
+
+    auto app_status =
+        _app_status_find_by_appid(app_info->GetAppId().c_str(), uid);
+    if (_app_status_is_running(app_status) > 0)
+      continue;
+
+    int priority = GetPriority(app_property, app_info->GetAppId());
+    infos.push_back(std::make_shared<OnBootAppInfo>(uid, priority, app_info));
+  }
+
+  return infos;
+}
+
+gboolean StartOnBootAppsCb(gpointer user_data) {
+  auto* app_info = static_cast<OnBootAppInfo*>(user_data);
+  auto& appid = app_info->GetAppInfo()->GetAppId();
+  uid_t uid = app_info->GetUid();
+
+  auto app_status = _app_status_find_by_appid(appid.c_str(), uid);
+  pid_t pid = _app_status_is_running(app_status);
+  if (pid < 0)
+    pid = _launch_start_app_local(uid, appid.c_str());
+
+  _W("appid(%s), pid(%d), uid(%u)", appid.c_str(), pid, uid);
+  app_info->UnrefSelf();
+  return G_SOURCE_REMOVE;
+}
+
+int OnAppInfoInsert(const char* msg, int arg1, int arg2, void* arg3,
+                    bundle* arg4) {
+  uid_t uid = static_cast<uid_t>(arg1);
+  if (_login_monitor_get_uid_state(uid) != UID_STATE_ACTIVE)
+    return NOTI_CONTINUE;
+
+  pkgmgrinfo_appinfo_h handle = static_cast<pkgmgrinfo_appinfo_h>(arg3);
+  char* appid;
+  if (pkgmgrinfo_appinfo_get_appid(handle, &appid) != PMINFO_R_OK) {
+    _E("pkgmgrinfo_appinfo_get_appid() is failed");
+    return NOTI_CONTINUE;
+  }
+
+  auto app_info = amd::AppInfoManager::GetInst().FindAppInfo(uid, appid);
+  if (app_info == nullptr) return NOTI_CONTINUE;
+
+  int ret = _launch_start_onboot_app_local(uid, appid, app_info.get());
+  _D("%s : %u : %d", appid, uid, ret);
+  return NOTI_CONTINUE;
+}
+
+int OnAppInfoAppEnabledEnd(const char* msg, int arg1, int arg2, void* arg3,
+                           bundle* arg4) {
+  uid_t uid = static_cast<uid_t>(arg1);
+  if (_login_monitor_get_uid_state(uid) != UID_STATE_ACTIVE)
+    return NOTI_CONTINUE;
+
+  const char* appid = static_cast<char*>(arg3);
+  auto app_info = amd::AppInfoManager::GetInst().FindAppInfo(uid, appid);
+  if (app_info == nullptr) return NOTI_CONTINUE;
+
+  if (app_info->GetComponentType().compare(APP_TYPE_SERVICE) != 0 ||
+      app_info->GetOnboot() != "true")
+    return NOTI_CONTINUE;
+
+  int ret = _launch_start_onboot_app_local(uid, appid, app_info.get());
+  _D("%s : %u : %d", appid, uid, ret);
+  return NOTI_CONTINUE;
+}
+
+gboolean RegisterUnlockTimerCb(gpointer user_data) {
+  amd::DisplayStateManager::GetInst().RegisterUnlockTimer();
+  return G_SOURCE_REMOVE;
+}
+
 }  // namespace
 
 int _boot_manager_start_onboot_apps(uid_t uid) {
-  auto& sequencer = amd::boot_sequencer::BootSequencer::GetInst();
-  sequencer.Load(uid);
-  sequencer.Start(uid);
+  auto infos = GetOnBootAppInfos(uid);
+  if (infos.empty())
+    return 0;
+
+  auto& inst = amd::DisplayStateManager::GetInst();
+  if (inst.IsLocked())
+    inst.UnregisterUnlockTimer();
+  else
+    inst.Lock();
+
+  auto compare = [](std::shared_ptr<OnBootAppInfo> const& a,
+                    std::shared_ptr<OnBootAppInfo> const& b) -> bool {
+    return a->GetPriority() > b->GetPriority();
+  };
+  infos.sort(compare);
+
+  guint delay_interval = 0;
+  guint idle_interval =
+      _config_get_onboot_max_interval() - _config_get_onboot_interval();
+  size_t max_size = idle_interval / _config_get_onboot_interval();
+  size_t size = infos.size();
+  if (size > max_size)
+    delay_interval = _config_get_onboot_interval() / (size - max_size);
+
+  guint index = 0;
+  guint interval = 0;
+  for (auto& info : infos) {
+    info->RefSelf();
+    if (interval >= idle_interval)
+      interval += delay_interval;
+    else
+      interval = _config_get_onboot_interval() * index++;
+
+    g_timeout_add(interval, StartOnBootAppsCb, static_cast<void*>(info.get()));
+  }
+  g_timeout_add(interval + kInterval, RegisterUnlockTimerCb, nullptr);
   return 0;
 }
 
 int _boot_manager_init(void) {
   _W("BOOT_MANAGER_INIT");
+  amd::boot_sequencer::BootSequencer::GetInst().Init();
   if (_app_property_metadata_add_filter(
           METADATA_KEY_ONBOOT_PRIORITY, nullptr) < 0) {
     _E("Failed to add metadata filter");
@@ -214,9 +396,12 @@ int _boot_manager_init(void) {
   if (_cynara_register_checkers(checkers, ARRAY_SIZE(checkers)) < 0)
     return -1;
 
+  _noti_listen(AMD_NOTI_MSG_APPINFO_INSERT, OnAppInfoInsert);
+  _noti_listen(AMD_NOTI_MSG_APPINFO_APP_ENABLED_END, OnAppInfoAppEnabledEnd);
   return 0;
 }
 
 void _boot_manager_fini(void) {
   _W("BOOT_MANAGER_FINI");
+  amd::boot_sequencer::BootSequencer::GetInst().Dispose();
 }
index 63a87f1..bf5c5f4 100644 (file)
 #include <glib.h>
 #include <string.h>
 
-#include <iostream>
 #include <fstream>
+#include <iostream>
 
 #include "lib/amd_launch.h"
 #include "lib/amd_noti.h"
 #include "lib/amd_signal.h"
 #include "lib/app_info/app_info_manager.hh"
 #include "lib/app_status/app_status_manager.hh"
+#include "lib/common/display_state_manager.hh"
 #include "lib/common/log_private.hh"
 
 namespace amd::boot_sequencer {
@@ -51,8 +52,6 @@ constexpr const char TAG_INFO_VCONF[] = "INFO:VCONF";
 constexpr const char TAG_INFO_PATH_EXISTS[] = "INFO:PATH_EXISTS";
 constexpr const char TAG_INFO_TIMEOUT[] = "INFO:TIMEOUT";
 
-constexpr const char REQUIRED_API_VERSION[] = "7";
-
 }  // namespace
 
 BootSequencer::BootSequencer() = default;
@@ -63,9 +62,6 @@ BootSequencer::~BootSequencer() {
 
 BootSequencer& BootSequencer::GetInst() {
   static BootSequencer inst;
-  if (inst.disposed_)
-    inst.Init();
-
   return inst;
 }
 
@@ -76,8 +72,7 @@ void BootSequencer::Init() {
   _noti_listen(AMD_NOTI_MSG_APP_STATUS_SET_REAL_PID, OnAppStatusSetRealPid);
   _noti_listen(AMD_NOTI_MSG_APP_STATUS_CLEANUP, OnAppStatusCleanup);
   _noti_listen(AMD_NOTI_MSG_APP_STATUS_ADD, OnAppStatusAdd);
-  _noti_listen(AMD_NOTI_MSG_APPINFO_INSERT, OnAppInfoInsert);
-  _noti_listen(AMD_NOTI_MSG_APPINFO_APP_ENABLED_END, OnAppInfoAppEnabledEnd);
+  _noti_listen(AMD_NOTI_MSG_APPINFO_LOAD, OnAppInfoLoad);
   _noti_listen(AMD_NOTI_MSG_APPINFO_REMOVE, OnAppInfoRemove);
   disposed_ = false;
 }
@@ -124,16 +119,6 @@ void BootSequencer::Load(uid_t uid) {
   if (ret != AUL_ERROR_NONE)
     _E("aul_boot_sequence_foreach_usr() is failed. error(%d)", ret);
 
-  auto appinfo_chunk = AppInfoManager::GetInst().FindAppInfoChunk(uid);
-  for (auto& [appid, app_info] : appinfo_chunk->GetAll()) {
-    if (app_info->GetOnboot() == "true" && !Contains(appid, uid)) {
-      _E("%s does not exists in db", appid.c_str());
-      auto app_info = std::make_shared<AppInfo>(appid, uid);
-      Insert(app_info, uid);
-      QueuePush(std::move(app_info));
-    }
-  }
-
   chunks_[uid]->RefineDependencies();
   QueueSort();
 }
@@ -159,15 +144,6 @@ void BootSequencer::Reload(uid_t uid) {
   if (ret != AUL_ERROR_NONE)
     _E("aul_boot_sequence_foreach_usr() is failed. error(%d)", ret);
 
-  auto appinfo_chunk = AppInfoManager::GetInst().FindAppInfoChunk(uid);
-  for (auto& [appid, app_info] : appinfo_chunk->GetAll()) {
-    if (app_info->GetOnboot() == "true" && !Contains(appid, uid)) {
-      _E("%s does not exists in db", appid.c_str());
-      auto app_info = std::make_shared<AppInfo>(appid, uid);
-      Insert(app_info, uid);
-    }
-  }
-
   chunks_[uid]->RefineDependencies();
 }
 
@@ -175,9 +151,7 @@ void BootSequencer::Start(uid_t uid) {
   if (source_ != 0)
     return;
 
-  _W("Lock display state");
-  _signal_send_display_lock_state();
-
+  DisplayStateManager::GetInst().Lock();
   source_ = g_timeout_add(100, OnRun, this);
 }
 
@@ -468,8 +442,7 @@ void BootSequencer::QueueErase(const std::string& appid, uid_t uid) {
 gboolean BootSequencer::OnRun(gpointer user_data) {
   auto& inst = BootSequencer::GetInst();
   if (inst.QueueEmpty()) {
-    _W("Unlock display state");
-    _signal_send_display_unlock_state();
+    DisplayStateManager::GetInst().RegisterUnlockTimer();
     inst.source_ = 0;
     return G_SOURCE_REMOVE;
   }
@@ -531,41 +504,12 @@ int BootSequencer::OnAppStatusAdd(const char* msg, int arg1, int arg2,
   return NOTI_CONTINUE;
 }
 
-void BootSequencer::StartLegacyOnbootApp(const char* appid, uid_t uid) {
-  auto app_info = AppInfoManager::GetInst().FindAppInfo(uid, appid);
-  if (app_info == nullptr)
-    return;
-
-  if (app_info->GetComponentType() != APP_TYPE_SERVICE ||
-      app_info->GetOnboot() != "true")
-    return;
-
-  _D("%s : %u", appid, uid);
-  if (strverscmp(REQUIRED_API_VERSION, app_info->GetApiVersion().c_str()) > 0) {
-    int ret = _launch_start_onboot_app_local(uid, appid, app_info.get());
-    _W("%s : %u : %d", appid, uid, ret);
-  }
-}
-
-int BootSequencer::OnAppInfoInsert(const char* msg, int arg1, int arg2,
-    void* arg3, bundle* arg4) {
-  uid_t uid = static_cast<uid_t>(arg1);
-  pkgmgrinfo_appinfo_h handle = static_cast<pkgmgrinfo_appinfo_h>(arg3);
-  char* appid;
-  if (pkgmgrinfo_appinfo_get_appid(handle, &appid) != PMINFO_R_OK) {
-    _E("pkgmgrinfo_appinfo_get_appid() is failed");
-    return NOTI_CONTINUE;
-  }
-
-  BootSequencer::StartLegacyOnbootApp(appid, uid);
-  return NOTI_CONTINUE;
-}
-
-int BootSequencer::OnAppInfoAppEnabledEnd(const char* msg, int arg1, int arg2,
-    void* arg3, bundle* arg4) {
+int BootSequencer::OnAppInfoLoad(const char* msg, int arg1, int arg2,
+                                 void* arg3, bundle* arg4) {
   uid_t uid = static_cast<uid_t>(arg1);
-  const char* appid = static_cast<char*>(arg3);
-  BootSequencer::StartLegacyOnbootApp(appid, uid);
+  auto& inst = BootSequencer::GetInst();
+  inst.Load(uid);
+  inst.Start(uid);
   return NOTI_CONTINUE;
 }
 
index fbdc902..46be967 100644 (file)
@@ -39,6 +39,7 @@ class BootSequencer {
   void Load(uid_t uid);
   void Reload(uid_t uid);
   void Start(uid_t uid);
+  void Init();
   void Dispose();
   bool StartApp(uid_t uid, const std::string& appid);
   std::shared_ptr<AppInfoChunk> GetBootSequenceApps(uid_t uid);
@@ -46,7 +47,6 @@ class BootSequencer {
  private:
   BootSequencer();
   ~BootSequencer();
-  void Init();
   void Insert(std::shared_ptr<AppInfo> app_info, uid_t uid);
   bool Contains(const std::string& appid, uid_t uid);
   std::shared_ptr<AppInfo> Lookup(const std::string& appid, uid_t uid);
@@ -64,20 +64,18 @@ class BootSequencer {
 
   static gboolean OnRun(gpointer user_data);
   static int OnAppStatusSetRealPid(const char* msg, int arg1, int arg2,
-      void* arg3, bundle* arg4);
-  static int OnAppStatusCleanup(const char* msg, int arg1, int arg2,
-      void* arg3, bundle* arg4);
-  static int OnAppStatusAdd(const char* msg, int arg1, int arg2,
-      void* arg3, bundle* arg4);
-  static void StartLegacyOnbootApp(const char* appid, uid_t uid);
-  static int OnAppInfoInsert(const char* msg, int arg1, int arg2,
-      void* arg3, bundle* arg4);
-  static int OnAppInfoAppEnabledEnd(const char* msg, int arg1, int arg2,
-      void* arg3, bundle* arg4);
-  static int OnAppInfoRemove(const char* msg, int arg1, int arg2,
-      void* arg3, bundle* arg4);
+                                   void* arg3, bundle* arg4);
+  static int OnAppStatusCleanup(const char* msg, int arg1, int arg2, void* arg3,
+                                bundle* arg4);
+  static int OnAppStatusAdd(const char* msg, int arg1, int arg2, void* arg3,
+                            bundle* arg4);
+  static int OnAppInfoLoad(const char* msg, int arg1, int arg2, void* arg3,
+                           bundle* arg4);
+  static int OnAppInfoRemove(const char* msg, int arg1, int arg2, void* arg3,
+                             bundle* arg4);
   static int OnLaunchAppStartEnd(const char* msg, int arg1, int arg2,
-      void* arg3, bundle* arg4);
+                                 void* arg3, bundle* arg4);
+
   void PrintLog(const char* tag, const char* format, ...);
   void PrintDependencies(const std::shared_ptr<AppInfo>& app_info);
 
diff --git a/src/lib/common/display_state_manager.cc b/src/lib/common/display_state_manager.cc
new file mode 100644 (file)
index 0000000..d42acdb
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023 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 "lib/common/display_state_manager.hh"
+
+#include "lib/amd_signal.h"
+#include "lib/common/log_private.hh"
+
+namespace amd {
+
+DisplayStateManager& DisplayStateManager::GetInst() {
+  static DisplayStateManager inst;
+  return inst;
+}
+
+void DisplayStateManager::Lock() {
+  if (locked_)
+    return;
+
+  _W("Lock");
+  _signal_send_display_lock_state();
+  locked_ = true;
+}
+
+void DisplayStateManager::Unlock() {
+  if (!locked_)
+    return;
+
+  _W("Unlock");
+  _signal_send_display_unlock_state();
+  locked_ = false;
+}
+
+void DisplayStateManager::RegisterUnlockTimer() {
+  if (timer_!= 0)
+    return;
+
+  timer_ = g_timeout_add(
+      5000, [](gpointer user_data) {
+        static_cast<DisplayStateManager*>(user_data)->Unlock();
+        return G_SOURCE_REMOVE;
+      }, this);
+}
+
+void DisplayStateManager::UnregisterUnlockTimer() {
+  if (timer_ == 0) return;
+
+  g_source_remove(timer_);
+  timer_ = 0;
+}
+
+bool DisplayStateManager::IsLocked() const {
+  return locked_;
+}
+
+DisplayStateManager::~DisplayStateManager() {
+  UnregisterUnlockTimer();
+  Unlock();
+}
+
+}  // namespace amd
diff --git a/src/lib/common/display_state_manager.hh b/src/lib/common/display_state_manager.hh
new file mode 100644 (file)
index 0000000..f6d7d8d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 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.
+ */
+
+#ifndef LIB_COMMON_DISPLAY_STATE_MANAGER_HH_
+#define LIB_COMMON_DISPLAY_STATE_MANAGER_HH_
+
+#include <glib.h>
+
+namespace amd {
+
+class DisplayStateManager {
+ public:
+  static DisplayStateManager& GetInst();
+
+  DisplayStateManager(const DisplayStateManager&) = delete;
+  DisplayStateManager& operator=(const DisplayStateManager&) = delete;
+  DisplayStateManager(DisplayStateManager&&) = delete;
+  DisplayStateManager& operator=(DisplayStateManager&&) = delete;
+
+  void Lock();
+  void Unlock();
+  void RegisterUnlockTimer();
+  void UnregisterUnlockTimer();
+  bool IsLocked() const;
+
+ private:
+  DisplayStateManager() = default;
+  ~DisplayStateManager();
+
+ private:
+  bool locked_ = false;
+  guint timer_ = 0;
+};
+
+}  // namespace amd
+
+#endif  // LIB_COMMON_DISPLAY_STATE_MANAGER_HH_