From: Pawel Kowalski
Date: Tue, 25 Jul 2017 11:34:23 +0000 (+0200)
Subject: Add new application for testing the CAPI.
X-Git-Tag: accepted/tizen/4.0/unified/20170920.081734~2
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d1f6e45e2e9687754444cd46078767e65d5fb0a8;p=platform%2Fcore%2Fsecurity%2Faskuser.git
Add new application for testing the CAPI.
The app is written in Tizen Studio 4.0 and is based on the
example 'Account Manager' for profile mobile-4.0.
Change-Id: Id05dda75cde1a20e80d7a7743f3df8b3e148e571
---
diff --git a/test/apps/capi/PPMTester/.cproject b/test/apps/capi/PPMTester/.cproject
new file mode 100644
index 0000000..36a2f92
--- /dev/null
+++ b/test/apps/capi/PPMTester/.cproject
@@ -0,0 +1,617 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/apps/capi/PPMTester/.exportMap b/test/apps/capi/PPMTester/.exportMap
new file mode 100644
index 0000000..de30516
--- /dev/null
+++ b/test/apps/capi/PPMTester/.exportMap
@@ -0,0 +1,5 @@
+{
+ global: main;
+ _IO_*;
+ local: *;
+};
diff --git a/test/apps/capi/PPMTester/.project b/test/apps/capi/PPMTester/.project
new file mode 100644
index 0000000..160aa91
--- /dev/null
+++ b/test/apps/capi/PPMTester/.project
@@ -0,0 +1,26 @@
+
+
+ PPMTester
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/test/apps/capi/PPMTester/.tproject b/test/apps/capi/PPMTester/.tproject
new file mode 100644
index 0000000..468a834
--- /dev/null
+++ b/test/apps/capi/PPMTester/.tproject
@@ -0,0 +1,12 @@
+
+
+
+
+ mobile-4.0
+
+
+
+
+
+
+
diff --git a/test/apps/capi/PPMTester/README b/test/apps/capi/PPMTester/README
new file mode 100644
index 0000000..9aedf43
--- /dev/null
+++ b/test/apps/capi/PPMTester/README
@@ -0,0 +1,45 @@
+README for PPMTester app
+
+The PPMTester app is an app created for testing CAPI of Privacy Privilege
+Manager. The app is created in Tizen Studio 4.0 and is based on the
+example app 'Account Manager' for profile mobile-4.0.
+
+In order to import the app into the Tizen Studio and build it for Tizen
+emulator, one needs to perform following steps (steps 1. and 2. may be
+ommited if the CAPI is already installed in Tizen Studio IDE and Tizen
+Emulator; if mobile-4 profile may be accessed when new a project is
+created, then probably the CAPI is installed):
+
+ 1 Prepare Tizen Studio IDE
+ a) Download askuser from gerrit repository and build it using gbs
+ b) Unpack generated rpm files
+ c) Copy libraries and includes into relevant directories in
+ $HOME/tizen-studio/platforms/tizen-4.0/mobile/rootstraps/
+ /mobile-4.0-emulator.core/usr/
+ d) Modify XML file
+ $HOME/tizen-studio/platforms/tizen-4.0/mobile/rootstraps/
+ /info/mobile-4.0-emulator.core.dev.xml
+ and add following lines in proper places:
+ /usr/include/privacy-privilege-manager
+ libcapi-privacy-privilege-manager.so
+ e) Remove library dependencies for each .so file extracted from
+ rpm in step b) *separately*. This can be done using tool
+ 'postlink' from native-app-rootstrap project repository.
+ Usage: /path/to/postlink /path/to/libX.so
+ The postlink command may be executed from any directory
+ (absolute paths to postlink and .so files may be used).
+
+ 2. Prepare Tizen Emulator
+ a) Run Tizen 4.0 Emulator (x86) from Tizen Studio
+ b) Copy askuser rpms using sdb: sdb push *.rpm /tmp
+ c) Connect to the emulator and install packages:
+ sdb root on; sdb shell; mount -o remount,rw /; cd /tmp;
+ rpm -i *.rpm --force --nodeps
+
+ 3. Import and build project in Tizen Studio
+ a) File -> Import... -> General, Existing Projects into Workspace ->
+ -> Next -> Select root directory using 'Browse' button ->
+ -> Check in 'Copy projects into workspace' -> Finish
+ b) Select proper emulator from drop-down list
+ c) Project -> Build All
+ d) Run
diff --git a/test/apps/capi/PPMTester/project_def.prop b/test/apps/capi/PPMTester/project_def.prop
new file mode 100644
index 0000000..f923439
--- /dev/null
+++ b/test/apps/capi/PPMTester/project_def.prop
@@ -0,0 +1,11 @@
+APPNAME = ppmtester
+
+type = app
+profile = mobile-4.0
+
+USER_SRCS = src/ppmtester.c
+USER_DEFS =
+USER_INC_DIRS =
+USER_OBJS =
+USER_LIBS =
+USER_EDCS =
diff --git a/test/apps/capi/PPMTester/shared/res/ppmtester.png b/test/apps/capi/PPMTester/shared/res/ppmtester.png
new file mode 100644
index 0000000..9765b1b
Binary files /dev/null and b/test/apps/capi/PPMTester/shared/res/ppmtester.png differ
diff --git a/test/apps/capi/PPMTester/src/ppmtester.c b/test/apps/capi/PPMTester/src/ppmtester.c
new file mode 100644
index 0000000..efbc62c
--- /dev/null
+++ b/test/apps/capi/PPMTester/src/ppmtester.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2017 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
+ */
+
+/**
+ * @file ppmtester.c
+ * @author Pawel Kowalski
+ * @brief The implementation of testing application of the PPM CAPI.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "ppmtester"
+
+#define BUFFER_SIZE 1024
+
+#if !defined(PACKAGE)
+#define PACKAGE "org.example.ppmtester"
+#endif
+
+typedef struct appdata
+{
+ Evas_Object *window;
+ Evas_Object *conform;
+ Evas_Object *navi;
+ Evas_Object *msg_box;
+} appdata_s;
+
+static void win_delete_request_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ ui_app_exit();
+}
+
+/**
+ * @brief Prints massage into the message box.
+ *
+ * @param[in] obj The message box.
+ * @param[in] msg The text message that is written to the message box.
+ * @param[in] ... Additional arguments declared in the text message.
+ */
+void print_msg(Evas_Object *obj, const char* msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ char buffer[BUFFER_SIZE];
+ vsnprintf(buffer, BUFFER_SIZE, msg, args);
+ va_end(args);
+
+ Evas_Coord c_y;
+ elm_entry_entry_append(obj, buffer);
+ elm_entry_entry_append(obj, "
");
+ elm_entry_cursor_end_set(obj);
+ elm_entry_cursor_geometry_get(obj, NULL, &c_y, NULL, NULL);
+ elm_scroller_region_show(obj, 0, c_y, 0, 0);
+}
+
+/**
+ * @brief Clears the message box.
+ *
+ * @param[in] data User specific data.
+ * @param[in] btn Pointer to the button object.
+ * @param[in] event_info Additional event information.
+ */
+static void _btn_clear_cb(void *data, Evas_Object *btn, void *event_info)
+{
+ appdata_s *ad = data;
+ elm_entry_entry_set(ad->msg_box, "");
+}
+
+/**
+ * @brief Creates the display object.
+ */
+Evas_Object *_create_new_cd_display(appdata_s *ad, const char *name, void *cb)
+{
+ // Create a scroller
+ Evas_Object *scroller = elm_scroller_add(ad->window);
+ evas_object_size_hint_weight_set(scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ // Create a new item
+ Elm_Object_Item *item =
+ elm_naviframe_item_push(ad->navi, "PPM Tester", NULL, NULL, scroller, NULL);
+ elm_object_item_part_text_set(item, "subtitle", "Test following privileges:");
+
+ if (cb != NULL)
+ elm_naviframe_item_pop_cb_set(item, (Elm_Naviframe_Item_Pop_Cb) cb, (void *)ad);
+
+ // Create a main box
+ Evas_Object *box = elm_box_add(scroller);
+ elm_object_content_set(scroller, box);
+ elm_box_horizontal_set(box, EINA_FALSE);
+ evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(box);
+
+ Evas_Object *inner_grid = elm_grid_add(box);
+ elm_object_content_set(box, inner_grid);
+ evas_object_size_hint_align_set(inner_grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(inner_grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(inner_grid);
+
+ Evas_Object *bbox_scroller = elm_scroller_add(inner_grid);
+ evas_object_size_hint_align_set(bbox_scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(bbox_scroller, EVAS_HINT_EXPAND, 0.0);
+ elm_scroller_policy_set(bbox_scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON);
+ elm_object_style_set(bbox_scroller, "handler");
+ evas_object_show(bbox_scroller);
+
+ // Create a box for adding content
+ Evas_Object *bbox = elm_box_add(bbox_scroller);
+ Evas_Coord padding_between_buttons = 3;
+ elm_box_padding_set(bbox, 0, padding_between_buttons);
+ elm_object_content_set(bbox_scroller, bbox);
+ elm_box_horizontal_set(bbox, EINA_FALSE);
+ evas_object_size_hint_align_set(bbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(bbox, EVAS_HINT_EXPAND, 0.0);
+ evas_object_show(bbox);
+
+ // Create "Clear" button
+ Evas_Object *bt = elm_button_add(box);
+ elm_object_text_set(bt, "Clear");
+ evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+ evas_object_smart_callback_add(bt, "clicked", _btn_clear_cb, ad);
+ evas_object_show(bt);
+
+ // Create a box for entry
+ Evas_Object *ebox = elm_box_add(inner_grid);
+ elm_box_horizontal_set(ebox, EINA_FALSE);
+ evas_object_size_hint_align_set(ebox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(ebox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(ebox);
+
+ // Create a message box
+ Evas_Object *display_window = elm_entry_add(ebox);
+ evas_object_size_hint_align_set(display_window, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(display_window, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(display_window);
+
+ elm_entry_editable_set(display_window, EINA_FALSE);
+ elm_entry_scrollable_set(display_window, EINA_TRUE);
+
+ ad->msg_box = display_window;
+ elm_scroller_policy_set(ad->msg_box, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON);
+ elm_box_pack_end(ebox, display_window);
+
+ elm_grid_pack(inner_grid, bbox_scroller, 0, 0, 100, 35);
+ elm_grid_pack(inner_grid, ebox, 0, 35, 100, 65);
+ elm_box_pack_end(box, inner_grid);
+ elm_box_pack_end(box, bt);
+
+ return bbox;
+}
+
+Eina_Bool _pop_cb(void *data, Elm_Object_Item *item)
+{
+ elm_win_lower(((appdata_s *)data)->window);
+ return EINA_FALSE;
+}
+
+/**
+ * @brief Function copied from the Account Manager example.
+ */
+Evas_Object *_new_button(appdata_s *ad, Evas_Object *display, const char *name, void *cb)
+{
+ // Create a button
+ Evas_Object *bt = elm_button_add(display);
+ elm_object_text_set(bt, name);
+ evas_object_smart_callback_add(bt, "clicked", (Evas_Smart_Cb) cb, ad);
+ evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(display, bt);
+ evas_object_show(bt);
+ return bt;
+}
+
+/**
+ * @brief Writes text into dlogutil and into GUI.
+ *
+ * @details In order to read a message using dlogutil,
+ * type in the emulator's terminal: dlogutil ppmtester
+ * The 'ppmtester' flag is set using LOG_TAG constant.
+ *
+ * @param[in] ad The structure with GUI elements.
+ * @param[in] privilege A privilege that is to be logged.
+ * @param[in] msg A text that is to be written.
+ */
+void log_privilege (appdata_s *ad, const char* privilege, const char* msg)
+{
+ print_msg(ad->msg_box, "----------
Privilege: %s
Message: %s", privilege, msg);
+ dlog_print(DLOG_INFO, LOG_TAG, "----------\nPrivilege: %s\nMessage: %s", privilege, msg);
+}
+
+/**
+ * @brief Based on ppm_popup_response_cb prototype from privacy-privilege-manager.h.
+ *
+ * @param[in] cause A value representing the reason why this callback
+ * has been called.
+ * @param[in] result A result of a response triggered by calling ppm_popup_request().
+ * @param[in] privilege A privilege that has been checked.
+ * @param[in] user_data User specific data.
+ */
+void ppm_popup_response_cb_function (ppm_call_cause_e cause, ppm_request_result_e result, const char *privilege, void *user_data)
+{
+ appdata_s *ad = user_data;
+ switch (cause)
+ {
+ case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER:
+ log_privilege(ad, privilege, "Callback was called with a valid answer.");
+ switch (result)
+ {
+ case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_ALLOW_FOREVER:
+ log_privilege(ad, privilege, "A user granted permission to use a privilege for an indefinite period of time.");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_FOREVER:
+ log_privilege(ad, privilege, "A user did not grant permission to use a privilege for an indefinite period of time.");
+ ui_app_exit();
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_ONCE:
+ log_privilege(ad, privilege, "A user did not grant permission to use a privilege once.");
+ break;
+ default:
+ break;
+ }
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR:
+ log_privilege(ad, privilege, "Callback was called because of an error.");
+ break;
+ default:
+ {
+ char msg[BUFFER_SIZE];
+ snprintf(msg, BUFFER_SIZE, "Unknown cause: %d", cause);
+ log_privilege(ad, privilege, msg);
+ break;
+ }
+ }
+}
+
+/**
+ * @brief Checks the privilege. Writes messages in the bottom part of the main window and
+ * into the shell (in order to read these messages use command: dlogutil ppmtester).
+ *
+ * @param[in] ad The structure with GUI elements.
+ * @param[in] privilege A privilege that is to be checked.
+ * @param[in] ret The code of the error.
+ */
+void app_log_errors(appdata_s *ad, const char* privilege, ppm_error_e ret)
+{
+ switch (ret)
+ {
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR:
+ log_privilege(ad, privilege, "I/O error");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER:
+ log_privilege(ad, privilege, "Invalid parameter");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_ALREADY_IN_PROGRESS:
+ log_privilege(ad, privilege, "Operation already in progress");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY:
+ log_privilege(ad, privilege, "Out of memory");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN:
+ log_privilege(ad, privilege, "Unknown error");
+ break;
+ default:
+ log_privilege(ad, privilege, "Unknown error");
+ break;
+ }
+}
+
+/**
+ * @brief Checks the privilege. Writes messages in the bottom part of the main window and
+ * into the shell (in order to read these messages use command: dlogutil ppmtester).
+ *
+ * @param[in] ad The structure with GUI elements.
+ * @param[in] privilege A privilege that is to be checked.
+ */
+void check_privilege (appdata_s *ad, const char* privilege)
+{
+ ppm_check_result_e result;
+
+ int ret = ppm_check_permission(privilege, &result);
+
+ if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) // If there is an error, print log.
+ {
+ app_log_errors(ad, privilege, ret);
+ return;
+ }
+
+ switch (result) // Alow, deny or ask.
+ {
+ case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW:
+ log_privilege(ad, privilege, "An application has permission to use a privilege.");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY:
+ log_privilege(ad, privilege, "An application doesn't have permission to use a privilege.");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK:
+ {
+ log_privilege(ad, privilege, "A user has to be asked whether to grant permission to use a privilege.");
+ int ret_popup = ppm_request_permission(privilege, ppm_popup_response_cb_function, ad);
+ if (ret_popup != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE)
+ {
+ app_log_errors(ad, privilege, ret_popup);
+ return;
+ }
+ break;
+ }
+ default:
+ {
+ char msg[BUFFER_SIZE];
+ snprintf(msg, BUFFER_SIZE, "Unknown result: %d", result);
+ log_privilege(ad, privilege, msg);
+ break;
+ }
+ }
+}
+
+/**
+ * @brief Callback for 'camera' button.
+ *
+ * @param[in] ad The structure with GUI elements.
+ * @param[in] obj Display object.
+ */
+void _test_privilege_camera(appdata_s *ad, Evas_Object *obj)
+{
+ check_privilege(ad, "http://tizen.org/privilege/camera");
+}
+
+/**
+ * @brief Callback for 'location' button.
+ *
+ * @param[in] ad The structure with GUI elements.
+ * @param[in] obj Display object.
+ */
+void _test_privilege_location(appdata_s *ad, Evas_Object *obj)
+{
+ check_privilege(ad, "http://tizen.org/privilege/location");
+}
+
+/**
+ * @brief Callback for 'contact.read' button.
+ *
+ * @param[in] ad The structure with GUI elements.
+ * @param[in] obj Display object.
+ */
+void _test_privilege_contact_read(appdata_s *ad, Evas_Object *obj)
+{
+ check_privilege(ad, "http://tizen.org/privilege/contact.read");
+}
+
+/**
+ * @brief Callback for 'contact.write' button.
+ *
+ * @param[in] ad The structure with GUI elements.
+ * @param[in] obj Display object.
+ */
+void _test_privilege_contact_write(appdata_s *ad, Evas_Object *obj)
+{
+ check_privilege(ad, "http://tizen.org/privilege/contact.write");
+}
+
+/**
+ * @brief Creates buttons in the main window.
+ *
+ * @param[in] ad The structure with GUI elements.
+ */
+void create_buttons_in_main_window(appdata_s *ad)
+{
+ Evas_Object *display = _create_new_cd_display(ad, "PPM Tester", _pop_cb);
+
+ _new_button(ad, display, "camera", _test_privilege_camera);
+ _new_button(ad, display, "location", _test_privilege_location);
+ _new_button(ad, display, "contact.read", _test_privilege_contact_read);
+ _new_button(ad, display, "contact.write", _test_privilege_contact_write);
+}
+
+/**
+ * @brief Creates base GUI (window, conformant, naviframe and buttons).
+ *
+ * @param[in] ad The structure with GUI elements.
+ */
+static void create_base_gui(appdata_s *ad)
+{
+ // Setting the window
+ ad->window = elm_win_util_standard_add(PACKAGE, PACKAGE);
+ elm_win_conformant_set(ad->window, EINA_TRUE);
+ elm_win_autodel_set(ad->window, EINA_TRUE);
+ elm_win_indicator_mode_set(ad->window, ELM_WIN_INDICATOR_SHOW);
+ elm_win_indicator_opacity_set(ad->window, ELM_WIN_INDICATOR_OPAQUE);
+ evas_object_smart_callback_add(ad->window, "delete, request", win_delete_request_cb, NULL);
+
+ // Create conformant
+ ad->conform = elm_conformant_add(ad->window);
+ evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(ad->window, ad->conform);
+ evas_object_show(ad->conform);
+
+ // Create a naviframe
+ ad->navi = elm_naviframe_add(ad->conform);
+ evas_object_size_hint_align_set(ad->navi, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(ad->navi, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ elm_object_content_set(ad->conform, ad->navi);
+ evas_object_show(ad->navi);
+
+ // Fill the list with items
+ create_buttons_in_main_window(ad);
+
+ eext_object_event_callback_add(ad->navi, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, NULL);
+
+ // Show the window after base gui is set up
+ evas_object_show(ad->window);
+}
+
+static bool app_create(void *data)
+{
+ /*
+ * Hook to take necessary actions before main event loop starts
+ * Initialize UI resources and application's data
+ * If this function returns true, the main loop of application starts
+ * If this function returns false, the application is terminated
+ */
+
+ appdata_s *ad = data;
+
+ create_base_gui(ad);
+
+ return true;
+}
+
+static void app_control(app_control_h app_control, void *data)
+{
+ // Handle the launch request.
+}
+
+static void app_pause(void *data)
+{
+ // Take necessary actions when application becomes invisible.
+}
+
+static void app_resume(void *data)
+{
+ // Take necessary actions when application becomes visible.
+
+ // Checking two example privileges on resume:
+ const char* privileges [] = {"http://tizen.org/privilege/alarm.get", "http://tizen.org/privilege/calendar.read"};
+ for (int i = 0; i < sizeof(privileges)/sizeof(privileges[0]); i++)
+ {
+ check_privilege(data, privileges[i]);
+ }
+}
+
+static void app_terminate(void *data)
+{
+ // Release all resources.
+}
+
+int main(int argc, char *argv[])
+{
+ appdata_s ad = {0,};
+ int ret = 0;
+
+ ui_app_lifecycle_callback_s event_callback = {0,};
+
+ event_callback.create = app_create;
+ event_callback.terminate = app_terminate;
+ event_callback.pause = app_pause;
+ event_callback.resume = app_resume;
+ event_callback.app_control = app_control;
+
+ ret = ui_app_main(argc, argv, &event_callback, &ad);
+ if (ret != APP_ERROR_NONE)
+ {
+ dlog_print(DLOG_ERROR, LOG_TAG, "app_main() is failed. err = %d", ret);
+ }
+
+ return ret;
+}
diff --git a/test/apps/capi/PPMTester/tizen-manifest.xml b/test/apps/capi/PPMTester/tizen-manifest.xml
new file mode 100644
index 0000000..344e47e
--- /dev/null
+++ b/test/apps/capi/PPMTester/tizen-manifest.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ ppmtester.png
+
+
+ http://tizen.org/privilege/calendar.write
+ http://tizen.org/privilege/contact.read
+ http://tizen.org/privilege/contact.write
+ http://tizen.org/privilege/location
+ http://tizen.org/privilege/calendar.read
+ http://tizen.org/privilege/alarm.get
+ http://tizen.org/privilege/alarm.set
+
+
\ No newline at end of file