Single app package support including service app 68/39968/1
authorYoumin Ha <youmin.ha@samsung.com>
Wed, 27 May 2015 05:36:38 +0000 (14:36 +0900)
committerYoumin Ha <youmin.ha@samsung.com>
Wed, 27 May 2015 05:46:24 +0000 (14:46 +0900)
To run Tizen TCT packages, single-app packages having only service apps
must be able to be installed. This commit enables installing app packages
having only service apps.
  - Removed mandatory ui-application app checking routine.
  - Added a routine checking the existance of at least 1 ui or service app.
  - Additional code for <service-application> attributes in
    step_generate_xml.cc.

Change-Id: Iaac04f6fb20055fe06ca6b3a67294c9354695ec0
Signed-off-by: Youmin Ha <youmin.ha@samsung.com>
src/common/step/step_copy.cc
src/common/step/step_generate_xml.cc
src/tpk/step/step_parse.cc

index 58733ea..19d4cd1 100644 (file)
@@ -65,12 +65,16 @@ Step::Status StepCopy::process() {
   context_->pkg_path.set(install_path.string());
 
   // FIXME: correctly order app's data.
-  // If there is 1 app in package, app's data are stored in <pkg_path>/<app_id>
-  // If there are >1 apps in package, app's data are stored in <pkg_path>
+  // If there is 1 app in package, the app's data are stored in
+  // <pkg_path>/<app_id>/
+  // If there are >1 apps in the package, app's data are stored in <pkg_path>
   // considering that multiple apps data are already separated in folders.
-  if (context_->manifest_data.get()->uiapplication &&
-      !context_->manifest_data.get()->uiapplication->next)
+  manifest_x *m = context_->manifest_data.get();
+  if ((m->uiapplication && !m->uiapplication->next && !m->serviceapplication) ||
+      (m->serviceapplication && !m->serviceapplication->next &&
+      !m->uiapplication)) {
     install_path /= bf::path(context_->manifest_data.get()->mainapp_id);
+  }
 
   bs::error_code error;
   bf::create_directories(install_path.parent_path(), error);
index b0c80ff..2a0256f 100644 (file)
@@ -27,11 +27,29 @@ namespace fs = boost::filesystem;
 namespace common_installer {
 namespace generate_xml {
 
+static void _writeUIApplicationAttributes(
+    xmlTextWriterPtr writer, uiapplication_x *app) {
+    xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
+        BAD_CAST "true");
+}
+
+static void _writeServiceApplicationAttributes(
+    xmlTextWriterPtr writer, serviceapplication_x *app) {
+  xmlTextWriterWriteAttribute(writer, BAD_CAST "auto-restart",
+      BAD_CAST(app->autorestart ? app->autorestart : "false"));
+  xmlTextWriterWriteAttribute(writer, BAD_CAST "on-boot",
+      BAD_CAST(app->onboot ? app->onboot : "false"));
+  xmlTextWriterWriteAttribute(writer, BAD_CAST "permission-type",
+      BAD_CAST(app->permission_type ? app->permission_type : ""));
+}
+
 template <typename T>
 Step::Status StepGenerateXml::GenerateApplicationCommonXml(T* app,
     xmlTextWriterPtr writer) {
   fs::path default_icon(
       tzplatform_mkpath(TZ_SYS_RW_ICONS, "app-installers.png"));
+
+  // common appributes among uiapplication_x and serviceapplication_x
   xmlTextWriterWriteAttribute(writer, BAD_CAST "appid", BAD_CAST app->appid);
 
   // binary is a symbolic link named <appid> and is located in <pkgid>/<appid>
@@ -44,9 +62,13 @@ Step::Status StepGenerateXml::GenerateApplicationCommonXml(T* app,
   else
     xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST "capp");
 
+  // app-specific attributes
   if (std::is_same<T, uiapplication_x>::value)
-    xmlTextWriterWriteAttribute(writer, BAD_CAST "taskmanage",
-        BAD_CAST "true");
+    _writeUIApplicationAttributes(
+        writer, reinterpret_cast<uiapplication_x *>(app));
+  if (std::is_same<T, serviceapplication_x>::value)
+    _writeServiceApplicationAttributes(
+        writer, reinterpret_cast<serviceapplication_x *>(app));
 
   label_x* label = nullptr;
   LISTHEAD(app->label, label);
index a64599c..4a8435f 100644 (file)
@@ -116,7 +116,7 @@ boost::filesystem::path* StepParse::GetManifestFilePath(
 bool StepParse::SetContextByManifestParser(XmlTree* tree) {
   // Get required elements
   XmlElement* manifest,
-      * ui_application, * label;
+      * ui_application, * service_application, * label;
 
   // manifest
   if (nullptr == (manifest = tree->GetRootElement())) {
@@ -130,21 +130,26 @@ bool StepParse::SetContextByManifestParser(XmlTree* tree) {
                 "' package='" << manifest->attr("package") <<
                 "' versionr='" << manifest->attr("version") << "'";
 
-  // ui_application
-  if (nullptr == (ui_application = Get1stChild(tree,
-          manifest, "ui-application"))) {
-    LOG(ERROR) << "No mandatory ui-application element in manifest xml";
+  // At least one of ui_application or service_application must be given
+  ui_application = Get1stChild(tree, manifest, "ui-application");
+  service_application = Get1stChild(tree, manifest, "service-application");
+  if (nullptr == ui_application && nullptr == service_application) {
+    LOG(ERROR) << "Neither <ui-application> nor <service-application>" <<
+        " element is found in manifest xml";
     return false;
   }
-  if (nullptr == (label = Get1stChild(tree, ui_application, "label"))) {
-    LOG(ERROR) << "No mandatory label element in manifest xml";
+  // label must be given
+  label = ui_application ? Get1stChild(tree, ui_application, "label") :
+      Get1stChild(tree, service_application, "label");
+  if (nullptr == label) {
+    LOG(ERROR) << "No mandatory <label> element in manifest xml";
     return false;
   }
 
   // set context_
   context_->config_data.get().application_name.set(label->content());
   context_->config_data.get().required_version.set(
-      manifest->attr("api_version"));
+      manifest->attr("api-version"));
   context_->pkgid.set(manifest->attr("package"));
   context_->manifest_data.set(static_cast<manifest_x*>(
       calloc(1, sizeof(manifest_x))));
@@ -160,8 +165,11 @@ bool StepParse::SetPkgInfoManifest(manifest_x* m,
 
   // Get required elements
   XmlElement* ui_application = Get1stChild(tree, manifest, "ui-application");
-  if (!ui_application) {
-    LOG(ERROR) << "No <ui-application> element is found in manifest xml";
+  XmlElement* service_application = Get1stChild(tree, manifest,
+      "service-application");
+  if (!(ui_application || service_application)) {   // mandatory check
+    LOG(ERROR) << "Neither <ui-application> nor <service-application>" <<
+        " element is found in manifest xml";
     return false;
   }
 
@@ -171,10 +179,13 @@ bool StepParse::SetPkgInfoManifest(manifest_x* m,
   m->version = string_strdup(manifest->attr("version"));
   m->installlocation = string_strdup(manifest->attr("install-location"));
 
-  m->mainapp_id = string_strdup(ui_application->attr("appid"));
+  // Choose main app among ui-application or service-application
+  // NOTE: main app must have appid attribute
+  XmlElement* main_app = ui_application ? ui_application : service_application;
+  m->mainapp_id = string_strdup(main_app->attr("appid"));
 
   // manifest' attribute from children's values
-  XmlElement* label = Get1stChild(tree, ui_application, "label");
+  XmlElement* label = Get1stChild(tree, main_app, "label");
   if (label) {
     m->label =  static_cast<label_x*>(calloc(1, sizeof(label_x)));
     m->label->name = string_strdup(label->content());
@@ -184,7 +195,7 @@ bool StepParse::SetPkgInfoManifest(manifest_x* m,
   return SetPkgInfoChildren(m, tree, manifest);
 }
 
-// Read and feel struct hierarchy
+// Read and fill struct hierarchy
 // The spec of tizen-manifest is referred from Tizen 2.2.1 header.
 bool StepParse::SetPkgInfoChildren(manifest_x* m,
     XmlTree* tree, XmlElement* manifest) {