Add boot sequencer parser plugin 80/268480/37
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 23 Dec 2021 10:30:30 +0000 (19:30 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 13 Jan 2022 00:32:52 +0000 (09:32 +0900)
The parser plugin is added for boot sequencer. The application can
defined dependencies of boot. AMD will start on-boot applications using
dependencies.
The aulctl tool is added for boot sequencer.

Change-Id: Ib7e8874228df6bf9cf0c5eabb3777d16402755f3
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
34 files changed:
CMakeLists.txt
data/appsvc_db.sql.in
packaging/aul.spec
parser/CMakeLists.txt
parser/boot-sequencer/CMakeLists.txt [new file with mode: 0644]
parser/boot-sequencer/app_info.cc [new file with mode: 0644]
parser/boot-sequencer/app_info.hh [new file with mode: 0644]
parser/boot-sequencer/appsvc_db.cc [new file with mode: 0644]
parser/boot-sequencer/appsvc_db.hh [new file with mode: 0644]
parser/boot-sequencer/data/boot-sequencer.info [new file with mode: 0644]
parser/boot-sequencer/database.cc [new file with mode: 0644]
parser/boot-sequencer/database.hh [new file with mode: 0644]
parser/boot-sequencer/event_type.hh [new file with mode: 0644]
parser/boot-sequencer/exception.cc [new file with mode: 0644]
parser/boot-sequencer/exception.hh [new file with mode: 0644]
parser/boot-sequencer/log_private.hh [new file with mode: 0644]
parser/boot-sequencer/package_event_args.cc [new file with mode: 0644]
parser/boot-sequencer/package_event_args.hh [new file with mode: 0644]
parser/boot-sequencer/parser_plugin.cc [new file with mode: 0644]
parser/boot-sequencer/parser_plugin.hh [new file with mode: 0644]
parser/boot-sequencer/pkgmgr_interface.cc [new file with mode: 0644]
scripts/12_appsvc-add.post.in
scripts/upgrade/2_appsvc_db_upgrade.sh.in [new file with mode: 0755]
server/CMakeLists.txt
server/api/aul_boot_sequence.cc [new file with mode: 0644]
server/api/aul_boot_sequence.h [new file with mode: 0644]
server/boot_sequence.cc [new file with mode: 0644]
server/boot_sequence.hh [new file with mode: 0644]
server/exception.cc [new file with mode: 0644]
server/exception.hh
tool/CMakeLists.txt
tool/aulctl/CMakeLists.txt [new file with mode: 0644]
tool/aulctl/aulctl.cc [new file with mode: 0644]
tool/recovery/appsvc_db_recovery.c

index dcfc064..b513dd4 100644 (file)
@@ -28,6 +28,7 @@ SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Mo
 
 ## Target
 SET(TARGET_AUL "aul")
+SET(TARGET_AUL_SERVER "aul-server")
 
 ENABLE_TESTING()
 SET(TARGET_AUL_UNIT_TESTS "aul-unit-tests")
@@ -123,11 +124,14 @@ CONFIGURE_FILE(data/appsvc_db.sql.in data/appsvc_db.sql @ONLY)
 CONFIGURE_FILE(scripts/12_appsvc-add.post.in scripts/12_appsvc-add.post @ONLY)
 CONFIGURE_FILE(scripts/501.appsvc_db_upgrade.sh.in scripts/501.appsvc_db_upgrade.sh @ONLY)
 CONFIGURE_FILE(scripts/upgrade/1_appsvc_db_upgrade.sh.in scripts/upgrade/1_appsvc_db_upgrade.sh @ONLY)
+CONFIGURE_FILE(scripts/upgrade/2_appsvc_db_upgrade.sh.in scripts/upgrade/2_appsvc_db_upgrade.sh @ONLY)
 
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/501.appsvc_db_upgrade.sh
   DESTINATION /usr/share/upgrade/scripts)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/upgrade/1_appsvc_db_upgrade.sh
   DESTINATION /etc/aul/upgrade/scripts)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/upgrade/2_appsvc_db_upgrade.sh
+  DESTINATION /etc/aul/upgrade/scripts)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/aul.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/feature/preexec_list.txt DESTINATION ${SHARE_INSTALL_PREFIX}/aul )
 INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/miregex DESTINATION ${SHARE_INSTALL_PREFIX}/aul )
index 55713c4..82040c1 100755 (executable)
@@ -2,37 +2,52 @@ PRAGMA journal_mode = PERSIST;
 PRAGMA user_version = @APPSVC_DB_VERSION@;
 
 CREATE TABLE IF NOT EXISTS appsvc (
-        operation TEXT,
-        mime_type TEXT DEFAULT 'NULL',
-        uri TEXT DEFAULT 'NULL',
-        pkg_name TEXT,
-        PRIMARY KEY (operation,mime_type,uri)
+  operation TEXT,
+  mime_type TEXT DEFAULT 'NULL',
+  uri TEXT DEFAULT 'NULL',
+  pkg_name TEXT,
+  PRIMARY KEY (operation, mime_type, uri)
 );
 
 CREATE TABLE IF NOT EXISTS alias_info (
-       alias_appid TEXT NOT NULL,
-       appid TEXT NOT NULL,
-       enable TEXT NOT NULL DEFAULT 'true',
-       PRIMARY KEY (alias_appid)
+  alias_appid TEXT NOT NULL,
+  appid TEXT NOT NULL,
+  enable TEXT NOT NULL DEFAULT 'true',
+  PRIMARY KEY (alias_appid)
 );
 
 CREATE TABLE IF NOT EXISTS alias_info_for_uid (
-       appid TEXT NOT NULL,
-       uid INTEGER NOT NULL,
-       is_enabled TEXT NOT NULL DEFAULT 'false',
-       PRIMARY KEY (appid, uid)
+  appid TEXT NOT NULL,
+  uid INTEGER NOT NULL,
+  is_enabled TEXT NOT NULL DEFAULT 'false',
+  PRIMARY KEY (appid, uid)
 );
 
 CREATE TRIGGER IF NOT EXISTS update_alias_info_for_uid
-       AFTER UPDATE ON alias_info_for_uid
-       BEGIN
-               DELETE FROM alias_info_for_uid
-               WHERE is_enabled='true';
-       END;
+  AFTER UPDATE ON alias_info_for_uid
+  BEGIN
+    DELETE FROM alias_info_for_uid
+    WHERE is_enabled='true';
+  END;
 
 CREATE TABLE IF NOT EXISTS allowed_info (
-       appid TEXT NOT NULL,
-       allowed_appid TEXT NOT NULL,
-       PRIMARY KEY (appid, allowed_appid)
+  appid TEXT NOT NULL,
+  allowed_appid TEXT NOT NULL,
+  PRIMARY KEY (appid, allowed_appid)
 );
 
+CREATE TABLE IF NOT EXISTS boot_sequence (
+  package TEXT NOT NULL,
+  appid TEXT NOT NULL,
+  after TEXT NOT NULL,
+  before TEXT NOT NULL,
+  requires TEXT NOT NULL,
+  conflicts TEXT NOT NULL,
+  vconf TEXT NOT NULL,
+  path_exists TEXT NOT NULL,
+  args TEXT NOT NULL,
+  background_launch TEXT NOT NULL,
+  wait_until_ready TEXT NOT NULL,
+  timeout TEXT NOT NULL,
+  PRIMARY KEY (appid)
+);
index 1f4ae56..d5c778b 100644 (file)
@@ -111,7 +111,7 @@ Application Utility Library (devel)
 %endif
 
 %define _aulresdir /opt/usr/home/owner/share/aul/res
-%define appsvc_db_version 1
+%define appsvc_db_version 2
 %define component_db_version 1
 
 %prep
@@ -233,16 +233,19 @@ chmod +x %{_aulresdir}/tpk/install.sh
 %{_bindir}/appsvc-db-recovery
 %{_bindir}/component-db-recovery
 %{_bindir}/aul_window
+%{_bindir}/aulctl
 %{_datadir}/aul/miregex/*
 %{_datadir}/aul/preexec_list.txt
 %{_datadir}/appsvc/*
 %{_datadir}/parser-plugins/component.info
 %{_datadir}/parser-plugins/alias-appid.info
 %{_datadir}/parser-plugins/allowed-appid.info
+%{_datadir}/parser-plugins/boot-sequencer.info
 %{TZ_SYS_DB}/.appsvc.db*
 %{TZ_SYS_DB}/.component.db*
 %{_sysconfdir}/package-manager/parserlib/metadata/*.so
 %{_sysconfdir}/package-manager/parserlib/libcomponent-based-application.so
+%{_sysconfdir}/package-manager/parserlib/libboot-sequencer.so
 
 %attr(0755,root,root) %{_sysconfdir}/gumd/useradd.d/*
 %attr(0755,root,root) %{_datadir}/upgrade/scripts/501.component_upgrade.sh
index 9cb57bf..708ab4e 100644 (file)
@@ -1,3 +1,4 @@
-ADD_SUBDIRECTORY(exec-checker)
+ADD_SUBDIRECTORY(boot-sequencer)
 ADD_SUBDIRECTORY(component)
+ADD_SUBDIRECTORY(exec-checker)
 ADD_SUBDIRECTORY(metadata)
diff --git a/parser/boot-sequencer/CMakeLists.txt b/parser/boot-sequencer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..46b11a3
--- /dev/null
@@ -0,0 +1,28 @@
+SET(TARGET_BOOT_SEQUENCER_PARSER_PLUGIN "boot-sequencer")
+
+SET(SHARED_DIR "${CMAKE_INSTALL_PREFIX}/share")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Werror -Winline")
+
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}
+  BOOT_SEQUENCER_PARSER_PLUGIN_SRCS)
+
+ADD_LIBRARY(${TARGET_BOOT_SEQUENCER_PARSER_PLUGIN} SHARED
+  ${BOOT_SEQUENCER_PARSER_PLUGIN_SRCS})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_BOOT_SEQUENCER_PARSER_PLUGIN}
+  PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+
+APPLY_PKG_CONFIG(${TARGET_BOOT_SEQUENCER_PARSER_PLUGIN} PUBLIC
+  DLOG_DEPS
+  GLIB_DEPS
+  LIBTZPLATFORM_CONFIG_DEPS
+  LIBXML_DEPS
+  PKGMGR_INFO_DEPS
+  PKGMGR_INSTALLER_DEPS
+)
+
+INSTALL(TARGETS ${TARGET_BOOT_SEQUENCER_PARSER_PLUGIN}
+  DESTINATION ${SYSCONF_INSTALL_DIR}/package-manager/parserlib)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/boot-sequencer.info
+  DESTINATION ${SHARED_DIR}/parser-plugins)
diff --git a/parser/boot-sequencer/app_info.cc b/parser/boot-sequencer/app_info.cc
new file mode 100644 (file)
index 0000000..db9327d
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2022 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 "app_info.hh"
+
+namespace boot_sequencer {
+
+AppInfo::AppInfo(std::string appid) : appid_(std::move(appid)) {}
+
+const std::string& AppInfo::GetAppId() const {
+  return appid_;
+}
+
+const std::string& AppInfo::GetAfter() const {
+  return after_;
+}
+
+const std::string& AppInfo::GetBefore() const {
+  return before_;
+}
+
+const std::string& AppInfo::GetRequires() const {
+  return requires_;
+}
+
+const std::string& AppInfo::GetConflicts() const {
+  return conflicts_;
+}
+
+const std::string& AppInfo::GetArgs() const {
+  return args_;
+}
+
+const std::string& AppInfo::GetVconf() const {
+  return vconf_;
+}
+
+const std::string& AppInfo::GetPathExists() const {
+  return path_exists_;
+}
+
+const std::string& AppInfo::GetBackgroundLaunch() const {
+  return background_launch_;
+}
+
+const std::string& AppInfo::GetWaitUntilReady() const {
+  return wait_until_ready_;
+}
+
+const std::string& AppInfo::GetTimeout() const {
+  return timeout_;
+}
+
+void AppInfo::SetAfter(std::string after) {
+  if (after_.empty())
+    after_ = std::move(after);
+  else
+    after_ += "|" + std::move(after);
+}
+
+void AppInfo::SetBefore(std::string before) {
+  if (before_.empty())
+    before_ = std::move(before);
+  else
+    before_ += "|" + std::move(before);
+}
+
+void AppInfo::SetRequires(std::string requires) {
+  if (requires_.empty())
+    requires_ = std::move(requires);
+  else
+    requires_ += "|" + std::move(requires);
+}
+
+void AppInfo::SetConflicts(std::string conflicts) {
+  if (conflicts_.empty())
+    conflicts_ = std::move(conflicts);
+  else
+    conflicts_ += "|" + std::move(conflicts);
+}
+
+void AppInfo::SetArgs(std::string args) {
+  args_ = std::move(args);
+}
+
+void AppInfo::SetVconf(std::string vconf) {
+  if (vconf_.empty())
+    vconf_ = std::move(vconf);
+  else
+    vconf_ += "|" + std::move(vconf);
+}
+
+void AppInfo::SetPathExists(std::string path_exists) {
+  if (path_exists_.empty())
+    path_exists_ = std::move(path_exists);
+  else
+    path_exists_ += "|" + std::move(path_exists);
+}
+
+void AppInfo::SetBackgroundLaunch(std::string background_launch) {
+  background_launch_ = std::move(background_launch);
+}
+
+void AppInfo::SetWaitUntilReady(std::string wait_until_ready) {
+  wait_until_ready_ = std::move(wait_until_ready);
+}
+
+void AppInfo::SetTimeout(std::string timeout) {
+  timeout_ = std::move(timeout);
+}
+
+}  // namespace boot_sequencer
diff --git a/parser/boot-sequencer/app_info.hh b/parser/boot-sequencer/app_info.hh
new file mode 100644 (file)
index 0000000..d9de0f3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022 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 APP_INFO_HH_
+#define APP_INFO_HH_
+
+#include <string>
+
+namespace boot_sequencer {
+
+class AppInfo {
+ public:
+  AppInfo(std::string appid);
+
+  const std::string& GetAppId() const;
+  const std::string& GetAfter() const;
+  const std::string& GetBefore() const;
+  const std::string& GetRequires() const;
+  const std::string& GetConflicts() const;
+  const std::string& GetArgs() const;
+  const std::string& GetVconf() const;
+  const std::string& GetPathExists() const;
+  const std::string& GetBackgroundLaunch() const;
+  const std::string& GetWaitUntilReady() const;
+  const std::string& GetTimeout() const;
+
+  void SetAfter(std::string after);
+  void SetBefore(std::string before);
+  void SetRequires(std::string requires);
+  void SetConflicts(std::string conflicts);
+  void SetArgs(std::string args);
+  void SetVconf(std::string vconf);
+  void SetPathExists(std::string path_exists);
+  void SetBackgroundLaunch(std::string background_launch);
+  void SetWaitUntilReady(std::string wait_until_ready);
+  void SetTimeout(std::string timeout);
+
+ private:
+  std::string appid_;
+  std::string after_;
+  std::string before_;
+  std::string requires_;
+  std::string conflicts_;
+  std::string args_;
+  std::string vconf_;
+  std::string path_exists_;
+  std::string background_launch_;
+  std::string wait_until_ready_;
+  std::string timeout_;
+};
+
+}  // namespace boot_sequencer
+
+#endif  // APP_INFO_HH_
diff --git a/parser/boot-sequencer/appsvc_db.cc b/parser/boot-sequencer/appsvc_db.cc
new file mode 100644 (file)
index 0000000..a339763
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2022 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 <tzplatform_config.h>
+
+#include <memory>
+
+#include "appsvc_db.hh"
+#include "log_private.hh"
+
+namespace boot_sequencer {
+namespace {
+
+constexpr const uid_t ROOT_UID = 0;
+
+const uid_t GLOBAL_USER = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+
+constexpr const char QUERY_SELECT[] =
+    "SELECT appid, after, before, requires, conflicts, vconf, path_exists, "
+    "args, background_launch, wait_until_ready, timeout "
+    "FROM boot_sequence WHERE package = ?;";
+constexpr const char QUERY_INSERT_OR_REPLACE[] =
+    "INSERT OR REPLACE INTO boot_sequence(package, appid, after, before, "
+    "requires, conflicts, vconf, path_exists, args, background_launch, "
+    "wait_until_ready, timeout) "
+    "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
+constexpr const char QUERY_DELETE[] =
+    "DELETE FROM boot_sequence WHERE package = ?;";
+
+}  // namespace
+
+AppSvcDB::AppSvcDB(uid_t uid) : Database(GetDBPath(uid)) {
+}
+
+AppSvcDB::~AppSvcDB() = default;
+
+std::vector<std::shared_ptr<AppInfo>> AppSvcDB::Select(
+    const std::string& package) {
+  std::vector<std::string> bind_text { package };
+  auto cursor = Query(QUERY_SELECT, bind_text);
+  if (cursor == nullptr)
+    return {};
+
+  cursor->Execute();
+  int idx;
+  std::vector<std::shared_ptr<AppInfo>> app_infos;
+  while (!cursor->IsDone()) {
+    idx = 0;
+    auto appid = cursor->GetColumn(idx++);
+    auto app_info = std::make_shared<AppInfo>(std::move(appid));
+    app_info->SetAfter(std::move(cursor->GetColumn(idx++)));
+    app_info->SetBefore(std::move(cursor->GetColumn(idx++)));
+    app_info->SetRequires(std::move(cursor->GetColumn(idx++)));
+    app_info->SetConflicts(std::move(cursor->GetColumn(idx++)));
+    app_info->SetVconf(std::move(cursor->GetColumn(idx++)));
+    app_info->SetPathExists(std::move(cursor->GetColumn(idx++)));
+    app_info->SetArgs(std::move(cursor->GetColumn(idx++)));
+    app_info->SetBackgroundLaunch(std::move(cursor->GetColumn(idx++)));
+    app_info->SetWaitUntilReady(std::move(cursor->GetColumn(idx++)));
+    app_info->SetTimeout(std::move(cursor->GetColumn(idx++)));
+    app_infos.push_back(std::move(app_info));
+    cursor->Next();
+  }
+
+  return app_infos;
+}
+
+void AppSvcDB::Insert(const std::string& package,
+    const std::shared_ptr<AppInfo>& app_info) {
+  std::vector<std::string> bind_text {
+    package,
+    app_info->GetAppId(),
+    app_info->GetAfter(),
+    app_info->GetBefore(),
+    app_info->GetRequires(),
+    app_info->GetConflicts(),
+    app_info->GetVconf(),
+    app_info->GetPathExists(),
+    app_info->GetArgs(),
+    app_info->GetBackgroundLaunch(),
+    app_info->GetWaitUntilReady(),
+    app_info->GetTimeout()
+  };
+  auto cursor = Query(QUERY_INSERT_OR_REPLACE, bind_text);
+  if (cursor == nullptr)
+    THROW(-1);
+
+  if (!cursor->Execute())
+    THROW(-1);
+}
+
+void AppSvcDB::Delete(const std::string& package) {
+  std::vector<std::string> bind_text { package };
+  auto cursor = Query(QUERY_DELETE, bind_text);
+  if (cursor == nullptr)
+    THROW(-1);
+
+  if (!cursor->Execute())
+    THROW(-1);
+}
+
+std::string AppSvcDB::GetDBPath(uid_t uid) {
+  std::string db_path;
+  if (uid == ROOT_UID || uid == GLOBAL_USER) {
+    db_path = std::string(tzplatform_getenv(TZ_SYS_DB)) + "/.appsvc.db";
+  } else {
+    db_path = std::string(tzplatform_getenv(TZ_SYS_DB)) + "/user/" +
+      std::to_string(uid) +  "/.appsvc.db";
+  }
+  return db_path;
+}
+
+}  // namespace boot_sequencer
diff --git a/parser/boot-sequencer/appsvc_db.hh b/parser/boot-sequencer/appsvc_db.hh
new file mode 100644 (file)
index 0000000..4aedad6
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022 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 APPSVC_DB_HH_
+#define APPSVC_DB_HH_
+
+#include <unistd.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "app_info.hh"
+#include "database.hh"
+
+namespace boot_sequencer {
+
+class AppSvcDB : public Database {
+ public:
+  AppSvcDB(uid_t uid);
+  virtual ~AppSvcDB();
+
+  std::vector<std::shared_ptr<AppInfo>> Select(const std::string& package);
+  void Insert(const std::string& package,
+      const std::shared_ptr<AppInfo>& app_info);
+  void Delete(const std::string& package);
+
+ private:
+  static std::string GetDBPath(uid_t uid);
+};
+
+}  // namespace boot_sequencer
+
+#endif  // APPSVC_DB_HH_
diff --git a/parser/boot-sequencer/data/boot-sequencer.info b/parser/boot-sequencer/data/boot-sequencer.info
new file mode 100644 (file)
index 0000000..fff4abc
--- /dev/null
@@ -0,0 +1,2 @@
+type="tag";name="ui-application";path="/etc/package-manager/parserlib/libboot-sequencer.so"
+type="tag";name="service-application";path="/etc/package-manager/parserlib/libboot-sequencer.so"
diff --git a/parser/boot-sequencer/database.cc b/parser/boot-sequencer/database.cc
new file mode 100644 (file)
index 0000000..761b1a2
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2022 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 <unistd.h>
+
+#include <memory>
+
+#include "database.hh"
+#include "exception.hh"
+#include "log_private.hh"
+
+namespace boot_sequencer {
+
+static const int BUSY_WAITING_USEC = 50000;
+static const int BUSY_WAITING_MAX = 40;
+
+Database::Cursor::~Cursor() {
+  if (stmt_ != nullptr)
+    sqlite3_finalize(stmt_);
+}
+
+Database::Cursor::Cursor(sqlite3* db, const std::string& query,
+    const std::vector<std::string>& bind_text) {
+  sqlite3_stmt* stmt;
+  int ret = sqlite3_prepare_v2(db, query.c_str(), query.length(), &stmt,
+      nullptr);
+  auto stmt_auto = std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*>(
+      stmt, sqlite3_finalize);
+  if (ret != SQLITE_OK) {
+    _E("sqlite3_prepare_v2() is failed. error(%s:%d)", sqlite3_errmsg(db), ret);
+    THROW(-ret);
+  }
+
+  int index = 1;
+  for (auto const& text : bind_text) {
+    ret = sqlite3_bind_text(stmt, index++, text.c_str(), -1, SQLITE_TRANSIENT);
+    if (ret != SQLITE_OK) {
+      _E("sqlite3_bind_text() is failed. index(%d), error(%s:%d)",
+          index - 1, sqlite3_errmsg(db), ret);
+      THROW(-ret);
+    }
+  }
+
+  stmt_ = stmt_auto.release();
+}
+
+void Database::Cursor::Next() {
+  int ret = sqlite3_step(stmt_);
+  if (ret == SQLITE_ROW)
+    return;
+
+  if (ret == SQLITE_DONE)
+    _D("SQLITE_DONE");
+  else if (ret == SQLITE_BUSY)
+    _E("SQLITE_BUSY");
+  else if (ret == SQLITE_ERROR)
+    _E("SQLITE_ERROR");
+  else if (ret == SQLITE_MISUSE)
+    _E("SQLITE_MISUSE");
+
+  done_ = true;
+}
+
+bool Database::Cursor::IsDone() const {
+  return done_;
+}
+
+bool Database::Cursor::Execute() {
+  int ret = sqlite3_step(stmt_);
+  if (ret != SQLITE_DONE) {
+    _E("sqlite3_step() is failed. error(%d)", ret);
+    if (ret != SQLITE_ROW)
+      done_ = true;
+
+    return false;
+  }
+
+  done_ = true;
+  return true;
+}
+
+std::string Database::Cursor::GetColumn(int index) {
+  auto* text = reinterpret_cast<const char*>(sqlite3_column_text(stmt_, index));
+  if (text)
+    return std::string(text);
+
+  return {};
+}
+
+Database::Database(std::string path) : path_(std::move(path)) {}
+
+Database::~Database() {
+  Close();
+}
+
+void Database::BeginTransaction() {
+  int ret = sqlite3_exec(db_, "BEGIN TRANSACTION", nullptr, nullptr, nullptr);
+  if (ret != SQLITE_OK) {
+    _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
+    THROW(-ret);
+  }
+}
+
+void Database::EndTransaction() {
+  int ret = sqlite3_exec(db_, "END TRANSACTION", nullptr, nullptr, nullptr);
+  if (ret != SQLITE_OK) {
+    _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
+    THROW(-ret);
+  }
+}
+
+void Database::Rollback() {
+  int ret = sqlite3_exec(db_, "ROLLBACK", nullptr, nullptr, nullptr);
+  if (ret != SQLITE_OK) {
+    _E("sqlite3_exec() is failed. error(%s:%d", sqlite3_errmsg(db_), ret);
+    THROW(-ret);
+  }
+}
+
+void Database::Open() {
+  sqlite3* db;
+  int ret = sqlite3_open_v2(path_.c_str(), &db, SQLITE_OPEN_READWRITE, nullptr);
+  if (ret != SQLITE_OK) {
+    _E("sqlite3_open_v2() is failed. error(%d)", ret);
+    sqlite3_close_v2(db);
+    THROW(-ret);
+  }
+
+  ret = sqlite3_busy_handler(db, BusyHandler,
+      static_cast<void*>(const_cast<char*>(path_.c_str())));
+  if (ret != SQLITE_OK) {
+    _E("sqlite3_busy_handler() is failed. error(%s:%d)",
+        sqlite3_errmsg(db), ret);
+    sqlite3_close_v2(db);
+    THROW(-ret);
+  }
+
+  ret = sqlite3_exec(db, "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
+  if (ret != SQLITE_OK) {
+    _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db), ret);
+    sqlite3_close_v2(db);
+    THROW(-ret);
+  }
+
+  db_ = db;
+}
+
+void Database::Close() {
+  if (db_) {
+    sqlite3_close_v2(db_);
+    db_ = nullptr;
+  }
+}
+
+std::shared_ptr<Database::Cursor> Database::Query(const std::string& query,
+    const std::vector<std::string>& bind_text) {
+  try {
+    auto cursor = std::shared_ptr<Database::Cursor>(
+        new Database::Cursor(db_, query, bind_text));
+    return cursor;
+  } catch (const Exception& e) {
+    return nullptr;
+  }
+}
+
+int Database::BusyHandler(void* data, int count) {
+  if (count < BUSY_WAITING_MAX) {
+    usleep(BUSY_WAITING_USEC);
+    return 1;
+  }
+
+  auto* path = static_cast<char*>(data);
+  _E("Database(%s) is busy", path);
+  return 0;
+}
+
+}  // namespace boot_sequencer
diff --git a/parser/boot-sequencer/database.hh b/parser/boot-sequencer/database.hh
new file mode 100644 (file)
index 0000000..8e0b9ed
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2022 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 DATABASE_HH_
+#define DATABASE_HH_
+
+#include <sqlite3.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "exception.hh"
+
+namespace boot_sequencer {
+
+class Database {
+ public:
+  class Cursor {
+   public:
+    ~Cursor();
+    Cursor(const Cursor&) = delete;
+    Cursor& operator=(const Cursor&) = delete;
+
+    void Next();
+    bool IsDone() const;
+    bool Execute();
+    std::string GetColumn(int index);
+
+   private:
+    friend class Database;
+    Cursor(sqlite3* db, const std::string& query,
+        const std::vector<std::string>& bind_text);
+
+   private:
+    sqlite3_stmt* stmt_ = nullptr;
+    bool done_ = false;
+  };
+
+  Database(std::string path);
+  virtual ~Database();
+
+  void Open();
+  void Close();
+  void BeginTransaction();
+  void EndTransaction();
+  void Rollback();
+  std::shared_ptr<Cursor> Query(const std::string& query,
+      const std::vector<std::string>& bind_text);
+
+ private:
+  static int BusyHandler(void* data, int count);
+
+ private:
+  std::string path_;
+  sqlite3* db_ = nullptr;
+};
+
+}  // namespace boot_sequencer
+
+#endif  // DATABASE_HH_
diff --git a/parser/boot-sequencer/event_type.hh b/parser/boot-sequencer/event_type.hh
new file mode 100644 (file)
index 0000000..3e9aab5
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022 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 EVENT_TYPE_HH_
+#define EVENT_TYPE_HH_
+
+namespace boot_sequencer {
+
+enum class EventType {
+  Install,
+  Uninstall,
+  Upgrade,
+};
+
+}  // namespace boot_sequencer
+
+#endif  // EVENT_TYPE_HH_
diff --git a/parser/boot-sequencer/exception.cc b/parser/boot-sequencer/exception.cc
new file mode 100644 (file)
index 0000000..59b5f41
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 "exception.hh"
+
+#include <libgen.h>
+
+namespace boot_sequencer {
+
+Exception::Exception(int error_code, std::string file, int line)
+    : error_code_(error_code) {
+  message_ = std::string(basename(const_cast<char*>(file.c_str()))) + ":" +
+      std::to_string(line) + " code:" + std::to_string(error_code_);
+}
+
+Exception::~Exception() = default;
+
+const char* Exception::what() const noexcept {
+  return message_.c_str();
+}
+
+int Exception::GetErrorCode() const {
+  return error_code_;
+}
+
+}  // namespace boot_sequencer
diff --git a/parser/boot-sequencer/exception.hh b/parser/boot-sequencer/exception.hh
new file mode 100644 (file)
index 0000000..e302aab
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 EXCEPTION_HH_
+#define EXCEPTION_HH_
+
+#include <exception>
+#include <string>
+
+#define THROW(error_code) throw Exception(error_code, __FILE__, __LINE__)
+
+namespace boot_sequencer {
+
+class Exception : public std::exception {
+ public:
+  explicit Exception(int error_code, std::string file, int line);
+  virtual ~Exception();
+
+  virtual const char* what() const noexcept;
+  int GetErrorCode() const;
+
+ private:
+  int error_code_;
+  std::string message_;
+};
+
+}  // namespace boot_sequencer
+
+#endif  // EXCEPTION_HH_
diff --git a/parser/boot-sequencer/log_private.hh b/parser/boot-sequencer/log_private.hh
new file mode 100644 (file)
index 0000000..4d2eca3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 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 LOG_PRIVATE_HH_
+#define LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "BOOT_SEQUENCER_PLUGIN_PARSER"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif  // LOG_PRIVATE_HH_
diff --git a/parser/boot-sequencer/package_event_args.cc b/parser/boot-sequencer/package_event_args.cc
new file mode 100644 (file)
index 0000000..6c91b9c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022 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 "package_event_args.hh"
+
+namespace boot_sequencer {
+
+PackageEventArgs::PackageEventArgs(std::string package, EventType event_type)
+    : package_(std::move(package)),
+      event_type_(event_type) {
+}
+
+const std::string& PackageEventArgs::GetPackage() const {
+  return package_;
+}
+
+EventType PackageEventArgs::GetEventType() const {
+  return event_type_;
+}
+
+void PackageEventArgs::Push(std::shared_ptr<AppInfo> app_info) {
+  app_infos_.push_back(std::move(app_info));
+}
+
+const std::vector<std::shared_ptr<AppInfo>>&
+PackageEventArgs::GetAppInfos() const {
+  return app_infos_;
+}
+
+void PackageEventArgs::Reset(std::vector<std::shared_ptr<AppInfo>> app_infos) {
+  app_infos_ = std::move(app_infos);
+}
+
+}  // namespace boot_sequencer
diff --git a/parser/boot-sequencer/package_event_args.hh b/parser/boot-sequencer/package_event_args.hh
new file mode 100644 (file)
index 0000000..67692e5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022 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 PACKAGE_EVENT_ARGS_HH_
+#define PACKAGE_EVENT_ARGS_HH_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "app_info.hh"
+#include "event_type.hh"
+
+namespace boot_sequencer {
+
+class PackageEventArgs {
+ public:
+  PackageEventArgs(std::string package, EventType event_type);
+
+  const std::string& GetPackage() const;
+  EventType GetEventType() const;
+
+  void Push(std::shared_ptr<AppInfo> app_info);
+  const std::vector<std::shared_ptr<AppInfo>>& GetAppInfos() const;
+  void Reset(std::vector<std::shared_ptr<AppInfo>> app_infos);
+
+ private:
+  std::string package_;
+  EventType event_type_;
+  std::vector<std::shared_ptr<AppInfo>> app_infos_;
+};
+
+}  // namespace boot_sequencer
+
+#endif  // PACKAGE_EVENT_ARGS_HH_
diff --git a/parser/boot-sequencer/parser_plugin.cc b/parser/boot-sequencer/parser_plugin.cc
new file mode 100644 (file)
index 0000000..fa55b0d
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2022 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 "parser_plugin.hh"
+
+#include <pkgmgr_installer_info.h>
+#include <unistd.h>
+
+#include "log_private.hh"
+
+namespace boot_sequencer {
+namespace {
+
+std::string GetName(xmlNode* node) {
+  if (node == nullptr)
+    return {};
+
+  return std::string(reinterpret_cast<const char*>(node->name));
+}
+
+std::string GetAttribute(xmlNode* node, const char* key) {
+  xmlChar* val = xmlGetProp(node, reinterpret_cast<const xmlChar*>(key));
+  if (val != nullptr) {
+    std::string attr(reinterpret_cast<char*>(val));
+    xmlFree(val);
+    return attr;
+  }
+
+  return {};
+}
+
+uid_t GetTargetUid() {
+  uid_t target_uid;
+  pkgmgr_installer_info_get_target_uid(&target_uid);
+  return target_uid;
+}
+
+}  // namespace
+
+ParserPlugin& ParserPlugin::GetInst() {
+  static ParserPlugin inst;
+  return inst;
+}
+
+void ParserPlugin::Init(xmlDocPtr doc, std::string package,
+    EventType event_type) {
+  doc_ = doc;
+  args_ = std::unique_ptr<PackageEventArgs>(
+      new PackageEventArgs(package, event_type));
+  backup_args_ = std::unique_ptr<PackageEventArgs>(
+      new PackageEventArgs(std::move(package), event_type));
+}
+
+int ParserPlugin::Process() {
+  int ret = Prepare();
+  if (ret != 0)
+    return ret;
+
+  ret = StepBackup();
+  if (ret != 0) {
+    Post();
+    return ret;
+  }
+
+  if (args_->GetEventType() == EventType::Install)
+    ret = StepInstall();
+  else if (args_->GetEventType() == EventType::Uninstall)
+    ret = StepUninstall();
+  else if (args_->GetEventType() == EventType::Upgrade)
+    ret = StepUpgrade();
+
+  if (ret != 0)
+    Rollback();
+
+  Post();
+  return ret;
+}
+
+int ParserPlugin::Undo() {
+  _E("Undo");
+  int ret = Prepare();
+  if (ret != 0)
+    return ret;
+
+  ret = StepUninstall();
+  if (ret != 0)
+    return ret;
+
+  ret = StepRestore();
+  Post();
+  return ret;
+}
+
+ParserPlugin::ParserPlugin() : db_(new AppSvcDB(GetTargetUid())) {}
+
+ParserPlugin::~ParserPlugin() = default;
+
+int ParserPlugin::Prepare() {
+  try {
+    db_->Open();
+    db_->BeginTransaction();
+  } catch (const Exception& e) {
+    _E("Exception(%s) occurs", e.what());
+    return e.GetErrorCode();
+  }
+
+  return 0;
+}
+
+int ParserPlugin::StepBackup() {
+  try {
+    auto app_infos = db_->Select(backup_args_->GetPackage());
+    backup_args_->Reset(std::move(app_infos));
+  } catch (const Exception& e) {
+    _E("Exception(%s) occurs", e.what());
+    return e.GetErrorCode();
+  }
+
+  return 0;
+}
+
+int ParserPlugin::StepInstall() {
+  int ret = Parse();
+  if (ret != 0)
+    return ret;
+
+  for (auto& app_info : args_->GetAppInfos()) {
+    try {
+      db_->Insert(args_->GetPackage(), app_info);
+    } catch (const Exception& e) {
+      _E("Exception(%s) occurs", e.what());
+      return e.GetErrorCode();
+    }
+  }
+
+  return 0;
+}
+
+int ParserPlugin::StepUninstall() {
+  try {
+    db_->Delete(args_->GetPackage());
+  } catch (const Exception& e) {
+    _E("Exception(%s) occurs", e.what());
+    return e.GetErrorCode();
+  }
+
+  return 0;
+}
+
+int ParserPlugin::StepUpgrade() {
+  int ret = StepUninstall();
+  if (ret != 0)
+    return ret;
+
+  return StepInstall();
+}
+
+int ParserPlugin::StepRestore() {
+  _E("Restore");
+  for (auto& app_info : backup_args_->GetAppInfos()) {
+    try {
+      db_->Insert(backup_args_->GetPackage(), app_info);
+    } catch (const Exception& e) {
+      _E("Exception(%s) occurs", e.what());
+      return e.GetErrorCode();
+    }
+  }
+
+  return 0;
+}
+
+void ParserPlugin::Post() {
+  try {
+    db_->EndTransaction();
+    db_->Close();
+  } catch (const Exception& e) {
+    _E("Exception(%s) occurs", e.what());
+  }
+}
+
+void ParserPlugin::Rollback() {
+  try {
+    db_->Rollback();
+  } catch (const Exception& e) {
+    _E("Exception(%s) occurs", e.what());
+  }
+}
+
+int ParserPlugin::Parse() {
+  xmlNode* root = xmlDocGetRootElement(doc_);
+  if (root == nullptr) {
+    _E("xmlDocGetRootElement() is failed");
+    return -1;
+  }
+
+  for (xmlNode* node = root->children; node; node = node->next) {
+    std::string appid = GetAttribute(node, "appid");
+    if (appid.empty())
+      continue;
+
+    std::string onboot = GetAttribute(node, "on-boot");
+    if (onboot != "true")
+      continue;
+
+    auto app_info = new (std::nothrow) AppInfo(appid);
+    if (app_info == nullptr) {
+      _E("Out of memory");
+      return -1;
+    }
+
+    for (xmlNode* child_node = node->children; child_node;
+         child_node = child_node->next) {
+      std::string name = GetName(child_node);
+      if (name != "boot-sequence")
+        continue;
+
+      ParseBootSequence(child_node, app_info);
+    }
+
+    args_->Push(std::shared_ptr<AppInfo>(app_info));
+  }
+
+  return 0;
+}
+
+void ParserPlugin::ParseBootSequence(xmlNode* node, AppInfo* app_info) {
+  for (xmlNode* child_node = node->children; child_node;
+       child_node = child_node->next) {
+    std::string name = GetName(child_node);
+    if (name == "dependency") {
+      auto after = GetAttribute(child_node, "after");
+      if (!after.empty())
+        app_info->SetAfter(std::move(after));
+
+      auto before = GetAttribute(child_node, "before");
+      if (!before.empty())
+        app_info->SetBefore(std::move(before));
+
+      auto requires = GetAttribute(child_node, "requires");
+      if (!requires.empty())
+        app_info->SetRequires(std::move(requires));
+
+      auto conflicts = GetAttribute(child_node, "conflicts");
+      if (!conflicts.empty())
+        app_info->SetConflicts(std::move(conflicts));
+
+      auto vconf = GetAttribute(child_node, "vconf");
+      if (!vconf.empty())
+        app_info->SetVconf(std::move(vconf));
+
+      auto path_exists = GetAttribute(child_node, "path-exists");
+      if (!path_exists.empty())
+        app_info->SetPathExists(std::move(path_exists));
+    } else if (name == "option") {
+      auto args = GetAttribute(child_node, "args");
+      if (!args.empty())
+        app_info->SetArgs(std::move(args));
+
+      auto background_launch = GetAttribute(child_node, "background-launch");
+      if (!background_launch.empty())
+        app_info->SetBackgroundLaunch(std::move(background_launch));
+
+      auto wait_until_ready = GetAttribute(child_node, "wait-until-ready");
+      if (!wait_until_ready.empty())
+        app_info->SetWaitUntilReady(std::move(wait_until_ready));
+
+      auto timeout = GetAttribute(child_node, "timeout");
+      if (!timeout.empty())
+        app_info->SetTimeout(std::move(timeout));
+    }
+  }
+
+  if (app_info->GetBackgroundLaunch().empty() ||
+      app_info->GetBackgroundLaunch() != "true" ||
+      app_info->GetBackgroundLaunch() != "false")
+    app_info->SetBackgroundLaunch("true");
+
+  if (app_info->GetWaitUntilReady().empty() ||
+      app_info->GetWaitUntilReady() != "true" ||
+      app_info->GetWaitUntilReady() != "false")
+    app_info->SetWaitUntilReady("true");
+
+  // Default timeout: 5 seconds
+  if (app_info->GetTimeout().empty())
+    app_info->SetTimeout("5000");
+}
+
+}  // namespace boot_sequencer
diff --git a/parser/boot-sequencer/parser_plugin.hh b/parser/boot-sequencer/parser_plugin.hh
new file mode 100644 (file)
index 0000000..df15223
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022 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 PARSER_PLUGIN_HH_
+#define PARSER_PLUGIN_HH_
+
+#include <libxml/tree.h>
+
+#include <memory>
+#include <string>
+
+#include "appsvc_db.hh"
+#include "package_event_args.hh"
+
+namespace boot_sequencer {
+
+class ParserPlugin {
+ public:
+  static ParserPlugin& GetInst();
+  void Init(xmlDocPtr doc, std::string package, EventType event_type);
+
+  int Process();
+  int Undo();
+
+ private:
+  ParserPlugin();
+  ~ParserPlugin();
+
+  int Prepare();
+  int StepBackup();
+  int StepInstall();
+  int StepUninstall();
+  int StepUpgrade();
+  int StepRestore();
+  void Post();
+  void Rollback();
+
+  int Parse();
+  void ParseBootSequence(xmlNode* node, AppInfo* app_info);
+
+ private:
+  std::unique_ptr<AppSvcDB> db_;
+  xmlDocPtr doc_;
+  std::unique_ptr<PackageEventArgs> args_;
+  std::unique_ptr<PackageEventArgs> backup_args_;
+};
+
+}  // namespace boot_sequencer
+
+#endif  // PARSER_PLUGIN_HH_
diff --git a/parser/boot-sequencer/pkgmgr_interface.cc b/parser/boot-sequencer/pkgmgr_interface.cc
new file mode 100644 (file)
index 0000000..39142dc
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2022 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 <glib.h>
+#include <libxml/tree.h>
+
+#include "parser_plugin.hh"
+
+#undef EXPORT
+#define EXPORT __attribute__ ((visibility("default")))
+
+using namespace boot_sequencer;
+
+extern "C" EXPORT int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc,
+    const char* package) {
+  auto& plugin = ParserPlugin::GetInst();
+  plugin.Init(doc, package, EventType::Install);
+  return plugin.Process();
+}
+
+extern "C" EXPORT int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr doc,
+    const char* package) {
+  auto& plugin = ParserPlugin::GetInst();
+  plugin.Init(doc, package, EventType::Upgrade);
+  return plugin.Process();
+}
+
+extern "C" EXPORT int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr doc,
+    const char* package) {
+  auto& plugin = ParserPlugin::GetInst();
+  plugin.Init(doc, package, EventType::Uninstall);
+  return plugin.Process();
+}
+
+extern "C" EXPORT int PKGMGR_PARSER_PLUGIN_RECOVERINSTALL(xmlDocPtr doc,
+    const char* package) {
+  auto& plugin = ParserPlugin::GetInst();
+  plugin.Init(doc, package, EventType::Uninstall);
+  return plugin.Process();
+}
+
+extern "C" EXPORT int PKGMGR_PARSER_PLUGIN_RECOVERUPGRADE(xmlDocPtr doc,
+    const char* package) {
+  auto& plugin = ParserPlugin::GetInst();
+  plugin.Init(doc, package, EventType::Upgrade);
+  return plugin.Process();
+}
+
+extern "C" EXPORT int PKGMGR_PARSER_PLUGIN_RECOVERUNINSTALL(xmlDocPtr doc,
+    const char* package) {
+  auto& plugin = ParserPlugin::GetInst();
+  plugin.Init(doc, package, EventType::Uninstall);
+  return plugin.Process();
+}
+
+extern "C" EXPORT int PKGMGR_PARSER_PLUGIN_UNDO(xmlDocPtr doc,
+    const char* package) {
+  return ParserPlugin::GetInst().Undo();
+}
index 5f342f5..e8126cf 100755 (executable)
@@ -19,38 +19,54 @@ PRAGMA journal_mode = PERSIST;
 PRAGMA user_version = @APPSVC_DB_VERSION@;
 
 CREATE TABLE IF NOT EXISTS appsvc (
-       operation TEXT,
-       mime_type TEXT DEFAULT 'NULL',
-       uri TEXT DEFAULT 'NULL',
-       pkg_name TEXT,
-       PRIMARY KEY (operation,mime_type,uri)
+  operation TEXT,
+  mime_type TEXT DEFAULT 'NULL',
+  uri TEXT DEFAULT 'NULL',
+  pkg_name TEXT,
+  PRIMARY KEY (operation,mime_type,uri)
 );
 
 CREATE TABLE IF NOT EXISTS alias_info (
-       alias_appid TEXT NOT NULL,
-       appid TEXT NOT NULL,
-       enable TEXT NOT NULL DEFAULT 'true',
-       PRIMARY KEY (alias_appid)
+  alias_appid TEXT NOT NULL,
+  appid TEXT NOT NULL,
+  enable TEXT NOT NULL DEFAULT 'true',
+  PRIMARY KEY (alias_appid)
 );
 
 CREATE TABLE IF NOT EXISTS alias_info_for_uid (
-       appid TEXT NOT NULL,
-       uid INTEGER NOT NULL,
-       is_enabled TEXT NOT NULL DEFAULT 'false',
-       PRIMARY KEY (appid, uid)
+  appid TEXT NOT NULL,
+  uid INTEGER NOT NULL,
+  is_enabled TEXT NOT NULL DEFAULT 'false',
+  PRIMARY KEY (appid, uid)
 );
 
 CREATE TRIGGER IF NOT EXISTS update_alias_info_for_uid
-       AFTER UPDATE ON alias_info_for_uid
-       BEGIN
-               DELETE FROM alias_info_for_uid
-               WHERE is_enabled='true';
-       END;
+  AFTER UPDATE ON alias_info_for_uid
+  BEGIN
+    DELETE FROM alias_info_for_uid
+    WHERE is_enabled='true';
+  END;
 
 CREATE TABLE IF NOT EXISTS allowed_info (
-       appid TEXT NOT NULL,
-       allowed_appid TEXT NOT NULL,
-       PRIMARY KEY (appid, allowed_appid)
+  appid TEXT NOT NULL,
+  allowed_appid TEXT NOT NULL,
+  PRIMARY KEY (appid, allowed_appid)
+);
+
+CREATE TABLE IF NOT EXISTS boot_sequence (
+  package TEXT NOT NULL,
+  appid TEXT NOT NULL,
+  after TEXT NOT NULL,
+  before TEXT NOT NULL,
+  requires TEXT NOT NULL,
+  conflicts TEXT NOT NULL,
+  vconf TEXT NOT NULL,
+  path_exists TEXT NOT NULL,
+  args TEXT NOT NULL,
+  background_launch TEXT NOT NULL,
+  wait_until_ready TEXT NOT NULL,
+  timeout TEXT NOT NULL,
+  PRIMARY KEY (appid)
 );
 
 EOF
diff --git a/scripts/upgrade/2_appsvc_db_upgrade.sh.in b/scripts/upgrade/2_appsvc_db_upgrade.sh.in
new file mode 100755 (executable)
index 0000000..b7b1d5e
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+#------------------------------------------#
+# appsvc db upgrade ver.2                  #
+#------------------------------------------#
+
+# Macro
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+
+PATH_DB="$1"
+PATH_NEW_DB="${PATH_DB}.new"
+PATH_BACKUP_DB="${PATH_DB}.bak"
+
+Init() {
+  echo "### Initialize"
+  cp ${PATH_DB} ${PATH_BACKUP_DB}
+  cp ${PATH_DB}-journal ${PATH_BACKUP_DB}-journal
+}
+
+# Create new Table
+CreateNewTable() {
+  echo " - Create new table: ${PATH_DB}"
+
+  sqlite3 ${PATH_DB} << EOF
+PRAGMA user_version = 2;
+
+CREATE TABLE IF NOT EXISTS boot_sequence (
+  package TEXT NOT NULL,
+  appid TEXT NOT NULL,
+  after TEXT NOT NULL,
+  before TEXT NOT NULL,
+  requires TEXT NOT NULL,
+  conflicts TEXT NOT NULL,
+  vconf TEXT NOT NULL,
+  path_exists TEXT NOT NULL,
+  args TEXT NOT NULL,
+  background_launch TEXT NOT NULL,
+  wait_until_ready TEXT NOT NULL,
+  timeout TEXT NOT NULL,
+  PRIMARY KEY (appid)
+);
+EOF
+}
+
+Upgrade() {
+  echo "### Upgrade"
+  CreateNewTable
+}
+
+Fini() {
+  echo "### Finish"
+  rm ${PATH_BACKUP_DB}
+  rm ${PATH_BACKUP_DB}-journal
+}
+
+echo "#### 2. Upgrade appsvc db ####"
+Init
+Upgrade
+Fini
+echo "#### 2. Upgrade appsvc db [Done] ####"
index 59c194c..5e8981c 100644 (file)
@@ -1,5 +1,3 @@
-SET(TARGET_AUL_SERVER "aul-server")
-
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} AUL_SERVER_SRCS)
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/api AUL_SERVER_API_SRCS)
 
diff --git a/server/api/aul_boot_sequence.cc b/server/api/aul_boot_sequence.cc
new file mode 100644 (file)
index 0000000..67d3d27
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2022 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 "server/api/aul_boot_sequence.h"
+
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "server/boot_sequence.hh"
+#include "server/common_private.hh"
+#include "server/database.hh"
+#include "server/log_private.hh"
+
+using namespace aul;
+
+namespace {
+
+constexpr const char APPSVC_DB[] = ".appsvc.db";
+constexpr const char QUERY_SELECT_FROM_BOOT_SEQUENCE[] =
+    "SELECT appid, after, before, requires, conflicts, vconf, path_exists, "
+    "args, background_launch, wait_until_ready, timeout FROM boot_sequence";
+
+using SelectBootSequenceCb =
+    int (*)(sqlite3*, sqlite3_stmt*,
+        std::tuple<std::vector<std::shared_ptr<BootSequence>>&>);
+
+template <typename T, typename ...ARGS>
+int Step(T cb, std::tuple<ARGS...> args,
+    bool readonly, const std::string& query, uid_t uid) {
+  std::string path = Database::GetPath(APPSVC_DB, uid);
+  Database db(path, false);
+  try {
+    db.Open(readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE);
+  } catch (Exception& e) {
+    return AUL_ERROR_IO_ERROR;
+  }
+
+  sqlite3_stmt* stmt;
+  __PREPARE_V2(db.GetHandle(), query.c_str(), query.length(), stmt);
+  auto stmt_ptr = std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*>(
+      stmt, sqlite3_finalize);
+
+  int ret;
+  if (readonly) {
+    ret = cb(db.GetHandle(), stmt, args);
+  } else {
+    db.BeginTransaction();
+    ret = cb(db.GetHandle(), stmt, args);
+    if (ret < 0)
+      db.Rollback();
+    else
+      db.EndTransaction();
+  }
+
+  return ret;
+}
+
+int GetBootSequence(uid_t uid,
+    std::vector<std::shared_ptr<BootSequence>>& infos) {
+  std::string query(QUERY_SELECT_FROM_BOOT_SEQUENCE);
+  std::tuple<std::vector<std::shared_ptr<BootSequence>>&> param(infos);
+  int ret = Step<SelectBootSequenceCb,
+      std::vector<std::shared_ptr<BootSequence>>&>(
+          [](sqlite3* db, sqlite3_stmt* stmt,
+             std::tuple<std::vector<std::shared_ptr<BootSequence>>&> args)
+          -> int {
+            auto& infos = std::get<0>(args);
+            int idx;
+            while (sqlite3_step(stmt) == SQLITE_ROW) {
+              idx = 0;
+              std::string appid = Database::ColumnText(stmt, idx++);
+              auto info = std::make_shared<BootSequence>(std::move(appid));
+              info->SetAfter(std::move(Database::ColumnText(stmt, idx++)));
+              info->SetBefore(std::move(Database::ColumnText(stmt, idx++)));
+              info->SetRequires(std::move(Database::ColumnText(stmt, idx++)));
+              info->SetConflicts(std::move(Database::ColumnText(stmt, idx++)));
+              info->SetVconf(std::move(Database::ColumnText(stmt, idx++)));
+              info->SetPathExists(std::move(Database::ColumnText(stmt, idx++)));
+              info->SetArgs(std::move(Database::ColumnText(stmt, idx++)));
+              info->SetBackgroundLaunch(
+                  std::move(Database::ColumnText(stmt, idx++)));
+              info->SetWaitUntilReady(
+                  std::move(Database::ColumnText(stmt, idx++)));
+              info->SetTimeout(std::move(Database::ColumnText(stmt, idx++)));
+              infos.push_back(std::move(info));
+            }
+
+            return AUL_ERROR_NONE;
+          }, param, false, query, uid);
+  if (ret != AUL_ERROR_NONE)
+    return AUL_ERROR_IO_ERROR;
+
+  return AUL_ERROR_NONE;
+}
+
+}  // namespace
+
+extern "C" API int aul_boot_sequence_foreach_usr(uid_t uid,
+    aul_boot_sequence_cb callback, void* user_data) {
+  if (callback == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  if (uid < REGULAR_UID_MIN)
+    uid = GLOBALAPP_UID;
+
+  std::vector<std::shared_ptr<BootSequence>> infos;
+  int ret = GetBootSequence(uid, infos);
+  if (ret == AUL_ERROR_NONE && uid != GLOBALAPP_UID)
+    ret = GetBootSequence(GLOBALAPP_UID, infos);
+
+  if (ret != AUL_ERROR_NONE) {
+    _E("Failed to get boot sequence. error(%d)", ret);
+    return ret;
+  }
+
+  for (auto& info : infos) {
+    if (!callback(info.get(), user_data))
+      break;
+  }
+
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_appid(aul_boot_sequence_h handle,
+    const char** appid) {
+  if (handle == nullptr || appid == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *appid = h->GetAppId().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_after(aul_boot_sequence_h handle,
+    const char** after) {
+  if (handle == nullptr || after == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *after = h->GetAfter().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_before(aul_boot_sequence_h handle,
+    const char** before) {
+  if (handle == nullptr || before == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *before = h->GetBefore().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_requires(aul_boot_sequence_h handle,
+    const char** requires) {
+  if (handle == nullptr || requires == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *requires = h->GetRequires().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_conflicts(aul_boot_sequence_h handle,
+    const char** conflicts) {
+  if (handle == nullptr || conflicts == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *conflicts = h->GetConflicts().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_vconf(aul_boot_sequence_h handle,
+    const char** vconf) {
+  if (handle == nullptr || vconf == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *vconf = h->GetVconf().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_path_exists(aul_boot_sequence_h handle,
+    const char** path_exists) {
+  if (handle == nullptr || path_exists == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *path_exists = h->GetPathExists().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_args(aul_boot_sequence_h handle,
+    const char** args) {
+  if (handle == nullptr || args == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *args = h->GetArgs().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_background_launch(
+    aul_boot_sequence_h handle, const char** background_launch) {
+  if (handle == nullptr || background_launch == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *background_launch = h->GetBackgroundLaunch().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_wait_until_ready(
+    aul_boot_sequence_h handle, const char** wait_until_ready) {
+  if (handle == nullptr || wait_until_ready == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *wait_until_ready = h->GetWaitUntilReady().c_str();
+  return AUL_ERROR_NONE;
+}
+
+extern "C" API int aul_boot_sequence_get_timeout(aul_boot_sequence_h handle,
+    const char** timeout) {
+  if (handle == nullptr || timeout == nullptr) {
+    _E("Invalid parameter");
+    return AUL_ERROR_INVALID_PARAMETER;
+  }
+
+  auto* h = static_cast<BootSequence*>(handle);
+  *timeout = h->GetTimeout().c_str();
+  return AUL_ERROR_NONE;
+}
diff --git a/server/api/aul_boot_sequence.h b/server/api/aul_boot_sequence.h
new file mode 100644 (file)
index 0000000..cd97b43
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022 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 __AUL_BOOT_SEQUENCE_H__
+#define __AUL_BOOT_SEQUENCE_H__
+
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <aul_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *aul_boot_sequence_h;
+
+typedef bool (*aul_boot_sequence_cb)(aul_boot_sequence_h handle, void *user_data);
+
+int aul_boot_sequence_foreach_usr(uid_t uid, aul_boot_sequence_cb callback, void *user_data);
+
+int aul_boot_sequence_get_appid(aul_boot_sequence_h handle, const char **appid);
+
+int aul_boot_sequence_get_after(aul_boot_sequence_h handle, const char **after);
+
+int aul_boot_sequence_get_before(aul_boot_sequence_h handle, const char **before);
+
+int aul_boot_sequence_get_requires(aul_boot_sequence_h handle, const char **requires);
+
+int aul_boot_sequence_get_conflicts(aul_boot_sequence_h handle, const char **conflicts);
+
+int aul_boot_sequence_get_vconf(aul_boot_sequence_h handle, const char **vconf);
+
+int aul_boot_sequence_get_path_exists(aul_boot_sequence_h handle, const char **path_exists);
+
+int aul_boot_sequence_get_args(aul_boot_sequence_h handle, const char **args);
+
+int aul_boot_sequence_get_background_launch(aul_boot_sequence_h handle, const char **background_launch);
+
+int aul_boot_sequence_get_wait_until_ready(aul_boot_sequence_h handle, const char **wait_until_ready);
+
+int aul_boot_sequence_get_timeout(aul_boot_sequence_h handle, const char** timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __AUL_BOOT_SEQUENCE_H__ */
diff --git a/server/boot_sequence.cc b/server/boot_sequence.cc
new file mode 100644 (file)
index 0000000..96d6b94
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2022 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 "server/boot_sequence.hh"
+
+namespace aul {
+
+BootSequence::BootSequence(std::string appid) : appid_(std::move(appid)) {}
+
+const std::string& BootSequence::GetAppId() const {
+  return appid_;
+}
+
+const std::string& BootSequence::GetAfter() const {
+  return after_;
+}
+
+const std::string& BootSequence::GetBefore() const {
+  return before_;
+}
+
+const std::string& BootSequence::GetRequires() const {
+  return requires_;
+}
+
+const std::string& BootSequence::GetConflicts() const {
+  return conflicts_;
+}
+
+const std::string& BootSequence::GetArgs() const {
+  return args_;
+}
+
+const std::string& BootSequence::GetVconf() const {
+  return vconf_;
+}
+
+const std::string& BootSequence::GetPathExists() const {
+  return path_exists_;
+}
+
+const std::string& BootSequence::GetBackgroundLaunch() const {
+  return background_launch_;
+}
+
+const std::string& BootSequence::GetWaitUntilReady() const {
+  return wait_until_ready_;
+}
+
+const std::string& BootSequence::GetTimeout() const {
+  return timeout_;
+}
+
+void BootSequence::SetAfter(std::string after) {
+  after_ = std::move(after);
+}
+
+void BootSequence::SetBefore(std::string before) {
+  before_ = std::move(before);
+}
+
+void BootSequence::SetRequires(std::string requires) {
+  requires_ = std::move(requires);
+}
+
+void BootSequence::SetConflicts(std::string conflicts) {
+  conflicts_ = std::move(conflicts);
+}
+
+void BootSequence::SetArgs(std::string args) {
+  args_ = std::move(args);
+}
+
+void BootSequence::SetVconf(std::string vconf) {
+  vconf_ = std::move(vconf);
+}
+
+void BootSequence::SetPathExists(std::string path_exists) {
+  path_exists_ = std::move(path_exists);
+}
+
+void BootSequence::SetBackgroundLaunch(std::string background_launch) {
+  background_launch_ = std::move(background_launch);
+}
+
+void BootSequence::SetWaitUntilReady(std::string wait_until_ready) {
+  wait_until_ready_ = std::move(wait_until_ready);
+}
+
+void BootSequence::SetTimeout(std::string timeout) {
+  timeout_ = std::move(timeout);
+}
+
+}  // namespace aul
diff --git a/server/boot_sequence.hh b/server/boot_sequence.hh
new file mode 100644 (file)
index 0000000..550f98d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022 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 SERVER_BOOT_SEQUENCE_HH_
+#define SERVER_BOOT_SEQUENCE_HH_
+
+#include <string>
+
+namespace aul {
+
+class BootSequence {
+ public:
+  BootSequence(std::string appid);
+
+  const std::string& GetAppId() const;
+  const std::string& GetAfter() const;
+  const std::string& GetBefore() const;
+  const std::string& GetRequires() const;
+  const std::string& GetConflicts() const;
+  const std::string& GetArgs() const;
+  const std::string& GetVconf() const;
+  const std::string& GetPathExists() const;
+  const std::string& GetBackgroundLaunch() const;
+  const std::string& GetWaitUntilReady() const;
+  const std::string& GetTimeout() const;
+
+  void SetAfter(std::string after);
+  void SetBefore(std::string before);
+  void SetRequires(std::string requires);
+  void SetConflicts(std::string conflicts);
+  void SetArgs(std::string args);
+  void SetVconf(std::string vconf);
+  void SetPathExists(std::string path_exists);
+  void SetBackgroundLaunch(std::string background_launch);
+  void SetWaitUntilReady(std::string wait_until_ready);
+  void SetTimeout(std::string timeout);
+
+ private:
+  std::string appid_;
+  std::string after_;
+  std::string before_;
+  std::string requires_;
+  std::string conflicts_;
+  std::string args_;
+  std::string vconf_;
+  std::string path_exists_;
+  std::string background_launch_;
+  std::string wait_until_ready_;
+  std::string timeout_;
+};
+
+}  // namespace aul
+
+#endif  // SERVER_BOOT_SEQUENCE_HH_
diff --git a/server/exception.cc b/server/exception.cc
new file mode 100644 (file)
index 0000000..318edbe
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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 "server/exception.hh"
+
+#include <libgen.h>
+
+namespace aul {
+
+Exception::Exception(int error_code, std::string file, int line)
+    : error_code_(error_code) {
+  message_ = std::string(basename(const_cast<char*>(file.c_str()))) + ":" +
+      std::to_string(line) + " code:" + std::to_string(error_code_);
+}
+
+Exception::~Exception() = default;
+
+const char* Exception::what() const noexcept {
+  return message_.c_str();
+}
+
+int Exception::GetErrorCode() {
+  return error_code_;
+}
+
+}  // namespace aul
index 1d9a5bb..c8c1647 100644 (file)
 #ifndef SERVER_EXCEPTION_HH_
 #define SERVER_EXCEPTION_HH_
 
-#include <libgen.h>
-
 #include <string>
 #include <exception>
 
-#include "server/log_private.hh"
-
 #define THROW(error_code) throw Exception(error_code, __FILE__, __LINE__)
 
 namespace aul {
 
 class Exception : public std::exception {
  public:
-  explicit Exception(int error_code, std::string file, int line) {
-    error_code_ = error_code;
-    message_ = std::string(basename(const_cast<char*>(file.c_str()))) + ":" +
-        std::to_string(line) + " code:" + std::to_string(error_code_);
-    _E("%s", message_.c_str());
-  }
-
-  virtual ~Exception() {}
-
-  virtual const char* what() const noexcept {
-    return message_.c_str();
-  }
-
-  int GetErrorCode() {
-    return error_code_;
-  }
+  explicit Exception(int error_code, std::string file, int line);
+  virtual ~Exception();
+
+  virtual const char* what() const noexcept;
+  int GetErrorCode();
 
  private:
   int error_code_;
index acef059..654338d 100644 (file)
@@ -4,6 +4,7 @@ ADD_SUBDIRECTORY(appgroup_info)
 ADD_SUBDIRECTORY(appid2pid)
 ADD_SUBDIRECTORY(aul_test)
 ADD_SUBDIRECTORY(aul_window)
+ADD_SUBDIRECTORY(aulctl)
 ADD_SUBDIRECTORY(compmgr_tool)
 ADD_SUBDIRECTORY(launch_app)
 ADD_SUBDIRECTORY(launch_debug)
diff --git a/tool/aulctl/CMakeLists.txt b/tool/aulctl/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1935e29
--- /dev/null
@@ -0,0 +1,25 @@
+SET(TARGET_AULCTL "aulctl")
+
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} AULCTL_SRCS)
+
+ADD_EXECUTABLE(${TARGET_AULCTL} ${AULCTL_SRCS})
+SET_TARGET_PROPERTIES(${TARGET_AULCTL} PROPERTIES
+  COMPILE_FLAGS ${CFLAGS} "-fPIE")
+SET_TARGET_PROPERTIES(${TARGET_AULCTL} PROPERTIES
+  LINK_FLAGS "-pie")
+TARGET_LINK_LIBRARIES(${TARGET_AULCTL} PRIVATE
+  ${TARGET_AUL}
+  ${TARGET_AUL_SERVER})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_AULCTL} PUBLIC
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../src
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../include
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../server
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../server/api)
+
+APPLY_PKG_CONFIG(${TARGET_AULCTL} PUBLIC
+  GLIB_DEPS
+)
+
+INSTALL(TARGETS ${TARGET_AULCTL} DESTINATION bin)
diff --git a/tool/aulctl/aulctl.cc b/tool/aulctl/aulctl.cc
new file mode 100644 (file)
index 0000000..6a7f2d9
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2022 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 <aul_boot_sequence.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <map>
+
+namespace {
+
+using HandleFunc = int (*)(int argc, char** argv);
+
+void PrintUsage(const char* cmdline) {
+  printf("%s <command> ...\n", cmdline);
+  printf(" - command list\n");
+  printf("   list-apps\n");
+}
+
+int HandleListApps(int argc, char** argv) {
+  printf("[%s]\n", argv[1]);
+  uid_t uid;
+  if (argc > 2)
+    uid = atoi(argv[2]);
+  else
+    uid = getuid();
+
+  int count = 0;
+  int ret = aul_boot_sequence_foreach_usr(uid,
+      [](aul_boot_sequence_h handle, void* user_data) -> bool {
+        int* cnt = static_cast<int*>(user_data);
+        if ((*cnt)++ == 0)
+          printf("==============================================\n");
+        else
+          printf("----------------------------------------------\n");
+
+        const char* val;
+        aul_boot_sequence_get_appid(handle, &val);
+        printf(" appid: %s\n", val);
+        aul_boot_sequence_get_after(handle, &val);
+        printf(" after: %s\n", val);
+        aul_boot_sequence_get_before(handle, &val);
+        printf(" before: %s\n", val);
+        aul_boot_sequence_get_requires(handle, &val);
+        printf(" requires: %s\n", val);
+        aul_boot_sequence_get_conflicts(handle, &val);
+        printf(" conflicts: %s\n", val);
+        aul_boot_sequence_get_vconf(handle, &val);
+        printf(" vconf: %s\n", val);
+        aul_boot_sequence_get_path_exists(handle, &val);
+        printf(" path-exists: %s\n", val);
+        aul_boot_sequence_get_args(handle, &val);
+        printf(" args: %s\n", val);
+        aul_boot_sequence_get_background_launch(handle, &val);
+        printf(" background-launch: %s\n", val);
+        aul_boot_sequence_get_wait_until_ready(handle, &val);
+        printf(" wait-until-ready: %s\n", val);
+        aul_boot_sequence_get_timeout(handle, &val);
+        printf(" timeout: %s\n", val);
+        return true;
+      }, &count);
+  if (count > 0)
+    printf("==============================================\n");
+
+  printf("[%s] result: %d\n", argv[1], ret);
+  return ret;
+}
+
+std::map<std::string, HandleFunc> handlers = {
+  { "list-apps", HandleListApps },
+};
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  if (argc < 2) {
+    PrintUsage(argv[0]);
+    return -1;
+  }
+
+  auto found = handlers.find(argv[1]);
+  if (found == handlers.end()) {
+    PrintUsage(argv[0]);
+    return -1;
+  }
+
+  return found->second(argc, argv);
+}
index 481111d..4d11a2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2020 - 2022 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.
         "  appid TEXT NOT NULL,\n"                                             \
         "  allowed_appid TEXT NOT NULL,\n"                                     \
         "  PRIMARY KEY (appid, allowed_appid)\n"                               \
-        ");"
+        ");\n"                                                                 \
+       "CREATE TABLE IF NOT EXISTS boot_sequence (\n"                         \
+       "  package TEXT NOT NULL,\n"                                           \
+       "  appid TEXT NOT NULL,\n"                                             \
+       "  after TEXT NOT NULL,\n"                                             \
+       "  before TEXT NOT NULL,\n"                                            \
+       "  requires TEXT NOT NULL,\n"                                          \
+       "  conflicts TEXT NOT NULL,\n"                                         \
+       "  vconf TEXT NOT NULL,\n"                                             \
+       "  path_exists TEXT NOT NULL,\n"                                       \
+       "  args TEXT NOT NULL,\n"                                              \
+       "  background_launch TEXT NOT NULL,\n"                                 \
+       "  wait_until_ready TEXT NOT NULL,\n"                                  \
+       "  timeout TEXT NOT NULL,\n"                                           \
+       "  PRIMARY KEY (appid)\n"                                              \
+       ");"
 
 static int __check_db_integrity(uid_t uid)
 {
@@ -65,6 +80,7 @@ static int __check_db_integrity(uid_t uid)
                "alias_info_for_uid",
                "allowed_info",
                "appsvc",
+               "boot_sequence",
        };
        char *db_path;
        int ret;