AEGIS_TEST! sandbox/aegis-test-tizen
authorminhoon.yi <minhoon.yi@samsung.com>
Tue, 25 Jul 2017 11:03:46 +0000 (20:03 +0900)
committerminhoon.yi <minhoon.yi@samsung.com>
Tue, 25 Jul 2017 11:03:46 +0000 (20:03 +0900)
Change-Id: I41cf7e050f9759426d7e572bf29ffaae6458a8ca

57 files changed:
AUTHORS
CMakeLists.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
inc/amd_app_com.h [new file with mode: 0644]
inc/amd_app_group.h [new file with mode: 0644]
inc/amd_app_property.h [new file with mode: 0644]
inc/amd_app_status.h [new file with mode: 0644]
inc/amd_appinfo.h [new file with mode: 0644]
inc/amd_cooldown.h [new file with mode: 0644]
inc/amd_cynara.h [new file with mode: 0644]
inc/amd_extractor.h [new file with mode: 0644]
inc/amd_inotify.h [new file with mode: 0644]
inc/amd_input.h [new file with mode: 0644]
inc/amd_launch.h [new file with mode: 0644]
inc/amd_login_monitor.h [new file with mode: 0644]
inc/amd_request.h [new file with mode: 0644]
inc/amd_rua.h [new file with mode: 0644]
inc/amd_screen_connector.h [new file with mode: 0644]
inc/amd_share.h [new file with mode: 0644]
inc/amd_signal.h [new file with mode: 0644]
inc/amd_socket.h [new file with mode: 0644]
inc/amd_splash_screen.h [new file with mode: 0644]
inc/amd_suspend.h [new file with mode: 0644]
inc/amd_util.h [new file with mode: 0644]
inc/amd_wayland.h [new file with mode: 0644]
inc/amd_widget.h [new file with mode: 0644]
inc/app_signal.h [new file with mode: 0644]
inc/aul_svc_priv_key.h [new file with mode: 0644]
packaging/ac.conf [new file with mode: 0644]
packaging/ac.service [new file with mode: 0644]
packaging/ac.socket [new file with mode: 0644]
packaging/amd.manifest [new file with mode: 0644]
packaging/amd.spec [new file with mode: 0644]
src/amd_app_com.c [new file with mode: 0644]
src/amd_app_group.c [new file with mode: 0644]
src/amd_app_property.c [new file with mode: 0644]
src/amd_app_status.c [new file with mode: 0644]
src/amd_appinfo.c [new file with mode: 0644]
src/amd_cooldown.c [new file with mode: 0644]
src/amd_cynara.c [new file with mode: 0644]
src/amd_extractor.c [new file with mode: 0644]
src/amd_inotify.c [new file with mode: 0644]
src/amd_input.c [new file with mode: 0644]
src/amd_launch.c [new file with mode: 0644]
src/amd_login_monitor.c [new file with mode: 0644]
src/amd_main.c [new file with mode: 0644]
src/amd_request.c [new file with mode: 0644]
src/amd_rua.c [new file with mode: 0644]
src/amd_screen_connector.c [new file with mode: 0644]
src/amd_share.c [new file with mode: 0644]
src/amd_signal.c [new file with mode: 0644]
src/amd_socket.c [new file with mode: 0644]
src/amd_splash_screen.c [new file with mode: 0644]
src/amd_suspend.c [new file with mode: 0644]
src/amd_util.c [new file with mode: 0644]
src/amd_wayland.c [new file with mode: 0644]
src/amd_widget.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index d4b78ce..064881e 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,20 +1,3 @@
-Authors of GNU Hello.
-
-  Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
-
-  Copying and distribution of this file, with or without modification,
-  are permitted in any medium without royalty provided the copyright
-  notice and this notice are preserved.
-
-The following contributions warranted legal paper exchanges with the
-Free Software Foundation.  See also the ChangeLog and THANKS files.
-
-Mike Haertel
-David MacKenzie
-Jan Brittenson
-Roland McGrath
-Charles Hannum
-Bruce Korb             hello.c, configure.ac.
-Karl Eichwalder                all files.
-Karl Berry             all files.
-The King               releases.
+Jayoun Lee <airjany@samsung.com>
+Sewook Park <sewook7.park@samsung.com>
+Jaeho Lee <jaeho81.lee@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ac46d47
--- /dev/null
@@ -0,0 +1,58 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
+
+PROJECT(amd C)
+AUX_SOURCE_DIRECTORY(src SOURCES)
+
+ADD_DEFINITIONS("-DSHARE_PREFIX=\"${SHARE_INSTALL_PREFIX}/aul\"")
+IF(with_wayland)
+       ADD_DEFINITIONS("-DWAYLAND")
+ENDIF(with_wayland)
+IF(with_x11)
+       ADD_DEFINITIONS("-DX11")
+ENDIF(with_x11)
+
+IF(_TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP)
+       ADD_DEFINITIONS("-DTIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP")
+ENDIF(_TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP)
+IF(_TIZEN_FEATURE_BLOCK_INPUT)
+       ADD_DEFINITIONS("-DTIZEN_FEATURE_BLOCK_INPUT")
+ENDIF(_TIZEN_FEATURE_BLOCK_INPUT)
+IF(_TIZEN_FEATURE_AUTO_ROTATION)
+       ADD_DEFINITIONS("-DTIZEN_FEATURE_AUTO_ROTATION")
+ENDIF(_TIZEN_FEATURE_AUTO_ROTATION)
+
+# Set required packages
+INCLUDE(FindPkgConfig)
+
+SET(AMD_PKG_CHECK_MODULES dlog rua aul glib-2.0 gio-2.0 vconf pkgmgr-info pkgmgr bundle libsystemd-daemon cynara-client cynara-creds-socket cynara-session cert-svc-vcore libtzplatform-config xkbcommon sensor security-manager ttrace app2sd capi-system-info)
+IF (with_wayland)
+       pkg_check_modules(pkgs REQUIRED  ${AMD_PKG_CHECK_MODULES} wayland-client tizen-extension-client wayland-tbm-client tizen-launch-client)
+ENDIF(with_wayland)
+IF(with_x11)
+       pkg_check_modules(pkgs REQUIRED  ${AMD_PKG_CHECK_MODULES} )
+ENDIF(with_x11)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+# Compiler flags
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/inc)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fpic")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+SET(CMAKE_SKIP_BUILD_RPATH true)
+# Linker flags
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+
+ADD_EXECUTABLE(amd ${SOURCES})
+SET_TARGET_PROPERTIES(amd PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS} -fPIE")
+TARGET_LINK_LIBRARIES(amd ${pkgs_LDFLAGS} "-pie")
+INSTALL(TARGETS amd DESTINATION bin)
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..a06208b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,204 @@
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
diff --git a/inc/amd_app_com.h b/inc/amd_app_com.h
new file mode 100644 (file)
index 0000000..5782450
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 - 2016 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 __AMD_APP_COM_H__
+#define __AMD_APP_COM_H__
+
+#include <stdbool.h>
+
+int _app_com_broker_init(void);
+int _app_com_broker_fini(void);
+int _app_com_client_remove(int cpid);
+int _app_com_add_endpoint(const char *endpoint, unsigned int propagate,
+               const char *assoc_priv);
+int _app_com_remove_endpoint(const char *endpoint);
+int _app_com_join(const char *endpoint, int cpid, const char *filter,
+               uid_t uid);
+int _app_com_send(const char *endpoint, int cpid, bundle *envelope, uid_t uid);
+int _app_com_leave(const char *endpoint, int cpid);
+const char *_app_com_get_privilege(const char *endpoint);
+bool _app_com_endpoint_exists(const char *endpoint);
+
+#endif /* __AMD_APP_COM_H__ */
+
diff --git a/inc/amd_app_group.h b/inc/amd_app_group.h
new file mode 100644 (file)
index 0000000..b186681
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <bundle.h>
+
+typedef enum {
+       APP_GROUP_LAUNCH_MODE_SINGLE = 0,
+       APP_GROUP_LAUNCH_MODE_GROUP,
+       APP_GROUP_LAUNCH_MODE_CALLER,
+       APP_GROUP_LAUNCH_MODE_SINGLETON,
+} app_group_launch_mode;
+
+void _app_group_remove(int pid);
+int _app_group_get_window(int pid);
+int _app_group_set_window(int pid, int wid);
+void _app_group_get_leader_pids(int *cnt, int **pids);
+void _app_group_get_group_pids(int leader_pid, int *cnt, int **pids);
+bool _app_group_is_leader_pid(int pid);
+bool _app_group_is_group_app(bundle *kb, uid_t uid);
+bool _app_group_is_sub_app(int pid);
+void _app_group_reroute(int pid);
+void _app_group_clear_top(int pid, uid_t uid);
+int _app_group_get_leader_pid(int pid);
+void _app_group_set_dead_pid(int pid);
+int _app_group_get_status(int pid);
+int _app_group_set_status(int pid, int status, bool force);
+int _app_group_get_fg_flag(int pid);
+int _app_group_set_hint(int pid, bundle *kb);
+int _app_group_find_second_leader(int lpid);
+void _app_group_remove_leader_pid(int lpid);
+int _app_group_can_start_app(const char *appid, bundle *b, bool *can_attach,
+               int *lpid, app_group_launch_mode *mode, uid_t uid);
+void _app_group_start_app(int pid, bundle *b, int lpid, bool can_attach,
+               app_group_launch_mode mode);
+int _app_group_find_singleton(const char *appid, int *found_pid,
+               int *found_lpid);
+int _app_group_can_reroute(int pid);
+void _app_group_lower(int pid, int *exit);
+void _app_group_restart_app(int pid, bundle *b);
+int _app_group_find_pid_from_recycle_bin(const char *appid);
+void _app_group_get_idle_pids(int *cnt, int **pids);
+void _app_group_remove_from_recycle_bin(int pid);
+int _app_group_get_next_caller_pid(int pid);
+int _app_group_activate_below(int pid, const char *below_appid);
+int _app_group_activate_above(int pid, const char *above_appid);
+int _app_group_attach(const char *parent_appid, const char *child_appid,
+               uid_t uid);
+int _app_group_detach(const char *child_appid, uid_t uid);
+int _app_group_init(void);
+void _app_group_fini(void);
diff --git a/inc/amd_app_property.h b/inc/amd_app_property.h
new file mode 100644 (file)
index 0000000..7981c35
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <glib.h>
+
+#define METADATA_LARGEMEMORY "http://tizen.org/metadata/largememory"
+#define METADATA_OOMTERMINATION "http://tizen.org/metadata/oomtermination"
+
+typedef struct app_property_s *app_property_h;
+
+int _app_property_add_alias_info(app_property_h app_property,
+               const char *alias_appid, const char *appid);
+int _app_property_remove_alias_info(app_property_h app_property,
+               const char *alias_appid, const char *appid);
+const char *_app_property_get_real_appid(app_property_h app_property,
+               const char *alias_appid);
+GList *_app_property_get_allowed_app_list(app_property_h app_property,
+               const char *appid);
+app_property_h _app_property_find(uid_t uid);
+int _app_property_insert(uid_t uid, const char *appid);
+int _app_property_delete(uid_t uid, const char *appid);
+int _app_property_load(uid_t uid);
+void _app_property_unload(uid_t uid);
+int _app_property_init(void);
+void _app_property_fini(void);
+void _app_property_cache_put(app_property_h app_property, const char *checksum, const char *appid);
+const char *_app_property_cache_get(app_property_h app_property, const char *checksum);
+void _app_property_cache_invalidate(app_property_h app_property);
+bool _app_property_metadata_query_bool(app_property_h app_property, const char *appid, const char *key);
+int _app_property_metadata_foreach(app_property_h app_property, const char *appid,
+               const char *key, int (*callback)(const char *value, void *data), void *user_data);
+bool _app_property_metadata_match(app_property_h app_property, const char *appid,
+               const char *key, const char *value);
+bool _app_property_metadata_query_activation(app_property_h app_property, const char *appid, const char *key);
+
+
+
diff --git a/inc/amd_app_status.h b/inc/amd_app_status.h
new file mode 100644 (file)
index 0000000..94d0319
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <glib.h>
+#include <stdbool.h>
+#include <security-manager.h>
+
+#include "amd_appinfo.h"
+
+typedef enum {
+       AT_SERVICE_APP,
+       AT_UI_APP,
+       AT_WIDGET_APP,
+       AT_WATCH_APP,
+} app_type_e;
+
+typedef struct _shared_info_t {
+       char *owner_appid;
+       private_sharing_req *handle;
+} shared_info_t;
+
+typedef struct app_status_s *app_status_h;
+
+void _app_status_send_fault_dead_for_update_app(const char *pkgid);
+void _app_status_send_fault_dead_for_oom_apps(void);
+void _app_status_fault_recovery(int pid, int uid, const char *pkgid,
+               const char *appid, int type, bool is_exit_notified);
+int _app_status_set_is_exit_notified(app_status_h app_status, bool is_exit_notified);
+bool _app_status_get_is_exit_notified(app_status_h app_status);
+int _app_status_add_app_info(const struct appinfo *ai, int pid,
+               bool is_subapp, uid_t uid, int caller_pid,
+               bool bg_launch, const char *instance_id,
+               bool debug_mode);
+int _app_status_remove_all_app_info_with_uid(uid_t uid);
+int _app_status_remove(app_status_h app_status);
+int _app_status_update_status(app_status_h app_status, int status, bool force,
+               bool update_group_info);
+int _app_status_update_last_caller_pid(app_status_h app_status, int caller_pid);
+int _app_status_update_bg_launch(app_status_h app_status, bool bg_launch);
+int _app_status_get_process_cnt(const char *appid);
+bool _app_status_is_home_app(app_status_h app_status);
+int _app_status_get_pid(app_status_h app_status);
+int _app_status_get_last_caller_pid(app_status_h app_status);
+int _app_status_is_running(app_status_h app_status);
+int _app_status_get_status(app_status_h app_status);
+uid_t _app_status_get_uid(app_status_h app_status);
+const char *_app_status_get_appid(app_status_h app_status);
+const char *_app_status_get_pkgid(app_status_h app_status);
+bool _app_status_get_bg_launch(app_status_h app_status);
+const char *_app_status_get_instance_id(app_status_h app_stauts);
+int _app_status_get_app_type(app_status_h app_status);
+int _app_status_add_shared_info(app_status_h app_status, shared_info_t *info);
+int _app_status_clear_shared_info_list(app_status_h stat);
+GList *_app_status_get_shared_info_list(app_status_h stat);
+bool _app_status_socket_exists(app_status_h app_status);
+bool _app_status_is_starting(app_status_h app_status);
+int _app_status_update_is_starting(app_status_h app_status, bool is_starting);
+const char *_app_status_get_app_path(app_status_h app_status);
+app_status_h _app_status_find(int pid);
+app_status_h _app_status_find_v2(int pid);
+app_status_h _app_status_find_by_appid(const char *appid, uid_t uid);
+app_status_h _app_status_find_by_appid_v2(const char *appid, uid_t uid);
+app_status_h _app_status_find_with_org_caller(const char *appid, uid_t uid,
+               int caller_pid);
+app_status_h _app_status_find_by_instance_id(const char *appid,
+               const char *instance_id, uid_t uid);
+void _app_status_find_service_apps(app_status_h app_status, int status,
+               void (*send_event_to_svc_core)(int, uid_t), bool suspend);
+void _app_status_check_service_only(app_status_h app_status,
+               void (*send_event_to_svc_core)(int, uid_t));
+int _app_status_send_running_appinfo(int fd, int cmd, uid_t uid);
+int _app_status_foreach_running_appinfo(void (*callback)(app_status_h, void *),
+               void *data);
+int _app_status_terminate_apps(const char *appid, uid_t uid);
+int _app_status_terminate_apps_by_pkgid(const char *pkgid, uid_t uid);
+int _app_status_get_appid_bypid(int fd, int pid);
+int _app_status_get_pkgid_bypid(int fd, int pid);
+int _app_status_get_instance_id_bypid(int fd, int pid);
+int _app_status_get_org_caller_pid(app_status_h app_status);
+int _app_status_publish_status(int pid, int context_status);
+void _app_status_cleanup(app_status_h app_status);
+int _app_status_usr_init(uid_t uid);
+void _app_status_usr_fini(uid_t uid);
+int _app_status_init(void);
+int _app_status_finish(void);
diff --git a/inc/amd_appinfo.h b/inc/amd_appinfo.h
new file mode 100644 (file)
index 0000000..ac197ca
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+#include <glib.h>
+#include <stdbool.h>
+
+#define AIT_START 0
+enum appinfo_type {
+       AIT_NAME = AIT_START,
+       AIT_EXEC,
+       AIT_PKGTYPE,
+       AIT_ONBOOT, /* start on boot: boolean */
+       AIT_RESTART, /* auto restart: boolean */
+       AIT_MULTI,
+       AIT_HWACC,
+       AIT_PERM,
+       AIT_PKGID,
+       AIT_PRELOAD,
+       AIT_STATUS,
+       AIT_POOL,
+       AIT_COMPTYPE,
+       AIT_TEP,
+       AIT_MOUNTABLE_PKG,
+       AIT_STORAGE_TYPE,
+       AIT_BG_CATEGORY,
+       AIT_LAUNCH_MODE,
+       AIT_GLOBAL,
+       AIT_EFFECTIVE_APPID,
+       AIT_TASKMANAGE,
+       AIT_VISIBILITY,
+       AIT_APPTYPE,
+       AIT_ROOT_PATH,
+       AIT_SPLASH_SCREEN,
+       AIT_SPLASH_SCREEN_DISPLAY,
+       AIT_API_VERSION,
+       AIT_ENABLEMENT,
+       AIT_COOLDOWN,
+       AIT_SYSTEM,
+       AIT_MAX
+};
+
+struct appinfo {
+       char *val[AIT_MAX];
+};
+
+struct appinfo_splash_screen {
+       GHashTable *portrait;
+       GHashTable *landscape;
+};
+
+struct appinfo_splash_image {
+       char *src;
+       char *type;
+       char *indicatordisplay;
+       char *color_depth;
+};
+
+#define APP_TYPE_SERVICE       "svcapp"
+#define APP_TYPE_UI            "uiapp"
+#define APP_TYPE_WIDGET                "widgetapp"
+#define APP_TYPE_WATCH         "watchapp"
+
+#define APP_ENABLEMENT_MASK_ACTIVE     0x1
+#define APP_ENABLEMENT_MASK_REQUEST    0x2
+
+typedef void (*appinfo_iter_callback)(void *user_data,
+               const char *filename, struct appinfo *c);
+int _appinfo_init(void);
+void _appinfo_fini(void);
+int _appinfo_insert(uid_t uid, const char *pkgid);
+struct appinfo *_appinfo_find(uid_t caller_uid, const char *appid);
+const char *_appinfo_get_value(const struct appinfo *c, enum appinfo_type type);
+const void *_appinfo_get_ptr_value(const struct appinfo *c,
+               enum appinfo_type type);
+int _appinfo_get_int_value(const struct appinfo *c, enum appinfo_type type,
+               int *val);
+int _appinfo_get_boolean(const struct appinfo *c, enum appinfo_type type,
+                       bool *val);
+int _appinfo_set_value(struct appinfo *c, enum appinfo_type, const char *val);
+int _appinfo_set_ptr_value(struct appinfo *c, enum appinfo_type, void *val);
+int _appinfo_set_int_value(struct appinfo *c, enum appinfo_type type, int val);
+void _appinfo_foreach(uid_t uid, appinfo_iter_callback cb, void *user_data);
+void _appinfo_reload(void);
+int _appinfo_load(uid_t uid);
+void _appinfo_unload(uid_t uid);
+bool _appinfo_is_pkg_updating(const char *pkgid);
diff --git a/inc/amd_cooldown.h b/inc/amd_cooldown.h
new file mode 100644 (file)
index 0000000..34dc0dd
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "amd_appinfo.h"
+
+#define APP_SUPPORT_MODE_VIP_APPLICATION 0x00000010
+
+#define COOLDOWN_STATUS_RELEASE "Release"
+#define COOLDOWN_STATUS_RELEASE_STRING_LEN 7
+#define COOLDOWN_STATUS_LIMITACTION "LimitAction"
+#define COOLDOWN_STATUS_LIMITACTION_STRING_LEN 11
+
+/* cooldown status values */
+enum cooldown_status_val {
+       COOLDOWN_RELEASE,
+       COOLDOWN_WARNING,
+       COOLDOWN_LIMIT,
+};
+
+int _cooldown_get_status(void);
+int _cooldown_check_mode(const struct appinfo *ai);
+int _cooldown_init(void);
+void _cooldown_fini(void);
diff --git a/inc/amd_cynara.h b/inc/amd_cynara.h
new file mode 100644 (file)
index 0000000..eb9f248
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 - 2016 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 __AMD_CYNARA_H__
+#define __AMD_CYNARA_H__
+
+#include "amd_request.h"
+
+int _cynara_init(void);
+void _cynara_finish(void);
+int _cynara_check_privilege(request_h req);
+
+#endif /* __AMD_CYNARA_H__ */
+
diff --git a/inc/amd_extractor.h b/inc/amd_extractor.h
new file mode 100644 (file)
index 0000000..18f179d
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+#include <bundle.h>
+
+#include "amd_appinfo.h"
+
+typedef char **(_extractor_mountable)(const struct appinfo *ai);
+
+char **_extractor_mountable_get_tep_paths(const struct appinfo *ai);
+char **_extractor_mountable_get_tpk_paths(const struct appinfo *ai);
+void _extractor_mount(const struct appinfo *ai, bundle *kb,
+               _extractor_mountable mountable);
+void _extractor_unmount(int pid, _extractor_mountable mountable);
+
diff --git a/inc/amd_inotify.h b/inc/amd_inotify.h
new file mode 100644 (file)
index 0000000..8db8bc7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <sys/inotify.h>
+
+typedef bool (*inotify_watch_cb)(const char *event_name, void *data);
+
+int _inotify_add_watch(const char *path, uint32_t mask,
+               inotify_watch_cb callback, void *data);
+void _inotify_rm_watch(int wd);
+int _inotify_init(void);
+void _inotify_fini(void);
diff --git a/inc/amd_input.h b/inc/amd_input.h
new file mode 100644 (file)
index 0000000..e8c1c35
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+int _input_init(void);
+int _input_fini(void);
+int _input_lock(void);
+int _input_unlock(void);
+
diff --git a/inc/amd_launch.h b/inc/amd_launch.h
new file mode 100644 (file)
index 0000000..c3bd036
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <bundle.h>
+
+#include "amd_request.h"
+#include "amd_util.h"
+#include "amd_appinfo.h"
+
+#define PROC_STATUS_LAUNCH 0
+#define PROC_STATUS_FG 3
+#define PROC_STATUS_BG 4
+#define PROC_STATUS_FOCUS 5
+#define PROC_STATUS_HIDE 7
+
+int _send_to_sigkill(int pid);
+int _resume_app(int pid, request_h req);
+int _pause_app(int pid, request_h req);
+int _term_app(int pid, request_h req);
+int _term_req_app(int pid, request_h req);
+int _term_bgapp(int pid, request_h req);
+int _term_sub_app(int pid, uid_t uid);
+int _launch_start_app(const char *appid, request_h req, bool *pending,
+               bool *bg_launch, bool new_instance);
+int _launch_start_app_local(uid_t uid, const char *appid);
+int _launch_start_app_local_with_bundle(uid_t uid, const char *appid,
+               bundle *kb);
+int _launch_start_onboot_app_local(uid_t uid, const char *appid,
+               struct appinfo *ai);
+int _launch_init(void);
+void _launch_set_focused_pid(int pid);
+int _launch_get_focused_pid(void);
+int _term_app_v2(int pid, request_h req, bool *pend);
+int _launch_start_onboot_apps(uid_t uid);
+int _terminate_app_local(uid_t uid, int pid);
+int _launch_add_fgmgr(int pid);
+void _launch_remove_fgmgr(int pid);
diff --git a/inc/amd_login_monitor.h b/inc/amd_login_monitor.h
new file mode 100644 (file)
index 0000000..6b56889
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016 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 __AMD_LOGIN_MONITOR_H__
+#define __AMD_LOGIN_MOINTOR_H__
+
+typedef enum uid_state_e {
+       UID_STATE_UNKNOWN = 0x00,
+       UID_STATE_OPENING = 0x01,
+       UID_STATE_LINGERING = 0x02,
+       UID_STATE_ONLINE = 0x04,
+       UID_STATE_ACTIVE = 0x08,
+       UID_STATE_CLOSING = 0x10,
+       UID_STATE_OFFLINE = 0x20,
+} uid_state;
+
+void _login_monitor_set_uid_state(uid_t uid, uid_state state);
+uid_state _login_monitor_get_uid_state(uid_t uid);
+int _login_monitor_get_uids(uid_t **uids);
+int _login_monitor_init(void);
+void _login_monitor_fini(void);
+
+#endif /* __AMD_LOGIN_MONITOR_H__ */
diff --git a/inc/amd_request.h b/inc/amd_request.h
new file mode 100644 (file)
index 0000000..5966a69
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#pragma once
+
+#include <bundle.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+typedef struct request_s *request_h;
+
+int _request_send_result(request_h req, int res);
+int _request_send_raw(request_h req, int cmd, unsigned char *data, int len);
+int _request_get_fd(request_h req);
+int _request_get_pid(request_h req);
+int _request_get_cmd(request_h req);
+bundle *_request_get_bundle(request_h req);
+request_h _request_create_local(int cmd, uid_t uid, int pid, bundle *kb);
+void _request_free_local(request_h req);
+int _request_remove_fd(request_h req);
+int _request_reply_for_pending_request(int pid);
+int _request_flush_pending_request(int pid);
+uid_t _request_get_target_uid(request_h req);
+uid_t _request_get_uid(request_h req);
+pid_t _request_get_target_pid(request_h req);
+int _request_usr_init(uid_t uid);
+int _request_init(void);
+void _request_fini(void);
diff --git a/inc/amd_rua.h b/inc/amd_rua.h
new file mode 100644 (file)
index 0000000..bd49ffa
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <unistd.h>
+#include <bundle.h>
+
+int _rua_update_screen_info(int pid, unsigned int surf);
+int _rua_add_info(int pid, bool new_instance);
+const char *_rua_get_image_path(int pid);
+int _rua_delete_info(bundle *b, uid_t uid);
+int _rua_usr_init(uid_t uid);
+void _rua_usr_fini(uid_t uid);
+int _rua_init(void);
+void _rua_fini(void);
diff --git a/inc/amd_screen_connector.h b/inc/amd_screen_connector.h
new file mode 100644 (file)
index 0000000..f84625b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+int _screen_connector_send_update_request(const char *appid,
+               const char *instance_id, uid_t uid);
+int _screen_connector_add_app_screen(int pid, unsigned int surf,
+               const char *instance_id, uid_t uid);
+int _screen_connector_remove_app_screen(int pid, const char *instance_id,
+               uid_t uid);
+int _screen_connector_remove_app_screen_v2(int pid, uid_t uid);
+int _screen_connector_update_app_screen(int pid, unsigned int surf, uid_t uid);
+int _screen_connector_add_screen_viewer(int pid, int screen_type,
+               bool priv, unsigned int ref, uid_t uid);
+int _screen_connector_remove_screen_viewer(int pid, int screen_type,
+               bool priv, unsigned int ref, uid_t uid);
+int _screen_connector_remove_screen_viewer_v2(int pid, uid_t uid);
+int _screen_connector_usr_init(uid_t uid);
+void _screen_connector_usr_fini(uid_t uid);
+int _screen_connector_init(void);
+void _screen_connector_fini(void);
+const char *_screen_connector_get_appid_by_surface_id(unsigned int surf,
+               uid_t uid);
+const char *_screen_connector_get_instance_id_by_surface_id(unsigned int surf,
+               uid_t uid);
+int _screen_connector_update_screen_viewer_status(int pid, int status,
+               unsigned int surf, uid_t uid);
+unsigned int _screen_connector_get_surface_id(const char *instance_id,
+               uid_t uid);
diff --git a/inc/amd_share.h b/inc/amd_share.h
new file mode 100644 (file)
index 0000000..59603f9
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+#include "amd_app_status.h"
+
+typedef struct shared_info_main_s *shared_info_h;
+
+shared_info_h _temporary_permission_create(int caller_pid, const char *appid,
+               bundle *kb, uid_t uid);
+int _temporary_permission_destroy(shared_info_h handle);
+int _temporary_permission_apply(int pid, uid_t uid, shared_info_h handle);
+int _temporary_permission_drop(int pid, uid_t uid);
+
diff --git a/inc/amd_signal.h b/inc/amd_signal.h
new file mode 100644 (file)
index 0000000..8aba2bd
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#define APP_BOOSTING_PERIOD 1500
+#define APP_BOOSTING_STOP 0
+
+#define RESOURCED_ATTRIBUTE_LARGEMEMORY                0x01
+#define RESOURCED_ATTRIBUTE_OOMTERMINATION     0X02
+#define RESOURCED_ATTRIBUTE_WEB_APP            0x04
+#define RESOURCED_ATTRIBUTE_DOWNLOAD_APP       0x08
+#define RESOURCED_ATTRIBUTE_SERVICE_APP                0x10
+
+int _signal_init(void);
+int _signal_send_watchdog(int pid, int signal_num);
+int _signal_send_proc_prelaunch(const char *appid, const char *pkgid,
+               int attribute, int category);
+int _signal_send_proc_suspend(int pid);
+int _signal_send_tep_mount(char *mnt_path[], const char *pkgid);
+int _signal_send_tep_unmount(const char *mnt_path);
+int _signal_get_proc_status(const int pid, int *status, int *focused);
+int _signal_subscribe_startup_finished(int (*callback)(uid_t uid, void *data),
+               void *user_data);
+int _signal_unsubscribe_startup_finished(void);
+int _signal_send_cpu_boost(int req);
+int _signal_send_display_lock_state(const char *state, char *flag,
+               unsigned int timeout);
+int _signal_send_display_unlock_state(const char *state, char *flag);
+int _signal_add_initializer(int (*callback)(void *data), void *user_data);
diff --git a/inc/amd_socket.h b/inc/amd_socket.h
new file mode 100644 (file)
index 0000000..2d6f791
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#pragma once
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define LAUNCHPAD_PROCESS_POOL_SOCK ".launchpad-process-pool-sock"
+
+#define PAD_CMD_LAUNCH 0
+#define PAD_CMD_VISIBILITY 10
+#define PAD_CMD_ADD_LOADER 11
+#define PAD_CMD_REMOVE_LOADER 12
+#define PAD_CMD_MAKE_DEFAULT_SLOTS 13
+#define PAD_CMD_DEMAND 14
+#define PAD_CMD_PING 15
+
+int _create_sock_activation(void);
+int _create_server_sock(void);
+int _send_cmd_to_launchpad(const char *pad_type, uid_t uid, int cmd,
+               bundle *kb);
+void _send_result_to_client(int fd, int res);
+void _send_result_to_client_v2(int fd, int res);
+
diff --git a/inc/amd_splash_screen.h b/inc/amd_splash_screen.h
new file mode 100644 (file)
index 0000000..fdf21ab
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <bundle.h>
+#include <tizen-extension-client-protocol.h>
+
+#include "amd_appinfo.h"
+
+typedef struct splash_image_s *splash_image_h;
+
+splash_image_h _splash_screen_get_image(int pid);
+splash_image_h _splash_screen_create_image(const struct appinfo *ai,
+               bundle *kb, int cmd, bool is_subapp);
+void _splash_screen_send_image(splash_image_h si);
+void _splash_screen_send_pid(splash_image_h si, int pid);
+void _splash_screen_set_effect_type(int pid, const char *appid, bool is_subapp);
+void _splash_screen_destroy_image(splash_image_h si);
+int _splash_screen_init(void);
+
diff --git a/inc/amd_suspend.h b/inc/amd_suspend.h
new file mode 100644 (file)
index 0000000..0f2e8b2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+#include "amd_appinfo.h"
+
+#define SUSPEND_TYPE_EXCLUDE "exclude"
+#define SUSPEND_TYPE_INCLUDE "include"
+
+enum suspend_status_e {
+       SUSPEND_STATUS_EXCLUDE,
+       SUSPEND_STATUS_INCLUDE,
+};
+
+bool _suspend_is_allowed_background(const struct appinfo *ai);
+void _suspend_add_timer(int pid, const struct appinfo *ai);
+void _suspend_remove_timer(int pid);
+int _suspend_add_proc(int pid);
+int _suspend_remove_proc(int pid);
+int _suspend_update_status(int pid, int status);
+void _suspend_init(void);
+void _suspend_fini(void);
+
diff --git a/inc/amd_util.h b/inc/amd_util.h
new file mode 100644 (file)
index 0000000..faaf364
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#pragma once
+
+#include <unistd.h>
+
+#include <dlog.h>
+#include <glib.h>
+#include <stdbool.h>
+#include <tzplatform_config.h>
+
+#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "AUL_AMD"
+
+#define _E(fmt, arg...) LOGE(fmt, ##arg)
+#define _D(fmt, arg...) LOGD(fmt, ##arg)
+#define _W(fmt, arg...) LOGW(fmt, ##arg)
+#define _I(fmt, arg...) LOGI(fmt, ##arg)
+
+#define MAX_LOCAL_BUFSZ 128
+#define MAX_PID_STR_BUFSZ 20
+#define MAX_UID_STR_BUFSZ 20
+
+#define MAX_PACKAGE_STR_SIZE 512
+#define MAX_PACKAGE_APP_PATH_SIZE 512
+
+#define REGULAR_UID_MIN 5000
+
+#define GSLIST_FOREACH_SAFE(list, l, l_next)   \
+       for (l = list,                            \
+                       l_next = g_slist_next(l);       \
+                       l;                              \
+                       l = l_next,                     \
+                       l_next = g_slist_next(l))
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+int _util_save_log(const char *tag, const char *message);
+int _util_init(void);
+void _util_fini(void);
+bool _util_check_oom(void);
diff --git a/inc/amd_wayland.h b/inc/amd_wayland.h
new file mode 100644 (file)
index 0000000..3cbd26a
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#pragma once
+
+#include <wayland-client.h>
+
+int _wayland_add_registry_listener(
+               struct wl_registry_listener *registry_listener,
+               void *data);
+struct wl_display *_wayland_get_display(void);
+int _wayland_init(void);
+void _wayland_finish(void);
+
diff --git a/inc/amd_widget.h b/inc/amd_widget.h
new file mode 100644 (file)
index 0000000..69557c3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 - 2016 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 __AMD_WIDGET_H__
+#define __AMD_WIDGET_H__
+
+#include "amd_request.h"
+
+int _widget_add(const char *widget_id, const char *instance_id, int pid,
+               uid_t uid);
+int _widget_del(const char *widget_id, const char *instance_id);
+int _widget_list(const char *widget_id, request_h req);
+int _widget_update(const char *widget_id, request_h req);
+int _widget_cleanup(int pid, uid_t uid);
+int _widget_is_faulted(const char *widget_id, int pid,
+               uid_t uid, bool *is_faulted);
+bool _widget_exist(int pid, uid_t uid);
+char *_widget_get_id(int pid, uid_t uid);
+int _widget_send_status_to_viewer(int pid, uid_t uid, const char *widget_id,
+               int viewer_pid, aul_widget_instance_event_e status);
+int _widget_send_dead_signal(int pid, uid_t uid, const char *pkgid);
+int _widget_count(const char *widget_id, uid_t uid);
+int _widget_get_pid(const char *widget_id, const char *instance_id);
+int _widget_verify_cmd(request_h req);
+int _widget_is_dying(int pid, uid_t uid);
+int _widget_init(void);
+void _widget_fini(void);
+int _widget_add_update_info(const char *pkg_id, int pid, uid_t uid);
+int _widget_send_dead_signal_for_update_widget(const char *pkgid);
+int _widget_send_dead_signal_for_faulted(int pid, uid_t uid,
+               const char *pkgid, const char *widget_id);
+void _widget_restart_faulted(void);
+void _widget_dead_handler(int pid, int uid, const char *pkgid, int caller_pid,
+               bool normal_exit, bool can_restart);
+void _widget_verify_instance(bundle *kb, int pid, uid_t uid);
+int _widget_send_running_info(request_h req);
+
+#endif /* __AMD_WIDGET_H__ */
+
diff --git a/inc/app_signal.h b/inc/app_signal.h
new file mode 100644 (file)
index 0000000..ed850cf
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2000 - 2015 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.
+ */
+
+#pragma once
+
+#define AUL_DBUS_PATH "/aul/dbus_handler"
+#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal"
+#define AUL_DBUS_APPDEAD_SIGNAL        "app_dead"
+#define AUL_DBUS_APPLAUNCH_SIGNAL      "app_launch"
+#define AUL_DBUS_HOMELAUNCH_SIGNAL     "home_launch"
+
+#define AUL_APP_STATUS_DBUS_PATH "/Org/Tizen/Aul/AppStatus"
+#define AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE "org.tizen.aul.AppStatus"
+#define STATUS_FOREGROUND "fg"
+#define STATUS_BACKGROUND "bg"
+
+#define AUL_APP_STATUS_DBUS_LAUNCH_REQUEST "AppLaunch"
+#define AUL_APP_STATUS_DBUS_RESUME_REQUEST "AppResume"
+#define AUL_APP_STATUS_DBUS_TERMINATE_REQUEST "AppTerminate"
+#define AUL_APP_STATUS_DBUS_STATUS_CHANGE "AppStatusChange"
+#define AUL_APP_STATUS_DBUS_GROUP "AppGroup"
+#define AUL_APP_STATUS_DBUS_TERMINATED "AppTerminated"
+
+#define SYSTEM_PATH_CORE       "/Org/Tizen/System/DeviceD/Core"
+#define SYSTEM_INTERFACE_CORE  "org.tizen.system.deviced.core"
+
+#define SYSTEM_SIGNAL_BOOTING_DONE             "BootingDone"
+
+#define SYSTEM_PATH_SYSNOTI    "/Org/Tizen/System/DeviceD/SysNoti"
+#define SYSTEM_INTERFACE_SYSNOTI       "org.tizen.system.deviced.SysNoti"
+
+#define SYSTEM_SIGNAL_COOLDOWN_CHANGED         "CoolDownChanged"
+
+#define RESOURCED_PATH_CORE    "/Org/Tizen/ResourceD/Process"
+#define RESOURCED_INTERFACE_CORE       "org.tizen.resourced.process"
+
+#define RESOURCED_SIGNAL_PROCESS_STATUS                "ProcStatus"
+
+#define ROTATION_BUS_NAME       "org.tizen.system.coord"
+#define ROTATION_OBJECT_PATH    "/Org/Tizen/System/Coord/Rotation"
+#define ROTATION_INTERFACE_NAME "org.tizen.system.coord.rotation"
+#define ROTATION_METHOD_NAME    "Degree"
+
+#define RESOURCED_PROC_OBJECT          "/Org/Tizen/ResourceD/Process"
+#define RESOURCED_PROC_INTERFACE       "org.tizen.resourced.process"
+#define RESOURCED_PROC_METHOD          "ProcExclude"
+
+#define APPFW_SUSPEND_HINT_PATH        "/Org/Tizen/Appfw/SuspendHint"
+#define APPFW_SUSPEND_HINT_INTERFACE   "org.tizen.appfw.SuspendHint"
+#define APPFW_SUSPEND_HINT_SIGNAL      "SuspendHint"
+
+#define RESOURCED_FREEZER_PATH "/Org/Tizen/Resourced/Freezer"
+#define RESOURCED_FREEZER_INTERFACE    "org.tizen.resourced.freezer"
+#define RESOURCED_FREEZER_SIGNAL       "FreezerState"
+
+#define RESOURCED_ALLOWED_BG_ATTRIBUTE                 0x100
+#define RESOURCED_BACKGROUND_MANAGEMENT_ATTRIBUTE      0x200
+#define RESOURCED_API_VER_2_4_ATTRIBUTE                        0x400
+
+#define RESOURCED_PROC_PRELAUNCH_SIGNAL "ProcPrelaunch"
+#define RESOURCED_PROC_WATCHDOG_SIGNAL "ProcWatchdog"
+#define RESOURCED_PROC_GROUP_SIGNAL "ProcGroup"
+
+#define PROC_TYPE_EXCLUDE              "exclude"
+#define PROC_TYPE_INCLUDE              "include"
+#define PROC_TYPE_WAKEUP               "wakeup"
+
+#define TEP_BUS_NAME "org.tizen.system.deviced"
+#define TEP_OBJECT_PATH "/Org/Tizen/System/DeviceD/Tzip"
+#define TEP_INTERFACE_NAME "org.tizen.system.deviced.Tzip"
+#define TEP_MOUNT_METHOD "Mount"
+#define TEP_UNMOUNT_METHOD "Unmount"
+#define TEP_IS_MOUNTED_METHOD "IsMounted"
+
+#define WM_PROC_NAME "org.enlightenment.wm"
+#define WM_PROC_PATH "/org/enlightenment/wm"
+#define WM_PROC_INTERFACE "org.enlightenment.wm.proc"
+#define WM_PROC_METHOD "GetProcStatus"
+
+#define SD_BUS_NAME "org.freedesktop.systemd1"
+#define SD_OBJECT_PATH "/org/freedesktop/systemd1"
+
+#define SD_MANAGER_INTERFACE "org.freedesktop.systemd1.Manager"
+#define SD_STARTUP_FINISHED_SIGNAL "StartupFinished"
+#define SD_USER_SESSION_STARTUP_FINISHED_SIGNAL "UserSessionStartupFinished"
+#define SD_SUBSCRIBE_METHOD "Subscribe"
+
+#define SD_UNIT_OBJECT_PATH "/org/freedesktop/systemd1/unit/default_2etarget"
+#define SD_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
+#define SD_GET_METHOD "Get"
+
+#define SYSTEM_BUS_NAME "org.tizen.system.deviced"
+#define SYSTEM_OBJECT_PATH "/Org/Tizen/System/DeviceD/PmQos"
+#define SYSTEM_INTERFACE_NAME "org.tizen.system.deviced.PmQos"
+#define SYSTEM_METHOD_NAME "AppLaunch"
+
+#define SYSTEM_PATH_DISPLAY            "/Org/Tizen/System/DeviceD/Display"
+#define SYSTEM_INTERFACE_DISPLAY       "org.tizen.system.deviced.display"
+#define SYSTEM_LOCK_STATE              "lockstate"
+#define SYSTEM_UNLOCK_STATE            "unlockstate"
+#define SYSTEM_LCD_OFF                 "lcdoff"
+#define SYSTEM_STAY_CUR_STATE          "staycurstate"
+#define SYSTEM_SLEEP_MARGIN            "sleepmargin"
diff --git a/inc/aul_svc_priv_key.h b/inc/aul_svc_priv_key.h
new file mode 100644 (file)
index 0000000..a3b03ae
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+#pragma once
+
+/** AUL SVC internal private key */
+#define AUL_SVC_K_OPERATION "__APP_SVC_OP_TYPE__"
+/** AUL SVC internal private key */
+#define AUL_SVC_K_URI       "__APP_SVC_URI__"
+/** AUL SVC internal private key */
+#define AUL_SVC_K_MIME      "__APP_SVC_MIME_TYPE__"
+/** AUL SVC internal private key */
+#define AUL_SVC_K_DATA      "__APP_SVC_DATA__"
+/** AUL SVC internal private key */
+#define AUL_SVC_K_PKG_NAME  "__APP_SVC_PKG_NAME__"
+/** AUL SVC internal private key */
+#define AUL_SVC_K_CATEGORY  "__APP_SVC_CATEGORY__"
+/** AUL SVC internal private key */
+#define AUL_SVC_K_RES_VAL   "__APP_SVC_K_RES_VAL__"
+/** AUL SVC internal private key */
+#define AUL_SVC_K_WIN_ID    "__APP_SVC_K_WIN_ID__"
+/** AUL SVC internal private key */
+#define AUL_SVC_K_LAUNCH_MODE   "__APP_SVC_LAUNCH_MODE__"
+
+
diff --git a/packaging/ac.conf b/packaging/ac.conf
new file mode 100644 (file)
index 0000000..f06cc3a
--- /dev/null
@@ -0,0 +1,15 @@
+d      /run/aul        1755    root    root
+t      /run/aul        -       -       -       -       security.SMACK64="System::Run"
+t      /run/aul        -       -       -       -       security.SMACK64TRANSMUTE="TRUE"
+d      /run/aul/apps   1777    root    root
+t      /run/aul/apps   -       -       -       -       security.SMACK64="*"
+t      /run/aul/apps   -       -       -       -       security.SMACK64TRANSMUTE="TRUE"
+d      /run/aul/daemons        1777    root    root
+t      /run/aul/daemons        -       -       -       -       security.SMACK64="User::Home"
+t      /run/aul/daemons        -       -       -       -       security.SMACK64TRANSMUTE="TRUE"
+d      /run/aul/dbspace        1777    root    root
+t      /run/aul/dbspace        -       -       -       -       security.SMACK64="User::Home"
+t      /run/aul/dbspace        -       -       -       -       security.SMACK64TRANSMUTE="TRUE"
+d      /run/aul/log    1777    root    root
+t      /run/aul/log    -       -       -       -       security.SMACK64="User::Home"
+t      /run/aul/log    -       -       -       -       security.SMACK64TRANSMUTE="TRUE"
diff --git a/packaging/ac.service b/packaging/ac.service
new file mode 100644 (file)
index 0000000..9e87925
--- /dev/null
@@ -0,0 +1,24 @@
+#
+#  Systemd script to Launch AMD
+#
+
+[Unit]
+Description=Start Application Management Daemon
+DefaultDependencies=false
+Requires=dbus.socket tizen-system-env.service
+After=dbus.socket tizen-system-env.service
+
+[Service]
+User=app_fw
+Group=app_fw
+SmackProcessLabel=System
+Type=notify
+EnvironmentFile=/run/tizen-system-env
+EnvironmentFile=/run/xdg-root-env
+ExecStart=/usr/bin/amd
+OOMScoreAdjust=-100
+Restart=on-failure
+RestartSec=3
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packaging/ac.socket b/packaging/ac.socket
new file mode 100644 (file)
index 0000000..74bf73d
--- /dev/null
@@ -0,0 +1,7 @@
+[Socket]
+ListenStream=/run/aul/daemons/.amd-sock
+SocketMode=0777
+DirectoryMode=0777
+
+[Install]
+WantedBy=sockets.target
diff --git a/packaging/amd.manifest b/packaging/amd.manifest
new file mode 100644 (file)
index 0000000..81ace0c
--- /dev/null
@@ -0,0 +1,6 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
+
diff --git a/packaging/amd.spec b/packaging/amd.spec
new file mode 100644 (file)
index 0000000..6aedd87
--- /dev/null
@@ -0,0 +1,146 @@
+%bcond_with x
+%bcond_with wayland
+
+Name:       amd
+Summary:    Application Management Daemon
+Version:    0.2.1
+Release:    1
+Group:      Application Framework/Service
+License:    Apache-2.0
+Source0:    %{name}-%{version}.tar.gz
+Source100:  ac.conf
+Source101:  ac.service
+Source102:  ac.socket
+Source1001: %{name}.manifest
+
+Requires(post):   /sbin/ldconfig
+Requires(post):   /usr/bin/systemctl
+Requires(postun): /sbin/ldconfig
+Requires(postun): /usr/bin/systemctl
+Requires(preun):  /usr/bin/systemctl
+Requires:   tizen-platform-config
+
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(gio-2.0)
+BuildRequires:  pkgconfig(bundle)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(security-manager)
+BuildRequires:  pkgconfig(rua)
+BuildRequires:  pkgconfig(aul)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(pkgmgr-info)
+BuildRequires:  pkgconfig(pkgmgr)
+BuildRequires:  pkgconfig(libtzplatform-config)
+BuildRequires:  pkgconfig(libsystemd-daemon)
+BuildRequires:  pkgconfig(cynara-client)
+BuildRequires:  pkgconfig(cynara-creds-socket)
+BuildRequires:  pkgconfig(cynara-session)
+BuildRequires:  pkgconfig(cert-svc-vcore)
+BuildRequires:  pkgconfig(xkbcommon)
+BuildRequires:  pkgconfig(sensor)
+BuildRequires:  pkgconfig(ttrace)
+BuildRequires:  pkgconfig(app2sd)
+BuildRequires:  pkgconfig(capi-system-info)
+%if %{with wayland}
+BuildRequires:  pkgconfig(wayland-client)
+BuildRequires:  pkgconfig(tizen-extension-client)
+BuildRequires:  pkgconfig(tizen-launch-client)
+BuildRequires:  pkgconfig(wayland-tbm-client)
+%endif
+
+%if "%{?profile}" == "tv"
+%define tizen_feature_terminate_unmanageable_app 0
+%define tizen_feature_block_input 0
+%define tizen_feature_auto_rotation 0
+%else
+%if "%{?profile}" == "ivi"
+%define tizen_feature_terminate_unmanageable_app 1
+%define tizen_feature_block_input 0
+%define tizen_feature_auto_rotation 0
+%else
+%define tizen_feature_terminate_unmanageable_app 1
+%define tizen_feature_block_input 1
+%define tizen_feature_auto_rotation 1
+%endif
+%endif
+
+%description
+Application management daemon
+
+%prep
+%setup -q
+sed -i 's|TZ_SYS_DB|%{TZ_SYS_DB}|g' %{SOURCE1001}
+cp %{SOURCE1001} .
+
+%build
+%if 0%{?simulator}
+CFLAGS="%{optflags} -D__emul__"; export CFLAGS
+%endif
+
+%if 0%{?tizen_feature_terminate_unmanageable_app}
+_TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP=ON
+%endif
+%if 0%{?tizen_feature_block_input}
+_TIZEN_FEATURE_BLOCK_INPUT=ON
+%endif
+%if 0%{?tizen_feature_auto_rotation}
+_TIZEN_FEATURE_AUTO_ROTATION=ON
+%endif
+
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+%cmake -DFULLVER=%{version} -DMAJORVER=${MAJORVER} \
+%if %{with wayland}
+       -Dwith_wayland=TRUE \
+%endif
+%if %{with x}
+       -Dwith_x11=TRUE \
+%endif
+       -D_TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP:BOOL=${_TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP} \
+       -D_TIZEN_FEATURE_BLOCK_INPUT:BOOL=${_TIZEN_FEATURE_BLOCK_INPUT} \
+       -D_TIZEN_FEATURE_AUTO_ROTATION:BOOL=${_TIZEN_FEATURE_AUTO_ROTATION} \
+       .
+
+%__make %{?_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+mkdir -p %{buildroot}%{_tmpfilesdir}
+mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
+mkdir -p %{buildroot}%{_unitdir}/sockets.target.wants
+install -m 0644 %SOURCE100 %{buildroot}%{_tmpfilesdir}/ac.conf
+install -m 0644 %SOURCE101 %{buildroot}%{_unitdir}/ac.service
+install -m 0644 %SOURCE102 %{buildroot}%{_unitdir}/ac.socket
+ln -sf ../ac.service %{buildroot}%{_unitdir}/multi-user.target.wants/ac.service
+ln -sf ../ac.socket %{buildroot}%{_unitdir}/sockets.target.wants/ac.socket
+
+%preun
+if [ $1 == 0 ]; then
+    systemctl stop ac.service
+    systemctl disable ac
+fi
+
+%post
+/sbin/ldconfig
+
+systemctl daemon-reload
+if [ $1 == 1 ]; then
+    systemctl restart ac.service
+fi
+
+%postun
+/sbin/ldconfig
+systemctl daemon-reload
+
+%files
+%license LICENSE
+%manifest %{name}.manifest
+%{_tmpfilesdir}/ac.conf
+%{_unitdir}/ac.service
+%{_unitdir}/multi-user.target.wants/ac.service
+%{_unitdir}/ac.socket
+%{_unitdir}/sockets.target.wants/ac.socket
+%caps(cap_kill,cap_dac_override=ep) %{_bindir}/amd
+
diff --git a/src/amd_app_com.c b/src/amd_app_com.c
new file mode 100644 (file)
index 0000000..680c1d9
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <glib.h>
+#include <bundle.h>
+#include <aul.h>
+#include <aul_cmd.h>
+#include <aul_app_com.h>
+#include <aul_sock.h>
+
+#include "amd_util.h"
+#include "amd_app_com.h"
+
+struct endpoint_info {
+       char *endpoint;
+       unsigned int propagate;
+       char *privilege;
+       GList *clients;
+};
+
+struct client_info {
+       int pid;
+       uid_t uid;
+       char *filter;
+       struct endpoint_info *endpoint;
+};
+
+static GHashTable *cpid_tbl;
+static GHashTable *endpoint_tbl;
+
+static void __remove_client(struct endpoint_info *info, int cpid);
+
+static void __free_endpoint(struct endpoint_info *info)
+{
+       if (!info)
+               return;
+
+       if (info->endpoint)
+               g_free(info->endpoint);
+
+       if (info->privilege)
+               g_free(info->privilege);
+
+       if (info->clients)
+               g_list_free(info->clients);
+
+       g_free(info);
+}
+
+int _app_com_broker_init(void)
+{
+       if (!endpoint_tbl) {
+               endpoint_tbl = g_hash_table_new(g_str_hash, g_str_equal);
+               if (endpoint_tbl == NULL) {
+                       _E("out of memory");
+                       return -1;
+               }
+       }
+
+       if (!cpid_tbl) {
+               cpid_tbl = g_hash_table_new(g_direct_hash, g_direct_equal);
+               if (cpid_tbl == NULL) {
+                       _E("out of memory");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static void __remove_cpid(gpointer key, gpointer value, gpointer user_data)
+{
+       int pid = GPOINTER_TO_INT(key);
+       struct endpoint_info *info;
+       GList *client_list = (GList *)value;
+
+       while (client_list) {
+               info = (struct endpoint_info *)client_list->data;
+               __remove_client(info, pid);
+               client_list = client_list->next;
+       }
+       g_list_free((GList *)value);
+}
+
+int _app_com_broker_fini(void)
+{
+       if (cpid_tbl) {
+               g_hash_table_foreach(cpid_tbl, __remove_cpid, NULL);
+               g_hash_table_destroy(cpid_tbl);
+               cpid_tbl = NULL;
+       }
+
+       if (endpoint_tbl) {
+               g_hash_table_destroy(endpoint_tbl);
+               endpoint_tbl = NULL;
+       }
+
+       return 0;
+}
+
+int _app_com_add_endpoint(const char *endpoint, unsigned int propagate,
+               const char *assoc_priv)
+{
+       struct endpoint_info *info;
+
+       info = g_hash_table_lookup(endpoint_tbl, endpoint);
+       if (info) {
+               _E("endpoint already exists.");
+               return AUL_APP_COM_R_ERROR_ENDPOINT_ALREADY_EXISTS;
+       }
+
+       _D("endpoint=%s propagate=%d assoc_priv=%s",
+                       endpoint, propagate, assoc_priv);
+
+       info = (struct endpoint_info *)g_malloc0(sizeof(struct endpoint_info));
+       if (info == NULL) {
+               _E("out of memory");
+               return AUL_APP_COM_R_ERROR_OUT_OF_MEMORY;
+       }
+
+       info->endpoint = g_strdup(endpoint);
+       info->propagate = propagate;
+       info->clients = NULL;
+
+       if (assoc_priv)
+               info->privilege = g_strdup(assoc_priv);
+       else
+               info->privilege = NULL;
+
+       g_hash_table_insert(endpoint_tbl, info->endpoint, info);
+
+       return AUL_APP_COM_R_ERROR_OK;
+}
+
+int _app_com_remove_endpoint(const char *endpoint)
+{
+       struct endpoint_info *info;
+
+       info = g_hash_table_lookup(endpoint_tbl, endpoint);
+       if (!info) {
+               _D("endpoint not exists");
+               return AUL_APP_COM_R_ERROR_UNKNOWN_ENDPOINT;
+       }
+
+       if (info->clients != NULL) {
+               _D("client active");
+               return AUL_APP_COM_R_ERROR_CLIENT_REMAINING;
+       }
+
+       g_hash_table_remove(endpoint_tbl, endpoint);
+       __free_endpoint(info);
+
+       return AUL_APP_COM_R_ERROR_OK;
+}
+
+static struct client_info *__add_client(struct endpoint_info *info,
+               const char *filter, int pid, uid_t uid)
+{
+       GList *client_list;
+       struct client_info *c;
+
+       c = (struct client_info *)g_malloc0(sizeof(struct client_info));
+       if (c == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       c->endpoint = info;
+       c->pid = pid;
+       c->uid = uid;
+       if (filter)
+               c->filter = g_strdup(filter);
+       else
+               c->filter = NULL;
+
+       info->clients = g_list_append(info->clients, c);
+       client_list = g_hash_table_lookup(cpid_tbl, GINT_TO_POINTER(pid));
+       if (client_list == NULL) {
+               client_list = g_list_append(client_list, info);
+               g_hash_table_insert(cpid_tbl, GINT_TO_POINTER(pid),
+                               client_list);
+       } else {
+               client_list = g_list_append(client_list, info);
+       }
+
+       return c;
+}
+
+int _app_com_join(const char *endpoint, int cpid, const char *filter,
+               uid_t uid)
+{
+       struct endpoint_info *info;
+
+       info = g_hash_table_lookup(endpoint_tbl, endpoint);
+       if (!info) {
+               _E("endpoint not exists: %s", endpoint);
+               return AUL_APP_COM_R_ERROR_UNKNOWN_ENDPOINT;
+       }
+
+       _D("endpoint=%s cpid=%d filter=%s uid=%d", endpoint, cpid, filter, uid);
+
+       if (__add_client(info, filter, cpid, uid) == NULL)
+               return AUL_APP_COM_R_ERROR_OUT_OF_MEMORY;
+
+       return AUL_APP_COM_R_ERROR_OK;
+}
+
+const char *_app_com_get_privilege(const char *endpoint)
+{
+       struct endpoint_info *info;
+
+       info = g_hash_table_lookup(endpoint_tbl, endpoint);
+       if (!info) {
+               _E("endpoint not exists: %s", endpoint);
+               return NULL;
+       }
+
+       return info->privilege;
+}
+
+static int __check_filter(const char *filter, int cpid, int rpid, bundle *b)
+{
+       /* TODO */
+       return 0;
+}
+
+int _app_com_send(const char *endpoint, int cpid, bundle *envelope, uid_t uid)
+{
+       struct endpoint_info *info;
+       GList *client_head;
+       struct client_info *client;
+       int ret;
+       int result = AUL_APP_COM_R_OK;
+
+       info = g_hash_table_lookup(endpoint_tbl, endpoint);
+       if (!info) {
+               _E("endpoint not exists: %s", endpoint);
+               return AUL_APP_COM_R_ERROR_UNKNOWN_ENDPOINT;
+       }
+
+       /* TODO delete internal keys */
+
+       _D("endpoint=%s cpid=%d", endpoint, cpid);
+
+       bundle_add_str(envelope, AUL_K_COM_ENDPOINT, endpoint);
+       bundle_add_byte(envelope, AUL_K_COM_RESULT, &result, sizeof(result));
+
+       client_head = info->clients;
+       while (client_head) {
+               client = (struct client_info *)client_head->data;
+               client_head = client_head->next;
+               if (client == NULL)
+                       continue;
+               if (client->pid == cpid)
+                       continue;
+               if (client->uid >= REGULAR_UID_MIN && client->uid != uid)
+                       continue;
+
+               if (client->filter) {
+                       ret = __check_filter(client->filter, cpid, client->pid,
+                                       envelope);
+                       if (ret < 0)
+                               continue;
+               }
+
+               ret = aul_sock_send_bundle(client->pid, client->uid,
+                               APP_COM_MESSAGE, envelope, AUL_SOCK_NOREPLY);
+               if (ret < 0) {
+                       _E("failed to send message pid(%d), uid(%d), ret(%d)",
+                                       client->pid, client->uid, ret);
+               }
+       }
+
+       return AUL_APP_COM_R_ERROR_OK;
+}
+
+static void __remove_client(struct endpoint_info *info, int cpid)
+{
+       GList *client_head;
+       struct client_info *client;
+
+       if (info == NULL)
+               return;
+
+       client_head = info->clients;
+       while (client_head) {
+               client = (struct client_info *)client_head->data;
+               client_head = client_head->next;
+               if (client && client->pid == cpid) {
+                       info->clients = g_list_remove(info->clients, client);
+                       if (client->filter)
+                               g_free(client->filter);
+
+                       g_free(client);
+               }
+       }
+
+       if (info->clients == NULL) {
+               g_hash_table_remove(endpoint_tbl, info->endpoint);
+               _D("endpoint removed: %s", info->endpoint);
+               __free_endpoint(info);
+       }
+}
+
+int _app_com_leave(const char *endpoint, int cpid)
+{
+       struct endpoint_info *info;
+       GList *endpoint_head;
+
+       info = g_hash_table_lookup(endpoint_tbl, endpoint);
+       if (!info) {
+               _E("endpoint not exists: %s", endpoint);
+               return AUL_APP_COM_R_ERROR_UNKNOWN_ENDPOINT;
+       }
+
+       endpoint_head = g_hash_table_lookup(cpid_tbl, GINT_TO_POINTER(cpid));
+       if (endpoint_head) {
+               endpoint_head = g_list_remove(endpoint_head, info);
+               if (endpoint_head == NULL) {
+                       g_hash_table_remove(cpid_tbl, GINT_TO_POINTER(cpid));
+               } else {
+                       g_hash_table_replace(cpid_tbl, GINT_TO_POINTER(cpid),
+                                       endpoint_head);
+               }
+       }
+       __remove_client(info, cpid);
+
+       return AUL_APP_COM_R_ERROR_OK;
+}
+
+int _app_com_client_remove(int cpid)
+{
+       GList *client_list;
+       struct endpoint_info *info;
+       GList *client_head;
+
+       client_list = g_hash_table_lookup(cpid_tbl, GINT_TO_POINTER(cpid));
+       if (client_list == NULL)
+               return AUL_APP_COM_R_OK;
+
+       client_head = g_list_first(client_list);
+       while (client_head) {
+               info = (struct endpoint_info *)client_head->data;
+               client_head = g_list_next(client_head);
+               if (info) {
+                       client_list = g_list_remove(client_list, info);
+                       __remove_client(info, cpid);
+               }
+       }
+
+       g_hash_table_remove(cpid_tbl, GINT_TO_POINTER(cpid));
+
+       return AUL_APP_COM_R_ERROR_OK;
+}
+
+bool _app_com_endpoint_exists(const char *endpoint)
+{
+       return g_hash_table_contains(endpoint_tbl, endpoint);
+}
diff --git a/src/amd_app_group.c b/src/amd_app_group.c
new file mode 100644 (file)
index 0000000..b0aaa04
--- /dev/null
@@ -0,0 +1,1688 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include <glib.h>
+#include <aul.h>
+#include <aul_svc.h>
+#include <bundle_internal.h>
+#include <aul_sock.h>
+#include <wayland-client.h>
+#include <wayland-tbm-client.h>
+#include <tizen-extension-client-protocol.h>
+
+#include "amd_util.h"
+#include "amd_app_group.h"
+#include "amd_launch.h"
+#include "amd_request.h"
+#include "amd_app_status.h"
+#include "app_signal.h"
+#include "amd_appinfo.h"
+#include "amd_share.h"
+#include "amd_suspend.h"
+#include "amd_wayland.h"
+
+#define APP_SVC_K_LAUNCH_MODE   "__APP_SVC_LAUNCH_MODE__"
+
+typedef struct _app_group_context_t {
+       int pid;
+       int wid;
+       int status;
+       int fg;
+       int group_sig;
+       int can_be_leader;
+       int reroute;
+       int caller_pid;
+       int can_shift;
+       int recycle;
+       app_group_launch_mode launch_mode;
+} app_group_context_t;
+
+static struct wl_display *display;
+static struct tizen_policy *tz_policy;
+static int tz_policy_initialized;
+static GHashTable *app_group_hash;
+static int dead_pid = -1;
+static int focused_leader_pid = -1;
+static GList *recycle_bin;
+extern char *home_appid;
+
+static void __wl_listener_cb(void *data, struct wl_registry *reg,
+               uint32_t id, const char *interface, uint32_t ver)
+{
+       if (!strcmp(interface, "tizen_policy")) {
+               if (!tz_policy) {
+                       tz_policy = wl_registry_bind(reg, id,
+                                       &tizen_policy_interface, 1);
+               }
+       }
+}
+
+static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
+               uint32_t id)
+{
+       if (tz_policy) {
+               tizen_policy_destroy(tz_policy);
+               tz_policy = NULL;
+       }
+}
+
+static struct wl_registry_listener registry_listener = {
+       __wl_listener_cb,
+       __wl_listener_remove_cb
+};
+
+static int __wl_init(void)
+{
+       if (!display) {
+               display = _wayland_get_display();
+               if (!display) {
+                       _E("Failed to get display");
+                       return -1;
+               }
+       }
+
+       if (!tz_policy)
+               return -1;
+
+       tz_policy_initialized = 1;
+
+       return 0;
+}
+
+static void __lower_window(int wid)
+{
+       if (!tz_policy_initialized) {
+               if (__wl_init() < 0) {
+                       _E("__wl_init() failed");
+                       return;
+               }
+       }
+
+       tizen_policy_lower_by_res_id(tz_policy, wid);
+       wl_display_roundtrip(display);
+}
+
+static void __attach_window(int parent_wid, int child_wid)
+{
+       if (!tz_policy_initialized) {
+               if (__wl_init() < 0) {
+                       _E("__wl_init() failed");
+                       return;
+               }
+       }
+
+       tizen_policy_set_transient_for(tz_policy, child_wid, parent_wid);
+       wl_display_roundtrip(display);
+}
+
+static void __detach_window(int child_wid)
+{
+       if (!tz_policy_initialized) {
+               if (__wl_init() < 0) {
+                       _E("__wl_init() failed");
+                       return;
+               }
+       }
+
+       tizen_policy_unset_transient_for(tz_policy, child_wid);
+       wl_display_roundtrip(display);
+}
+
+static void __activate_below(int wid, int below_wid)
+{
+       if (!tz_policy_initialized) {
+               if (__wl_init() < 0) {
+                       _E("__wl_init() failed");
+                       return;
+               }
+       }
+
+       tizen_policy_activate_below_by_res_id(tz_policy, below_wid, wid);
+       wl_display_roundtrip(display);
+}
+
+static void __activate_above(int wid, int above_wid)
+{
+       if (!tz_policy_initialized) {
+               if (__wl_init() < 0) {
+                       _E("__wl_init() failed");
+                       return;
+               }
+       }
+
+       tizen_policy_activate_above_by_res_id(tz_policy, above_wid, wid);
+       wl_display_roundtrip(display);
+}
+
+static gint __comp_pid(gconstpointer a, gconstpointer b)
+{
+       app_group_context_t *ac1 = (app_group_context_t *)a;
+
+       return ac1->pid - GPOINTER_TO_INT(b);
+}
+
+static void __list_destroy_cb(gpointer data)
+{
+       free(data);
+}
+
+static gboolean __hash_table_cb(gpointer key, gpointer value,
+               gpointer user_data)
+{
+       int pid = GPOINTER_TO_INT(user_data);
+       GList *list = (GList *)value;
+       GList *itr = g_list_first(list);
+       app_group_context_t *ac;
+
+       while (itr != NULL) {
+               ac = (app_group_context_t *)itr->data;
+               if (ac && ac->pid == pid) {
+                       free(ac);
+                       list = g_list_delete_link(list, itr);
+                       if (g_list_length(list) == 0) {
+                               g_list_free_full(list, __list_destroy_cb);
+                               return TRUE;
+                       } else {
+                               return FALSE;
+                       }
+               }
+               itr = g_list_next(itr);
+       }
+
+       return FALSE;
+}
+
+static GList *__find_removable_apps(int from)
+{
+       int cnt;
+       int *pids = NULL;
+       GList *list = NULL;
+       bool found = false;
+       int i;
+       int j;
+       int *gpids = NULL;
+       int gcnt;
+
+       _app_group_get_leader_pids(&cnt, &pids);
+
+       for (i = 0; i < cnt; i++) {
+               _app_group_get_group_pids(pids[i], &gcnt, &gpids);
+               for (j = 0; j < gcnt; j++) {
+                       if (gpids[j] == from) {
+                               found = true;
+                               continue;
+                       }
+
+                       if (found) {
+                               list = g_list_append(list,
+                                               GINT_TO_POINTER(gpids[j]));
+                       }
+               }
+
+               if (gpids != NULL)
+                       free(gpids);
+
+               if (found)
+                       break;
+       }
+
+       if (pids != NULL)
+               free(pids);
+
+       return list;
+}
+
+static void __prepare_to_suspend_services(int pid, uid_t uid)
+{
+       int ret;
+       int dummy;
+
+       _D("[__SUSPEND__] pid: %d, uid: %d", pid, uid);
+       ret = aul_sock_send_raw(pid, uid, APP_SUSPEND, (unsigned char *)&dummy,
+                       sizeof(int), AUL_SOCK_NOREPLY);
+       if (ret < 0)
+               _E("error on suspend service for pid: %d", pid);
+}
+
+static void __prepare_to_wake_services(int pid, uid_t uid)
+{
+       int ret;
+       int dummy;
+
+       _D("[__SUSPEND__] pid: %d, uid: %d", pid, uid);
+       ret = aul_sock_send_raw(pid, uid, APP_WAKE, (unsigned char *)&dummy,
+                       sizeof(int), AUL_SOCK_NOREPLY);
+       if (ret < 0)
+               _E("error on wake service for pid: %d", pid);
+}
+
+static void __set_flag(GList *list, int cpid, int flag, bool force)
+{
+       app_group_context_t *ac;
+       app_status_h app_status;
+       const struct appinfo *ai;
+       const char *appid;
+       const char *pkgid;
+       int bg_category;
+       uid_t uid;
+
+       while (list) {
+               ac = (app_group_context_t *)list->data;
+               if (ac && (ac->fg != flag || force == true)) {
+                       app_status = _app_status_find(ac->pid);
+                       appid = _app_status_get_appid(app_status);
+                       uid = _app_status_get_uid(app_status);
+                       ai = _appinfo_find(uid, appid);
+                       pkgid = _appinfo_get_value(ai, AIT_PKGID);
+                       bg_category = (intptr_t)_appinfo_get_value(ai,
+                                       AIT_BG_CATEGORY);
+                       if (flag) {
+                               _D("Send FG signal %s", appid);
+                               aul_send_app_status_change_signal(ac->pid,
+                                               appid, pkgid, STATUS_FOREGROUND,
+                                               APP_TYPE_UI);
+                               if (!bg_category) {
+                                       _app_status_find_service_apps(
+                                               app_status,
+                                               STATUS_VISIBLE,
+                                               __prepare_to_wake_services,
+                                               false);
+                               }
+                       } else {
+                               _D("send BG signal %s", appid);
+                               aul_send_app_status_change_signal(ac->pid,
+                                               appid, pkgid, STATUS_BACKGROUND,
+                                               APP_TYPE_UI);
+                               if (!bg_category) {
+                                       _app_status_find_service_apps(
+                                               app_status,
+                                               STATUS_BG,
+                                               __prepare_to_suspend_services,
+                                               true);
+                                       if (force && cpid == ac->pid) {
+                                               __prepare_to_suspend_services(
+                                                               ac->pid, uid);
+                                               _suspend_add_timer(ac->pid, ai);
+                                       }
+                               }
+                       }
+                       ac->fg = flag;
+               }
+               list = g_list_next(list);
+       }
+}
+
+static void __set_fg_flag(int cpid, int flag, bool force)
+{
+       int lpid = _app_group_get_leader_pid(cpid);
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               ac = (app_group_context_t *)i->data;
+               if (ac && ac->pid == lpid) {
+                       __set_flag(i, cpid, flag, force);
+                       break;
+               }
+       }
+}
+
+static bool __is_visible(int cpid)
+{
+       int lpid = _app_group_get_leader_pid(cpid);
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               ac = (app_group_context_t *)i->data;
+               if (ac && ac->pid == lpid) {
+                       while (i != NULL) {
+                               ac = (app_group_context_t *)i->data;
+                               if (ac && ac->status == STATUS_VISIBLE)
+                                       return true;
+
+                               i = g_list_next(i);
+                       }
+                       break;
+               }
+       }
+
+       return false;
+}
+
+static bool __can_attach_window(bundle *b, const char *appid,
+               app_group_launch_mode *launch_mode, uid_t uid)
+{
+       char *str = NULL;
+       const char *mode = NULL;
+       const struct appinfo *ai = NULL;
+
+       ai = _appinfo_find(uid, appid);
+       mode = _appinfo_get_value(ai, AIT_LAUNCH_MODE);
+
+       if (mode == NULL)
+               *launch_mode = APP_GROUP_LAUNCH_MODE_SINGLE;
+       else if (strcmp(mode, "caller") == 0)
+               *launch_mode = APP_GROUP_LAUNCH_MODE_CALLER;
+       else if (strcmp(mode, "single") == 0)
+               *launch_mode = APP_GROUP_LAUNCH_MODE_SINGLE;
+       else if (strcmp(mode, "group") == 0)
+               *launch_mode = APP_GROUP_LAUNCH_MODE_GROUP;
+       else if (strcmp(mode, "singleton") == 0)
+               *launch_mode = APP_GROUP_LAUNCH_MODE_SINGLETON;
+
+       switch (*launch_mode) {
+       case APP_GROUP_LAUNCH_MODE_CALLER:
+       case APP_GROUP_LAUNCH_MODE_SINGLETON:
+               _D("launch mode from db is caller or singleton");
+
+               bundle_get_str(b, APP_SVC_K_LAUNCH_MODE, &str);
+               if (str != NULL && strncmp(str, "group", 5) == 0)
+                       return true;
+               break;
+       case APP_GROUP_LAUNCH_MODE_GROUP:
+               return true;
+       case APP_GROUP_LAUNCH_MODE_SINGLE:
+               return false;
+       }
+
+       return false;
+}
+
+static bool __can_be_leader(bundle *b)
+{
+       char *str = NULL;
+
+       bundle_get_str(b, AUL_SVC_K_CAN_BE_LEADER, &str);
+       if (str != NULL && strcmp(str, "true") == 0)
+               return true;
+
+       return false;
+}
+
+static int __get_previous_pid(int pid)
+{
+       int previous_pid = -1;
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac == NULL) {
+                               i = g_list_next(i);
+                               continue;
+                       }
+
+                       if (ac && ac->pid == pid)
+                               return previous_pid;
+
+                       previous_pid = ac->pid;
+                       i = g_list_next(i);
+               }
+       }
+
+       return -1;
+}
+
+static int __get_caller_pid(bundle *kb)
+{
+       const char *pid_str;
+       int pid;
+
+       pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
+       if (pid_str)
+               goto end;
+
+       pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
+       if (pid_str == NULL)
+               return -1;
+
+end:
+       pid = atoi(pid_str);
+       if (pid <= 1)
+               return -1;
+
+       return pid;
+}
+
+static app_group_context_t *__detach_context_from_recycle_bin(int pid)
+{
+       GList *iter = recycle_bin;
+       app_group_context_t *ac;
+
+       while (iter) {
+               ac = (app_group_context_t *)iter->data;
+               if (ac && ac->pid == pid) {
+                       recycle_bin = g_list_delete_link(recycle_bin, iter);
+                       return ac;
+               }
+
+               iter = g_list_next(iter);
+       }
+
+       return NULL;
+
+}
+
+static void __group_add(int leader_pid, int pid, int wid,
+               app_group_launch_mode mode, int caller_pid, int can_shift,
+               int recycle)
+{
+       app_group_context_t *ac = NULL;
+       GList *list;
+       GList *tmp_list;
+
+       ac = __detach_context_from_recycle_bin(pid);
+       if (ac == NULL) {
+               ac = malloc(sizeof(app_group_context_t));
+               if (ac == NULL) {
+                       _E("out of memory");
+                       return;
+               }
+               ac->pid = pid;
+               ac->wid = wid;
+               ac->fg = 0;
+               ac->can_be_leader = 0;
+               ac->reroute = 0;
+               ac->launch_mode = mode;
+               ac->caller_pid = caller_pid;
+               ac->can_shift = can_shift;
+               ac->recycle = recycle;
+       }
+
+       if (leader_pid == pid || ac->recycle)
+               ac->group_sig = 1;
+       else
+               ac->group_sig = 0;
+
+       dead_pid = -1;
+
+       list = (GList *)g_hash_table_lookup(app_group_hash,
+                       GINT_TO_POINTER(leader_pid));
+       if (list != NULL) {
+               tmp_list = g_list_find_custom(list, GINT_TO_POINTER(pid),
+                               __comp_pid);
+               if (tmp_list != NULL) {
+                       _E("pid exist");
+                       free(ac);
+                       return;
+               }
+       }
+
+       list = g_list_append(list, ac);
+       g_hash_table_insert(app_group_hash, GINT_TO_POINTER(leader_pid), list);
+
+       if (ac->wid != 0)
+               _app_group_set_window(pid, ac->wid);
+}
+
+static void __group_remove(int pid)
+{
+       int ppid = __get_previous_pid(pid);
+
+       g_hash_table_foreach_remove(app_group_hash, __hash_table_cb,
+                       GINT_TO_POINTER(pid));
+
+       if (ppid != -1)
+               _app_group_set_status(ppid, -1, false);
+}
+
+static app_group_context_t *__get_context(int pid)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac && ac->pid == pid)
+                               return ac;
+
+                       i = g_list_next(i);
+               }
+       }
+
+       return NULL;
+}
+
+static int __can_recycle(int pid)
+{
+       app_group_context_t *context = __get_context(pid);
+
+       if (context)
+               return context->recycle;
+
+       return 0;
+}
+
+static int __can_reroute(int pid)
+{
+       app_group_context_t *context = __get_context(pid);
+
+       if (context)
+               return context->reroute;
+
+       return 0;
+}
+
+static app_group_context_t *__context_dup(const app_group_context_t *context)
+{
+       app_group_context_t *dup;
+
+       if (!context) {
+               _E("context is NULL.");
+               return NULL;
+       }
+
+       dup = malloc(sizeof(app_group_context_t));
+       if (!dup) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       memcpy(dup, context, sizeof(app_group_context_t));
+       return dup;
+}
+
+static void __do_recycle(app_group_context_t *context)
+{
+       const char *appid;
+       const char *pkgid;
+       const struct appinfo *ai;
+       app_status_h app_status;
+       uid_t uid;
+
+       app_status = _app_status_find(context->pid);
+       uid = _app_status_get_uid(app_status);
+
+       if (context->fg) {
+               appid = _app_status_get_appid(app_status);
+               ai = _appinfo_find(uid, appid);
+               pkgid = _appinfo_get_value(ai, AIT_PKGID);
+
+               _D("send_signal BG %s", appid);
+               aul_send_app_status_change_signal(context->pid, appid, pkgid,
+                               STATUS_BACKGROUND, APP_TYPE_UI);
+               _app_status_find_service_apps(app_status, STATUS_BG,
+                               __prepare_to_suspend_services, true);
+               context->fg = 0;
+       }
+       recycle_bin = g_list_append(recycle_bin, context);
+       _temporary_permission_drop(context->pid, uid);
+}
+
+void _app_group_remove(int pid)
+{
+       app_group_context_t *context;
+
+       __group_remove(pid);
+       context = __detach_context_from_recycle_bin(pid);
+       if (context)
+               free(context);
+}
+
+void _app_group_remove_from_recycle_bin(int pid)
+{
+       app_group_context_t *context = __detach_context_from_recycle_bin(pid);
+
+       if (context)
+               free(context);
+}
+
+int _app_group_get_window(int pid)
+{
+       app_group_context_t *context = __get_context(pid);
+
+       if (context)
+               return context->wid;
+
+       return -1;
+}
+
+int _app_group_set_window(int pid, int wid)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       int previous_wid;
+       int caller_wid;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               previous_wid = 0;
+               while (i != NULL) {
+                       ac = (app_group_context_t *) i->data;
+                       if (ac == NULL) {
+                               i = g_list_next(i);
+                               continue;
+                       }
+
+                       if (ac && ac->pid == pid) {
+                               ac->wid = wid;
+                               if (previous_wid != 0)
+                                       __attach_window(previous_wid, wid);
+
+                               if (ac->can_shift && ac->caller_pid > 0) {
+                                       caller_wid = _app_group_get_window(
+                                                       ac->caller_pid);
+                                       if (caller_wid != 0) {
+                                               __attach_window(caller_wid,
+                                                               wid);
+                                       }
+                               }
+
+                               i = g_list_next(i);
+                               if (i) {
+                                       ac = (app_group_context_t *)i->data;
+                                       if (ac->wid != 0)
+                                               __attach_window(wid, ac->wid);
+                               }
+
+                               return 0;
+                       }
+                       previous_wid = ac->wid;
+                       i = g_list_next(i);
+               }
+       }
+
+       return -1;
+}
+
+void _app_group_clear_top(int pid, uid_t uid)
+{
+       int p;
+       int wid;
+       GList *list;
+       GList *itr;
+
+       list = __find_removable_apps(pid);
+       if (list != NULL) {
+               itr = g_list_last(list);
+               while (itr != NULL) {
+                       p = GPOINTER_TO_INT(itr->data);
+                       if (p > 0) {
+                               wid = _app_group_get_window(p);
+                               __detach_window(wid);
+                               aul_send_app_terminate_request_signal(p,
+                                               NULL, NULL, NULL);
+                               _term_sub_app(p, uid);
+                               _app_group_remove(p);
+                       }
+                       itr = g_list_previous(itr);
+               }
+               g_list_free(list);
+       }
+}
+
+bool _app_group_is_group_app(bundle *kb, uid_t uid)
+{
+       char *str = NULL;
+       const char *mode;
+       char *appid = NULL;
+       const struct appinfo *ai;
+
+       if (kb == NULL)
+               return false;
+
+       bundle_get_str(kb, AUL_K_APPID, &appid);
+       if (appid == NULL)
+               return false;
+
+       ai = _appinfo_find(uid, appid);
+       mode = _appinfo_get_value(ai, AIT_LAUNCH_MODE);
+
+       if (mode != NULL && (strcmp(mode, "caller") == 0 ||
+                               strcmp(mode, "singleton") == 0)) {
+               bundle_get_str(kb, APP_SVC_K_LAUNCH_MODE, &str);
+               if (str != NULL && strcmp(str, "group") == 0)
+                       return true;
+       } else if (mode != NULL && strcmp(mode, "group") == 0) {
+               return true;
+       }
+
+       return false;
+}
+
+void _app_group_get_leader_pids(int *cnt, int **pids)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       int size = g_hash_table_size(app_group_hash);
+       int *leader_pids;
+       int i;
+
+       if (size > 0) {
+               leader_pids = (int *)malloc(sizeof(int) * size);
+               if (leader_pids == NULL) {
+                       _E("out of memory");
+                       *cnt = 0;
+                       *pids = NULL;
+                       return;
+               }
+
+               g_hash_table_iter_init(&iter, app_group_hash);
+               i = 0;
+               while (g_hash_table_iter_next(&iter, &key, &value)) {
+                       leader_pids[i] = GPOINTER_TO_INT(key);
+                       i++;
+               }
+
+               *cnt = size;
+               *pids = leader_pids;
+       } else {
+               *cnt = 0;
+               *pids = NULL;
+       }
+}
+
+bool _app_group_is_leader_pid(int pid)
+{
+       int cnt;
+       int *pids = NULL;
+       int i;
+
+       _app_group_get_leader_pids(&cnt, &pids);
+       for (i = 0; i < cnt; i++) {
+               if (pid == pids[i]) {
+                       free(pids);
+                       return true;
+               }
+       }
+
+       if (pids != NULL)
+               free(pids);
+
+       return false;
+}
+
+void _app_group_get_group_pids(int leader_pid, int *cnt, int **pids)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       int size;
+       int *pid_array;
+       int j;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               if (GPOINTER_TO_INT(key) == leader_pid) {
+                       list = (GList *)value;
+                       i = g_list_first(list);
+                       size = g_list_length(list);
+
+                       if (size > 0) {
+                               j = 0;
+                               pid_array = (int *)malloc(sizeof(int) * size);
+                               if (pid_array == NULL) {
+                                       _E("out of memory");
+                                       *cnt = 0;
+                                       *pids = NULL;
+                                       return;
+                               }
+
+                               while (i != NULL) {
+                                       ac = (app_group_context_t *)i->data;
+                                       pid_array[j] = ac->pid;
+                                       i = g_list_next(i);
+                                       j++;
+                               }
+
+                               *cnt = size;
+                               *pids = pid_array;
+                       } else {
+                               *cnt = 0;
+                               *pids = NULL;
+                       }
+                       return;
+               }
+       }
+
+       *cnt = 0;
+       *pids = NULL;
+}
+
+bool _app_group_is_sub_app(int pid)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *found;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               if (list != NULL) {
+                       found = g_list_find_custom(list, GINT_TO_POINTER(pid),
+                                       __comp_pid);
+                       if (found) {
+                               if (g_list_first(list) == found)
+                                       return false;
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+void _app_group_reroute(int pid)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *found;
+       GList *before;
+       GList *after;
+       app_group_context_t *ac1;
+       app_group_context_t *ac2;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               if (list != NULL) {
+                       found = g_list_find_custom(list, GINT_TO_POINTER(pid),
+                                       __comp_pid);
+                       if (found) {
+                               before = g_list_previous(found);
+                               after = g_list_next(found);
+                               if (before == NULL || after == NULL)
+                                       return;
+
+                               _D("reroute");
+                               ac1 = (app_group_context_t *)before->data;
+                               ac2 = (app_group_context_t *)after->data;
+
+                               __attach_window(ac1->wid, ac2->wid);
+                               break;
+                       }
+               }
+       }
+}
+
+int _app_group_get_leader_pid(int pid)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *found;
+       int lpid = -1;
+       int again = 0;
+
+repeat:
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               if (list != NULL) {
+                       found = g_list_find_custom(list, GINT_TO_POINTER(pid),
+                                       __comp_pid);
+                       if (found) {
+                               lpid = GPOINTER_TO_INT(key);
+                               break;
+                       }
+               }
+       }
+
+       if (lpid == -1 && dead_pid == pid)
+               lpid = focused_leader_pid;
+
+       if (lpid == -1 && again == 0) {
+               pid = getpgid(pid);
+               again = 1;
+               goto repeat;
+       }
+
+       return lpid;
+}
+
+void _app_group_set_dead_pid(int pid)
+{
+       focused_leader_pid = _app_group_get_leader_pid(pid);
+       dead_pid = pid;
+       if (dead_pid == focused_leader_pid) {
+               focused_leader_pid = -1;
+               dead_pid = -1;
+       }
+}
+
+int _app_group_get_status(int pid)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac && ac->pid == pid)
+                               return  ac->status;
+
+                       i = g_list_next(i);
+               }
+       }
+       return -1;
+}
+
+static void __set_status(app_group_context_t *ac, app_group_context_t *last_ac,
+               int lpid, int pid, int status, bool force)
+{
+       const char *pkgid;
+       app_status_h app_status;
+
+       if (status > 0)
+               ac->status = status;
+
+       if (last_ac->wid != 0 || status == STATUS_VISIBLE || force == TRUE) {
+               if (__is_visible(pid)) {
+                       __set_fg_flag(pid, 1, force);
+                       if (!ac->group_sig && lpid != pid) {
+                               app_status = _app_status_find(pid);
+                               pkgid = _app_status_get_pkgid(app_status);
+                               _D("send group signal %d", pid);
+                               aul_send_app_group_signal(lpid, pid, pkgid);
+                               ac->group_sig = 1;
+                       }
+               } else {
+                       __set_fg_flag(pid, 0, force);
+               }
+       }
+}
+
+int _app_group_set_status(int pid, int status, bool force)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+       GList *last;
+       app_group_context_t *last_ac;
+       int lpid;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               last = g_list_last(list);
+               last_ac = (app_group_context_t *)last->data;
+               lpid = GPOINTER_TO_INT(key);
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac && ac->pid == pid) {
+                               __set_status(ac, last_ac, lpid, pid, status,
+                                               force);
+                               return 0;
+                       }
+                       i = g_list_next(i);
+               }
+       }
+       return -1;
+}
+
+int _app_group_get_fg_flag(int pid)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac && ac->pid == pid)
+                               return ac->fg;
+
+                       i = g_list_next(i);
+               }
+       }
+
+       return 0;
+}
+
+int _app_group_set_hint(int pid, bundle *kb)
+{
+       char *str_leader = NULL;
+       char *str_reroute = NULL;
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+
+       if (kb == NULL)
+               return -1;
+
+       bundle_get_str(kb, AUL_SVC_K_CAN_BE_LEADER, &str_leader);
+       bundle_get_str(kb, AUL_SVC_K_REROUTE, &str_reroute);
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac && ac->pid == pid) {
+                               if (str_leader && !strcmp(str_leader, "true"))
+                                       ac->can_be_leader = 1;
+                               if (str_reroute && !strcmp(str_reroute, "true"))
+                                       ac->reroute = 1;
+                               return 0;
+                       }
+                       i = g_list_next(i);
+               }
+       }
+
+       return -1;
+}
+
+int _app_group_find_second_leader(int lpid)
+{
+       app_group_context_t *ac;
+       GList *list;
+
+       list = (GList *)g_hash_table_lookup(app_group_hash,
+                       GINT_TO_POINTER(lpid));
+       if (list != NULL) {
+               list = g_list_next(list);
+               if (list != NULL) {
+                       ac = (app_group_context_t *)list->data;
+                       if (ac && ac->can_be_leader) {
+                               _W("found the second leader, lpid: %d, pid: %d",
+                                               lpid, ac->pid);
+                               return ac->pid;
+                       }
+               }
+       }
+
+       return -1;
+}
+
+void _app_group_remove_leader_pid(int lpid)
+{
+       app_group_context_t *ac;
+       GList *next;
+       GList *list;
+
+       list = (GList *)g_hash_table_lookup(app_group_hash,
+                       GINT_TO_POINTER(lpid));
+       if (list != NULL) {
+               next = g_list_next(list);
+               if (next != NULL) {
+                       ac = (app_group_context_t *)list->data;
+                       if (ac)
+                               free(ac);
+                       list = g_list_delete_link(list, list);
+                       ac = (app_group_context_t *)next->data;
+                       g_hash_table_insert(app_group_hash,
+                                       GINT_TO_POINTER(ac->pid), next);
+                       g_hash_table_remove(app_group_hash,
+                                       GINT_TO_POINTER(lpid));
+               }
+       }
+}
+
+int _app_group_can_start_app(const char *appid, bundle *b, bool *can_attach,
+               int *lpid, app_group_launch_mode *mode, uid_t uid)
+{
+       const char *val;
+       int caller_pid;
+       int caller_wid;
+
+       *can_attach = false;
+       if (__can_attach_window(b, appid, mode, uid)) {
+               *can_attach = true;
+               val = bundle_get_val(b, AUL_K_ORG_CALLER_PID);
+               if (val == NULL)
+                       val = bundle_get_val(b, AUL_K_CALLER_PID);
+
+               if (val == NULL) {
+                       _E("no caller pid");
+                       return -1;
+               }
+
+               caller_pid = atoi(val);
+               *lpid = _app_group_get_leader_pid(caller_pid);
+               if (*lpid != -1) {
+                       caller_wid = _app_group_get_window(caller_pid);
+                       if (caller_wid == 0) {
+                               _D("caller window wasn't ready");
+                               if (__can_be_leader(b))
+                                       *can_attach = false;
+                               else
+                                       *can_attach = true;
+                       }
+               } else {
+                       _E("no lpid");
+                       if (__can_be_leader(b))
+                               *can_attach = false;
+                       else
+                               return -1;
+               }
+       }
+
+       return 0;
+}
+
+void _app_group_start_app(int pid, bundle *b, int lpid, bool can_attach,
+               app_group_launch_mode mode)
+{
+       int caller_pid = __get_caller_pid(b);
+       int can_shift = 0;
+       int recycle = 0;
+       const char *str;
+
+       _D("app_group_start_app");
+
+       str = bundle_get_val(b, AUL_SVC_K_SHIFT_WINDOW);
+       if (str != NULL && strcmp(str, "true") == 0)
+               can_shift = 1;
+
+       str = bundle_get_val(b, AUL_SVC_K_RECYCLE);
+       if (str != NULL && strcmp(str, "true") == 0)
+               recycle = 1;
+
+       if (can_attach)
+               __group_add(lpid, pid, 0, mode, caller_pid, 0, recycle);
+       else
+               __group_add(pid, pid, 0, mode, caller_pid, can_shift, 0);
+       _app_group_set_hint(pid, b);
+}
+
+int _app_group_find_singleton(const char *appid, int *found_pid,
+               int *found_lpid)
+{
+       GHashTableIter iter;
+       gpointer key = NULL;
+       gpointer value = NULL;
+       app_status_h app_status;
+       const char *target;
+       GList *list;
+       app_group_context_t *ac;
+       int singleton = APP_GROUP_LAUNCH_MODE_SINGLETON;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               while (list != NULL) {
+                       ac = (app_group_context_t *)list->data;
+                       if (ac && ac->launch_mode == singleton) {
+                               app_status = _app_status_find(ac->pid);
+                               target = _app_status_get_appid(app_status);
+                               if (appid && target && !strcmp(appid, target)) {
+                                       *found_pid = ac->pid;
+                                       *found_lpid = GPOINTER_TO_INT(key);
+                                       return 0;
+                               }
+                       }
+                       list = g_list_next(list);
+               }
+       }
+
+       return -1;
+}
+
+int _app_group_can_reroute(int pid)
+{
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac && ac->pid == pid)
+                               return ac->reroute;
+
+                       i = g_list_next(i);
+               }
+       }
+
+       return 0;
+}
+
+void _app_group_lower(int pid, int *exit)
+{
+       app_group_context_t *ac;
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       GList *list;
+       GList *i;
+
+       if (_app_group_is_sub_app(pid)) {
+               if (__can_recycle(pid) && __can_reroute(pid)) {
+                       ac = __get_context(pid);
+                       if (ac) {
+                               _app_group_reroute(pid);
+
+                               if (ac->wid != 0)
+                                       __detach_window(ac->wid);
+
+                               ac = __context_dup(ac);
+                               __group_remove(pid);
+                               if (ac)
+                                       __do_recycle(ac);
+                       }
+                       *exit = 0;
+               } else
+                       *exit = 1;
+               return;
+       }
+
+       *exit = 0;
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+
+                       if (ac && ac->pid == pid) {
+                               if (ac->can_shift) {
+                                       __detach_window(ac->wid);
+                                       ac->can_shift = 0;
+                                       __lower_window(ac->wid);
+                               }
+                               return;
+                       }
+                       i = g_list_next(i);
+               }
+       }
+}
+
+static void __restart_app(app_group_context_t *ac, int pid, bundle *b)
+{
+       const char *pid_str;
+       int cwid;
+
+       ac->caller_pid = __get_caller_pid(b);
+
+       if (ac->can_shift) {
+               if (ac->wid != 0)
+                       __detach_window(ac->wid);
+               ac->can_shift = 0;
+       }
+
+       pid_str = bundle_get_val(b, AUL_SVC_K_SHIFT_WINDOW);
+       if (pid_str && !strcmp(pid_str, "true")) {
+               ac->can_shift = 1;
+               if (ac->wid != 0) {
+                       if (ac->caller_pid > 0) {
+                               cwid = _app_group_get_window(ac->caller_pid);
+                               if (cwid != 0)
+                                       __attach_window(cwid, ac->wid);
+                               else
+                                       _E("invalid caller wid");
+                       } else {
+                               _E("invalid caller pid");
+                       }
+               }
+       }
+}
+
+void _app_group_restart_app(int pid, bundle *b)
+{
+       GList *list;
+       GList *i;
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       app_group_context_t *ac;
+
+       if (b == NULL)
+               return;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac && ac->pid == pid) {
+                               __restart_app(ac, pid, b);
+                               return;
+                       }
+                       i = g_list_next(i);
+               }
+       }
+}
+
+int _app_group_find_pid_from_recycle_bin(const char *appid)
+{
+       app_group_context_t *ac;
+       app_status_h app_status;
+       const char *appid_from_bin;
+       GList *iter = recycle_bin;
+
+       while (iter) {
+               ac = (app_group_context_t *)iter->data;
+               app_status = _app_status_find(ac->pid);
+               appid_from_bin = _app_status_get_appid(app_status);
+               if (appid && appid_from_bin && !strcmp(appid, appid_from_bin))
+                       return ac->pid;
+
+               iter = g_list_next(iter);
+       }
+
+       return -1;
+}
+
+void _app_group_get_idle_pids(int *cnt, int **pids)
+{
+       GList *iter = recycle_bin;
+       int idle_cnt = g_list_length(iter);
+       int *idle_pids;
+       int i = 0;
+       app_group_context_t *ac;
+
+       if (idle_cnt <= 0) {
+               *cnt = 0;
+               *pids = NULL;
+               return;
+       }
+
+       idle_pids = (int *)malloc(sizeof(int) * idle_cnt);
+       if (idle_pids == NULL) {
+               _E("Out-of-memory");
+               *cnt = 0;
+               *pids = NULL;
+               return;
+       }
+
+       while (iter) {
+               ac = (app_group_context_t *)iter->data;
+               idle_pids[i] = ac->pid;
+               iter = g_list_next(iter);
+               i++;
+       }
+
+       *cnt = idle_cnt;
+       *pids = idle_pids;
+}
+
+int _app_group_get_next_caller_pid(int pid)
+{
+       GList *list;
+       GList *i;
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       app_group_context_t *ac;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               list = (GList *)value;
+               i = g_list_first(list);
+               while (i != NULL) {
+                       ac = (app_group_context_t *)i->data;
+                       if (ac && ac->pid == pid) {
+                               i = g_list_next(i);
+                               if (i == NULL)
+                                       return -1;
+
+                               ac = (app_group_context_t *)i->data;
+                               return ac->caller_pid;
+                       }
+                       i = g_list_next(i);
+               }
+       }
+
+       return -1;
+}
+
+int _app_group_activate_below(int pid, const char *below_appid)
+{
+       app_group_context_t *context = __get_context(pid);
+       int wid;
+       int tpid;
+       GList *list;
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       app_status_h app_status;
+       const char *appid;
+
+       if (!context) {
+               _E("Invalid pid");
+               return -1;
+       }
+
+       if (context->wid == 0) {
+               _E("Caller wid was 0");
+               return -1;
+       }
+
+       if (!below_appid) {
+               _E("below_appid was null");
+               return -1;
+       }
+
+       wid = context->wid;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               tpid = GPOINTER_TO_INT(key);
+               app_status = _app_status_find(tpid);
+               appid = _app_status_get_appid(app_status);
+               if (appid && strcmp(appid, below_appid) == 0) {
+                       list = (GList *)value;
+                       context  = (app_group_context_t *)list->data;
+                       __activate_below(wid, context->wid);
+                       return 0;
+               }
+       }
+
+       _E("Failed to find available appid to move");
+       return -1;
+}
+
+int _app_group_activate_above(int pid, const char *above_appid)
+{
+       app_group_context_t *context = __get_context(pid);
+       int wid;
+       int tpid;
+       GList *list;
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       app_status_h app_status;
+       const char *appid;
+
+       if (!context) {
+               _E("Invalid pid");
+               return -1;
+       }
+
+       if (context->wid == 0) {
+               _E("Caller wid was 0");
+               return -1;
+       }
+
+       if (!above_appid) {
+               _E("below_appid was null");
+               return -1;
+       }
+
+       wid = context->wid;
+
+       g_hash_table_iter_init(&iter, app_group_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               tpid = GPOINTER_TO_INT(key);
+               app_status = _app_status_find(tpid);
+               appid = _app_status_get_appid(app_status);
+               if (appid && strcmp(appid, above_appid) == 0) {
+                       list = (GList *)value;
+                       context  = (app_group_context_t *)list->data;
+                       __activate_above(wid, context->wid);
+                       return 0;
+               }
+       }
+
+       _E("Failed to find available appid to move");
+       return -1;
+}
+
+int _app_group_attach(const char *parent_appid, const char *child_appid,
+               uid_t uid)
+{
+       app_status_h status;
+       int ppid;
+       int cpid;
+       int pwid;
+       int cwid;
+
+       status = _app_status_find_by_appid(parent_appid, uid);
+       if (!status) {
+               _E("parent app is not running %s", parent_appid);
+               return -1;
+       }
+
+       ppid = _app_status_get_pid(status);
+       status = _app_status_find_by_appid(child_appid, uid);
+       if (!status) {
+               _E("child app is not running %s", child_appid);
+               return -1;
+       }
+
+       pwid = _app_group_get_window(ppid);
+       if (pwid == 0) {
+               _E("window wasn't ready - ppid(%d)", ppid);
+               return -1;
+       }
+
+       cpid = _app_status_get_pid(status);
+       cwid = _app_group_get_window(cpid);
+       if (cwid == 0) {
+               _E("window wasn't ready - cpid(%d)", cpid);
+               return -1;
+       }
+
+       __attach_window(pwid, cwid);
+
+       return 0;
+}
+
+int _app_group_detach(const char *child_appid, uid_t uid)
+{
+       app_status_h status;
+       int cpid;
+       int cwid;
+
+       status = _app_status_find_by_appid(child_appid, uid);
+       if (!status) {
+               _E("child app is not running %s", child_appid);
+               return -1;
+       }
+
+       cpid = _app_status_get_pid(status);
+       cwid = _app_group_get_window(cpid);
+       if (cwid == 0) {
+               _E("window wasn't ready : %d", cwid);
+               return -1;
+       }
+
+       __detach_window(cwid);
+
+       return 0;
+}
+
+int _app_group_init(void)
+{
+       _D("app group init");
+       _wayland_add_registry_listener(&registry_listener, NULL);
+       app_group_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                       NULL, NULL);
+       if (app_group_hash == NULL) {
+               _E("Failed to create app group hash");
+               return -1;
+       }
+
+       return 0;
+}
+
+void _app_group_fini(void)
+{
+       _D("app group fini");
+       /* TODO: Destroy app group info */
+}
+
diff --git a/src/amd_app_property.c b/src/amd_app_property.c
new file mode 100644 (file)
index 0000000..ec00f0c
--- /dev/null
@@ -0,0 +1,741 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <ctype.h>
+#include <gio/gio.h>
+#include <aul_svc.h>
+#include <pkgmgr-info.h>
+
+#include "amd_util.h"
+#include "amd_app_property.h"
+
+struct metadata_filter {
+       const char *key;
+       const char *value; /* Could be NULL */
+};
+
+struct metadata_entity {
+       char *appid;
+       char *key;
+       char *value;
+};
+
+struct app_property_s {
+       uid_t uid;
+       GHashTable *alias_info_table;
+       GHashTable *allowed_info_table;
+       GHashTable *appid_cache_table;
+       GList *metadata_list;
+};
+
+static GHashTable *user_prop_table;
+
+static int __foreach_allowed_info(const char *appid, const char *allowed_appid,
+               void *data);
+
+static int __add_alias_info(const char *alias_appid,
+               const char *appid, void *user_data)
+{
+       GHashTable *alias_info_table = (GHashTable *)user_data;
+       char *key;
+       char *value;
+       char *id;
+
+       if (alias_appid == NULL || appid == NULL || alias_info_table == NULL) {
+               _W("Invalid parameter");
+               return -1;
+       }
+
+       key = strdup(alias_appid);
+       if (key == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       value = strdup(appid);
+       if (value == NULL) {
+               _E("out of memory");
+               free(key);
+               return -1;
+       }
+
+       id = g_hash_table_lookup(alias_info_table, key);
+       if (id) {
+               _D("Replace alias info - alias_appid(%s), appid(%d)",
+                               key, value);
+               g_hash_table_replace(alias_info_table, key, value);
+       } else {
+               g_hash_table_insert(alias_info_table, key, value);
+       }
+
+       return 0;
+}
+
+int _app_property_add_alias_info(app_property_h app_property,
+               const char *alias_appid, const char *appid)
+{
+       int ret;
+
+       if (app_property == NULL || appid == NULL) {
+               _W("Invalid parameter");
+               return -1;
+       }
+
+       if (alias_appid && appid) {
+               ret = __add_alias_info(alias_appid, appid,
+                               app_property->alias_info_table);
+               if (ret < 0) {
+                       _W("Failed to add alias info");
+                       return -1;
+               }
+       } else if (appid) {
+               ret = aul_svc_foreach_alias_info_by_appid_for_uid(
+                               __add_alias_info, appid,
+                               app_property->uid,
+                               app_property->alias_info_table);
+               if (ret < 0) {
+                       _W("Failed to retrive alias info - appid(%s)", appid);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static gboolean __remove_alias_info(gpointer key, gpointer value,
+               gpointer user_data)
+{
+       if (value == NULL || user_data == NULL) {
+               _W("Invalid parameter");
+               return FALSE;
+       }
+
+       if (strcmp(value, user_data) == 0)
+               return TRUE;
+
+       return FALSE;
+}
+
+int _app_property_remove_alias_info(app_property_h app_property,
+               const char *alias_appid, const char *appid)
+{
+       const char *id;
+
+       if (app_property == NULL || (alias_appid == NULL && appid == NULL)) {
+               _W("Invalid parameter");
+               return -1;
+       }
+
+       if (alias_appid) {
+               id = g_hash_table_lookup(app_property->alias_info_table,
+                               alias_appid);
+               if (id) {
+                       g_hash_table_remove(app_property->alias_info_table,
+                                       alias_appid);
+               }
+       } else {
+               g_hash_table_foreach_remove(app_property->alias_info_table,
+                               __remove_alias_info, (gpointer)appid);
+       }
+
+       return 0;
+}
+
+const char *_app_property_get_real_appid(app_property_h app_property,
+               const char *alias_appid)
+{
+       if (app_property == NULL || alias_appid == NULL) {
+               _W("Invalid parameter");
+               return NULL;
+       }
+
+       return g_hash_table_lookup(app_property->alias_info_table, alias_appid);
+}
+
+GList *_app_property_get_allowed_app_list(app_property_h app_property,
+               const char *appid)
+{
+       if (app_property == NULL || appid == NULL) {
+               _W("Invalid parameter");
+               return NULL;
+       }
+
+       return g_hash_table_lookup(app_property->allowed_info_table, appid);
+}
+
+app_property_h _app_property_find(uid_t uid)
+{
+       if (user_prop_table == NULL)
+               return NULL;
+
+       return g_hash_table_lookup(user_prop_table, GUINT_TO_POINTER(uid));
+}
+
+int _app_property_insert(uid_t uid, const char *appid)
+{
+       int ret;
+       app_property_h app_property;
+
+       if (appid == NULL) {
+               _W("Invalid parameter");
+               return -1;
+       }
+
+       app_property = _app_property_find(uid);
+       if (app_property == NULL)
+               return -1;
+
+       ret = aul_svc_foreach_alias_info_by_appid_for_uid(__add_alias_info,
+                       appid, app_property->uid,
+                       app_property->alias_info_table);
+       if (ret < 0) {
+               _E("Failed to retrive alias info uid(%d) - ret(%d)",
+                               app_property->uid, ret);
+               return -1;
+       }
+
+       ret = aul_svc_foreach_allowed_info_by_appid_for_uid(
+                       __foreach_allowed_info, appid,
+                       app_property->uid, app_property->allowed_info_table);
+       if (ret < 0) {
+               _E("Failed to retrive allowed info uid(%d) - ret (%d)",
+                               app_property->uid, ret);
+               return -1;
+       }
+
+       _D("uid(%d), appid(%s)", uid, appid);
+
+       return 0;
+}
+
+int _app_property_delete(uid_t uid, const char *appid)
+{
+       app_property_h app_property;
+
+       if (appid == NULL) {
+               _W("Invalid parameter");
+               return -1;
+       }
+
+       app_property = _app_property_find(uid);
+       if (app_property == NULL)
+               return -1;
+
+       g_hash_table_foreach_remove(app_property->alias_info_table,
+                       __remove_alias_info, (gpointer)appid);
+
+       g_hash_table_remove(app_property->allowed_info_table, appid);
+       _D("uid(%d), appid(%d)", uid, appid);
+
+       return 0;
+}
+
+static void __foreach_alias_info(const char *alias_appid, const char *appid,
+               void *data)
+{
+       GHashTable *alias_info_table = (GHashTable *)data;
+       char *key;
+       char *value;
+
+       if (alias_appid == NULL || appid == NULL || alias_info_table == NULL) {
+               _W("Invalid parameter");
+               return;
+       }
+
+       key = strdup(alias_appid);
+       if (key == NULL) {
+               _E("out of memory");
+               return;
+       }
+
+       value = strdup(appid);
+       if (value == NULL) {
+               _E("out of memory");
+               free(key);
+               return;
+       }
+
+       g_hash_table_insert(alias_info_table, key, value);
+}
+
+static int __foreach_allowed_info(const char *appid, const char *allowed_appid,
+               void *data)
+{
+       GHashTable *allowed_info_table = (GHashTable *)data;
+       char *key;
+       char *value;
+       GList *list;
+
+       if (appid == NULL || allowed_appid == NULL ||
+                       allowed_info_table == NULL) {
+               _W("Invalid parameter");
+               return -1;
+       }
+
+       value = strdup(allowed_appid);
+       if (value == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       list = g_hash_table_lookup(allowed_info_table, appid);
+       if (list) {
+               list = g_list_append(list, value);
+       } else {
+               key = strdup(appid);
+               if (key == NULL) {
+                       _E("out of memory");
+                       free(value);
+                       return -1;
+               }
+
+               list = g_list_append(list, value);
+               g_hash_table_insert(allowed_info_table, key, list);
+       }
+
+       return 0;
+}
+
+static void __destroy_allowed_info_list(gpointer data)
+{
+       GList *list = (GList *)data;
+
+       if (list == NULL)
+               return;
+
+       g_list_free_full(list, free);
+}
+
+static struct app_property_s *__create_app_property(uid_t uid)
+{
+       struct app_property_s *prop;
+
+       prop = calloc(1, sizeof(struct app_property_s));
+       if (prop == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       prop->uid = uid;
+       prop->alias_info_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                       free, free);
+       if (prop->alias_info_table == NULL) {
+               _E("Failed to create alias info table");
+               free(prop);
+               return NULL;
+       }
+
+       prop->allowed_info_table = g_hash_table_new_full(g_str_hash,
+                       g_str_equal, free, __destroy_allowed_info_list);
+       if (prop->allowed_info_table == NULL) {
+               _E("Failed to create allowed info table");
+               g_hash_table_destroy(prop->alias_info_table);
+               free(prop);
+               return NULL;
+       }
+
+       prop->appid_cache_table = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
+       if (prop->appid_cache_table == NULL) {
+               _E("Failed to create appid cache table");
+               g_hash_table_destroy(prop->allowed_info_table);
+               g_hash_table_destroy(prop->alias_info_table);
+               free(prop);
+               return NULL;
+       }
+
+       prop->metadata_list = NULL;
+
+       return prop;
+}
+
+static void __free_metadata_entity(gpointer data)
+{
+       struct metadata_entity *entity = data;
+
+       if (!entity)
+               return;
+
+       free(entity->appid);
+       free(entity->key);
+       free(entity->value);
+       free(entity);
+}
+
+static void __destroy_app_property(gpointer data)
+{
+       struct app_property_s *prop = (struct app_property_s *)data;
+
+       if (prop == NULL)
+               return;
+
+       if (prop->allowed_info_table)
+               g_hash_table_destroy(prop->allowed_info_table);
+       if (prop->alias_info_table)
+               g_hash_table_destroy(prop->alias_info_table);
+       if (prop->appid_cache_table)
+               g_hash_table_destroy(prop->appid_cache_table);
+       if (prop->metadata_list)
+               g_list_free_full(prop->metadata_list, __free_metadata_entity);
+
+       free(prop);
+}
+
+static gint __comp_metadata_list(gconstpointer a, gconstpointer b)
+{
+       const struct metadata_entity *entity1 = a;
+       const struct metadata_entity *entity2 = b;
+
+       if (!a || !b)
+               return -1;
+
+       if (!strcmp(entity1->appid, entity2->appid) &&
+                       !strcmp(entity1->key, entity2->key) &&
+                       !strcmp(entity1->value, entity2->value))
+               return 0;
+
+       return -1;
+}
+
+static void __add_metadata_info(const char *appid, const char *key,
+               const char *val, struct app_property_s *prop)
+{
+       struct metadata_entity *entity;
+
+       if (appid == NULL || key == NULL) {
+               _W("Invalid parameter");
+               return;
+       }
+
+       entity = calloc(1, sizeof(struct metadata_entity));
+       if (entity == NULL) {
+               _E("out of memory");
+               return;
+       }
+
+       entity->appid = strdup(appid);
+       if (!entity->appid) {
+               _E("out of memory");
+               goto err;
+       }
+
+       entity->key = strdup(key);
+       if (!entity->key) {
+               _E("out of memory");
+               goto err;
+       }
+
+       if (val) {
+               entity->value = strdup(val);
+               if (!entity->value) {
+                       _E("out of memory");
+                       goto err;
+               }
+       }
+
+       if (g_list_find_custom(prop->metadata_list, entity, __comp_metadata_list))
+               goto err;
+
+       prop->metadata_list = g_list_append(prop->metadata_list, entity);
+       return;
+
+err:
+       free(entity->appid);
+       free(entity->key);
+       free(entity->value);
+       free(entity);
+}
+
+static struct metadata_filter __metadata_table[] = {
+       { METADATA_LARGEMEMORY, NULL },
+       { METADATA_OOMTERMINATION, NULL },
+};
+
+static int __app_list_cb(pkgmgrinfo_appinfo_h handle, void *user_data)
+{
+       char *appid = NULL;
+       struct app_property_s *prop = user_data;
+       char *val;
+       int ret;
+       int i;
+       const int n = ARRAY_SIZE(__metadata_table);
+
+       pkgmgrinfo_appinfo_get_appid(handle, &appid);
+
+       if (!appid)
+               return -1;
+
+       for (i = 0; i < n; i++) {
+               val = NULL;
+               ret = pkgmgrinfo_appinfo_get_metadata_value(handle,
+                               __metadata_table[i].key, &val);
+               if (ret == PMINFO_R_OK) {
+                       __add_metadata_info(appid,
+                                       __metadata_table[i].key,
+                                       val, prop);
+               }
+       }
+
+       return 0;
+}
+
+static int __load_metadata(struct app_property_s *prop)
+{
+       int ret;
+       pkgmgrinfo_appinfo_metadata_filter_h handle;
+       int i;
+       const int n = ARRAY_SIZE(__metadata_table);
+
+       ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
+       if (ret != PMINFO_R_OK)
+               return -1;
+
+       for (i = 0; i < n; i++) {
+               ret = pkgmgrinfo_appinfo_metadata_filter_add(handle,
+                               __metadata_table[i].key,
+                               __metadata_table[i].value);
+               if (ret != PMINFO_R_OK) {
+                       pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+                       return -1;
+               }
+       }
+
+       ret = pkgmgrinfo_appinfo_usr_metadata_filter_foreach(handle,
+                       __app_list_cb, prop, prop->uid);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+               return -1;
+       }
+
+       ret = pkgmgrinfo_appinfo_usr_metadata_filter_foreach(handle,
+                       __app_list_cb, prop, GLOBAL_USER);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+               return -1;
+       }
+
+       pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+
+       return 0;
+}
+
+static int __load_app_property(struct app_property_s *prop)
+{
+       int ret;
+
+       if (prop == NULL) {
+               _W("Invalid parameter");
+               return -1;
+       }
+
+       ret = aul_svc_foreach_alias_info_for_uid(__foreach_alias_info,
+                       prop->uid, prop->alias_info_table);
+       if (ret < 0) {
+               _E("Failed to retrive alias info uid(%d) - ret(%d)",
+                               prop->uid, ret);
+               return -1;
+       }
+
+       ret = aul_svc_foreach_allowed_info_for_uid(__foreach_allowed_info,
+                       prop->uid, prop->allowed_info_table);
+       if (ret < 0) {
+               _E("Failed to retrive allowed info uid(%d) - ret(%d)",
+                               prop->uid, ret);
+               return -1;
+       }
+
+       ret = __load_metadata(prop);
+       if (ret < 0) {
+               _E("Failed to retrive metadata info uid(%d) - ret(%d)",
+                               prop->uid, ret);
+               return -1;
+       }
+
+       return 0;
+}
+
+int _app_property_load(uid_t uid)
+{
+       int ret;
+       struct app_property_s *prop;
+
+       prop = __create_app_property(uid);
+       if (prop == NULL)
+               return -1;
+
+       ret = __load_app_property(prop);
+       if (ret < 0) {
+               _E("Failed to load properties - ret(%d)", ret);
+               __destroy_app_property(prop);
+               return -1;
+       }
+
+       g_hash_table_insert(user_prop_table, GUINT_TO_POINTER(uid), prop);
+
+       return 0;
+}
+
+void _app_property_unload(uid_t uid)
+{
+       g_hash_table_remove(user_prop_table, GUINT_TO_POINTER(uid));
+}
+
+int _app_property_init(void)
+{
+       _D("app property init");
+
+       user_prop_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                       NULL, __destroy_app_property);
+       if (user_prop_table == NULL) {
+               _E("Failed to create user prop table");
+               return -1;
+       }
+
+       return 0;
+}
+
+void _app_property_fini(void)
+{
+       _D("app property fini");
+
+       if (user_prop_table)
+               g_hash_table_destroy(user_prop_table);
+}
+
+void _app_property_cache_put(app_property_h app_property, const char *checksum, const char *appid)
+{
+       if (!app_property || !checksum || !appid)
+               return;
+
+       g_hash_table_replace(app_property->appid_cache_table, strdup(checksum), strdup(appid));
+}
+
+const char *_app_property_cache_get(app_property_h app_property, const char *checksum)
+{
+       const char *appid;
+
+       if (!app_property || !checksum)
+               return NULL;
+
+       appid = g_hash_table_lookup(app_property->appid_cache_table, checksum);
+
+       return appid;
+}
+
+void _app_property_cache_invalidate(app_property_h app_property)
+{
+       if (app_property)
+               g_hash_table_remove_all(app_property->appid_cache_table);
+}
+
+bool _app_property_metadata_query_bool(app_property_h app_property,
+               const char *appid, const char *key)
+{
+       return _app_property_metadata_match(app_property, appid, key, "true");
+}
+
+int _app_property_metadata_foreach(app_property_h app_property,
+               const char *appid, const char *key,
+               int (*callback)(const char *value, void *data),
+               void *user_data)
+{
+       struct metadata_entity *ret;
+       GList *i;
+
+       if (!app_property || !appid || !key)
+               return -1;
+
+       i = app_property->metadata_list;
+       while (i) {
+               ret = i->data;
+
+               if (!strcmp(ret->appid, appid) &&
+                       strcmp(ret->key, key)) {
+                       if (callback(ret->value, user_data) < 0)
+                               break;
+               }
+
+               i = g_list_next(i);
+       }
+
+       return 0;
+}
+
+bool _app_property_metadata_match(app_property_h app_property,
+               const char *appid, const char *key, const char *value)
+{
+       struct metadata_entity entity;
+       GList *i;
+
+       if (!app_property || !appid || !key || !value)
+               return false;
+
+       entity.appid = (char *)appid;
+       entity.key = (char *)key;
+       entity.value = (char *)value;
+       i = g_list_find_custom(app_property->metadata_list,
+                       &entity, __comp_metadata_list);
+       if (!i)
+               return false;
+
+       return true;
+}
+
+static gint __comp_key(gconstpointer a, gconstpointer b)
+{
+       const struct metadata_entity *entity1 = a;
+       const struct metadata_entity *entity2 = b;
+
+       if (!a || !b)
+               return -1;
+
+       if (!strcmp(entity1->appid, entity2->appid) &&
+                       !strcmp(entity1->key, entity2->key)) {
+               if (entity1->value && !strcmp(entity1->value, "false"))
+                       return -1;
+
+               return 0;
+       }
+
+       return -1;
+}
+
+bool _app_property_metadata_query_activation(app_property_h app_property,
+               const char *appid, const char *key)
+{
+       struct metadata_entity entity;
+       GList *i;
+
+       if (!app_property || !appid || !key)
+               return false;
+
+       entity.appid = (char *)appid;
+       entity.key = (char *)key;
+       entity.value = NULL;
+       i = g_list_find_custom(app_property->metadata_list,
+                       &entity, __comp_key);
+
+       if (!i)
+               return false;
+
+       return true;
+}
+
+
diff --git a/src/amd_app_status.c b/src/amd_app_status.c
new file mode 100644 (file)
index 0000000..22ce370
--- /dev/null
@@ -0,0 +1,1840 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <glib.h>
+#include <aul.h>
+#include <string.h>
+#include <linux/limits.h>
+#include <vconf.h>
+#include <time.h>
+#include <aul_sock.h>
+#include <aul_proc.h>
+#include <ctype.h>
+#include <gio/gio.h>
+#include <bundle_internal.h>
+
+#include "amd_app_status.h"
+#include "amd_appinfo.h"
+#include "amd_request.h"
+#include "amd_launch.h"
+#include "amd_util.h"
+#include "amd_app_group.h"
+#include "amd_input.h"
+#include "amd_suspend.h"
+#include "amd_socket.h"
+#include "amd_share.h"
+#include "amd_extractor.h"
+#include "amd_app_com.h"
+#include "amd_widget.h"
+#include "amd_screen_connector.h"
+#include "amd_cooldown.h"
+#include "amd_inotify.h"
+
+struct pkg_status_s {
+       char *pkgid;
+       int status;
+       GSList *ui_list;
+       GSList *svc_list;
+};
+
+struct app_status_s {
+       char *appid;
+       char *app_path;
+       char *pkgid;
+       char *instance_id;
+       int app_type;
+       int pid;
+       uid_t uid;
+       int status;
+       bool is_subapp;
+       int leader_pid;
+       int timestamp;
+       int fg_count;
+       bool managed;
+       int org_caller_pid;
+       int last_caller_pid;
+       struct pkg_status_s *pkg_status;
+       GList *shared_info_list;
+       bool bg_launch;
+       bool socket_exists;
+       bool starting;
+       bool is_exit_notified;
+       bool debug_mode;
+       guint timer;
+};
+
+struct fault_app_s {
+       int pid;
+       int uid;
+       char *appid;
+       char *pkgid;
+       int type;
+};
+
+static GHashTable *oom_app_table;
+static GHashTable *pkg_update_app_table;
+static GSList *app_status_list;
+static GHashTable *pkg_status_table;
+static int limit_bg_uiapps;
+static char *home_appid;
+static GHashTable *__wd_table;
+
+int _app_status_set_is_exit_notified(app_status_h app_status, bool is_exit_notified)
+{
+       if (app_status == NULL)
+               return -1;
+
+       app_status->is_exit_notified = is_exit_notified;
+
+       return 0;
+}
+
+bool _app_status_get_is_exit_notified(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return false;
+
+       return app_status->is_exit_notified;
+}
+
+static void __send_fault_dead_signal(int pid, int uid, const char *appid,
+               int type, bool is_exit_notified)
+{
+       char *endpoint = NULL;
+       char sender_pid_str[MAX_PID_STR_BUFSZ];
+       bundle *kb;
+
+       if (type == AT_WATCH_APP)
+               endpoint = "watch.dead";
+
+       if (endpoint == NULL)
+               return;
+
+       kb = bundle_create();
+       if (!kb) {
+               _E("cannot create bundle out of memory");
+               return;
+       }
+
+       _D("send pid %d uid %d appid %s type %d is_exit_notified %d",
+                       pid, uid, appid, type, is_exit_notified);
+
+       snprintf(sender_pid_str, MAX_PID_STR_BUFSZ, "%d", pid);
+       bundle_add(kb, AUL_K_APPID, appid);
+       bundle_add(kb, AUL_K_PID, sender_pid_str);
+       bundle_add(kb, AUL_K_IS_FAULT, (is_exit_notified == true) ? "false" : "true");
+
+       _app_com_send(endpoint, getpgid(pid), kb, uid);
+}
+
+void _app_status_fault_recovery(int pid, int uid, const char *pkgid,
+       const char *appid, int type, bool is_exit_notified)
+{
+       struct fault_app_s *app_info;
+
+       if (_util_check_oom()) {
+               app_info =
+                       g_hash_table_lookup(
+                                       oom_app_table,
+                                       appid);
+               if (app_info == NULL) {
+                       app_info = (struct fault_app_s *)
+                                       calloc(1, sizeof(struct fault_app_s));
+                       app_info->appid = strdup(appid);
+                       app_info->pkgid = strdup(pkgid);
+                       app_info->pid = pid;
+                       app_info->uid = uid;
+                       app_info->type = type;
+                       g_hash_table_insert(
+                                       oom_app_table,
+                                       app_info->appid,
+                                       app_info);
+               }
+       } else if (_appinfo_is_pkg_updating(pkgid)) {
+               app_info =
+                       g_hash_table_lookup(
+                                       pkg_update_app_table,
+                                       appid);
+               if (app_info == NULL) {
+                       app_info = (struct fault_app_s *)
+                                       calloc(1, sizeof(struct fault_app_s));
+                       app_info->appid = strdup(appid);
+                       app_info->pkgid = strdup(pkgid);
+                       app_info->pid = pid;
+                       app_info->uid = uid;
+                       app_info->type = type;
+                       g_hash_table_insert(
+                                       pkg_update_app_table,
+                                       app_info->pkgid,
+                                       app_info);
+               }
+       } else {
+               __send_fault_dead_signal(pid, uid, appid, type, is_exit_notified);
+       }
+}
+
+static void __destroy_fault_app_info(gpointer data)
+{
+       struct fault_app_s *info =
+                       (struct fault_app_s *)data;
+
+       if (info == NULL)
+               return;
+       if (info->appid)
+               free(info->appid);
+       if (info->pkgid)
+               free(info->pkgid);
+
+       free(info);
+}
+
+void _app_status_send_fault_dead_for_oom_apps(void)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+       struct fault_app_s *info;
+
+       g_hash_table_iter_init(&iter, oom_app_table);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               info = (struct fault_app_s *)value;
+               __send_fault_dead_signal(info->pid, info->uid, info->appid,
+                               info->type, false);
+       }
+       g_hash_table_remove_all(oom_app_table);
+
+}
+
+void _app_status_send_fault_dead_for_update_app(const char *pkgid)
+{
+       struct fault_app_s *info;
+
+       info = g_hash_table_lookup(pkg_update_app_table, pkgid);
+       if (info != NULL) {
+               __send_fault_dead_signal(info->pid, info->uid, info->appid,
+                               info->type, false);
+               g_hash_table_remove(pkg_update_app_table, pkgid);
+       }
+}
+
+static int __get_managed_uiapp_cnt(void)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+       int cnt = 0;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->managed &&
+                               app_status->app_type == AT_UI_APP)
+                       cnt++;
+       }
+
+       return cnt;
+}
+
+static void __cleanup_bg_uiapps(int n)
+{
+       GSList *iter;
+       GSList *iter_next;
+       struct app_status_s *app_status;
+       int i = 0;
+       int ret;
+
+       GSLIST_FOREACH_SAFE(app_status_list, iter, iter_next) {
+               if (i == n)
+                       break;
+
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->status != STATUS_VISIBLE) {
+                       ret = _terminate_app_local(app_status->uid,
+                                       app_status->pid);
+                       if (ret < 0) {
+                               _E("Failed to terminate app(%d)",
+                                               app_status->pid);
+                               continue;
+                       }
+                       i++;
+               }
+       }
+}
+
+static gint __compare_app_status_for_sorting(gconstpointer p1, gconstpointer p2)
+{
+       struct app_status_s *app_status1 = (struct app_status_s *)p1;
+       struct app_status_s *app_status2 = (struct app_status_s *)p2;
+       int app_group_cnt1;
+       int app_group_cnt2;
+       int *app_group_pids1;
+       int *app_group_pids2;
+
+       if (app_status1->app_type != AT_UI_APP ||
+                       app_status2->app_type != AT_UI_APP)
+               return 0;
+
+       if (app_status1->timestamp > app_status2->timestamp)
+               return 1;
+       else if (app_status1->timestamp < app_status2->timestamp)
+               return -1;
+
+       _app_group_get_group_pids(app_status1->leader_pid, &app_group_cnt1,
+                       &app_group_pids1);
+       _app_group_get_group_pids(app_status2->leader_pid, &app_group_cnt2,
+                       &app_group_pids2);
+       free(app_group_pids1);
+       free(app_group_pids2);
+
+       if (app_group_cnt1 < app_group_cnt2)
+               return 1;
+       else if (app_group_cnt1 > app_group_cnt2)
+               return -1;
+
+       if (app_status1->fg_count > app_status2->fg_count)
+               return 1;
+       else if (app_status1->fg_count < app_status2->fg_count)
+               return -1;
+
+       return 0;
+}
+
+static void __check_running_uiapp_list(void)
+{
+       int len;
+       int n;
+
+       len = __get_managed_uiapp_cnt();
+       if (len <= 0)
+               return;
+
+       n = len - limit_bg_uiapps;
+       if (n <= 0)
+               return;
+
+       app_status_list = g_slist_sort(app_status_list,
+                       (GCompareFunc)__compare_app_status_for_sorting);
+       __cleanup_bg_uiapps(n);
+}
+
+static void __vconf_cb(keynode_t *key, void *data)
+{
+       const char *name;
+
+       name = vconf_keynode_get_name(key);
+       if (name && strcmp(name, VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS) == 0) {
+               limit_bg_uiapps = vconf_keynode_get_int(key);
+               if (limit_bg_uiapps > 0)
+                       __check_running_uiapp_list();
+       }
+}
+
+static void __update_leader_app_status(int leader_pid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+
+       if (leader_pid <= 0)
+               return;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->pid == leader_pid) {
+                       app_status->timestamp = time(NULL) / 10;
+                       app_status->fg_count++;
+                       break;
+               }
+       }
+}
+
+static void __remove_all_shared_info(struct app_status_s *app_status)
+{
+       GList *list;
+       shared_info_t *shared_info;
+
+       if (!app_status || !app_status->shared_info_list)
+               return;
+
+       list = app_status->shared_info_list;
+       while (list) {
+               shared_info = (shared_info_t *)list->data;
+               if (shared_info) {
+                       if (shared_info->owner_appid)
+                               free(shared_info->owner_appid);
+                       free(shared_info);
+               }
+               list = g_list_next(list);
+       }
+
+       g_list_free(app_status->shared_info_list);
+       app_status->shared_info_list = NULL;
+}
+
+static void __add_pkg_status(struct app_status_s *app_status)
+{
+       struct pkg_status_s *pkg_status;
+
+       if (app_status == NULL) {
+               _E("Invalid parameter");
+               return;
+       }
+
+       if (app_status->app_type != AT_SERVICE_APP &&
+                       app_status->app_type != AT_UI_APP)
+               return;
+
+       if (pkg_status_table == NULL) {
+               pkg_status_table = g_hash_table_new(g_str_hash, g_str_equal);
+               if (pkg_status_table == NULL) {
+                       _E("out of memory");
+                       return;
+               }
+       }
+
+       pkg_status = g_hash_table_lookup(pkg_status_table, app_status->pkgid);
+       if (pkg_status == NULL) {
+               pkg_status = (struct pkg_status_s *)calloc(1,
+                               sizeof(struct pkg_status_s));
+               if (pkg_status == NULL) {
+                       _E("out of memory");
+                       return;
+               }
+
+               pkg_status->pkgid = strdup(app_status->pkgid);
+               if (pkg_status->pkgid == NULL) {
+                       _E("out of memory");
+                       free(pkg_status);
+                       return;
+               }
+
+               g_hash_table_insert(pkg_status_table, pkg_status->pkgid,
+                               pkg_status);
+       }
+
+       pkg_status->status = app_status->status;
+       app_status->pkg_status = pkg_status;
+
+       if (app_status->app_type == AT_SERVICE_APP) {
+               pkg_status->svc_list = g_slist_append(pkg_status->svc_list,
+                               app_status);
+       } else {
+               pkg_status->ui_list = g_slist_append(pkg_status->ui_list,
+                               app_status);
+       }
+}
+
+static int __get_ui_app_status_pkg_status(struct pkg_status_s *pkg_status)
+{
+       struct app_status_s *app_status;
+       GSList *iter;
+
+       for (iter = pkg_status->ui_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status->status != STATUS_BG)
+                       return app_status->status;
+       }
+
+       return STATUS_BG;
+}
+
+static int __update_pkg_status(struct app_status_s *app_status)
+{
+       struct pkg_status_s *pkg_status;
+       int ret;
+
+       if (app_status == NULL)
+               return -1;
+
+       if (pkg_status_table == NULL)
+               return -1;
+
+       pkg_status = (struct pkg_status_s *)g_hash_table_lookup(
+                       pkg_status_table, app_status->pkgid);
+       if (pkg_status == NULL) {
+               _E("pkgid(%s) is not on list", app_status->pkgid);
+               return -1;
+       }
+
+       if (pkg_status->ui_list) {
+               ret = __get_ui_app_status_pkg_status(pkg_status);
+               if (ret > -1)
+                       pkg_status->status = ret;
+       } else {
+               pkg_status->status = STATUS_SERVICE;
+       }
+
+       return 0;
+}
+
+static void __remove_pkg_status(struct app_status_s *app_status)
+{
+       struct pkg_status_s *pkg_status;
+
+       if (app_status == NULL) {
+               _E("Invalid parameter");
+               return;
+       }
+
+       pkg_status = g_hash_table_lookup(pkg_status_table, app_status->pkgid);
+       if (pkg_status == NULL)
+               return;
+
+       if (app_status->app_type == AT_SERVICE_APP) {
+               pkg_status->svc_list = g_slist_remove(pkg_status->svc_list,
+                               app_status);
+               _D("STATUS_SERVICE: appid(%s)", app_status->appid);
+       } else {
+               pkg_status->ui_list = g_slist_remove(pkg_status->ui_list,
+                               app_status);
+               _D("~STATUS_SERVICE: appid(%s)", app_status->appid);
+       }
+
+       if (!pkg_status->svc_list && !pkg_status->ui_list) {
+               g_hash_table_remove(pkg_status_table, pkg_status->pkgid);
+               if (pkg_status->pkgid)
+                       free(pkg_status->pkgid);
+               free(pkg_status);
+       }
+}
+
+static void __destroy_app_status(struct app_status_s *app_status)
+{
+       if (app_status == NULL)
+               return;
+
+       if (app_status->app_type == AT_WIDGET_APP)
+               _widget_cleanup(app_status->pid, app_status->uid);
+
+       __remove_all_shared_info(app_status);
+
+       if (app_status->instance_id)
+               free(app_status->instance_id);
+       if (app_status->pkgid)
+               free(app_status->pkgid);
+       if (app_status->app_path)
+               free(app_status->app_path);
+       if (app_status->appid)
+               free(app_status->appid);
+       if (app_status->timer)
+               g_source_remove(app_status->timer);
+
+       free(app_status);
+}
+
+static int __get_app_type(const char *comp_type)
+{
+       if (comp_type == NULL)
+               return -1;
+
+       if (strcmp(comp_type, APP_TYPE_SERVICE) == 0)
+               return AT_SERVICE_APP;
+       else if (strcmp(comp_type, APP_TYPE_UI) == 0)
+               return AT_UI_APP;
+       else if (strcmp(comp_type, APP_TYPE_WIDGET) == 0)
+               return AT_WIDGET_APP;
+       else if (strcmp(comp_type, APP_TYPE_WATCH) == 0)
+               return AT_WATCH_APP;
+
+       return -1;
+}
+
+static int __app_status_set_app_info(struct app_status_s *app_status,
+               const struct appinfo *ai, int pid,
+               bool is_subapp, uid_t uid, int caller_pid,
+               bool bg_launch, const char *instance_id)
+{
+       const char *appid;
+       const char *app_path;
+       const char *pkgid;
+       const char *comp_type;
+       const char *taskmanage;
+       char buf[MAX_PACKAGE_STR_SIZE];
+
+       appid = _appinfo_get_value(ai, AIT_NAME);
+       if (appid == NULL)
+               return -1;
+
+       app_status->appid = strdup(appid);
+       if (app_status->appid == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       app_path = _appinfo_get_value(ai, AIT_EXEC);
+       if (app_path == NULL)
+               return -1;
+
+       app_status->app_path = strdup(app_path);
+       if (app_status->app_path == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       pkgid = _appinfo_get_value(ai, AIT_PKGID);
+       if (pkgid == NULL)
+               return -1;
+
+       app_status->pkgid = strdup(pkgid);
+       if (app_status->pkgid == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       comp_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (comp_type == NULL)
+               return -1;
+
+       app_status->app_type = __get_app_type(comp_type);
+       if (app_status->app_type == -1) {
+               _E("Unknown component type: %s", comp_type);
+               return -1;
+       }
+
+       if (app_status->app_type == AT_SERVICE_APP)
+               app_status->status = STATUS_SERVICE;
+       else
+               app_status->status = STATUS_LAUNCHING;
+
+       if (instance_id) {
+               app_status->instance_id = strdup(instance_id);
+               if (app_status->instance_id == NULL) {
+                       _E("out of memory");
+                       return -1;
+               }
+       } else {
+               snprintf(buf, sizeof(buf), "%s:%d", appid, pid);
+               app_status->instance_id = strdup(buf);
+               if (app_status->instance_id == NULL) {
+                       _E("out of memory");
+                       return -1;
+               }
+       }
+
+       app_status->pid = pid;
+       app_status->uid = uid;
+       app_status->is_subapp = is_subapp;
+       if (app_status->app_type == AT_UI_APP)
+               app_status->leader_pid = _app_group_get_leader_pid(pid);
+
+       app_status->timestamp = time(NULL) / 10;
+       app_status->org_caller_pid = caller_pid;
+       app_status->last_caller_pid = caller_pid;
+
+       taskmanage = _appinfo_get_value(ai, AIT_TASKMANAGE);
+       if (taskmanage && strcmp(taskmanage, "true") == 0 &&
+                       app_status->leader_pid > 0 &&
+                       app_status->is_subapp == false)
+               app_status->managed = true;
+
+       app_status->bg_launch = bg_launch;
+       app_status->socket_exists = false;
+       app_status->starting = false;
+       app_status->is_exit_notified = false;
+
+       return 0;
+}
+
+int _app_status_add_app_info(const struct appinfo *ai, int pid,
+               bool is_subapp, uid_t uid, int caller_pid,
+               bool bg_launch, const char *instance_id,
+               bool debug_mode)
+{
+       GSList *iter;
+       GSList *iter_next;
+       struct app_status_s *app_status;
+       int r;
+
+       if (ai == NULL)
+               return -1;
+
+       GSLIST_FOREACH_SAFE(app_status_list, iter, iter_next) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->pid == pid) {
+                       if (app_status->uid == uid)
+                               return 0;
+
+                       app_status_list = g_slist_remove(app_status_list,
+                                       app_status);
+                       __remove_pkg_status(app_status);
+                       __destroy_app_status(app_status);
+                       break;
+               }
+       }
+
+       app_status = (struct app_status_s *)calloc(1,
+                       sizeof(struct app_status_s));
+       if (app_status == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       r = __app_status_set_app_info(app_status, ai, pid, is_subapp, uid,
+                       caller_pid, bg_launch, instance_id);
+       if (r < 0) {
+               __destroy_app_status(app_status);
+               return -1;
+       }
+
+       app_status_list = g_slist_append(app_status_list, app_status);
+       __add_pkg_status(app_status);
+
+       return 0;
+}
+
+int _app_status_remove_all_app_info_with_uid(uid_t uid)
+{
+       GSList *iter;
+       GSList *iter_next;
+       struct app_status_s *app_status;
+
+       GSLIST_FOREACH_SAFE(app_status_list, iter, iter_next) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->uid == uid) {
+                       app_status_list = g_slist_remove(app_status_list,
+                                       app_status);
+                       __destroy_app_status(app_status);
+               }
+       }
+
+       return 0;
+}
+
+int _app_status_remove(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return -1;
+
+       app_status_list = g_slist_remove(app_status_list, app_status);
+       __remove_pkg_status(app_status);
+       __destroy_app_status(app_status);
+
+       return 0;
+}
+
+static gboolean __terminate_timer_cb(gpointer data)
+{
+       int pid = GPOINTER_TO_INT(data);
+       app_status_h app_status;
+       int r;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return G_SOURCE_REMOVE;
+
+       _D("pid(%d)", pid);
+       r = kill(pid, SIGKILL);
+       if (r < 0)
+               _W("Failed to send SIGKILL, pid(%d), errno(%d)", pid, errno);
+
+       app_status->timer = 0;
+       return G_SOURCE_REMOVE;
+}
+
+int _app_status_update_status(app_status_h app_status, int status, bool force,
+               bool update_group_info)
+{
+       if (app_status == NULL || status < 0)
+               return -1;
+
+       _D("pid: %d, status: %d", app_status->pid, status);
+#ifdef TIZEN_FEATURE_BLOCK_INPUT
+       _input_unlock();
+#endif /* TIZEN_FEATURE_BLOCK_INPUT */
+
+       if (app_status->status == STATUS_DYING) {
+               _E("%s is STATUS_DYING", app_status->appid);
+               return -1;
+       }
+
+       app_status->status = status;
+       if (app_status->status == STATUS_VISIBLE) {
+               app_status->timestamp = time(NULL) / 10;
+               app_status->fg_count++;
+               if (!app_status->managed)
+                       __update_leader_app_status(app_status->leader_pid);
+               if (app_status->fg_count == 1 && limit_bg_uiapps > 0)
+                       __check_running_uiapp_list();
+       } else if (app_status->status == STATUS_DYING) {
+               _screen_connector_remove_app_screen_v2(app_status->pid,
+                               app_status->uid);
+               if (!app_status->debug_mode) {
+                       app_status->timer = g_timeout_add_seconds(5,
+                                       __terminate_timer_cb,
+                                       GINT_TO_POINTER(app_status->pid));
+               }
+               aul_send_app_terminate_request_signal(app_status->pid,
+                               NULL, NULL, NULL);
+       }
+
+       __update_pkg_status(app_status);
+       _D("pid: %d, appid: %s, pkgid: %s, status: %d",
+                       app_status->pid, app_status->appid, app_status->pkgid,
+                       app_status->status);
+
+       if (update_group_info && status != STATUS_DYING)
+               _app_group_set_status(app_status->pid, app_status->status, force);
+
+       return 0;
+}
+
+int _app_status_update_last_caller_pid(app_status_h app_status, int caller_pid)
+{
+       if (app_status == NULL)
+               return -1;
+
+       app_status->last_caller_pid = caller_pid;
+
+       return 0;
+}
+
+int _app_status_update_bg_launch(app_status_h app_status, bool bg_launch)
+{
+       if (app_status == NULL)
+               return -1;
+
+       if (!app_status->bg_launch)
+               return 0;
+
+       app_status->bg_launch = bg_launch;
+
+       return 0;
+}
+
+int _app_status_get_process_cnt(const char *appid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+       int cnt = 0;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->appid &&
+                               strcmp(app_status->appid, appid) == 0)
+                       cnt++;
+       }
+
+       return cnt;
+}
+
+bool _app_status_is_home_app(app_status_h app_status)
+{
+       const char *appid = _app_status_get_appid(app_status);
+
+       if (!appid)
+               return false;
+       if (!home_appid)
+               return false;
+
+       if (strcmp(home_appid, appid) == 0)
+               return true;
+
+       return false;
+}
+
+int _app_status_get_pid(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return -1;
+
+       return app_status->pid;
+}
+
+int _app_status_get_org_caller_pid(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return -1;
+
+       return app_status->org_caller_pid;
+}
+
+int _app_status_get_last_caller_pid(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return -1;
+
+       return app_status->last_caller_pid;
+}
+
+int _app_status_is_running(app_status_h app_status)
+{
+       if (app_status == NULL ||
+               (app_status->app_type == AT_UI_APP && app_status->is_subapp))
+               return -1;
+
+       return app_status->pid;
+}
+
+int _app_status_get_status(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return -1;
+
+       return app_status->status;
+}
+
+uid_t _app_status_get_uid(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return (uid_t)-1;
+
+       return app_status->uid;
+}
+
+const char *_app_status_get_appid(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return NULL;
+
+       return app_status->appid;
+}
+
+const char *_app_status_get_pkgid(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return NULL;
+
+       return app_status->pkgid;
+}
+
+bool _app_status_get_bg_launch(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return false;
+
+       return app_status->bg_launch;
+}
+
+const char *_app_status_get_instance_id(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return NULL;
+
+       return app_status->instance_id;
+}
+
+int _app_status_get_app_type(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return -1;
+
+       return app_status->app_type;
+}
+
+int _app_status_add_shared_info(app_status_h app_status, shared_info_t *info)
+{
+       if (app_status == NULL || info == NULL)
+               return -1;
+
+       app_status->shared_info_list = g_list_append(
+                       app_status->shared_info_list, info);
+
+       return 0;
+}
+
+int _app_status_clear_shared_info_list(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return -1;
+
+       __remove_all_shared_info(app_status);
+
+       return 0;
+}
+
+GList *_app_status_get_shared_info_list(app_status_h app_status)
+{
+       return app_status->shared_info_list;
+}
+
+bool _app_status_socket_exists(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return false;
+
+       return app_status->socket_exists;
+}
+
+bool _app_status_is_starting(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return false;
+
+       return app_status->starting;
+}
+
+int _app_status_update_is_starting(app_status_h app_status, bool is_starting)
+{
+       if (app_status == NULL)
+               return -1;
+
+       app_status->starting = is_starting;
+
+       return 0;
+}
+
+const char *_app_status_get_app_path(app_status_h app_status)
+{
+       if (app_status == NULL)
+               return NULL;
+
+       return app_status->app_path;
+}
+
+app_status_h _app_status_find(int pid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->pid == pid)
+                       return app_status;
+       }
+
+       return NULL;
+}
+
+static int __read_ppid_from_proc(const char *path, int *ppid)
+{
+       FILE *fp;
+       int ret;
+       int result = -1;
+       char *buf = NULL;
+       int val;
+
+       if (path == NULL)
+               return -1;
+
+       fp = fopen(path, "r");
+       if (fp == NULL)
+               return -1;
+
+       ret = fscanf(fp, "%ms %d\n", &buf, &val);
+       while (ret != EOF) {
+               if (ret == 2) {
+                       if (buf && strcmp(buf, "PPid:") == 0) {
+                               *ppid = val;
+                               result = 0;
+                               _D("ppid : %d", *ppid);
+                               break;
+                       }
+               }
+
+               free(buf);
+               buf = NULL;
+               ret = fscanf(fp, "%ms %d\n", &buf, &val);
+       }
+
+       fclose(fp);
+       free(buf);
+
+       return result;
+}
+
+int __proc_get_ppid_by_pid(int pid)
+{
+       char path[PATH_MAX] = { 0, };
+       int ret = 0;
+       int ppid;
+
+       snprintf(path, sizeof(path), "/proc/%d/status", pid);
+       ret = __read_ppid_from_proc(path, &ppid);
+       if (ret < 0)
+               return -1;
+
+       return ppid;
+}
+
+app_status_h _app_status_find_v2(int pid)
+{
+       int ppid;
+       int pgid;
+       struct app_status_s *app_status = NULL;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               pgid = getpgid(pid);
+               if (pgid > 0)
+                       app_status = _app_status_find(pgid);
+       }
+
+       if (app_status == NULL) {
+               ppid = __proc_get_ppid_by_pid(pid);
+               app_status = _app_status_find(ppid);
+       }
+
+       return app_status;
+}
+
+app_status_h _app_status_find_by_appid(const char *appid, uid_t uid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->appid &&
+                               strcmp(app_status->appid, appid) == 0 &&
+                               app_status->uid == uid &&
+                               app_status->is_subapp == false)
+                       return app_status;
+       }
+
+       return NULL;
+}
+
+app_status_h _app_status_find_by_appid_v2(const char *appid, uid_t uid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->appid &&
+                               strcmp(app_status->appid, appid) == 0 &&
+                               app_status->uid == uid)
+                       return app_status;
+       }
+
+       return NULL;
+}
+
+app_status_h _app_status_find_with_org_caller(const char *appid, uid_t uid,
+               int caller_pid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->appid &&
+                               strcmp(app_status->appid, appid) == 0 &&
+                               app_status->uid == uid &&
+                               app_status->org_caller_pid == caller_pid)
+                       return app_status;
+       }
+
+       return NULL;
+}
+
+app_status_h _app_status_find_by_instance_id(const char *appid,
+               const char *instance_id, uid_t uid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->instance_id &&
+                               app_status->uid == uid &&
+                               !strcmp(app_status->instance_id, instance_id) &&
+                               !strcmp(app_status->appid, appid))
+                       return app_status;
+       }
+
+       return NULL;
+}
+
+void _app_status_find_service_apps(app_status_h app_status, int status,
+               void (*send_event_to_svc_core)(int, uid_t), bool suspend)
+{
+       GSList *iter;
+       GSList *svc_list = NULL;
+       const struct appinfo *ai;
+       struct app_status_s *svc_status;
+       int bg_allowed;
+       uid_t uid;
+
+       if (app_status == NULL) {
+               _E("Invalid parameter");
+               return;
+       }
+
+       uid = _app_status_get_uid(app_status);
+       if (app_status->pkg_status && app_status->pkg_status->status == status)
+               svc_list = app_status->pkg_status->svc_list;
+
+       for (iter = svc_list; iter; iter = g_slist_next(iter)) {
+               svc_status = (struct app_status_s *)iter->data;
+               if (svc_status && svc_status->uid == uid) {
+                       ai = _appinfo_find(uid, svc_status->appid);
+                       bg_allowed = (intptr_t)_appinfo_get_value(ai,
+                                       AIT_BG_CATEGORY);
+                       if (!bg_allowed) {
+                               send_event_to_svc_core(svc_status->pid, uid);
+                               if (suspend)
+                                       _suspend_add_timer(svc_status->pid, ai);
+                               else
+                                       _suspend_remove_timer(svc_status->pid);
+                       }
+               }
+       }
+}
+
+void _app_status_check_service_only(app_status_h app_status,
+               void (*send_event_to_svc_core)(int, uid_t))
+{
+       GSList *iter;
+       GSList *ui_list = NULL;
+       struct app_status_s *ui_status;
+       int ui_cnt = 0;
+       int bg_allowed;
+       const char *appid;
+       const struct appinfo *ai;
+       uid_t uid;
+
+       if (app_status == NULL) {
+               _E("Invalid parameter");
+               return;
+       }
+
+       uid = _app_status_get_uid(app_status);
+       if (app_status->pkg_status && app_status->pkg_status->ui_list)
+               ui_list = app_status->pkg_status->ui_list;
+
+       for (iter = ui_list; iter; iter = g_slist_next(iter)) {
+               ui_status = (struct app_status_s *)iter->data;
+               if (_app_status_get_status(ui_status) != STATUS_DYING)
+                       ui_cnt++;
+       }
+
+       if (ui_cnt == 0) {
+               appid = _app_status_get_appid(app_status);
+               ai = _appinfo_find(uid, appid);
+               bg_allowed = (intptr_t)_appinfo_get_value(ai, AIT_BG_CATEGORY);
+               if (!bg_allowed) {
+                       send_event_to_svc_core(app_status->pid, uid);
+                       _suspend_add_timer(app_status->pid, ai);
+               }
+       }
+}
+
+static bundle *__create_appinfo_bundle(app_status_h app_status)
+{
+       bundle *b;
+       char tmp_str[MAX_PID_STR_BUFSZ];
+
+       b = bundle_create();
+       if (b == NULL)
+               return NULL;
+
+       snprintf(tmp_str, sizeof(tmp_str), "%d", app_status->pid);
+       bundle_add(b, AUL_K_PID, tmp_str);
+       bundle_add(b, AUL_K_APPID, app_status->appid);
+       bundle_add(b, AUL_K_EXEC, app_status->app_path);
+       bundle_add(b, AUL_K_PKGID, app_status->pkgid);
+       snprintf(tmp_str, sizeof(tmp_str), "%d", app_status->status);
+       bundle_add(b, AUL_K_STATUS, tmp_str);
+       snprintf(tmp_str, sizeof(tmp_str), "%d", app_status->is_subapp);
+       bundle_add(b, AUL_K_IS_SUBAPP, tmp_str);
+       if (app_status->instance_id)
+               bundle_add(b, AUL_K_INSTANCE_ID, app_status->instance_id);
+
+       return b;
+}
+
+static int __send_running_appinfo(app_status_h app_status, int fd)
+{
+       int ret;
+       bundle *b;
+       bundle_raw *raw = NULL;
+       int len = 0;
+
+       b = __create_appinfo_bundle(app_status);
+       if (b == NULL) {
+               _E("out of memory");
+               aul_sock_send_raw_with_fd(fd, APP_GET_INFO_ERROR,
+                               NULL, 0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       ret = bundle_encode(b, &raw, &len);
+       bundle_free(b);
+       if (ret != BUNDLE_ERROR_NONE) {
+               _E("Failed to encode bundle");
+               aul_sock_send_raw_with_fd(fd, APP_GET_INFO_ERROR, NULL,
+                               0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       ret = aul_sock_send_raw_with_fd(fd, APP_GET_INFO_OK,
+                       (unsigned char *)raw, len,
+                       AUL_SOCK_ASYNC | AUL_SOCK_BUNDLE);
+       if (ret < 0) {
+               _E("Failed to send raw data: %s", raw);
+               free(raw);
+               return ret;
+       }
+       free(raw);
+
+       return 0;
+}
+
+int _app_status_send_running_appinfo(int fd, int cmd, uid_t uid)
+{
+       GSList *list = NULL;
+       GSList *iter;
+       struct app_status_s *app_status;
+       int ret;
+       int count;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status->uid != uid ||
+                               app_status->status == STATUS_DYING)
+                       continue;
+               if (cmd != APP_ALL_RUNNING_INFO &&
+                               cmd != APP_RUNNING_INSTANCE_INFO &&
+                               (app_status->app_type == AT_UI_APP &&
+                                app_status->is_subapp))
+                       continue;
+               if (cmd == APP_RUNNING_INSTANCE_INFO &&
+                               app_status->instance_id == NULL)
+                       continue;
+
+               list = g_slist_append(list, app_status);
+       }
+
+       count = g_slist_length(list);
+       if (count == 0) {
+               _E("Applications are not running");
+               _send_result_to_client(fd, -1);
+               return -1;
+       }
+       _send_result_to_client_v2(fd, count);
+
+       for (iter = list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status == NULL)
+                       continue;
+
+               ret = __send_running_appinfo(app_status, fd);
+               if (ret < 0) {
+                       g_slist_free(list);
+                       return -1;
+               }
+       }
+       close(fd);
+       g_slist_free(list);
+
+       return 0;
+}
+
+int _app_status_foreach_running_appinfo(void (*callback)(app_status_h, void *),
+               void *data)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+
+       if (callback == NULL)
+               return -1;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status->status == STATUS_DYING ||
+                               app_status->is_subapp)
+                       continue;
+               callback(app_status, data);
+       }
+
+       return 0;
+}
+
+int _app_status_terminate_apps(const char *appid, uid_t uid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+       int ret;
+
+       if (appid == NULL)
+               return -1;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status->uid == uid &&
+                               strcmp(app_status->appid, appid) == 0 &&
+                               app_status->status != STATUS_DYING) {
+                       ret = _terminate_app_local(app_status->uid,
+                                       app_status->pid);
+                       if (ret < 0) {
+                               _E("Failed to terminate app(%d)",
+                                               app_status->pid);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int _app_status_terminate_apps_by_pkgid(const char *pkgid, uid_t uid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+       int ret;
+
+       if (pkgid == NULL)
+               return -1;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status->uid == uid &&
+                               strcmp(app_status->pkgid, pkgid) == 0 &&
+                               app_status->status != STATUS_DYING) {
+                       ret = _terminate_app_local(app_status->uid,
+                                       app_status->pid);
+                       if (ret < 0) {
+                               _E("Failed to terminate app(%d)",
+                                               app_status->pid);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int _app_status_get_appid_bypid(int fd, int pid)
+{
+       int cmd = APP_GET_INFO_ERROR;
+       int len = 0;
+       int pgid;
+       int ppid;
+       int ret;
+       char appid[MAX_PACKAGE_STR_SIZE] = {0,};
+       app_status_h app_status;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               pgid = getpgid(pid);
+               if (pgid > 0) {
+                       app_status = _app_status_find(pgid);
+                       if (app_status == NULL) {
+                               ppid = __proc_get_ppid_by_pid(pid);
+                               app_status = _app_status_find(ppid);
+                       }
+               }
+       }
+
+       if (app_status) {
+               snprintf(appid, sizeof(appid), "%s",
+                               _app_status_get_appid(app_status));
+               SECURE_LOGD("appid for %d is %s", pid, appid);
+               len = strlen(appid);
+               cmd = APP_GET_INFO_OK;
+       }
+
+       ret = aul_sock_send_raw_with_fd(fd, cmd, (unsigned char *)appid,
+                       len, AUL_SOCK_NOREPLY);
+
+       return ret;
+}
+
+int _app_status_get_pkgid_bypid(int fd, int pid)
+{
+       int cmd = APP_GET_INFO_ERROR;
+       int len = 0;
+       int pgid;
+       int ppid;
+       int ret;
+       char pkgid[MAX_PACKAGE_STR_SIZE] = {0,};
+       app_status_h app_status;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               pgid = getpgid(pid);
+               if (pgid > 0) {
+                       app_status = _app_status_find(pgid);
+                       if (app_status == NULL) {
+                               ppid = __proc_get_ppid_by_pid(pid);
+                               app_status = _app_status_find(ppid);
+                       }
+               }
+       }
+
+       if (app_status) {
+               snprintf(pkgid, sizeof(pkgid), "%s",
+                               _app_status_get_pkgid(app_status));
+               SECURE_LOGD("pkgid for %d is %s", pid, pkgid);
+               len = strlen(pkgid);
+               cmd = APP_GET_INFO_OK;
+       }
+
+       ret = aul_sock_send_raw_with_fd(fd, cmd, (unsigned char *)pkgid,
+                       len, AUL_SOCK_NOREPLY);
+
+       return ret;
+}
+
+int _app_status_get_instance_id_bypid(int fd, int pid)
+{
+       int cmd = APP_GET_INFO_ERROR;
+       int len = 0;
+       int ret;
+       const char *instance_id;
+       char buf[MAX_PACKAGE_STR_SIZE] = {0,};
+       app_status_h app_status;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               app_status = _app_status_find(getpgid(pid));
+               if (app_status == NULL) {
+                       app_status = _app_status_find(
+                                       __proc_get_ppid_by_pid(pid));
+               }
+       }
+
+       instance_id = _app_status_get_instance_id(app_status);
+       if (instance_id) {
+               snprintf(buf, sizeof(buf), "%s", instance_id);
+               SECURE_LOGD("pid(%d), instance-id(%s)", pid, instance_id);
+               len = strlen(buf);
+               cmd = APP_GET_INFO_OK;
+       }
+
+       ret = aul_sock_send_raw_with_fd(fd, cmd, (unsigned char *)buf, len,
+                       AUL_SOCK_NOREPLY);
+
+       return ret;
+}
+
+static void __home_appid_vconf_cb(keynode_t *key, void *data)
+{
+       char *tmpstr;
+
+       tmpstr = vconf_keynode_get_str(key);
+       if (tmpstr == NULL)
+               return;
+
+       if (home_appid)
+               free(home_appid);
+       home_appid = strdup(tmpstr);
+}
+
+int _app_status_publish_status(int pid, int context_status)
+{
+       bundle *b;
+       char endpoint_system[MAX_LOCAL_BUFSZ];
+       char endpoint_user[MAX_LOCAL_BUFSZ];
+       bool endpoint_system_exists;
+       bool endpoint_user_exists;
+       char buf[MAX_PID_STR_BUFSZ];
+       app_status_h app_status;
+       const char *appid;
+       uid_t uid;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return -1;
+
+       appid = _app_status_get_appid(app_status);
+       uid = _app_status_get_uid(app_status);
+       snprintf(endpoint_user, sizeof(endpoint_user),
+                       "app_status_event:%s:%d", appid, uid);
+       snprintf(endpoint_system, sizeof(endpoint_system),
+                       "app_status_event:%s", appid);
+       endpoint_system_exists = _app_com_endpoint_exists(endpoint_system);
+       endpoint_user_exists = _app_com_endpoint_exists(endpoint_user);
+       if (!endpoint_system_exists && !endpoint_user_exists)
+               return -1;
+
+       b = __create_appinfo_bundle(app_status);
+       if (b == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       snprintf(buf, sizeof(buf), "%d", context_status);
+       bundle_add(b, "__CONTEXT_STATUS__", buf);
+       if (endpoint_system_exists)
+               _app_com_send(endpoint_system, pid, b, uid);
+       if (endpoint_user_exists)
+               _app_com_send(endpoint_user, pid, b, uid);
+       bundle_free(b);
+
+       return 0;
+}
+
+static void __terminate_widget_apps_by_org_caller(int caller_pid, uid_t uid)
+{
+       GSList *iter;
+       struct app_status_s *app_status;
+       int ret;
+
+       for (iter = app_status_list; iter; iter = g_slist_next(iter)) {
+               app_status = (struct app_status_s *)iter->data;
+               if ((app_status->app_type == AT_WIDGET_APP ||
+                               app_status->app_type == AT_WATCH_APP) &&
+                               app_status->uid == uid &&
+                               app_status->org_caller_pid == caller_pid &&
+                               app_status->status != STATUS_DYING) {
+                       ret = _terminate_app_local(app_status->uid,
+                                       app_status->pid);
+                       if (ret < 0) {
+                               _E("Failed to terminate app(%d)",
+                                               app_status->pid);
+                       }
+               }
+       }
+}
+
+void _app_status_cleanup(app_status_h app_status)
+{
+       int pid;
+       int caller_pid;
+       const char *instance_id;
+       uid_t uid;
+
+       if (app_status == NULL)
+               return;
+
+       pid = _app_status_get_pid(app_status);
+       uid = _app_status_get_uid(app_status);
+       _D("pid: %d, uid: %d", pid, uid);
+
+       instance_id = _app_status_get_instance_id(app_status);
+       if (instance_id == NULL)
+               instance_id = _app_status_get_appid(app_status);
+       _screen_connector_remove_app_screen_v2(pid, uid);
+       _screen_connector_remove_screen_viewer_v2(pid, uid);
+
+       __terminate_widget_apps_by_org_caller(pid, uid);
+       _extractor_unmount(pid, _extractor_mountable_get_tep_paths);
+       _extractor_unmount(pid, _extractor_mountable_get_tpk_paths);
+       _app_com_client_remove(pid);
+       if (_app_group_is_leader_pid(pid)) {
+               _W("app_group_leader_app, pid: %d", pid);
+               if (_app_group_find_second_leader(pid) == -1) {
+                       _app_group_clear_top(pid, uid);
+                       _app_group_set_dead_pid(pid);
+                       _app_group_remove(pid);
+               } else {
+                       _app_group_remove_leader_pid(pid);
+               }
+       } else if (_app_group_is_sub_app(pid)) {
+               _W("app_group_sub_app, pid: %d", pid);
+               caller_pid = _app_group_get_next_caller_pid(pid);
+               if (_app_group_can_reroute(pid)
+                               || (caller_pid > 0 && caller_pid != pid)) {
+                       _W("app_group reroute");
+                       _app_group_reroute(pid);
+               } else {
+                       _W("app_group clear top");
+                       _app_group_clear_top(pid, uid);
+               }
+               _app_group_set_dead_pid(pid);
+               _app_group_remove(pid);
+       }
+
+       _launch_remove_fgmgr(pid);
+       _suspend_remove_proc(pid);
+       _app_group_remove_from_recycle_bin(pid);
+       _temporary_permission_drop(pid, uid);
+       _app_status_remove(app_status);
+       aul_send_app_terminated_signal(pid);
+}
+
+static bool __socket_monitor_cb(const char *event_name, void *data)
+{
+       app_status_h app_status;
+       int pid = -1;
+
+       if (event_name == NULL)
+               return true;
+
+       if (isdigit(*event_name))
+               pid = atoi(event_name);
+
+       if (pid > 1) {
+               _D("pid(%d)", pid);
+               _request_reply_for_pending_request(pid);
+               app_status = _app_status_find(pid);
+               if (app_status) {
+                       app_status->socket_exists = true;
+                       app_status->starting = true;
+               }
+       }
+
+       return true;
+}
+
+static bool __dir_monitor_cb(const char *event_name, void *data)
+{
+       char *path = (char *)data;
+       char *str = basename(path);
+       uid_t uid;
+       int wd;
+
+       if (event_name == NULL || str == NULL)
+               return true;
+
+       if (strcmp(event_name, str) == 0) {
+               wd = _inotify_add_watch(path, IN_CREATE, __socket_monitor_cb,
+                               NULL);
+               uid = strtol(event_name, NULL, 10);
+               g_hash_table_insert(__wd_table, GUINT_TO_POINTER(uid),
+                               GINT_TO_POINTER(wd));
+               free(path);
+               return false;
+       }
+
+       return true;
+}
+
+int _app_status_usr_init(uid_t uid)
+{
+       int wd;
+       char buf[PATH_MAX];
+       char *path;
+
+       wd = GPOINTER_TO_INT(g_hash_table_lookup(__wd_table,
+                               GUINT_TO_POINTER(uid)));
+       if (wd > 0) {
+               _D("Already exists");
+               return 0;
+       }
+
+       snprintf(buf, sizeof(buf), "/run/aul/apps/%d", uid);
+       if (access(buf, F_OK) == 0) {
+               wd = _inotify_add_watch(buf, IN_CREATE, __socket_monitor_cb,
+                               NULL);
+               if (wd < 0) {
+                       _E("Failed to add a watch - uid(%d)", uid);
+                       return -1;
+               }
+
+               g_hash_table_insert(__wd_table, GUINT_TO_POINTER(uid),
+                               GINT_TO_POINTER(wd));
+       } else {
+               path = strdup(buf);
+               if (path == NULL) {
+                       _E("Out of memory");
+                       return -1;
+               }
+
+               _inotify_add_watch("/run/aul/apps", IN_CREATE,
+                               __dir_monitor_cb, path);
+       }
+
+       return 0;
+}
+
+void _app_status_usr_fini(uid_t uid)
+{
+       int wd;
+       GSList *iter;
+       GSList *iter_next;
+       app_status_h app_status;
+
+       wd = GPOINTER_TO_INT(g_hash_table_lookup(__wd_table,
+                               GUINT_TO_POINTER(uid)));
+       if (wd > 0)
+               g_hash_table_remove(__wd_table, GUINT_TO_POINTER(uid));
+       else
+               _D("Watch fd doesn't exist - uid(%d)", uid);
+
+       GSLIST_FOREACH_SAFE(app_status_list, iter, iter_next) {
+               app_status = (struct app_status_s *)iter->data;
+               if (app_status && app_status->uid == uid)
+                       _app_status_cleanup(app_status);
+       }
+}
+
+static void __remove_inotify_watch(gpointer data)
+{
+       int wd = GPOINTER_TO_INT(data);
+
+       if (wd <= 0)
+               return;
+
+       _inotify_rm_watch(wd);
+}
+
+int _app_status_init(void)
+{
+       int ret;
+
+       __wd_table = g_hash_table_new_full(g_direct_hash,
+                       g_direct_equal, NULL, __remove_inotify_watch);
+       if (__wd_table == NULL) {
+               _E("Failed to create wd hash table");
+               return -1;
+       }
+
+       ret = vconf_get_int(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS,
+                       &limit_bg_uiapps);
+       if (ret != VCONF_OK)
+               _E("Failed to get %s", VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS);
+
+       ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS,
+                       __vconf_cb, NULL);
+       if (ret != 0) {
+               _E("Failed to register callback for %s",
+                               VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS);
+       }
+
+       home_appid = vconf_get_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME);
+       ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME,
+                       __home_appid_vconf_cb, NULL);
+       if (ret != 0) {
+               _E("Failed to register callback for %s",
+                               VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME);
+       }
+
+       oom_app_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                       NULL, __destroy_fault_app_info);
+       pkg_update_app_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                       NULL, __destroy_fault_app_info);
+
+       _cooldown_init();
+       return 0;
+}
+
+int _app_status_finish(void)
+{
+       int ret;
+       GSList *iter;
+       GSList *iter_next;
+       app_status_h app_status;
+
+       GSLIST_FOREACH_SAFE(app_status_list, iter, iter_next) {
+               app_status = (app_status_h)iter->data;
+               _app_status_cleanup(app_status);
+       }
+
+       ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS,
+                       __vconf_cb);
+       if (ret != 0)
+               _E("Failed to remove a callback");
+
+       ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME,
+                       __home_appid_vconf_cb);
+       if (ret != 0)
+               _E("Failed to remove a callback");
+
+       free(home_appid);
+
+       if (__wd_table)
+               g_hash_table_destroy(__wd_table);
+
+       _cooldown_fini();
+
+       g_hash_table_destroy(oom_app_table);
+       g_hash_table_destroy(pkg_update_app_table);
+
+       return 0;
+}
diff --git a/src/amd_appinfo.c b/src/amd_appinfo.c
new file mode 100644 (file)
index 0000000..9022b8a
--- /dev/null
@@ -0,0 +1,1973 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <dirent.h>
+#include <package-manager.h>
+#include <pkgmgr-info.h>
+#include <vconf.h>
+#include <aul.h>
+
+#include "amd_util.h"
+#include "amd_appinfo.h"
+#include "amd_launch.h"
+#include "amd_app_status.h"
+#include "amd_signal.h"
+#include "amd_app_property.h"
+#include "amd_login_monitor.h"
+#include "amd_widget.h"
+
+static pkgmgr_client *pc;
+static GHashTable *user_tbl;
+static GHashTable *pkg_pending;
+struct user_appinfo {
+       uid_t uid;
+       GHashTable *tbl; /* key is appid, value is struct appinfo */
+};
+
+struct app_event_info {
+       int req_id;
+       int type;
+       uid_t uid;
+};
+
+struct pkg_event_info {
+       uid_t target_uid;
+       const char *pkgid;
+};
+
+static GList *app_event_list;
+
+typedef int (*appinfo_handler_add_cb)(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data);
+typedef void (*appinfo_handler_remove_cb)(void *data);
+
+typedef struct _appinfo_vft {
+       appinfo_handler_add_cb constructor;
+       appinfo_handler_remove_cb destructor;
+} appinfo_vft;
+
+enum _background_category {
+       _BACKGROUND_CATEGORY_MEDIA = 0x01,
+       _BACKGROUND_CATEGORY_DOWNLOAD = 0x02,
+       _BACKGROUND_CATEGORY_BACKGROUND_NETWORK = 0x04,
+       _BACKGROUND_CATEGORY_LOCATION = 0x08,
+       _BACKGROUND_CATEGORY_SENSOR = 0x10,
+       _BACKGROUND_CATEGORY_IOT_COMMUNICATION = 0x20,
+       _BACKGROUND_CATEGORY_SYSTEM = 0x40
+};
+
+static int gles = 1;
+
+static void __free_appinfo_splash_image(gpointer data)
+{
+       struct appinfo_splash_image *splash_image = data;
+
+       if (splash_image == NULL)
+               return;
+
+       if (splash_image->color_depth)
+               free(splash_image->color_depth);
+       if (splash_image->indicatordisplay)
+               free(splash_image->indicatordisplay);
+       if (splash_image->type)
+               free(splash_image->type);
+       if (splash_image->src)
+               free(splash_image->src);
+       free(splash_image);
+}
+
+static void __free_user_appinfo(gpointer data)
+{
+       struct user_appinfo *info = (struct user_appinfo *)data;
+
+       g_hash_table_destroy(info->tbl);
+       free(info);
+}
+
+static int __read_background_category(const char *category_name,
+               void *user_data)
+{
+       struct appinfo *c = user_data;
+       int category = (intptr_t)(c->val[AIT_BG_CATEGORY]);
+
+       if (!category_name)
+               return 0;
+
+       if (strcmp(category_name, "disable") == 0) {
+               c->val[AIT_BG_CATEGORY] = 0x00;
+               return -1;
+       }
+
+       if (strcmp(category_name, "media") == 0) {
+               c->val[AIT_BG_CATEGORY] = (char *)((intptr_t)(category |
+                               _BACKGROUND_CATEGORY_MEDIA));
+       } else if (strcmp(category_name, "download") == 0) {
+               c->val[AIT_BG_CATEGORY] = (char *)((intptr_t)(category |
+                               _BACKGROUND_CATEGORY_DOWNLOAD));
+       } else if (strcmp(category_name, "background-network") == 0) {
+               c->val[AIT_BG_CATEGORY] = (char *)((intptr_t)(category |
+                               _BACKGROUND_CATEGORY_BACKGROUND_NETWORK));
+       } else if (strcmp(category_name, "location") == 0) {
+               c->val[AIT_BG_CATEGORY] = (char *)((intptr_t)(category |
+                               _BACKGROUND_CATEGORY_LOCATION));
+       } else if (strcmp(category_name, "sensor") == 0) {
+               c->val[AIT_BG_CATEGORY] = (char *)((intptr_t)(category |
+                               _BACKGROUND_CATEGORY_SENSOR));
+       } else if (strcmp(category_name, "iot-communication") == 0) {
+               c->val[AIT_BG_CATEGORY] = (char *)((intptr_t)(category |
+                               _BACKGROUND_CATEGORY_IOT_COMMUNICATION));
+       } else if (strcmp(category_name, "system") == 0) {
+               c->val[AIT_BG_CATEGORY] = (char *)((intptr_t)(category |
+                               _BACKGROUND_CATEGORY_SYSTEM));
+       }
+
+       return 0;
+}
+
+static void __appinfo_remove_splash_screen(void *data)
+{
+       struct appinfo_splash_screen *splash_screen =
+               (struct appinfo_splash_screen *)data;
+
+       if (splash_screen == NULL)
+               return;
+
+       if (splash_screen->portrait)
+               g_hash_table_destroy(splash_screen->portrait);
+       if (splash_screen->landscape)
+               g_hash_table_destroy(splash_screen->landscape);
+       free(splash_screen);
+}
+
+static int __appinfo_add_exec(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *exec = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get exec");
+               return -1;
+       }
+
+       info->val[AIT_EXEC] = strdup(exec);
+
+       return 0;
+}
+
+static int __appinfo_add_pkgtype(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *pkgtype = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_pkgtype(handle, &pkgtype);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get pkgtype");
+               return -1;
+       }
+
+       info->val[AIT_PKGTYPE] = strdup(pkgtype);
+
+       return 0;
+}
+
+static int __appinfo_add_onboot(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       bool onboot = false;
+
+       ret = pkgmgrinfo_appinfo_is_onboot(handle, &onboot);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get onboot");
+               return -1;
+       }
+
+       info->val[AIT_ONBOOT] = strdup(onboot ? "true" : "false");
+
+       return 0;
+}
+
+static int __appinfo_add_restart(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       bool restart = false;
+
+       ret = pkgmgrinfo_appinfo_is_autorestart(handle, &restart);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get restart");
+               return -1;
+       }
+
+       info->val[AIT_RESTART] = GINT_TO_POINTER(restart ? 1 : 0);
+
+       return 0;
+}
+
+static int __appinfo_add_multi(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       bool multiple = false;
+
+       ret = pkgmgrinfo_appinfo_is_multiple(handle, &multiple);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get multiple");
+               return -1;
+       }
+
+       info->val[AIT_MULTI] = strdup(multiple ? "true" : "false");
+
+       return 0;
+}
+
+static int __appinfo_add_hwacc(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       pkgmgrinfo_app_hwacceleration hwacc;
+
+       ret = pkgmgrinfo_appinfo_get_hwacceleration(handle, &hwacc);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get hwacc");
+               return -1;
+       }
+
+       info->val[AIT_HWACC] = strdup(
+                               (gles == 0 ||
+                                hwacc == PMINFO_HWACCELERATION_OFF) ?
+                               "NOT_USE" :
+                               (hwacc == PMINFO_HWACCELERATION_ON) ?
+                               "USE" :
+                               "SYS");
+
+       return 0;
+}
+
+static int __appinfo_add_perm(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       pkgmgrinfo_permission_type permission;
+
+       ret = pkgmgrinfo_appinfo_get_permission_type(handle, &permission);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get permission type");
+               return -1;
+       }
+
+       info->val[AIT_PERM] = strdup(
+                               (permission == PMINFO_PERMISSION_SIGNATURE) ?
+                               "signature" :
+                               (permission == PMINFO_PERMISSION_PRIVILEGE) ?
+                               "privilege" :
+                               "normal");
+
+       return 0;
+}
+
+static int __appinfo_add_pkgid(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *pkgid = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get pkgid");
+               return -1;
+       }
+
+       info->val[AIT_PKGID] = strdup(pkgid);
+
+       return 0;
+}
+
+static int __appinfo_add_preload(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       bool preload = false;
+
+       ret = pkgmgrinfo_appinfo_is_preload(handle, &preload);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get preload");
+               return -1;
+       }
+
+       info->val[AIT_PRELOAD] = strdup(preload ? "true" : "false");
+
+       return 0;
+}
+
+static int __appinfo_add_status(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       info->val[AIT_STATUS] = strdup("installed");
+
+       return 0;
+}
+
+static int __appinfo_add_pool(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       bool process_pool = false;
+
+       ret = pkgmgrinfo_appinfo_is_process_pool(handle, &process_pool);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get process_pool");
+               return -1;
+       }
+
+       info->val[AIT_POOL] = strdup(process_pool ? "true" : "false");
+
+       return 0;
+}
+
+static int __appinfo_add_comptype(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *component_type = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_component_type(handle, &component_type);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get component type");
+               return -1;
+       }
+
+       info->val[AIT_COMPTYPE] = strdup(component_type);
+
+       return 0;
+}
+
+static int __appinfo_add_tep(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *tep_name = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_tep_name(handle, &tep_name);
+       if (ret != PMINFO_R_OK) {
+               info->val[AIT_TEP] = NULL;
+       } else {
+               if (tep_name && strlen(tep_name) > 0)
+                       info->val[AIT_TEP] = strdup(tep_name);
+               else
+                       info->val[AIT_TEP] = NULL;
+       }
+
+       return 0;
+}
+
+static int __appinfo_add_mountable_pkg(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *tpk_name = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_zip_mount_file(handle, &tpk_name);
+       if (ret != PMINFO_R_OK) {
+               info->val[AIT_MOUNTABLE_PKG] = NULL;
+       } else {
+               if (tpk_name && strlen(tpk_name) > 0)
+                       info->val[AIT_MOUNTABLE_PKG] = strdup(tpk_name);
+               else
+                       info->val[AIT_MOUNTABLE_PKG] = NULL;
+       }
+
+       return 0;
+}
+
+static int __appinfo_add_storage_type(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       pkgmgrinfo_installed_storage installed_storage;
+
+       ret = pkgmgrinfo_appinfo_get_installed_storage_location(handle,
+                       &installed_storage);
+       if (ret == PMINFO_R_OK) {
+               if (installed_storage == PMINFO_INTERNAL_STORAGE)
+                       info->val[AIT_STORAGE_TYPE] = strdup("internal");
+               else if (installed_storage == PMINFO_EXTERNAL_STORAGE)
+                       info->val[AIT_STORAGE_TYPE] = strdup("external");
+       } else {
+               info->val[AIT_STORAGE_TYPE] = strdup("internal");
+       }
+
+       return 0;
+}
+
+static int __appinfo_add_bg_category(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+
+       ret = pkgmgrinfo_appinfo_foreach_background_category(handle,
+                       __read_background_category, info);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get background category");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __appinfo_add_launch_mode(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *mode = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_launch_mode(handle, &mode);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get launch_mode");
+               return -1;
+       }
+
+       info->val[AIT_LAUNCH_MODE] = strdup(mode ? mode : "single");
+
+       return 0;
+}
+
+static int __appinfo_add_global(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       bool is_global = false;
+
+       ret = pkgmgrinfo_appinfo_is_global(handle, &is_global);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get is_global info");
+               return -1;
+       }
+
+       info->val[AIT_GLOBAL] = strdup(is_global ? "true" : "false");
+
+       return 0;
+}
+
+static int __appinfo_add_effective_appid(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *effective_appid = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_effective_appid(handle, &effective_appid);
+       if (ret != PMINFO_R_OK) {
+               info->val[AIT_EFFECTIVE_APPID] = NULL;
+       } else {
+               if (effective_appid && strlen(effective_appid) > 0) {
+                       info->val[AIT_EFFECTIVE_APPID] =
+                               strdup(effective_appid);
+               }
+       }
+
+       return 0;
+}
+
+static int __appinfo_add_taskmanage(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       bool taskmanage = false;
+
+       pkgmgrinfo_appinfo_is_taskmanage(handle, &taskmanage);
+
+       info->val[AIT_TASKMANAGE] = strdup(taskmanage ? "true" : "false");
+
+       return 0;
+}
+
+static int __appinfo_add_apptype(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *apptype = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_apptype(handle, &apptype);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get apptype");
+               return -1;
+       }
+
+       info->val[AIT_APPTYPE] = strdup(apptype);
+
+       return 0;
+}
+
+static int __appinfo_add_root_path(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *path = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_root_path(handle, &path);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get root path");
+               return -1;
+       }
+
+       info->val[AIT_ROOT_PATH] = path ? strdup(path) : NULL;
+
+       return 0;
+}
+
+static int __add_splash_screen_list_cb(const char *src, const char *type,
+               const char *orientation, const char *indicatordisplay,
+               const char *operation, const char *color_depth, void *user_data)
+{
+       struct appinfo *info = (struct appinfo *)user_data;
+       struct appinfo_splash_screen *splash_screen;
+       struct appinfo_splash_image *splash_image;
+       char *key;
+
+       splash_image = (struct appinfo_splash_image *)calloc(1,
+                       sizeof(struct appinfo_splash_image));
+       if (splash_image == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       splash_image->src = strdup(src);
+       splash_image->type = strdup(type);
+       splash_image->indicatordisplay = strdup(indicatordisplay);
+       splash_image->color_depth = strdup(color_depth);
+       key = strdup(operation);
+
+       splash_screen =
+               (struct appinfo_splash_screen *)info->val[AIT_SPLASH_SCREEN];
+       if (splash_screen == NULL) {
+               splash_screen = (struct appinfo_splash_screen *)calloc(1,
+                               sizeof(struct appinfo_splash_screen));
+               if (splash_screen == NULL) {
+                       _E("out of memory");
+                       __free_appinfo_splash_image(splash_image);
+                       free(key);
+                       return -1;
+               }
+               info->val[AIT_SPLASH_SCREEN] = (char *)splash_screen;
+       }
+
+       if (strcasecmp(orientation, "portrait") == 0) {
+               if (splash_screen->portrait == NULL) {
+                       splash_screen->portrait = g_hash_table_new_full(
+                                       g_str_hash, g_str_equal, g_free,
+                                       __free_appinfo_splash_image);
+               }
+               g_hash_table_insert(splash_screen->portrait, key, splash_image);
+       } else if (strcasecmp(orientation, "landscape") == 0) {
+               if (splash_screen->landscape == NULL) {
+                       splash_screen->landscape = g_hash_table_new_full(
+                                       g_str_hash, g_str_equal, g_free,
+                                       __free_appinfo_splash_image);
+               }
+               g_hash_table_insert(splash_screen->landscape, key,
+                               splash_image);
+       } else {
+               __free_appinfo_splash_image(splash_image);
+               free(key);
+       }
+
+       return 0;
+}
+
+static int __appinfo_add_splash_screens(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+
+       ret = pkgmgrinfo_appinfo_foreach_splash_screen(handle,
+                       __add_splash_screen_list_cb, info);
+       if (ret < 0) {
+               _E("Failed to get splash screen");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __appinfo_add_splash_screen_display(
+               const pkgmgrinfo_appinfo_h handle, struct appinfo *info,
+               void *data)
+{
+       bool splash_screen_display = true;
+       int ret;
+
+       ret = pkgmgrinfo_appinfo_get_splash_screen_display(handle,
+                       &splash_screen_display);
+       if (ret < 0)
+               _D("Failed to get splash screen display");
+
+       info->val[AIT_SPLASH_SCREEN_DISPLAY] =
+               GINT_TO_POINTER(splash_screen_display ? 1 : 0);
+
+       return 0;
+}
+
+static int __appinfo_add_api_version(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       char *api_version;
+
+       ret = pkgmgrinfo_appinfo_get_api_version(handle, &api_version);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get api version");
+               return -1;
+       }
+
+       info->val[AIT_API_VERSION] = strdup(api_version);
+
+       return 0;
+}
+
+static int __appinfo_add_enablement(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       bool disabled = false;
+
+       ret = pkgmgrinfo_appinfo_is_disabled(handle, &disabled);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get enablement");
+               return -1;
+       }
+
+       info->val[AIT_ENABLEMENT] = GINT_TO_POINTER(disabled ? 0 : 1);
+
+       return 0;
+}
+
+static int __appinfo_add_cooldown_mode(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       int support_mode = 0;
+
+       ret = pkgmgrinfo_appinfo_get_support_mode(handle, &support_mode);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get support mode value");
+               return -1;
+       }
+
+       if (support_mode & APP_SUPPORT_MODE_COOL_DOWN_VAL)
+               info->val[AIT_COOLDOWN] = strdup("true");
+       else
+               info->val[AIT_COOLDOWN] = strdup("false");
+
+       return 0;
+}
+
+static int __appinfo_add_system(const pkgmgrinfo_appinfo_h handle,
+               struct appinfo *info, void *data)
+{
+       int ret;
+       bool system = false;
+
+       ret = pkgmgrinfo_appinfo_is_system(handle, &system);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get support mode value");
+               return -1;
+       }
+
+       if (system)
+               info->val[AIT_SYSTEM] = strdup("true");
+       else
+               info->val[AIT_SYSTEM] = strdup("false");
+       if (info->val[AIT_SYSTEM] == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       return 0;
+}
+
+static  appinfo_vft appinfo_table[AIT_MAX] = {
+       [AIT_NAME] = {
+               .constructor = NULL,
+               .destructor = NULL
+       },
+       [AIT_EXEC] = {
+               .constructor = __appinfo_add_exec,
+               .destructor = free
+       },
+       [AIT_PKGTYPE] = {
+               .constructor = __appinfo_add_pkgtype,
+               .destructor = free
+       },
+       [AIT_ONBOOT] = {
+               .constructor = __appinfo_add_onboot,
+               .destructor = free
+       },
+       [AIT_RESTART] = {
+               .constructor = __appinfo_add_restart,
+               .destructor = NULL
+       },
+       [AIT_MULTI] = {
+               .constructor = __appinfo_add_multi,
+               .destructor = free
+       },
+       [AIT_HWACC] = {
+               .constructor = __appinfo_add_hwacc,
+               .destructor = free
+       },
+       [AIT_PERM] = {
+               .constructor = __appinfo_add_perm,
+               .destructor = free
+       },
+       [AIT_PKGID] = {
+               .constructor = __appinfo_add_pkgid,
+               .destructor = free
+       },
+       [AIT_PRELOAD] = {
+               .constructor = __appinfo_add_preload,
+               .destructor = free
+       },
+       [AIT_STATUS] = {
+               .constructor = __appinfo_add_status,
+               .destructor = free
+       },
+       [AIT_POOL] = {
+               .constructor = __appinfo_add_pool,
+               .destructor = free
+       },
+       [AIT_COMPTYPE] = {
+               .constructor = __appinfo_add_comptype,
+               .destructor = free
+       },
+       [AIT_TEP] = {
+               .constructor = __appinfo_add_tep,
+               .destructor = free
+       },
+       [AIT_MOUNTABLE_PKG] = {
+               .constructor = __appinfo_add_mountable_pkg,
+               .destructor = free
+       },
+       [AIT_STORAGE_TYPE] = {
+               .constructor = __appinfo_add_storage_type,
+               .destructor = free
+       },
+       [AIT_BG_CATEGORY] = {
+               .constructor = __appinfo_add_bg_category,
+               .destructor = NULL
+       },
+       [AIT_LAUNCH_MODE] = {
+               .constructor = __appinfo_add_launch_mode,
+               .destructor = free
+       },
+       [AIT_GLOBAL] = {
+               .constructor = __appinfo_add_global,
+               .destructor = free
+       },
+       [AIT_EFFECTIVE_APPID] = {
+               .constructor = __appinfo_add_effective_appid,
+               .destructor = free
+       },
+       [AIT_TASKMANAGE] = {
+               .constructor = __appinfo_add_taskmanage,
+               .destructor = free
+       },
+       [AIT_VISIBILITY] = {
+               .constructor = NULL,
+               .destructor = free
+       },
+       [AIT_APPTYPE] = {
+               .constructor = __appinfo_add_apptype,
+               .destructor = free
+       },
+       [AIT_ROOT_PATH] = {
+               .constructor = __appinfo_add_root_path,
+               .destructor = free
+       },
+       [AIT_SPLASH_SCREEN] = {
+               .constructor = __appinfo_add_splash_screens,
+               .destructor = __appinfo_remove_splash_screen
+       },
+       [AIT_SPLASH_SCREEN_DISPLAY] = {
+               .constructor = __appinfo_add_splash_screen_display,
+               .destructor = NULL
+       },
+       [AIT_API_VERSION] = {
+               .constructor = __appinfo_add_api_version,
+               .destructor = free
+       },
+       [AIT_ENABLEMENT] = {
+               .constructor = __appinfo_add_enablement,
+               .destructor = NULL
+       },
+       [AIT_COOLDOWN] = {
+               .constructor = __appinfo_add_cooldown_mode,
+               .destructor = free
+       },
+       [AIT_SYSTEM] = {
+               .constructor = __appinfo_add_system,
+               .destructor = free
+       },
+
+};
+
+static void __appinfo_remove_handler(gpointer data)
+{
+       struct appinfo *c = data;
+       int i;
+
+       if (!c)
+               return;
+
+       for (i = AIT_START; i < AIT_MAX; i++) {
+               if (appinfo_table[i].destructor && c->val[i] != NULL)
+                       appinfo_table[i].destructor(c->val[i]);
+       }
+
+       free(c);
+}
+
+static int __appinfo_insert_handler (const pkgmgrinfo_appinfo_h handle,
+                                       void *data)
+{
+       int i;
+       struct appinfo *c;
+       struct user_appinfo *info = (struct user_appinfo *)data;
+       char *appid;
+       int ret;
+       char err_buf[1024];
+
+       if (!handle || !info) {
+               _E("null app handle");
+               return -1;
+       }
+
+       if (pkgmgrinfo_appinfo_get_appid(handle, &appid) != PMINFO_R_OK) {
+               _E("fail to get appinfo");
+               return -1;
+       }
+
+       g_hash_table_remove(info->tbl, appid);
+
+       c = calloc(1, sizeof(struct appinfo));
+       if (!c) {
+               _E("create appinfo: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               return -1;
+       }
+
+       c->val[AIT_NAME] = strdup(appid);
+
+       for (i = AIT_START; i < AIT_MAX; i++) {
+               if (appinfo_table[i].constructor) {
+                       ret = appinfo_table[i].constructor(handle, c, info);
+                       if (ret < 0) {
+                               __appinfo_remove_handler(c);
+                               return -1;
+                       }
+               }
+       }
+
+       SECURE_LOGD("%s : %s : %s : %s", c->val[AIT_NAME], c->val[AIT_COMPTYPE],
+               c->val[AIT_PKGTYPE], c->val[AIT_APPTYPE]);
+
+       g_hash_table_insert(info->tbl, c->val[AIT_NAME], c);
+       _app_property_insert(info->uid, c->val[AIT_NAME]);
+
+       return 0;
+}
+
+static int __appinfo_update_handler(const pkgmgrinfo_appinfo_h handle,
+               void *data)
+{
+       int i;
+       struct appinfo *c;
+       struct user_appinfo *info = (struct user_appinfo *)data;
+       char *appid;
+       int ret;
+       bool restart;
+       int auto_restart;
+
+       if (!handle || !info) {
+               _E("Invalid parameter");
+               return -1;
+       }
+
+       ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get appinfo");
+               return -1;
+       }
+
+       c = (struct appinfo *)g_hash_table_lookup(info->tbl, appid);
+       if (!c) {
+               _E("Failed to find appinfo(%s)", appid);
+               return -1;
+       }
+
+       if (c->val[AIT_STATUS] && strcmp(c->val[AIT_STATUS], "restart") == 0)
+               restart = true;
+       else
+               restart = false;
+
+       for (i = AIT_START; i < AIT_MAX; i++) {
+               if (appinfo_table[i].destructor && c->val[i])
+                       appinfo_table[i].destructor(c->val[i]);
+
+               if (appinfo_table[i].constructor) {
+                       ret = appinfo_table[i].constructor(handle, c, info);
+                       if (ret < 0) {
+                               __appinfo_remove_handler(c);
+                               return -1;
+                       }
+               }
+       }
+       SECURE_LOGD("%s : %s : %s : %s",
+                       c->val[AIT_NAME], c->val[AIT_COMPTYPE],
+                       c->val[AIT_PKGTYPE], c->val[AIT_APPTYPE]);
+       _app_property_insert(info->uid, c->val[AIT_NAME]);
+
+       auto_restart = GPOINTER_TO_INT(c->val[AIT_RESTART]);
+       if (auto_restart && restart)
+               _launch_start_app_local(info->uid, c->val[AIT_NAME]);
+
+       return 0;
+}
+
+static int __insert_appinfo(const pkgmgrinfo_appinfo_h handle, void *data)
+{
+       int ret;
+       struct appinfo *ai;
+       struct user_appinfo *info = (struct user_appinfo *)data;
+       char *appid = NULL;
+
+       ret = __appinfo_insert_handler(handle, data);
+       if (ret < 0)
+               return -1;
+
+       ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
+       if (ret != PMINFO_R_OK)
+               return -1;
+
+       ai = (struct appinfo *)g_hash_table_lookup(info->tbl, appid);
+       if (ai == NULL)
+               return -1;
+
+       _launch_start_onboot_app_local(info->uid, appid, ai);
+
+       return 0;
+}
+
+static void __remove_user_appinfo(uid_t uid)
+{
+       g_hash_table_remove(user_tbl, GINT_TO_POINTER(uid));
+}
+
+static struct user_appinfo *__add_user_appinfo(uid_t uid)
+{
+       int r;
+       struct user_appinfo *info;
+
+       info = calloc(1, sizeof(struct user_appinfo));
+       if (info == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       info->uid = uid;
+       info->tbl = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+                       __appinfo_remove_handler);
+       if (info->tbl == NULL) {
+               _E("out of memory");
+               free(info);
+               return NULL;
+       }
+
+       g_hash_table_insert(user_tbl, GINT_TO_POINTER(uid), info);
+
+       r = pkgmgrinfo_appinfo_get_usr_installed_list_full(
+                       __appinfo_insert_handler, uid,
+                       PMINFO_APPINFO_GET_SPLASH_SCREEN, info);
+       if (r != PMINFO_R_OK) {
+               __remove_user_appinfo(uid);
+               return NULL;
+       }
+
+       _D("loaded appinfo table for uid %d", uid);
+
+       return info;
+}
+
+static struct user_appinfo *__find_user_appinfo(uid_t uid)
+{
+       return g_hash_table_lookup(user_tbl, GINT_TO_POINTER(uid));
+}
+
+static void __appinfo_set_blocking_cb(void *user_data,
+               const char *appid, struct appinfo *info)
+{
+       struct pkg_event_info *pkg_info = (struct pkg_event_info *)user_data;
+
+       if (strcmp(info->val[AIT_PKGID], pkg_info->pkgid))
+               return;
+
+       if (pkg_info->target_uid == GLOBAL_USER &&
+                       !strcmp(info->val[AIT_GLOBAL], "false"))
+               return;
+       else if (pkg_info->target_uid != GLOBAL_USER &&
+                       !strcmp(info->val[AIT_GLOBAL], "true"))
+               return;
+
+       free(info->val[AIT_STATUS]);
+       info->val[AIT_STATUS] = strdup("blocking");
+       _D("%s status changed: blocking", appid);
+}
+
+static void __appinfo_unset_blocking_cb(void *user_data,
+               const char *appid, struct appinfo *info)
+{
+       struct pkg_event_info *pkg_info = (struct pkg_event_info *)user_data;
+
+       if (strcmp(info->val[AIT_PKGID], pkg_info->pkgid))
+               return;
+
+       if (pkg_info->target_uid == GLOBAL_USER &&
+                       !strcmp(info->val[AIT_GLOBAL], "false"))
+               return;
+       else if (pkg_info->target_uid != GLOBAL_USER &&
+                       !strcmp(info->val[AIT_GLOBAL], "true"))
+               return;
+
+       free(info->val[AIT_STATUS]);
+       info->val[AIT_STATUS] = strdup("installed");
+       _D("%s status changed: installed", appid);
+}
+
+static gboolean __appinfo_remove_cb(gpointer key, gpointer value, gpointer data)
+{
+       struct pkg_event_info *pkg_info = (struct pkg_event_info *)data;
+       struct appinfo *info = (struct appinfo *)value;
+
+       if (strcmp(info->val[AIT_PKGID], pkg_info->pkgid))
+               return FALSE;
+
+       if (pkg_info->target_uid == GLOBAL_USER &&
+                       !strcmp(info->val[AIT_GLOBAL], "false"))
+               return FALSE;
+       else if (pkg_info->target_uid != GLOBAL_USER &&
+                       !strcmp(info->val[AIT_GLOBAL], "true"))
+               return FALSE;
+
+       _app_property_delete(GPOINTER_TO_UINT(key), info->val[AIT_NAME]);
+
+       _D("appinfo removed: %s", info->val[AIT_NAME]);
+       return TRUE;
+}
+
+static void __appinfo_delete_on_event(uid_t uid, void *data)
+{
+       struct user_appinfo *info;
+       app_property_h prop;
+
+       info = __find_user_appinfo(uid);
+       if (info == NULL) {
+               _E("cannot find appinfo for uid %d", uid);
+               return;
+       }
+
+       prop = _app_property_find(uid);
+       _app_property_cache_invalidate(prop);
+       g_hash_table_foreach_remove(info->tbl, __appinfo_remove_cb,
+                       (gpointer)data);
+}
+
+static void __appinfo_insert_on_event(uid_t uid, const char *pkgid)
+{
+       app_property_h prop;
+
+       prop = _app_property_find(uid);
+       _app_property_cache_invalidate(prop);
+       _appinfo_insert(uid, pkgid);
+}
+
+static void __appinfo_update_on_event(uid_t uid, void *data)
+{
+       struct pkg_event_info *pkg_info = (struct pkg_event_info *)data;
+       struct user_appinfo *info;
+       app_property_h prop;
+       pkgmgrinfo_pkginfo_h handle;
+       int ret;
+
+       info = __find_user_appinfo(uid);
+       if (info == NULL) {
+               _E("cannot find appinfo for uid %d", uid);
+               return;
+       }
+
+       prop = _app_property_find(uid);
+       _app_property_cache_invalidate(prop);
+
+       ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_info->pkgid, uid, &handle);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to get pkginfo(%s)", pkg_info->pkgid);
+               return;
+       }
+
+       ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
+                       __appinfo_update_handler, info, info->uid);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to update pkginfo(%s)", pkg_info->pkgid);
+               pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+               return;
+       }
+
+       pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+}
+
+static void __set_blocking(struct pkg_event_info *info)
+{
+       uid_t *uids = NULL;
+       int r;
+       int i;
+
+       if (info->target_uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return;
+
+               for (i = 0; i < r; i++) {
+                       _appinfo_foreach(uids[i],
+                                       __appinfo_set_blocking_cb, info);
+                       _D("terminate apps by PackageID - %s", info->pkgid);
+                       _app_status_terminate_apps_by_pkgid(info->pkgid,
+                                       uids[i]);
+               }
+               free(uids);
+
+               return;
+       }
+
+       _appinfo_foreach(info->target_uid, __appinfo_set_blocking_cb, info);
+       _D("terminate apps by PackageID - %s", info->pkgid);
+       _app_status_terminate_apps_by_pkgid(info->pkgid, info->target_uid);
+}
+
+static void __unset_blocking(struct pkg_event_info *info)
+{
+       uid_t *uids = NULL;
+       int r;
+       int i;
+
+       if (info->target_uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return;
+
+               for (i = 0; i < r; i++) {
+                       _appinfo_foreach(uids[i],
+                                       __appinfo_unset_blocking_cb, info);
+               }
+               free(uids);
+
+               return;
+       }
+
+       _appinfo_foreach(info->target_uid, __appinfo_unset_blocking_cb, info);
+}
+
+static void __delete_on_event(struct pkg_event_info *info)
+{
+       uid_t *uids = NULL;
+       int r;
+       int i;
+
+       if (info->target_uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return;
+
+               for (i = 0; i < r; i++)
+                       __appinfo_delete_on_event(uids[i], info);
+               free(uids);
+
+               return;
+       }
+
+       __appinfo_delete_on_event(info->target_uid, info);
+}
+
+static void __insert_on_event(struct pkg_event_info *info)
+{
+       uid_t *uids = NULL;
+       int r;
+       int i;
+
+       if (info->target_uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return;
+
+               for (i = 0; i < r; i++)
+                       __appinfo_insert_on_event(uids[i], info->pkgid);
+               free(uids);
+
+               return;
+       }
+
+       __appinfo_insert_on_event(info->target_uid, info->pkgid);
+}
+
+static void __update_on_event(struct pkg_event_info *info)
+{
+       uid_t *uids = NULL;
+       int r;
+       int i;
+
+       if (info->target_uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return;
+
+               for (i = 0; i < r; i++)
+                       __appinfo_update_on_event(uids[i], info);
+               free(uids);
+
+               return;
+       }
+
+       __appinfo_update_on_event(info->target_uid, info);
+}
+
+static int __appinfo_is_pkg_exist(uid_t uid, const char *pkgid)
+{
+       int r;
+       struct user_appinfo *info;
+       GHashTableIter iter;
+       gpointer key, value;
+       uid_t *uids = NULL;
+
+       if (pkgid == NULL)
+               return 0;
+
+       if (uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return 0;
+
+               uid = uids[0];
+
+               free(uids);
+       }
+
+       info = __find_user_appinfo(uid);
+       if (info == NULL) {
+               _E("cannot find appinfo for uid %d", uid);
+               return 0;
+       }
+
+       g_hash_table_iter_init(&iter, info->tbl);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               struct appinfo *ai = (struct appinfo *)value;
+               if (strcmp(pkgid, ai->val[AIT_PKGID]) == 0)
+                       return 1;
+       }
+
+       return 0;
+}
+
+static void __appinfo_enable_pkg_apps(uid_t uid, const char *pkgid, int enable)
+{
+       int r;
+       int i;
+       struct user_appinfo *info;
+       GHashTableIter iter;
+       gpointer key, value;
+       uid_t *uids = NULL;
+       struct appinfo *ai;
+       int prev_val;
+       const char *appid;
+
+       if (pkgid == NULL)
+               return;
+
+       if (uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return;
+
+               for (i = 0; i < r; i++)
+                       __appinfo_enable_pkg_apps(uids[i], pkgid, enable);
+
+               free(uids);
+
+               return;
+       }
+
+       info = __find_user_appinfo(uid);
+       if (info == NULL) {
+               _E("cannot find appinfo for uid %d", uid);
+               return;
+       }
+
+       g_hash_table_iter_init(&iter, info->tbl);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               ai = (struct appinfo *)value;
+
+               if (strcmp(pkgid, ai->val[AIT_PKGID]) == 0) {
+                       _appinfo_get_int_value(ai, AIT_ENABLEMENT, &prev_val);
+                       _appinfo_set_int_value(ai, AIT_ENABLEMENT, enable);
+                       if (prev_val == 0 && enable == 1) {
+                               appid = _appinfo_get_value(ai, AIT_NAME);
+                               _launch_start_onboot_app_local(uid, appid, ai);
+                       }
+               }
+       }
+
+       return;
+}
+
+static void __update_property(uid_t uid)
+{
+       uid_t *uids = NULL;
+       int r;
+       int i;
+
+       if (uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return;
+
+               for (i = 0; i < r; i++) {
+                       _app_property_unload(uids[i]);
+                       _app_property_load(uids[i]);
+               }
+
+               free(uids);
+
+               return;
+       }
+
+       _app_property_unload(uid);
+       _app_property_load(uid);
+}
+
+static int __package_event_cb(uid_t target_uid, int req_id,
+               const char *pkg_type, const char *pkgid,
+               const char *key, const char *val, const void *pmsg, void *data)
+{
+       int ret;
+       char *op;
+       struct pkg_event_info info = {
+               .target_uid = target_uid,
+               .pkgid = pkgid
+       };
+       pkgmgrinfo_pkginfo_h pkginfo;
+
+       if (!strcasecmp(key, "start")) {
+               if (!strcasecmp(val, "uninstall") ||
+                               !strcasecmp(val, "update") ||
+                               !strcasecmp(val, "move"))
+                       __set_blocking(&info);
+
+               g_hash_table_insert(pkg_pending, strdup(pkgid), strdup(val));
+       }
+
+       if (!strcasecmp(key, "error")) {
+               op = g_hash_table_lookup(pkg_pending, pkgid);
+               if (op == NULL)
+                       return 0;
+
+               if (!strcasecmp(op, "uninstall") ||
+                               !strcasecmp(op, "update") ||
+                               !strcasecmp(op, "move"))
+                       __unset_blocking(&info);
+
+               g_hash_table_remove(pkg_pending, pkgid);
+       }
+
+       if (!strcasecmp(key, "end")) {
+               op = g_hash_table_lookup(pkg_pending, pkgid);
+               if (op == NULL)
+                       return 0;
+
+               if (!strcasecmp(op, "uninstall")) {
+                       ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
+                                       info.pkgid, info.target_uid,
+                                       &pkginfo);
+                       if (ret == PMINFO_R_OK) {
+                               pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+                               __unset_blocking(&info);
+                               __appinfo_enable_pkg_apps(info.target_uid,
+                                               info.pkgid, 0);
+                       } else {
+                               __delete_on_event(&info);
+                       }
+                       __update_property(info.target_uid);
+               } else if (!strcasecmp(op, "install")) {
+                       if (!__appinfo_is_pkg_exist(
+                                       info.target_uid,
+                                       info.pkgid)) {
+                               __insert_on_event(&info);
+                       } else {
+                               __unset_blocking(&info);
+                               __appinfo_enable_pkg_apps(info.target_uid,
+                                               info.pkgid, 1);
+                       }
+                       __update_property(info.target_uid);
+               } else if (!strcasecmp(op, "update") ||
+                               !strcasecmp(op, "move")) {
+                       __update_on_event(&info);
+                       __update_property(info.target_uid);
+                       _widget_send_dead_signal_for_update_widget(pkgid);
+                       _app_status_send_fault_dead_for_update_app(pkgid);
+               }
+
+               g_hash_table_remove(pkg_pending, pkgid);
+       }
+
+       return 0;
+}
+
+static void __add_app_event_info(int req_id, int type, uid_t uid)
+{
+       struct app_event_info *info;
+
+       info = (struct app_event_info *)malloc(sizeof(struct app_event_info));
+       if (info == NULL) {
+               _E("Out of memory");
+               return;
+       }
+
+       info->req_id = req_id;
+       info->type = type;
+       info->uid = uid;
+
+       app_event_list = g_list_append(app_event_list, (gpointer)info);
+}
+
+static struct app_event_info *__find_app_event_info(int req_id, uid_t uid)
+{
+       GList *iter;
+       struct app_event_info *info;
+
+       iter = g_list_first(app_event_list);
+       while (iter) {
+               info = (struct app_event_info *)iter->data;
+               if (info && info->req_id == req_id && info->uid == uid)
+                       return info;
+
+               iter = g_list_next(iter);
+       }
+
+       return NULL;
+}
+
+static void __remove_app_event_info(struct app_event_info *info)
+{
+       if (info == NULL)
+               return;
+
+       app_event_list = g_list_remove(app_event_list, info);
+       free(info);
+}
+
+static int __package_app_event_cb(uid_t target_uid, int req_id,
+               const char *pkg_type, const char *pkgid, const char *appid,
+               const char *key, const char *val, const void *pmsg, void *data)
+{
+       struct appinfo *ai;
+       int old;
+       struct app_event_info *ei;
+       uid_t *uids = NULL;
+       int r;
+       int i;
+       struct user_appinfo *info;
+       pkgmgrinfo_appinfo_h handle;
+
+       _D("appid:%s, key:%s, val:%s, req_id: %d, target_uid: %d ", appid, key, val, req_id, target_uid);
+       if (target_uid < REGULAR_UID_MIN) {
+               r = _login_monitor_get_uids(&uids);
+               if (r <= 0)
+                       return 0;
+       } else {
+               r = 1;
+       }
+
+       for (i = 0; i < r; i++) {
+               if (uids)
+                       target_uid = uids[i];
+               ai = _appinfo_find(target_uid, appid);
+
+               if (!strcasecmp(key, "start")) {
+                       if (!strcasecmp(val, "enable_global_app_for_uid") ||
+                                       !strcasecmp(val, "enable_app")) {
+                               if (ai) {
+                                       _appinfo_get_int_value(ai, AIT_ENABLEMENT, &old);
+                                       old |= APP_ENABLEMENT_MASK_REQUEST;
+                                       _appinfo_set_int_value(ai, AIT_ENABLEMENT, old);
+                               }
+                               __add_app_event_info(req_id, AIT_ENABLEMENT, target_uid);
+                       } else if (!strcasecmp(val, "disable_global_app_for_uid") ||
+                                       !strcasecmp(val, "disable_app")) {
+                               __add_app_event_info(req_id, AIT_ENABLEMENT, target_uid);
+                       } else if (!strcasecmp(val, "enable_app_splash_screen")) {
+                               if (ai) {
+                                       _appinfo_get_int_value(ai, AIT_SPLASH_SCREEN_DISPLAY,
+                                                       &old);
+                                       old |= APP_ENABLEMENT_MASK_REQUEST;
+                                       _appinfo_set_int_value(ai, AIT_SPLASH_SCREEN_DISPLAY,
+                                                       old);
+                                       __add_app_event_info(req_id, AIT_SPLASH_SCREEN_DISPLAY, target_uid);
+                               }
+                       } else if (!strcasecmp(val, "disable_app_splash_screen")) {
+                               if (ai)
+                                       __add_app_event_info(req_id, AIT_SPLASH_SCREEN_DISPLAY, target_uid);
+                       }
+               } else if (!strcasecmp(key, "end")) {
+                       ei = __find_app_event_info(req_id, target_uid);
+                       if (ei == NULL)
+                               continue;
+
+                       if (!strcasecmp(val, "ok")) {
+                               if (ei->type == AIT_ENABLEMENT ||
+                                               ei->type == AIT_SPLASH_SCREEN_DISPLAY) {
+                                       if (ai) {
+                                               _appinfo_get_int_value(ai, ei->type, &old);
+                                               old >>= 1;
+                                               _appinfo_set_int_value(ai, ei->type, old);
+                                       } else if (ei->type == AIT_ENABLEMENT) {
+                                               info = __find_user_appinfo(target_uid);
+                                               if (info == NULL) {
+                                                       _E("load appinfo for uid %d failed", target_uid);
+                                                       __remove_app_event_info(ei);
+                                                       continue;
+                                               }
+
+                                               r = pkgmgrinfo_appinfo_get_usr_appinfo(appid, target_uid, &handle);
+                                               if (r != PMINFO_R_OK) {
+                                                       _E("get appinfo failed: %s", appid);
+                                                       __remove_app_event_info(ei);
+                                                       continue;
+                                               }
+
+                                               _D("add the new appinfo");
+                                               __insert_appinfo(handle, info);
+                                               pkgmgrinfo_appinfo_destroy_appinfo(handle);
+                                               __remove_app_event_info(ei);
+                                               continue;
+                                       }
+
+                                       if (ei->type == AIT_ENABLEMENT &&
+                                               !(old & APP_ENABLEMENT_MASK_ACTIVE)) {
+                                               _E("terminate apps: %s", appid);
+                                               _app_status_terminate_apps(appid,
+                                                               target_uid);
+                                       } else if (ei->type == AIT_ENABLEMENT &&
+                                               (old & APP_ENABLEMENT_MASK_ACTIVE)) {
+                                               _launch_start_onboot_app_local(
+                                                               target_uid, appid, ai);
+                                       }
+                               }
+                       } else if (!strcasecmp(val, "fail")) {
+                               if (ei->type == AIT_ENABLEMENT ||
+                                               ei->type == AIT_SPLASH_SCREEN_DISPLAY) {
+                                       if (ai) {
+                                               _appinfo_get_int_value(ai, ei->type, &old);
+                                               old &= APP_ENABLEMENT_MASK_ACTIVE;
+                                               _appinfo_set_int_value(ai, ei->type, old);
+                                       }
+                               }
+                       }
+                       __remove_app_event_info(ei);
+               }
+       }
+
+       free(uids);
+       return 0;
+}
+
+static int __init_package_event_handler(void *data)
+{
+       int ret;
+
+       pc = pkgmgr_client_new(PC_LISTENING);
+       if (pc == NULL)
+               return -1;
+
+       pkgmgr_client_set_status_type(pc, PKGMGR_CLIENT_STATUS_ALL);
+
+       ret = pkgmgr_client_listen_status(pc, __package_event_cb, NULL);
+       if (ret < 0)
+               return -1;
+
+       ret = pkgmgr_client_listen_app_status(pc, __package_app_event_cb, NULL);
+       if (ret < 0)
+               return -1;
+
+       return 0;
+}
+
+static void __fini_package_event_handler(void)
+{
+       pkgmgr_client_free(pc);
+}
+
+int _appinfo_init(void)
+{
+       FILE *fp;
+       char buf[4096] = {0,};
+       char *tmp;
+       char err_buf[1024];
+
+       fp = fopen("/proc/cmdline", "r");
+       if (fp == NULL) {
+               _E("appinfo init failed: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               return -1;
+       }
+
+       if (fgets(buf, sizeof(buf), fp) != NULL) {
+               tmp = strstr(buf, "gles");
+               if (tmp != NULL) {
+                       if (sscanf(tmp, "gles=%d", &gles) != 1)
+                               _D("Failed to convert format");
+               }
+       }
+       fclose(fp);
+
+       user_tbl = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
+                       __free_user_appinfo);
+       if (user_tbl == NULL)
+               return -1;
+
+       pkg_pending = g_hash_table_new_full(g_str_hash, g_str_equal,
+                       free, free);
+       if (pkg_pending == NULL)
+               return -1;
+
+       if (__init_package_event_handler(NULL) < 0)
+               _signal_add_initializer(__init_package_event_handler, NULL);
+
+       return 0;
+}
+
+void _appinfo_fini(void)
+{
+       __fini_package_event_handler();
+       g_hash_table_destroy(user_tbl);
+       g_hash_table_destroy(pkg_pending);
+}
+
+struct appinfo *_appinfo_find(uid_t caller_uid, const char *appid)
+{
+       struct user_appinfo *info;
+
+       if (appid == NULL) {
+               _W("appid is NULL");
+               return NULL;
+       }
+
+       /* search from user table */
+       info = __find_user_appinfo(caller_uid);
+       if (info == NULL)
+               return NULL;
+
+       return g_hash_table_lookup(info->tbl, appid);
+}
+
+int _appinfo_insert(uid_t uid, const char *pkgid)
+{
+       int ret;
+       struct user_appinfo *info;
+       pkgmgrinfo_pkginfo_h handle;
+
+       info = __find_user_appinfo(uid);
+       if (info == NULL) {
+               _E("load appinfo for uid %d failed", uid);
+               return -1;
+       }
+
+       ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
+       if (ret != PMINFO_R_OK) {
+               _E("get pkginfo failed: %s", pkgid);
+               return -1;
+       }
+
+       ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
+                       __insert_appinfo, info, info->uid);
+       if (ret != PMINFO_R_OK) {
+               _E("add appinfo of pkg %s failed", pkgid);
+               pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+               return -1;
+       }
+
+       pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+
+       return 0;
+}
+
+static void __reload_appinfo(gpointer key, gpointer value, gpointer user_data)
+{
+       int r;
+       struct user_appinfo *info = (struct user_appinfo *)value;
+
+       g_hash_table_remove_all(info->tbl);
+
+       r = pkgmgrinfo_appinfo_get_usr_installed_list_full(
+                       __appinfo_insert_handler, info->uid,
+                       PMINFO_APPINFO_GET_SPLASH_SCREEN, info);
+       if (r != PMINFO_R_OK) {
+               __remove_user_appinfo(info->uid);
+               return;
+       }
+
+       _D("reloaded appinfo table for uid %d", info->uid);
+}
+
+void _appinfo_reload(void)
+{
+       g_hash_table_foreach(user_tbl, __reload_appinfo, NULL);
+}
+
+const char *_appinfo_get_value(const struct appinfo *c, enum appinfo_type type)
+{
+       char err_buf[1024];
+
+       if (!c) {
+               errno = EINVAL;
+               _E("appinfo get value: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               return NULL;
+       }
+
+       if (type < AIT_START || type >= AIT_MAX)
+               return NULL;
+
+       return c->val[type];
+}
+
+const void *_appinfo_get_ptr_value(const struct appinfo *c,
+               enum appinfo_type type)
+{
+       char err_buf[1024];
+
+       if (!c) {
+               errno = EINVAL;
+               _E("appinfo get value: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               return NULL;
+       }
+
+       if (type < AIT_START || type >= AIT_MAX)
+               return NULL;
+
+       return c->val[type];
+}
+
+int _appinfo_get_int_value(const struct appinfo *c, enum appinfo_type type,
+               int *val)
+{
+       char err_buf[1024];
+
+       if (!c) {
+               errno = EINVAL;
+               _E("appinfo get value: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               return -1;
+       }
+
+       if (type < AIT_START || type >= AIT_MAX)
+               return -1;
+
+       *val = GPOINTER_TO_INT(c->val[type]);
+
+       return 0;
+}
+
+int _appinfo_get_boolean(const struct appinfo *c, enum appinfo_type type,
+                       bool *val)
+{
+       char err_buf[1024] = {0, };
+
+       if (!c || type < AIT_START || type >= AIT_MAX
+               || c->val[type] == NULL) {
+               errno = EINVAL;
+               _E("appinfo get boolean: %s", strerror_r(errno, err_buf,
+                               sizeof(err_buf)));
+               return -1;
+       }
+
+       if (!strcmp(c->val[type], "true") || !strcmp(c->val[type], "1")) {
+               *val = true;
+       } else if (!strcmp(c->val[type], "false") ||
+               !strcmp(c->val[type], "0")) {
+               *val = false;
+       } else {
+               errno = EINVAL;
+               _E("Unexpected appinfo field value");
+               return -1;
+       }
+       return 0;
+}
+
+int _appinfo_set_value(struct appinfo *c, enum appinfo_type type,
+               const char *val)
+{
+       if (!c || !val) {
+               errno = EINVAL;
+               _E("appinfo is NULL, type: %d, val %s", type, val);
+               return -1;
+       }
+
+       if (type < AIT_START || type >= AIT_MAX)
+               return -1;
+
+       _D("%s : %s : %s", c->val[AIT_NAME], c->val[type], val);
+       if (c->val[type])
+               free(c->val[type]);
+       c->val[type] = strdup(val);
+
+       return 0;
+}
+
+int _appinfo_set_ptr_value(struct appinfo *c, enum appinfo_type type, void *val)
+{
+       if (!c || !val) {
+               errno = EINVAL;
+               _E("appinfo is NULL, type: %d, val %p", type, val);
+               return -1;
+       }
+
+       if (type < AIT_START || type >= AIT_MAX)
+               return -1;
+
+       _D("%s : %p : %p", c->val[AIT_NAME], c->val[type], val);
+       if (appinfo_table[type].destructor && c->val[type] != NULL)
+               appinfo_table[type].destructor(c->val[type]);
+
+       c->val[type] = (char *)val;
+       return 0;
+}
+
+int _appinfo_set_int_value(struct appinfo *c, enum appinfo_type type, int val)
+{
+       if (!c) {
+               errno = EINVAL;
+               _E("appinfo is NULL, type: %d, val %d", type, val);
+               return -1;
+       }
+
+       if (type < AIT_START || type >= AIT_MAX)
+               return -1;
+
+       _D("%s : %p : %p", c->val[AIT_NAME], c->val[type], val);
+
+       c->val[type] = (char *)GINT_TO_POINTER(val);
+       return 0;
+}
+
+struct _cbinfo {
+       appinfo_iter_callback cb;
+       void *cb_data;
+};
+
+static void __iter_cb(gpointer key, gpointer value, gpointer user_data)
+{
+       struct _cbinfo *cbi = user_data;
+
+       if (cbi == NULL)
+               return;
+
+       cbi->cb(cbi->cb_data, key, value);
+}
+
+void _appinfo_foreach(uid_t uid, appinfo_iter_callback cb, void *user_data)
+{
+       struct user_appinfo *info;
+       struct _cbinfo cbi;
+       char err_buf[1024];
+
+       info = __find_user_appinfo(uid);
+       if (info == NULL)
+               return;
+
+       if (!cb) {
+               errno = EINVAL;
+               _E("appinfo foreach: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               return;
+       }
+
+       cbi.cb = cb;
+       cbi.cb_data = user_data;
+
+       g_hash_table_foreach(info->tbl, __iter_cb, &cbi);
+}
+
+int _appinfo_load(uid_t uid)
+{
+       struct user_appinfo *info;
+
+       info = __find_user_appinfo(uid);
+       if (info) {
+               _D("%d appinfo already exists", uid);
+               return 0;
+       }
+
+       info = __add_user_appinfo(uid);
+       if (info == NULL) {
+               _W("Failed to load appinfo - %d", uid);
+               return -1;
+       }
+
+       _D("loaded appinfo table for uid(%d)", uid);
+       return 0;
+}
+
+void _appinfo_unload(uid_t uid)
+{
+       struct user_appinfo *info;
+
+       info = __find_user_appinfo(uid);
+       if (info == NULL) {
+               _D("%d appinfo doesn't exist");
+               return;
+       }
+
+       __remove_user_appinfo(uid);
+       _D("unloaded appinfo table for uid(%d)", uid);
+}
+
+bool _appinfo_is_pkg_updating(const char *pkgid)
+{
+       char *op;
+
+       if (pkg_pending == NULL)
+               return false;
+
+       op = g_hash_table_lookup(pkg_pending, pkgid);
+       if (op != NULL && !strcasecmp(op, "update"))
+               return true;
+
+       return false;
+}
diff --git a/src/amd_cooldown.c b/src/amd_cooldown.c
new file mode 100644 (file)
index 0000000..4de722b
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <aul.h>
+
+#include "amd_util.h"
+#include "amd_app_status.h"
+#include "amd_appinfo.h"
+#include "amd_launch.h"
+#include "amd_login_monitor.h"
+#include "amd_signal.h"
+#include "amd_cooldown.h"
+
+static int cooldown_status;
+
+static void __cooldown_limitaction(app_status_h app_status, void *data)
+{
+       const struct appinfo *ai;
+       const char *taskmanage;
+       const char *cooldown;
+       const char *appid;
+       int app_type;
+       uid_t uid;
+
+       if (_app_status_is_home_app(app_status))
+               return;
+
+       app_type = _app_status_get_app_type(app_status);
+       if (app_type == AT_WIDGET_APP || app_type == AT_WATCH_APP)
+               return;
+
+       uid = _app_status_get_uid(app_status);
+       appid = _app_status_get_appid(app_status);
+       ai = _appinfo_find(uid, appid);
+       if (ai == NULL)
+               return;
+
+       cooldown = _appinfo_get_value(ai, AIT_COOLDOWN);
+       if (cooldown && strcmp(cooldown, "true") != 0) {
+               if (app_type == AT_UI_APP) {
+                       taskmanage = _appinfo_get_value(ai, AIT_TASKMANAGE);
+                       if (taskmanage && strcmp(taskmanage, "true") != 0)
+                               return;
+               }
+
+               _app_status_terminate_apps(appid, uid);
+       }
+}
+
+static void __cooldown_release(void)
+{
+       uid_state state;
+       uid_t *uids;
+       int r;
+       int i;
+
+       r = _login_monitor_get_uids(&uids);
+       if (r <= 0)
+               return;
+
+       for (i = 0; i < r; ++i) {
+               state = _login_monitor_get_uid_state(uids[i]);
+               if (state == UID_STATE_ONLINE || state == UID_STATE_ACTIVE)
+                       _launch_start_onboot_apps(uids[i]);
+       }
+       free(uids);
+}
+
+static int __cooldown_signal_cb(const char *status, void *data)
+{
+       _D("status %s", status);
+       if (strcmp(status, COOLDOWN_STATUS_LIMITACTION) == 0) {
+               cooldown_status = COOLDOWN_LIMIT;
+               _app_status_foreach_running_appinfo(__cooldown_limitaction,
+                       NULL);
+       } else if (strcmp(status, COOLDOWN_STATUS_RELEASE) == 0 &&
+                       cooldown_status != COOLDOWN_RELEASE) {
+               cooldown_status = COOLDOWN_RELEASE;
+               __cooldown_release();
+       }
+
+       return 0;
+}
+
+int _cooldown_get_status(void)
+{
+       return cooldown_status;
+}
+
+int _cooldown_check_mode(const struct appinfo *ai)
+{
+       const char *taskmanage;
+       const char *cooldown;
+       const char *comptype;
+
+       if (cooldown_status != COOLDOWN_LIMIT)
+               return 0;
+
+       cooldown = _appinfo_get_value(ai, AIT_COOLDOWN);
+       if (cooldown && strcmp(cooldown, "true") == 0)
+               return 0;
+
+       comptype = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (comptype == NULL) {
+               _E("Failed to get comptype");
+               return -1;
+       }
+
+       if (strcmp(comptype, APP_TYPE_WIDGET) == 0 ||
+                       strcmp(comptype, APP_TYPE_WATCH) == 0)
+               return 0;
+
+       if (strcmp(comptype, APP_TYPE_UI) == 0) {
+               taskmanage = _appinfo_get_value(ai, AIT_TASKMANAGE);
+               if (taskmanage && strcmp(taskmanage, "false") == 0)
+                       return 0;
+       }
+
+       _W("Cannot launch this app in COOLDOWN mode");
+       return -1;
+}
+
+static int __register_cooldown_signal(void *data)
+{
+       return aul_listen_cooldown_signal(__cooldown_signal_cb, data);
+}
+
+int _cooldown_init(void)
+{
+       int r;
+
+       _D("cooldown init");
+
+       r = __register_cooldown_signal(NULL);
+       if (r < 0) {
+               _W("Failed to register cooldown signal");
+               _signal_add_initializer(__register_cooldown_signal, NULL);
+       }
+
+       return 0;
+}
+
+void _cooldown_fini(void)
+{
+       _D("cooldown fini");
+       aul_listen_cooldown_signal(NULL, NULL);
+}
diff --git a/src/amd_cynara.c b/src/amd_cynara.c
new file mode 100644 (file)
index 0000000..e90d874
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <malloc.h>
+#include <stdlib.h>
+
+#include <cynara-client.h>
+#include <cynara-creds-socket.h>
+#include <cynara-session.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <aul_sock.h>
+#include <aul_svc.h>
+#include <aul_svc_priv_key.h>
+#include <amd_app_com.h>
+#include <amd_request.h>
+#include <amd_appinfo.h>
+#include <aul.h>
+#include <aul_screen_connector.h>
+
+#include "amd_util.h"
+#include "amd_app_status.h"
+#include "amd_widget.h"
+
+#define SYSPOPUP_NAME "_INTERNAL_SYSPOPUP_NAME_"
+#define PRIVILEGE_WIDGET_VIEWER \
+       "http://tizen.org/privilege/widget.viewer"
+#define PRIVILEGE_APPMANAGER_LAUNCH \
+       "http://tizen.org/privilege/appmanager.launch"
+#define PRIVILEGE_APPMANAGER_KILL \
+       "http://tizen.org/privilege/appmanager.kill"
+#define PRIVILEGE_APPMANAGER_KILL_BGAPP \
+       "http://tizen.org/privilege/appmanager.kill.bgapp"
+#define PRIVILEGE_DOWNLOAD \
+       "http://tizen.org/privilege/download"
+#define PRIVILEGE_CALL \
+       "http://tizen.org/privilege/call"
+#define PRIVILEGE_SYSTEM_SETTING \
+       "http://tizen.org/privilege/systemsettings.admin"
+#define PRIVILEGE_PLATFORM \
+       "http://tizen.org/privilege/internal/default/platform"
+
+static cynara *r_cynara;
+
+struct caller_info {
+       char *user;
+       char *client;
+       char *session;
+};
+
+typedef int (*checker_func)(struct caller_info *info, request_h req,
+               void *data);
+
+struct checker_info {
+       int cmd;
+       checker_func checker;
+       void *data;
+};
+
+static const char *__convert_operation_to_privilege(const char *operation)
+{
+       if (operation == NULL)
+               return NULL;
+       else if (!strcmp(operation, AUL_SVC_OPERATION_DOWNLOAD))
+               return PRIVILEGE_DOWNLOAD;
+       else if (!strcmp(operation, AUL_SVC_OPERATION_CALL))
+               return PRIVILEGE_CALL;
+       else if (!strcmp(operation, AUL_SVC_OPERATION_LAUNCH_WIDGET))
+               return PRIVILEGE_WIDGET_VIEWER;
+
+       return NULL;
+}
+
+static void __destroy_caller_info(struct caller_info *info)
+{
+       if (info == NULL)
+               return;
+
+       if (info->client)
+               free(info->client);
+
+       if (info->session)
+               free(info->session);
+
+       if (info->user)
+               free(info->user);
+}
+
+static int __get_caller_info_from_cynara(int sockfd, struct caller_info *info)
+{
+       pid_t pid;
+       int r;
+       char buf[MAX_LOCAL_BUFSZ];
+
+       if (info == NULL)
+               return -1;
+
+       r = cynara_creds_socket_get_pid(sockfd, &pid);
+       if (r != CYNARA_API_SUCCESS) {
+               cynara_strerror(r, buf, MAX_LOCAL_BUFSZ);
+               _E("cynara_creds_socket_get_pid failed: %s", buf);
+               return -1;
+       }
+
+       info->session = cynara_session_from_pid(pid);
+       if (info->session == NULL) {
+               _E("cynara_session_from_pid failed.");
+               return -1;
+       }
+
+       r = cynara_creds_socket_get_user(sockfd, USER_METHOD_DEFAULT,
+                       &(info->user));
+       if (r != CYNARA_API_SUCCESS) {
+               cynara_strerror(r, buf, MAX_LOCAL_BUFSZ);
+               _E("cynara_cred_socket_get_user failed.");
+               return -1;
+       }
+
+       r = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_DEFAULT,
+                       &(info->client));
+       if (r != CYNARA_API_SUCCESS) {
+               cynara_strerror(r, buf, MAX_LOCAL_BUFSZ);
+               _E("cynara_creds_socket_get_client failed.");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __check_privilege(struct caller_info *info, const char *privilege)
+{
+       int ret;
+       char buf[MAX_LOCAL_BUFSZ];
+
+       ret = cynara_check(r_cynara, info->client, info->session, info->user,
+                       privilege);
+       switch (ret) {
+       case CYNARA_API_ACCESS_ALLOWED:
+               _D("%s(%s) from user %s privilege %s allowed.", info->client,
+                               info->session, info->user, privilege);
+               ret = 0;
+               break;
+       case CYNARA_API_ACCESS_DENIED:
+               _E("%s(%s) from user %s privilege %s denied.", info->client,
+                               info->session, info->user, privilege);
+               ret = -1;
+               break;
+       default:
+               cynara_strerror(ret, buf, MAX_LOCAL_BUFSZ);
+               _E("cynara_check failed: %s", buf);
+               ret = -1;
+               break;
+       }
+
+       return ret;
+}
+
+static int __simple_checker(struct caller_info *info, request_h req, void *data)
+{
+       return __check_privilege(info, (const char *)data);
+}
+
+static int __widget_viewer_checker(struct caller_info *info, request_h req,
+               void *data)
+{
+       char *appid = NULL;
+       const char *apptype;
+       struct appinfo *appinfo;
+       bundle *appcontrol = _request_get_bundle(req);
+
+       if (!appcontrol) {
+               _E("wrong argument");
+               return -1;
+       }
+
+       bundle_get_str(appcontrol, AUL_K_APPID, &appid);
+       if (!appid) {
+               _E("can not resolve appid. request denied.");
+               return -1;
+       }
+
+       appinfo = _appinfo_find(_request_get_target_uid(req), appid);
+       if (!appinfo) {
+               _E("can not resolve appinfo of %s. request denied.", appid);
+               return -1;
+       }
+
+       apptype = _appinfo_get_value(appinfo, AIT_COMPTYPE);
+       if (!apptype) {
+               _E("can not resolve apptype of %s. request denied.", appid);
+               return -1;
+       }
+
+       if (!strcmp(apptype, APP_TYPE_WIDGET) ||
+                       !strcmp(apptype, APP_TYPE_WATCH))
+               return __check_privilege(info, PRIVILEGE_WIDGET_VIEWER);
+
+       _E("illegal app type of request: %s - " \
+                       "only widget or watch apps are allowed", apptype);
+
+       return -1;
+}
+
+static int __app_term_by_pid_async_checker(struct caller_info *info,
+               request_h req, void *data)
+{
+       int pid;
+       char *term_pid;
+       bool is_widget = false;
+       bundle *kb;
+
+       kb = _request_get_bundle(req);
+       if (kb == NULL)
+               return -1;
+
+       bundle_get_str(kb, AUL_K_APPID, &term_pid);
+       if (term_pid == NULL)
+               return -1;
+
+       pid = atoi(term_pid);
+       is_widget = _widget_exist(pid, _request_get_target_uid(req));
+
+       if (is_widget)
+               return __check_privilege(info, PRIVILEGE_WIDGET_VIEWER);
+
+       return __simple_checker(info, req, data);
+}
+
+static int __appcontrol_checker(struct caller_info *info, request_h req,
+               void *data)
+{
+       bundle *appcontrol;
+       const char *op_priv = NULL;
+       char *op = NULL;
+       const char *below;
+       const char *syspopup;
+       int ret;
+
+       appcontrol = _request_get_bundle(req);
+       if (appcontrol == NULL)
+               return 0;
+
+       ret = bundle_get_str(appcontrol, AUL_SVC_K_OPERATION, &op);
+       if (ret == BUNDLE_ERROR_NONE)
+               op_priv = __convert_operation_to_privilege(op);
+
+       if (op_priv) {
+               if (!strcmp(op_priv, PRIVILEGE_WIDGET_VIEWER))
+                       return __widget_viewer_checker(info, req, data);
+
+               ret = __check_privilege(info, op_priv);
+               if (ret < 0)
+                       return ret;
+       }
+
+       syspopup = bundle_get_val(appcontrol, SYSPOPUP_NAME);
+       below = bundle_get_val(appcontrol, AUL_SVC_K_RELOCATE_BELOW);
+       if (below || syspopup) {
+               ret = __check_privilege(info, PRIVILEGE_PLATFORM);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return __check_privilege(info, PRIVILEGE_APPMANAGER_LAUNCH);
+}
+
+static int __com_create_checker(struct caller_info *info, request_h req,
+               void *data)
+{
+       char *privilege = NULL;
+       bundle *kb = _request_get_bundle(req);
+
+       bundle_get_str(kb, AUL_K_COM_PRIVILEGE, &privilege);
+       if (!privilege)
+               return 0; /* non-privileged */
+
+       return __check_privilege(info, privilege);
+}
+
+static int __com_join_checker(struct caller_info *info, request_h req,
+               void *data)
+{
+       char *endpoint = NULL;
+       const char *privilege;
+       bundle *kb = _request_get_bundle(req);
+
+       bundle_get_str(kb, AUL_K_COM_ENDPOINT, &endpoint);
+       if (!endpoint)
+               return -1;
+
+       privilege = _app_com_get_privilege(endpoint);
+       if (!privilege)
+               return 0; /* non-privileged */
+
+       return __check_privilege(info, privilege);
+}
+
+static int __label_checker(struct caller_info *info, request_h req,
+               void *data)
+{
+       if (strcmp(info->client, "System::Privileged") == 0)
+               return 0;
+
+       return -1;
+}
+
+static int __screen_connector_checker(struct caller_info *info, request_h req,
+               void *data)
+{
+       int ret;
+       bundle *b = _request_get_bundle(req);
+       const char *type_str;
+       int type;
+
+       if (b == NULL)
+               return -1;
+
+       type_str = bundle_get_val(b, AUL_K_SCREEN_TYPE);
+       if (type_str == NULL)
+               return -1;
+
+       type = atoi(type_str);
+       if (type & AUL_SCREEN_TYPE_UI)
+               ret = __check_privilege(info, PRIVILEGE_PLATFORM);
+       else
+               ret = __check_privilege(info, PRIVILEGE_WIDGET_VIEWER);
+
+       return ret;
+}
+
+static struct checker_info checker_table[] = {
+       {
+               .cmd = APP_OPEN,
+               .checker = __appcontrol_checker,
+               .data = NULL
+       },
+       {
+               .cmd = APP_RESUME,
+               .checker = __appcontrol_checker,
+               .data = NULL
+       },
+       {
+               .cmd = APP_START,
+               .checker = __appcontrol_checker,
+               .data = NULL
+       },
+       {
+               .cmd = APP_START_RES,
+               .checker = __appcontrol_checker,
+               .data = NULL
+       },
+       {
+               .cmd = APP_TERM_BY_PID_WITHOUT_RESTART,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_APPMANAGER_KILL
+       },
+       {
+               .cmd = APP_TERM_BY_PID_ASYNC,
+               .checker = __app_term_by_pid_async_checker,
+               .data = PRIVILEGE_APPMANAGER_KILL
+       },
+       {
+               .cmd = APP_TERM_BY_PID,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_APPMANAGER_KILL
+       },
+       {
+               .cmd = APP_KILL_BY_PID,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_APPMANAGER_KILL
+       },
+       {
+               .cmd = APP_TERM_BGAPP_BY_PID,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_APPMANAGER_KILL_BGAPP
+       },
+       {
+               .cmd = APP_COM_JOIN,
+               .checker = __com_create_checker,
+               .data = NULL
+       },
+       {
+               .cmd = APP_COM_CREATE,
+               .checker = __com_join_checker,
+               .data = NULL
+       },
+       {
+               .cmd = APP_SET_APP_CONTROL_DEFAULT_APP,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_SYSTEM_SETTING
+       },
+       {
+               .cmd = APP_UNSET_APP_CONTROL_DEFAULT_APP,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_SYSTEM_SETTING
+       },
+       {
+               .cmd = APP_START_ASYNC,
+               .checker = __appcontrol_checker,
+               .data = NULL
+       },
+       {
+               .cmd = APP_TERM_BY_PID_SYNC,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_APPMANAGER_KILL
+       },
+       {
+               .cmd = APP_TERM_BY_PID_SYNC_WITHOUT_RESTART,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_APPMANAGER_KILL
+       },
+       {
+               .cmd = APP_UPDATE_RUA_STAT,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_PLATFORM
+       },
+       {
+               .cmd = APP_ADD_HISTORY,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_PLATFORM
+       },
+       {
+               .cmd = APP_REMOVE_HISTORY,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_PLATFORM
+       },
+       {
+               .cmd = APP_SET_ALIAS_APPID,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_SYSTEM_SETTING
+       },
+       {
+               .cmd = APP_UNSET_ALIAS_APPID,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_SYSTEM_SETTING
+       },
+       {
+               .cmd = APP_ENABLE_ALIAS_INFO,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_SYSTEM_SETTING
+       },
+       {
+               .cmd = APP_DISABLE_ALIAS_INFO,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_SYSTEM_SETTING
+       },
+       {
+               .cmd = LAUNCHPAD_LAUNCH_SIGNAL,
+               .checker = __label_checker,
+               .data = NULL
+       },
+       {
+               .cmd = LAUNCHPAD_DEAD_SIGNAL,
+               .checker = __label_checker,
+               .data = NULL
+       },
+       {
+               .cmd = ADD_SCREEN_VIEWER,
+               .checker = __screen_connector_checker,
+               .data = NULL
+       },
+       {
+               .cmd = REMOVE_SCREEN_VIEWER,
+               .checker = __screen_connector_checker,
+               .data = NULL
+       },
+       {
+               .cmd = APP_UPDATE_REQUESTED,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_PLATFORM
+       },
+       {
+               .cmd = APP_WINDOW_ATTACH,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_PLATFORM
+       },
+       {
+               .cmd = APP_WINDOW_DETACH,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_PLATFORM
+       },
+       {
+               .cmd = APP_START_RES_ASYNC,
+               .checker = __appcontrol_checker,
+               .data = NULL
+       },
+       {
+               .cmd = WIDGET_RUNNING_INFO,
+               .checker = __simple_checker,
+               .data = PRIVILEGE_PLATFORM
+       }
+};
+
+static int checker_len = sizeof(checker_table) / sizeof(struct checker_info);
+
+static int __check_privilege_by_checker(request_h req, struct caller_info *info)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < checker_len; i++) {
+               if (checker_table[i].cmd == _request_get_cmd(req)) {
+                       ret = checker_table[i].checker(info, req,
+                                       checker_table[i].data);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int __check_command(int cmd)
+{
+       int i;
+
+       for (i = 0; i < checker_len; i++) {
+               if (checker_table[i].cmd == cmd)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int _cynara_check_privilege(request_h req)
+{
+       int r;
+       struct caller_info info = {NULL, NULL, NULL};
+
+       if (!__check_command(_request_get_cmd(req)))
+               return 0;
+
+       r = __get_caller_info_from_cynara(_request_get_fd(req), &info);
+       if (r < 0) {
+               _E("Failed to get caller info");
+               __destroy_caller_info(&info);
+               return -1;
+       }
+
+       r = __check_privilege_by_checker(req, &info);
+
+       __destroy_caller_info(&info);
+
+       return r;
+}
+
+int _cynara_init(void)
+{
+       int ret;
+
+       ret = cynara_initialize(&r_cynara, NULL);
+       if (ret != CYNARA_API_SUCCESS) {
+               _E("cynara initialize failed.");
+               return ret;
+       }
+
+       return 0;
+}
+
+void _cynara_finish(void)
+{
+       if (r_cynara == NULL)
+               return;
+
+       cynara_finish(r_cynara);
+       r_cynara = NULL;
+}
+
diff --git a/src/amd_extractor.c b/src/amd_extractor.c
new file mode 100644 (file)
index 0000000..c9b4427
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2016 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 <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <aul.h>
+#include <bundle_internal.h>
+#include <tzplatform_config.h>
+
+#include "amd_util.h"
+#include "amd_signal.h"
+#include "amd_app_status.h"
+#include "amd_extractor.h"
+
+#define PATH_APP_ROOT tzplatform_getenv(TZ_USER_APP)
+#define PATH_GLOBAL_APP_RO_ROOT tzplatform_getenv(TZ_SYS_RO_APP)
+#define PATH_GLOBAL_APP_RW_ROOT tzplatform_getenv(TZ_SYS_RW_APP)
+
+static GHashTable *mount_point_hash;
+
+static const char *__get_app_root_path(const struct appinfo *ai)
+{
+       const char *path_app_root;
+       const char *global;
+       const char *preload;
+
+       preload = _appinfo_get_value(ai, AIT_PRELOAD);
+       global = _appinfo_get_value(ai, AIT_GLOBAL);
+       if (global && strncmp(global, "true", strlen("true")) == 0) {
+               if (preload && strncmp(preload, "true", strlen("true")) == 0)
+                       path_app_root = PATH_GLOBAL_APP_RO_ROOT;
+               else
+                       path_app_root = PATH_GLOBAL_APP_RW_ROOT;
+       } else {
+               path_app_root = PATH_APP_ROOT;
+       }
+
+       return path_app_root;
+}
+
+char **_extractor_mountable_get_tep_paths(const struct appinfo *ai)
+{
+       char tep_path[PATH_MAX];
+       char **mnt_path;
+       const char *pkgid;
+       const char *tep_name;
+
+       if (ai == NULL)
+               return NULL;
+
+       pkgid = _appinfo_get_value(ai, AIT_PKGID);
+       if (pkgid == NULL)
+               return NULL;
+
+       tep_name = _appinfo_get_value(ai, AIT_TEP);
+       if (tep_name == NULL)
+               return NULL;
+
+       mnt_path = (char **)malloc(sizeof(char *) * 2);
+       if (mnt_path == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       mnt_path[1] = strdup(tep_name);
+       snprintf(tep_path, PATH_MAX, "%s/%s/tep/mount",
+                       __get_app_root_path(ai), pkgid);
+       mnt_path[0] = strdup(tep_path);
+
+       return mnt_path;
+}
+
+char **_extractor_mountable_get_tpk_paths(const struct appinfo *ai)
+{
+       char mount_point[PATH_MAX];
+       char **mnt_path;
+       const char *pkgid;
+       const char *tpk;
+
+       if (ai == NULL)
+               return NULL;
+
+       pkgid = _appinfo_get_value(ai, AIT_PKGID);
+       if (pkgid == NULL)
+               return NULL;
+
+       tpk = _appinfo_get_value(ai, AIT_MOUNTABLE_PKG);
+       if (tpk == NULL)
+               return NULL;
+
+       mnt_path = (char **)malloc(sizeof(char *) * 2);
+       if (mnt_path == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       mnt_path[1] = strdup(tpk);
+       snprintf(mount_point, PATH_MAX, "%s/%s/.pkg",
+                               __get_app_root_path(ai), pkgid);
+       mnt_path[0] = strdup(mount_point);
+
+       return mnt_path;
+}
+
+static void __free_path(char **path, int cnt)
+{
+       int i;
+
+       if (path == NULL)
+               return;
+
+       for (i = 0; i < cnt; i++) {
+               if (path[i])
+                       free(path[i]);
+       }
+       free(path);
+}
+
+static void __free_set(gpointer data)
+{
+       g_hash_table_destroy((GHashTable *)data);
+}
+
+static void __prepare_map(void)
+{
+       if (mount_point_hash == NULL) {
+               mount_point_hash = g_hash_table_new_full(g_str_hash,
+                               g_str_equal, free, __free_set);
+       }
+}
+
+static void __put_mount_path(const struct appinfo *ai, const char *str)
+{
+       const char *appid;
+       GHashTable *set;
+
+       __prepare_map();
+       set = g_hash_table_lookup(mount_point_hash, str);
+       if (set == NULL) {
+               set = g_hash_table_new_full(g_str_hash, g_str_equal,
+                               free, NULL);
+               if (set == NULL)
+                       return;
+               g_hash_table_insert(mount_point_hash, strdup(str), set);
+       }
+
+       appid = _appinfo_get_value(ai, AIT_NAME);
+       g_hash_table_insert(set, strdup(appid), NULL);
+}
+
+static bool __is_unmountable(const char *appid, const char *key)
+{
+       GHashTable *set;
+
+       if (_app_status_get_process_cnt(appid) > 1)
+               return false;
+
+       __prepare_map();
+       set  = g_hash_table_lookup(mount_point_hash, key);
+
+       if (set == NULL)
+               return false;
+
+       g_hash_table_remove(set, appid);
+       if (g_hash_table_size(set) > 0)
+               return false;
+
+       return true;
+}
+
+void _extractor_mount(const struct appinfo *ai, bundle *kb,
+               _extractor_mountable mountable)
+{
+       int ret;
+       const char **array = NULL;
+       int len = 0;
+       const char *default_array[1] = { NULL };
+       char **new_array = NULL;
+       int i;
+       bool dup = false;
+       const char *pkgid = NULL;
+       char **mnt_path;
+
+       mnt_path = mountable(ai);
+       if (mnt_path == NULL)
+               return;
+
+       if (!mnt_path[0] || !mnt_path[1]) {
+               __free_path(mnt_path, 2);
+               return;
+       }
+
+       array = bundle_get_str_array(kb, AUL_TEP_PATH, &len);
+       if (array == NULL) {
+               default_array[0] = mnt_path[0];
+               bundle_add_str_array(kb, AUL_TEP_PATH,
+                                    default_array, 1);
+       } else {
+               for (i = 0; i < len; i++) {
+                       if (strcmp(mnt_path[0], array[i]) == 0) {
+                               dup = true;
+                               break;
+                       }
+               }
+
+               if (!dup) {
+                       new_array = malloc(sizeof(char *) * (len + 1));
+                       if (new_array == NULL) {
+                               _E("out of memory");
+                               __free_path(mnt_path, 2);
+                               return;
+                       }
+
+                       for (i = 0; i < len; i++)
+                               new_array[i] = strdup(array[i]);
+                       new_array[len] = strdup(mnt_path[0]);
+                       bundle_del(kb, AUL_TEP_PATH);
+                       bundle_add_str_array(kb, AUL_TEP_PATH,
+                                       (const char **)new_array, len + 1);
+                       __free_path(new_array, len + 1);
+               }
+       }
+
+       __put_mount_path(ai, mnt_path[0]);
+       ret = aul_is_tep_mount_dbus_done(mnt_path[0]);
+       if (ret != 1) {
+               pkgid = _appinfo_get_value(ai, AIT_PKGID);
+               ret = _signal_send_tep_mount(mnt_path, pkgid);
+               if (ret < 0) {
+                       _E("dbus error %d", ret);
+               } else {
+                       _D("Mount request was sent %s %s",
+                                       mnt_path[0], mnt_path[1]);
+               }
+       }
+
+       __free_path(mnt_path, 2);
+}
+
+void _extractor_unmount(int pid, _extractor_mountable mountable)
+{
+       const char *appid;
+       const struct appinfo *ai;
+       int ret;
+       char **mnt_path;
+       app_status_h app_status;
+       uid_t uid;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return;
+
+       uid = _app_status_get_uid(app_status);
+       appid = _app_status_get_appid(app_status);
+       if (appid == NULL)
+               return;
+
+       ai = _appinfo_find(uid, appid);
+       if (ai == NULL)
+               return;
+
+       mnt_path = mountable(ai);
+       if (mnt_path == NULL)
+               return;
+
+       if (!__is_unmountable(appid, mnt_path[0]))
+               return;
+
+       g_hash_table_remove(mount_point_hash, mnt_path[0]);
+       ret = _signal_send_tep_unmount(mnt_path[0]);
+       if (ret < 0)
+               _E("Failed to send unmount: %s", mnt_path[0]);
+       else
+               _D("Unmount request was sent %s", mnt_path[0]);
+
+       __free_path(mnt_path, 2);
+}
diff --git a/src/amd_inotify.c b/src/amd_inotify.c
new file mode 100644 (file)
index 0000000..edfefc9
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/inotify.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "amd_util.h"
+#include "amd_inotify.h"
+
+#define INOTIFY_BUF (1024 * ((sizeof(struct inotify_event)) + 16))
+
+struct inotify_watch_info {
+       int wd;
+       inotify_watch_cb cb;
+       void *data;
+};
+
+struct inotify_info {
+       int fd;
+       GIOChannel *io;
+       guint id;
+       bool initialized;
+};
+
+static struct inotify_info __inotify;
+static GList *__watch_list;
+
+static void __destroy_inotify_watch_info(gpointer data)
+{
+       struct inotify_watch_info *info = (struct inotify_watch_info *)data;
+
+       if (info == NULL)
+               return;
+
+       if (info->wd > 0)
+               inotify_rm_watch(__inotify.fd, info->wd);
+       free(info);
+}
+
+static struct inotify_watch_info *__create_inotify_watch_info(const char *path,
+               uint32_t mask, inotify_watch_cb cb, void *data)
+{
+       struct inotify_watch_info *info;
+
+       info = calloc(1, sizeof(struct inotify_watch_info));
+       if (info == NULL) {
+               _E("Out of memory");
+               return NULL;
+       }
+
+       info->wd = inotify_add_watch(__inotify.fd, path, mask);
+       if (info->wd < 0) {
+               _E("Failed to add inotify watch, path(%s), errno(%d)",
+                               path, errno);
+               free(info);
+               return NULL;
+       }
+
+       info->cb = cb;
+       info->data = data;
+
+       return info;
+}
+
+static void __fini_inotify(void)
+{
+       if (__inotify.id) {
+               g_source_remove(__inotify.id);
+               __inotify.id = 0;
+       }
+
+       if (__inotify.io) {
+               g_io_channel_unref(__inotify.io);
+               __inotify.io = NULL;
+       }
+
+       if (__inotify.fd > 0) {
+               close(__inotify.fd);
+               __inotify.fd = 0;
+       }
+
+       __inotify.initialized = false;
+}
+
+static struct inotify_watch_info *__find_inotify_watch_info(int wd)
+{
+       struct inotify_watch_info *info;
+       GList *iter;
+
+       iter = __watch_list;
+       while (iter) {
+               info = (struct inotify_watch_info *)iter->data;
+               if (info->wd == wd)
+                       return info;
+
+               iter = g_list_next(iter);
+       }
+
+       return NULL;
+}
+
+static gboolean __inotify_watch_cb(GIOChannel *io, GIOCondition cond,
+               gpointer data)
+{
+       char buf[INOTIFY_BUF];
+       ssize_t len;
+       int i = 0;
+       struct inotify_event *e;
+       int fd = g_io_channel_unix_get_fd(io);
+       struct inotify_watch_info *info;
+
+       len = read(fd, buf, sizeof(buf));
+       if (len < 0) {
+               _W("Failed to read from a inotify file descriptor");
+               return G_SOURCE_CONTINUE;
+       }
+
+       while (i < len) {
+               e = (struct inotify_event *)&buf[i];
+               if (e->len) {
+                       info = __find_inotify_watch_info(e->wd);
+                       if (info && !info->cb(e->name, info->data)) {
+                               __watch_list = g_list_remove(__watch_list,
+                                               info);
+                               __destroy_inotify_watch_info(info);
+                       }
+               }
+
+               i += offsetof(struct inotify_event, name) + e->len;
+               if (i >= INOTIFY_BUF)
+                       break;
+       }
+
+       return G_SOURCE_CONTINUE;
+}
+
+static int __init_inotify(void)
+{
+       GIOCondition cond = G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP;
+
+       if (__inotify.initialized)
+               return 0;
+
+       __inotify.fd = inotify_init1(IN_CLOEXEC);
+       if (__inotify.fd < 0) {
+               _E("Failed to initialize inotify");
+               return -1;
+       }
+
+       __inotify.io = g_io_channel_unix_new(__inotify.fd);
+       if (__inotify.io == NULL) {
+               _E("Failed to create a new GIOChannel");
+               __fini_inotify();
+               return -1;
+       }
+
+       __inotify.id = g_io_add_watch(__inotify.io, cond,
+                       __inotify_watch_cb, NULL);
+       if (__inotify.id == 0) {
+               _E("Failed to add GIOChannel watch");
+               __fini_inotify();
+               return -1;
+       }
+
+       __inotify.initialized = true;
+
+       return 0;
+}
+
+int _inotify_add_watch(const char *path, uint32_t mask,
+               inotify_watch_cb callback, void *data)
+{
+       struct inotify_watch_info *info;
+
+       if (path == NULL || callback == NULL) {
+               _E("Invalid parameter");
+               return -1;
+       }
+
+       if (__init_inotify() < 0)
+               return -1;
+
+       info = __create_inotify_watch_info(path, mask, callback, data);
+       if (info == NULL)
+               return -1;
+
+       __watch_list = g_list_append(__watch_list, info);
+
+       return info->wd;
+}
+
+void _inotify_rm_watch(int wd)
+{
+       struct inotify_watch_info *info;
+
+       info = __find_inotify_watch_info(wd);
+       if (!info)
+               return;
+
+       __watch_list = g_list_remove(__watch_list, info);
+       __destroy_inotify_watch_info(info);
+}
+
+int _inotify_init(void)
+{
+       _D("inotify init");
+
+       __init_inotify();
+
+       return 0;
+}
+
+void _inotify_fini(void)
+{
+       _D("inotify fini");
+
+       if (__watch_list)
+               g_list_free_full(__watch_list, __destroy_inotify_watch_info);
+
+       __fini_inotify();
+}
diff --git a/src/amd_input.c b/src/amd_input.c
new file mode 100644 (file)
index 0000000..8f5c3b5
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdbool.h>
+#include <malloc.h>
+#include <sys/mman.h>
+
+#include <glib.h>
+#include <aul.h>
+#include <wayland-client.h>
+#include <tizen-extension-client-protocol.h>
+#include <xkbcommon/xkbcommon.h>
+
+#include "amd_util.h"
+#include "amd_input.h"
+#include "amd_wayland.h"
+
+#define TIMEOUT_VAL 1000
+
+static bool listener_added;
+static bool locked;
+static bool init_done;
+static guint timer;
+static struct tizen_keyrouter *keyrouter;
+static struct tizen_input_device_manager *input_devmgr;
+static struct wl_display *display;
+static struct wl_seat *seat;
+struct xkb_context *g_ctx;
+struct xkb_keymap *g_keymap;
+struct wl_keyboard *keyboard;
+
+typedef struct _keycode_map {
+       xkb_keysym_t keysym;
+       xkb_keycode_t *keycodes;
+       int nkeycodes;
+} keycode_map;
+
+static void __keyboard_keymap(void *data, struct wl_keyboard *keyboard,
+               uint32_t format, int fd, uint32_t size)
+{
+       char *map = NULL;
+
+       _D("format=%d, fd=%d, size=%d", format, fd, size);
+       if (!g_ctx) {
+               _E("This client failed to make xkb context");
+               close(fd);
+               return;
+       }
+
+       if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
+               _E("Invaild format: %d", format);
+               close(fd);
+               return;
+       }
+
+       map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+       if (map == MAP_FAILED) {
+               _E("Failed to mmap from fd(%d) size(%d)", fd, size);
+               close(fd);
+               return;
+       }
+
+       g_keymap = xkb_map_new_from_string(g_ctx, map,
+                       XKB_KEYMAP_FORMAT_TEXT_V1, 0);
+       munmap(map, size);
+       if (!g_keymap)
+               _E("Failed to get keymap from fd(%d)", fd);
+       close(fd);
+}
+
+static void __keyboard_enter(void *data, struct wl_keyboard *keyboard,
+               uint32_t serial, struct wl_surface *surface,
+               struct wl_array *keys)
+{
+       _D("serial=%d", serial);
+}
+
+static void __keyboard_leave(void *data, struct wl_keyboard *keyboard,
+               uint32_t serial, struct wl_surface *surface)
+{
+       _D("serial=%d", serial);
+}
+
+static void __keyboard_key(void *data, struct wl_keyboard *keyboard,
+               uint32_t serial, uint32_t time, uint32_t key, uint32_t state_w)
+{
+       _D("serial=%d, time=%d, key=%d, state_w=%d",
+                       serial, time, key, state_w);
+}
+
+static void __keyboard_modifiers(void *data, struct wl_keyboard *keyboard,
+               uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
+               uint32_t mods_locked, uint32_t group)
+{
+       _D("serial=%d, mods_depressed=%d, mods_latched=%d mods_locked=%d, " \
+                       "group=%d", serial, mods_depressed, mods_latched,
+                       mods_locked, group);
+}
+
+static const struct wl_keyboard_listener keyboard_listener = {
+       .keymap = __keyboard_keymap,
+       .enter = __keyboard_enter,
+       .leave = __keyboard_leave,
+       .key = __keyboard_key,
+       .modifiers = __keyboard_modifiers
+};
+
+static void __global_registry_handler(void *data, struct wl_registry *registry,
+               uint32_t id, const char *interface, uint32_t version)
+{
+       if (interface == NULL)
+               return;
+
+       if (strcmp(interface, "tizen_input_device_manager") == 0) {
+               if (!input_devmgr) {
+                       input_devmgr = wl_registry_bind(registry, id,
+                                       &tizen_input_device_manager_interface,
+                                       1);
+                       _D("input_devmgr = %p", input_devmgr);
+               }
+       } else if (strcmp(interface, "tizen_keyrouter") == 0) {
+               if (!keyrouter) {
+                       keyrouter = wl_registry_bind(registry, id,
+                                       &tizen_keyrouter_interface, 1);
+                       _D("keyrouter = %p", keyrouter);
+               }
+       } else if (strcmp(interface, "wl_seat") == 0) {
+               if (!seat) {
+                       seat = wl_registry_bind(registry, id,
+                                       &wl_seat_interface, 1);
+                       if (!seat)
+                               return;
+
+                       _D("Succeed to bind wl_seat_interface!");
+                       keyboard = wl_seat_get_keyboard(seat);
+                       wl_keyboard_add_listener(keyboard, &keyboard_listener,
+                                       NULL);
+                       _D("keyboard = %p", keyboard);
+               }
+       }
+}
+
+static void __global_registry_remover(void *data, struct wl_registry *registry,
+               uint32_t id)
+{
+       if (keyrouter) {
+               tizen_keyrouter_destroy(keyrouter);
+               keyrouter = NULL;
+       }
+
+       if (input_devmgr) {
+               tizen_input_device_manager_destroy(input_devmgr);
+               input_devmgr = NULL;
+       }
+
+       if (keyboard) {
+               wl_keyboard_destroy(keyboard);
+               keyboard = NULL;
+       }
+}
+
+static struct wl_registry_listener registry_listener = {
+       __global_registry_handler,
+       __global_registry_remover
+};
+
+static gboolean __timeout_handler(void *data)
+{
+       timer = 0;
+       _input_unlock();
+       return FALSE;
+}
+
+static void __find_keycode(struct xkb_keymap *keymap, xkb_keycode_t key,
+               void *data)
+{
+       keycode_map *found_keycodes = (keycode_map *)data;
+       xkb_keysym_t keysym = found_keycodes->keysym;
+       int nsyms = 0;
+       const xkb_keysym_t *syms_out = NULL;
+
+       nsyms = xkb_keymap_key_get_syms_by_level(keymap, key, 0, 0, &syms_out);
+       if (nsyms && syms_out && *syms_out == keysym) {
+               found_keycodes->nkeycodes++;
+               found_keycodes->keycodes = realloc(found_keycodes->keycodes,
+                               sizeof(int) * found_keycodes->nkeycodes);
+               found_keycodes->keycodes[found_keycodes->nkeycodes - 1] = key;
+       }
+}
+
+static int __xkb_keycode_from_keysym(struct xkb_keymap *keymap,
+               xkb_keysym_t keysym, xkb_keycode_t **keycodes)
+{
+       keycode_map found_keycodes = {0,};
+
+       found_keycodes.keysym = keysym;
+       xkb_keymap_key_for_each(g_keymap, __find_keycode, &found_keycodes);
+       *keycodes = found_keycodes.keycodes;
+
+       return found_keycodes.nkeycodes;
+}
+
+static void __keygrab_request(struct tizen_keyrouter *tizen_keyrouter,
+               struct wl_surface *surface, uint32_t key, uint32_t mode)
+{
+       tizen_keyrouter_set_keygrab(tizen_keyrouter, surface, key, mode);
+       _D("request set_keygrab (key:%d, mode:%d)!", key, mode);
+}
+
+static void __keyungrab_request(struct tizen_keyrouter *tizen_keyrouter,
+               struct wl_surface *surface, uint32_t key)
+{
+       tizen_keyrouter_unset_keygrab(tizen_keyrouter, surface, key);
+       _D("request unset_keygrab (key:%d)!", key);
+}
+
+static void __do_keygrab(const char *keyname, uint32_t mode)
+{
+       xkb_keysym_t keysym = 0x0;
+       int nkeycodes = 0;
+       xkb_keycode_t *keycodes = NULL;
+       int i;
+
+       keysym = xkb_keysym_from_name(keyname, XKB_KEYSYM_NO_FLAGS);
+       nkeycodes = __xkb_keycode_from_keysym(g_keymap, keysym, &keycodes);
+
+       for (i = 0; i < nkeycodes; i++) {
+               _D("%s's keycode is %d (nkeycode: %d)",
+                               keyname, keycodes[i], nkeycodes);
+               __keygrab_request(keyrouter, NULL, keycodes[i], mode);
+       }
+       free(keycodes);
+       keycodes = NULL;
+}
+
+static void __do_keyungrab(const char *keyname)
+{
+       xkb_keysym_t keysym = 0x0;
+       int nkeycodes = 0;
+       xkb_keycode_t *keycodes = NULL;
+       int i;
+
+       keysym = xkb_keysym_from_name(keyname, XKB_KEYSYM_NO_FLAGS);
+       nkeycodes = __xkb_keycode_from_keysym(g_keymap, keysym, &keycodes);
+
+       for (i = 0; i < nkeycodes; i++) {
+               _D("%s's keycode is %d (nkeycode: %d)\n",
+                               keyname, keycodes[i], nkeycodes);
+               __keyungrab_request(keyrouter, NULL, keycodes[i]);
+       }
+       free(keycodes);
+       keycodes = NULL;
+}
+
+static int __xkb_init(void)
+{
+       if (!g_ctx) {
+               g_ctx = xkb_context_new(0);
+               if (!g_ctx) {
+                       _E("Failed to get xkb_context");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static void __xkb_fini(void)
+{
+       if (g_ctx) {
+               xkb_context_unref(g_ctx);
+               g_ctx = NULL;
+       }
+}
+
+static void __input_device_info(void *data,
+               struct tizen_input_device *tizen_input_device,
+               const char *name, uint32_t class, uint32_t subclass,
+               struct wl_array *axes)
+{
+       _D("device info - name: %s, class: %d, subclass: %d",
+                       name, class, subclass);
+}
+
+static void __input_device_event_device(void *data,
+               struct tizen_input_device *tizen_input_device,
+               unsigned int serial, const char *name, uint32_t time)
+{
+       _D("event device - name: %s, time: %d", name, time);
+}
+
+static void __input_device_axis(void *data,
+               struct tizen_input_device *tizen_input_device,
+               uint32_t axis_type, wl_fixed_t value)
+{
+       _D("axis - axis_type: %d, value: %lf",
+                       axis_type, wl_fixed_to_double(value));
+}
+
+static const struct tizen_input_device_listener input_device_listener = {
+       __input_device_info,
+       __input_device_event_device,
+       __input_device_axis,
+};
+
+static void __cb_device_add(void *data,
+               struct tizen_input_device_manager *tizen_input_device_manager,
+               uint32_t serial, const char *name,
+               struct tizen_input_device *device, struct wl_seat *seat)
+{
+       _D("device is added!", name);
+       tizen_input_device_add_listener(device, &input_device_listener, NULL);
+}
+
+static void __cb_device_remove(void *data,
+               struct tizen_input_device_manager *tizen_input_device_manager,
+               uint32_t serial, const char *name,
+               struct tizen_input_device *device, struct wl_seat *seat)
+{
+       _D("%s device is removed!", name);
+       tizen_input_device_destroy(device);
+}
+
+static void __cb_error(void *data,
+               struct tizen_input_device_manager *tizen_input_device_manager,
+               uint32_t errorcode)
+{
+       _E("error: %d", errorcode);
+}
+
+static void __cb_block_expired(void *data,
+               struct tizen_input_device_manager *tizen_input_device_manager)
+{
+       _D("block expired");
+}
+
+static struct tizen_input_device_manager_listener input_devmgr_listener = {
+       __cb_device_add,
+       __cb_device_remove,
+       __cb_error,
+       __cb_block_expired
+};
+
+int _input_init(void)
+{
+       if (!listener_added) {
+               _wayland_add_registry_listener(&registry_listener, NULL);
+               listener_added = true;
+       }
+
+       if (!display) {
+               display = _wayland_get_display();
+               if (!display) {
+                       _E("Failed to connect to wayland compositor");
+                       return -1;
+               }
+       }
+
+       if (__xkb_init() < 0)
+               return -1;
+
+       _D("Connected to wayland compositor!");
+
+       if (input_devmgr == NULL) {
+               _E("input_devmgr is null");
+               return -1;
+       }
+
+       if (keyrouter == NULL) {
+               _E("keyrouter is null");
+               return -1;
+       }
+
+       if (seat == NULL) {
+               _E("seat is null");
+               return -1;
+       }
+
+       if (keyboard == NULL) {
+               _E("keyboard is null");
+               return -1;
+       }
+
+       if (tizen_input_device_manager_add_listener(input_devmgr,
+               &input_devmgr_listener, NULL) < 0) {
+               _E("Failed to add listener");
+       }
+       wl_display_flush(display);
+       wl_display_roundtrip(display);
+
+       if (g_keymap == NULL) {
+               _E("g_keymap is null");
+               return -1;
+       }
+
+       init_done = true;
+
+       return 0;
+}
+
+int _input_fini(void)
+{
+       __xkb_fini();
+
+       return 0;
+}
+
+int _input_lock(void)
+{
+       if (locked)
+               _input_unlock();
+
+       if (!init_done && _input_init() < 0)
+               return -1;
+
+       _D("call tizen_input_device_manager_block_events");
+       tizen_input_device_manager_block_events(input_devmgr, 0,
+               TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN |
+               TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE, TIMEOUT_VAL);
+       timer = g_timeout_add(TIMEOUT_VAL, __timeout_handler, NULL);
+       __do_keygrab("XF86Back", TIZEN_KEYROUTER_MODE_EXCLUSIVE);
+       wl_display_roundtrip(display);
+
+       locked = true;
+
+       return 0;
+}
+
+int _input_unlock(void)
+{
+       if (!locked)
+               return 0;
+
+       if (!init_done && _input_init() < 0)
+               return -1;
+
+       _D("call tizen_input_device_manager_unblock_events");
+       tizen_input_device_manager_unblock_events(input_devmgr, 0);
+       __do_keyungrab("XF86Back");
+       wl_display_roundtrip(display);
+
+       locked = false;
+       if (timer > 0) {
+               g_source_remove(timer);
+               timer = 0;
+       }
+
+       return 0;
+}
+
diff --git a/src/amd_launch.c b/src/amd_launch.c
new file mode 100644 (file)
index 0000000..d59453c
--- /dev/null
@@ -0,0 +1,1983 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <signal.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <aul.h>
+#include <glib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/prctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pkgmgr-info.h>
+#include <poll.h>
+#include <tzplatform_config.h>
+#include <cert-svc/ccert.h>
+#include <cert-svc/cinstance.h>
+#include <aul_sock.h>
+#include <aul_svc.h>
+#include <aul_svc_priv_key.h>
+#include <ttrace.h>
+#include <app2ext_interface.h>
+#include <vconf.h>
+#include <system_info.h>
+
+#include "amd_launch.h"
+#include "amd_appinfo.h"
+#include "amd_app_status.h"
+#include "amd_app_group.h"
+#include "amd_util.h"
+#include "app_signal.h"
+#include "amd_socket.h"
+#include "amd_share.h"
+#include "amd_app_com.h"
+#include "amd_splash_screen.h"
+#include "amd_input.h"
+#include "amd_suspend.h"
+#include "amd_signal.h"
+#include "amd_extractor.h"
+#include "amd_app_property.h"
+#include "amd_cooldown.h"
+#include "amd_widget.h"
+#include "amd_screen_connector.h"
+#include "amd_rua.h"
+
+#define DAC_ACTIVATE
+
+#define TERM_WAIT_SEC 3
+#define INIT_PID 1
+
+#define AUL_PR_NAME 16
+#define OSP_K_LAUNCH_TYPE "__OSP_LAUNCH_TYPE__"
+#define OSP_V_LAUNCH_TYPE_DATACONTROL "datacontrol"
+#define APP_CONTROL_OPERATION_MAIN "http://tizen.org/appcontrol/operation/main"
+
+struct launch_s {
+       const char *appid;
+       const struct appinfo *ai;
+       const char *instance_id;
+       int pid;
+       int leader_pid;
+       bool can_attach;
+       bool new_process;
+       bool is_subapp;
+       app_group_launch_mode launch_mode;
+       int prelaunch_attr;
+       int bg_category;
+       int bg_allowed;
+       shared_info_h share_info;
+       bool bg_launch;
+       bool new_instance;
+       app_status_h app_status;
+       bool debug_mode;
+};
+
+struct fgmgr {
+       guint tid;
+       int pid;
+};
+
+static GList *_fgmgr_list;
+static int __pid_of_last_launched_ui_app;
+static int __focused_pid;
+
+static void __set_reply_handler(int fd, int pid, request_h req, int cmd);
+static int __nofork_processing(int cmd, int pid, bundle *kb, request_h req);
+extern void _cleanup_dead_info(app_status_h app_status);
+
+typedef enum {
+       TIZEN_PROFILE_UNKNOWN = 0,
+       TIZEN_PROFILE_MOBILE = 0x1,
+       TIZEN_PROFILE_WEARABLE = 0x2,
+       TIZEN_PROFILE_TV = 0x4,
+       TIZEN_PROFILE_IVI = 0x8,
+       TIZEN_PROFILE_COMMON = 0x10,
+} tizen_profile_t;
+
+static tizen_profile_t __get_tizen_profile(void)
+{
+       static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
+       char *profile_name = NULL;
+
+       if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
+               return profile;
+
+       system_info_get_platform_string("http://tizen.org/feature/profile",
+                       &profile_name);
+       if (profile_name == NULL)
+               return profile;
+
+       switch (*profile_name) {
+       case 'm':
+       case 'M':
+               profile = TIZEN_PROFILE_MOBILE;
+               break;
+       case 'w':
+       case 'W':
+               profile = TIZEN_PROFILE_WEARABLE;
+               break;
+       case 't':
+       case 'T':
+               profile = TIZEN_PROFILE_TV;
+               break;
+       case 'i':
+       case 'I':
+               profile = TIZEN_PROFILE_IVI;
+               break;
+       default: /* common or unknown ==> ALL ARE COMMON. */
+               profile = TIZEN_PROFILE_COMMON;
+               break;
+       }
+       free(profile_name);
+
+       return profile;
+}
+
+static void __set_stime(bundle *kb)
+{
+       struct timeval tv;
+       char tmp[MAX_LOCAL_BUFSZ];
+
+       gettimeofday(&tv, NULL);
+       snprintf(tmp, MAX_LOCAL_BUFSZ, "%ld/%ld", tv.tv_sec, tv.tv_usec);
+       bundle_add(kb, AUL_K_STARTTIME, tmp);
+}
+
+int _launch_start_app_local_with_bundle(uid_t uid, const char *appid,
+               bundle *kb)
+{
+       request_h req;
+       int r;
+       bool dummy;
+       bool dummy_mode;
+
+       __set_stime(kb);
+       bundle_add(kb, AUL_K_APPID, appid);
+       req = _request_create_local(APP_START, uid, getpid(), kb);
+       if (req == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       r = _launch_start_app(appid, req, &dummy, &dummy_mode, false);
+       _request_free_local(req);
+
+       return r;
+}
+
+int _launch_start_app_local(uid_t uid, const char *appid)
+{
+       int pid;
+       bundle *kb;
+
+       kb = bundle_create();
+       if (kb == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       pid = _launch_start_app_local_with_bundle(uid, appid, kb);
+       bundle_free(kb);
+
+       return pid;
+}
+
+int _launch_start_onboot_app_local(uid_t uid, const char *appid,
+               struct appinfo *ai)
+{
+       int ret = -1;
+       int enable = 1;
+       app_status_h app_status;
+       const char *comp_type;
+       const char *onboot;
+
+       if (appid == NULL || ai == NULL)
+               return -1;
+
+       comp_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (comp_type == NULL || strcmp(comp_type, APP_TYPE_SERVICE) != 0)
+               return -1;
+
+       onboot = _appinfo_get_value(ai, AIT_ONBOOT);
+       if (onboot == NULL || strcmp(onboot, "true") != 0)
+               return -1;
+
+       ret = _appinfo_get_int_value(ai, AIT_ENABLEMENT, &enable);
+       if (ret == 0 && !(enable & APP_ENABLEMENT_MASK_ACTIVE))
+               return -1;
+
+       app_status = _app_status_find_by_appid(appid, uid);
+       if (_app_status_is_running(app_status) > 0)
+               return -1;
+
+       _D("start app %s from user %d by onboot", appid, uid);
+       return _launch_start_app_local(uid, appid);
+}
+
+int _terminate_app_local(uid_t uid, int pid)
+{
+       request_h req;
+       int ret;
+
+       req = _request_create_local(APP_TERM_BY_PID, uid, getpid(), NULL);
+       if (req == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       aul_send_app_terminate_request_signal(pid, NULL, NULL, NULL);
+       ret = _term_app(pid, req);
+       _request_free_local(req);
+
+       return ret;
+}
+
+int _send_to_sigkill(int pid)
+{
+       int pgid;
+
+       if (pid <= 1)
+               return -1;
+
+       pgid = getpgid(pid);
+       if (pgid <= 1)
+               return -1;
+
+       if (killpg(pgid, SIGKILL) < 0)
+               return -1;
+
+       return 0;
+}
+
+int _resume_app(int pid, request_h req)
+{
+       int dummy;
+       int ret;
+
+       ret = aul_sock_send_raw(pid, _request_get_target_uid(req),
+                       APP_RESUME_BY_PID, (unsigned char *)&dummy, 0,
+                       AUL_SOCK_ASYNC);
+       if (ret < 0) {
+               if (ret == -EAGAIN) {
+                       _E("resume packet timeout error");
+               } else {
+                       _E("raise failed - %d resume fail\n", pid);
+                       _E("we will term the app - %d\n", pid);
+                       _send_to_sigkill(pid);
+                       ret = -1;
+               }
+               _request_send_result(req, ret);
+       }
+       _D("resume done\n");
+
+       if (ret > 0)
+               __set_reply_handler(ret, pid, req, APP_RESUME_BY_PID);
+
+       return ret;
+}
+
+int _pause_app(int pid, request_h req)
+{
+       int dummy;
+       int ret;
+
+       ret = aul_sock_send_raw(pid, _request_get_target_uid(req),
+                       APP_PAUSE_BY_PID, (unsigned char *)&dummy, 0,
+                       AUL_SOCK_ASYNC);
+       if (ret < 0) {
+               if (ret == -EAGAIN) {
+                       _E("pause packet timeout error");
+               } else {
+                       _E("iconify failed - %d pause fail", pid);
+                       _E("we will term the app - %d", pid);
+                       _send_to_sigkill(pid);
+                       ret = -1;
+               }
+               _request_send_result(req, ret);
+       }
+       _D("pause done");
+
+       if (ret > 0)
+               __set_reply_handler(ret, pid, req, APP_PAUSE_BY_PID);
+
+       return ret;
+}
+
+int _term_sub_app(int pid, uid_t uid)
+{
+       int dummy;
+       int ret;
+
+       ret = aul_sock_send_raw(pid, uid, APP_TERM_BY_PID_ASYNC,
+                       (unsigned char *)&dummy, 0, AUL_SOCK_NOREPLY);
+       if (ret < 0) {
+               _E("terminate packet send error - use SIGKILL");
+               if (_send_to_sigkill(pid) < 0) {
+                       _E("fail to killing - %d\n", pid);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int _term_app(int pid, request_h req)
+{
+       int dummy;
+       int ret;
+       int cnt;
+       int *pids = NULL;
+       int i;
+       uid_t uid = _request_get_target_uid(req);
+
+       if (_app_group_is_leader_pid(pid)) {
+               _app_group_get_group_pids(pid, &cnt, &pids);
+               for (i = cnt - 1; i >= 0; i--) {
+                       if (i != 0)
+                               _term_sub_app(pids[i], uid);
+                       _app_group_remove(pids[i]);
+               }
+               free(pids);
+       }
+
+       ret = aul_sock_send_raw(pid, uid, APP_TERM_BY_PID,
+                       (unsigned char *)&dummy, 0, AUL_SOCK_ASYNC);
+       if (ret < 0) {
+               _D("terminate packet send error - use SIGKILL");
+               if (_send_to_sigkill(pid) < 0) {
+                       _E("fail to killing - %d\n", pid);
+                       _request_send_result(req, -1);
+                       return -1;
+               }
+               _request_send_result(req, 0);
+       }
+       _D("term done\n");
+
+       if (ret > 0)
+               __set_reply_handler(ret, pid, req, APP_TERM_BY_PID);
+
+       return 0;
+}
+
+int _term_req_app(int pid, request_h req)
+{
+       int dummy;
+       int ret;
+
+       ret = aul_sock_send_raw(pid, _request_get_target_uid(req),
+                       APP_TERM_REQ_BY_PID, (unsigned char *)&dummy, 0,
+                       AUL_SOCK_ASYNC);
+       if (ret < 0) {
+               _D("terminate req send error");
+               _request_send_result(req, ret);
+       }
+
+       if (ret > 0)
+               __set_reply_handler(ret, pid, req, APP_TERM_REQ_BY_PID);
+
+       return 0;
+}
+
+int _term_bgapp(int pid, request_h req)
+{
+       int dummy;
+       int ret;
+       int cnt;
+       int *pids = NULL;
+       int i;
+       int status = -1;
+       app_status_h app_status;
+       uid_t uid = _request_get_target_uid(req);
+
+       if (_app_group_is_leader_pid(pid)) {
+               _app_group_get_group_pids(pid, &cnt, &pids);
+               if (cnt > 0) {
+                       app_status = _app_status_find(pids[cnt - 1]);
+                       status = _app_status_get_status(app_status);
+                       if (status == STATUS_BG) {
+                               for (i = cnt - 1 ; i >= 0; i--) {
+                                       if (i != 0)
+                                               _term_sub_app(pids[i], uid);
+                                       _app_group_remove(pids[i]);
+                               }
+                       }
+               }
+               free(pids);
+       }
+
+       ret = aul_sock_send_raw(pid, uid, APP_TERM_BGAPP_BY_PID,
+                       (unsigned char *)&dummy, sizeof(int), AUL_SOCK_ASYNC);
+       if (ret < 0) {
+               _D("terminate packet send error - use SIGKILL");
+               if (_send_to_sigkill(pid) < 0) {
+                       _E("fail to killing - %d", pid);
+                       _request_send_result(req, -1);
+                       return -1;
+               }
+               _request_send_result(req, 0);
+       }
+       _D("term_bgapp done");
+
+       if (ret > 0)
+               __set_reply_handler(ret, pid, req, APP_TERM_BGAPP_BY_PID);
+
+       return 0;
+}
+
+int _term_app_v2(int pid, request_h req, bool *pend)
+{
+       int dummy;
+       int ret;
+       int cnt;
+       int *pids = NULL;
+       int i;
+       uid_t uid = _request_get_target_uid(req);
+
+       if (_app_group_is_leader_pid(pid)) {
+               _app_group_get_group_pids(pid, &cnt, &pids);
+               for (i = cnt - 1; i >= 0; i--) {
+                       if (i != 0)
+                               _term_sub_app(pids[i], uid);
+                       _app_group_remove(pids[i]);
+               }
+               free(pids);
+       }
+
+       ret = aul_sock_send_raw(pid, uid, APP_TERM_BY_PID_SYNC,
+                       (unsigned char *)&dummy, 0,
+                       AUL_SOCK_ASYNC | AUL_SOCK_NOREPLY);
+       if (ret < 0) {
+               _D("Failed to send the terminate packet - use SIGKILL");
+               if (_send_to_sigkill(pid) < 0) {
+                       _E("Failed to kill - %d\n", pid);
+                       _request_send_result(req, -1);
+                       return -1;
+               }
+       }
+       _D("term v2 done");
+
+       if (pend)
+               *pend = true;
+
+       return 0;
+}
+
+static int __fake_launch_app(int cmd, int pid, bundle *kb, request_h req)
+{
+       int ret;
+
+       ret = aul_sock_send_bundle(pid, _request_get_target_uid(req), cmd, kb,
+                       AUL_SOCK_ASYNC);
+       if (ret < 0) {
+               _E("error request fake launch - error code = %d", ret);
+               _request_send_result(req, ret);
+       }
+
+       if (ret > 0)
+               __set_reply_handler(ret, pid, req, cmd);
+
+       return ret;
+}
+
+static int __fake_launch_app_async(int cmd, int pid, bundle *kb, request_h req)
+{
+       int ret;
+
+       ret = aul_sock_send_bundle(pid, _request_get_target_uid(req), cmd, kb,
+                       AUL_SOCK_ASYNC);
+       if (ret < 0) {
+               _E("error request fake launch - error code = %d", ret);
+               _request_send_result(req, ret);
+       }
+
+       if (ret > 0) {
+               _send_result_to_client(_request_remove_fd(req), pid);
+               __set_reply_handler(ret, pid, req, cmd);
+       }
+
+       return ret;
+}
+
+static gboolean __au_glib_check(GSource *src)
+{
+       GSList *fd_list;
+       GPollFD *tmp;
+
+       fd_list = src->poll_fds;
+       do {
+               tmp = (GPollFD *) fd_list->data;
+               if ((tmp->revents & (POLLIN | POLLPRI)))
+                       return TRUE;
+               fd_list = fd_list->next;
+       } while (fd_list);
+
+       return FALSE;
+}
+
+static gboolean __au_glib_dispatch(GSource *src, GSourceFunc callback,
+               gpointer data)
+{
+       callback(data);
+       return TRUE;
+}
+
+static gboolean __au_glib_prepare(GSource *src, gint *timeout)
+{
+       return FALSE;
+}
+
+static GSourceFuncs funcs = {
+       .prepare = __au_glib_prepare,
+       .check = __au_glib_check,
+       .dispatch = __au_glib_dispatch,
+       .finalize = NULL
+};
+
+struct reply_info {
+       GSource *src;
+       GPollFD *gpollfd;
+       guint timer_id;
+       int clifd;
+       int pid;
+       int cmd;
+       bundle *kb;
+};
+
+static gboolean __reply_handler(gpointer data)
+{
+       struct reply_info *r_info = (struct reply_info *)data;
+       int fd = r_info->gpollfd->fd;
+       int len;
+       int res = 0;
+       int clifd = r_info->clifd;
+       int pid = r_info->pid;
+       char err_buf[1024];
+
+       len = recv(fd, &res, sizeof(int), 0);
+       if (len == -1) {
+               if (errno == EAGAIN) {
+                       _E("recv timeout : %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+                       res = -EAGAIN;
+               } else {
+                       _E("recv error : %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+                       res = -ECOMM;
+               }
+       }
+       close(fd);
+
+       if (res >= 0)
+               res = pid;
+       _send_result_to_client(clifd, res);
+
+       _D("listen fd : %d , send fd : %d, pid : %d", fd, clifd, pid);
+
+       g_source_remove(r_info->timer_id);
+       g_source_remove_poll(r_info->src, r_info->gpollfd);
+       g_source_destroy(r_info->src);
+       g_source_unref(r_info->src);
+       g_free(r_info->gpollfd);
+       if (r_info->kb)
+               bundle_free(r_info->kb);
+       free(r_info);
+
+       return TRUE;
+}
+
+static gboolean __recv_timeout_handler(gpointer data)
+{
+       struct reply_info *r_info = (struct reply_info *)data;
+       int fd = r_info->gpollfd->fd;
+       int clifd = r_info->clifd;
+       const char *appid;
+       const struct appinfo *ai;
+       const char *taskmanage;
+       app_status_h app_status;
+       uid_t uid;
+       int ret = -EAGAIN;
+
+       _E("application is not responding: pid(%d) cmd(%d)",
+                       r_info->pid, r_info->cmd);
+       close(fd);
+
+       switch (r_info->cmd) {
+       case APP_OPEN:
+       case APP_RESUME:
+       case APP_START:
+       case APP_START_RES:
+       case APP_START_ASYNC:
+       case APP_START_RES_ASYNC:
+               app_status = _app_status_find(r_info->pid);
+               if (app_status == NULL)
+                       break;
+
+               uid = _app_status_get_uid(app_status);
+               if (_app_status_get_app_type(app_status) == AT_WIDGET_APP)
+                       _widget_verify_instance(r_info->kb, r_info->pid, uid);
+
+               appid = _app_status_get_appid(app_status);
+               ai = _appinfo_find(uid, appid);
+               if (ai == NULL)
+                       break;
+               taskmanage = _appinfo_get_value(ai, AIT_TASKMANAGE);
+               if (taskmanage && strcmp(taskmanage, "true") == 0)
+                       _signal_send_watchdog(r_info->pid, SIGKILL);
+               break;
+       case APP_TERM_BY_PID:
+       case APP_TERM_BGAPP_BY_PID:
+               if (_send_to_sigkill(r_info->pid) == 0)
+                       ret = 0;
+               break;
+       }
+
+       _send_result_to_client(clifd, ret);
+       g_source_remove_poll(r_info->src, r_info->gpollfd);
+       g_source_destroy(r_info->src);
+       g_source_unref(r_info->src);
+       g_free(r_info->gpollfd);
+       if (r_info->kb)
+               bundle_free(r_info->kb);
+       free(r_info);
+
+       return FALSE;
+}
+
+static void __set_reply_handler(int fd, int pid, request_h req, int cmd)
+{
+       GPollFD *gpollfd;
+       GSource *src;
+       struct reply_info *r_info;
+       struct timeval tv;
+       bundle *kb = _request_get_bundle(req);
+
+       src = g_source_new(&funcs, sizeof(GSource));
+       if (src == NULL) {
+               _E("Out of memory");
+               return;
+       }
+
+       gpollfd = (GPollFD *)g_malloc(sizeof(GPollFD));
+       if (gpollfd == NULL) {
+               _E("Out of memory");
+               g_source_unref(src);
+               return;
+       }
+
+       gpollfd->events = POLLIN;
+       gpollfd->fd = fd;
+
+       r_info = malloc(sizeof(*r_info));
+       if (r_info == NULL) {
+               _E("out of memory");
+               g_free(gpollfd);
+               g_source_unref(src);
+               return;
+       }
+
+       if (kb) {
+               r_info->kb = bundle_dup(kb);
+               if (r_info->kb == NULL) {
+                       _E("Out of memory");
+                       free(r_info);
+                       g_free(gpollfd);
+                       g_source_unref(src);
+                       return;
+               }
+       } else {
+               r_info->kb = NULL;
+       }
+
+       r_info->clifd = _request_remove_fd(req);
+       r_info->pid = pid;
+       r_info->src = src;
+       r_info->gpollfd = gpollfd;
+       r_info->cmd = cmd;
+
+       tv = aul_sock_get_rcv_timeval();
+       r_info->timer_id = g_timeout_add_seconds(tv.tv_sec,
+                       __recv_timeout_handler, (gpointer)r_info);
+       g_source_add_poll(src, gpollfd);
+       g_source_set_callback(src, (GSourceFunc)__reply_handler,
+                       (gpointer)r_info, NULL);
+       g_source_set_priority(src, G_PRIORITY_DEFAULT);
+       g_source_attach(src, NULL);
+
+       _D("listen fd : %d, send fd : %d", fd, r_info->clifd);
+}
+
+static void __check_request_for_app_boosting(request_h req)
+{
+       int cmd = _request_get_cmd(req);
+       bundle *kb = _request_get_bundle(req);
+       int lcd_status = 0;
+       const char *op;
+
+       if (kb == NULL)
+               return;
+
+       op = bundle_get_val(kb, AUL_SVC_K_OPERATION);
+       if ((op && !strcmp(op, APP_CONTROL_OPERATION_MAIN)) ||
+                       cmd == APP_OPEN) {
+               vconf_get_int(VCONFKEY_PM_STATE, &lcd_status);
+               if (lcd_status == VCONFKEY_PM_STATE_LCDOFF)
+                       _D("LCD OFF: Skip app launch boost");
+               else
+                       _signal_send_cpu_boost(APP_BOOSTING_PERIOD);
+       }
+}
+
+static int __nofork_processing(int cmd, int pid, bundle *kb, request_h req)
+{
+       int ret;
+
+       __check_request_for_app_boosting(req);
+
+       switch (cmd) {
+       case APP_OPEN:
+       case APP_RESUME:
+               _D("resume app's pid : %d\n", pid);
+               ret = _resume_app(pid, req);
+               if (ret < 0)
+                       _E("__resume_app failed. error code = %d", ret);
+               _D("resume app done");
+               break;
+       case APP_START:
+       case APP_START_RES:
+               _D("fake launch pid : %d\n", pid);
+               ret = __fake_launch_app(cmd, pid, kb, req);
+               if (ret < 0)
+                       _E("fake_launch failed. error code = %d", ret);
+               _D("fake launch done");
+               break;
+       case APP_START_ASYNC:
+       case APP_START_RES_ASYNC:
+               ret = __fake_launch_app_async(cmd, pid, kb, req);
+               if (ret < 0)
+                       _E("fake_launch_async failed. error code = %d", ret);
+               _D("fake launch async done");
+               break;
+       default:
+               _E("unknown command: %d", cmd);
+               ret = -1;
+       }
+
+       return ret;
+}
+
+static int __compare_signature(const struct appinfo *ai, int cmd,
+               uid_t caller_uid, const char *appid, const char *caller_appid)
+{
+       const char *permission;
+       const struct appinfo *caller_ai;
+       const char *preload;
+       const char *api_version;
+       pkgmgrinfo_cert_compare_result_type_e compare_result;
+
+       permission = _appinfo_get_value(ai, AIT_PERM);
+       if (permission && strcmp(permission, "signature") == 0) {
+               if (caller_uid != 0 && (cmd == APP_START ||
+                                       cmd == APP_START_RES ||
+                                       cmd == APP_START_ASYNC ||
+                                       cmd == APP_START_RES_ASYNC)) {
+                       caller_ai = _appinfo_find(caller_uid, caller_appid);
+                       preload = _appinfo_get_value(caller_ai, AIT_PRELOAD);
+                       if (!preload || strcmp(preload, "true") == 0)
+                               return 0;
+
+                       api_version = _appinfo_get_value(caller_ai,
+                                       AIT_API_VERSION);
+                       if (api_version && strverscmp(api_version, "2.4") < 0)
+                               return 0;
+
+                       /* is admin is global */
+                       if (caller_uid != GLOBAL_USER) {
+                               pkgmgrinfo_pkginfo_compare_usr_app_cert_info(
+                                               caller_appid, appid,
+                                               caller_uid, &compare_result);
+                       } else {
+                               pkgmgrinfo_pkginfo_compare_app_cert_info(
+                                               caller_appid, appid,
+                                               &compare_result);
+                       }
+
+                       if (compare_result != PMINFO_CERT_COMPARE_MATCH)
+                               return -EILLEGALACCESS;
+               }
+       }
+
+       return 0;
+}
+
+static int __get_pid_for_app_group(const char *appid, uid_t uid, bundle *kb,
+               struct launch_s *handle)
+{
+       int status;
+       int found_pid = -1;
+       int found_lpid = -1;
+       int ret;
+
+       if (_app_group_is_group_app(kb, uid)) {
+               handle->pid = -1;
+               handle->is_subapp = true;
+               handle->app_status = NULL;
+       } else {
+               if (handle->new_instance)
+                       handle->is_subapp = true;
+               else
+                       handle->is_subapp = false;
+       }
+
+       status = _app_status_get_status(handle->app_status);
+       if (handle->pid <= 0 || status == STATUS_DYING) {
+               ret = _app_group_find_singleton(appid, &found_pid, &found_lpid);
+               if (ret == 0) {
+                       handle->pid = found_pid;
+                       handle->new_process = false;
+               } else {
+                       handle->new_process = true;
+               }
+
+               ret = _app_group_can_start_app(appid, kb, &handle->can_attach,
+                               &handle->leader_pid, &handle->launch_mode, uid);
+               if (ret != 0) {
+                       _E("can't make group info");
+                       return -EILLEGALACCESS;
+               }
+
+               if (handle->can_attach && handle->leader_pid == found_lpid) {
+                       _E("can't launch singleton app in the same group");
+                       return -EILLEGALACCESS;
+               }
+
+               if (found_pid != -1) {
+                       _W("_app_group_clear_top, pid: %d", found_pid);
+                       _app_group_clear_top(found_pid, uid);
+               }
+       }
+
+       if (handle->pid == -1 && handle->can_attach)
+               handle->pid = _app_group_find_pid_from_recycle_bin(appid);
+
+       if (handle->pid > 0)
+               handle->app_status = _app_status_find(handle->pid);
+
+       return 0;
+}
+
+static void __prepare_to_suspend_services(int pid, uid_t uid)
+{
+       int dummy;
+
+       SECURE_LOGD("[__SUSPEND__] pid: %d, uid: %d", pid, uid);
+       aul_sock_send_raw(pid, uid, APP_SUSPEND, (unsigned char *)&dummy,
+                       sizeof(int), AUL_SOCK_NOREPLY);
+}
+
+static void __prepare_to_wake_services(int pid, uid_t uid)
+{
+       int dummy;
+
+       SECURE_LOGD("[__SUSPEND__] pid: %d, uid: %d", pid, uid);
+       aul_sock_send_raw(pid, uid, APP_WAKE, (unsigned char *)&dummy,
+                       sizeof(int), AUL_SOCK_NOREPLY);
+}
+
+static gboolean __check_service_only(gpointer user_data)
+{
+       int pid = GPOINTER_TO_INT(user_data);
+       app_status_h app_status;
+
+       SECURE_LOGD("[__SUSPEND__] pid :%d", pid);
+       app_status = _app_status_find(pid);
+       _app_status_check_service_only(app_status,
+                       __prepare_to_suspend_services);
+
+       return FALSE;
+}
+
+static char *__get_cert_value_from_pkginfo(const char *pkgid, uid_t uid)
+{
+       int ret;
+       const char *cert_value;
+       char *ret_cert;
+       pkgmgrinfo_certinfo_h certinfo;
+
+       ret = pkgmgrinfo_pkginfo_create_certinfo(&certinfo);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to create certinfo");
+               return NULL;
+       }
+
+       ret = pkgmgrinfo_pkginfo_load_certinfo(pkgid, certinfo, uid);
+       if (ret != PMINFO_R_OK) {
+               _E("Failed to load certinfo");
+               pkgmgrinfo_pkginfo_destroy_certinfo(certinfo);
+               return NULL;
+       }
+
+       ret = pkgmgrinfo_pkginfo_get_cert_value(certinfo,
+                       PMINFO_DISTRIBUTOR_ROOT_CERT, &cert_value);
+       if (ret != PMINFO_R_OK || cert_value == NULL) {
+               _E("Failed to get cert value");
+               pkgmgrinfo_pkginfo_destroy_certinfo(certinfo);
+               return NULL;
+       }
+
+       ret_cert = strdup(cert_value);
+       pkgmgrinfo_pkginfo_destroy_certinfo(certinfo);
+
+       return ret_cert;
+}
+
+static int __get_visibility_from_certsvc(const char *cert_value)
+{
+       int ret;
+       CertSvcInstance instance;
+       CertSvcCertificate certificate;
+       CertSvcVisibility visibility = CERTSVC_VISIBILITY_PUBLIC;
+
+       if (cert_value == NULL)
+               return (int)visibility;
+
+       ret = certsvc_instance_new(&instance);
+       if (ret != CERTSVC_SUCCESS) {
+               _E("certsvc_instance_new() is failed.");
+               return (int)visibility;
+       }
+
+       ret = certsvc_certificate_new_from_memory(instance,
+                       (const unsigned char *)cert_value,
+                       strlen(cert_value),
+                       CERTSVC_FORM_DER_BASE64,
+                       &certificate);
+       if (ret != CERTSVC_SUCCESS) {
+               _E("certsvc_certificate_new_from_memory() is failed.");
+               certsvc_instance_free(instance);
+               return (int)visibility;
+       }
+
+       ret = certsvc_certificate_get_visibility(certificate, &visibility);
+       if (ret != CERTSVC_SUCCESS)
+               _E("certsvc_certificate_get_visibility() is failed.");
+
+       certsvc_certificate_free(certificate);
+       certsvc_instance_free(instance);
+
+       return (int)visibility;
+}
+
+static int __check_allowed_appid(const char *callee_appid,
+               const char *caller_appid, uid_t uid)
+{
+       app_property_h app_property;
+       GList *list;
+       GList *iter;
+       char *allowed_appid;
+
+       app_property = _app_property_find(uid);
+       if (app_property == NULL)
+               return -1;
+
+       list = _app_property_get_allowed_app_list(app_property, callee_appid);
+       iter = g_list_first(list);
+       while (iter) {
+               allowed_appid = (char *)iter->data;
+               if (allowed_appid && strcmp(allowed_appid, caller_appid) == 0) {
+                       _D("allowed appid(%s), appid(%s)",
+                                       allowed_appid, callee_appid);
+                       return 0;
+               }
+
+               iter = g_list_next(iter);
+       }
+
+       return -1;
+}
+
+static int __check_execute_permission(const char *callee_pkgid,
+               const char *caller_appid, uid_t caller_uid, bundle *kb)
+{
+       struct appinfo *ai;
+       const char *caller_pkgid;
+       const char *launch_type;
+       const char *v;
+       const char *callee_appid = bundle_get_val(kb, AUL_K_APPID);
+       char num[256];
+       int vi_num;
+       int visibility;
+       char *cert_value;
+       int ret;
+
+       if (callee_pkgid == NULL)
+               return -1;
+
+       ai = _appinfo_find(caller_uid, caller_appid);
+       if (ai == NULL)
+               return 0;
+
+       caller_pkgid = _appinfo_get_value(ai, AIT_PKGID);
+       if (caller_pkgid == NULL)
+               return 0;
+
+       if (strcmp(caller_pkgid, callee_pkgid) == 0)
+               return 0;
+
+       ret = __check_allowed_appid(callee_appid, caller_appid, caller_uid);
+       if (ret == 0)
+               return 0;
+
+       launch_type = bundle_get_val(kb, OSP_K_LAUNCH_TYPE);
+       if (launch_type == NULL
+               || strcmp(launch_type, OSP_V_LAUNCH_TYPE_DATACONTROL) != 0) {
+               v = _appinfo_get_value(ai, AIT_VISIBILITY);
+               if (v == NULL) {
+                       cert_value = __get_cert_value_from_pkginfo(caller_pkgid,
+                                       caller_uid);
+                       vi_num = __get_visibility_from_certsvc(cert_value);
+                       if (cert_value)
+                               free(cert_value);
+
+                       snprintf(num, sizeof(num), "%d", vi_num);
+                       _appinfo_set_value(ai, AIT_VISIBILITY, num);
+                       v = num;
+               }
+
+               visibility = atoi(v);
+               if (!(visibility & CERTSVC_VISIBILITY_PLATFORM)) {
+                       _E("Couldn't launch service app in other packages");
+                       return -EREJECTED;
+               }
+       }
+
+       return 0;
+}
+
+static gboolean __fg_timeout_handler(gpointer data)
+{
+       struct fgmgr *fg = data;
+       app_status_h app_status;
+
+       if (!fg)
+               return FALSE;
+
+       app_status = _app_status_find(fg->pid);
+       if (app_status == NULL)
+               return FALSE;
+
+       _W("%d is running in the background", fg->pid);
+       _app_status_update_status(app_status, STATUS_BG, true, true);
+
+       _fgmgr_list = g_list_remove(_fgmgr_list, fg);
+       free(fg);
+
+       return FALSE;
+}
+
+int _launch_add_fgmgr(int pid)
+{
+       struct fgmgr *fg;
+
+       fg = calloc(1, sizeof(struct fgmgr));
+       if (!fg) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       fg->pid = pid;
+       fg->tid = g_timeout_add(5000, __fg_timeout_handler, fg);
+
+       _fgmgr_list = g_list_append(_fgmgr_list, fg);
+
+       return 0;
+}
+
+void _launch_remove_fgmgr(int pid)
+{
+       GList *iter = NULL;
+       struct fgmgr *fg;
+
+       if (pid < 0)
+               return;
+
+       for (iter = _fgmgr_list; iter != NULL; iter = g_list_next(iter)) {
+               fg = (struct fgmgr *)iter->data;
+               if (fg->pid == pid) {
+                       g_source_remove(fg->tid);
+                       _fgmgr_list = g_list_remove(_fgmgr_list, fg);
+                       free(fg);
+                       return;
+               }
+       }
+}
+
+static int __send_hint_for_visibility(uid_t uid)
+{
+       bundle *b;
+       int ret;
+
+       b = bundle_create();
+       if (b == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       ret = _send_cmd_to_launchpad(LAUNCHPAD_PROCESS_POOL_SOCK, uid,
+                       PAD_CMD_VISIBILITY, b);
+       bundle_free(b);
+       __pid_of_last_launched_ui_app = 0;
+
+       return ret;
+}
+
+#ifdef TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP
+static void __terminate_unmanageable_app(app_status_h app_status)
+{
+       const char *appid = NULL;
+       int cnt = 0;
+       int *pids = NULL;
+       int i;
+       const char *taskmanage = NULL;
+       const struct appinfo *ai = NULL;
+       int bg_category = 0x00;
+       app_status_h status_h;
+       int st;
+       uid_t uid;
+
+       if (!_app_status_is_home_app(app_status))
+               return;
+
+       _app_group_get_leader_pids(&cnt, &pids);
+       if (pids == NULL)
+               return;
+
+       for (i = 0; i < cnt; i++) {
+               status_h = _app_status_find(pids[i]);
+               if (!status_h)
+                       continue;
+
+               if (_app_status_is_home_app(status_h))
+                       continue;
+
+               appid = _app_status_get_appid(status_h);
+               ai = _appinfo_find(_app_status_get_uid(status_h), appid);
+               taskmanage = _appinfo_get_value(ai, AIT_TASKMANAGE);
+               _appinfo_get_int_value(ai, AIT_BG_CATEGORY, &bg_category);
+               uid = _app_status_get_uid(status_h);
+
+               if (taskmanage && strcmp("false", taskmanage) == 0
+                       && bg_category == 0) {
+                       st = _app_status_get_status(status_h);
+                       if (st == STATUS_BG) {
+                               _W("terminate %d %s %d", pids[i], appid, st);
+                               aul_send_app_terminate_request_signal(pids[i],
+                                               NULL, NULL, NULL);
+                               _term_sub_app(pids[i], uid);
+                       }
+               }
+       }
+
+       free(pids);
+}
+#endif /* TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP */
+
+static const char *__get_name(const char *appid)
+{
+       char *name_token;
+
+       if (!appid)
+               return NULL;
+
+       name_token = strrchr(appid, '.');
+       if (name_token == NULL)
+               return appid;
+
+       name_token++;
+
+       return name_token;
+}
+
+static int __app_status_handler(int pid, int status, void *data)
+{
+       const char *appid;
+       const char *name;
+       int bg_category;
+       int old_status;
+       const struct appinfo *ai;
+       app_status_h app_status;
+       uid_t uid;
+       unsigned int surf;
+
+       _W("pid(%d) status(%d)", pid, status);
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return 0;
+
+       old_status = _app_status_get_status(app_status);
+       if (old_status == STATUS_DYING && old_status != PROC_STATUS_LAUNCH)
+               return 0;
+
+       uid = _app_status_get_uid(app_status);
+       switch (status) {
+       case PROC_STATUS_FG:
+               _launch_remove_fgmgr(pid);
+               _app_status_update_status(app_status, STATUS_VISIBLE, false, true);
+               _suspend_remove_timer(pid);
+
+               if (pid == __pid_of_last_launched_ui_app)
+                       __send_hint_for_visibility(uid);
+
+#ifdef TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP
+               __terminate_unmanageable_app(app_status);
+#endif /* TIZEN_FEATURE_TERMINATE_UNMANAGEABLE_APP */
+
+               surf = (unsigned int)_app_group_get_window(pid);
+               _screen_connector_update_app_screen(pid, surf, uid);
+               _rua_update_screen_info(pid, surf);
+               break;
+       case PROC_STATUS_BG:
+               _app_status_update_status(app_status, STATUS_BG, false, true);
+               appid = _app_status_get_appid(app_status);
+               if (appid) {
+                       ai = _appinfo_find(uid, appid);
+                       bg_category = (bool)_appinfo_get_value(ai,
+                                       AIT_BG_CATEGORY);
+                       if (!bg_category)
+                               _suspend_add_timer(pid, ai);
+               }
+               break;
+       case PROC_STATUS_FOCUS:
+               __focused_pid = pid;
+               surf = (unsigned int)_app_group_get_window(pid);
+               _screen_connector_update_app_screen(pid, surf, uid);
+               _rua_update_screen_info(pid, surf);
+               break;
+
+       case PROC_STATUS_HIDE:
+               _app_status_update_status(app_status, STATUS_BG, false, false);
+               break;
+
+       case PROC_STATUS_LAUNCH:
+               _signal_send_cpu_boost(APP_BOOSTING_STOP);
+               appid = _app_status_get_appid(app_status);
+               if (appid) {
+                       name = __get_name(appid);
+                       if (name)
+                               LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]", name);
+               }
+               break;
+
+       }
+
+       return 0;
+}
+
+void _launch_set_focused_pid(int pid)
+{
+       __focused_pid = pid;
+}
+
+int _launch_get_focused_pid(void)
+{
+       return __focused_pid;
+}
+
+static int __listen_app_status_signal(void *data)
+{
+       int ret;
+
+       ret = aul_listen_app_status_signal(__app_status_handler, data);
+       if (ret < 0)
+               return -1;
+
+       return 0;
+}
+
+int _launch_init(void)
+{
+       int ret;
+
+       _D("_launch_init");
+
+       ret = __listen_app_status_signal(NULL);
+       if (ret < 0)
+               _signal_add_initializer(__listen_app_status_signal, NULL);
+
+       return 0;
+}
+
+static int __check_ver(const char *required, const char *actual)
+{
+       int ret;
+
+       if (required && actual) {
+               ret = strverscmp(required, actual);
+               if (ret < 1)
+                       return 1;
+       }
+
+       return 0;
+}
+
+static int __get_prelaunch_attribute(const struct appinfo *ai,
+               const char *appid, uid_t uid)
+{
+       int attribute_val = RESOURCED_BACKGROUND_MANAGEMENT_ATTRIBUTE;
+       const char *api_version;
+       const char *comp;
+       const char *pkg_type;
+       bool system = false;
+       app_property_h prop;
+
+       api_version = _appinfo_get_value(ai, AIT_API_VERSION);
+       if (api_version && __check_ver("2.4", api_version))
+               attribute_val |= RESOURCED_API_VER_2_4_ATTRIBUTE;
+
+       comp = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (comp && !strcmp(comp, APP_TYPE_SERVICE))
+               attribute_val |= RESOURCED_ATTRIBUTE_SERVICE_APP;
+
+       pkg_type = _appinfo_get_value(ai, AIT_PKGTYPE);
+       if (pkg_type && !strcmp(pkg_type, "wgt")) {
+               attribute_val |= RESOURCED_ATTRIBUTE_LARGEMEMORY;
+               attribute_val |= RESOURCED_ATTRIBUTE_WEB_APP;
+       }
+
+       _appinfo_get_boolean(ai, AIT_SYSTEM, &system);
+       if (!system)
+               attribute_val |= RESOURCED_ATTRIBUTE_DOWNLOAD_APP;
+
+       prop = _app_property_find(uid);
+       if (prop) {
+               if (_app_property_metadata_query_activation(prop, appid, METADATA_LARGEMEMORY))
+                       attribute_val |= RESOURCED_ATTRIBUTE_LARGEMEMORY;
+               if (_app_property_metadata_query_activation(prop, appid, METADATA_OOMTERMINATION))
+                       attribute_val |= RESOURCED_ATTRIBUTE_OOMTERMINATION;
+       }
+
+       _D("api-version: %s", api_version);
+       _D("prelaunch attribute %d%d%d%d%d",
+                       (attribute_val & 0x10) >> 4,
+                       (attribute_val & 0x8) >> 3,
+                       (attribute_val & 0x4) >> 2,
+                       (attribute_val & 0x2) >> 1,
+                       (attribute_val & 0x1));
+
+       return attribute_val;
+}
+
+static int __get_background_category(const struct appinfo *ai)
+{
+       int category = 0x0;
+
+       category = (intptr_t)_appinfo_get_value(ai, AIT_BG_CATEGORY);
+
+       _D("background category: %#x", category);
+
+       return category;
+}
+
+static bool __is_allowed_background(const char *component_type, int bg_category)
+{
+       bool bg_allowed = false;
+
+       /*
+        * 2.4 bg-categorized (uiapp || svcapp) || watch || widget -> bg allowed
+        * 2.3 uiapp -> not allowed, 2.3 svcapp -> bg allowed
+        */
+       if (!strcmp(component_type, APP_TYPE_UI) ||
+                       !strcmp(component_type, APP_TYPE_SERVICE)) {
+               if (bg_category)
+                       bg_allowed = true;
+       } else {
+               bg_allowed = true;
+       }
+
+       return bg_allowed;
+}
+
+static void __set_caller_appinfo(const char *caller_appid, int caller_pid,
+               uid_t caller_uid, bundle *kb)
+{
+       char buf[MAX_PID_STR_BUFSZ];
+
+       snprintf(buf, sizeof(buf), "%d", caller_pid);
+       bundle_del(kb, AUL_K_CALLER_PID);
+       bundle_add(kb, AUL_K_CALLER_PID, buf);
+
+       snprintf(buf, sizeof(buf), "%d", caller_uid);
+       bundle_del(kb, AUL_K_CALLER_UID);
+       bundle_add(kb, AUL_K_CALLER_UID, buf);
+
+       if (caller_appid) {
+               bundle_del(kb, AUL_K_CALLER_APPID);
+               bundle_add(kb, AUL_K_CALLER_APPID, caller_appid);
+       }
+}
+
+static const char *__get_caller_appid(int caller_pid, uid_t caller_uid)
+{
+       app_status_h app_status;
+
+       app_status = _app_status_find(caller_pid);
+       if (app_status == NULL && caller_uid >= REGULAR_UID_MIN)
+               app_status = _app_status_find(getpgid(caller_pid));
+
+       return _app_status_get_appid(app_status);
+}
+
+static int __check_executable(const struct appinfo *ai)
+{
+       const char *status;
+       int enable;
+       int ret;
+
+       status = _appinfo_get_value(ai, AIT_STATUS);
+       if (status == NULL)
+               return -1;
+
+       if (strcmp(status, "blocking") == 0) {
+               _D("Blocking");
+               return -EREJECTED;
+       }
+
+       ret = _appinfo_get_int_value(ai, AIT_ENABLEMENT, &enable);
+       if (ret == 0 && !(enable & APP_ENABLEMENT_MASK_ACTIVE)) {
+               _D("Disabled");
+               return -EREJECTED;
+       }
+
+       return 0;
+}
+
+static void __set_appinfo_for_launchpad(const struct appinfo *ai, bundle *kb)
+{
+       const char *str;
+
+       str = _appinfo_get_value(ai, AIT_HWACC);
+       if (str) {
+               bundle_del(kb, AUL_K_HWACC);
+               bundle_add(kb, AUL_K_HWACC, str);
+       }
+
+       str = _appinfo_get_value(ai, AIT_ROOT_PATH);
+       if (str) {
+               bundle_del(kb, AUL_K_ROOT_PATH);
+               bundle_add(kb, AUL_K_ROOT_PATH, str);
+       }
+
+       str = _appinfo_get_value(ai, AIT_EXEC);
+       if (str) {
+               bundle_del(kb, AUL_K_EXEC);
+               bundle_add(kb, AUL_K_EXEC, str);
+       }
+
+       str = _appinfo_get_value(ai, AIT_PKGTYPE);
+       if (str) {
+               bundle_del(kb, AUL_K_PACKAGETYPE);
+               bundle_add(kb, AUL_K_PACKAGETYPE, str);
+       }
+
+       str = _appinfo_get_value(ai, AIT_PKGID);
+       if (str) {
+               bundle_del(kb, AUL_K_PKGID);
+               bundle_add(kb, AUL_K_PKGID, str);
+       }
+
+       str = _appinfo_get_value(ai, AIT_POOL);
+       if (str) {
+               bundle_del(kb, AUL_K_INTERNAL_POOL);
+               bundle_add(kb, AUL_K_INTERNAL_POOL, str);
+       }
+
+       str = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (str) {
+               bundle_del(kb, AUL_K_COMP_TYPE);
+               bundle_add(kb, AUL_K_COMP_TYPE, str);
+       }
+
+       str = _appinfo_get_value(ai, AIT_APPTYPE);
+       if (str) {
+               bundle_del(kb, AUL_K_APP_TYPE);
+               bundle_add(kb, AUL_K_APP_TYPE, str);
+       }
+
+       str = _appinfo_get_value(ai, AIT_API_VERSION);
+       if (str) {
+               bundle_del(kb, AUL_K_API_VERSION);
+               bundle_add(kb, AUL_K_API_VERSION, str);
+       }
+}
+
+static int __get_app_status(struct launch_s *handle, request_h req,
+               const char *comp_type, const char *caller_appid)
+{
+       const char *widget_viewer;
+       const char *multiple;
+       int *target_pid = NULL;
+       size_t target_pid_sz;
+       bundle *kb = _request_get_bundle(req);
+       int caller_pid = _request_get_pid(req);
+       uid_t target_uid = _request_get_target_uid(req);
+       int ret;
+
+       if (caller_appid && strcmp(comp_type, APP_TYPE_WIDGET) == 0) {
+               handle->is_subapp = true;
+               widget_viewer = bundle_get_val(kb, AUL_K_WIDGET_VIEWER);
+               if (widget_viewer && strcmp(widget_viewer, caller_appid) == 0) {
+                       _D("widget_viewer(%s)", widget_viewer);
+                       handle->app_status = _app_status_find_with_org_caller(
+                                       handle->appid, target_uid, caller_pid);
+               } else {
+                       ret = bundle_get_byte(kb, AUL_K_TARGET_PID,
+                                       (void **)&target_pid, &target_pid_sz);
+                       if (ret != BUNDLE_ERROR_NONE) {
+                               _E("Cannot launch widget app");
+                               return -EREJECTED;
+                       }
+
+                       handle->app_status = _app_status_find(*target_pid);
+                       if (handle->app_status == NULL) {
+                               _E("Cannot find widget app(%d)", *target_pid);
+                               return -EREJECTED;
+                       }
+               }
+       } else if (strcmp(comp_type, APP_TYPE_WATCH) == 0) {
+               handle->is_subapp = true;
+               widget_viewer = bundle_get_val(kb, AUL_K_WIDGET_VIEWER);
+               if (widget_viewer && caller_appid &&
+                               !strcmp(widget_viewer, caller_appid)) {
+                       _D("watch_viewer(%s)", widget_viewer);
+                       handle->app_status = _app_status_find_with_org_caller(
+                                       handle->appid, target_uid, caller_pid);
+               } else {
+                       ret = bundle_get_byte(kb, AUL_K_TARGET_PID,
+                                       (void **)&target_pid, &target_pid_sz);
+                       if (ret != BUNDLE_ERROR_NONE) {
+                               handle->app_status =
+                                       _app_status_find_by_appid_v2(
+                                                       handle->appid,
+                                                       target_uid);
+                       } else {
+                               handle->app_status =
+                                       _app_status_find(*target_pid);
+                       }
+
+                       if (handle->app_status == NULL) {
+                               _E("Cannot find watch app(%s)", handle->appid);
+                               return -EREJECTED;
+                       }
+               }
+       } else {
+               handle->instance_id = bundle_get_val(kb, AUL_K_INSTANCE_ID);
+               if (handle->instance_id) {
+                       handle->app_status = _app_status_find_by_instance_id(
+                                       handle->appid, handle->instance_id,
+                                       target_uid);
+                       if (!handle->app_status && !handle->new_instance) {
+                               _E("Failed to find app instance(%s)",
+                                               handle->instance_id);
+                               return -EREJECTED;
+                       }
+               } else {
+                       multiple = _appinfo_get_value(handle->ai, AIT_MULTI);
+                       if (multiple == NULL || !strcmp(multiple, "false")) {
+                               handle->app_status = _app_status_find_by_appid(
+                                               handle->appid, target_uid);
+                       }
+               }
+       }
+
+       handle->pid = _app_status_get_pid(handle->app_status);
+
+       return 0;
+}
+
+static int __prepare_starting_app(struct launch_s *handle, request_h req,
+               const char *appid, bool new_instance)
+{
+       int ret;
+       const char *pkgid;
+       const char *comp_type;
+       const char *caller_appid;
+       const char *installed_storage;
+       const char *bg_launch;
+       const char *global;
+       int cmd = _request_get_cmd(req);
+       int caller_pid = _request_get_pid(req);
+       uid_t caller_uid = _request_get_uid(req);
+       uid_t target_uid = _request_get_target_uid(req);
+       uid_t pkg_uid;
+       bundle *kb = _request_get_bundle(req);
+#ifdef TIZEN_FEATURE_BLOCK_INPUT
+       int status;
+#endif /* TIZEN_FEATURE_BLOCK_INPUT */
+       const struct appinfo *caller_ai;
+
+       handle->new_instance = new_instance;
+       handle->appid = appid;
+       handle->ai = _appinfo_find(target_uid, appid);
+       if (handle->ai == NULL) {
+               _D("Failed to find appinfo of %s", appid);
+               return -ENOENT;
+       }
+
+       ret = __check_executable(handle->ai);
+       if (ret < 0)
+               return -1;
+
+       caller_appid = __get_caller_appid(caller_pid, caller_uid);
+       if (caller_appid) {
+               caller_ai = _appinfo_find(caller_uid, caller_appid);
+               if (caller_ai) {
+                       comp_type = _appinfo_get_value(caller_ai, AIT_COMPTYPE);
+                       if (comp_type && !strcmp(comp_type, APP_TYPE_UI))
+                               bundle_del(kb, AUL_SVC_K_CAN_BE_LEADER);
+               }
+       }
+       __set_caller_appinfo(caller_appid, caller_pid, caller_uid, kb);
+
+       ret = __compare_signature(handle->ai, cmd, target_uid, appid,
+                       caller_appid);
+       if (ret < 0)
+               return ret;
+
+       ret = _cooldown_check_mode(handle->ai);
+       if (ret < 0) {
+               _E("Unable to launch %s in cooldown mode", handle->appid);
+               return ret;
+       }
+
+       pkgid = _appinfo_get_value(handle->ai, AIT_PKGID);
+       installed_storage = _appinfo_get_value(handle->ai, AIT_STORAGE_TYPE);
+       if (installed_storage && strcmp(installed_storage, "external") == 0) {
+               global = _appinfo_get_value(handle->ai, AIT_GLOBAL);
+
+               if (global && strcmp("true", global) == 0)
+                       pkg_uid = GLOBAL_USER;
+               else
+                       pkg_uid = target_uid;
+
+               if (app2ext_usr_enable_external_pkg(pkgid, pkg_uid) < 0) {
+                       _E("Failed to enable exteranl pkg(%s)", pkgid);
+                       return -1;
+               }
+       }
+
+       bg_launch = bundle_get_val(kb, AUL_SVC_K_BG_LAUNCH);
+       if (bg_launch && strcmp(bg_launch, "enable") == 0)
+               handle->bg_launch = true;
+
+       comp_type = _appinfo_get_value(handle->ai, AIT_COMPTYPE);
+       if (comp_type == NULL)
+               return -1;
+
+       ret = __get_app_status(handle, req, comp_type, caller_appid);
+       if (ret < 0)
+               return ret;
+
+       if (strcmp(comp_type, APP_TYPE_UI) == 0) {
+               ret = __get_pid_for_app_group(appid, target_uid, kb, handle);
+               if (ret < 0)
+                       return ret;
+
+#ifdef TIZEN_FEATURE_BLOCK_INPUT
+               status = _app_status_get_status(handle->app_status);
+               if (status != STATUS_VISIBLE && !handle->bg_launch)
+                       _input_lock();
+#endif /* TIZEN_FEATURE_BLOCK_INPUT */
+       } else if (caller_appid && strcmp(comp_type, APP_TYPE_SERVICE) == 0) {
+               ret = __check_execute_permission(pkgid, caller_appid,
+                               target_uid, kb);
+               if (ret < 0)
+                       return ret;
+       } else if (caller_appid && strcmp(comp_type, APP_TYPE_WIDGET) == 0) {
+               ret = _widget_verify_cmd(req);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (cmd == APP_START_RES) {
+               bundle_del(kb, AUL_K_WAIT_RESULT);
+               bundle_add(kb, AUL_K_WAIT_RESULT, "1");
+       }
+
+       if (caller_appid) {
+               handle->share_info = _temporary_permission_create(caller_pid,
+                               appid, kb, target_uid);
+               if (handle->share_info == NULL)
+                       _W("No sharable path: %d %s", caller_pid, appid);
+       }
+
+       _extractor_mount(handle->ai, kb, _extractor_mountable_get_tep_paths);
+       _extractor_mount(handle->ai, kb, _extractor_mountable_get_tpk_paths);
+
+       handle->prelaunch_attr = __get_prelaunch_attribute(
+                       handle->ai, appid, target_uid);
+       handle->bg_category = __get_background_category(handle->ai);
+       handle->bg_allowed = __is_allowed_background(comp_type,
+                       handle->bg_category);
+       if (handle->bg_allowed) {
+               _D("[__SUSPEND__] allowed background, appid: %s, app-type: %s",
+                               appid, comp_type);
+               bundle_del(kb, AUL_K_ALLOWED_BG);
+               bundle_add(kb, AUL_K_ALLOWED_BG, "ALLOWED_BG");
+       }
+
+       return 0;
+}
+
+static int __do_starting_app(struct launch_s *handle, request_h req,
+               bool *pending, bool *bg_launch)
+{
+       int status = -1;
+       int cmd = _request_get_cmd(req);
+       int caller_pid = _request_get_pid(req);
+       uid_t target_uid = _request_get_target_uid(req);
+       bundle *kb = _request_get_bundle(req);
+       const char *pkgid;
+       const char *comp_type;
+       const char *pad_type = LAUNCHPAD_PROCESS_POOL_SOCK;
+       splash_image_h splash_image = NULL;
+       int ret;
+       char err_buf[1024];
+       bool socket_exists;
+
+       pkgid = _appinfo_get_value(handle->ai, AIT_PKGID);
+       comp_type = _appinfo_get_value(handle->ai, AIT_COMPTYPE);
+       status = _app_status_get_status(handle->app_status);
+       if (handle->pid > 0 && status != STATUS_DYING) {
+               if (handle->pid == caller_pid) {
+                       SECURE_LOGD("caller & callee process are same. %s:%d,",
+                                       handle->appid, handle->pid);
+                       return -ELOCALLAUNCH_ID;
+               }
+
+               _util_save_log("RESUMING", handle->appid);
+
+               aul_send_app_resume_request_signal(handle->pid,
+                               handle->appid, pkgid, comp_type);
+               _suspend_remove_timer(handle->pid);
+               if (comp_type && !strcmp(comp_type, APP_TYPE_SERVICE)) {
+                       if (handle->bg_allowed == false) {
+                               __prepare_to_wake_services(handle->pid,
+                                               target_uid);
+                       }
+               }
+
+               ret = __nofork_processing(cmd, handle->pid, kb, req);
+               if (ret < 0) {
+                       _temporary_permission_destroy(handle->share_info);
+                       socket_exists =
+                               _app_status_socket_exists(handle->app_status);
+                       if (ret == -ECOMM && socket_exists) {
+                               _E("ECOMM error, we will term the app - %s:%d",
+                                               handle->appid, handle->pid);
+                               _send_to_sigkill(handle->pid);
+                               _app_status_cleanup(handle->app_status);
+                               return -1;
+                       }
+               }
+
+               _app_status_update_last_caller_pid(
+                               handle->app_status, caller_pid);
+               _app_status_update_bg_launch(
+                               handle->app_status, handle->bg_launch);
+               *bg_launch = _app_status_get_bg_launch(handle->app_status);
+
+               return ret;
+       }
+
+       if (handle->pid > 0 && status == STATUS_DYING) {
+               ret = kill(handle->pid, SIGKILL);
+               if (ret == -1) {
+                       _W("Failed to send SIGKILL: %d:%s,", handle->pid,
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               }
+               _app_status_cleanup(handle->app_status);
+       }
+
+       __set_appinfo_for_launchpad(handle->ai, kb);
+       if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) {
+               aul_svc_set_loader_id(kb, PAD_LOADER_ID_DIRECT);
+               handle->debug_mode = true;
+       }
+
+       if (handle->instance_id == NULL && handle->bg_launch == false) {
+               splash_image = _splash_screen_create_image(handle->ai, kb, cmd,
+                               handle->is_subapp);
+               _splash_screen_send_image(splash_image);
+       }
+
+       _signal_send_proc_prelaunch(handle->appid, pkgid,
+                       handle->prelaunch_attr, handle->bg_category);
+       _signal_send_cpu_boost(APP_BOOSTING_PERIOD);
+
+       if (__get_tizen_profile() == TIZEN_PROFILE_WEARABLE)
+               bundle_add(kb, AUL_K_PROFILE, "wearable");
+       ret = _send_cmd_to_launchpad(pad_type, target_uid, PAD_CMD_LAUNCH, kb);
+       if (ret < 0) {
+               _signal_send_cpu_boost(APP_BOOSTING_STOP);
+               _temporary_permission_destroy(handle->share_info);
+               _splash_screen_destroy_image(splash_image);
+               return ret;
+       }
+
+       handle->pid = ret;
+       *pending = true;
+       *bg_launch = handle->bg_launch;
+
+       if (splash_image) {
+               _splash_screen_send_pid(splash_image, handle->pid);
+       } else if (comp_type && !strcmp(comp_type, APP_TYPE_UI)) {
+               _splash_screen_set_effect_type(handle->pid, handle->appid,
+                               handle->is_subapp);
+       }
+
+       _suspend_add_proc(handle->pid);
+       aul_send_app_launch_request_signal(handle->pid, handle->appid,
+                       pkgid, comp_type);
+
+       _util_save_log("LAUNCHING", handle->appid);
+       if (handle->debug_mode) {
+               _W("Exclude - %s(%d)", handle->appid, handle->pid);
+               aul_update_freezer_status(handle->pid, "exclude");
+               return ret;
+       }
+
+       if (comp_type && !strcmp(comp_type, APP_TYPE_SERVICE)) {
+               if (!handle->bg_allowed)
+                       g_idle_add(__check_service_only, GINT_TO_POINTER(ret));
+       }
+
+       return ret;
+}
+
+static int __complete_starting_app(struct launch_s *handle, request_h req)
+{
+       bundle *kb = _request_get_bundle(req);
+       uid_t target_uid = _request_get_target_uid(req);
+       int caller_pid = _request_get_pid(req);
+       const char *comp_type;
+       int ret;
+       char log_status[AUL_PR_NAME];
+
+       comp_type = _appinfo_get_value(handle->ai, AIT_COMPTYPE);
+       if (comp_type && !strcmp(comp_type, APP_TYPE_UI)) {
+               if (handle->new_process) {
+                       _D("Add app group info %d", handle->pid);
+                       __pid_of_last_launched_ui_app = handle->pid;
+                       _app_group_start_app(handle->pid, kb,
+                                       handle->leader_pid,
+                                       handle->can_attach,
+                                       handle->launch_mode);
+               } else {
+                       _app_group_restart_app(handle->pid, kb);
+               }
+       }
+
+       _app_status_add_app_info(handle->ai, handle->pid, handle->is_subapp,
+                       target_uid, caller_pid, handle->bg_launch,
+                       handle->instance_id, handle->debug_mode);
+
+       if (handle->share_info) {
+               ret = _temporary_permission_apply(handle->pid, target_uid,
+                               handle->share_info);
+               if (ret < 0)
+                       _D("Couldn't apply temporary permission: %d", ret);
+
+               _temporary_permission_destroy(handle->share_info);
+       }
+
+       snprintf(log_status, sizeof(log_status), "SUCCESS: %d", handle->pid);
+       _util_save_log(log_status, handle->appid);
+       return handle->pid;
+}
+
+static void __handle_onboot(void *user_data, const char *appid,
+               struct appinfo *info)
+{
+       uid_t uid = GPOINTER_TO_UINT(user_data);
+
+       _launch_start_onboot_app_local(uid, appid, info);
+}
+
+static gboolean __load_onboot_apps(gpointer data)
+{
+       uid_t uid = GPOINTER_TO_UINT(data);
+
+       _D("onboot uid(%d)", uid);
+       _appinfo_foreach(uid, __handle_onboot, data);
+       _signal_send_display_unlock_state(SYSTEM_LCD_OFF, SYSTEM_SLEEP_MARGIN);
+
+       return FALSE;
+}
+
+int _launch_start_onboot_apps(uid_t uid)
+{
+       _signal_send_display_lock_state(SYSTEM_LCD_OFF,
+                       SYSTEM_STAY_CUR_STATE, 0);
+       g_idle_add(__load_onboot_apps, GUINT_TO_POINTER(uid));
+
+       return 0;
+}
+
+int _launch_start_app(const char *appid, request_h req, bool *pending,
+               bool *bg_launch, bool new_instance)
+{
+       int ret;
+       struct launch_s launch_data = {0,};
+       int caller_pid = _request_get_pid(req);
+       uid_t caller_uid = _request_get_uid(req);
+       int cmd = _request_get_cmd(req);
+
+       traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "AMD:START_APP");
+       _D("_launch_start_app: appid=%s caller pid=%d uid=%d",
+                       appid, caller_pid, caller_uid);
+
+       ret = __prepare_starting_app(&launch_data, req, appid, new_instance);
+       if (ret < 0) {
+               _request_send_result(req, ret);
+               traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
+               _util_save_log("FAILURE", appid);
+               return -1;
+       }
+
+       ret = __do_starting_app(&launch_data, req, pending, bg_launch);
+       if (ret < 0) {
+               _request_send_result(req, ret);
+               traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
+               _util_save_log("FAILURE", appid);
+               return -1;
+       }
+
+       if (cmd == APP_START_ASYNC || cmd == APP_START_RES_ASYNC)
+               _request_send_result(req, ret);
+
+       ret = __complete_starting_app(&launch_data, req);
+       traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
+       if (ret < 0)
+               _util_save_log("FAILURE", appid);
+
+       return ret;
+}
diff --git a/src/amd_login_monitor.c b/src/amd_login_monitor.c
new file mode 100644 (file)
index 0000000..8183739
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <systemd/sd-login.h>
+#include <tzplatform_config.h>
+#include <bundle_internal.h>
+
+#include "amd_util.h"
+#include "amd_login_monitor.h"
+#include "amd_appinfo.h"
+#include "amd_app_property.h"
+#include "amd_app_status.h"
+#include "amd_wayland.h"
+#include "amd_socket.h"
+#include "amd_request.h"
+#include "amd_screen_connector.h"
+#include "amd_launch.h"
+#include "amd_signal.h"
+#include "amd_rua.h"
+
+#define PATH_AUL_DAEMONS "/run/aul/daemons"
+#define LOGIN_TIMEOUT_SEC 90
+
+typedef int (*login_cb)(uid_t uid);
+typedef void (*logout_cb)(uid_t uid);
+
+typedef struct login_handler_s {
+       uid_state state;
+       login_cb login;
+} login_handler;
+
+typedef struct logout_handler_s {
+       uid_state state;
+       logout_cb logout;
+} logout_handler;
+
+struct login_monitor_s {
+       sd_login_monitor *m;
+       GIOChannel *io;
+       guint sid;
+};
+
+struct user_s {
+       uid_t uid;
+       uid_state state;
+       guint timer;
+};
+
+static struct login_monitor_s *login_monitor;
+static GList *user_list;
+static login_handler login_table[] = {
+       {
+               .state = UID_STATE_OPENING | UID_STATE_ONLINE |
+                       UID_STATE_ACTIVE,
+               .login = _appinfo_load
+       },
+       {
+               .state = UID_STATE_OPENING | UID_STATE_ONLINE |
+                       UID_STATE_ACTIVE,
+               .login = _app_property_load
+       },
+       {
+               .state = UID_STATE_OPENING | UID_STATE_ONLINE |
+                       UID_STATE_ACTIVE,
+               .login = _app_status_usr_init
+       },
+       {
+               .state = UID_STATE_OPENING | UID_STATE_ONLINE |
+                       UID_STATE_ACTIVE,
+               .login = _screen_connector_usr_init
+       },
+       {
+               .state = UID_STATE_ONLINE | UID_STATE_ACTIVE,
+               .login = _request_usr_init
+       },
+       {
+               .state = UID_STATE_ACTIVE,
+               .login = _launch_start_onboot_apps
+       },
+       {
+               .state = UID_STATE_ONLINE | UID_STATE_ACTIVE,
+               .login = _rua_usr_init
+       }
+};
+static logout_handler logout_table[] = {
+       {
+               .state = UID_STATE_OFFLINE,
+               .logout = _appinfo_unload
+       },
+       {
+               .state = UID_STATE_OFFLINE,
+               .logout = _app_property_unload
+       },
+       {
+               .state = UID_STATE_CLOSING | UID_STATE_OFFLINE,
+               .logout = _app_status_usr_fini
+       },
+       {
+               .state = UID_STATE_CLOSING | UID_STATE_OFFLINE,
+               .logout = _screen_connector_usr_fini
+       },
+       {
+               .state = UID_STATE_CLOSING | UID_STATE_OFFLINE,
+               .logout = _rua_usr_fini
+       }
+};
+
+static int __connect_to_launchpad(uid_t uid);
+static void __user_login(struct user_s *user);
+
+static gboolean __login_timout_handler(gpointer data)
+{
+       struct user_s *user = (struct user_s *)data;
+
+       if (user->state == UID_STATE_ACTIVE) {
+               user->timer = 0;
+               return FALSE;
+       }
+
+       user->timer = 0;
+       user->state = UID_STATE_ACTIVE;
+       __user_login(user);
+
+       return FALSE;
+}
+
+static void __user_login(struct user_s *user)
+{
+       unsigned int i;
+
+       if (user->state == UID_STATE_OPENING) {
+               if (__connect_to_launchpad(user->uid) == 0) {
+                       user->state = UID_STATE_ONLINE;
+                       user->timer = g_timeout_add_seconds(
+                                       LOGIN_TIMEOUT_SEC,
+                                       __login_timout_handler,
+                                       user);
+               }
+       }
+
+       _D("user login - uid(%d), state(%d)", user->uid, user->state);
+       for (i = 0; i < ARRAY_SIZE(login_table); i++) {
+               if (login_table[i].state & user->state) {
+                       if (login_table[i].login)
+                               login_table[i].login(user->uid);
+               }
+       }
+}
+
+static void __user_logout(struct user_s *user)
+{
+       unsigned int i;
+
+       _D("user logout - uid(%d), state(%d)", user->uid, user->state);
+       for (i = 0; i < ARRAY_SIZE(logout_table); i++) {
+               if (logout_table[i].state & user->state) {
+                       if (logout_table[i].logout)
+                               logout_table[i].logout(user->uid);
+               }
+       }
+}
+
+void _login_monitor_set_uid_state(uid_t uid, uid_state state)
+{
+       GList *iter;
+       struct user_s *user;
+
+       if (uid < REGULAR_UID_MIN)
+               return;
+
+       iter = g_list_first(user_list);
+       while (iter) {
+               user = (struct user_s *)iter->data;
+               if (user && user->uid == uid && user->state != state) {
+                       user->state = state;
+                       if (user->state == UID_STATE_ONLINE) {
+                               user->timer = g_timeout_add_seconds(
+                                               LOGIN_TIMEOUT_SEC,
+                                               __login_timout_handler,
+                                               user);
+                               __user_login(user);
+                       } else {
+                               __user_logout(user);
+                       }
+                       break;
+               }
+               iter = g_list_next(iter);
+       }
+}
+
+uid_state _login_monitor_get_uid_state(uid_t uid)
+{
+       GList *iter;
+       uid_state res = UID_STATE_UNKNOWN;
+       struct user_s *user;
+
+       if (uid < REGULAR_UID_MIN)
+               return res;
+
+       iter = g_list_first(user_list);
+       while (iter) {
+               user = (struct user_s *)iter->data;
+               if (user && user->uid == uid) {
+                       res = user->state;
+                       break;
+               }
+               iter = g_list_next(iter);
+       }
+
+       return res;
+}
+
+int _login_monitor_get_uids(uid_t **uids)
+{
+       int r;
+       uid_t *l;
+       GList *iter;
+       unsigned int i = 0;
+       struct user_s *user;
+
+       if (uids == NULL) {
+               _E("Invalid parameter");
+               return -1;
+       }
+
+       if (user_list == NULL)
+               return -1;
+
+       r = g_list_length(user_list);
+       if (r == 0)
+               return 0;
+
+       l = calloc(r, sizeof(uid_t));
+       if (l == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       iter = g_list_first(user_list);
+       while (iter) {
+               user = (struct user_s *)iter->data;
+               l[i++] = user->uid;
+               iter = g_list_next(iter);
+       }
+
+       *uids = l;
+
+       return r;
+}
+
+static int __connect_to_launchpad(uid_t uid)
+{
+       int r;
+       bundle *b;
+       char path[PATH_MAX];
+
+       snprintf(path, sizeof(path), "%s/%d/%s",
+                       PATH_AUL_DAEMONS, uid, LAUNCHPAD_PROCESS_POOL_SOCK);
+       if (access(path, F_OK) != 0) {
+               _D("%s doesn't exist", path);
+               return -1;
+       }
+
+       b = bundle_create();
+       if (b == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       r = _send_cmd_to_launchpad(LAUNCHPAD_PROCESS_POOL_SOCK,
+                       uid, PAD_CMD_PING, b);
+       bundle_free(b);
+       if (r != 0) {
+               _E("Failed to connect launchpad - uid(%d), result(%d)", uid, r);
+               return -1;
+       }
+
+       return 0;
+}
+
+static gint __compare_uids(gconstpointer a, gconstpointer b)
+{
+       struct user_s *user = (struct user_s *)a;
+       uid_t cur_uid = GPOINTER_TO_UINT(b);
+
+       if (user == NULL)
+               return -1;
+
+       if (user->uid == cur_uid)
+               return 0;
+
+       return -1;
+}
+
+static void __check_user_state(void)
+{
+       uid_t *uids = NULL;
+       int ret;
+       int i;
+       GList *list;
+       char *state = NULL;
+       struct user_s *user;
+
+       ret = sd_get_uids(&uids);
+       if (ret <= 0) {
+               _W("Failed to get uids - %d", ret);
+               return;
+       }
+
+       for (i = 0; i < ret; i++) {
+               if (uids[i] < REGULAR_UID_MIN)
+                       continue;
+
+               if (sd_uid_get_state(uids[i], &state) < 0)
+                       continue;
+
+               list = g_list_find_custom(user_list,
+                               GUINT_TO_POINTER(uids[i]),
+                               __compare_uids);
+
+               if (strcmp(state, "opening") == 0 ||
+                               strcmp(state, "online") == 0) {
+                       if (list == NULL) {
+                               user = malloc(sizeof(struct user_s));
+                               if (user == NULL) {
+                                       _E("out of memory");
+                                       free(uids);
+                                       return;
+                               }
+                               user->uid = uids[i];
+                               user->state = UID_STATE_OPENING;
+                               user->timer = 0;
+                               user_list = g_list_append(user_list, user);
+                               __user_login(user);
+                       }
+               } else if (strcmp(state, "closing") == 0) {
+                       if (list) {
+                               user = (struct user_s *)list->data;
+                               if (user) {
+                                       user->state = UID_STATE_CLOSING;
+                                       __user_logout(user);
+                               }
+                       }
+               } else if (strcmp(state, "offline") == 0) {
+                       if (list) {
+                               user = (struct user_s *)list->data;
+                               if (user) {
+                                       user_list = g_list_remove(user_list,
+                                                       user);
+                                       user->state = UID_STATE_OFFLINE;
+                                       __user_logout(user);
+                                       if (user->timer)
+                                               g_source_remove(user->timer);
+                                       free(user);
+                               }
+                       }
+               }
+               _D("uid(%d), state(%s)", uids[i], state);
+               free(state);
+               state = NULL;
+       }
+       free(uids);
+}
+
+static gboolean __monitor_login_cb(GIOChannel *io, GIOCondition condition,
+               gpointer data)
+{
+       _D("login monitor");
+       sd_login_monitor_flush(login_monitor->m);
+
+       __check_user_state();
+
+       return TRUE;
+}
+
+static int __init_login_monitor(void)
+{
+       int r;
+       int fd;
+
+       login_monitor = (struct login_monitor_s *)calloc(1,
+                       sizeof(struct login_monitor_s));
+       if (login_monitor == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       r = sd_login_monitor_new("uid", &login_monitor->m);
+       if (r < 0) {
+               _E("Failed to create sd login monitor");
+               return -1;
+       }
+
+       fd = sd_login_monitor_get_fd(login_monitor->m);
+       if (fd < 0) {
+               _E("Failed to get file descriptor");
+               return -1;
+       }
+
+       login_monitor->io = g_io_channel_unix_new(fd);
+       if (login_monitor->io == NULL) {
+               _E("Failed to create GIOChannel");
+               return -1;
+       }
+
+       login_monitor->sid = g_io_add_watch(login_monitor->io,
+                       G_IO_IN | G_IO_HUP, __monitor_login_cb, NULL);
+       if (login_monitor->sid == 0) {
+               _E("Failed to add gio watch");
+               return -1;
+       }
+
+       return 0;
+}
+
+static void __fini_login_monitor(void)
+{
+       if (login_monitor == NULL)
+               return;
+
+       if (login_monitor->sid) {
+               g_source_remove(login_monitor->sid);
+               login_monitor->sid = 0;
+       }
+
+       if (login_monitor->io) {
+               g_io_channel_unref(login_monitor->io);
+               login_monitor->io = NULL;
+       }
+
+       if (login_monitor->m) {
+               sd_login_monitor_unref(login_monitor->m);
+               login_monitor->m = NULL;
+       }
+
+       free(login_monitor);
+       login_monitor = NULL;
+}
+
+static int __startup_finished_cb(uid_t uid, void *user_data)
+{
+       GList *list;
+       struct user_s *user;
+
+       _D("uid(%d)", uid);
+       if (uid < REGULAR_UID_MIN)
+               return -1;
+
+       list = g_list_find_custom(user_list, GUINT_TO_POINTER(uid),
+                       __compare_uids);
+       if (list == NULL) {
+               user = malloc(sizeof(struct user_s));
+               if (user == NULL) {
+                       _E("out of memory");
+                       return -1;
+               }
+               user->uid = uid;
+               user->timer = 0;
+               user_list = g_list_append(user_list, user);
+       } else {
+               user = (struct user_s *)list->data;
+               if (user == NULL)
+                       return -1;
+       }
+
+       if (user->timer) {
+               g_source_remove(user->timer);
+               user->timer = 0;
+       }
+
+       user->state = UID_STATE_ACTIVE;
+       __user_login(user);
+
+       return 0;
+}
+
+static int __subscribe_startup_finished(void *data)
+{
+       return _signal_subscribe_startup_finished(__startup_finished_cb, data);
+}
+
+int _login_monitor_init(void)
+{
+       uid_t uid;
+       struct user_s *user;
+
+       _D("login monitor init");
+       if (__init_login_monitor()) {
+               _E("Failed to initialize login monitor");
+               __fini_login_monitor();
+               return -1;
+       }
+
+       __check_user_state();
+
+       if (user_list == NULL || g_list_length(user_list) == 0) {
+               uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+               _D("default user(%d)", uid);
+               user = malloc(sizeof(struct user_s));
+               if (user == NULL) {
+                       _E("out of memory");
+                       return -1;
+               }
+               user->uid = uid;
+               user->timer = 0;
+               user->state = UID_STATE_OPENING;
+               user_list = g_list_append(user_list, user);
+               __user_login(user);
+       }
+
+       if (__subscribe_startup_finished(NULL) < 0)
+               _signal_add_initializer(__subscribe_startup_finished, NULL);
+
+       return 0;
+}
+
+void _login_monitor_fini(void)
+{
+       _D("login monitor fini");
+
+       _signal_unsubscribe_startup_finished();
+
+       if (user_list)
+               g_list_free_full(user_list, free);
+
+       __fini_login_monitor();
+}
diff --git a/src/amd_main.c b/src/amd_main.c
new file mode 100644 (file)
index 0000000..07d98ac
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <aul.h>
+#include <glib.h>
+#include <tzplatform_config.h>
+#include <systemd/sd-daemon.h>
+
+#include "amd_util.h"
+#include "amd_appinfo.h"
+#include "amd_app_status.h"
+#include "amd_launch.h"
+#include "amd_request.h"
+#include "amd_app_group.h"
+#include "amd_cynara.h"
+#include "amd_app_com.h"
+#include "amd_share.h"
+#include "amd_socket.h"
+#include "amd_splash_screen.h"
+#include "amd_input.h"
+#include "amd_signal.h"
+#include "amd_wayland.h"
+#include "amd_extractor.h"
+#include "amd_suspend.h"
+#include "amd_widget.h"
+#include "amd_app_property.h"
+#include "amd_screen_connector.h"
+#include "amd_login_monitor.h"
+#include "amd_rua.h"
+#include "amd_inotify.h"
+
+struct restart_info {
+       char *appid;
+       int count;
+       guint timer;
+};
+
+static GHashTable *restart_tbl;
+
+static gboolean __restart_timeout_handler(void *data)
+{
+       struct restart_info *ri = (struct restart_info *)data;
+
+       _D("ri (%x)", ri);
+       _D("appid (%s)", ri->appid);
+
+       g_hash_table_remove(restart_tbl, ri->appid);
+       free(ri->appid);
+       free(ri);
+
+       return FALSE;
+}
+
+static bool __check_restart(const char *appid)
+{
+       struct restart_info *ri = NULL;
+       char err_buf[1024];
+
+       ri = g_hash_table_lookup(restart_tbl, appid);
+       if (!ri) {
+               ri = malloc(sizeof(struct restart_info));
+               if (!ri) {
+                       _E("create restart info: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+                       return false;
+               }
+               memset(ri, 0, sizeof(struct restart_info));
+               ri->appid = strdup(appid);
+               ri->count = 1;
+               g_hash_table_insert(restart_tbl, ri->appid, ri);
+
+               _D("ri (%x)", ri);
+               _D("appid (%s)", appid);
+
+               ri->timer = g_timeout_add(10 * 1000, __restart_timeout_handler,
+                               ri);
+       } else {
+               ri->count++;
+               _D("count (%d)", ri->count);
+               if (ri->count > 5) {
+                       g_source_remove(ri->timer);
+                       g_hash_table_remove(restart_tbl, ri->appid);
+                       free(ri->appid);
+                       free(ri);
+                       return false;
+               }
+       }
+       return true;
+}
+
+static bool __can_restart_app(const char *appid, uid_t uid)
+{
+       const char *pkg_status;
+       const char *component_type;
+       struct appinfo *ai;
+       int r;
+       int val = 0;
+       int enable = 1;
+
+       _D("appid: %s", appid);
+       ai = _appinfo_find(uid, appid);
+       if (!ai)
+               return false;
+
+       component_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (!component_type)
+               return false;
+
+       if (strcmp(component_type, APP_TYPE_SERVICE) != 0)
+               return false;
+
+       r = _appinfo_get_int_value(ai, AIT_ENABLEMENT, &enable);
+       if (r == 0 && !(enable & APP_ENABLEMENT_MASK_ACTIVE)) {
+               _D("Disabled");
+               return false;
+       }
+
+       pkg_status = _appinfo_get_value(ai, AIT_STATUS);
+       if (pkg_status && strcmp(pkg_status, "blocking") == 0) {
+               _appinfo_set_value(ai, AIT_STATUS, "restart");
+       } else if (pkg_status && strcmp(pkg_status, "norestart") == 0) {
+               _appinfo_set_value(ai, AIT_STATUS, "installed");
+       } else {
+               r = _appinfo_get_int_value(ai, AIT_RESTART, &val);
+               if (r == 0 && val && __check_restart(appid))
+                       return true;
+       }
+
+       return false;
+}
+
+static int __app_dead_handler(int pid, void *data)
+{
+       bool restart = false;
+       char *appid = NULL;
+       const char *tmp_appid;
+       app_status_h app_status;
+       splash_image_h splash_image;
+       uid_t uid;
+       char buf[MAX_LOCAL_BUFSZ];
+       int app_type;
+
+       if (pid <= 0)
+               return 0;
+
+       _D("APP_DEAD_SIGNAL : %d", pid);
+
+       splash_image = _splash_screen_get_image(pid);
+       if (splash_image)
+               _splash_screen_destroy_image(splash_image);
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return 0;
+
+       tmp_appid = _app_status_get_appid(app_status);
+       if (tmp_appid == NULL)
+               return 0;
+
+       uid = _app_status_get_uid(app_status);
+       app_type = _app_status_get_app_type(app_status);
+
+       if (app_type == AT_WIDGET_APP) {
+               _widget_dead_handler(
+                               pid,
+                               uid,
+                               _app_status_get_pkgid(app_status),
+                               _app_status_get_org_caller_pid(app_status),
+                               _app_status_get_is_exit_notified(app_status),
+                               __check_restart(tmp_appid)
+                               );
+       } else if (app_type == AT_WATCH_APP) {
+               _app_status_fault_recovery(
+                               pid,
+                               uid,
+                               _app_status_get_pkgid(app_status),
+                               tmp_appid,
+                               app_type,
+                               _app_status_get_is_exit_notified(app_status));
+
+       }
+
+       restart = __can_restart_app(tmp_appid, uid);
+       if (restart)
+               appid = strdup(tmp_appid);
+
+       _request_flush_pending_request(pid);
+       _app_status_publish_status(pid, STATUS_TERMINATE);
+       _app_status_cleanup(app_status);
+
+       if (restart)
+               _launch_start_app_local(uid, appid);
+       if (appid)
+               free(appid);
+
+       snprintf(buf, sizeof(buf), "%d", pid);
+       _util_save_log("TERMINATED", buf);
+       return 0;
+}
+
+static int __listen_app_dead_signal(void *data)
+{
+       int ret;
+
+       ret = aul_listen_app_dead_signal(__app_dead_handler, data);
+       if (ret < 0)
+               return -1;
+
+       return 0;
+}
+
+static void __ignore_app_dead_signal(void)
+{
+       aul_listen_app_dead_signal(NULL, NULL);
+}
+
+static int __init(void)
+{
+       int r;
+
+       if (_appinfo_init()) {
+               _E("_appinfo_init failed");
+               return -1;
+       }
+
+       if (__listen_app_dead_signal(NULL) < 0) {
+               _W("aul_listen_app_dead_signal failed");
+               _signal_add_initializer(__listen_app_dead_signal, NULL);
+       }
+
+       restart_tbl = g_hash_table_new(g_str_hash, g_str_equal);
+
+       r = _cynara_init();
+       if (r != 0) {
+               _E("cynara initialize failed.");
+               return -1;
+       }
+
+       _request_init();
+       _app_status_init();
+       _app_group_init();
+       _app_com_broker_init();
+       _launch_init();
+       _splash_screen_init();
+#ifdef TIZEN_FEATURE_BLOCK_INPUT
+       _input_init();
+#endif /* TIZEN_FEATURE_BLOCK_INPUT */
+       _wayland_init();
+       _suspend_init();
+       _signal_init();
+       _widget_init();
+       _app_property_init();
+       _screen_connector_init();
+       _login_monitor_init();
+       _util_init();
+       _rua_init();
+       _inotify_init();
+
+       return 0;
+}
+
+static void __ready(void)
+{
+       int fd;
+
+       _D("AMD is ready");
+
+       fd = creat("/run/.amd_ready",
+               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+       if (fd != -1)
+               close(fd);
+
+       sd_notify(0, "READY=1");
+}
+
+static void __finish(void)
+{
+       _inotify_fini();
+       _rua_fini();
+       _util_fini();
+       _login_monitor_fini();
+       _screen_connector_fini();
+       _app_property_fini();
+       _widget_fini();
+       _suspend_fini();
+       _wayland_finish();
+#ifdef TIZEN_FEATURE_BLOCK_INPUT
+       _input_fini();
+#endif /* TIZEN_FEATURE_BLOCK_INPUT */
+       _app_com_broker_fini();
+       _app_group_fini();
+       _app_status_finish();
+       _request_fini();
+       _cynara_finish();
+
+       if (restart_tbl) {
+               g_hash_table_destroy(restart_tbl);
+               restart_tbl = NULL;
+       }
+
+       __ignore_app_dead_signal();
+
+       _appinfo_fini();
+}
+
+int main(int argc, char *argv[])
+{
+       GMainLoop *mainloop = NULL;
+
+       if (__init() != 0) {
+               _E("AMD Initialization failed!\n");
+               return -1;
+       }
+
+       __ready();
+
+       mainloop = g_main_loop_new(NULL, FALSE);
+       if (!mainloop) {
+               _E("failed to create glib main loop");
+               return -1;
+       }
+       g_main_loop_run(mainloop);
+
+       __finish();
+
+       return 0;
+}
diff --git a/src/amd_request.c b/src/amd_request.c
new file mode 100644 (file)
index 0000000..473de1b
--- /dev/null
@@ -0,0 +1,3927 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <poll.h>
+#include <ctype.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <aul.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <rua_internal.h>
+#include <rua_stat_internal.h>
+#include <tzplatform_config.h>
+#include <systemd/sd-login.h>
+#include <aul_sock.h>
+#include <aul_svc.h>
+#include <aul_app_com.h>
+#include <aul_screen_connector.h>
+
+#include "amd_util.h"
+#include "amd_request.h"
+#include "amd_launch.h"
+#include "amd_appinfo.h"
+#include "amd_app_status.h"
+#include "amd_app_group.h"
+#include "amd_cynara.h"
+#include "amd_socket.h"
+#include "amd_app_com.h"
+#include "amd_share.h"
+#include "amd_input.h"
+#include "amd_widget.h"
+#include "aul_svc_priv_key.h"
+#include "amd_signal.h"
+#include "amd_app_property.h"
+#include "amd_screen_connector.h"
+#include "amd_login_monitor.h"
+#include "amd_rua.h"
+
+#define INHOUSE_UID     tzplatform_getuid(TZ_USER_NAME)
+
+#define MAX_NR_OF_DESCRIPTORS 2
+#define PENDING_REQUEST_TIMEOUT 5000 /* msec */
+#define SYSTEM_REQUEST_TIMEOUT 90000 /* msec */
+#define PENDING_MESSAGE_MAX_CNT 100
+#define MULTI_INSTANCE_SHORTCUT "multi-instance-shortcut"
+#define QUERY_KEY_ID "id="
+#define QUERY_KEY_ICON "icon="
+#define QUERY_KEY_NAME "name="
+
+static int amd_fd;
+static GIOChannel *amd_io;
+static guint amd_wid;
+static GHashTable *__dc_socket_pair_hash;
+static GHashTable *pending_table;
+
+struct pending_item {
+       int pid;
+       guint timer;
+       GList *pending_list;
+       GList *reply_list;
+};
+
+struct request_s {
+       GTimeVal start;
+       guint timer;
+       int cmd;
+       int clifd;
+       pid_t pid;
+       pid_t t_pid;
+       uid_t uid;
+       uid_t t_uid;
+       bundle *kb;
+       int len;
+       int opt;
+       unsigned char data[1];
+};
+
+typedef struct _rua_stat_pkt_t {
+       pid_t pid;
+       uid_t uid;
+       char *stat_tag;
+       char *stat_caller;
+       char *appid;
+       char *instance_id;
+       char *instance_name;
+       char *icon;
+       char *uri;
+       gboolean is_group_app;
+       char *data;
+       int len;
+} rua_stat_pkt_t;
+
+struct reply_info {
+       guint timer;
+       pid_t pid;
+       int result;
+       int cmd;
+       int clifd;
+       rua_stat_pkt_t *rua;
+};
+
+struct instance_info {
+       char *id;
+       char *name;
+       char *icon;
+       char *uri;
+};
+
+typedef int (*app_cmd_dispatch_func)(request_h req);
+static gboolean __timeout_pending_item(gpointer user_data);
+static gboolean __dispatch_request(gpointer data);
+static gboolean __timeout_request(gpointer data);
+static gboolean __timeout_reply(gpointer data);
+static struct reply_info *__create_reply_info(guint interval, pid_t pid,
+               int result, int cmd, int clifd, rua_stat_pkt_t *rua);
+
+static int __send_message(int sock, const struct iovec *vec, int vec_size,
+               const int *desc, int nr_desc)
+{
+       struct msghdr msg = {0,};
+       int sndret;
+       int desclen = 0;
+       struct cmsghdr *cmsg = NULL;
+       char buff[CMSG_SPACE(sizeof(int) * MAX_NR_OF_DESCRIPTORS)] = {0,};
+
+       if (vec == NULL || vec_size < 1)
+               return -EINVAL;
+       if (nr_desc < 0 || nr_desc > MAX_NR_OF_DESCRIPTORS)
+               return -EINVAL;
+       if (desc == NULL)
+               nr_desc = 0;
+
+       msg.msg_iov = (struct iovec *)vec;
+       msg.msg_iovlen = vec_size;
+
+       /* sending ancillary data */
+       if (nr_desc > 0) {
+               msg.msg_control = buff;
+               msg.msg_controllen = sizeof(buff);
+               cmsg = CMSG_FIRSTHDR(&msg);
+               if (cmsg == NULL)
+                       return -EINVAL;
+
+               /* packing files descriptors */
+               if (nr_desc > 0) {
+                       cmsg->cmsg_level = SOL_SOCKET;
+                       cmsg->cmsg_type = SCM_RIGHTS;
+                       desclen = cmsg->cmsg_len =
+                               CMSG_LEN(sizeof(int) * nr_desc);
+                       memcpy((int *)CMSG_DATA(cmsg), desc,
+                                       sizeof(int) * nr_desc);
+                       cmsg = CMSG_NXTHDR(&msg, cmsg);
+                       _D("packing file descriptors done");
+               }
+
+               /* finished packing updating the corect length */
+               msg.msg_controllen = desclen;
+       } else {
+               msg.msg_control = NULL;
+               msg.msg_controllen = 0;
+       }
+
+       sndret = sendmsg(sock, &msg, 0);
+       _D("sendmsg ret : %d", sndret);
+       if (sndret < 0)
+               return -errno;
+
+       return sndret;
+}
+
+static int __get_caller_pid(bundle *kb)
+{
+       const char *pid_str;
+       int pid;
+
+       pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
+       if (pid_str)
+               goto end;
+
+       pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
+       if (pid_str == NULL)
+               return -1;
+
+end:
+       pid = atoi(pid_str);
+       if (pid <= 1)
+               return -1;
+
+       return pid;
+}
+
+static int __app_process_by_pid(request_h req, const char *pid_str,
+               bool *pending)
+{
+       int pid;
+       int ret;
+       int dummy;
+       const char *appid;
+       const char *pkgid;
+       const char *type;
+       const struct appinfo *ai;
+       uid_t target_uid = _request_get_target_uid(req);
+       app_status_h app_status;
+
+       if (pid_str == NULL)
+               return -1;
+
+       pid = atoi(pid_str);
+       if (pid <= 1) {
+               _E("invalid pid");
+               return -1;
+       }
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               _E("pid %d is not an application", pid);
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       appid = _app_status_get_appid(app_status);
+       ai = _appinfo_find(target_uid, appid);
+       if (ai == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       pkgid = _appinfo_get_value(ai, AIT_PKGID);
+       type = _appinfo_get_value(ai, AIT_COMPTYPE);
+
+       switch (req->cmd) {
+       case APP_RESUME_BY_PID:
+       case APP_RESUME_BY_PID_ASYNC:
+       case APP_PAUSE_BY_PID:
+               aul_send_app_resume_request_signal(pid, appid, pkgid, type);
+               break;
+       default:
+               aul_send_app_terminate_request_signal(pid, appid, pkgid, type);
+               break;
+       }
+
+       switch (req->cmd) {
+       case APP_RESUME_BY_PID_ASYNC:
+               _request_send_result(req, 0);
+       case APP_RESUME_BY_PID:
+               ret = _resume_app(pid, req);
+               break;
+       case APP_TERM_BY_PID:
+       case APP_TERM_BY_PID_WITHOUT_RESTART:
+               ret = _term_app(pid, req);
+               break;
+       case APP_TERM_BGAPP_BY_PID:
+               ret = _term_bgapp(pid, req);
+               break;
+       case APP_KILL_BY_PID:
+               ret = _send_to_sigkill(pid);
+               if (ret < 0)
+                       _E("fail to killing - %d\n", pid);
+               _app_status_update_status(app_status, STATUS_DYING, false, true);
+               _request_send_result(req, ret);
+               break;
+       case APP_TERM_REQ_BY_PID:
+               ret = _term_req_app(pid, req);
+               break;
+       case APP_TERM_BY_PID_ASYNC:
+               ret = aul_sock_send_raw(pid, target_uid, req->cmd,
+                               (unsigned char *)&dummy, sizeof(int),
+                               AUL_SOCK_NOREPLY);
+               if (ret < 0)
+                       _D("terminate req packet send error");
+
+               _request_send_result(req, ret);
+               break;
+       case APP_PAUSE_BY_PID:
+               ret = _pause_app(pid, req);
+               break;
+       case APP_TERM_BY_PID_SYNC:
+       case APP_TERM_BY_PID_SYNC_WITHOUT_RESTART:
+               if (_app_status_get_status(app_status) == STATUS_DYING) {
+                       _W("%d is dying", pid);
+                       if (pending)
+                               *pending = true;
+                       ret = 0;
+                       break;
+               }
+               ret = _term_app_v2(pid, req, pending);
+               break;
+       default:
+               _E("unknown command: %d", req->cmd);
+               ret = -1;
+       }
+
+       return ret;
+}
+
+static void __set_effective_appid(uid_t uid, bundle *kb)
+{
+       const struct appinfo *ai;
+       const struct appinfo *effective_ai;
+       const char *appid;
+       const char *effective_appid;
+       const char *pkgid;
+       const char *effective_pkgid;
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       if (appid == NULL)
+               return;
+
+       ai = _appinfo_find(uid, appid);
+       if (ai == NULL)
+               return;
+
+       bundle_del(kb, AUL_SVC_K_PKG_NAME);
+       bundle_add(kb, AUL_SVC_K_PKG_NAME, appid);
+
+       effective_appid = _appinfo_get_value(ai, AIT_EFFECTIVE_APPID);
+       if (effective_appid == NULL)
+               return;
+
+       effective_ai = _appinfo_find(uid, effective_appid);
+       if (effective_ai == NULL)
+               return;
+
+       pkgid = _appinfo_get_value(ai, AIT_PKGID);
+       effective_pkgid = _appinfo_get_value(effective_ai, AIT_PKGID);
+       if (pkgid && effective_pkgid && strcmp(pkgid, effective_pkgid) == 0) {
+               _D("use effective appid instead of the real appid");
+               bundle_del(kb, AUL_K_APPID);
+               bundle_add(kb, AUL_K_APPID, effective_appid);
+       }
+}
+
+static void __set_real_appid(uid_t uid, bundle *kb)
+{
+       const char *alias_appid;
+       const char *appid;
+       const char *alias_info;
+       app_property_h app_property;
+
+       alias_appid = bundle_get_val(kb, AUL_K_APPID);
+       if (alias_appid == NULL)
+               return;
+
+       alias_info = bundle_get_val(kb, AUL_SVC_K_ALIAS_INFO);
+       if (alias_info && strcmp(alias_info, "disable") == 0)
+               return;
+
+       app_property = _app_property_find(uid);
+       if (app_property == NULL)
+               return;
+
+       appid = _app_property_get_real_appid(app_property, alias_appid);
+       if (appid == NULL)
+               return;
+
+       _D("alias_appid(%s), appid(%s)", alias_appid, appid);
+       bundle_del(kb, AUL_K_ORG_APPID);
+       bundle_add(kb, AUL_K_ORG_APPID, alias_appid);
+       bundle_del(kb, AUL_K_APPID);
+       bundle_add(kb, AUL_K_APPID, appid);
+}
+
+static void __free_rua_stat_pkt(rua_stat_pkt_t *pkt)
+{
+       if (pkt == NULL)
+               return;
+
+       if (pkt->data)
+               free(pkt->data);
+       if (pkt->uri)
+               free(pkt->uri);
+       if (pkt->icon)
+               free(pkt->icon);
+       if (pkt->instance_name)
+               free(pkt->instance_name);
+       if (pkt->instance_id)
+               free(pkt->instance_id);
+       if (pkt->appid)
+               free(pkt->appid);
+       if (pkt->stat_caller)
+               free(pkt->stat_caller);
+       if (pkt->stat_tag)
+               free(pkt->stat_tag);
+
+       free(pkt);
+}
+
+static gboolean __add_history_handler(gpointer user_data)
+{
+       struct rua_rec rec = { 0, };
+       int ret;
+       struct appinfo *ai;
+       rua_stat_pkt_t *pkt = (rua_stat_pkt_t *)user_data;
+
+       if (!pkt)
+               return FALSE;
+
+       if (!pkt->is_group_app) {
+               ai = _appinfo_find(pkt->uid, pkt->appid);
+
+               rec.pkg_name = pkt->appid;
+               rec.app_path = (char *)_appinfo_get_value(ai, AIT_EXEC);
+
+               if (pkt->len > 0)
+                       rec.arg = pkt->data;
+
+               rec.launch_time = time(NULL);
+               rec.instance_id = pkt->instance_id;
+               rec.instance_name = pkt->instance_name;
+               rec.icon = pkt->icon;
+               rec.uri = pkt->uri;
+               rec.image = (char *)_rua_get_image_path(pkt->pid);
+
+               SECURE_LOGD("add rua history %s %s",
+                               rec.pkg_name, rec.app_path);
+               ret = rua_usr_db_add_history(&rec, pkt->uid);
+               if (ret == -1)
+                       _D("rua add history error");
+       }
+
+       if (pkt->stat_caller != NULL && pkt->stat_tag != NULL) {
+               SECURE_LOGD("rua_stat_caller: %s, rua_stat_tag: %s",
+                               pkt->stat_caller, pkt->stat_tag);
+               rua_stat_usr_db_update(pkt->stat_caller, pkt->stat_tag,
+                               pkt->uid);
+       }
+
+       __free_rua_stat_pkt(pkt);
+
+       return FALSE;
+}
+
+static rua_stat_pkt_t *__create_rua_stat_pkt(request_h req, bundle *kb,
+               const char *appid, struct instance_info *info, int pid)
+{
+       const char *stat_caller;
+       const char *stat_tag;
+       rua_stat_pkt_t *rua_stat_item;
+
+       rua_stat_item = calloc(1, sizeof(rua_stat_pkt_t));
+       if (rua_stat_item == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       rua_stat_item->pid = pid;
+
+       if (req->len > 0) {
+               rua_stat_item->data = calloc(req->len + 1, sizeof(char));
+               if (rua_stat_item->data == NULL) {
+                       _E("out of memory");
+                       __free_rua_stat_pkt(rua_stat_item);
+                       return NULL;
+               }
+               memcpy(rua_stat_item->data, req->data, req->len);
+       }
+       rua_stat_item->len = req->len;
+
+       stat_caller = bundle_get_val(kb, AUL_SVC_K_RUA_STAT_CALLER);
+       if (stat_caller != NULL) {
+               rua_stat_item->stat_caller = strdup(stat_caller);
+               if (rua_stat_item->stat_caller == NULL) {
+                       _E("Out of memory");
+                       __free_rua_stat_pkt(rua_stat_item);
+                       return NULL;
+               }
+       }
+
+       stat_tag = bundle_get_val(kb, AUL_SVC_K_RUA_STAT_TAG);
+       if (stat_tag != NULL) {
+               rua_stat_item->stat_tag = strdup(stat_tag);
+               if (rua_stat_item->stat_tag == NULL) {
+                       _E("Out of memory");
+                       __free_rua_stat_pkt(rua_stat_item);
+                       return NULL;
+               }
+
+       }
+
+       if (appid) {
+               rua_stat_item->appid = strdup(appid);
+               if (rua_stat_item->appid == NULL) {
+                       _E("Out of memory");
+                       __free_rua_stat_pkt(rua_stat_item);
+                       return NULL;
+               }
+       }
+
+       if (info->id) {
+               rua_stat_item->instance_id = strdup(info->id);
+               if (rua_stat_item->instance_id == NULL) {
+                       _E("Out of memory");
+                       __free_rua_stat_pkt(rua_stat_item);
+                       return NULL;
+               }
+       }
+
+       if (info->name) {
+               rua_stat_item->instance_name = strdup(info->name);
+               if (rua_stat_item->instance_name == NULL) {
+                       _E("Out of memory");
+                       __free_rua_stat_pkt(rua_stat_item);
+                       return NULL;
+               }
+       }
+
+       if (info->icon) {
+               rua_stat_item->icon = strdup(info->icon);
+               if (rua_stat_item->icon == NULL) {
+                       _E("Out of memory");
+                       __free_rua_stat_pkt(rua_stat_item);
+                       return NULL;
+               }
+       }
+
+       if (info->uri) {
+               rua_stat_item->uri = strdup(info->uri);
+               if (rua_stat_item->uri == NULL) {
+                       _E("Out of memory");
+                       __free_rua_stat_pkt(rua_stat_item);
+                       return NULL;
+               }
+       }
+
+       rua_stat_item->uid = _request_get_target_uid(req);
+       rua_stat_item->is_group_app = _app_group_is_group_app(kb,
+                       rua_stat_item->uid);
+
+       return rua_stat_item;
+}
+
+static int __dispatch_get_mp_socket_pair(request_h req)
+{
+       int handles[2] = {0, 0};
+       struct iovec vec[3];
+       int msglen = 0;
+       char buffer[1024];
+       int ret;
+       struct timeval read_timeout;
+       struct timeval write_timeout;
+
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) {
+               _E("error create socket pair");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       if (handles[0] == -1) {
+               _E("error socket open");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       read_timeout.tv_sec = 5;
+       read_timeout.tv_usec = 0;
+       write_timeout.tv_sec = 25; /*dbus default timeout */
+       write_timeout.tv_usec = 0;
+
+       ret = setsockopt(handles[0], SOL_SOCKET, SO_RCVTIMEO, &read_timeout, sizeof(read_timeout));
+       if (ret < 0) {
+               _E("Cannot Set SO_RCVTIMEO for socket %d", handles[0]);
+               _request_send_result(req, -1);
+               goto out;
+       }
+
+       ret = setsockopt(handles[0], SOL_SOCKET, SO_SNDTIMEO, &write_timeout, sizeof(write_timeout));
+       if (ret < 0) {
+               _E("Cannot Set SO_SNDTIMEO for socket %d", handles[0]);
+               _request_send_result(req, -1);
+               goto out;
+       }
+
+       ret = setsockopt(handles[1], SOL_SOCKET, SO_RCVTIMEO, &read_timeout, sizeof(read_timeout));
+       if (ret < 0) {
+               _E("Cannot Set SO_RCVTIMEO for socket %d", handles[1]);
+               _request_send_result(req, -1);
+               goto out;
+       }
+
+       ret = setsockopt(handles[1], SOL_SOCKET, SO_SNDTIMEO, &write_timeout, sizeof(write_timeout));
+       if (ret < 0) {
+               _E("Cannot Set SO_SNDTIMEO for socket %d", handles[1]);
+               _request_send_result(req, -1);
+               goto out;
+       }
+
+       _D("amd send mp fd : [%d, %d]", handles[0], handles[1]);
+       vec[0].iov_base = buffer;
+       vec[0].iov_len = strlen(buffer) + 1;
+
+       msglen = __send_message(req->clifd, vec, 1, handles, 2);
+       if (msglen < 0) {
+               _E("Error[%d]: while sending message\n", -msglen);
+               _request_send_result(req, -1);
+               ret = -1;
+       }
+out:
+       close(handles[0]);
+       close(handles[1]);
+
+       return ret;
+}
+
+static int __dispatch_get_dc_socket_pair(request_h req)
+{
+       const char *caller;
+       const char *callee;
+       const char *datacontrol_type;
+       char *socket_pair_key = NULL;
+       int socket_pair_key_len;
+       int *handles = NULL;
+       struct iovec vec[3];
+       int msglen = 0;
+       char buffer[1024];
+       bundle *kb = req->kb;
+       struct timeval tv;
+       int ret;
+
+       caller = bundle_get_val(kb, AUL_K_CALLER_APPID);
+       if (caller == NULL)
+               goto err_out;
+       callee = bundle_get_val(kb, AUL_K_CALLEE_APPID);
+       if (callee == NULL)
+               goto err_out;
+       datacontrol_type = bundle_get_val(kb, "DATA_CONTOL_TYPE");
+
+       socket_pair_key_len = strlen(caller) + strlen(callee) + 2;
+
+       socket_pair_key = (char *)calloc(socket_pair_key_len, sizeof(char));
+       if (socket_pair_key == NULL) {
+               _E("calloc fail");
+               goto err_out;
+       }
+
+       snprintf(socket_pair_key, socket_pair_key_len, "%s_%s", caller, callee);
+       _D("socket pair key : %s", socket_pair_key);
+
+       handles = g_hash_table_lookup(__dc_socket_pair_hash, socket_pair_key);
+       if (handles == NULL) {
+               handles = (int *)calloc(2, sizeof(int));
+               if (handles == NULL) {
+                       _E("calloc fail");
+                       goto err_out;
+               }
+
+               if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) {
+                       _E("error create socket pair");
+                       _request_send_result(req, -1);
+                       free(handles);
+                       handles = NULL;
+                       goto err_out;
+               }
+
+               if (handles[0] == -1 || handles[1] == -1) {
+                       _E("error socket open");
+                       _request_send_result(req, -1);
+                       free(handles);
+                       handles = NULL;
+                       goto err_out;
+               }
+
+               tv.tv_sec = 5;
+               tv.tv_usec = 0;
+               ret = setsockopt(handles[0], SOL_SOCKET, SO_RCVTIMEO, &tv,
+                               sizeof(tv));
+               if (ret < 0) {
+                       _E("Cannot Set SO_RCVTIMEO for socket %d", handles[0]);
+                       _request_send_result(req, -1);
+                       close(handles[0]);
+                       close(handles[1]);
+                       free(handles);
+                       handles = NULL;
+                       goto err_out;
+               }
+
+               ret = setsockopt(handles[1], SOL_SOCKET, SO_RCVTIMEO, &tv,
+                               sizeof(tv));
+               if (ret < 0) {
+                       _E("Cannot Set SO_RCVTIMEO for socket %d", handles[1]);
+                       _request_send_result(req, -1);
+                       close(handles[0]);
+                       close(handles[1]);
+                       free(handles);
+                       handles = NULL;
+                       goto err_out;
+               }
+
+               g_hash_table_insert(__dc_socket_pair_hash,
+                               strdup(socket_pair_key), handles);
+               _D("New socket pair insert done.");
+       }
+
+       SECURE_LOGD("amd send fd : [%d, %d]", handles[0], handles[1]);
+       vec[0].iov_base = buffer;
+       vec[0].iov_len = 1;
+
+       if (datacontrol_type != NULL) {
+               _D("datacontrol_type : %s", datacontrol_type);
+               if (strcmp(datacontrol_type, "consumer") == 0) {
+                       msglen = __send_message(req->clifd, vec, 1,
+                                       &handles[0], 1);
+                       if (msglen < 0) {
+                               _E("Error[%d]: while sending message", -msglen);
+                               _request_send_result(req, -1);
+                               goto err_out;
+                       }
+                       close(handles[0]);
+                       handles[0] = -1;
+                       if (handles[1] == -1) {
+                               _E("remove from hash : %s", socket_pair_key);
+                               g_hash_table_remove(__dc_socket_pair_hash,
+                                               socket_pair_key);
+                       }
+
+               } else {
+                       msglen = __send_message(req->clifd, vec, 1,
+                                       &handles[1], 1);
+                       if (msglen < 0) {
+                               _E("Error[%d]: while sending message", -msglen);
+                               _request_send_result(req, -1);
+                               goto err_out;
+                       }
+                       close(handles[1]);
+                       handles[1] = -1;
+                       if (handles[0] == -1) {
+                               _E("remove from hash : %s", socket_pair_key);
+                               g_hash_table_remove(__dc_socket_pair_hash,
+                                               socket_pair_key);
+                       }
+               }
+       }
+       SECURE_LOGD("send_message msglen : [%d]\n", msglen);
+       if (socket_pair_key)
+               free(socket_pair_key);
+
+       return 0;
+
+err_out:
+       if (socket_pair_key) {
+               g_hash_table_remove(__dc_socket_pair_hash, socket_pair_key);
+               free(socket_pair_key);
+       }
+
+       return -1;
+}
+
+static int __dispatch_update_rua_stat(request_h req)
+{
+       int result;
+       char *caller = NULL;
+       char *tag = NULL;
+       uid_t uid = _request_get_target_uid(req);
+
+       bundle_get_str(req->kb, AUL_SVC_K_RUA_STAT_CALLER, &caller);
+       bundle_get_str(req->kb, AUL_SVC_K_RUA_STAT_TAG, &tag);
+       result = rua_stat_usr_db_update(caller, tag, uid);
+       _D("rua_stat_usr_db_update - uid(%d), result(%d)", uid, result);
+       _request_send_result(req, result);
+
+       return 0;
+}
+
+static int __dispatch_add_history(request_h req)
+{
+       int result;
+       struct rua_rec rec = {0,};
+       char *time_str;
+       uid_t uid = _request_get_target_uid(req);
+       bundle *b = _request_get_bundle(req);
+
+       bundle_get_str(b, AUL_K_RUA_PKGNAME, &rec.pkg_name);
+       bundle_get_str(b, AUL_K_RUA_APPPATH, &rec.app_path);
+       bundle_get_str(b, AUL_K_RUA_ARG, &rec.arg);
+       bundle_get_str(b, AUL_K_RUA_TIME, &time_str);
+       if (time_str != NULL)
+               rec.launch_time = atoi(time_str);
+       else
+               rec.launch_time = (int)time(NULL);
+       bundle_get_str(b, AUL_K_RUA_INSTANCE_ID, &rec.instance_id);
+       bundle_get_str(b, AUL_K_RUA_INSTANCE_NAME, &rec.instance_name);
+       bundle_get_str(b, AUL_K_RUA_ICON, &rec.icon);
+       bundle_get_str(b, AUL_K_RUA_URI, &rec.uri);
+
+       result = rua_usr_db_add_history(&rec, uid);
+       _D("rua_usr_db_add_history - uid(%d), result(%d)", uid, result);
+       _request_send_result(req, result);
+
+       return 0;
+}
+
+static int __dispatch_remove_history(request_h req)
+{
+       int result;
+       bundle *b = _request_get_bundle(req);
+       uid_t uid = _request_get_target_uid(req);
+
+       result = rua_usr_db_delete_history(b, uid);
+       _D("rua_usr_db_delete_history - uid(%d), result(%d)", uid, result);
+       _request_send_result(req, result);
+
+       _rua_delete_info(b, uid);
+
+       return 0;
+}
+
+static int __dispatch_app_group_get_window(request_h req)
+{
+       char *buf;
+       int pid;
+       int wid;
+
+       bundle_get_str(req->kb, AUL_K_PID, &buf);
+       pid = atoi(buf);
+       wid = _app_group_get_window(pid);
+       _request_send_result(req, wid);
+
+       return 0;
+}
+
+static int __dispatch_app_group_set_window(request_h req)
+{
+       char *buf;
+       int pid = _request_get_pid(req);
+       uid_t uid = _request_get_target_uid(req);
+       int wid;
+       int ret;
+
+       bundle_get_str(req->kb, AUL_K_WID, &buf);
+       wid = atoi(buf);
+       ret = _app_group_set_window(pid, wid);
+       _request_send_result(req, ret);
+       _D("pid(%d), wid(%d)", pid, wid);
+       _screen_connector_add_app_screen(pid, wid, NULL, uid);
+
+       return ret;
+}
+
+static int __dispatch_app_group_get_fg_flag(request_h req)
+{
+       char *buf;
+       int pid;
+       int fg;
+
+       bundle_get_str(req->kb, AUL_K_PID, &buf);
+       pid = atoi(buf);
+       fg = _app_group_get_fg_flag(pid);
+       _request_send_result(req, fg);
+
+       return 0;
+}
+
+static int __dispatch_app_group_clear_top(request_h req)
+{
+       int pid = _request_get_pid(req);
+       uid_t uid = _request_get_target_uid(req);
+
+       _app_group_clear_top(pid, uid);
+       _request_send_result(req, 0);
+
+       return 0;
+}
+
+static int __dispatch_app_group_get_leader_pid(request_h req)
+{
+       char *buf;
+       int pid;
+       int lpid;
+
+       bundle_get_str(req->kb, AUL_K_PID, &buf);
+       pid = atoi(buf);
+       lpid = _app_group_get_leader_pid(pid);
+       _request_send_result(req, lpid);
+
+       return 0;
+}
+
+static int __dispatch_app_group_get_leader_pids(request_h req)
+{
+       int cnt;
+       int *pids;
+       unsigned char empty[1] = {0,};
+
+       _app_group_get_leader_pids(&cnt, &pids);
+
+       if (pids == NULL || cnt == 0) {
+               _request_send_raw(req, APP_GROUP_GET_LEADER_PIDS, empty, 0);
+       } else {
+               _request_send_raw(req, APP_GROUP_GET_LEADER_PIDS,
+                               (unsigned char *)pids, cnt * sizeof(int));
+       }
+
+       if (pids != NULL)
+               free(pids);
+
+       return 0;
+}
+
+static int __dispatch_app_group_get_idle_pids(request_h req)
+{
+       int cnt;
+       int *pids;
+       unsigned char empty[1] = {0,};
+
+       _app_group_get_idle_pids(&cnt, &pids);
+       if (pids == NULL || cnt == 0) {
+               _request_send_raw(req, APP_GROUP_GET_IDLE_PIDS, empty, 0);
+       } else {
+               _request_send_raw(req, APP_GROUP_GET_IDLE_PIDS,
+                               (unsigned char *)pids, cnt * sizeof(int));
+       }
+
+       if (pids != NULL)
+               free(pids);
+
+       return 0;
+}
+
+static int __dispatch_app_group_get_group_pids(request_h req)
+{
+       char *buf;
+       int leader_pid;
+       int cnt;
+       int *pids;
+       unsigned char empty[1] = { 0 };
+
+       bundle_get_str(req->kb, AUL_K_LEADER_PID, &buf);
+       leader_pid = atoi(buf);
+
+       _app_group_get_group_pids(leader_pid, &cnt, &pids);
+       if (pids == NULL || cnt == 0) {
+               _request_send_raw(req, APP_GROUP_GET_GROUP_PIDS, empty, 0);
+       } else {
+               _request_send_raw(req, APP_GROUP_GET_GROUP_PIDS,
+                               (unsigned char *)pids, cnt * sizeof(int));
+       }
+
+       if (pids != NULL)
+               free(pids);
+
+       return 0;
+}
+
+static int __dispatch_app_group_lower(request_h req)
+{
+       int ret = 0;
+
+       _app_group_lower(req->pid, &ret);
+       _request_send_result(req, ret);
+
+       return ret;
+}
+
+static int __dispatch_app_group_activate_below(request_h req)
+{
+       char *buf = NULL;
+       int ret;
+
+       bundle_get_str(req->kb, AUL_K_APPID, &buf);
+       ret = _app_group_activate_below(req->pid, buf);
+       _request_send_result(req, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_group_activate_above(request_h req)
+{
+       char *buf = NULL;
+       int ret;
+
+       bundle_get_str(req->kb, AUL_K_APPID, &buf);
+       ret = _app_group_activate_above(req->pid, buf);
+       _request_send_result(req, ret);
+
+       return 0;
+}
+
+static guint __get_pending_interval(GTimeVal *start, GTimeVal *end)
+{
+       guint sec;
+       guint usec;
+       guint interval;
+
+       sec = (end->tv_sec - start->tv_sec) * 1000;
+       usec = (end->tv_usec - start->tv_usec) / 1000;
+       interval = sec + usec;
+       if (interval >= PENDING_REQUEST_TIMEOUT)
+               return 0;
+
+       return PENDING_REQUEST_TIMEOUT - interval;
+}
+
+static char *__get_value_from_query(const char *src, const char *key)
+{
+       int src_len = strlen(src);
+       int key_len = strlen(key);
+
+       if (src_len > key_len) {
+               if (strncmp(src, key, key_len) == 0)
+                       return g_uri_unescape_string(src + key_len, NULL);
+       }
+
+       return NULL;
+}
+
+static void __free_instance_info(struct instance_info *info)
+{
+       if (info->uri) {
+               free(info->uri);
+               info->uri = NULL;
+       }
+
+       if (info->id) {
+               free(info->id);
+               info->id = NULL;
+       }
+
+       if (info->icon) {
+               free(info->icon);
+               info->icon = NULL;
+       }
+
+       if (info->name) {
+               free(info->name);
+               info->name = NULL;
+       }
+}
+
+static int __get_instance_info(bundle *kb, struct instance_info *info)
+{
+       const char *uri;
+       gchar *scheme;
+       gchar *query;
+       char *token;
+       char *dup_uri;
+
+       uri = bundle_get_val(kb, AUL_SVC_K_URI);
+       if (uri == NULL)
+               return -1;
+
+       scheme = g_uri_parse_scheme(uri);
+       if (scheme == NULL)
+               return -1;
+
+       if (strcmp(scheme, MULTI_INSTANCE_SHORTCUT) != 0) {
+               g_free(scheme);
+               return -1;
+       }
+       g_free(scheme);
+
+       dup_uri = strdup(uri);
+       if (dup_uri == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       info->uri = strdup(uri);
+       if (info->uri == NULL) {
+               _E("Out of memory");
+               free(dup_uri);
+               return -1;
+       }
+
+       query = index(dup_uri, '?');
+       if (query == NULL || query + 1 == NULL) {
+               __free_instance_info(info);
+               free(dup_uri);
+               return -1;
+       }
+
+       token = strtok(query + 1, "&");
+       while (token != NULL) {
+               if (info->id == NULL)
+                       info->id = __get_value_from_query(token, QUERY_KEY_ID);
+               if (info->icon == NULL) {
+                       info->icon = __get_value_from_query(token,
+                                       QUERY_KEY_ICON);
+               }
+               if (info->name == NULL) {
+                       info->name = __get_value_from_query(token,
+                                       QUERY_KEY_NAME);
+               }
+
+               token = strtok(NULL, "&");
+       }
+       free(dup_uri);
+
+       if (info->id == NULL || info->icon == NULL || info->name == NULL) {
+               _W("Failed to get instance info");
+               __free_instance_info(info);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __dispatch_app_start(request_h req)
+{
+       const char *appid;
+       const char *instance_id;
+       int ret;
+       bundle *kb;
+       bool pending = false;
+       struct pending_item *item;
+       GTimeVal end;
+       guint interval;
+       bool bg_launch = false;
+       bool new_instance = false;
+       struct instance_info info = {0,};
+       struct reply_info *reply;
+       int clifd;
+       rua_stat_pkt_t *rua = NULL;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       __set_real_appid(_request_get_target_uid(req), kb);
+       __set_effective_appid(_request_get_target_uid(req), kb);
+       if (__get_instance_info(kb, &info) == 0) {
+               bundle_del(kb, AUL_K_INSTANCE_ID);
+               bundle_add(kb, AUL_K_INSTANCE_ID, info.id);
+               new_instance = true;
+               _D("Multiple instance launch - id(%s), name(%s), icon(%s)",
+                               info.id, info.name, info.icon);
+       } else {
+               instance_id = bundle_get_val(kb, AUL_K_INSTANCE_ID);
+               if (instance_id) {
+                       info.id = strdup(instance_id);
+                       _D("Multiple instance launch - id(%s)", info.id);
+               }
+       }
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       ret = _launch_start_app(appid, req, &pending, &bg_launch, new_instance);
+#ifdef TIZEN_FEATURE_BLOCK_INPUT
+       if (ret <= 0)
+               _input_unlock();
+#endif /* TIZEN_FEATURE_BLOCK_INPUT */
+
+       /* add pending list to wait app launched successfully */
+       if (pending) {
+               item = g_hash_table_lookup(pending_table, GINT_TO_POINTER(ret));
+               if (item == NULL) {
+                       item = calloc(1, sizeof(struct pending_item));
+                       if (item == NULL) {
+                               _E("Out of memory");
+                               _request_send_result(req, ret);
+                               __free_instance_info(&info);
+                               return -1;
+                       }
+                       item->pid = ret;
+                       g_hash_table_insert(pending_table, GINT_TO_POINTER(ret),
+                                       item);
+               } else {
+                       if (item->timer) {
+                               g_source_remove(item->timer);
+                               item->timer = 0;
+                       }
+               }
+
+               if (!bg_launch) {
+                       rua = __create_rua_stat_pkt(req, kb, appid, &info, ret);
+                       if (rua && !rua->is_group_app)
+                               _rua_add_info(ret, new_instance);
+               }
+
+               clifd = _request_remove_fd(req);
+               g_get_current_time(&end);
+               interval = __get_pending_interval(&req->start, &end);
+               reply = __create_reply_info(interval, ret, ret,
+                               req->cmd, clifd, rua);
+               if (reply == NULL) {
+                       _send_result_to_client(clifd, ret);
+                       __free_instance_info(&info);
+                       return -1;
+               }
+
+               item->reply_list = g_list_append(item->reply_list, reply);
+               __free_instance_info(&info);
+               return 0;
+       }
+
+       if (ret > 0 && !bg_launch) {
+               rua = __create_rua_stat_pkt(req, kb, appid, &info, ret);
+               if (rua == NULL) {
+                       __free_instance_info(&info);
+                       return -1;
+               }
+               g_timeout_add(1500, __add_history_handler, rua);
+       }
+       __free_instance_info(&info);
+
+       return 0;
+}
+
+static int __get_caller_uid(bundle *kb, uid_t *uid)
+{
+       const char *val;
+
+       val = bundle_get_val(kb, AUL_K_ORG_CALLER_UID);
+       if (val == NULL)
+               val = bundle_get_val(kb, AUL_K_CALLER_UID);
+
+       if (val == NULL) {
+               _E("Failed to get caller uid");
+               return -1;
+       }
+
+       *uid = atol(val);
+       _D("caller uid(%d)", *uid);
+
+       return 0;
+}
+
+static void __set_instance_id(bundle *kb)
+{
+       app_status_h app_status;
+       const char *instance_id;
+       const char *callee_pid;
+       int pid;
+
+       callee_pid = bundle_get_val(kb, AUL_K_FWD_CALLEE_PID);
+       if (callee_pid == NULL)
+               callee_pid = bundle_get_val(kb, AUL_K_CALLEE_PID);
+
+       if (callee_pid == NULL) {
+               _E("Failed to get callee pid");
+               return;
+       }
+
+       pid = atoi(callee_pid);
+       if (pid <= 0)
+               return;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return;
+
+       instance_id = _app_status_get_instance_id(app_status);
+       if (instance_id == NULL)
+               return;
+
+       bundle_del(kb, AUL_K_INSTANCE_ID);
+       bundle_add(kb, AUL_K_INSTANCE_ID, instance_id);
+       _D("instance_id(%s)", instance_id);
+}
+
+static int __dispatch_app_result(request_h req)
+{
+       bundle *kb;
+       int pid;
+       int pgid;
+       char tmp_pid[MAX_PID_STR_BUFSZ];
+       int res;
+       shared_info_h si = NULL;
+       const char *appid;
+       int ret;
+       uid_t target_uid = _request_get_target_uid(req);
+       app_status_h app_status;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       pid = __get_caller_pid(kb);
+       if (pid < 0)
+               return AUL_R_ERROR;
+
+       pgid = getpgid(req->pid);
+       if (pgid > 0) {
+               snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", pgid);
+               bundle_del(kb, AUL_K_CALLEE_PID);
+               bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
+       }
+
+       if (__get_caller_uid(kb, &target_uid) < 0)
+               return AUL_R_ERROR;
+
+       __set_instance_id(kb);
+       app_status = _app_status_find(getpgid(pid));
+       appid = _app_status_get_appid(app_status);
+       if (appid) {
+               si = _temporary_permission_create(pgid, appid, kb, target_uid);
+               if (si == NULL)
+                       _D("No sharable path : %d %s", pgid, appid);
+       }
+
+       res = aul_sock_send_bundle(pid, target_uid, req->cmd, kb,
+                       AUL_SOCK_NOREPLY);
+       if (res < 0)
+               res = AUL_R_ERROR;
+
+       if (si) {
+               if (res >= 0) {
+                       ret = _temporary_permission_apply(pid, target_uid, si);
+                       if (ret != 0) {
+                               _D("Couldn't apply temporary permission: %d",
+                                               ret);
+                       }
+               }
+               _temporary_permission_destroy(si);
+       }
+
+       return 0;
+}
+
+static int __dispatch_app_pause(request_h req)
+{
+       const char *appid;
+       bundle *kb;
+       int ret;
+       app_status_h app_status;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       app_status = _app_status_find_by_appid(appid,
+                       _request_get_target_uid(req));
+       ret = _app_status_get_pid(app_status);
+       if (ret > 0)
+               ret = _pause_app(ret, req);
+       else
+               _E("%s is not running", appid);
+
+       return 0;
+}
+
+static int __dispatch_app_process_by_pid(request_h req)
+{
+       const char *appid;
+       bundle *kb;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       __app_process_by_pid(req, appid, NULL);
+
+       return 0;
+}
+
+static int __dispatch_app_term_async(request_h req)
+{
+       const char *appid;
+       bundle *kb;
+       const char *term_pid;
+       struct appinfo *ai;
+       app_status_h app_status;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       term_pid = bundle_get_val(kb, AUL_K_APPID);
+       app_status = _app_status_find(atoi(term_pid));
+       appid = _app_status_get_appid(app_status);
+       ai = _appinfo_find(_request_get_target_uid(req), appid);
+       if (ai) {
+               _appinfo_set_value(ai, AIT_STATUS, "norestart");
+               __app_process_by_pid(req, term_pid, NULL);
+       }
+
+       return 0;
+}
+
+static int __dispatch_app_term(request_h req)
+{
+       const char *appid;
+       bundle *kb;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       __app_process_by_pid(req, appid, NULL);
+
+       return 0;
+}
+
+static int __dispatch_app_running_info(request_h req)
+{
+       int ret;
+
+       ret = _app_status_send_running_appinfo(_request_remove_fd(req),
+                       req->cmd, _request_get_target_uid(req));
+       return ret;
+}
+
+static int __dispatch_app_all_running_info(request_h req)
+{
+       int ret;
+
+       ret = _app_status_send_running_appinfo(_request_remove_fd(req),
+                       req->cmd, _request_get_target_uid(req));
+       return ret;
+}
+
+static int __dispatch_app_is_running(request_h req)
+{
+       const char *appid;
+       int ret;
+       app_status_h app_status;
+       bundle *b = _request_get_bundle(req);
+
+       if (b == NULL) {
+               _E("Failed to get bundle");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       appid = bundle_get_val(b, AUL_K_APPID);
+       if (appid == NULL) {
+               _E("Failed to get appid");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       app_status = _app_status_find_by_appid(appid,
+                       _request_get_target_uid(req));
+       ret = _app_status_is_running(app_status);
+       SECURE_LOGD("APP_IS_RUNNING : %s : %d", appid, ret);
+       _request_send_result(req, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_get_appid_by_pid(request_h req)
+{
+       int pid;
+       int ret;
+       const char *pid_str;
+       bundle *b = _request_get_bundle(req);
+
+       if (b == NULL) {
+               _E("Failed to get bundle");
+               aul_sock_send_raw_with_fd(_request_remove_fd(req),
+                               APP_GET_INFO_ERROR, NULL, 0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       pid_str = bundle_get_val(b, AUL_K_PID);
+       if (pid_str == NULL || !isdigit(pid_str[0])) {
+               _E("Failed to get pid");
+               aul_sock_send_raw_with_fd(_request_remove_fd(req),
+                               APP_GET_INFO_ERROR, NULL, 0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       pid = atoi(pid_str);
+       ret = _app_status_get_appid_bypid(_request_remove_fd(req), pid);
+       _D("app_status_get_appid_bypid : %d : %d", pid, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_get_pkgid_by_pid(request_h req)
+{
+       int pid;
+       int ret;
+       const char *pid_str;
+       bundle *b = _request_get_bundle(req);
+
+       if (b == NULL) {
+               _E("Failed to get bundle");
+               aul_sock_send_raw_with_fd(_request_remove_fd(req),
+                               APP_GET_INFO_ERROR, NULL, 0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       pid_str = bundle_get_val(b, AUL_K_PID);
+       if (pid_str == NULL || !isdigit(pid_str[0])) {
+               _E("Failed to get pid");
+               aul_sock_send_raw_with_fd(_request_remove_fd(req),
+                               APP_GET_INFO_ERROR, NULL, 0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       pid = atoi(pid_str);
+       ret = _app_status_get_pkgid_bypid(_request_remove_fd(req), pid);
+       _D("APP_GET_PKGID_BYPID : %d : %d", pid, ret);
+
+       return 0;
+}
+
+static int __dispatch_legacy_command(request_h req)
+{
+       _request_send_result(req, 0);
+       return 0;
+}
+
+static int __dispatch_app_status_update(request_h req)
+{
+       int *status;
+       const char *appid;
+       struct appinfo *ai;
+       app_status_h app_status;
+
+       app_status = _app_status_find(req->pid);
+       if (app_status == NULL)
+               return -1;
+
+       status = (int *)req->data;
+       switch (*status) {
+       case STATUS_NORESTART:
+               appid = _app_status_get_appid(app_status);
+               ai = _appinfo_find(_request_get_target_uid(req), appid);
+               _appinfo_set_value((struct appinfo *)ai, AIT_STATUS,
+                               "norestart");
+               break;
+       case STATUS_VISIBLE:
+       case STATUS_BG:
+               break;
+       default:
+               _app_status_update_status(app_status, *status, false, true);
+               break;
+       }
+
+       return 0;
+}
+
+static int __dispatch_app_get_status(request_h req)
+{
+       int pid;
+       int status;
+       app_status_h app_status;
+       const char *pid_str;
+       bundle *b;
+
+       b = _request_get_bundle(req);
+       if (b == NULL) {
+               _E("Failed to get bundle");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       pid_str = bundle_get_val(b, AUL_K_PID);
+       if (pid_str == NULL || !isdigit(pid_str[0])) {
+               _E("Falied to get pid");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       pid = atoi(pid_str);
+       app_status = _app_status_find(pid);
+       status = _app_status_get_status(app_status);
+       _request_send_result(req, status);
+
+       return 0;
+}
+
+static int __dispatch_app_add_loader(request_h req)
+{
+       bundle *kb;
+       int ret;
+       char tmpbuf[MAX_PID_STR_BUFSZ];
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       snprintf(tmpbuf, sizeof(tmpbuf), "%d", getpgid(req->pid));
+       bundle_add(kb, AUL_K_CALLER_PID, tmpbuf);
+       ret = _send_cmd_to_launchpad(LAUNCHPAD_PROCESS_POOL_SOCK,
+                       _request_get_target_uid(req), PAD_CMD_ADD_LOADER, kb);
+       _request_send_result(req, ret);
+
+       return ret;
+}
+
+static int __dispatch_app_remove_loader(request_h req)
+{
+       bundle *kb;
+       int ret;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       ret = _send_cmd_to_launchpad(LAUNCHPAD_PROCESS_POOL_SOCK,
+                       _request_get_target_uid(req), PAD_CMD_REMOVE_LOADER,
+                       kb);
+       _request_send_result(req, ret);
+
+       return ret;
+}
+
+static int __dispatch_launchpad_dead_signal(request_h req)
+{
+       uid_t target_uid = _request_get_target_uid(req);
+
+       _D("uid(%d)", target_uid);
+       _login_monitor_set_uid_state(target_uid, UID_STATE_CLOSING);
+       close(_request_remove_fd(req));
+
+       return 0;
+}
+
+static int __dispatch_amd_reload_appinfo(request_h req)
+{
+       _D("AMD_RELOAD_APPINFO");
+       _appinfo_reload();
+       _request_send_result(req, 0);
+
+       return 0;
+}
+
+static int __dispatch_app_com_create(request_h req)
+{
+       bundle *kb;
+       int ret;
+       size_t propagate_size;
+       unsigned int propagate = 0;
+       const char *privilege;
+       const char *endpoint;
+       unsigned int *prop;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       endpoint = bundle_get_val(kb, AUL_K_COM_ENDPOINT);
+       if (endpoint == NULL) {
+               _request_send_result(req, AUL_APP_COM_R_ERROR_FATAL_ERROR);
+               return 0;
+       }
+
+       privilege = bundle_get_val(kb, AUL_K_COM_PRIVILEGE);
+       if (!privilege) {
+               /* privilege is not mandatory so far */
+               _D("non-privileged endpoint: %s", endpoint);
+       }
+
+       ret = bundle_get_byte(kb, AUL_K_COM_PROPAGATE, (void **)&prop,
+                       &propagate_size);
+       if (ret == 0)
+               propagate = *prop;
+
+       _D("endpoint: %s propagate: %x privilege: %s",
+                       endpoint, propagate, privilege);
+
+       ret = _app_com_add_endpoint(endpoint, propagate, privilege);
+       if (ret == AUL_APP_COM_R_ERROR_OK ||
+                       ret == AUL_APP_COM_R_ERROR_ENDPOINT_ALREADY_EXISTS) {
+               ret = _app_com_join(endpoint, getpgid(req->pid), NULL,
+                               _request_get_uid(req));
+               if (ret == AUL_APP_COM_R_ERROR_ILLEGAL_ACCESS) {
+                       _E("illegal access: remove endpoint");
+                       _app_com_remove_endpoint(endpoint);
+               }
+       }
+
+       _request_send_result(req, ret);
+       return 0;
+}
+
+static int __dispatch_app_com_join(request_h req)
+{
+       bundle *kb;
+       int ret;
+       const char *endpoint;
+       const char *filter;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       endpoint = bundle_get_val(kb, AUL_K_COM_ENDPOINT);
+       if (endpoint == NULL) {
+               bundle_free(kb);
+               _request_send_result(req, AUL_APP_COM_R_ERROR_FATAL_ERROR);
+               return 0;
+       }
+
+       filter = bundle_get_val(kb, AUL_K_COM_FILTER);
+
+       ret = _app_com_join(endpoint, getpgid(req->pid), filter,
+                       _request_get_uid(req));
+
+       _request_send_result(req, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_com_send(request_h req)
+{
+       bundle *kb;
+       int ret;
+       const char *endpoint;
+       int sender_pid = _request_get_pid(req);
+       char sender_pid_str[MAX_PID_STR_BUFSZ];
+       uid_t sender_uid = _request_get_uid(req);
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       snprintf(sender_pid_str, MAX_PID_STR_BUFSZ, "%d", sender_pid);
+       bundle_del(kb, AUL_K_COM_SENDER_PID);
+       bundle_add(kb, AUL_K_COM_SENDER_PID, sender_pid_str);
+       endpoint = bundle_get_val(kb, AUL_K_COM_ENDPOINT);
+       if (endpoint == NULL) {
+               _request_send_result(req, AUL_APP_COM_R_ERROR_FATAL_ERROR);
+               return 0;
+       }
+
+       ret = _app_com_send(endpoint, getpgid(sender_pid), kb, sender_uid);
+       _request_send_result(req, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_com_leave(request_h req)
+{
+       bundle *kb;
+       int ret;
+       const char *endpoint;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       endpoint = bundle_get_val(kb, AUL_K_COM_ENDPOINT);
+       if (endpoint == NULL) {
+               _request_send_result(req, AUL_APP_COM_R_ERROR_FATAL_ERROR);
+               return 0;
+       }
+
+       ret = _app_com_leave(endpoint, getpgid(req->pid));
+       _request_send_result(req, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_register_pid(request_h req)
+{
+       bundle *kb;
+       const struct appinfo *ai;
+       const char *appid;
+       const char *component_type;
+       const char *pid_str;
+       int pid;
+       int ret;
+       uid_t target_uid = _request_get_target_uid(req);
+       int caller_pid = _request_get_pid(req);
+       app_status_h app_status;
+       int status = -1;
+       int focused = -1;
+
+       kb = req->kb;
+       if (kb == NULL)
+               return -1;
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       if (appid == NULL)
+               return -1;
+
+       pid_str = bundle_get_val(kb, AUL_K_PID);
+       if (pid_str == NULL)
+               return -1;
+
+       pid = atoi(pid_str);
+       app_status = _app_status_find_by_appid(appid, target_uid);
+       ret = _app_status_is_running(app_status);
+       if (ret > 0) {
+               if (ret != pid)
+                       kill(pid, SIGKILL);
+               _D("status info is already exist: %s", appid);
+               return 0;
+       }
+       _D("appid: %s, pid: %d", appid, pid);
+
+       ai = _appinfo_find(target_uid, appid);
+       component_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (component_type && strcmp(component_type, APP_TYPE_UI) == 0) {
+               _app_group_start_app(pid, kb, pid, FALSE,
+                               APP_GROUP_LAUNCH_MODE_SINGLE);
+       }
+
+       _app_status_add_app_info(ai, pid, false, target_uid, caller_pid,
+                       false, NULL, false);
+
+       if (component_type && strcmp(component_type, APP_TYPE_SERVICE) != 0) {
+               ret = _signal_get_proc_status(pid, &status, &focused);
+               if (ret < 0)
+                       return -1;
+
+               if (focused == 1)
+                       _launch_set_focused_pid(pid);
+
+               if (status == PROC_STATUS_FG)
+                       status = STATUS_VISIBLE;
+               else if (status == PROC_STATUS_BG)
+                       status = STATUS_BG;
+               else
+                       return -1;
+
+               app_status = _app_status_find(pid);
+               if (app_status == NULL)
+                       return -1;
+
+               _app_status_update_status(app_status, status, false, true);
+       }
+
+       return 0;
+}
+
+static int __dispatch_app_set_app_control_default_app(request_h req)
+{
+       bundle *kb = NULL;
+       const char *op;
+       const char *mime_type;
+       const char *uri;
+       const char *appid;
+       int ret;
+       app_property_h prop;
+
+       kb = req->kb;
+       if (kb == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       op = aul_svc_get_operation(kb);
+       appid = aul_svc_get_appid(kb);
+       if (op == NULL || appid == NULL) {
+               _E("Invalid operation, appid");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       mime_type = aul_svc_get_mime(kb);
+       uri = aul_svc_get_uri(kb);
+
+       ret = aul_svc_set_defapp_for_uid(op, mime_type, uri,
+                       appid, _request_get_target_uid(req));
+       if (ret < 0) {
+               _E("Error[%d], aul_svc_set_defapp", ret);
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       prop = _app_property_find(_request_get_target_uid(req));
+       _app_property_cache_invalidate(prop);
+       _request_send_result(req, 0);
+       return 0;
+}
+
+static int __dispatch_app_unset_app_control_default_app(request_h req)
+{
+       char appid[MAX_PACKAGE_STR_SIZE];
+       int ret;
+       app_property_h prop;
+
+       snprintf(appid, MAX_PACKAGE_STR_SIZE - 1, "%s",
+                       (const char *)req->data);
+
+       ret = aul_svc_unset_defapp_for_uid(appid, _request_get_target_uid(req));
+       if (ret < 0) {
+               _E("Error[%d], aul_svc_unset_defapp", ret);
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       prop = _app_property_find(_request_get_target_uid(req));
+       _app_property_cache_invalidate(prop);
+       _request_send_result(req, 0);
+       return 0;
+}
+
+static int __dispatch_app_set_process_group(request_h req)
+{
+       int owner_pid;
+       int child_pid;
+       bundle *kb = NULL;
+       const char *child_appid;
+       const char *child_pkgid = NULL;
+       const struct appinfo *ai;
+       const char *str_pid;
+       app_status_h app_status;
+       int ret;
+
+       kb = req->kb;
+       if (kb == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       str_pid = bundle_get_val(kb, AUL_K_OWNER_PID);
+       if (str_pid == NULL) {
+               _E("No owner pid");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       owner_pid = atoi(str_pid);
+       str_pid = bundle_get_val(kb, AUL_K_CHILD_PID);
+       if (str_pid == NULL) {
+               _E("No child pid");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       child_pid = atoi(str_pid);
+       app_status = _app_status_find(child_pid);
+       if (app_status) {
+               child_appid = _app_status_get_appid(app_status);
+               ai = _appinfo_find(_request_get_target_uid(req), child_appid);
+               child_pkgid = _appinfo_get_value(ai, AIT_PKGID);
+       }
+
+       ret = aul_send_app_group_signal(owner_pid, child_pid, child_pkgid);
+
+       _request_send_result(req, ret);
+       return 0;
+}
+
+static int __dispatch_app_prepare_candidate_process(request_h req)
+{
+       bundle *b = NULL;
+       int ret;
+
+       b = bundle_create();
+       if (b == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = _send_cmd_to_launchpad(LAUNCHPAD_PROCESS_POOL_SOCK,
+                       _request_get_target_uid(req), PAD_CMD_DEMAND, b);
+       bundle_free(b);
+
+       _request_send_result(req, ret);
+       return 0;
+}
+
+static int __dispatch_app_term_sync(request_h req)
+{
+       int ret;
+       int pid;
+       const char *appid;
+       bundle *kb;
+       struct pending_item *item;
+       bool pending = false;
+       GTimeVal end;
+       guint interval;
+       struct reply_info *reply;
+       int clifd;
+
+       kb = req->kb;
+       if (kb == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       ret = __app_process_by_pid(req, appid, &pending);
+       if (ret < 0)
+               return -1;
+
+       /* add pending list to wait app terminated successfully */
+       if (pending) {
+               pid = atoi(appid);
+               clifd = _request_remove_fd(req);
+               g_get_current_time(&end);
+               interval = __get_pending_interval(&req->start, &end);
+               reply = __create_reply_info(interval, pid, -EAGAIN,
+                               req->cmd, clifd, NULL);
+               if (reply == NULL) {
+                       _send_result_to_client(clifd, ret);
+                       return -1;
+               }
+
+               item = g_hash_table_lookup(pending_table, GINT_TO_POINTER(pid));
+               if (item == NULL) {
+                       item = calloc(1, sizeof(struct pending_item));
+                       if (item == NULL) {
+                               _E("Out of memory");
+                               return -1;
+                       }
+                       item->pid = pid;
+                       g_hash_table_insert(pending_table, GINT_TO_POINTER(pid),
+                                       item);
+               } else {
+                       if (item->timer) {
+                               g_source_remove(item->timer);
+                               item->timer = 0;
+                       }
+               }
+               item->reply_list = g_list_append(item->reply_list, reply);
+               item->timer = g_timeout_add(interval, __timeout_pending_item,
+                               item);
+       }
+
+       return 0;
+}
+
+static int __dispatch_app_term_sync_without_restart(request_h req)
+{
+       int ret = -1;
+       const char *appid;
+       const char *term_pid;
+       const char *component_type;
+       struct appinfo *ai;
+       app_status_h app_status;
+
+       term_pid = bundle_get_val(req->kb, AUL_K_APPID);
+       if (term_pid == NULL)
+               goto exception;
+
+       app_status = _app_status_find(atoi(term_pid));
+       if (app_status == NULL)
+               goto exception;
+
+       appid = _app_status_get_appid(app_status);
+       if (appid == NULL)
+               goto exception;
+
+       ai = _appinfo_find(_request_get_target_uid(req), appid);
+       if (ai == NULL)
+               goto exception;
+
+       component_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (!component_type)
+               goto exception;
+
+       ret = __dispatch_app_term_sync(req);
+       if (ret < 0)
+               return ret;
+
+       if (strcmp(component_type, APP_TYPE_SERVICE) == 0)
+               _appinfo_set_value(ai, AIT_STATUS, "norestart");
+       return 0;
+
+exception:
+       _request_send_result(req, ret);
+       return ret;
+}
+
+static int __dispatch_app_get_status_by_appid(request_h req)
+{
+       int status;
+       int pid;
+       uid_t uid;
+       const char *appid;
+       bundle *kb;
+       app_status_h app_status;
+
+       kb = _request_get_bundle(req);
+       if (kb == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       uid = _request_get_target_uid(req);
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       if (appid == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       app_status = _app_status_find_by_appid(appid, uid);
+       pid = _app_status_is_running(app_status);
+       if (pid <= 0) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       status = _app_status_get_status(app_status);
+       if (status == STATUS_VISIBLE) {
+               if (_launch_get_focused_pid() == pid)
+                       status = STATUS_FOCUS;
+       }
+
+       _request_send_result(req, status);
+       _D("appid: %s, pid: %d, status: %d", appid, pid, status);
+
+       return 0;
+}
+
+static int __validate_widget_owner(request_h req)
+{
+       app_status_h status;
+       const char *appid;
+       char *widget_id = NULL;
+       const char *appid_part = NULL;
+       bundle *kb = req->kb;
+
+       status = _app_status_find(req->pid);
+       if (!status)
+               return -1;
+
+       appid = _app_status_get_appid(status);
+       bundle_get_str(kb, AUL_K_WIDGET_ID, &widget_id);
+       if (!widget_id || !appid)
+               return -1;
+
+       appid_part = g_strstr_len(widget_id, strlen(widget_id), "@");
+       if (appid_part)
+               appid_part = appid_part + 1;
+       else
+               appid_part = widget_id;
+
+       return strcmp(appid_part, appid);
+}
+
+static int __dispatch_widget_add_del(request_h req)
+{
+       bundle *kb = req->kb;
+       char *widget_id = NULL;
+       char *instance_id = NULL;
+       int ret;
+
+       if (__validate_widget_owner(req) < 0) {
+               _request_send_result(req, -EINVAL);
+               return -1;
+       }
+
+       bundle_get_str(kb, AUL_K_WIDGET_ID, &widget_id);
+       bundle_get_str(kb, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
+       if (!widget_id || !instance_id) {
+               _request_send_result(req, -EINVAL);
+               return -1;
+       }
+
+       if (req->cmd == WIDGET_ADD)
+               ret = _widget_add(widget_id, instance_id, req->pid, req->uid);
+       else
+               ret = _widget_del(widget_id, instance_id);
+
+       _request_send_result(req, ret);
+
+       return ret;
+}
+
+static int __validate_widget_caller(request_h req)
+{
+       bundle *kb = req->kb;
+       char *appid = NULL;
+       struct appinfo *target;
+       const char *target_pkgid;
+       app_status_h caller_status;
+       const char *caller_pkgid;
+
+       if (req->uid < REGULAR_UID_MIN) {
+               _D("bypass caller package check");
+               return 0;
+       }
+
+       bundle_get_str(kb, AUL_K_APPID, &appid);
+       if (!appid) {
+               _E("no appid provided");
+               return -1;
+       }
+
+       target = _appinfo_find(req->uid, appid);
+       if (!target) {
+               _E("can not find appinfo of %s", appid);
+               return -1;
+       }
+
+       target_pkgid = _appinfo_get_value(target, AIT_PKGID);
+       if (!target_pkgid) {
+               _E("can not get pkgid %s", target_pkgid);
+               return -1;
+       }
+
+       caller_status = _app_status_find(req->pid);
+       if (!caller_status)
+               return 0; /* not app? */
+
+       caller_pkgid = _app_status_get_pkgid(caller_status);
+       if (!caller_pkgid) {
+               _E("can not get caller pkgid");
+               return -1;
+       }
+
+       _D("compare pkgid %s:%s", caller_pkgid, target_pkgid);
+       if (strcmp(caller_pkgid, target_pkgid) == 0)
+               return 0;
+
+       return -1;
+}
+
+static int __dispatch_widget_get_content(request_h req)
+{
+       int handles[2] = {0,};
+       struct iovec vec[3];
+       int msglen = 0;
+       char buffer[1024];
+       int ret;
+       bundle *kb = req->kb;
+       struct timeval tv;
+       int pid;
+       char *widget_id = NULL;
+       char *instance_id = NULL;
+
+       if (__validate_widget_caller(req) < 0) {
+               _request_send_result(req, -EILLEGALACCESS);
+               return -1;
+       }
+
+       bundle_get_str(kb, AUL_K_WIDGET_ID, &widget_id);
+       bundle_get_str(kb, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
+
+       pid = _widget_get_pid(widget_id, instance_id);
+       if (pid < 0) {
+               _E("can not find widget");
+               _request_send_result(req, -ENOENT);
+               return -1;
+       }
+
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) {
+               _E("error create socket pair");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       if (handles[0] == -1) {
+               _E("error socket open");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       tv.tv_sec = 5;
+       tv.tv_usec = 0;
+
+       ret = setsockopt(handles[1], SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+       if (ret < 0) {
+               _E("cannot set SO_RCVTIMEO for socket %d", handles[0]);
+               _request_send_result(req, -1);
+               goto out;
+       }
+
+       vec[0].iov_base = buffer;
+       vec[0].iov_len = strlen(buffer) + 1;
+
+       ret = aul_sock_send_bundle(pid, _request_get_target_uid(req), req->cmd,
+                       req->kb, AUL_SOCK_ASYNC);
+
+       msglen = __send_message(ret, vec, 1, &(handles[0]), 1);
+       if (msglen < 0) {
+               _E("Error[%d]: while sending message to widget", -msglen);
+               _request_send_result(req, -1);
+               ret = -1;
+               goto out;
+       }
+
+       msglen = __send_message(req->clifd, vec, 1, &(handles[1]), 1);
+       if (msglen < 0) {
+               _E("Error[%d]: while sending message to caller", -msglen);
+               _request_send_result(req, -1);
+               ret = -1;
+       }
+
+out:
+       close(handles[0]);
+       close(handles[1]);
+
+       return ret;
+}
+
+static int __dispatch_widget_list(request_h req)
+{
+       bundle *kb = req->kb;
+       char *widget_id = NULL;
+       int ret;
+
+       if (__validate_widget_caller(req) < 0) {
+               _request_send_result(req, -EILLEGALACCESS);
+               return -1;
+       }
+
+       bundle_get_str(kb, AUL_K_WIDGET_ID, &widget_id);
+       if (!widget_id) {
+               _request_send_result(req, -EINVAL);
+               return -1;
+       }
+
+       ret = _widget_list(widget_id, req);
+
+       return ret;
+}
+
+static int __dispatch_widget_update(request_h req)
+{
+       bundle *kb = _request_get_bundle(req);
+       char *widget_id = NULL;
+       int ret;
+
+       if (__validate_widget_caller(req) < 0) {
+               _request_send_result(req, -EILLEGALACCESS);
+               return -1;
+       }
+
+       bundle_get_str(kb, AUL_K_WIDGET_ID, &widget_id);
+       if (!widget_id) {
+               _request_send_result(req, -EINVAL);
+               return -1;
+       }
+
+       /* update will pass bundle by app_control */
+       req->cmd = APP_START_ASYNC;
+
+       ret = _widget_update(widget_id, req);
+       if (ret < 0)
+               return -1;
+
+       return 0;
+}
+
+static int __dispatch_widget_count(request_h req)
+{
+       bundle *kb = req->kb;
+       char *widget_id = NULL;
+       int count;
+
+       bundle_get_str(kb, AUL_K_WIDGET_ID, &widget_id);
+       if (!widget_id) {
+               _request_send_result(req, -EINVAL);
+               return -1;
+       }
+       count = _widget_count(widget_id, _request_get_uid(req));
+       _D("dispatch widget count %d", count);
+       _request_send_result(req, count);
+
+       return 0;
+}
+
+static int __dispatch_app_get_last_caller_pid(request_h req)
+{
+       int pid;
+       int ret;
+       app_status_h app_status;
+       const char *pid_str;
+       bundle *b = _request_get_bundle(req);
+
+       if (b == NULL) {
+               _E("Failed to get bundle");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       pid_str = bundle_get_val(b, AUL_K_PID);
+       if (pid_str == NULL || !isdigit(pid_str[0])) {
+               _E("Failed to get pid");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       pid = atoi(pid_str);
+       app_status = _app_status_find(pid);
+       ret = _app_status_get_last_caller_pid(app_status);
+       _D("app_get_last_caller_pid: %d : %d", pid, ret);
+       _request_send_result(req, ret);
+
+       return ret;
+}
+
+static int __dispatch_app_set_alias_appid(request_h req)
+{
+       int ret;
+       const char *appid;
+       const char *alias_appid;
+       const struct appinfo *ai;
+       bundle *kb;
+       uid_t uid = _request_get_target_uid(req);
+       app_property_h app_property;
+
+       kb = _request_get_bundle(req);
+       if (kb == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       alias_appid = bundle_get_val(kb, AUL_K_ALIAS_APPID);
+       if (alias_appid == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       if (appid == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ai = _appinfo_find(uid, appid);
+       if (ai == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = aul_svc_set_alias_appid_for_uid(alias_appid, appid, uid);
+       if (ret < 0) {
+               _E("Failed to set alias appid - alias_appid(%s), appid(%s)",
+                               alias_appid, appid);
+               _request_send_result(req, ret);
+               return -1;
+       }
+
+       app_property = _app_property_find(uid);
+       if (app_property == NULL) {
+               _E("Failed to find app property - uid(%d)", uid);
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = _app_property_add_alias_info(app_property, alias_appid, appid);
+       if (ret < 0) {
+               _E("Failed to add alias info - %s:%s", alias_appid, appid);
+               _request_send_result(req, ret);
+               return -1;
+       }
+
+       _request_send_result(req, 0);
+
+       return 0;
+}
+
+static int __dispatch_app_unset_alias_appid(request_h req)
+{
+       int ret;
+       const char *alias_appid;
+       bundle *kb;
+       uid_t uid = _request_get_target_uid(req);
+       app_property_h app_property;
+
+       kb = _request_get_bundle(req);
+       if (kb == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       alias_appid = bundle_get_val(kb, AUL_K_ALIAS_APPID);
+       if (alias_appid == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = aul_svc_unset_alias_appid_for_uid(alias_appid, uid);
+       if (ret < 0) {
+               _E("Failed to unset alias appid - alias_appid(%s)", alias_appid);
+               _request_send_result(req, ret);
+               return -1;
+       }
+
+       app_property = _app_property_find(uid);
+       if (app_property == NULL) {
+               _E("Failed to find app property - uid(%d)", uid);
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = _app_property_remove_alias_info(app_property, alias_appid, NULL);
+       if (ret < 0) {
+               _E("Failed to remove alias info - %s", alias_appid);
+               _request_send_result(req, ret);
+               return -1;
+       }
+
+       _request_send_result(req, 0);
+
+       return 0;
+}
+
+static int __dispatch_app_enable_alias_info(request_h req)
+{
+       int ret;
+       const char *appid;
+       bundle *kb;
+       uid_t uid = _request_get_target_uid(req);
+       app_property_h app_property;
+
+       kb = _request_get_bundle(req);
+       if (kb == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       if (appid == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = aul_svc_enable_alias_info_for_uid(appid, uid);
+       if (ret < 0) {
+               _E("Failed to activate alias info - appid(%s)", appid);
+               _request_send_result(req, ret);
+               return -1;
+       }
+
+       app_property = _app_property_find(uid);
+       if (app_property == NULL) {
+               _E("Failed to find app property - uid(%d)", uid);
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = _app_property_add_alias_info(app_property, NULL, appid);
+       if (ret < 0) {
+               _E("Failed to add alias info - %s", appid);
+               _request_send_result(req, ret);
+               return -1;
+       }
+
+       _request_send_result(req, 0);
+
+       return 0;
+}
+
+static int __dispatch_app_disable_alias_info(request_h req)
+{
+       int ret;
+       const char *appid;
+       bundle *kb;
+       uid_t uid = _request_get_target_uid(req);
+       app_property_h app_property;
+
+       kb = _request_get_bundle(req);
+       if (kb == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       appid = bundle_get_val(kb, AUL_K_APPID);
+       if (appid == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = aul_svc_disable_alias_info_for_uid(appid, uid);
+       if (ret < 0) {
+               _E("Failed to deactivate alias info - appid(%s)", appid);
+               _request_send_result(req, ret);
+               return -1;
+       }
+
+       app_property = _app_property_find(uid);
+       if (app_property == NULL) {
+               _E("Failed to find app property - uid(%d)", uid);
+               _request_send_result(req, -1);
+       }
+
+       ret = _app_property_remove_alias_info(app_property, NULL, appid);
+       if (ret < 0) {
+               _E("Failed to remove alias info - appid(%s)", appid);
+               _request_send_result(req, ret);
+               return -1;
+       }
+
+       _request_send_result(req, 0);
+
+       return 0;
+}
+
+static int __dispatch_add_app_screen(request_h req)
+{
+       uid_t uid = _request_get_target_uid(req);
+       int pid = _request_get_pid(req);
+       bundle *b = _request_get_bundle(req);
+       const char *instance_id;
+       const char *value;
+       unsigned int surf;
+       int ret;
+
+       if (b == NULL)
+               return -1;
+
+       instance_id = bundle_get_val(b, AUL_K_INSTANCE_ID);
+       value = bundle_get_val(b, AUL_K_WID);
+       if (value == NULL)
+               return -1;
+
+       surf = atol(value);
+       ret = _screen_connector_add_app_screen(pid, surf,
+                       instance_id, uid);
+       _D("pid(%d), surf(%d), instance_id(%s), result(%d)",
+                       pid, surf, instance_id, ret);
+
+       return 0;
+}
+
+static int __dispatch_remove_app_screen(request_h req)
+{
+       uid_t uid = _request_get_target_uid(req);
+       int pid = _request_get_pid(req);
+       bundle *b = _request_get_bundle(req);
+       const char *instance_id;
+       int ret;
+
+       if (b == NULL)
+               return -1;
+
+       instance_id = bundle_get_val(b, AUL_K_INSTANCE_ID);
+       ret = _screen_connector_remove_app_screen(pid,
+                       instance_id, uid);
+       _D("pid(%d), instance_id(%s), result(%d)",
+                       pid, instance_id, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_update_requested(request_h req)
+{
+       uid_t uid = _request_get_target_uid(req);
+       int caller_pid = _request_get_pid(req);
+       bundle *b = _request_get_bundle(req);
+       const char *appid;
+       const char *instance_id;
+       int ret;
+
+       if (b == NULL)
+               return -1;
+
+       appid = bundle_get_val(b, AUL_K_APPID);
+       if (appid == NULL)
+               return -1;
+
+       instance_id = bundle_get_val(b, AUL_K_INSTANCE_ID);
+       ret = _screen_connector_send_update_request(appid, instance_id, uid);
+       _D("appid(%s), instance_id(%s), caller_pid(%d), result(%d)",
+                       appid, instance_id, caller_pid, ret);
+
+       return 0;
+}
+
+static int __dispatch_add_screen_viewer(request_h req)
+{
+       uid_t uid = _request_get_target_uid(req);
+       int pid = _request_get_pid(req);
+       bundle *b = _request_get_bundle(req);
+       const char *value;
+       bool priv;
+       int screen_type;
+       unsigned int ref;
+       int ret;
+
+       if (b == NULL)
+               return -1;
+
+       value = bundle_get_val(b, AUL_K_SCREEN_TYPE);
+       if (value == NULL)
+               return -1;
+       screen_type = atoi(value);
+
+       value = bundle_get_val(b, AUL_K_VIEWER_REF);
+       if (value == NULL)
+               return -1;
+       ref = atol(value);
+
+       value = bundle_get_val(b, AUL_K_PRIVATE);
+       if (value && strcmp(value, "true") == 0)
+               priv = true;
+       else
+               priv = false;
+
+       ret = _screen_connector_add_screen_viewer(pid, screen_type,
+                       priv, ref, uid);
+       _D("pid(%d), screen_type(%d), private(%d), result(%d)",
+                       pid, screen_type, priv, ret);
+
+       return 0;
+}
+
+static int __dispatch_remove_screen_viewer(request_h req)
+{
+       uid_t uid = _request_get_target_uid(req);
+       int pid = _request_get_pid(req);
+       bundle *b = _request_get_bundle(req);
+       const char *value;
+       bool priv;
+       int screen_type;
+       unsigned int ref;
+       int ret;
+
+       if (b == NULL)
+               return -1;
+
+       value = bundle_get_val(b, AUL_K_SCREEN_TYPE);
+       if (value == NULL)
+               return -1;
+       screen_type = atoi(value);
+
+       value = bundle_get_val(b, AUL_K_VIEWER_REF);
+       if (value == NULL)
+               return -1;
+       ref = atol(value);
+
+       value = bundle_get_val(b, AUL_K_PRIVATE);
+       if (value && strcmp(value, "true") == 0)
+               priv = true;
+       else
+               priv = false;
+
+       ret = _screen_connector_remove_screen_viewer(pid, screen_type,
+                       priv, ref, uid);
+       _D("pid(%d), screen_type(%d), private(%d), result(%d)",
+                       pid, screen_type, priv, ret);
+
+       return 0;
+}
+
+static int __dispatch_launchpad_launch_signal(request_h req)
+{
+       uid_t target_uid = _request_get_target_uid(req);
+
+       _D("uid(%d)", target_uid);
+       _login_monitor_set_uid_state(target_uid, UID_STATE_ONLINE);
+       close(_request_remove_fd(req));
+
+       return 0;
+}
+
+static int __dispatch_app_running_instance_info(request_h req)
+{
+       int fd = _request_remove_fd(req);
+       int cmd = _request_get_cmd(req);
+       uid_t target_uid = _request_get_target_uid(req);
+
+       return _app_status_send_running_appinfo(fd, cmd, target_uid);
+}
+
+static int __dispatch_app_get_instance_id_by_pid(request_h req)
+{
+       int pid;
+       int ret;
+       const char *pid_str;
+       int fd = _request_remove_fd(req);
+       bundle *b = _request_get_bundle(req);
+
+       if (b == NULL) {
+               _E("Failed to get bundle");
+               aul_sock_send_raw_with_fd(fd, APP_GET_INFO_ERROR,
+                               NULL, 0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       pid_str = bundle_get_val(b, AUL_K_PID);
+       if (pid_str == NULL || !isdigit(pid_str[0])) {
+               _E("Failed to get pid");
+               aul_sock_send_raw_with_fd(fd, APP_GET_INFO_ERROR,
+                               NULL, 0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       pid = atoi(pid_str);
+       ret = _app_status_get_instance_id_bypid(fd, pid);
+       _D("app get instance-id by pid - pid(%d), ret(%d)", pid, ret);
+
+       return ret;
+}
+
+static int __dispatch_app_get_appid_from_cache(request_h req)
+{
+       const char *checksum;
+       const char *appid;
+       bundle *b = _request_get_bundle(req);
+       app_property_h prop = _app_property_find(_request_get_target_uid(req));
+
+       checksum = bundle_get_val(b, AUL_K_CHECKSUM);
+       appid  = _app_property_cache_get(prop, checksum);
+
+       if (!appid) {
+               aul_sock_send_raw_with_fd(_request_remove_fd(req),
+                               APP_GET_APPID_FROM_CACHE, NULL, 0, AUL_SOCK_NOREPLY);
+               return 0;
+       }
+
+       aul_sock_send_raw_with_fd(_request_remove_fd(req),
+               APP_GET_APPID_FROM_CACHE, (unsigned char *)appid,
+               strlen(appid), AUL_SOCK_NOREPLY);
+
+       return 0;
+}
+
+static int __dispatch_app_set_cache(request_h req)
+{
+       const char *appid;
+       const char *checksum;
+       bundle *b = _request_get_bundle(req);
+       app_property_h prop = _app_property_find(_request_get_target_uid(req));
+
+       appid = bundle_get_val(b, AUL_K_APPID);
+       checksum = bundle_get_val(b, AUL_K_CHECKSUM);
+
+       if (!appid || !checksum) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       _app_property_cache_put(prop, checksum, appid);
+       _request_send_result(req, 0);
+       return 0;
+}
+
+static int __dispatch_app_invalidate_cache(request_h req)
+{
+       app_property_h prop = _app_property_find(_request_get_target_uid(req));
+
+       _app_property_cache_invalidate(prop);
+       _request_send_result(req, 0);
+       return 0;
+}
+
+static int __dispatch_app_startup_signal(request_h req)
+{
+       int pid = _request_get_pid(req);
+       app_status_h app_status;
+       struct pending_item *item;
+       struct reply_info *info;
+       GList *iter;
+
+       _I("[APP_STARTUP_SIGNAL] pid(%d)", pid);
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return -1;
+
+       _app_status_update_is_starting(app_status, true);
+       if (_app_status_get_app_type(app_status) == AT_UI_APP &&
+                       _app_status_get_status(app_status) != STATUS_VISIBLE)
+               _launch_add_fgmgr(pid);
+
+       item = g_hash_table_lookup(pending_table, GINT_TO_POINTER(pid));
+       if (item == NULL) {
+               _W("pending item doesn't exist - pid(%d)", pid);
+               return -1;
+       }
+
+       item->timer = g_timeout_add(PENDING_REQUEST_TIMEOUT,
+                       __timeout_pending_item, item);
+
+       iter = g_list_first(item->reply_list);
+       while (iter) {
+               info = (struct reply_info *)iter->data;
+               if (info && info->rua) {
+                       g_timeout_add(1500, __add_history_handler, info->rua);
+                       info->rua = NULL;
+               }
+               iter = g_list_next(iter);
+       }
+
+       return 0;
+}
+
+static int __dispatch_app_window_attach(request_h req)
+{
+       bundle *b = _request_get_bundle(req);
+       const char *parent_appid;
+       const char *child_appid;
+       int ret;
+       uid_t uid = _request_get_target_uid(req);
+
+       if (!b) {
+               _E("Invalid bundle");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       parent_appid = bundle_get_val(b, AUL_K_PARENT_APPID);
+       if (!parent_appid) {
+               _E("Invalid parameters");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       child_appid = bundle_get_val(b, AUL_K_CHILD_APPID);
+       if (!child_appid) {
+               _E("Invalid parameters");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = _app_group_attach(parent_appid, child_appid, uid);
+       _request_send_result(req, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_window_detach(request_h req)
+{
+       bundle *b = _request_get_bundle(req);
+       const char *child_appid;
+       int ret;
+       uid_t uid = _request_get_target_uid(req);
+
+       if (!b) {
+               _E("Invalid bundle");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       child_appid = bundle_get_val(b, AUL_K_CHILD_APPID);
+       if (!child_appid) {
+               _E("Invalid parameters");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = _app_group_detach(child_appid, uid);
+       _request_send_result(req, ret);
+
+       return 0;
+}
+
+static int __dispatch_app_notify_exit(request_h req)
+{
+       int pid = _request_get_pid(req);
+       int ret;
+       app_status_h app_status;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               _E("pid %d is not an application", pid);
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret = _app_status_set_is_exit_notified(app_status, true);
+       _D("[APP_NOTIFY_EXIT] result(%d)", ret);
+
+       return 0;
+}
+
+static int __dispatch_app_get_appid_by_surface_id(request_h req)
+{
+       uid_t uid = _request_get_target_uid(req);
+       bundle *b = _request_get_bundle(req);
+       unsigned int *surf = NULL;
+       const char *appid;
+       size_t size;
+       bundle *ret_b;
+
+       if (b == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       bundle_get_byte(b, "__AUL_SC_SURFACE__", (void **)&surf, &size);
+       if (surf == NULL) {
+               _E("Failed to get surface");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       appid = _screen_connector_get_appid_by_surface_id(*surf, uid);
+       if (appid == NULL) {
+               _E("Failed to get appid");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret_b = bundle_create();
+       if (ret_b == NULL) {
+               _E("Out of memory");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       bundle_add_str(ret_b, AUL_K_APPID, appid);
+       aul_sock_send_bundle_with_fd(_request_remove_fd(req),
+                       _request_get_cmd(req), ret_b, AUL_SOCK_NOREPLY);
+       bundle_free(ret_b);
+
+       return 0;
+}
+
+static int __dispatch_app_get_instance_id_by_surface_id(request_h req)
+{
+       uid_t uid = _request_get_target_uid(req);
+       bundle *b = _request_get_bundle(req);
+       unsigned int *surf = NULL;
+       const char *instance_id;
+       size_t size;
+       bundle *ret_b;
+
+       if (b == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       bundle_get_byte(b, "__AUL_SC_SURFACE__", (void **)&surf, &size);
+       if (surf == NULL) {
+               _E("Failed to get surface");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       instance_id = _screen_connector_get_instance_id_by_surface_id(*surf,
+                       uid);
+       if (instance_id == NULL) {
+               _E("Failed to get instance_id");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       ret_b = bundle_create();
+       if (ret_b == NULL) {
+               _E("Out of memory");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       bundle_add_str(ret_b, AUL_K_INSTANCE_ID, instance_id);
+       aul_sock_send_bundle_with_fd(_request_remove_fd(req),
+                       _request_get_cmd(req), ret_b, AUL_SOCK_NOREPLY);
+       bundle_free(ret_b);
+
+       return 0;
+}
+
+static int __dispatch_update_screen_viewer_status(request_h req)
+{
+       uid_t uid = _request_get_target_uid(req);
+       int pid = _request_get_pid(req);
+       bundle *b = _request_get_bundle(req);
+       const char *val;
+       aul_screen_status_e status;
+       unsigned int surf;
+       int r;
+
+       if (b == NULL) {
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       val = bundle_get_val(b, "__AUL_SC_VIEWER_STATUS__");
+       if (val == NULL || !isdigit(*val)) {
+               _E("Failed to get viewer status");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       status = atoi(val);
+
+       val = bundle_get_val(b, AUL_K_WID);
+       if (val == NULL || !isdigit(*val)) {
+               _E("Failed to get surface id");
+               _request_send_result(req, -1);
+               return -1;
+       }
+
+       surf = strtoul(val, NULL, 10);
+
+       r = _screen_connector_update_screen_viewer_status(pid, status,
+                       surf, uid);
+       _request_send_result(req, r);
+
+       return 0;
+}
+
+static int __dispatch_widget_running_info(request_h req)
+{
+       return _widget_send_running_info(req);
+}
+
+static app_cmd_dispatch_func dispatch_table[APP_CMD_MAX] = {
+       [APP_GET_DC_SOCKET_PAIR] = __dispatch_get_dc_socket_pair,
+       [APP_GET_MP_SOCKET_PAIR] = __dispatch_get_mp_socket_pair,
+       [APP_START] =  __dispatch_app_start,
+       [APP_OPEN] = __dispatch_app_start,
+       [APP_RESUME] = __dispatch_app_start,
+       [APP_RESUME_BY_PID] = __dispatch_app_process_by_pid,
+       [APP_TERM_BY_PID] = __dispatch_app_term,
+       [APP_TERM_BY_PID_WITHOUT_RESTART] = __dispatch_app_term_async,
+       [APP_RESULT] = __dispatch_app_result,
+       [APP_START_RES] = __dispatch_app_start,
+       [APP_CANCEL] = __dispatch_app_result,
+       [APP_KILL_BY_PID] = __dispatch_app_term,
+       [APP_UPDATE_RUA_STAT] = __dispatch_update_rua_stat,
+       [APP_ADD_HISTORY] = __dispatch_add_history,
+       [APP_REMOVE_HISTORY] = __dispatch_remove_history,
+       [APP_RUNNING_INFO] = __dispatch_app_running_info,
+       [APP_RUNNING_INFO_RESULT] = NULL,
+       [APP_IS_RUNNING] = __dispatch_app_is_running,
+       [APP_GET_APPID_BYPID] = __dispatch_app_get_appid_by_pid,
+       [APP_GET_PKGID_BYPID] = __dispatch_app_get_pkgid_by_pid,
+       [APP_GET_INFO_OK] = NULL,
+       [APP_GET_INFO_ERROR] = NULL,
+       [APP_KEY_EVENT] = NULL,
+       [APP_KEY_RESERVE] = __dispatch_legacy_command,
+       [APP_KEY_RELEASE] = __dispatch_legacy_command,
+       [APP_STATUS_UPDATE] = __dispatch_app_status_update,
+       [APP_RUNNING_LIST_UPDATE] = __dispatch_legacy_command,
+       [APP_TERM_REQ_BY_PID] = __dispatch_app_process_by_pid,
+       [APP_TERM_BY_PID_ASYNC] = __dispatch_app_term_async,
+       [APP_TERM_BGAPP_BY_PID] = __dispatch_app_term,
+       [APP_PAUSE] = __dispatch_app_pause,
+       [APP_PAUSE_BY_PID] = __dispatch_app_process_by_pid,
+       [APP_GROUP_GET_WINDOW] = __dispatch_app_group_get_window,
+       [APP_GROUP_SET_WINDOW] = __dispatch_app_group_set_window,
+       [APP_GROUP_GET_FG] = __dispatch_app_group_get_fg_flag,
+       [APP_GROUP_GET_LEADER_PID] = __dispatch_app_group_get_leader_pid,
+       [APP_GROUP_GET_LEADER_PIDS] = __dispatch_app_group_get_leader_pids,
+       [APP_GROUP_GET_GROUP_PIDS] = __dispatch_app_group_get_group_pids,
+       [APP_GROUP_GET_IDLE_PIDS] = __dispatch_app_group_get_idle_pids,
+       [APP_GROUP_LOWER] = __dispatch_app_group_lower,
+       [APP_GROUP_CLEAR_TOP] = __dispatch_app_group_clear_top,
+       [APP_GROUP_ACTIVATE_BELOW] = __dispatch_app_group_activate_below,
+       [APP_GROUP_ACTIVATE_ABOVE] = __dispatch_app_group_activate_above,
+       [APP_GET_STATUS] = __dispatch_app_get_status,
+       [APP_ADD_LOADER] = __dispatch_app_add_loader,
+       [APP_REMOVE_LOADER] = __dispatch_app_remove_loader,
+       [APP_GET_PID] = __dispatch_app_is_running,
+       [AMD_RELOAD_APPINFO] = __dispatch_amd_reload_appinfo,
+       [LAUNCHPAD_DEAD_SIGNAL] = __dispatch_launchpad_dead_signal,
+       [APP_COM_CREATE] = __dispatch_app_com_create,
+       [APP_COM_JOIN] = __dispatch_app_com_join,
+       [APP_COM_SEND] = __dispatch_app_com_send,
+       [APP_COM_LEAVE] = __dispatch_app_com_leave,
+       [WIDGET_ADD] = __dispatch_widget_add_del,
+       [WIDGET_DEL] = __dispatch_widget_add_del,
+       [WIDGET_LIST] = __dispatch_widget_list,
+       [WIDGET_UPDATE] = __dispatch_widget_update,
+       [WIDGET_COUNT] = __dispatch_widget_count,
+       [WIDGET_GET_CONTENT] = __dispatch_widget_get_content,
+       [APP_REGISTER_PID] = __dispatch_app_register_pid,
+       [APP_ALL_RUNNING_INFO] = __dispatch_app_all_running_info,
+       [APP_SET_APP_CONTROL_DEFAULT_APP] =
+               __dispatch_app_set_app_control_default_app,
+       [APP_UNSET_APP_CONTROL_DEFAULT_APP] =
+               __dispatch_app_unset_app_control_default_app,
+       [APP_START_ASYNC] = __dispatch_app_start,
+       [APP_SET_PROCESS_GROUP] = __dispatch_app_set_process_group,
+       [APP_PREPARE_CANDIDATE_PROCESS] =
+               __dispatch_app_prepare_candidate_process,
+       [APP_TERM_BY_PID_SYNC] = __dispatch_app_term_sync,
+       [APP_GET_STATUS_BY_APPID] = __dispatch_app_get_status_by_appid,
+       [APP_GET_LAST_CALLER_PID] = __dispatch_app_get_last_caller_pid,
+       [APP_TERM_BY_PID_SYNC_WITHOUT_RESTART] =
+               __dispatch_app_term_sync_without_restart,
+       [APP_RESUME_BY_PID_ASYNC] = __dispatch_app_process_by_pid,
+       [APP_SET_ALIAS_APPID] = __dispatch_app_set_alias_appid,
+       [APP_UNSET_ALIAS_APPID] = __dispatch_app_unset_alias_appid,
+       [APP_ENABLE_ALIAS_INFO] = __dispatch_app_enable_alias_info,
+       [APP_DISABLE_ALIAS_INFO] = __dispatch_app_disable_alias_info,
+       [ADD_APP_SCREEN] = __dispatch_add_app_screen,
+       [REMOVE_APP_SCREEN] = __dispatch_remove_app_screen,
+       [APP_UPDATE_REQUESTED] = __dispatch_app_update_requested,
+       [ADD_SCREEN_VIEWER] = __dispatch_add_screen_viewer,
+       [REMOVE_SCREEN_VIEWER] = __dispatch_remove_screen_viewer,
+       [LAUNCHPAD_LAUNCH_SIGNAL] = __dispatch_launchpad_launch_signal,
+       [APP_RUNNING_INSTANCE_INFO] = __dispatch_app_running_instance_info,
+       [APP_GET_INSTANCE_ID_BYPID] = __dispatch_app_get_instance_id_by_pid,
+       [APP_GET_APPID_FROM_CACHE] = __dispatch_app_get_appid_from_cache,
+       [APP_SET_CACHE] = __dispatch_app_set_cache,
+       [APP_INVALIDATE_CACHE] = __dispatch_app_invalidate_cache,
+       [APP_STARTUP_SIGNAL] = __dispatch_app_startup_signal,
+       [APP_WINDOW_ATTACH] = __dispatch_app_window_attach,
+       [APP_WINDOW_DETACH] = __dispatch_app_window_detach,
+       [APP_START_RES_ASYNC] = __dispatch_app_start,
+       [APP_NOTIFY_EXIT] = __dispatch_app_notify_exit,
+       [APP_GET_APPID_BY_SURFACE_ID] = __dispatch_app_get_appid_by_surface_id,
+       [APP_GET_INSTANCE_ID_BY_SURFACE_ID] =
+               __dispatch_app_get_instance_id_by_surface_id,
+       [UPDATE_SCREEN_VIEWER_STATUS] = __dispatch_update_screen_viewer_status,
+       [WIDGET_RUNNING_INFO] = __dispatch_widget_running_info,
+};
+
+static void __free_reply_info(gpointer data)
+{
+       struct reply_info *reply = (struct reply_info *)data;
+
+       if (reply == NULL)
+               return;
+
+       if (reply->rua)
+               __free_rua_stat_pkt(reply->rua);
+       if (reply->clifd)
+               close(reply->clifd);
+       if (reply->timer)
+               g_source_remove(reply->timer);
+       free(reply);
+}
+
+static struct reply_info *__create_reply_info(guint interval, pid_t pid,
+               int result, int cmd, int clifd, rua_stat_pkt_t *rua)
+{
+       struct reply_info *reply;
+
+       reply = malloc(sizeof(struct reply_info));
+       if (reply == NULL) {
+               _E("Out of memory");
+               return NULL;
+       }
+
+       reply->pid = pid;
+       reply->result = result;
+       reply->cmd = cmd;
+       reply->clifd = clifd;
+       reply->timer = g_timeout_add(interval, __timeout_reply, reply);
+       reply->rua = rua;
+
+       return reply;
+}
+
+static void __free_request(gpointer data)
+{
+       request_h req = (request_h)data;
+
+       if (req == NULL)
+               return;
+
+       if (req->clifd)
+               close(req->clifd);
+       if (req->timer)
+               g_source_remove(req->timer);
+       if (req->kb)
+               bundle_free(req->kb);
+
+       free(req);
+}
+
+static void __free_pending_item(gpointer user_data)
+{
+       struct pending_item *item = (struct pending_item *)user_data;
+
+       if (item == NULL)
+               return;
+
+       if (item->reply_list)
+               g_list_free_full(item->reply_list, __free_reply_info);
+       if (item->pending_list)
+               g_list_free_full(item->pending_list, __free_request);
+       if (g_main_context_find_source_by_user_data(NULL, item))
+               g_source_remove(item->timer);
+       free(item);
+}
+
+static void __timeout_pending_reply(gpointer data, gpointer user_data)
+{
+       struct reply_info *reply = (struct reply_info *)data;
+
+       if (reply == NULL)
+               return;
+
+       _send_result_to_client(reply->clifd, reply->result);
+       reply->clifd = 0;
+}
+
+static void __timeout_pending_request(gpointer data, gpointer user_data)
+{
+       request_h req = (request_h)data;
+
+       if (req == NULL)
+               return;
+
+       _request_send_result(req, -EAGAIN);
+}
+
+static gboolean __timeout_pending_item(gpointer user_data)
+{
+       struct pending_item *item = (struct pending_item *)user_data;
+
+       if (item == NULL)
+               return FALSE;
+
+       g_list_foreach(item->reply_list, __timeout_pending_reply, NULL);
+       g_list_foreach(item->pending_list, __timeout_pending_request, NULL);
+       g_hash_table_remove(pending_table, GINT_TO_POINTER(item->pid));
+
+       return FALSE;
+}
+
+static void __flush_pending_reply_list(GList **reply_list, bool is_dead)
+{
+       GList *iter;
+       struct reply_info *reply;
+
+       if (reply_list == NULL)
+               return;
+
+       iter = g_list_first(*reply_list);
+       while (iter) {
+               reply = (struct reply_info *)iter->data;
+               iter = g_list_next(iter);
+               if (reply == NULL)
+                       continue;
+
+               if (reply->cmd == APP_TERM_BY_PID_SYNC_WITHOUT_RESTART ||
+                               reply->cmd == APP_TERM_BY_PID_SYNC) {
+                       if (!is_dead)
+                               continue;
+
+                       reply->result = 0;
+               }
+
+               *reply_list = g_list_remove(*reply_list, reply);
+               _send_result_to_client(reply->clifd, reply->result);
+               reply->clifd = 0;
+               __free_reply_info(reply);
+       }
+}
+
+static void __flush_pending_request_list(GList **pending_list)
+{
+       GList *iter;
+       request_h req;
+
+       if (pending_list == NULL)
+               return;
+
+       iter = g_list_first(*pending_list);
+       while (iter) {
+               req = (request_h)iter->data;
+               iter = g_list_next(iter);
+               if (req == NULL)
+                       continue;
+
+               *pending_list = g_list_remove(*pending_list, req);
+               if (req->timer) {
+                       g_source_remove(req->timer);
+                       req->timer = 0;
+               }
+               g_idle_add(__dispatch_request, req);
+       }
+}
+
+int _request_flush_pending_request(int pid)
+{
+       struct pending_item *item;
+
+       item = (struct pending_item *)g_hash_table_lookup(pending_table,
+                       GINT_TO_POINTER(pid));
+       if (item == NULL)
+               return -1;
+
+       __flush_pending_reply_list(&item->reply_list, true);
+       __timeout_pending_item((gpointer)item);
+
+       return 0;
+}
+
+int _request_reply_for_pending_request(int pid)
+{
+       struct pending_item *item;
+
+       _app_status_publish_status(pid, STATUS_LAUNCHING);
+
+       item = (struct pending_item *)g_hash_table_lookup(pending_table,
+                       GINT_TO_POINTER(pid));
+       if (item == NULL)
+               return -1;
+
+       __flush_pending_reply_list(&item->reply_list, false);
+       __flush_pending_request_list(&item->pending_list);
+
+       return 0;
+}
+
+static request_h __get_request(int clifd, app_pkt_t *pkt,
+               struct ucred cr)
+{
+       request_h req;
+       const char *target_uid;
+
+       req = (request_h)malloc(sizeof(struct request_s) + pkt->len);
+       if (req == NULL)
+               return NULL;
+
+       g_get_current_time(&req->start);
+       req->timer = 0;
+       req->clifd = clifd;
+       req->pid = cr.pid;
+       req->t_pid = 0;
+       req->uid = cr.uid;
+       req->cmd = pkt->cmd;
+       req->len = pkt->len;
+       req->opt = pkt->opt;
+       memcpy(req->data, pkt->data, pkt->len + 1);
+
+       if (pkt->opt & AUL_SOCK_BUNDLE) {
+               req->kb = bundle_decode(pkt->data, pkt->len);
+               if (req->kb == NULL) {
+                       free(req);
+                       return NULL;
+               }
+
+               target_uid = bundle_get_val(req->kb, AUL_K_TARGET_UID);
+               if (target_uid && isdigit(target_uid[0]))
+                       req->t_uid = atoi(target_uid);
+               else
+                       req->t_uid = cr.uid;
+       } else {
+               req->kb = NULL;
+               req->t_uid = cr.uid;
+       }
+
+       return req;
+}
+
+static gboolean __timeout_reply(gpointer data)
+{
+       struct reply_info *reply = (struct reply_info *)data;
+       struct pending_item *item;
+
+       if (reply == NULL)
+               return FALSE;
+
+       item = g_hash_table_lookup(pending_table, GINT_TO_POINTER(reply->pid));
+       if (item)
+               item->reply_list = g_list_remove(item->reply_list, reply);
+
+       _send_result_to_client(reply->clifd, reply->result);
+       reply->clifd = 0;
+       reply->timer = 0;
+       __free_reply_info(reply);
+
+       return FALSE;
+}
+
+static gboolean __timeout_request(gpointer data)
+{
+       request_h req = (request_h)data;
+       struct pending_item *item;
+
+       if (req == NULL)
+               return FALSE;
+
+       item = g_hash_table_lookup(pending_table, GINT_TO_POINTER(req->t_pid));
+       if (item)
+               item->pending_list = g_list_remove(item->pending_list, req);
+
+       if (req->clifd)
+               _request_send_result(req, -EAGAIN);
+       req->timer = 0;
+       __free_request(req);
+
+       return FALSE;
+}
+
+static app_status_h __get_app_status(request_h req, const char *appid)
+{
+       int pid;
+       app_status_h app_status;
+       int status;
+       struct appinfo *ai;
+       const char *comp_type;
+
+       switch (req->cmd) {
+       case APP_RESUME_BY_PID:
+       case APP_TERM_BY_PID:
+       case APP_TERM_BY_PID_WITHOUT_RESTART:
+       case APP_KILL_BY_PID:
+       case APP_TERM_REQ_BY_PID:
+       case APP_TERM_BY_PID_ASYNC:
+       case APP_TERM_BGAPP_BY_PID:
+       case APP_PAUSE_BY_PID:
+       case APP_TERM_BY_PID_SYNC:
+       case APP_TERM_BY_PID_SYNC_WITHOUT_RESTART:
+               /* get pid */
+               pid = atoi(appid);
+               app_status = _app_status_find(pid);
+               break;
+       case APP_START_ASYNC:
+       case APP_START_RES_ASYNC:
+               ai = _appinfo_find(_request_get_target_uid(req), appid);
+               comp_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+               if (comp_type && (strcmp(comp_type, APP_TYPE_WIDGET) == 0 ||
+                               strcmp(comp_type, APP_TYPE_WATCH) == 0)) {
+                       app_status = _app_status_find_with_org_caller(appid,
+                                       _request_get_target_uid(req),
+                                       _request_get_pid(req));
+               } else {
+                       app_status = _app_status_find_by_appid(appid,
+                                       _request_get_target_uid(req));
+               }
+               break;
+       default:
+               app_status = _app_status_find_by_appid(appid,
+                               _request_get_target_uid(req));
+               break;
+       }
+
+       if (app_status == NULL)
+               return NULL;
+
+       status = _app_status_get_status(app_status);
+       if (status == STATUS_DYING)
+               return NULL;
+
+       return app_status;
+}
+
+static int __check_request(request_h req)
+{
+       int pid;
+       struct pending_item *item;
+       app_status_h app_status;
+       const char *appid;
+
+       if (req->opt & AUL_SOCK_NOREPLY)
+               close(_request_remove_fd(req));
+
+       if ((req->opt & AUL_SOCK_QUEUE) == 0)
+               return 0;
+
+       if (req->kb == NULL)
+               return -1;
+
+       appid = bundle_get_val(req->kb, AUL_K_APPID);
+       if (appid == NULL)
+               return -1;
+
+       app_status = __get_app_status(req, appid);
+       if (app_status == NULL)
+               return 0;
+
+       if (_app_status_socket_exists(app_status))
+               return 0;
+
+       pid = _app_status_get_pid(app_status);
+       item = g_hash_table_lookup(pending_table, GINT_TO_POINTER(pid));
+       if (item == NULL)
+               return 0;
+
+       if (!_app_status_is_starting(app_status)) {
+               req->t_pid = pid;
+               _W("%s(%d) is waiting to be started.", appid, pid);
+               req->timer = g_timeout_add(PENDING_REQUEST_TIMEOUT,
+                               __timeout_request, req);
+       }
+
+       item->pending_list = g_list_append(item->pending_list, req);
+
+       return 1;
+}
+
+static int __check_target_user(request_h req)
+{
+       int r;
+       uid_t *uids;
+       int i;
+       uid_state state;
+
+       if (req->t_uid >= REGULAR_UID_MIN) {
+               state = _login_monitor_get_uid_state(req->t_uid);
+               if (state == UID_STATE_ONLINE || state == UID_STATE_ACTIVE)
+                       return 0;
+
+               return -1;
+       }
+
+       r = _login_monitor_get_uids(&uids);
+       if (r <= 0)
+               return -1;
+
+       for (i = 0; i < r; i++) {
+               state = _login_monitor_get_uid_state(uids[i]);
+               if (state == UID_STATE_ONLINE || state == UID_STATE_ACTIVE) {
+                       req->t_uid = uids[i];
+                       break;
+               }
+       }
+       free(uids);
+
+       if (req->t_uid < REGULAR_UID_MIN)
+               return -1;
+
+       return 0;
+}
+
+static gboolean __dispatch_request(gpointer data)
+{
+       request_h req = (request_h)data;
+
+       if (req == NULL)
+               return FALSE;
+
+       if (req->cmd < 0 || req->cmd >= APP_CMD_MAX) {
+               __free_request(req);
+               return FALSE;
+       }
+
+       if (dispatch_table[req->cmd]) {
+               if (dispatch_table[req->cmd](req) != 0)
+                       _E("callback returns FALSE : %d", req->cmd);
+       } else {
+               _E("Invalid request or not supported command");
+       }
+
+       __free_request(req);
+
+       return FALSE;
+}
+
+int _request_usr_init(uid_t uid)
+{
+       GList *iter;
+       request_h req;
+       int r;
+       struct pending_item *item;
+
+       item = g_hash_table_lookup(pending_table, GINT_TO_POINTER(getpid()));
+       if (item == NULL || item->pending_list == NULL)
+               return 0;
+
+       iter = g_list_first(item->pending_list);
+       while (iter) {
+               req = (request_h)iter->data;
+               iter = g_list_next(iter);
+               if (req == NULL)
+                       continue;
+
+               req->t_pid = 0;
+               if (req->t_uid < REGULAR_UID_MIN)
+                       req->t_uid = uid;
+
+               if (req->t_uid == uid) {
+                       g_source_remove(req->timer);
+                       req->timer = 0;
+                       item->pending_list = g_list_remove(item->pending_list,
+                                       req);
+
+                       r = __check_request(req);
+                       if (r == 0)
+                               g_idle_add(__dispatch_request, (gpointer)req);
+                       else if (r < 0)
+                               __free_request(req);
+               }
+       }
+
+       return 0;
+}
+
+static gboolean __request_handler(GIOChannel *io, GIOCondition cond,
+               gpointer data)
+{
+       int fd = g_io_channel_unix_get_fd(io);
+       app_pkt_t *pkt;
+       int ret;
+       int clifd;
+       struct ucred cr;
+       request_h req;
+       int len;
+       struct pending_item *item;
+
+       pkt = aul_sock_recv_pkt(fd, &clifd, &cr);
+       if (pkt == NULL) {
+               _E("recv error");
+               return TRUE;
+       }
+
+       req = __get_request(clifd, pkt, cr);
+       if (req == NULL) {
+               close(clifd);
+               free(pkt);
+               return TRUE;
+       }
+       free(pkt);
+
+       if (req->uid >= REGULAR_UID_MIN) {
+               if (req->uid != req->t_uid) {
+                       _E("request has been deined - uid(%d), target_uid(%d)",
+                                       req->uid, req->t_uid);
+                       ret = -EILLEGALACCESS;
+                       _request_send_result(req, ret);
+                       __free_request(req);
+                       return TRUE;
+               }
+
+               ret = _cynara_check_privilege(req);
+               if (ret < 0) {
+                       _E("request has been denied by cynara");
+                       ret = -EILLEGALACCESS;
+                       _request_send_result(req, ret);
+                       __free_request(req);
+                       return TRUE;
+               }
+       } else {
+               ret = __check_target_user(req);
+               if (ret < 0 && (req->cmd == APP_START_ASYNC ||
+                                       req->cmd == APP_START_RES_ASYNC)) {
+                       item = g_hash_table_lookup(pending_table,
+                                       GINT_TO_POINTER(getpid()));
+                       if (item == NULL) {
+                               item = calloc(1, sizeof(struct pending_item));
+                               if (item == NULL) {
+                                       _E("Out of memory");
+                                       _request_send_result(req, ret);
+                                       __free_request(req);
+                                       return TRUE;
+                               }
+                               item->pid = getpid();
+                               g_hash_table_insert(pending_table,
+                                               GINT_TO_POINTER(getpid()),
+                                               item);
+                       }
+
+                       len = g_list_length(item->pending_list);
+                       if (len <= PENDING_MESSAGE_MAX_CNT) {
+                               _D("user not logged");
+                               _request_send_result(req, 0);
+                               req->t_pid = getpid();
+                               req->timer = g_timeout_add(
+                                               SYSTEM_REQUEST_TIMEOUT,
+                                               __timeout_request, req);
+                               item->pending_list = g_list_append(
+                                               item->pending_list, req);
+                               return TRUE;
+                       }
+               }
+       }
+
+       ret = __check_request(req);
+       if (ret < 0) {
+               _request_send_result(req, ret);
+               __free_request(req);
+               return TRUE;
+       } else if (ret > 0) {
+               return TRUE;
+       }
+
+       __dispatch_request((gpointer)req);
+
+       return TRUE;
+}
+
+int _request_get_fd(request_h req)
+{
+       return req->clifd;
+}
+
+int _request_get_pid(request_h req)
+{
+       return req->pid;
+}
+
+pid_t _request_get_target_pid(request_h req)
+{
+       return req->t_pid;
+}
+
+bundle *_request_get_bundle(request_h req)
+{
+       return req->kb;
+}
+
+request_h _request_create_local(int cmd, uid_t uid, int pid, bundle *kb)
+{
+       request_h req;
+
+       req = (request_h)malloc(sizeof(struct request_s));
+       if (req == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       g_get_current_time(&req->start);
+       req->timer = 0;
+       req->clifd = -1;
+       req->pid = pid;
+       req->t_pid = 0;
+       req->uid = getuid();
+       req->t_uid = uid;
+       req->cmd = cmd;
+       req->len = 0;
+       req->opt = AUL_SOCK_NONE;
+       req->kb = bundle_dup(kb);
+
+       return req;
+}
+
+void _request_free_local(request_h req)
+{
+       if (req == NULL)
+               return;
+
+       if (req->kb)
+               bundle_free(req->kb);
+
+       free(req);
+}
+
+int _request_get_cmd(request_h req)
+{
+       return req->cmd;
+}
+
+int _request_remove_fd(request_h req)
+{
+       int r = req->clifd;
+
+       req->clifd = 0;
+
+       return r;
+}
+
+uid_t _request_get_target_uid(request_h req)
+{
+       return req->t_uid;
+}
+
+uid_t _request_get_uid(request_h req)
+{
+       return req->uid;
+}
+
+int _request_send_raw(request_h req, int cmd, unsigned char *data, int len)
+{
+       return aul_sock_send_raw_with_fd(_request_remove_fd(req), cmd, data,
+                       len, AUL_SOCK_NOREPLY);
+}
+
+int _request_send_result(request_h req, int res)
+{
+       if (req->clifd && (req->opt & AUL_SOCK_NOREPLY))
+               close(_request_remove_fd(req));
+       else if (req->clifd)
+               _send_result_to_client(_request_remove_fd(req), res);
+
+       return 0;
+}
+
+static void __free_socket_pair(gpointer data)
+{
+       int *handles = (int *)data;
+
+       if (handles[0] > 0)
+               close(handles[0]);
+       if (handles[1] > 0)
+               close(handles[1]);
+       free(handles);
+}
+
+int _request_init(void)
+{
+       _D("request init");
+       __dc_socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+                       free, __free_socket_pair);
+       if (__dc_socket_pair_hash == NULL) {
+               _E("Failed to create socket pair table");
+               _request_fini();
+               return -1;
+       }
+
+       pending_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                       NULL, __free_pending_item);
+       if (pending_table == NULL) {
+               _E("Failed to create pending table");
+               _request_fini();
+               return -1;
+       }
+
+       amd_fd = _create_sock_activation();
+       if (amd_fd == -1) {
+               _D("Create server socket without socket activation");
+               amd_fd = _create_server_sock();
+               if (amd_fd == -1) {
+                       _E("Create server socket failed.");
+                       _request_fini();
+                       return -1;
+               }
+       }
+
+       amd_io = g_io_channel_unix_new(amd_fd);
+       if (amd_io == NULL) {
+               _E("Failed to create gio channel");
+               _request_fini();
+               return -1;
+       }
+
+       amd_wid = g_io_add_watch(amd_io, G_IO_IN, __request_handler, NULL);
+       if (amd_wid == 0) {
+               _E("Failed to add gio watch");
+               _request_fini();
+               return -1;
+       }
+
+       return 0;
+}
+
+void _request_fini(void)
+{
+       _D("request fini");
+       if (amd_wid) {
+               g_source_remove(amd_wid);
+               amd_wid = 0;
+       }
+
+       if (amd_io) {
+               g_io_channel_unref(amd_io);
+               amd_io = NULL;
+       }
+
+       if (amd_fd > 0) {
+               close(amd_fd);
+               amd_fd = 0;
+       }
+
+       if (pending_table) {
+               g_hash_table_destroy(pending_table);
+               pending_table = NULL;
+       }
+
+       if (__dc_socket_pair_hash) {
+               g_hash_table_destroy(__dc_socket_pair_hash);
+               __dc_socket_pair_hash = NULL;
+       }
+}
diff --git a/src/amd_rua.c b/src/amd_rua.c
new file mode 100644 (file)
index 0000000..58a729b
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <aul.h>
+#include <rua_internal.h>
+
+#include "amd_util.h"
+#include "amd_rua.h"
+#include "amd_app_status.h"
+#include "amd_app_group.h"
+#include "amd_inotify.h"
+
+#define PATH_RUN       "/run"
+#define FILE_E_IMG     ".e-img"
+#define PATH_RUN_E_IMG PATH_RUN "/" FILE_E_IMG
+
+struct rua_info_s {
+       uid_t uid;
+       char *appid;
+       char *app_path;
+       char *instance_id;
+       char *image_path;
+       unsigned int surf;
+};
+
+static int __dir_wd;
+static int __img_wd;
+static GHashTable *__rua_tbl;
+
+static void __destroy_rua_info(gpointer data)
+{
+       struct rua_info_s *info = (struct rua_info_s *)data;
+
+       if (info == NULL)
+               return;
+
+       if (info->image_path) {
+               unlink(info->image_path); /* Delete image file */
+               free(info->image_path);
+       }
+
+       if (info->instance_id)
+               free(info->instance_id);
+
+       if (info->app_path)
+               free(info->app_path);
+
+       if (info->appid)
+               free(info->appid);
+
+       free(info);
+}
+
+static struct rua_info_s *__create_rua_info(const char *appid,
+               const char *app_path, const char *instance_id,
+               uid_t uid)
+{
+       struct rua_info_s *info;
+
+       info = calloc(1, sizeof(struct rua_info_s));
+       if (info == NULL) {
+               _E("Out of memory");
+               return NULL;
+       }
+
+       info->appid = strdup(appid);
+       if (info->appid == NULL) {
+               _E("Out of memory");
+               __destroy_rua_info(info);
+               return NULL;
+       }
+
+       info->app_path = strdup(app_path);
+       if (info->app_path == NULL) {
+               _E("Out of memory");
+               __destroy_rua_info(info);
+               return NULL;
+       }
+
+       if (instance_id) {
+               info->instance_id = strdup(instance_id);
+               if (info->instance_id == NULL) {
+                       _E("Out of memory");
+                       __destroy_rua_info(info);
+                       return NULL;
+               }
+       }
+
+       info->uid = uid;
+
+       return info;
+}
+
+int _rua_update_screen_info(int pid, unsigned int surf)
+{
+       struct rua_info_s *info;
+       int leader_pid;
+
+       if (__rua_tbl == NULL)
+               return -1;
+
+       leader_pid = _app_group_get_leader_pid(pid);
+       if (leader_pid > 0)
+               pid = leader_pid;
+
+       info = (struct rua_info_s *)g_hash_table_lookup(__rua_tbl,
+                       GINT_TO_POINTER(pid));
+       if (info == NULL)
+               return -1;
+
+       info->surf = surf;
+
+       return 0;
+}
+
+int _rua_add_info(int pid, bool new_instance)
+{
+       struct rua_info_s *info;
+       app_status_h app_status;
+       const char *appid;
+       const char *app_path;
+       const char *instance_id;
+       uid_t uid;
+
+       if (__rua_tbl == NULL)
+               return 0;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return -1;
+
+       appid = _app_status_get_appid(app_status);
+       app_path = _app_status_get_app_path(app_status);
+       uid = _app_status_get_uid(app_status);
+
+       if (new_instance)
+               instance_id = _app_status_get_instance_id(app_status);
+       else
+               instance_id = NULL;
+
+       info = __create_rua_info(appid, app_path, instance_id, uid);
+       if (info == NULL)
+               return -1;
+
+       if (g_hash_table_contains(__rua_tbl, GINT_TO_POINTER(pid)))
+               g_hash_table_replace(__rua_tbl, GINT_TO_POINTER(pid), info);
+       else
+               g_hash_table_insert(__rua_tbl, GINT_TO_POINTER(pid), info);
+
+       return 0;
+}
+
+static gboolean __foreach_remove_by_uid(gpointer key, gpointer value,
+               gpointer data)
+{
+       struct rua_info_s *info = (struct rua_info_s *)value;
+       uid_t uid = GPOINTER_TO_UINT(data);
+
+       if (info->uid == uid)
+               return TRUE;
+
+       return FALSE;
+}
+
+static gboolean __foreach_remove_by_appid(gpointer key, gpointer value,
+               gpointer data)
+{
+       struct rua_info_s *info = (struct rua_info_s *)value;
+       const char *appid = (const char *)data;
+
+       if (strcmp(info->appid, appid) == 0)
+               return TRUE;
+
+       return FALSE;
+}
+
+static gboolean __foreach_remove_by_app_path(gpointer key, gpointer value,
+               gpointer data)
+{
+       struct rua_info_s *info = (struct rua_info_s *)value;
+       const char *app_path = (const char *)data;
+
+       if (strcmp(info->app_path, app_path) == 0)
+               return TRUE;
+
+       return FALSE;
+}
+
+static gboolean __foreach_remove_by_instance_id(gpointer key, gpointer value,
+               gpointer data)
+{
+       struct rua_info_s *info = (struct rua_info_s *)value;
+       const char *instance_id = (const char *)data;
+
+       if (info->instance_id && strcmp(info->instance_id, instance_id) == 0)
+               return TRUE;
+
+       return FALSE;
+}
+
+const char *_rua_get_image_path(int pid)
+{
+       struct rua_info_s *info;
+
+       if (__rua_tbl == NULL)
+               return NULL;
+
+       info = (struct rua_info_s *)g_hash_table_lookup(__rua_tbl,
+                       GINT_TO_POINTER(pid));
+       if (info == NULL)
+               return NULL;
+
+       return info->image_path;
+}
+
+int _rua_delete_info(bundle *b, uid_t uid)
+{
+       char *appid = NULL;
+       char *app_path = NULL;
+       char *instance_id = NULL;
+
+       if (b) {
+               bundle_get_str(b, AUL_K_RUA_PKGNAME, &appid);
+               bundle_get_str(b, AUL_K_RUA_APPPATH, &app_path);
+               bundle_get_str(b, AUL_K_RUA_INSTANCE_ID, &instance_id);
+       }
+
+       if (appid) {
+               g_hash_table_foreach_remove(__rua_tbl,
+                               __foreach_remove_by_appid, appid);
+       } else if (app_path) {
+               g_hash_table_foreach_remove(__rua_tbl,
+                               __foreach_remove_by_app_path, app_path);
+       } else if (instance_id) {
+               g_hash_table_foreach_remove(__rua_tbl,
+                               __foreach_remove_by_instance_id, instance_id);
+       } else {
+               g_hash_table_foreach_remove(__rua_tbl,
+                               __foreach_remove_by_uid, GUINT_TO_POINTER(uid));
+       }
+
+       return 0;
+}
+
+static void __update_img_file(const char *img)
+{
+       int r;
+       int pid = -1;
+       unsigned int surf = 0;
+       int num = -1;
+       char buf[PATH_MAX];
+       struct rua_info_s *info;
+       int leader_pid;
+
+       sscanf(img, "win_%d_%u-%d.png", &pid, &surf, &num);
+       if (pid <= 0)
+               return;
+
+       snprintf(buf, sizeof(buf), "%s/%s", PATH_RUN_E_IMG, img);
+
+       leader_pid = _app_group_get_leader_pid(pid);
+       if (leader_pid > 0)
+               pid = leader_pid;
+
+       info = (struct rua_info_s *)g_hash_table_lookup(__rua_tbl,
+                       GINT_TO_POINTER(pid));
+       if (info == NULL || (info->surf != 0 && info->surf != surf)) {
+               unlink(buf);
+               return;
+       }
+
+       if (info->image_path) {
+               if (strcmp(info->image_path, buf) == 0)
+                       return;
+
+               unlink(info->image_path);
+               free(info->image_path);
+       }
+
+       r = rua_usr_db_update_image(info->appid, info->instance_id,
+                       buf, info->uid);
+       if (r < 0)
+               _W("Failed to update image path - appid(%s)", info->appid);
+
+       info->image_path = strdup(buf);
+       if (info->image_path == NULL)
+               _E("Out of memory");
+
+       if (info->surf == 0)
+               info->surf = surf;
+}
+
+static void __find_imgs(void)
+{
+       DIR *dp;
+       struct dirent *dentry = NULL;
+       char buf[PATH_MAX];
+       struct stat statbuf;
+       int r;
+
+       dp = opendir(PATH_RUN_E_IMG);
+       if (dp == NULL)
+               return;
+
+       while ((dentry = readdir(dp))) {
+               if (!strcmp(dentry->d_name, ".") ||
+                               !strcmp(dentry->d_name, ".."))
+                       continue;
+
+               snprintf(buf, sizeof(buf), "%s/%s",
+                               PATH_RUN_E_IMG, dentry->d_name);
+               r = stat(buf, &statbuf);
+               if (r == 0) {
+                       if (S_ISREG(statbuf.st_mode))
+                               __update_img_file(buf);
+               }
+       }
+       closedir(dp);
+}
+
+static bool __img_monitor_cb(const char *event_name, void *data)
+{
+       if (event_name) {
+               __update_img_file(event_name);
+               _D("%s is created", event_name);
+       }
+
+       return true;
+}
+
+static bool __dir_monitor_cb(const char *event_name, void *data)
+{
+       if (event_name == NULL)
+               return true;
+
+       if (strcmp(event_name, FILE_E_IMG) == 0) {
+               __img_wd = _inotify_add_watch(PATH_RUN_E_IMG, IN_CREATE,
+                               __img_monitor_cb, NULL);
+               if (__img_wd < 0)
+                       _E("Failed to add inotify watch");
+               else
+                       __find_imgs();
+
+               __dir_wd = 0;
+               return false;
+       }
+
+       return true;
+}
+
+int _rua_usr_init(uid_t uid)
+{
+       int r;
+
+       r = rua_usr_db_delete_history(NULL, uid);
+       if (r < 0) {
+               _E("Failed to delete rua history - uid(%u)", uid);
+               return -1;
+       }
+
+       return 0;
+}
+
+void _rua_usr_fini(uid_t uid)
+{
+       if (__rua_tbl == NULL)
+               return;
+
+       g_hash_table_foreach_remove(__rua_tbl,
+                       __foreach_remove_by_uid, GUINT_TO_POINTER(uid));
+}
+
+int _rua_init(void)
+{
+       _D("[RUA] init");
+
+       if (access(PATH_RUN_E_IMG, F_OK) == 0) {
+               __img_wd = _inotify_add_watch(PATH_RUN_E_IMG, IN_CREATE,
+                               __img_monitor_cb, NULL);
+               if (__img_wd < 0)
+                       return -1;
+
+               __find_imgs();
+       } else {
+               __dir_wd = _inotify_add_watch(PATH_RUN, IN_CREATE,
+                               __dir_monitor_cb, NULL);
+               if (__dir_wd < 0)
+                       return -1;
+       }
+
+       __rua_tbl = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                       NULL, __destroy_rua_info);
+       if (__rua_tbl == NULL) {
+               _E("Failed to create rua table");
+               return -1;
+       }
+
+       return 0;
+}
+
+void _rua_fini(void)
+{
+       _D("[RUA] finish");
+
+       if (__rua_tbl) {
+               g_hash_table_destroy(__rua_tbl);
+               __rua_tbl = NULL;
+       }
+
+       if (__dir_wd > 0)
+               _inotify_rm_watch(__dir_wd);
+       if (__img_wd > 0)
+               _inotify_rm_watch(__img_wd);
+}
diff --git a/src/amd_screen_connector.c b/src/amd_screen_connector.c
new file mode 100644 (file)
index 0000000..3aa7ba9
--- /dev/null
@@ -0,0 +1,956 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <bundle_internal.h>
+#include <aul.h>
+#include <aul_sock.h>
+#include <aul_screen_connector.h>
+
+#include "amd_util.h"
+#include "amd_app_group.h"
+#include "amd_app_status.h"
+#include "amd_app_com.h"
+#include "amd_suspend.h"
+#include "amd_screen_connector.h"
+
+#define SUSPEND_INTERVAL 5 /* sec */
+
+struct app_screen_s {
+       char *appid;
+       char *instance_id;
+       int pid;
+       uid_t uid;
+       unsigned int surf;
+       int screen_type;
+       int caller_pid;
+       GList *viewer_list;
+};
+
+struct viewer_info_s {
+       int pid;
+       int screen_type;
+       bool priv;
+       unsigned int ref;
+       aul_screen_status_e status;
+       GList *watch_list;
+};
+
+struct user_info_s {
+       uid_t uid;
+       GList *screen_viewer_list;
+       GList *app_screen_list;
+};
+
+static GHashTable *user_table;
+
+static struct app_screen_s *__create_app_screen(int pid, uid_t uid,
+               const char *appid, unsigned int surf, const char *instance_id,
+               int screen_type, int caller_pid)
+{
+       struct app_screen_s *app_screen;
+
+       app_screen = calloc(1, sizeof(struct app_screen_s));
+       if (app_screen == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       app_screen->appid = strdup(appid);
+       if (app_screen->appid == NULL) {
+               _E("out of memory");
+               free(app_screen);
+               return NULL;
+       }
+
+       app_screen->instance_id = strdup(instance_id);
+       if (app_screen->instance_id == NULL) {
+               _E("out of memory");
+               free(app_screen->appid);
+               free(app_screen);
+               return NULL;
+       }
+
+       app_screen->pid = pid;
+       app_screen->uid = uid;
+       app_screen->surf = surf;
+       app_screen->screen_type = screen_type;
+       app_screen->caller_pid = caller_pid;
+
+       return app_screen;
+}
+
+static void __destroy_app_screen(gpointer data)
+{
+       struct app_screen_s *app_screen = (struct app_screen_s *)data;
+       struct viewer_info_s *viewer_info;
+       GList *iter;
+
+       if (app_screen == NULL)
+               return;
+
+       if (app_screen->viewer_list) {
+               iter = app_screen->viewer_list;
+               while (iter) {
+                       viewer_info = (struct viewer_info_s *)iter->data;
+                       viewer_info->watch_list = g_list_remove(
+                                       viewer_info->watch_list, app_screen);
+                       iter = g_list_next(iter);
+               }
+               g_list_free(app_screen->viewer_list);
+       }
+
+       if (app_screen->instance_id)
+               free(app_screen->instance_id);
+       if (app_screen->appid)
+               free(app_screen->appid);
+       free(app_screen);
+}
+
+static gint __compare_instance_id(gconstpointer a, gconstpointer b)
+{
+       struct app_screen_s *app_screen = (struct app_screen_s *)a;
+       const char *instance_id = (const char *)b;
+
+       if (app_screen == NULL || instance_id == NULL)
+               return -1;
+
+       if (!strcmp(app_screen->instance_id, instance_id))
+               return 0;
+
+       return -1;
+}
+
+static void __destroy_viewer_info(struct viewer_info_s *viewer_info)
+{
+       struct app_screen_s *app_screen;
+       GList *iter;
+
+       if (viewer_info == NULL)
+               return;
+
+       if (viewer_info->watch_list) {
+               iter = viewer_info->watch_list;
+               while (iter) {
+                       app_screen = (struct app_screen_s *)iter->data;
+                       app_screen->viewer_list = g_list_remove(
+                                       app_screen->viewer_list, viewer_info);
+                       iter = g_list_next(iter);
+               }
+               g_list_free(viewer_info->watch_list);
+       }
+
+       free(viewer_info);
+}
+
+static struct viewer_info_s *__create_viewer_info(int pid, int screen_type,
+               bool priv, unsigned int ref)
+{
+       struct viewer_info_s *viewer_info;
+
+       viewer_info = calloc(1, sizeof(struct viewer_info_s));
+       if (viewer_info == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       viewer_info->pid = pid;
+       viewer_info->screen_type = screen_type;
+       viewer_info->priv = priv;
+       viewer_info->ref = ref;
+
+       return viewer_info;
+}
+
+static void __destroy_user_info(gpointer data)
+{
+       struct user_info_s *user_info = (struct user_info_s *)data;
+
+       if (user_info == NULL)
+               return;
+
+       if (user_info->app_screen_list) {
+               g_list_free_full(user_info->app_screen_list,
+                               __destroy_app_screen);
+       }
+       if (user_info->screen_viewer_list)
+               g_list_free_full(user_info->screen_viewer_list, free);
+       free(user_info);
+}
+
+static struct user_info_s *__create_user_info(uid_t uid)
+{
+       struct user_info_s *user_info;
+
+       user_info = malloc(sizeof(struct user_info_s));
+       if (user_info == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       user_info->uid = uid;
+       user_info->screen_viewer_list = NULL;
+       user_info->app_screen_list = NULL;
+
+       return user_info;
+}
+
+static bundle *__create_bundle(struct app_screen_s *app_screen,
+               const char *event)
+{
+       bundle *b;
+
+       b = bundle_create();
+       if (b == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       bundle_add_str(b, "__AUL_SC_EVENT__", event);
+       bundle_add_str(b, "__AUL_SC_APPID__", app_screen->appid);
+       bundle_add_byte(b, "__AUL_SC_PID__", &app_screen->pid, sizeof(int));
+       bundle_add_byte(b, "__AUL_SC_SURFACE__",
+                       &app_screen->surf, sizeof(unsigned int));
+       bundle_add_str(b, "__AUL_SC_INSTANCE_ID__", app_screen->instance_id);
+
+       return b;
+}
+
+static void __send_app_screen_event(struct viewer_info_s *viewer_info,
+               struct app_screen_s *app_screen, const char *event)
+{
+       bundle *b;
+       char endpoint[128];
+
+       b = __create_bundle(app_screen, event);
+       if (b == NULL) {
+               _E("out of memory");
+               return;
+       }
+
+       snprintf(endpoint, sizeof(endpoint), "app_screen_event:%u:%d",
+                       viewer_info->ref, viewer_info->pid);
+       _app_com_send(endpoint, app_screen->pid, b, app_screen->uid);
+       bundle_free(b);
+}
+
+static void __send_app_screen_added(gpointer data, gpointer user_data)
+{
+       struct viewer_info_s *viewer_info = (struct viewer_info_s *)data;
+       struct app_screen_s *app_screen = (struct app_screen_s *)user_data;
+
+       if (viewer_info->pid == app_screen->pid)
+               return;
+       if (viewer_info->priv && viewer_info->pid != app_screen->caller_pid)
+               return;
+       if (!(viewer_info->screen_type & app_screen->screen_type))
+               return;
+       __send_app_screen_event(viewer_info, app_screen, "add_screen");
+}
+
+static void __send_app_screen_removed(gpointer data, gpointer user_data)
+{
+       struct viewer_info_s *viewer_info = (struct viewer_info_s *)data;
+       struct app_screen_s *app_screen = (struct app_screen_s *)user_data;
+
+       if (viewer_info->pid == app_screen->pid)
+               return;
+       if (viewer_info->priv && viewer_info->pid != app_screen->caller_pid)
+               return;
+       if (!(viewer_info->screen_type & app_screen->screen_type))
+               return;
+       __send_app_screen_event(viewer_info, app_screen, "remove_screen");
+}
+
+static void __send_app_screen_updated(gpointer data, gpointer user_data)
+{
+       struct viewer_info_s *viewer_info = (struct viewer_info_s *)data;
+       struct app_screen_s *app_screen = (struct app_screen_s *)user_data;
+
+       if (viewer_info->pid == app_screen->pid)
+               return;
+       if (viewer_info->priv && viewer_info->pid != app_screen->caller_pid)
+               return;
+       if (!(viewer_info->screen_type & app_screen->screen_type))
+               return;
+       __send_app_screen_event(viewer_info, app_screen, "update_screen");
+}
+
+static gint __compare_app_screen_instance_id(gconstpointer a, gconstpointer b)
+{
+       struct app_screen_s *app_screen = (struct app_screen_s *)a;
+       const char *instance_id = (const char *)b;
+
+       if (strcmp(app_screen->instance_id, instance_id) == 0)
+               return 0;
+
+       return -1;
+}
+
+unsigned int _screen_connector_get_surface_id(const char *instance_id,
+               uid_t uid)
+{
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       GList *found;
+
+       if (instance_id == NULL)
+               return 0;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return 0;
+
+       found = g_list_find_custom(user_info->app_screen_list,
+                       instance_id, __compare_app_screen_instance_id);
+       if (found) {
+               app_screen = (struct app_screen_s *)found->data;
+               return app_screen->surf;
+       }
+
+       return 0;
+}
+
+static int __get_screen_type(int app_type)
+{
+       switch (app_type) {
+       case AT_UI_APP:
+               return AUL_SCREEN_TYPE_UI;
+       case AT_WIDGET_APP:
+               return AUL_SCREEN_TYPE_WIDGET;
+       case AT_WATCH_APP:
+               return AUL_SCREEN_TYPE_WATCH;
+       default:
+               return -1;
+       }
+}
+
+static int __get_pid_by_surf(int pid, unsigned int surf)
+{
+       int *pids = NULL;
+       int cnt = 0;
+       int i;
+       unsigned int wid;
+
+       _app_group_get_group_pids(pid, &cnt, &pids);
+       for (i = 0; i < cnt; ++i) {
+               wid = (unsigned int)_app_group_get_window(pids[i]);
+               if (wid == surf) {
+                       _D("pid(%d), surf(%u)", pids[i], surf);
+                       pid = pids[i];
+               }
+       }
+       free(pids);
+
+       return pid;
+}
+
+static gboolean __suspend_timer(gpointer data)
+{
+       int pid = GPOINTER_TO_INT(data);
+       int ret;
+
+       if (pid < 1)
+               return FALSE;
+
+       ret = _suspend_update_status(pid, SUSPEND_STATUS_INCLUDE);
+       _D("pid(%d), result(%d)", pid, ret);
+
+       return FALSE;
+}
+
+static gint __compare_app_screen_surf(gconstpointer a, gconstpointer b)
+{
+       struct app_screen_s *app_screen = (struct app_screen_s *)a;
+       unsigned int surf = GPOINTER_TO_UINT(b);
+
+       if (app_screen->surf == surf)
+               return 0;
+
+       return -1;
+}
+
+const char *_screen_connector_get_appid_by_surface_id(unsigned int surf,
+               uid_t uid)
+{
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       GList *found;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return NULL;
+
+       found = g_list_find_custom(user_info->app_screen_list,
+                       GUINT_TO_POINTER(surf), __compare_app_screen_surf);
+       if (found) {
+               app_screen = (struct app_screen_s *)found->data;
+               return app_screen->appid;
+       }
+
+       return NULL;
+}
+
+const char *_screen_connector_get_instance_id_by_surface_id(unsigned int surf,
+               uid_t uid)
+{
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       GList *found;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return NULL;
+
+       found = g_list_find_custom(user_info->app_screen_list,
+                       GUINT_TO_POINTER(surf), __compare_app_screen_surf);
+       if (found) {
+               app_screen = (struct app_screen_s *)found->data;
+               return app_screen->instance_id;
+       }
+
+       return NULL;
+}
+
+/* TODO: The provider_appid should be provider_instance_id. */
+static int __send_viewer_visibility_to_provider(const char *provider_appid,
+               aul_screen_status_e status, int viewer_pid, uid_t viewer_uid)
+{
+       bundle *b;
+
+       b = bundle_create();
+       if (b == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       bundle_add_byte(b, "__AUL_SC_VIEWER_STATUS__",
+                       &status, sizeof(aul_screen_status_e));
+       _app_com_send(provider_appid, viewer_pid, b, viewer_uid);
+       bundle_free(b);
+       _D("send viewer status to %s(%d)", provider_appid, status);
+
+       return 0;
+}
+
+static gint __compare_viewer_pid(gconstpointer a, gconstpointer b)
+{
+       struct viewer_info_s *viewer_info = (struct viewer_info_s *)a;
+       int pid = GPOINTER_TO_INT(b);
+
+       if (viewer_info->pid == pid)
+               return 0;
+
+       return -1;
+}
+
+int _screen_connector_update_screen_viewer_status(int pid, int status,
+               unsigned int surf, uid_t uid)
+{
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       struct viewer_info_s *viewer_info;
+       bool send_pause = true;
+       GList *found;
+       GList *iter;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return -1;
+
+       found = g_list_find_custom(user_info->screen_viewer_list,
+                       GINT_TO_POINTER(pid), __compare_viewer_pid);
+       if (found == NULL)
+               return -1;
+
+       viewer_info = (struct viewer_info_s *)found->data;
+       viewer_info->status = status;
+
+       found = g_list_find_custom(user_info->app_screen_list,
+                       GUINT_TO_POINTER(surf), __compare_app_screen_surf);
+       if (found == NULL)
+               return -1;
+
+       app_screen = (struct app_screen_s *)found->data;
+       found = g_list_find(app_screen->viewer_list, viewer_info);
+       if (!found) {
+               app_screen->viewer_list = g_list_append(app_screen->viewer_list,
+                               viewer_info);
+       }
+
+       found = g_list_find(viewer_info->watch_list, app_screen);
+       if (!found) {
+               viewer_info->watch_list = g_list_append(viewer_info->watch_list,
+                               app_screen);
+       }
+
+       if (status == AUL_SCREEN_STATUS_PAUSE) {
+               iter = app_screen->viewer_list;
+               while (iter) {
+                       viewer_info = (struct viewer_info_s *)iter->data;
+                       if (viewer_info->status != AUL_SCREEN_STATUS_PAUSE) {
+                               /*
+                                * Every veiwer must be paused to send
+                                * viewer pause event to provider
+                                */
+                               send_pause = false;
+                               break;
+                       }
+                       iter = g_list_next(iter);
+               }
+               if (send_pause) {
+                       __send_viewer_visibility_to_provider(app_screen->appid,
+                                       status, pid, uid);
+               }
+       } else if (status == AUL_SCREEN_STATUS_RESUME) {
+               __send_viewer_visibility_to_provider(app_screen->appid, status,
+                               pid, uid);
+       } else {
+               _W("Unknown status(%d)", status);
+       }
+
+       return 0;
+}
+
+int _screen_connector_send_update_request(const char *appid,
+               const char *instance_id, uid_t uid)
+{
+       app_status_h app_status;
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       int dummy = 0;
+       int pid;
+       int ret;
+       GList *found;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return -1;
+
+       if (instance_id) {
+               app_status = _app_status_find_by_instance_id(appid,
+                               instance_id, uid);
+       } else {
+               app_status = _app_status_find_by_appid(appid, uid);
+       }
+       if (app_status == NULL)
+               return -1;
+       if (_app_status_get_status(app_status) == STATUS_DYING)
+               return -1;
+       if (_app_status_get_app_type(app_status) != AT_UI_APP)
+               return -1;
+       if (_app_status_is_home_app(app_status))
+               return -1;
+       if (instance_id == NULL) {
+               instance_id = _app_status_get_instance_id(app_status);
+               if (instance_id == NULL)
+                       return -1;
+       }
+
+       found = g_list_find_custom(user_info->app_screen_list, instance_id,
+                       __compare_instance_id);
+       if (found == NULL)
+               return -1;
+
+       app_screen = (struct app_screen_s *)found->data;
+       pid = __get_pid_by_surf(app_screen->pid, app_screen->surf);
+       ret = _suspend_update_status(pid, SUSPEND_STATUS_EXCLUDE);
+       if (ret < 0)
+               return -1;
+
+       ret = aul_sock_send_raw(pid, uid, APP_UPDATE_REQUESTED,
+                       (unsigned char *)&dummy, 0, AUL_SOCK_NOREPLY);
+       if (ret < 0) {
+               _E("Failed to send the update request");
+               _suspend_update_status(pid, SUSPEND_STATUS_INCLUDE);
+               return -1;
+       }
+       g_timeout_add_seconds(SUSPEND_INTERVAL, __suspend_timer,
+                       GINT_TO_POINTER(pid));
+       _D("pid(%d), uid(%d)", pid, uid);
+
+       return 0;
+}
+
+int _screen_connector_add_app_screen(int pid, unsigned int surf,
+               const char *instance_id, uid_t uid)
+{
+       app_status_h app_status;
+       const char *appid;
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       int caller_pid;
+       int leader_pid;
+       int app_type;
+       int screen_type;
+       GList *found;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return -1;
+
+       leader_pid = _app_group_get_leader_pid(pid);
+       if (leader_pid > 0)
+               pid = leader_pid;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               _W("Failed to find app status info - pid(%d), uid(%d)",
+                               pid, uid);
+               return -1;
+       }
+
+       if (_app_status_is_home_app(app_status))
+               return 0;
+
+       appid = _app_status_get_appid(app_status);
+       if (instance_id == NULL) {
+               instance_id = _app_status_get_instance_id(app_status);
+               if (instance_id == NULL)
+                       return -1;
+       }
+
+       found = g_list_find_custom(user_info->app_screen_list, instance_id,
+                       __compare_instance_id);
+       if (found) {
+               app_screen = (struct app_screen_s *)found->data;
+               if (app_screen->surf == surf) {
+                       _D("Already exists");
+                       return 0;
+               }
+
+               app_screen->surf = surf;
+               g_list_foreach(user_info->screen_viewer_list,
+                               __send_app_screen_updated, app_screen);
+               return 0;
+       }
+
+       caller_pid = _app_status_get_org_caller_pid(app_status);
+       app_type = _app_status_get_app_type(app_status);
+       screen_type = __get_screen_type(app_type);
+       app_screen = __create_app_screen(pid, uid, appid, surf, instance_id,
+                       screen_type, caller_pid);
+       if (app_screen == NULL)
+               return -1;
+
+       user_info->app_screen_list = g_list_append(user_info->app_screen_list,
+                       app_screen);
+       g_list_foreach(user_info->screen_viewer_list,
+                       __send_app_screen_added, app_screen);
+       _D("pid(%d), appid(%s), surf(%d), uid(%d)", pid, appid, surf, uid);
+
+       return 0;
+}
+
+int _screen_connector_remove_app_screen(int pid, const char *instance_id,
+               uid_t uid)
+{
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       app_status_h app_status;
+       int leader_pid;
+       GList *found;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return -1;
+
+       leader_pid = _app_group_get_leader_pid(pid);
+       if (leader_pid > 0)
+               pid = leader_pid;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               _W("Failed to find app status info - pid(%d), uid(%d)",
+                               pid, uid);
+               return -1;
+       }
+
+       if (_app_status_is_home_app(app_status))
+               return 0;
+
+       if (instance_id == NULL) {
+               instance_id = _app_status_get_instance_id(app_status);
+               if (instance_id == NULL)
+                       return -1;
+       }
+
+       found = g_list_find_custom(user_info->app_screen_list, instance_id,
+                       __compare_instance_id);
+       if (found == NULL)
+               return -1;
+
+       app_screen = (struct app_screen_s *)found->data;
+       g_list_foreach(user_info->screen_viewer_list,
+                       __send_app_screen_removed, app_screen);
+       user_info->app_screen_list = g_list_remove(user_info->app_screen_list,
+                       app_screen);
+       __destroy_app_screen(app_screen);
+       _D("pid(%d), instance_id(%s)", pid, instance_id);
+
+       return 0;
+}
+
+static gint __compare_viewers(gconstpointer a, gconstpointer b)
+{
+       struct viewer_info_s *viewer_a = (struct viewer_info_s *)a;
+       struct viewer_info_s *viewer_b = (struct viewer_info_s *)b;
+
+       if (viewer_a->pid == viewer_b->pid &&
+                       viewer_a->screen_type == viewer_b->screen_type &&
+                       viewer_a->priv == viewer_b->priv &&
+                       viewer_a->ref == viewer_b->ref)
+               return 0;
+
+       return -1;
+}
+
+int _screen_connector_update_app_screen(int pid, unsigned int surf, uid_t uid)
+{
+       app_status_h app_status;
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       const char *appid;
+       const char *instance_id;
+       int leader_pid;
+       GList *found;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return -1;
+
+       leader_pid = _app_group_get_leader_pid(pid);
+       if (leader_pid > 0)
+               pid = leader_pid;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               _W("Failed to find app status info - pid(%d), uid(%d)",
+                               pid, uid);
+               return -1;
+       }
+
+       if (_app_status_is_home_app(app_status))
+               return 0;
+
+       appid = _app_status_get_appid(app_status);
+       instance_id = _app_status_get_instance_id(app_status);
+       if (instance_id == NULL)
+               return -1;
+
+       found = g_list_find_custom(user_info->app_screen_list, instance_id,
+                       __compare_instance_id);
+       if (found == NULL)
+               return -1;
+
+       app_screen = (struct app_screen_s *)found->data;
+       if (app_screen->surf == surf)
+               return 0;
+
+       app_screen->surf = surf;
+       g_list_foreach(user_info->screen_viewer_list,
+                       __send_app_screen_updated, app_screen);
+       _D("pid(%d), appid(%s), surf(%d), uid(%d)", pid, appid, surf, uid);
+
+       return 0;
+}
+
+int _screen_connector_remove_app_screen_v2(int pid, uid_t uid)
+{
+       struct user_info_s *user_info;
+       struct app_screen_s *app_screen;
+       GList *iter;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL)
+               return -1;
+
+       iter = g_list_first(user_info->app_screen_list);
+       while (iter) {
+               app_screen = (struct app_screen_s *)iter->data;
+               iter = g_list_next(iter);
+               if (app_screen && app_screen->pid == pid) {
+                       _D("pid(%d), surf(%d)", pid, app_screen->surf);
+                       g_list_foreach(user_info->screen_viewer_list,
+                                       __send_app_screen_removed, app_screen);
+                       user_info->app_screen_list = g_list_remove(
+                                       user_info->app_screen_list,
+                                       app_screen);
+                       __destroy_app_screen(app_screen);
+               }
+       }
+
+       return 0;
+}
+
+static void __foreach_app_screen_list(gpointer data, gpointer user_data)
+{
+       __send_app_screen_added(user_data, data);
+}
+
+int _screen_connector_add_screen_viewer(int pid, int screen_type,
+               bool priv, unsigned int ref, uid_t uid)
+{
+       app_status_h app_status;
+       struct user_info_s *user_info;
+       struct viewer_info_s *viewer_info;
+       GList *list;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL) {
+               _W("Failed to find app status info - pid(%d)", pid);
+               return -1;
+       }
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL) {
+               _W("user info is empty");
+               return -1;
+       }
+
+       viewer_info = __create_viewer_info(pid, screen_type, priv, ref);
+       if (viewer_info == NULL)
+               return -1;
+
+       list = g_list_find_custom(user_info->screen_viewer_list, viewer_info,
+                       __compare_viewers);
+       if (list) {
+               _D("Already exists");
+               __destroy_viewer_info(viewer_info);
+               return 0;
+       }
+
+       user_info->screen_viewer_list = g_list_append(
+                       user_info->screen_viewer_list, viewer_info);
+
+       g_list_foreach(user_info->app_screen_list,
+                       __foreach_app_screen_list, viewer_info);
+       _D("pid(%d), screen_type(%d), private(%d), ref(%u), uid(%d)",
+                       pid, screen_type, priv, ref, uid);
+
+       return 0;
+}
+
+int _screen_connector_remove_screen_viewer(int pid, int screen_type,
+               bool priv, unsigned int ref, uid_t uid)
+{
+       struct user_info_s *user_info;
+       struct viewer_info_s *viewer_info;
+       GList *iter;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL) {
+               _W("user info is empty");
+               return -1;
+       }
+
+       iter = g_list_first(user_info->screen_viewer_list);
+       while (iter) {
+               viewer_info = (struct viewer_info_s *)iter->data;
+               iter = g_list_next(iter);
+               if (viewer_info->pid == pid &&
+                               viewer_info->screen_type == screen_type &&
+                               viewer_info->priv == priv &&
+                               viewer_info->ref == ref) {
+                       user_info->screen_viewer_list = g_list_remove(
+                                       user_info->screen_viewer_list,
+                                       viewer_info);
+                       __destroy_viewer_info(viewer_info);
+               }
+       }
+
+       _D("pid(%d), screen_type(%d), private(%d), ref(%u) uid(%d)",
+                       pid, screen_type, priv, ref, uid);
+
+       return 0;
+}
+
+int _screen_connector_remove_screen_viewer_v2(int pid, uid_t uid)
+{
+       struct user_info_s *user_info;
+       struct viewer_info_s *viewer_info;
+       GList *iter;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info == NULL) {
+               _W("user info is empty");
+               return -1;
+       }
+
+       iter = g_list_first(user_info->screen_viewer_list);
+       while (iter) {
+               viewer_info = (struct viewer_info_s *)iter->data;
+               iter = g_list_next(iter);
+               if (viewer_info->pid == pid) {
+                       user_info->screen_viewer_list = g_list_remove(
+                                       user_info->screen_viewer_list,
+                                       viewer_info);
+                       __destroy_viewer_info(viewer_info);
+               }
+       }
+
+       return 0;
+}
+
+int _screen_connector_usr_init(uid_t uid)
+{
+       struct user_info_s *user_info;
+
+       user_info = g_hash_table_lookup(user_table, GUINT_TO_POINTER(uid));
+       if (user_info) {
+               _E("Already exists");
+               return 0;
+       }
+
+       user_info = __create_user_info(uid);
+       if (user_info == NULL)
+               return -1;
+
+       g_hash_table_insert(user_table, GUINT_TO_POINTER(uid), user_info);
+
+       return 0;
+}
+
+void _screen_connector_usr_fini(uid_t uid)
+{
+       g_hash_table_remove(user_table, GUINT_TO_POINTER(uid));
+}
+
+int _screen_connector_init(void)
+{
+       _D("screen connector init");
+
+       user_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                       NULL, __destroy_user_info);
+       if (user_table == NULL) {
+               _E("Failed to create user table");
+               return -1;
+       }
+
+       return 0;
+}
+
+void _screen_connector_fini(void)
+{
+       _D("screen connector fini");
+
+       if (user_table)
+               g_hash_table_destroy(user_table);
+}
diff --git a/src/amd_share.c b/src/amd_share.c
new file mode 100644 (file)
index 0000000..26b0742
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <linux/limits.h>
+
+#include <glib.h>
+#include <aul.h>
+#include <aul_svc.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <tzplatform_config.h>
+#include <security-manager.h>
+
+#include "amd_util.h"
+#include "amd_appinfo.h"
+#include "amd_app_status.h"
+#include "amd_share.h"
+#include "aul_svc_priv_key.h"
+
+#define LEGACY_APP_PATH                "/opt/usr/apps/"
+
+struct shared_info_main_s {
+       char *appid;
+       uid_t uid;
+       shared_info_t *shared_info;
+};
+
+static int __can_share(const char *path, const char *pkgid, uid_t uid)
+{
+       struct stat path_stat;
+       char buf[PATH_MAX];
+
+       if (stat(path, &path_stat) != 0) {
+               _E("failed to stat file to share (%s, %d)", path, errno);
+               return -1;
+       }
+
+       if (!S_ISREG(path_stat.st_mode)) {
+               _E("file is not a regular file (%s)", path);
+               return -1;
+       }
+
+       tzplatform_set_user(uid);
+       snprintf(buf, sizeof(buf), "%s/%s/data/",
+                       tzplatform_getenv(TZ_USER_APP), pkgid);
+       tzplatform_reset_user();
+
+       if (strncmp(path, buf, strlen(buf)) != 0) {
+               SECURE_LOGD("file is not in app's data directory (%s)", path);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __get_owner_pid(int caller_pid, bundle *kb)
+{
+       char *org_caller = NULL;
+       const char *appid;
+       int org_caller_pid;
+       app_status_h app_status;
+       int ret;
+
+       ret = bundle_get_str(kb, AUL_K_ORG_CALLER_PID, &org_caller);
+       if (ret != BUNDLE_ERROR_NONE)
+               return caller_pid;
+
+       org_caller_pid = atoi(org_caller);
+       app_status = _app_status_find(caller_pid);
+       appid = _app_status_get_appid(app_status);
+       if (appid && (strcmp(APP_SELECTOR, appid) == 0 ||
+                       strcmp(SHARE_PANEL, appid) == 0))
+               caller_pid = org_caller_pid;
+
+       return caller_pid;
+}
+
+static const char *__get_owner_appid(int caller_pid, bundle *kb)
+{
+       const char *owner_appid;
+       int owner_pid = -1;
+       app_status_h app_status;
+
+       owner_pid = __get_owner_pid(caller_pid, kb);
+       owner_pid = getpgid(owner_pid); /* for webapp */
+       app_status = _app_status_find(owner_pid);
+       owner_appid = _app_status_get_appid(app_status);
+
+       return owner_appid;
+}
+
+static shared_info_h __new_shared_info_handle(const char *appid, uid_t uid,
+               const char *owner_appid)
+{
+       shared_info_h h;
+       int ret;
+
+       h = malloc(sizeof(struct shared_info_main_s));
+       if (h == NULL)
+               return NULL;
+
+       h->shared_info = malloc(sizeof(shared_info_t));
+       if (h->shared_info == NULL) {
+               free(h);
+               return NULL;
+       }
+
+       ret = security_manager_private_sharing_req_new(&h->shared_info->handle);
+       if (ret != SECURITY_MANAGER_SUCCESS) {
+               free(h->shared_info);
+               free(h);
+               return NULL;
+       }
+
+       h->shared_info->owner_appid = strdup(owner_appid);
+       h->appid = strdup(appid);
+       h->uid = uid;
+
+       return h;
+}
+
+static char *__convert_legacy_path(const char *path, uid_t uid)
+{
+       char buf[PATH_MAX];
+       int len = strlen(LEGACY_APP_PATH);
+
+       if (strncmp(LEGACY_APP_PATH, path, len) == 0) {
+               tzplatform_set_user(uid);
+               snprintf(buf, sizeof(buf), "%s/%s",
+                       tzplatform_getenv(TZ_USER_APP), &path[len]);
+               tzplatform_reset_user();
+
+               return strdup(buf);
+       }
+
+       return strdup(path);
+}
+
+static GList *__add_valid_uri(GList *paths, int caller_pid, const char *appid,
+               const char *owner_appid, bundle *kb, uid_t uid)
+{
+       char *path = NULL;
+       const char *pkgid;
+       const struct appinfo *ai;
+       int ret;
+
+       ret = bundle_get_str(kb, AUL_SVC_K_URI, &path);
+       if (ret != BUNDLE_ERROR_NONE)
+               return paths;
+
+       if (!path) {
+               _D("path was null");
+               return paths;
+       }
+
+       if (strncmp(path, "file://", 7) == 0) {
+               path = &path[7];
+       } else {
+               _E("file wasn't started with file://");
+               return paths;
+       }
+
+       ai = _appinfo_find(uid, owner_appid);
+       pkgid = _appinfo_get_value(ai, AIT_PKGID);
+
+       path = __convert_legacy_path(path, uid);
+       if (__can_share(path, pkgid, uid) != 0) {
+               _E("__can_share() returned an error");
+               free(path);
+               return paths;
+       }
+       paths = g_list_append(paths, path);
+
+       return paths;
+}
+
+static GList *__add_valid_key_for_data_selected(GList *paths, int caller_pid,
+               const char *appid, const char *owner_appid, bundle *kb,
+               uid_t uid)
+{
+       int i;
+       int len = 0;
+       const char **path_array = NULL;
+       char *path_str;
+       int type = bundle_get_type(kb, AUL_SVC_DATA_SELECTED);
+       const char *pkgid = NULL;
+       const struct appinfo *ai = NULL;
+
+       if (type != BUNDLE_TYPE_STR_ARRAY)
+               return paths;
+
+       path_array = bundle_get_str_array(kb, AUL_SVC_DATA_SELECTED, &len);
+       if (!path_array || len <= 0) {
+               _E("path_array was null");
+               return paths;
+       }
+
+       ai = _appinfo_find(uid, owner_appid);
+       if (ai == NULL) {
+               _E("appinfo is NULL");
+               return paths;
+       }
+       pkgid = _appinfo_get_value(ai, AIT_PKGID);
+       if (pkgid == NULL) {
+               _E("pkgid was null");
+               return paths;
+       }
+
+       for (i = 0; i < len; i++) {
+               path_str = __convert_legacy_path(path_array[i], uid);
+               if (__can_share(path_str, pkgid, uid) == 0)
+                       paths = g_list_append(paths, path_str);
+               else
+                       free(path_str);
+       }
+
+       return paths;
+}
+
+static GList *__add_valid_key_for_data_path(GList *paths, int caller_pid,
+               const char *appid, const char *owner_appid, bundle *kb,
+               uid_t uid)
+{
+       int type = bundle_get_type(kb, AUL_SVC_DATA_PATH);
+       char *path = NULL;
+       const char **path_array = NULL;
+       int len;
+       int i;
+       const char *pkgid = NULL;
+       const struct appinfo *ai = NULL;
+       char *path_str;
+
+       switch (type) {
+       case BUNDLE_TYPE_STR:
+               bundle_get_str(kb, AUL_SVC_DATA_PATH, &path);
+               if (!path) {
+                       _E("path was null");
+                       break;
+               }
+
+               ai = _appinfo_find(uid, owner_appid);
+               pkgid = _appinfo_get_value(ai, AIT_PKGID);
+               if (pkgid == NULL) {
+                       _E("pkgid was null");
+                       break;
+               }
+
+               path = __convert_legacy_path(path, uid);
+               if (__can_share(path, pkgid, uid) != 0) {
+                       _E("__can_share() returned an error");
+                       free(path);
+                       break;
+               }
+
+               paths = g_list_append(paths, path);
+               break;
+       case BUNDLE_TYPE_STR_ARRAY:
+               path_array = bundle_get_str_array(kb, AUL_SVC_DATA_PATH, &len);
+               if (!path_array || len <= 0) {
+                       _E("path_array was null");
+                       break;
+               }
+
+               ai = _appinfo_find(uid, owner_appid);
+               pkgid = _appinfo_get_value(ai, AIT_PKGID);
+               if (pkgid == NULL) {
+                       _E("pkgid was null");
+                       break;
+               }
+
+               for (i = 0; i < len; i++) {
+                       path_str = __convert_legacy_path(path_array[i], uid);
+                       if (__can_share(path_str, pkgid, uid) == 0)
+                               paths = g_list_append(paths, path_str);
+                       else
+                               free(path_str);
+               }
+
+               break;
+       }
+
+       return paths;
+}
+
+static char **__convert_list_to_array(GList *list)
+{
+       int len;
+       int i = 0;
+       char **array;
+
+       if (list == NULL)
+               return NULL;
+
+       len = g_list_length(list);
+       if (len == 0)
+               return NULL;
+
+       array = (char **)g_malloc(sizeof(char *) * (len + 1));
+       if (array == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       while (list) {
+               array[i] = g_strdup(list->data);
+               list = g_list_next(list);
+               i++;
+       }
+       array[len] = NULL;
+
+       return array;
+}
+
+shared_info_h _temporary_permission_create(int caller_pid, const char *appid,
+               bundle *kb, uid_t uid)
+{
+       char **path_array = NULL;
+       int len;
+       const char *owner_appid = NULL;
+       GList *paths = NULL;
+       shared_info_h h = NULL;
+       int r;
+
+       owner_appid = __get_owner_appid(caller_pid, kb);
+       paths = __add_valid_key_for_data_path(paths, caller_pid, appid,
+                       owner_appid, kb, uid);
+       paths = __add_valid_key_for_data_selected(paths, caller_pid, appid,
+                       owner_appid, kb, uid);
+       paths = __add_valid_uri(paths, caller_pid, appid, owner_appid, kb, uid);
+       if (!paths || !owner_appid)
+               goto clear;
+
+       _D("grant permission %s : %s", owner_appid, appid);
+
+       h = __new_shared_info_handle(appid, uid, owner_appid);
+       if (h == NULL)
+               goto clear;
+
+       len = g_list_length(paths);
+       path_array = __convert_list_to_array(paths);
+       if (path_array == NULL)
+               goto clear;
+
+       r = security_manager_private_sharing_req_set_owner_appid(
+                       h->shared_info->handle, owner_appid);
+       if (r != SECURITY_MANAGER_SUCCESS)
+               _E("Failed to set owner appid(%s) %d", owner_appid, r);
+
+       r = security_manager_private_sharing_req_set_target_appid(
+                       h->shared_info->handle, appid);
+       if (r != SECURITY_MANAGER_SUCCESS)
+               _E("Failed to set target appid(%s) %d", appid, r);
+
+       r = security_manager_private_sharing_req_add_paths(
+                       h->shared_info->handle, (const char **)path_array, len);
+       if (r != SECURITY_MANAGER_SUCCESS)
+               _E("Failed to add paths %d", r);
+
+       _D("security_manager_private_sharing_apply ++");
+       r = security_manager_private_sharing_apply(h->shared_info->handle);
+       _D("security_manager_private_sharing_apply --");
+       if (r != SECURITY_MANAGER_SUCCESS) {
+               _E("Failed to apply private sharing %d", r);
+               _temporary_permission_destroy(h);
+               h = NULL;
+       }
+
+clear:
+       if (paths)
+               g_list_free_full(paths, free);
+
+       if (path_array)
+               g_strfreev(path_array);
+
+       return h;
+}
+
+int _temporary_permission_apply(int pid, uid_t uid, shared_info_h handle)
+{
+       int ret;
+       app_status_h app_status;
+
+       if (handle == NULL)
+               return -1;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return -1;
+
+       ret = _app_status_add_shared_info(app_status, handle->shared_info);
+       if (ret != 0)
+               return ret;
+
+       handle->shared_info = NULL;
+
+       return 0;
+}
+
+int _temporary_permission_destroy(shared_info_h handle)
+{
+       int r;
+
+       if (handle == NULL)
+               return -1;
+
+       if (handle->shared_info) { /* back out */
+               _D("revoke permission %s : %s",
+                               handle->shared_info->owner_appid,
+                               handle->appid);
+               r = security_manager_private_sharing_drop(
+                               handle->shared_info->handle);
+               if (r != SECURITY_MANAGER_SUCCESS)
+                       _E("revoke error %d", r);
+
+               security_manager_private_sharing_req_free(
+                               handle->shared_info->handle);
+               free(handle->shared_info->owner_appid);
+       }
+
+       free(handle->appid);
+       free(handle);
+
+       return 0;
+}
+
+int _temporary_permission_drop(int pid, uid_t uid)
+{
+       int r;
+       shared_info_t *sit;
+       app_status_h app_status;
+       GList *list;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return -1;
+
+       list = _app_status_get_shared_info_list(app_status);
+       if (!list) {
+               _D("list was null");
+               return -1;
+       }
+
+       while (list) {
+               sit = (shared_info_t *)list->data;
+               _D("revoke permission %s : %d", sit->owner_appid, pid);
+               r = security_manager_private_sharing_drop(sit->handle);
+               if (r != SECURITY_MANAGER_SUCCESS)
+                       _E("revoke error %d", r);
+               security_manager_private_sharing_req_free(sit->handle);
+               list = g_list_next(list);
+       }
+
+       return _app_status_clear_shared_info_list(app_status);
+}
+
diff --git a/src/amd_signal.c b/src/amd_signal.c
new file mode 100644 (file)
index 0000000..6039dd2
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 2016 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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include "app_signal.h"
+#include "amd_util.h"
+#include "amd_signal.h"
+#include "amd_cooldown.h"
+
+#define MAX_LABEL_BUFSZ 1024
+#define SIGNAL_INIT_INTERVAL 3
+
+struct signal_initializer {
+       int (*callback)(void *data);
+       void *data;
+};
+
+static GDBusConnection *system_conn;
+static GList *signal_init_list;
+static guint startup_finished_sid;
+static guint user_session_startup_finished_sid;
+static int (*startup_finished_callback)(uid_t, void *);
+static void *startup_finished_data;
+static uid_t startup_finished_uid;
+static bool system_boot_completed;
+static bool user_boot_completed;
+
+static GDBusConnection *__get_system_conn(void)
+{
+       GError *err = NULL;
+
+       if (system_conn)
+               return system_conn;
+
+       system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (system_conn == NULL) {
+               _E("g_bus_get_sync() is failed: %s", err->message);
+               g_error_free(err);
+               return NULL;
+       }
+
+       return system_conn;
+}
+
+int _signal_send_watchdog(int pid, int signal_num)
+{
+       GError *err = NULL;
+       GDBusConnection *conn;
+
+       if (_cooldown_get_status() == COOLDOWN_LIMIT) {
+               _E("cooldown status:LimitAction");
+               _E("watchdog signal already sent for pid %d", pid);
+               return -1;
+       }
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       if (g_dbus_connection_emit_signal(conn,
+                                       NULL,
+                                       RESOURCED_PROC_OBJECT,
+                                       RESOURCED_PROC_INTERFACE,
+                                       RESOURCED_PROC_WATCHDOG_SIGNAL,
+                                       g_variant_new("(ii)", pid, signal_num),
+                                       &err) == FALSE) {
+               _E("g_dbus_connection_emit_signal() is failed: %s",
+                                       err->message);
+               g_error_free(err);
+               return -1;
+       }
+
+       if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+               _E("g_dbus_connection_flush_sync() is failed: %s",
+                                       err->message);
+               g_error_free(err);
+               return -1;
+       }
+
+       _W("send a watchdog signal done: %d", pid);
+
+       return 0;
+}
+
+int _signal_send_proc_prelaunch(const char *appid, const char *pkgid,
+               int attribute, int category)
+{
+       GError *err = NULL;
+       GVariant *param;
+       GDBusConnection *conn;
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       param = g_variant_new("(ssii)", appid, pkgid, attribute, category);
+       if (g_dbus_connection_emit_signal(conn,
+                                       NULL,
+                                       RESOURCED_PROC_OBJECT,
+                                       RESOURCED_PROC_INTERFACE,
+                                       RESOURCED_PROC_PRELAUNCH_SIGNAL,
+                                       param,
+                                       &err) == FALSE) {
+               _E("g_dbus_connection_emit_signal() is failed: %s",
+                                       err->message);
+               g_error_free(err);
+               return -1;
+       }
+
+       if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+               _E("g_dbus_connection_flush_sync() is failed: %s",
+                                       err->message);
+               g_error_free(err);
+               return -1;
+       }
+
+       _W("send a prelaunch signal done: " \
+                       "appid(%s) pkgid(%s) attribute(%x) category(%x)",
+                       appid, pkgid, attribute, category);
+
+       return 0;
+}
+
+int _signal_send_tep_mount(char *mnt_path[], const char *pkgid)
+{
+       GError *err = NULL;
+       GDBusMessage *msg;
+       GDBusConnection *conn;
+       int ret = 0;
+       int rv = 0;
+       struct stat link_buf = {0,};
+       GVariant *param;
+       char buf[MAX_LABEL_BUFSZ];
+
+       if (pkgid == NULL) {
+               _E("Invalid parameter");
+               return -1;
+       }
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       rv = lstat(mnt_path[0], &link_buf);
+       if (rv == 0) {
+               rv = unlink(mnt_path[0]);
+               if (rv)
+                       _E("Unable tp remove link file %s", mnt_path[0]);
+       }
+
+       msg = g_dbus_message_new_method_call(TEP_BUS_NAME,
+                                       TEP_OBJECT_PATH,
+                                       TEP_INTERFACE_NAME,
+                                       TEP_MOUNT_METHOD);
+       if (msg == NULL) {
+               _E("g_dbus_message_new_method_call() is failed.");
+               return -1;
+       }
+
+       snprintf(buf, sizeof(buf), "User::Pkg::%s::RO", pkgid);
+       param = g_variant_new("(sss)", mnt_path[0], mnt_path[1], buf);
+       g_dbus_message_set_body(msg, param);
+
+       if (g_dbus_connection_send_message(conn,
+                                       msg,
+                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                       NULL,
+                                       &err) == FALSE) {
+               _E("g_dbus_connection_send_message() is failed: %s",
+                                       err->message);
+               ret = -1;
+       }
+
+       if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+               _E("g_dbus_connection_flush_sync() is failed: %s",
+                                       err->message);
+               ret = -1;
+       }
+
+       g_object_unref(msg);
+       g_clear_error(&err);
+
+       return ret;
+}
+
+int _signal_send_tep_unmount(const char *mnt_path)
+{
+       GError *err = NULL;
+       GDBusMessage *msg;
+       GDBusConnection *conn;
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       msg = g_dbus_message_new_method_call(TEP_BUS_NAME,
+                                       TEP_OBJECT_PATH,
+                                       TEP_INTERFACE_NAME,
+                                       TEP_UNMOUNT_METHOD);
+       if (msg == NULL) {
+               _E("g_dbus_message_new_method_call() is failed.");
+               return -1;
+       }
+
+       g_dbus_message_set_body(msg, g_variant_new("(s)", mnt_path));
+       if (g_dbus_connection_send_message(conn,
+                                       msg,
+                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                       NULL,
+                                       &err) == FALSE) {
+               _E("g_dbus_connection_send_message() is failed: %s",
+                                       err->message);
+               g_object_unref(msg);
+               g_clear_error(&err);
+               return -1;
+       }
+
+       g_dbus_connection_flush(conn, NULL, NULL, NULL);
+       g_object_unref(msg);
+       g_clear_error(&err);
+
+       return 0;
+}
+
+int _signal_send_proc_suspend(int pid)
+{
+       GError *err = NULL;
+       GDBusConnection *conn;
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       if (g_dbus_connection_emit_signal(conn,
+                                       NULL,
+                                       APPFW_SUSPEND_HINT_PATH,
+                                       APPFW_SUSPEND_HINT_INTERFACE,
+                                       APPFW_SUSPEND_HINT_SIGNAL,
+                                       g_variant_new("(i)", pid),
+                                       &err) == FALSE) {
+               _E("g_dbus_connection_emit_signal() is failed: %s",
+                                       err->message);
+               g_error_free(err);
+               return -1;
+       }
+
+       if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+               _E("g_dbus_connection_flush_sync() is failed: %s",
+                                       err->message);
+               g_error_free(err);
+               return -1;
+       }
+
+       _D("[__SUSPEND__] Send suspend hint, pid: %d", pid);
+
+       return 0;
+}
+
+int _signal_get_proc_status(const int pid, int *status, int *focused)
+{
+       GError *err = NULL;
+       GDBusMessage *message;
+       GDBusMessage *reply;
+       GVariant *var;
+       GDBusConnection *conn;
+       int proc_status = -1;
+       int proc_focus = -1;
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       message = g_dbus_message_new_method_call(WM_PROC_NAME,
+                                       WM_PROC_PATH,
+                                       WM_PROC_INTERFACE,
+                                       WM_PROC_METHOD);
+       if (message == NULL) {
+               _E("g_bus_message_new_method_call() is failed.");
+               return -1;
+       }
+
+       g_dbus_message_set_body(message, g_variant_new("(i)", pid));
+       reply = g_dbus_connection_send_message_with_reply_sync(conn,
+                                       message,
+                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                       -1,
+                                       NULL,
+                                       NULL,
+                                       &err);
+       g_dbus_connection_flush(conn, NULL, NULL, NULL);
+       g_object_unref(message);
+       if (reply == NULL) {
+               _E("g_dbus_connection_send_message_with_reply_sync failed: %s",
+                                       err->message);
+               g_clear_error(&err);
+               return -1;
+       }
+
+       var = g_dbus_message_get_body(reply);
+       if (var == NULL) {
+               _E("g_dbus_message_get_body() is failed");
+               g_object_unref(reply);
+               return -1;
+       }
+       g_variant_get(var, "(ii)", &proc_status, &proc_focus);
+
+       g_object_unref(reply);
+
+       if (proc_status == -1 || proc_focus == -1) {
+               _E("Failed to get proc status info");
+               return -1;
+       }
+
+       *status = proc_status;
+       *focused = proc_focus;
+       _D("pid(%d), status(%d), focused(%d)", pid, proc_status, proc_focus);
+
+       return 0;
+}
+
+static void __system_bus_signal_handler(GDBusConnection *connection,
+               const gchar *sender_name, const gchar *object_path,
+               const gchar *interface_name, const char *signal_name,
+               GVariant *parameters, gpointer user_data)
+{
+       guint64 uid = 0;
+
+       _W("[SIGNAL_HANDLER] signal(%s)", signal_name);
+       if (g_strcmp0(signal_name, SD_STARTUP_FINISHED_SIGNAL) == 0) {
+               system_boot_completed = true;
+               _D("[SIGNAL_HANDLER] system boot completed");
+       } else if (g_strcmp0(signal_name,
+                       SD_USER_SESSION_STARTUP_FINISHED_SIGNAL) == 0) {
+               user_boot_completed = true;
+               g_variant_get(parameters, "(t)", &uid);
+               startup_finished_uid = (uid_t)uid;
+               _D("[SIGNAL_HANDLER] user boot completed");
+       }
+
+       if (system_boot_completed && user_boot_completed) {
+               if (startup_finished_callback) {
+                       startup_finished_callback(startup_finished_uid,
+                                       startup_finished_data);
+               }
+
+               user_boot_completed = false;
+       }
+}
+
+static guint __subscribe_system_bus(const char *object_path,
+               const char *interface_name, const char *signal_name)
+{
+       guint sid;
+       GError *err = NULL;
+       GDBusConnection *conn;
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return 0;
+
+       sid = g_dbus_connection_signal_subscribe(conn,
+                                               NULL,
+                                               interface_name,
+                                               signal_name,
+                                               object_path,
+                                               NULL,
+                                               G_DBUS_SIGNAL_FLAGS_NONE,
+                                               __system_bus_signal_handler,
+                                               NULL,
+                                               NULL);
+       if (sid == 0)
+               _E("g_bus_connection_signal_subscribe() is failed");
+
+       g_clear_error(&err);
+
+       return sid;
+}
+
+int _signal_subscribe_startup_finished(int (*callback)(uid_t uid, void *data),
+               void *user_data)
+{
+       if (callback == NULL)
+               return -1;
+
+       startup_finished_sid = __subscribe_system_bus(SD_OBJECT_PATH,
+                       SD_MANAGER_INTERFACE,
+                       SD_STARTUP_FINISHED_SIGNAL);
+       if (startup_finished_sid == 0) {
+               _E("Failed to subscribe systemd signal");
+               return -1;
+       }
+
+       user_session_startup_finished_sid = __subscribe_system_bus(
+                       SD_OBJECT_PATH,
+                       SD_MANAGER_INTERFACE,
+                       SD_USER_SESSION_STARTUP_FINISHED_SIGNAL);
+       if (user_session_startup_finished_sid == 0) {
+               _E("Failed to subscribe systemd signal");
+               _signal_unsubscribe_startup_finished();
+               return -1;
+       }
+
+       startup_finished_callback = callback;
+       startup_finished_data = user_data;
+       _D("[SIGNAL] subscribe startup finished");
+
+       return 0;
+}
+
+int _signal_unsubscribe_startup_finished(void)
+{
+       GDBusConnection *conn;
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       if (!startup_finished_sid && !user_session_startup_finished_sid)
+               return 0;
+
+       if (startup_finished_sid) {
+               g_dbus_connection_signal_unsubscribe(conn,
+                               startup_finished_sid);
+               startup_finished_sid = 0;
+       }
+
+       if (user_session_startup_finished_sid) {
+               g_dbus_connection_signal_unsubscribe(conn,
+                               user_session_startup_finished_sid);
+               user_session_startup_finished_sid = 0;
+       }
+
+       startup_finished_callback = NULL;
+       startup_finished_data = NULL;
+       _D("[SIGNAL] unsubscribe startup finished");
+
+       return 0;
+}
+
+int _signal_send_cpu_boost(int req)
+{
+       GError *err = NULL;
+       GDBusMessage *msg;
+       GDBusConnection *conn;
+       int res = 0;
+
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       msg = g_dbus_message_new_method_call(SYSTEM_BUS_NAME,
+                                               SYSTEM_OBJECT_PATH,
+                                               SYSTEM_INTERFACE_NAME,
+                                               SYSTEM_METHOD_NAME);
+       if (msg == NULL) {
+               _E("g_dbus_message_new_method_call() is failed.");
+               return -1;
+       }
+
+       g_dbus_message_set_body(msg, g_variant_new("(i)", req));
+       if (g_dbus_connection_send_message(conn,
+                                       msg,
+                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                       NULL,
+                                       &err) == FALSE) {
+               _E("g_dbus_connection_send_message() is failed(%s)",
+                                       err->message);
+               res = -1;
+       }
+
+       g_dbus_connection_flush(conn, NULL, NULL, NULL);
+       g_object_unref(msg);
+       g_clear_error(&err);
+
+       _D("send cpu boost req(%d)", req);
+
+       return res;
+}
+
+int _signal_send_display_lock_state(const char *state, char *flag, unsigned int timeout)
+{
+       GError *err = NULL;
+       GDBusConnection *conn;
+       GDBusMessage *msg;
+       const char *holdkeyblock_string = "holdkeyblock";
+       int ret = 0;
+
+       _D("Acquring display lock");
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       msg = g_dbus_message_new_method_call(SYSTEM_BUS_NAME,
+                       SYSTEM_PATH_DISPLAY,
+                       SYSTEM_INTERFACE_DISPLAY,
+                       SYSTEM_LOCK_STATE);
+       if (msg == NULL) {
+               _E("g_dbus_message_new_method_call() is failed");
+               return -1;
+       }
+
+       g_dbus_message_set_body(msg, g_variant_new("(sssi)", state,
+                       flag, holdkeyblock_string, timeout));
+       if (!g_dbus_connection_send_message(conn, msg,
+                               G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err)) {
+                ret = -1;
+               _E("Unable to send dbus message for acquring lock as  %s",
+                       err->message);
+       }
+
+       _D("Display lock acquired");
+       g_object_unref(msg);
+       g_dbus_connection_flush_sync(conn, NULL, NULL);
+       g_clear_error(&err);
+       return ret;
+}
+
+int _signal_send_display_unlock_state(const char *state, char *flag)
+{
+       GError *err = NULL;
+       GDBusConnection *conn;
+       GDBusMessage *msg;
+       int ret = 0;
+
+       _D("releasing display lock");
+       conn = __get_system_conn();
+       if (conn == NULL)
+               return -1;
+
+       msg = g_dbus_message_new_method_call(SYSTEM_BUS_NAME,
+                       SYSTEM_PATH_DISPLAY,
+                       SYSTEM_INTERFACE_DISPLAY,
+                       SYSTEM_UNLOCK_STATE);
+       if (msg == NULL) {
+               _E("g_dbus_message_new_method_call() is failed");
+               return -1;
+       }
+
+       g_dbus_message_set_body(msg, g_variant_new("(ss)", state, flag));
+       if (!g_dbus_connection_send_message(conn, msg,
+                               G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err)) {
+               _E("Unable to send dbus message for releasing lock as  %s",
+                       err->message);
+               ret = -1;
+       }
+
+       _D("Display lock released");
+       g_object_unref(msg);
+       g_dbus_connection_flush_sync(conn, NULL, NULL);
+       g_clear_error(&err);
+       return ret;
+}
+
+int _signal_add_initializer(int (*callback)(void *data), void *user_data)
+{
+       struct signal_initializer *initializer;
+
+       if (callback == NULL) {
+               _E("Invalid parameter");
+               return -1;
+       }
+
+       initializer = (struct signal_initializer *)malloc(
+                       sizeof(struct signal_initializer));
+       if (initializer == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       initializer->callback = callback;
+       initializer->data = user_data;
+
+       signal_init_list = g_list_append(signal_init_list, initializer);
+
+       return 0;
+}
+
+static gboolean __dispatch_initializer_list(gpointer user_data)
+{
+       struct signal_initializer *initializer;
+       GList *list;
+       int ret;
+
+       list = g_list_first(signal_init_list);
+       while (list) {
+               initializer = (struct signal_initializer *)list->data;
+               list = g_list_next(list);
+               if (initializer) {
+                       ret = initializer->callback(initializer->data);
+                       if (ret == 0) {
+                               signal_init_list =
+                                       g_list_remove(signal_init_list,
+                                                       initializer);
+                               free(initializer);
+                       }
+               }
+       }
+
+       if (signal_init_list == NULL) {
+               _D("init list is NULL");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+int _signal_init(void)
+{
+       if (signal_init_list) {
+               g_timeout_add_seconds(SIGNAL_INIT_INTERVAL,
+                               __dispatch_initializer_list, NULL);
+       }
+
+       return 0;
+}
diff --git a/src/amd_socket.c b/src/amd_socket.c
new file mode 100644 (file)
index 0000000..60ce075
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/xattr.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/limits.h>
+
+#include <bundle.h>
+#include <systemd/sd-daemon.h>
+#include <aul_sock.h>
+
+#include "amd_util.h"
+#include "amd_socket.h"
+
+#define PATH_AMD_SOCK "/run/aul/daemons/.amd-sock"
+
+int _create_sock_activation(void)
+{
+       int fds;
+
+       fds = sd_listen_fds(0);
+       if (fds == 1) {
+               if (chmod(PATH_AMD_SOCK, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0)
+                       _E("change mode error: %d", errno);
+               return SD_LISTEN_FDS_START;
+       }
+
+       if (fds > 1)
+               _E("Too many file descriptors received.\n");
+       else
+               _D("There is no socket stream");
+
+       return -1;
+}
+
+int _create_server_sock(void)
+{
+       int fd;
+       struct sockaddr_un addr;
+
+       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+       if (fd < 0) {
+               _E("create socket error: %d", errno);
+               return -1;
+       }
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sun_family = AF_UNIX;
+       snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", PATH_AMD_SOCK);
+       unlink(addr.sun_path);
+
+       if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) {
+               _E("bind error: %d", errno);
+               close(fd);
+               return -1;
+       }
+
+       if (chmod(addr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
+               _E("change mode error: %d", errno);
+               close(fd);
+               return -1;
+       }
+
+       aul_sock_set_sock_option(fd, 0);
+
+       if (listen(fd, 128) == -1) {
+               _E("listen error: %d", errno);
+               close(fd);
+               return -1;
+       }
+
+       return fd;
+}
+
+static int __connect_client_sock(int fd, const struct sockaddr *saptr,
+               socklen_t salen, int nsec)
+{
+       int flags;
+       int ret;
+       int error;
+       socklen_t len;
+       fd_set readfds;
+       fd_set writefds;
+       struct timeval timeout;
+
+       flags = fcntl(fd, F_GETFL, 0);
+       fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+       error = 0;
+       ret = connect(fd, (struct sockaddr *)saptr, salen);
+       if (ret < 0) {
+               if (errno != EAGAIN && errno != EINPROGRESS) {
+                       fcntl(fd, F_SETFL, flags);
+                       return -2;
+               }
+       }
+
+       /* Do whatever we want while the connect is taking place. */
+       if (ret == 0)
+               goto done;      /* connect completed immediately */
+
+       FD_ZERO(&readfds);
+       FD_SET(fd, &readfds);
+       writefds = readfds;
+       timeout.tv_sec = 0;
+       timeout.tv_usec = nsec;
+
+       ret = select(fd + 1, &readfds, &writefds, NULL,
+                    nsec ? &timeout : NULL);
+       if (ret == 0) {
+               close(fd);      /* timeout */
+               errno = ETIMEDOUT;
+               return -1;
+       }
+
+       if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
+               len = sizeof(error);
+               if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+                       return -1;      /* Solaris pending error */
+       } else {
+               return -1;      /* select error: sockfd not set*/
+       }
+
+done:
+       (void)fcntl(fd, F_SETFL, flags);
+       if (error) {
+               close(fd);
+               errno = error;
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __create_launchpad_client_sock(const char *pad_type, uid_t uid)
+{
+       int fd = -1;
+       struct sockaddr_un saddr = { 0, };
+       int retry = 1;
+       int ret = -1;
+
+       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+       /*  support above version 2.6.27*/
+       if (fd < 0) {
+               if (errno == EINVAL) {
+                       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+                       if (fd < 0) {
+                               _E("second chance - socket create error");
+                               return -1;
+                       }
+               } else {
+                       _E("socket error");
+                       return -1;
+               }
+       }
+
+       saddr.sun_family = AF_UNIX;
+       snprintf(saddr.sun_path, sizeof(saddr.sun_path),
+                       "/run/aul/daemons/%d/%s", uid, pad_type);
+ retry_con:
+       ret = __connect_client_sock(fd, (struct sockaddr *)&saddr,
+                       sizeof(saddr), 100 * 1000);
+       if (ret < -1) {
+               _E("maybe peer not launched or peer daed\n");
+               if (retry > 0) {
+                       usleep(100 * 1000);
+                       retry--;
+                       goto retry_con;
+               }
+       }
+       if (ret < 0) {
+               close(fd);
+               return -1;
+       }
+
+       aul_sock_set_sock_option(fd, 1);
+
+       return fd;
+}
+
+int _send_cmd_to_launchpad(const char *pad_type, uid_t uid, int cmd, bundle *kb)
+{
+       int fd;
+       int len;
+       int res;
+       char err_buf[1024];
+
+       fd = __create_launchpad_client_sock(pad_type, uid);
+       if (fd < 0)
+               return -1;
+
+       res = aul_sock_send_bundle_with_fd(fd, cmd, kb, AUL_SOCK_ASYNC);
+       if (res < 0) {
+               close(fd);
+               return res;
+       }
+
+retry_recv:
+       len = recv(fd, &res, sizeof(int), 0);
+       if (len == -1) {
+               if (errno == EAGAIN) {
+                       _E("recv timeout : %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+                       res = -EAGAIN;
+               } else if (errno == EINTR) {
+                       _D("recv : %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+                       goto retry_recv;
+               } else {
+                       _E("recv error : %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+                       res = -ECOMM;
+               }
+       }
+
+       close(fd);
+
+       return res;
+}
+
+void _send_result_to_client(int fd, int res)
+{
+       if (fd < 3)
+               return;
+
+       if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
+               if (errno == EPIPE)
+                       _E("send failed due to EPIPE.");
+               _E("send fail to client");
+       }
+
+       close(fd);
+}
+
+void _send_result_to_client_v2(int fd, int res)
+{
+       if (fd < 3)
+               return;
+
+       if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
+               if (errno == EPIPE)
+                       _E("send failed due to EPIPE.");
+               _E("send fail to client");
+       }
+}
+
diff --git a/src/amd_splash_screen.c b/src/amd_splash_screen.c
new file mode 100644 (file)
index 0000000..eef8c4e
--- /dev/null
@@ -0,0 +1,786 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <glib.h>
+#include <aul.h>
+#include <aul_cmd.h>
+#include <aul_svc.h>
+#include <aul_svc_priv_key.h>
+#include <wayland-client.h>
+#include <wayland-tbm-client.h>
+#include <tizen-launch-client-protocol.h>
+#include <vconf.h>
+#include <sensor_internal.h>
+
+#include "amd_appinfo.h"
+#include "amd_util.h"
+#include "amd_splash_screen.h"
+#include "amd_wayland.h"
+#include "amd_app_status.h"
+
+#define K_FAKE_EFFECT "__FAKE_EFFECT__"
+#define APP_CONTROL_OPERATION_MAIN "http://tizen.org/appcontrol/operation/main"
+#define SPLASH_SCREEN_INFO_PATH "/usr/share/aul"
+#define TAG_SPLASH_IMAGE "[SplashImage]"
+#define TAG_NAME "Name"
+#define TAG_FILE "File"
+#define TAG_TYPE "Type"
+#define TAG_ORIENTATION "Orientation"
+#define TAG_INDICATOR_DISPLAY "Indicator-display"
+#define TAG_COLOR_DEPTH "Color-depth"
+#define TIMEOUT_INTERVAL 10000 /* 10 sec */
+
+struct splash_image_s {
+       struct tizen_launch_splash *image;
+       char *appid;
+       char *src;
+       int type;
+       int rotation;
+       int indicator;
+       int color_depth;
+       int pid;
+       char *effect_type;
+       char *theme_type;
+       guint timer;
+};
+
+struct rotation_s {
+       int handle;
+       int angle;
+       int auto_rotate;
+};
+
+struct image_info_s {
+       char *name;
+       char *file;
+       char *type;
+       char *orientation;
+       char *indicator_display;
+       char *color_depth;
+};
+
+static struct wl_display *display;
+static struct tizen_launch_effect *tz_launch_effect;
+static int splash_screen_initialized;
+static struct rotation_s rotation;
+static int rotation_initialized;
+static GList *default_image_list;
+static splash_image_h splash_image;
+
+static int __init_splash_screen(void);
+static int __init_rotation(void);
+
+splash_image_h _splash_screen_get_image(int pid)
+{
+       if (splash_image == NULL)
+               return NULL;
+
+       if (splash_image->pid == pid)
+               return splash_image;
+
+       return NULL;
+}
+
+static void __set_splash_image(splash_image_h si)
+{
+       splash_image = si;
+}
+
+void _splash_screen_destroy_image(splash_image_h si)
+{
+       if (si == NULL)
+               return;
+
+       if (si->timer)
+               g_source_remove(si->timer);
+       if (si->theme_type)
+               free(si->theme_type);
+       if (si->effect_type)
+               free(si->effect_type);
+       if (si->appid)
+               free(si->appid);
+       if (si->src)
+               free(si->src);
+       if (si->image) {
+               tizen_launch_splash_destroy(si->image);
+               wl_display_flush(display);
+       }
+       free(si);
+       __set_splash_image(NULL);
+}
+
+static gboolean __timeout_handler(gpointer data)
+{
+       splash_image_h si = (splash_image_h)data;
+       app_status_h app_status;
+
+       if (si == NULL)
+               return FALSE;
+
+       app_status = _app_status_find(si->pid);
+       if (app_status) {
+               if (_app_status_is_starting(app_status) == false) {
+                       _W("% is not starting", si->pid);
+                       return TRUE;
+               }
+       }
+
+       si->timer = 0;
+       _splash_screen_destroy_image(si);
+
+       return FALSE;
+}
+
+static int __app_can_launch_splash_image(const struct appinfo *ai,
+                                       bundle *kb)
+{
+       const char *comp_type;
+       const char *fake_effect;
+       int display;
+
+       comp_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (comp_type == NULL || strcmp(comp_type, APP_TYPE_UI) != 0) {
+               _D("component_type: %s", comp_type);
+               return -1;
+       }
+
+       fake_effect = bundle_get_val(kb, K_FAKE_EFFECT);
+       if (fake_effect && strncmp(fake_effect, "OFF", strlen("OFF")) == 0)
+               return -1;
+
+       _appinfo_get_int_value(ai, AIT_SPLASH_SCREEN_DISPLAY, &display);
+       if (!(display & APP_ENABLEMENT_MASK_ACTIVE))
+               return -1;
+
+       return 0;
+}
+
+static struct appinfo_splash_image *__get_splash_image_info(
+               const struct appinfo *ai, bundle *kb, int cmd)
+{
+       struct appinfo_splash_image *ai_si;
+       const struct appinfo_splash_screen *ai_ss;
+       const char *operation;
+       GHashTable *tbl;
+       const struct appinfo *caller_ai;
+       const char *uid_str;
+       const char *caller_appid;
+       const char *comp_type;
+       uid_t uid = 0;
+
+       ai_ss = _appinfo_get_ptr_value(ai, AIT_SPLASH_SCREEN);
+       if (ai_ss == NULL)
+               return NULL;
+
+       if ((rotation.angle == 90 || rotation.angle == 270)
+                               && rotation.auto_rotate == true)
+               tbl = ai_ss->landscape;
+       else
+               tbl = ai_ss->portrait;
+
+       if (tbl == NULL)
+               return NULL;
+
+       operation = bundle_get_val(kb, AUL_SVC_K_OPERATION);
+       if (cmd == APP_OPEN || (operation &&
+                       (!strcmp(operation, APP_CONTROL_OPERATION_MAIN) ||
+                        !strcmp(operation, AUL_SVC_OPERATION_DEFAULT))))
+               return g_hash_table_lookup(tbl, "launch-effect");
+
+       if (operation) {
+               ai_si = g_hash_table_lookup(tbl, operation);
+               if (ai_si)
+                       return ai_si;
+       }
+
+       caller_appid = bundle_get_val(kb, AUL_K_CALLER_APPID);
+       if (caller_appid == NULL)
+               return NULL;
+
+       uid_str = bundle_get_val(kb, AUL_K_TARGET_UID);
+       if (uid_str == NULL)
+               return NULL;
+
+       uid = atol(uid_str);
+       caller_ai = _appinfo_find(uid, caller_appid);
+       if (caller_ai == NULL)
+               return NULL;
+
+       comp_type = _appinfo_get_value(caller_ai, AIT_COMPTYPE);
+       if (comp_type == NULL)
+               return NULL;
+
+       if (!strcmp(comp_type, APP_TYPE_WATCH) ||
+                       !strcmp(comp_type, APP_TYPE_WIDGET))
+               return g_hash_table_lookup(tbl, "launch-effect");
+
+       return NULL;
+}
+
+static struct image_info_s *__get_default_image_info(bundle *kb)
+{
+       struct image_info_s *info = NULL;
+       const char *orientation = "portrait";
+       const char *str;
+       GList *list;
+
+       if (default_image_list == NULL)
+               return NULL;
+
+       if ((rotation.angle == 90 || rotation.angle == 270) &&
+                       rotation.auto_rotate == true)
+               orientation = "landscape";
+
+       str = bundle_get_val(kb, AUL_SVC_K_SPLASH_SCREEN);
+       if (str == NULL)
+               str = "default";
+
+       list = default_image_list;
+       while (list) {
+               info = (struct image_info_s *)list->data;
+               if (info && strcmp(str, info->name) == 0) {
+                       if (!strcasecmp(info->orientation, orientation))
+                               return info;
+               }
+
+               list = g_list_next(list);
+       }
+
+       return NULL;
+}
+
+splash_image_h _splash_screen_create_image(const struct appinfo *ai,
+               bundle *kb, int cmd, bool is_subapp)
+{
+       struct splash_image_s *si;
+       struct appinfo_splash_image *ai_si;
+       struct image_info_s *info;
+       const char *appid;
+       const char *src = NULL;
+       int file_type = 0;
+       int indicator = 1;
+       int color_depth = 24; /* default */
+
+       if (!splash_screen_initialized) {
+               if (__init_splash_screen() < 0)
+                       return NULL;
+       }
+
+       if (__app_can_launch_splash_image(ai, kb) < 0)
+               return NULL;
+
+       if (!rotation_initialized) {
+               if (__init_rotation() < 0)
+                       _W("Failed to initialize rotation");
+       }
+       _D("angle: %d", rotation.angle);
+
+       ai_si = __get_splash_image_info(ai, kb, cmd);
+       if (ai_si) {
+               src = ai_si->src;
+               if (access(src, F_OK) != 0)
+                       return NULL;
+               if (strcasecmp(ai_si->type, "edj") == 0)
+                       file_type = 1;
+               if (strcmp(ai_si->indicatordisplay, "false") == 0)
+                       indicator = 0;
+               if (strcmp(ai_si->color_depth, "32") == 0)
+                       color_depth = 32;
+       } else {
+               info = __get_default_image_info(kb);
+               if (info == NULL)
+                       return NULL;
+               src = info->file;
+               if (access(src, F_OK) != 0)
+                       return NULL;
+               if (strcasecmp(info->type, "edj") == 0)
+                       file_type = 1;
+               if (strcmp(info->indicator_display, "false") == 0)
+                       indicator = 0;
+               if (strcmp(info->color_depth, "32") == 0)
+                       color_depth = 32;
+       }
+
+       si = (struct splash_image_s *)calloc(1, sizeof(struct splash_image_s));
+       if (si == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       si->image = tizen_launch_effect_create_splash_img(
+                       tz_launch_effect);
+       if (si->image == NULL) {
+               _E("Failed to get launch image");
+               free(si);
+               return NULL;
+       }
+       wl_display_flush(display);
+
+       si->src = strdup(src);
+       if (si->src == NULL) {
+               _E("out of memory");
+               _splash_screen_destroy_image(si);
+               return NULL;
+       }
+
+       if (is_subapp)
+               si->effect_type = strdup("depth-in");
+       else
+               si->effect_type = strdup("launch");
+       if (si->effect_type == NULL) {
+               _E("Out of memory");
+               _splash_screen_destroy_image(si);
+               return NULL;
+       }
+
+       si->theme_type = strdup("default");
+       if (si->theme_type == NULL) {
+               _E("Out of memory");
+               _splash_screen_destroy_image(si);
+               return NULL;
+       }
+
+       appid = _appinfo_get_value(ai, AIT_NAME);
+       si->appid = strdup(appid);
+       if (si->appid == NULL) {
+               _E("out of memory");
+               _splash_screen_destroy_image(si);
+               return NULL;
+       }
+
+       si->type = file_type;
+       si->rotation = rotation.angle;
+       si->indicator = indicator;
+       si->color_depth = color_depth;
+
+       si->timer = g_timeout_add(TIMEOUT_INTERVAL, __timeout_handler, si);
+       __set_splash_image(si);
+
+       return si;
+}
+
+void _splash_screen_send_image(splash_image_h si)
+{
+       struct wl_array options;
+       bundle *b;
+       bundle_raw *raw_data = NULL;
+       int len = 0;
+       int ret;
+       size_t size;
+       void *data;
+
+       if (si == NULL || si->image == NULL)
+               return;
+
+       wl_array_init(&options);
+
+       b = bundle_create();
+       if (b == NULL) {
+               _E("out of memory");
+               return;
+       }
+
+       bundle_add(b, AUL_K_APPID, si->appid);
+       ret = bundle_encode(b, &raw_data, &len);
+       if (ret != BUNDLE_ERROR_NONE) {
+               _E("Failed to encode bundle");
+               bundle_free(b);
+               return;
+       }
+       bundle_free(b);
+
+       size = strlen((const char *)raw_data);
+       data = wl_array_add(&options, size + 1);
+       memcpy(data, raw_data, size + 1);
+       free(raw_data);
+
+       _D("src(%s), type(%d), color-depth(%d), rotation(%d), " \
+                       "indicator(%d), effect_type(%s)",
+                       si->src, si->type, si->color_depth, si->rotation,
+                       si->indicator, si->effect_type);
+       tizen_launch_splash_launch(si->image, si->src, si->type,
+                       si->color_depth, si->rotation, si->indicator,
+                       si->effect_type, si->theme_type, &options);
+       wl_display_flush(display);
+
+       wl_array_release(&options);
+}
+
+void _splash_screen_send_pid(splash_image_h si, int pid)
+{
+       if (si == NULL)
+               return;
+
+       si->pid = pid;
+       tizen_launch_splash_owner(si->image, pid);
+       wl_display_flush(display);
+}
+
+void _splash_screen_set_effect_type(int pid, const char *appid, bool is_subapp)
+{
+       struct wl_array options;
+       bundle *b;
+       bundle_raw *raw_data = NULL;
+       int len = 0;
+       int ret;
+       size_t size;
+       void *data;
+       const char *effect_type;
+
+       if (!splash_screen_initialized)
+               return;
+
+       wl_array_init(&options);
+
+       if (is_subapp)
+               effect_type = "depth-in";
+       else
+               effect_type = "launch";
+
+       b = bundle_create();
+       if (b == NULL) {
+               _E("out of memory");
+               return;
+       }
+
+       bundle_add(b, AUL_K_APPID, appid);
+       ret = bundle_encode(b, &raw_data, &len);
+       if (ret != BUNDLE_ERROR_NONE) {
+               _E("Failed to encode bundle");
+               bundle_free(b);
+               return;
+       }
+       bundle_free(b);
+
+       size = strlen((const char *)raw_data);
+       data = wl_array_add(&options, size + 1);
+       memcpy(data, raw_data, size + 1);
+       free(raw_data);
+
+       _D("effect_type(%s), pid(%d)", effect_type, pid);
+       tizen_launch_effect_type_set(tz_launch_effect, effect_type,
+                       pid, &options);
+       wl_display_flush(display);
+
+       wl_array_release(&options);
+}
+
+static void __wl_listener_cb(void *data, struct wl_registry *registry,
+               unsigned int id, const char *interface, unsigned int version)
+{
+       if (interface && strcmp(interface, "tizen_launch_effect") == 0) {
+               _D("interface: %s", interface);
+               if (!tz_launch_effect) {
+                       tz_launch_effect = wl_registry_bind(registry, id,
+                                       &tizen_launch_effect_interface, 1);
+               }
+       }
+}
+
+static void __wl_listener_remove_cb(void *data, struct wl_registry *registry,
+               unsigned int id)
+{
+       if (tz_launch_effect) {
+               tizen_launch_effect_destroy(tz_launch_effect);
+               tz_launch_effect = NULL;
+       }
+}
+
+static struct wl_registry_listener registry_listener = {
+       __wl_listener_cb,
+       __wl_listener_remove_cb
+};
+
+static int __init_splash_screen(void)
+{
+       if (!display) {
+               display = _wayland_get_display();
+               if (!display) {
+                       _E("Failed to get display");
+                       return -1;
+               }
+       }
+
+       if (!tz_launch_effect) {
+               _E("Failed to bind tizen launch screen");
+               return -1;
+       }
+
+       splash_screen_initialized = 1;
+
+       return 0;
+}
+
+#ifdef TIZEN_FEATURE_AUTO_ROTATION
+static void __rotation_changed_cb(sensor_t sensor, unsigned int event_type,
+               sensor_data_t *data, void *user_data)
+{
+       int event;
+
+       if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT)
+               return;
+
+       event = (int)data->values[0];
+       switch (event) {
+       case AUTO_ROTATION_DEGREE_0:
+               rotation.angle = 0;
+               break;
+       case AUTO_ROTATION_DEGREE_90:
+               rotation.angle = 90;
+               break;
+       case AUTO_ROTATION_DEGREE_180:
+               rotation.angle = 180;
+               break;
+       case AUTO_ROTATION_DEGREE_270:
+               rotation.angle = 270;
+               break;
+       default:
+               break;
+       }
+
+       _D("angle: %d", rotation.angle);
+}
+
+static void __auto_rotate_screen_cb(keynode_t *key, void *data)
+{
+       rotation.auto_rotate = vconf_keynode_get_bool(key);
+       if (!rotation.auto_rotate) {
+               _D("auto_rotate: %d, angle: %d",
+                               rotation.auto_rotate, rotation.angle);
+       }
+}
+#endif /* TIZEN_FEATURE_AUTO_ROTATION */
+
+static int __init_rotation(void)
+{
+#ifdef TIZEN_FEATURE_AUTO_ROTATION
+       int ret;
+       bool r;
+       sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
+
+       rotation.angle = 0;
+       rotation.handle = sensord_connect(sensor);
+       if (rotation.handle < 0) {
+               _W("Failed to connect sensord");
+               return -1;
+       }
+
+       r = sensord_register_event(rotation.handle,
+                       AUTO_ROTATION_CHANGE_STATE_EVENT,
+                       SENSOR_INTERVAL_NORMAL,
+                       0,
+                       __rotation_changed_cb,
+                       NULL);
+       if (!r) {
+               _W("Failed to register event");
+               sensord_disconnect(rotation.handle);
+               return -1;
+       }
+
+       r = sensord_start(rotation.handle, 0);
+       if (!r) {
+               _W("Failed to start sensord");
+               sensord_unregister_event(rotation.handle,
+                               AUTO_ROTATION_CHANGE_STATE_EVENT);
+               sensord_disconnect(rotation.handle);
+               return -1;
+       }
+
+       ret = vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL,
+                       &rotation.auto_rotate);
+       if (ret != VCONF_OK)
+               rotation.auto_rotate = false;
+
+       ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL,
+                       __auto_rotate_screen_cb, NULL);
+       if (ret != 0) {
+               _W("Failed to register callback for %s",
+                               VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL);
+       }
+#endif /* TIZEN_FEATURE_AUTO_ROTATION */
+       rotation_initialized = 1;
+
+       return 0;
+}
+
+static void __destroy_image_info(struct image_info_s *info)
+{
+       if (info == NULL)
+               return;
+
+       if (info->color_depth)
+               free(info->color_depth);
+       if (info->indicator_display)
+               free(info->indicator_display);
+       if (info->type)
+               free(info->type);
+       if (info->orientation)
+               free(info->orientation);
+       if (info->file)
+               free(info->file);
+       if (info->name)
+               free(info->name);
+       free(info);
+}
+
+struct image_info_s *__create_image_info(void)
+{
+       struct image_info_s *info;
+
+       info = (struct image_info_s *)calloc(1, sizeof(struct image_info_s));
+       if (info == NULL) {
+               _E("out of memory");
+               return NULL;
+       }
+
+       return info;
+}
+
+static int __validate_image_info(struct image_info_s *info)
+{
+       if (info == NULL)
+               return -1;
+
+       if (info->name == NULL ||
+                       info->file == NULL ||
+                       info->orientation == NULL)
+               return -1;
+
+       if (info->type == NULL) {
+               if (strstr(info->file, "edj"))
+                       info->type = strdup("edj");
+               else
+                       info->type = strdup("img");
+       }
+
+       if (info->indicator_display == NULL)
+               info->indicator_display = strdup("true");
+
+       if (info->color_depth == NULL)
+               info->color_depth = strdup("24");
+
+       return 0;
+}
+
+static void __parse_file(const char *file)
+{
+       FILE *fp;
+       char buf[LINE_MAX];
+       char tok1[LINE_MAX];
+       char tok2[LINE_MAX];
+       struct image_info_s *info = NULL;
+
+       fp = fopen(file, "rt");
+       if (fp == NULL)
+               return;
+
+       while (fgets(buf, sizeof(buf), fp) != NULL) {
+               tok1[0] = '\0';
+               tok2[0] = '\0';
+               sscanf(buf, "%s %s", tok1, tok2);
+
+               if (strcasecmp(TAG_SPLASH_IMAGE, tok1) == 0) {
+                       if (info) {
+                               if (__validate_image_info(info) < 0) {
+                                       __destroy_image_info(info);
+                               } else {
+                                       default_image_list = g_list_append(
+                                                       default_image_list,
+                                                       info);
+                               }
+                       }
+                       info = __create_image_info();
+                       continue;
+               }
+
+               if (tok1[0] == '\0' || tok2[0] == '\0' || info == NULL)
+                       continue;
+
+               if (strcasecmp(TAG_NAME, tok1) == 0)
+                       info->name = strdup(tok2);
+               else if (strcasecmp(TAG_FILE, tok1) == 0)
+                       info->file = strdup(tok2);
+               else if (strcasecmp(TAG_TYPE, tok1) == 0)
+                       info->type = strdup(tok2);
+               else if (strcasecmp(TAG_ORIENTATION, tok1) == 0)
+                       info->orientation = strdup(tok2);
+               else if (strcasecmp(TAG_INDICATOR_DISPLAY, tok1) == 0)
+                       info->indicator_display = strdup(tok2);
+               else if (strcasecmp(TAG_COLOR_DEPTH, tok1) == 0)
+                       info->color_depth = strdup(tok2);
+       }
+
+       if (info) {
+               if (__validate_image_info(info) < 0) {
+                       __destroy_image_info(info);
+               } else {
+                       default_image_list = g_list_append(default_image_list,
+                                       info);
+               }
+       }
+
+       fclose(fp);
+}
+
+static int __load_splash_screen_info(const char *path)
+{
+       DIR *dp;
+       struct dirent entry;
+       struct dirent *result = NULL;
+       char *ext;
+       char buf[PATH_MAX];
+
+       dp = opendir(path);
+       if (dp == NULL)
+               return -1;
+
+       while (readdir_r(dp, &entry, &result) == 0 && result != NULL) {
+               if (entry.d_name[0] == '.')
+                       continue;
+
+               ext = strrchr(entry.d_name, '.');
+               if (ext && !strcmp(ext, ".conf")) {
+                       snprintf(buf, sizeof(buf), "%s/%s", path, entry.d_name);
+                       __parse_file(buf);
+               }
+       }
+
+       closedir(dp);
+
+       return 0;
+}
+
+int _splash_screen_init(void)
+{
+       _D("init splash screen");
+
+       __load_splash_screen_info(SPLASH_SCREEN_INFO_PATH);
+       _wayland_add_registry_listener(&registry_listener, NULL);
+
+       if (__init_rotation() < 0)
+               _W("Failed to initialize rotation");
+
+       return 0;
+}
+
diff --git a/src/amd_suspend.c b/src/amd_suspend.c
new file mode 100644 (file)
index 0000000..c153c2d
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <aul.h>
+#include <aul_sock.h>
+#include <bundle_internal.h>
+
+#include "amd_signal.h"
+#include "amd_util.h"
+#include "amd_suspend.h"
+#include "amd_app_status.h"
+
+typedef struct proc_info {
+       pid_t pid;
+       guint timer_id;
+} proc_info_t;
+
+static GHashTable *proc_info_tbl;
+
+static void __destroy_proc_info_value(gpointer data)
+{
+       proc_info_t *proc = (proc_info_t *)data;
+
+       if (proc)
+               free(proc);
+}
+
+static void __prepare_to_suspend(int pid, uid_t uid)
+{
+       int ret;
+       int dummy;
+
+       _D("[__SUSPEND__] pid: %d, uid: %d", pid, uid);
+       ret = aul_sock_send_raw(pid, uid, APP_SUSPEND, (unsigned char *)&dummy,
+                       sizeof(int), AUL_SOCK_NOREPLY);
+       if (ret < 0)
+               _E("Failed to send APP_SUSPEND %d", pid);
+}
+
+static void __prepare_to_wake(int pid, uid_t uid)
+{
+       int ret;
+       bundle *kb;
+
+       kb = bundle_create();
+       if (kb == NULL) {
+               _E("out of memory");
+               return;
+       }
+
+       bundle_add(kb, AUL_K_ALLOWED_BG, "ALLOWED_BG");
+
+       _D("[__SUSPEND__] pid: %d, uid: %d", pid, uid);
+       ret = aul_sock_send_bundle(pid, uid, APP_WAKE, kb, AUL_SOCK_NOREPLY);
+       if (ret != AUL_R_OK)
+               _E("Failed to send APP_WAKE %d", pid);
+
+       bundle_free(kb);
+}
+
+static void __wake_bg_apps(app_status_h app_status, void *data)
+{
+       const char *appid;
+       int status;
+       uid_t uid;
+       const struct appinfo *ai;
+       int target_category;
+       int bg_category;
+       bool bg_allowed;
+       int pid;
+
+       if (app_status == NULL)
+               return;
+
+       status = _app_status_get_status(app_status);
+       if (status != STATUS_BG && status != STATUS_SERVICE)
+               return;
+
+       appid = _app_status_get_appid(app_status);
+       uid = _app_status_get_uid(app_status);
+       pid = _app_status_get_pid(app_status);
+
+       ai = _appinfo_find(uid, appid);
+       if (ai == NULL)
+               return;
+
+       if (data) {
+               target_category = GPOINTER_TO_INT(data);
+               bg_category = (intptr_t)_appinfo_get_value(ai, AIT_BG_CATEGORY);
+               if (bg_category != target_category)
+                       return;
+       } else {
+               bg_allowed = _suspend_is_allowed_background(ai);
+               if (bg_allowed == true)
+                       return;
+       }
+
+       _D("[__SUSPEND__] Wake %s %d", appid, pid);
+       _suspend_remove_timer(pid);
+       __prepare_to_wake(pid, uid);
+       _app_status_find_service_apps(app_status, status,
+                       __prepare_to_wake, false);
+       aul_update_freezer_status(pid, "exclude");
+}
+
+static void __suspend_bg_apps(app_status_h app_status, void *data)
+{
+       const char *appid;
+       int status;
+       uid_t uid;
+       const struct appinfo *ai;
+       int target_category;
+       int bg_category;
+       bool bg_allowed;
+       int pid;
+
+       if (app_status == NULL)
+               return;
+
+       status = _app_status_get_status(app_status);
+       if (status != STATUS_BG && status != STATUS_SERVICE)
+               return;
+
+       appid = _app_status_get_appid(app_status);
+       uid = _app_status_get_uid(app_status);
+       pid = _app_status_get_pid(app_status);
+
+       ai = _appinfo_find(uid, appid);
+       if (ai == NULL)
+               return;
+
+       if (data) {
+               target_category = GPOINTER_TO_INT(data);
+               bg_category = (intptr_t)_appinfo_get_value(ai, AIT_BG_CATEGORY);
+               if (bg_category != target_category)
+                       return;
+       } else {
+               bg_allowed = _suspend_is_allowed_background(ai);
+               if (bg_allowed == true)
+                       return;
+       }
+
+       _D("[__SUSPEND__] Suspend %s %d", appid, pid);
+       _app_status_find_service_apps(app_status, status,
+                       __prepare_to_suspend, true);
+       __prepare_to_suspend(pid, uid);
+       _suspend_add_timer(pid, ai);
+       aul_update_freezer_status(pid, "include");
+}
+
+void _suspend_init(void)
+{
+       if (!proc_info_tbl) {
+               proc_info_tbl = g_hash_table_new_full(g_direct_hash,
+                               g_direct_equal, NULL,
+                               __destroy_proc_info_value);
+       }
+
+       _D("_amd_proc_init done");
+}
+
+void _suspend_fini(void)
+{
+       g_hash_table_destroy(proc_info_tbl);
+       _D("_amd_proc_fini done");
+}
+
+proc_info_t *__create_proc_info(int pid)
+{
+       proc_info_t *proc;
+
+       if (pid < 1) {
+               _E("invalid pid");
+               return NULL;
+       }
+
+       proc = (proc_info_t *)malloc(sizeof(proc_info_t));
+       if (proc == NULL) {
+               _E("insufficient memory");
+               return NULL;
+       }
+
+       proc->pid = pid;
+       proc->timer_id = 0;
+
+       return proc;
+}
+
+proc_info_t *__find_proc_info(int pid)
+{
+       proc_info_t *proc;
+
+       if (pid < 1) {
+               _E("invalid pid");
+               return NULL;
+       }
+
+       proc = (proc_info_t *)g_hash_table_lookup(proc_info_tbl,
+                       GINT_TO_POINTER(pid));
+       if (proc == NULL) {
+               _E("proc info not found");
+               return NULL;
+       }
+
+       return proc;
+}
+
+int __add_proc_info(proc_info_t *proc)
+{
+       if (proc == NULL) {
+               _E("invalid proc info");
+               return -1;
+       }
+
+       if (proc->pid < 1) {
+               _E("invalid pid");
+               return -1;
+       }
+
+       g_hash_table_insert(proc_info_tbl, GINT_TO_POINTER(proc->pid), proc);
+
+       return 0;
+}
+
+int _suspend_add_proc(int pid)
+{
+       proc_info_t *proc;
+
+       proc = __create_proc_info(pid);
+       if (proc)
+               return __add_proc_info(proc);
+
+       return -1;
+}
+
+int _suspend_remove_proc(int pid)
+{
+       proc_info_t *proc;
+
+       if (pid < 1) {
+               _E("invalid pid");
+               return -1;
+       }
+
+       proc = (proc_info_t *)g_hash_table_lookup(proc_info_tbl,
+                       GINT_TO_POINTER(pid));
+       if (proc == NULL) {
+               _E("proc info not found");
+               return -1;
+       }
+
+       g_hash_table_remove(proc_info_tbl, GINT_TO_POINTER(pid));
+
+       return 0;
+}
+
+static gboolean __send_suspend_hint(gpointer data)
+{
+       proc_info_t *proc;
+       int pid = GPOINTER_TO_INT(data);
+
+       proc = __find_proc_info(pid);
+       if (proc && proc->timer_id > 0) {
+               _signal_send_proc_suspend(pid);
+               proc->timer_id = 0;
+       }
+
+       return FALSE;
+}
+
+bool _suspend_is_allowed_background(const struct appinfo *ai)
+{
+       int bg_category;
+       const char *comp_type;
+
+       comp_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (comp_type == NULL)
+               return false;
+
+       if (strcmp(comp_type, APP_TYPE_UI) != 0 &&
+                       strcmp(comp_type, APP_TYPE_SERVICE) != 0)
+               return true;
+
+       /*
+        * 2.4 bg-categorized (uiapp || svcapp) || watch || widget -> bg allowed
+        * 2.3 uiapp -> not allowed, 2.3 svcapp -> bg allowed
+        */
+       bg_category = (intptr_t)_appinfo_get_value(ai, AIT_BG_CATEGORY);
+       if (bg_category)
+               return true;
+
+       return false;
+}
+
+void _suspend_add_timer(int pid, const struct appinfo *ai)
+{
+       bool bg_allowed;
+       proc_info_t *proc;
+
+       bg_allowed = _suspend_is_allowed_background(ai);
+       if (bg_allowed)
+               return;
+
+       proc = __find_proc_info(pid);
+       if (proc == NULL) {
+               proc = __create_proc_info(pid);
+               if (proc)
+                       __add_proc_info(proc);
+       }
+
+       if (proc) {
+               proc->timer_id = g_timeout_add_seconds(10, __send_suspend_hint,
+                               GINT_TO_POINTER(pid));
+       }
+}
+
+void _suspend_remove_timer(int pid)
+{
+       proc_info_t *proc;
+
+       proc = __find_proc_info(pid);
+       if (proc && proc->timer_id > 0) {
+               g_source_remove(proc->timer_id);
+               proc->timer_id = 0;
+       }
+}
+
+int _suspend_update_status(int pid, int status)
+{
+       app_status_h app_status;
+
+       if (pid < 0)
+               return -1;
+
+       app_status = _app_status_find(pid);
+       if (app_status == NULL)
+               return -1;
+
+       if (status == SUSPEND_STATUS_EXCLUDE) {
+               __wake_bg_apps(app_status, NULL);
+       } else if (status == SUSPEND_STATUS_INCLUDE) {
+               __suspend_bg_apps(app_status, NULL);
+       } else {
+               _E("Unknown status(%d)", status);
+               return -1;
+       }
+       _D("[__SUSPEND__] pid(%d), status(%d)", pid, status);
+
+       return 0;
+}
diff --git a/src/amd_util.c b/src/amd_util.c
new file mode 100644 (file)
index 0000000..b3462dc
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <vconf.h>
+#include <aul.h>
+
+#include "amd_util.h"
+#include "amd_widget.h"
+#include "amd_app_status.h"
+
+#define AMD_LOG_BUFFER_SIZE 10000
+#define AMD_LOG_BUFFER_STRING_SIZE 128
+#define AMD_LOG_FILE "/run/aul/log/amd.log"
+
+static int log_index;
+static int log_fd;
+
+int _util_save_log(const char *tag, const char *message)
+{
+       int ret;
+       int offset;
+       time_t now;
+       char time_buf[32] = {0,};
+       char buffer[AMD_LOG_BUFFER_STRING_SIZE];
+       char err_buf[1024];
+
+       if (log_fd < 0) {
+               _E("error in opening the file: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               return -1;
+       }
+
+       time(&now);
+       ctime_r(&now, time_buf);
+       if (log_index != 0)
+               offset = lseek(log_fd, 0, SEEK_CUR);
+       else
+               offset = lseek(log_fd, 0, SEEK_SET);
+
+       if (offset == -1)
+               _E("error in lseek: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+
+       snprintf(buffer, sizeof(buffer), "[%-6d] %-15s %-50s %s",
+                       log_index, tag, message, time_buf);
+
+       ret = write(log_fd, buffer, strlen(buffer));
+       if (ret < 0) {
+               _E("Cannot write the amd log: %d", ret);
+               return -1;
+       }
+
+       if (++log_index >= AMD_LOG_BUFFER_SIZE)
+               log_index = 0;
+
+       return 0;
+}
+
+static void __low_mem_key_changed_cb(keynode_t *node, void *data)
+{
+       int status;
+
+       if (vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status) < 0)
+               return;
+
+       _D("mem status changed %d(normal:%d)",
+                       status, VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
+       if (status == VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
+               _widget_restart_faulted();
+               _app_status_send_fault_dead_for_oom_apps();
+       }
+}
+
+bool _util_check_oom(void)
+{
+       int ret;
+       int status;
+
+       ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
+       if (ret == 0 && status >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) {
+               _W("low memory");
+               return true;
+       }
+
+       return false;
+}
+
+static int __init_log(void)
+{
+       int offset;
+       char err_buf[1024];
+
+       log_fd = open(AMD_LOG_FILE, O_CREAT | O_WRONLY, 0644);
+       if (log_fd < 0) {
+               _E("error in opening the file: %s",
+                               strerror_r(errno, err_buf, sizeof(err_buf)));
+               return -1;
+       }
+
+       offset = lseek(log_fd, 0, SEEK_END);
+       if (offset != 0) {
+               log_index = (int)(offset / AMD_LOG_BUFFER_STRING_SIZE);
+               if (log_index >= AMD_LOG_BUFFER_SIZE) {
+                       log_index = 0;
+                       lseek(log_fd, 0, SEEK_SET);
+               }
+       }
+
+       return 0;
+}
+
+int _util_init(void)
+{
+       if (__init_log() < 0)
+               return -1;
+
+       if (vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY,
+               __low_mem_key_changed_cb, NULL) < 0) {
+               _E("vconf initialize failed.");
+               return -1;
+       }
+
+       return 0;
+}
+
+void _util_fini(void)
+{
+       if (log_fd > 0)
+               close(log_fd);
+
+       vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY,
+                       (vconf_callback_fn) __low_mem_key_changed_cb);
+}
diff --git a/src/amd_wayland.c b/src/amd_wayland.c
new file mode 100644 (file)
index 0000000..3b58df6
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <wayland-client.h>
+#include <wayland-tbm-client.h>
+#include <tizen-extension-client-protocol.h>
+
+#include "amd_util.h"
+#include "amd_wayland.h"
+#include "amd_inotify.h"
+
+#define PATH_RUN_WAYLAND "/run/wayland-0"
+#define PATH_RUN_WMREADY "/run/.wm_ready"
+#define PATH_RUN "/run"
+
+struct wl_listener {
+       struct wl_registry_listener *registry_listener;
+       void *data;
+};
+
+static bool wl_ready;
+static bool wm_ready;
+static bool wl_initialized;
+static struct wl_display *display;
+static struct wl_registry *registry;
+static GList *wl_list;
+static int __wd;
+
+static void __init_wl(void);
+
+int _wayland_add_registry_listener(
+               struct wl_registry_listener *registry_listener,
+               void *data)
+{
+       struct wl_listener *listener;
+
+       if (registry_listener == NULL)
+               return -1;
+
+       listener = (struct wl_listener *)calloc(1, sizeof(struct wl_listener));
+       if (listener == NULL) {
+               _E("out of memory");
+               return -1;
+       }
+
+       listener->registry_listener = registry_listener;
+       listener->data = data;
+
+       wl_list = g_list_append(wl_list, listener);
+
+       return 0;
+}
+
+struct wl_display *_wayland_get_display(void)
+{
+       if (!display && wl_initialized)
+               __init_wl();
+
+       return display;
+}
+
+static void __wl_listener_cb(void *data, struct wl_registry *reg,
+               unsigned int id, const char *interface, unsigned int version)
+{
+       GList *iter;
+       struct wl_listener *listener;
+
+       for (iter = g_list_first(wl_list); iter; iter = g_list_next(iter)) {
+               listener = (struct wl_listener *)iter->data;
+               if (listener && listener->registry_listener &&
+                               listener->registry_listener->global) {
+                       listener->registry_listener->global(listener->data,
+                                       reg, id, interface, version);
+               }
+       }
+}
+
+static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
+               unsigned int id)
+{
+       GList *iter;
+       struct wl_listener *listener;
+
+       iter = g_list_first(wl_list);
+       while (iter) {
+               listener = (struct wl_listener *)iter->data;
+               if (listener && listener->registry_listener &&
+                               listener->registry_listener->global_remove) {
+                       listener->registry_listener->global_remove(
+                                       listener->data, reg, id);
+               }
+
+               iter = g_list_next(iter);
+               wl_list = g_list_remove(wl_list, listener);
+               free(listener);
+       }
+}
+
+
+static const struct wl_registry_listener registry_listener = {
+       __wl_listener_cb,
+       __wl_listener_remove_cb
+};
+
+static void __init_wl(void)
+{
+       display = wl_display_connect(NULL);
+       if (display == NULL) {
+               _E("Failed to connect wayland display");
+               return;
+       }
+
+       registry = wl_display_get_registry(display);
+       if (registry == NULL) {
+               _E("Failed to get wayland registry");
+               wl_display_disconnect(display);
+               display = NULL;
+               return;
+       }
+
+       wl_registry_add_listener(registry, &registry_listener, NULL);
+       wl_display_flush(display);
+       wl_display_roundtrip(display);
+}
+
+static bool __wayland_monitor_cb(const char *event_name, void *data)
+{
+       if (event_name == NULL)
+               return true;
+
+       if (strcmp(event_name, "wayland-0") == 0) {
+               _D("%s is created", event_name);
+               wl_ready = true;
+       } else if (strcmp(event_name, ".wm_ready") == 0) {
+               _D("%s is created", event_name);
+               wm_ready = true;
+       }
+
+       if (wm_ready && wl_ready) {
+               wl_initialized = true;
+               __init_wl();
+               __wd = 0;
+               return false;
+       }
+
+       return true;
+}
+
+int _wayland_init(void)
+{
+       _D("wayland init");
+
+       if (access(PATH_RUN_WAYLAND, F_OK) == 0) {
+               _D("%s exists", PATH_RUN_WAYLAND);
+               wl_ready = true;
+       }
+
+       if (access(PATH_RUN_WMREADY, F_OK) == 0) {
+               _D("%s exists", PATH_RUN_WMREADY);
+               wm_ready = true;
+       }
+
+       if (wl_ready && wm_ready) {
+               wl_initialized = true;
+               __init_wl();
+               return 0;
+       }
+
+       __wd = _inotify_add_watch(PATH_RUN, IN_CREATE,
+                       __wayland_monitor_cb, NULL);
+       if (__wd < 0) {
+               _E("Failed to add inotify watch");
+               return -1;
+       }
+
+       return 0;
+}
+
+void _wayland_finish(void)
+{
+       _D("wayland finish");
+
+       if (__wd > 0)
+               _inotify_rm_watch(__wd);
+
+       if (registry) {
+               wl_registry_destroy(registry);
+               registry = NULL;
+       }
+
+       if (display) {
+               wl_display_disconnect(display);
+               display = NULL;
+       }
+}
diff --git a/src/amd_widget.c b/src/amd_widget.c
new file mode 100644 (file)
index 0000000..c9cb5c3
--- /dev/null
@@ -0,0 +1,980 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+#define _GNU_SOURCE
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <aul.h>
+#include <aul_sock.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+
+#include "amd_app_com.h"
+#include "amd_request.h"
+#include "amd_util.h"
+#include "amd_launch.h"
+#include "amd_widget.h"
+#include "amd_app_status.h"
+#include "amd_screen_connector.h"
+#include "amd_socket.h"
+
+#ifndef AUL_K_WIDGET_OPERATION
+#define AUL_K_WIDGET_OPERATION "__WIDGET_OP__"
+#endif
+
+#ifndef AUL_K_WIDGET_FORCE
+#define AUL_K_WIDGET_FORCE "__WIDGET_FORCE__"
+#endif
+
+typedef struct _widget_t {
+       char *pkg_id;
+       char *widget_id;
+       int pid;
+       uid_t uid;
+       GList *instances;
+} widget_t;
+
+typedef struct _restart_widget_info{
+       int pid;
+       int uid;
+       char *widget_id;
+       int caller_pid;
+       char *pkgid;
+       guint timer;
+} restart_widget_info;
+
+struct widget_status_info {
+       const char *endpoint;
+       const char *widget_id;
+       const char *instance_id;
+       const char *pkg_id;
+       const char *is_fault;
+       int status;
+       int pid;
+       uid_t uid;
+};
+
+static GList *__widgets;
+static GList *__update_widgets;
+static GHashTable *__restart_widget_tbl;
+
+static int __send_status_info(struct widget_status_info *info)
+{
+       char buf[MAX_PID_STR_BUFSZ];
+       bundle *kb;
+       int r;
+
+       kb = bundle_create();
+       if (kb == NULL) {
+               _E("Out of memory");
+               return -1;
+       }
+
+       snprintf(buf, sizeof(buf), "%d", info->pid);
+       bundle_add(kb, AUL_K_COM_SENDER_PID, buf);
+       bundle_add(kb, AUL_K_WIDGET_ID, info->widget_id);
+       bundle_add_byte(kb, AUL_K_WIDGET_STATUS, &info->status, sizeof(int));
+
+       if (info->instance_id)
+               bundle_add(kb, AUL_K_WIDGET_INSTANCE_ID, info->instance_id);
+       if (info->pkg_id)
+               bundle_add(kb, AUL_K_PKGID, info->pkg_id);
+       if (info->is_fault)
+               bundle_add(kb, AUL_K_IS_FAULT, info->is_fault);
+
+       r = _app_com_send(info->endpoint, getpgid(info->pid), kb, info->uid);
+       bundle_free(kb);
+
+       return r;
+}
+
+static void __restart_faulted_widget(int pid, int uid, const char *appid,
+               const char *pkgid, int caller_pid)
+{
+       _W("restart widget pid %d uid %d appid %s caller_pid %d pkgid %s",
+                       pid, uid, appid, caller_pid, pkgid);
+       _widget_send_status_to_viewer(
+               pid,
+               uid,
+               appid,
+               caller_pid,
+               AUL_WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST);
+
+       _widget_send_dead_signal_for_faulted(
+               pid,
+               uid,
+               pkgid,
+               appid);
+}
+
+void _widget_restart_faulted()
+{
+       GHashTableIter iter;
+       gpointer key, value;
+       restart_widget_info *info;
+
+       g_hash_table_iter_init(&iter, __restart_widget_tbl);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               info = (restart_widget_info *)value;
+               __restart_faulted_widget(info->pid, info->uid, info->widget_id,
+                               info->pkgid, info->caller_pid);
+       }
+       g_hash_table_remove_all(__restart_widget_tbl);
+}
+
+static void __destroy_widget_info(gpointer data)
+{
+       restart_widget_info *info =
+                       (restart_widget_info *)data;
+
+       if (info == NULL)
+               return;
+       if (info->widget_id)
+               free(info->widget_id);
+       if (info->pkgid)
+               free(info->pkgid);
+       free(info);
+}
+
+static widget_t *__find_widget_by_pid(int pid, uid_t uid)
+{
+       GList *widget_list = __widgets;
+       widget_t *widget;
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               if (widget->pid == pid && widget->uid == uid)
+                       return widget;
+
+               widget_list = widget_list->next;
+       }
+
+       return NULL;
+}
+
+static char *__get_id_by_pid(int pid, uid_t uid)
+{
+       widget_t *widget;
+
+       widget = __find_widget_by_pid(pid, uid);
+       if (!widget)
+               return NULL;
+
+       return widget->widget_id;
+}
+
+void _widget_dead_handler(int pid, int uid,
+               const char *pkgid, int caller_pid, bool is_exit_notified,
+               bool can_restart)
+{
+       bool is_widget = false;
+       restart_widget_info *widget_info;
+       char *widget_id;
+
+       is_widget = _widget_exist(pid, uid);
+       if (!is_widget)
+               return;
+
+       widget_id = __get_id_by_pid(pid, uid);
+       _W("restart process start %s", widget_id);
+       if (!can_restart) {
+               if(!is_exit_notified) {
+                       _widget_send_dead_signal_for_faulted(
+                                       pid,
+                                       uid,
+                                       pkgid,
+                                       widget_id);
+               } else {
+                       _widget_send_dead_signal(pid, uid, pkgid);
+               }
+               return;
+       }
+
+       /* Restart fault widget logic start */
+       if (!is_exit_notified) {
+               /*
+                * Screen info should be removed before send dead signal
+                * If not, _app_status_cleanup will send
+                * AUL_SCREEN_CONNECTOR_EVENT_TYPE_REMOVE
+                * event to the viewer and recreated instance with same
+                * instance id info will be removed by
+                * AUL_SCREEN_CONNECTOR_EVENT_TYPE_REMOVE event.
+                */
+               _screen_connector_remove_app_screen_v2(pid, uid);
+               if (_util_check_oom()) {
+                       widget_info =
+                               g_hash_table_lookup(
+                                               __restart_widget_tbl,
+                                               widget_id);
+                       if (widget_info == NULL) {
+                               widget_info = (restart_widget_info *)
+                                               calloc(1, sizeof(restart_widget_info));
+                               widget_info->widget_id = strdup(widget_id);
+                               widget_info->pkgid = strdup(pkgid);
+                               widget_info->pid = pid;
+                               widget_info->uid = uid;
+                               widget_info->caller_pid = caller_pid;
+                               g_hash_table_insert(
+                                               __restart_widget_tbl,
+                                               widget_info->widget_id,
+                                               widget_info);
+                       }
+               } else {
+                       __restart_faulted_widget(pid, uid, widget_id,
+                                       pkgid,
+                                       caller_pid);
+               }
+       } else {
+               /*
+                * If widget package is in update process
+                * widget dead signal will be sent after
+                * update process is completed so that
+                * viewer can restart widget at that time.
+                */
+               if (_appinfo_is_pkg_updating(pkgid)) {
+                       _widget_send_status_to_viewer(pid, uid, widget_id,
+                                       caller_pid,
+                                       AUL_WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST);
+                       _widget_add_update_info(pkgid, pid, uid);
+               } else {
+                       /* Normal exit */
+                       _widget_send_dead_signal(pid, uid, pkgid);
+               }
+       }
+}
+
+static void __free_widget(gpointer data)
+{
+       widget_t *widget = (widget_t *)data;
+
+       free(widget->widget_id);
+       g_list_free_full(widget->instances, free);
+       free(widget);
+}
+
+static widget_t *__find_widget(const char *widget_id, int pid, uid_t uid)
+{
+       GList *widget_list = __widgets;
+       widget_t *widget;
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               if (strcmp(widget->widget_id, widget_id) == 0) {
+                       if (widget->pid == pid && widget->uid == uid)
+                               return widget;
+               }
+
+               widget_list = widget_list->next;
+       }
+
+       return NULL;
+}
+
+static widget_t *__find_instance(const char *widget_id, const char *instance_id)
+{
+       GList *widget_list = __widgets;
+       GList *instance_list;
+       widget_t *widget;
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               if (strcmp(widget->widget_id, widget_id) == 0
+                                               && widget->instances) {
+                       instance_list = g_list_find_custom(widget->instances,
+                                       instance_id, (GCompareFunc)g_strcmp0);
+
+                       if (instance_list)
+                               return widget;
+               }
+
+               widget_list = widget_list->next;
+       }
+
+       return NULL;
+}
+
+bool _widget_exist(int pid, uid_t uid)
+{
+       GList *widget_list = __widgets;
+       widget_t *widget;
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               if (widget->pid == pid && widget->uid == uid)
+                       return true;
+
+               widget_list = widget_list->next;
+       }
+       return false;
+}
+
+int _widget_send_status_to_viewer(int pid, uid_t uid, const char *widget_id,
+               int viewer_pid, aul_widget_instance_event_e status)
+{
+       app_status_h viewer_app_status;
+       struct widget_status_info info;
+
+       viewer_app_status = _app_status_find(viewer_pid);
+       if (viewer_app_status == NULL)
+               return -1;
+
+       info.endpoint = _app_status_get_appid(viewer_app_status);
+       info.widget_id = widget_id;
+       info.instance_id = NULL;
+       info.pkg_id = NULL;
+       info.is_fault = NULL;
+       info.status = status;
+       info.pid = pid;
+       info.uid = _app_status_get_uid(viewer_app_status);
+
+       return __send_status_info(&info);
+}
+
+int _widget_send_dead_signal(int pid, uid_t uid, const char *pkgid)
+{
+       widget_t *widget = NULL;
+       GList *widget_list = __widgets;
+       struct widget_status_info info;
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               if (widget->pid == pid && widget->uid == uid)
+                       break;
+               widget_list = widget_list->next;
+       }
+
+       if (!widget) {
+               _E("cannot find widget pid : %d, uid %d", pid, uid);
+               return -1;
+       }
+
+       info.endpoint = "widget.status";
+       info.widget_id = widget->widget_id;
+       info.instance_id = NULL;
+       info.pkg_id = pkgid;
+       info.is_fault = "false";
+       info.status = AUL_WIDGET_LIFE_CYCLE_EVENT_APP_DEAD;
+       info.pid = pid;
+       info.uid = uid;
+
+       return __send_status_info(&info);
+}
+
+int _widget_send_dead_signal_for_faulted(int pid, uid_t uid,
+               const char *pkgid, const char *widget_id)
+{
+       struct widget_status_info info = {
+               .endpoint = "widget.status",
+               .widget_id = widget_id,
+               .instance_id = NULL,
+               .pkg_id = pkgid,
+               .is_fault = "true",
+               .status = AUL_WIDGET_LIFE_CYCLE_EVENT_APP_DEAD,
+               .pid = pid,
+               .uid = uid
+       };
+
+       return __send_status_info(&info);
+}
+
+int _widget_send_dead_signal_for_update_widget(const char *pkgid)
+{
+       widget_t *widget = NULL;
+       GList *widget_list = __update_widgets;
+       struct widget_status_info info;
+       int r;
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               if (strcmp(pkgid, widget->pkg_id) == 0)
+                       break;
+               widget_list = widget_list->next;
+       }
+
+       if (!widget) {
+               _E("cannot find update widget pkgid : %s", pkgid);
+               return -1;
+       }
+
+       __update_widgets = g_list_remove(__update_widgets, widget);
+
+       info.endpoint = "widget.status";
+       info.widget_id = widget->widget_id;
+       info.instance_id = NULL;
+       info.pkg_id = pkgid;
+       info.is_fault = "true";
+       info.status = AUL_WIDGET_LIFE_CYCLE_EVENT_APP_DEAD;
+       info.pid = widget->pid;
+       info.uid = widget->uid;
+
+       r = __send_status_info(&info);
+
+       if (widget->widget_id)
+               free(widget->widget_id);
+       if (widget->pkg_id)
+               free(widget->pkg_id);
+       free(widget);
+
+       return r;
+}
+
+int _widget_add_update_info(const char *pkg_id, int pid, uid_t uid)
+{
+       widget_t *widget;
+       widget_t *target_widget = NULL;
+       GList *widget_list = __widgets;
+
+       if (!pkg_id)
+               return -1;
+
+       while (widget_list) {
+               target_widget = (widget_t *)widget_list->data;
+               if (target_widget->pid == pid && target_widget->uid == uid)
+                       break;
+               widget_list = widget_list->next;
+       }
+       if (!target_widget) {
+               _E("cannot find target_widget pid : %d, uid %d", pid, uid);
+               return -1;
+       }
+
+       widget = (widget_t *)calloc(1, sizeof(widget_t));
+       if (!widget) {
+               _E("out of memory");
+               return -1;
+       }
+
+       widget->widget_id = strdup(target_widget->widget_id);
+       widget->uid = uid;
+       widget->pid = pid;
+       widget->pkg_id = strdup(pkg_id);
+       __update_widgets = g_list_append(__update_widgets, widget);
+
+       _D("update widget instance added: %s - %s (%d:%d)", widget->widget_id, pkg_id,
+                                                               uid, pid);
+       return 0;
+}
+
+
+int _widget_add(const char *widget_id, const char *instance_id,
+               int pid, uid_t uid)
+{
+       widget_t *widget;
+       char *id;
+
+       if (!widget_id || !instance_id)
+               return -1;
+
+       id = strdup(instance_id);
+       if (!id) {
+               _E("out of memory");
+               return -1;
+       }
+
+       widget = __find_widget(widget_id, pid, uid);
+       if (!widget) {
+               widget = __find_instance(widget_id, instance_id);
+               if (!widget) {
+                       widget = (widget_t *)calloc(1, sizeof(widget_t));
+                       if (!widget) {
+                               _E("out of memory");
+                               free(id);
+                               return -1;
+                       }
+                       widget->widget_id = strdup(widget_id);
+                       widget->uid = uid;
+                       __widgets = g_list_append(__widgets, widget);
+               }
+               widget->pid = pid;
+       }
+       if (__find_instance(widget_id, instance_id) == NULL)
+               widget->instances = g_list_append(widget->instances, id);
+       else
+               free(id);
+
+       _D("widget instance added: %s - %s (%d:%d)", widget_id, instance_id,
+                                                               uid, pid);
+       return 0;
+}
+
+int _widget_del(const char *widget_id, const char *instance_id)
+{
+       widget_t *widget;
+       GList *stored_list;
+
+       if (!widget_id || !instance_id)
+               return -1;
+
+       widget = __find_instance(widget_id, instance_id);
+       if (!widget)
+               return -1;
+       stored_list = g_list_find_custom(widget->instances, instance_id,
+                        (GCompareFunc)g_strcmp0);
+
+       if (stored_list) {
+               widget->instances = g_list_remove_link(widget->instances,
+                               stored_list);
+               free(stored_list->data);
+               g_list_free(stored_list);
+               _D("widget instace deleted: %s - %s (%d:%d)", widget->widget_id,
+                               instance_id, widget->uid, widget->pid);
+               return 0;
+       }
+
+       return -1;
+}
+
+int _widget_list(const char *widget_id, request_h req)
+{
+       bundle *rvalue;
+       widget_t *widget;
+       GList *widget_list = __widgets;
+       GList *instance_list;
+       char pid_buf[10];
+       int fd;
+
+       if (!widget_id)
+               return -1;
+
+       rvalue = bundle_create();
+       if (!rvalue) {
+               _E("out of memory");
+               return -1;
+       }
+
+       _D("start instance list");
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               if (strcmp(widget->widget_id, widget_id) == 0) {
+                       instance_list = widget->instances;
+                       snprintf(pid_buf, sizeof(pid_buf), "%d", widget->pid);
+                       while (instance_list) {
+                               _D("%s - %s", widget_id, instance_list->data);
+                               bundle_add_str(rvalue, instance_list->data,
+                                                               pid_buf);
+                               instance_list = instance_list->next;
+                       }
+               }
+               widget_list = widget_list->next;
+       }
+
+       _D("end instance list");
+
+       fd = _request_remove_fd(req);
+       aul_sock_send_bundle_with_fd(fd, 0, rvalue, AUL_SOCK_NOREPLY);
+
+       bundle_free(rvalue);
+
+       return 0;
+}
+
+static int __can_update_widget(bundle *kb, int pid)
+{
+       app_status_h widget_app_status;
+       const char *force;
+       int viewer_pid;
+       int focused_pid;
+
+       force = bundle_get_val(kb, AUL_K_WIDGET_FORCE);
+       if (force && strcmp(force, "true") == 0)
+               return 0;
+
+       widget_app_status = _app_status_find(pid);
+       if (widget_app_status == NULL)
+               return -EINVAL;
+
+       viewer_pid = _app_status_get_org_caller_pid(widget_app_status);
+       focused_pid = _launch_get_focused_pid();
+       if (viewer_pid != focused_pid) {
+               _D("The viewer app(%d) doesn't have focus", viewer_pid);
+               return -ECANCELED;
+       }
+
+       return 0;
+}
+
+int _widget_update(const char *widget_id, request_h req)
+{
+       char *instance_id = NULL;
+       char *appid = NULL;
+       bundle *kb = _request_get_bundle(req);
+       int ret = -1;
+       widget_t *widget;
+       GList *widget_list = __widgets;
+       bool dummy;
+       bool dummy_mode;
+       const char *operation;
+       bool update;
+       uid_t target_uid = _request_get_target_uid(req);
+
+       if (!kb || !widget_id) {
+               _request_send_result(req, -EINVAL);
+               return -1;
+       }
+
+       bundle_get_str(kb, AUL_K_APPID, &appid);
+       if (!appid) {
+               _E("missing appid:%s", widget_id);
+               _request_send_result(req, -EINVAL);
+               return -1;
+       }
+
+       operation = bundle_get_val(kb, AUL_K_WIDGET_OPERATION);
+       if (operation && strcmp(operation, "update") == 0)
+               update = true;
+       else
+               update = false;
+
+       bundle_get_str(kb, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
+       if (!instance_id) { /* all instances */
+               while (widget_list) {
+                       widget = (widget_t *)widget_list->data;
+                       widget_list = widget_list->next;
+                       if (strcmp(widget->widget_id, widget_id) == 0 &&
+                                       widget->uid == target_uid) {
+                               bundle_del(kb, AUL_K_TARGET_PID);
+                               bundle_add_byte(kb, AUL_K_TARGET_PID,
+                                               (void *)&widget->pid,
+                                               sizeof(widget->pid));
+
+                               if (update) {
+                                       ret = __can_update_widget(kb,
+                                                       widget->pid);
+                                       if (ret != 0) {
+                                               _W("Cannot update widget(%d)",
+                                                               widget->pid);
+                                               _request_send_result(req, ret);
+                                               continue;
+                                       }
+                               }
+
+                               ret = _launch_start_app(appid, req, &dummy,
+                                               &dummy_mode, false);
+                               _D("update widget: %s(%d)", widget->widget_id,
+                                                               widget->pid);
+                       }
+               }
+       } else {
+               widget = __find_instance(widget_id, instance_id);
+               if (widget) {
+                       bundle_del(kb, AUL_K_TARGET_PID);
+                       bundle_add_byte(kb, AUL_K_TARGET_PID,
+                               (void *)&widget->pid, sizeof(widget->pid));
+
+                       if (update) {
+                               ret = __can_update_widget(kb, widget->pid);
+                               if (ret != 0) {
+                                       _E("Cannot update widget");
+                                       _request_send_result(req, ret);
+                                       return ret;
+                               }
+                       }
+               }
+
+               ret = _launch_start_app(appid, req, &dummy, &dummy_mode, false);
+               _D("update widget: %s", widget_id);
+       }
+
+       return ret;
+}
+
+int _widget_cleanup(int pid, uid_t uid)
+{
+       GList *widget_list = __widgets;
+       widget_t *widget;
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               widget_list = widget_list->next;
+               if (widget->pid == pid && widget->uid == uid) {
+                       if (widget->instances)
+                               g_list_free_full(widget->instances, free);
+                       __widgets = g_list_remove(__widgets, widget);
+               }
+       }
+
+       _D("cleanup widget %d:%d", pid, uid);
+
+       return 0;
+}
+
+int _widget_get_pid(const char *widget_id, const char *instance_id)
+{
+       widget_t *widget;
+
+       widget = __find_instance(widget_id, instance_id);
+       if (!widget)
+               return -1;
+
+       return widget->pid;
+}
+
+int _widget_count(const char *widget_id, uid_t uid)
+{
+       widget_t *widget;
+       GList *widget_list = __widgets;
+       GList *instance_list;
+       int count = 0;
+
+       if (!widget_id)
+               return -1;
+
+       while (widget_list) {
+               widget = (widget_t *)widget_list->data;
+               _D("widget %s", widget->widget_id);
+               if (strcmp(widget->widget_id, widget_id) == 0 &&
+                               widget->uid == uid) {
+                       instance_list = widget->instances;
+                       if (instance_list)
+                               count += g_list_length(instance_list);
+                       _D("widget count %d", count);
+               }
+               widget_list = widget_list->next;
+       }
+
+       return count;
+}
+
+int _widget_verify_cmd(request_h req)
+{
+       bundle *kb = _request_get_bundle(req);
+       const char *command;
+       const char *instance_id;
+       const char *widget_id;
+       widget_t *widget;
+
+       if (!kb) {
+               _E("invalid argument");
+               return -1;
+       }
+
+       widget_id = bundle_get_val(kb, AUL_K_WIDGET_ID);
+       if (!widget_id)
+               return 0;
+
+       instance_id = bundle_get_val(kb, AUL_K_WIDGET_INSTANCE_ID);
+       if (!instance_id)
+               return 0;
+
+       command = bundle_get_val(kb, AUL_K_WIDGET_OPERATION);
+       if (!command)
+               return 0;
+
+       if (strcmp(command, "create") == 0)
+               return 0;
+
+       widget = __find_instance(widget_id, instance_id);
+       if (!widget) {
+               _E("invalid command: %s - target instance %s is not exist",
+                       command, instance_id);
+               return -EREJECTED;
+       }
+
+       return 0;
+}
+
+int _widget_init(void)
+{
+       _D("widget init");
+       __restart_widget_tbl =
+                       g_hash_table_new_full(g_str_hash, g_str_equal,
+                                       NULL, __destroy_widget_info);
+
+       return 0;
+}
+
+void _widget_fini(void)
+{
+       _D("widget fini");
+
+
+       if (__restart_widget_tbl) {
+               g_hash_table_destroy(__restart_widget_tbl);
+               __restart_widget_tbl = NULL;
+       }
+
+       if (__widgets)
+               g_list_free_full(__widgets, __free_widget);
+}
+
+void _widget_verify_instance(bundle *kb, int pid, uid_t uid)
+{
+       const char *operation;
+       const char *instance_id;
+       const char *widget_id;
+       widget_t *widget;
+       struct widget_status_info info;
+
+       if (kb == NULL)
+               return;
+
+       operation = bundle_get_val(kb, AUL_K_WIDGET_OPERATION);
+       if (operation == NULL)
+               return;
+
+       if (strcmp(operation, "create") != 0)
+               return;
+
+       widget_id = bundle_get_val(kb, AUL_K_WIDGET_ID);
+       if (widget_id == NULL)
+               return;
+
+       instance_id = bundle_get_val(kb, AUL_K_WIDGET_INSTANCE_ID);
+       if (instance_id == NULL)
+               return;
+
+       widget = __find_instance(widget_id, instance_id);
+       if (widget)
+               return;
+
+       info.endpoint = "widget.status";
+       info.widget_id = widget_id;
+       info.instance_id = instance_id;
+       info.pkg_id = NULL;
+       info.is_fault = NULL;
+       info.status = AUL_WIDGET_INSTANCE_EVENT_CREATE_ABORTED;
+       info.pid = pid;
+       info.uid = uid;
+
+       __send_status_info(&info);
+}
+
+static bundle *__create_bundle(widget_t *widget)
+{
+       char buf[MAX_PID_STR_BUFSZ];
+       app_status_h app_status;
+       bundle *b;
+
+       app_status = _app_status_find(widget->pid);
+       if (app_status == NULL)
+               return NULL;
+
+       b = bundle_create();
+       if (b == NULL) {
+               _E("Out of memory");
+               return NULL;
+       }
+
+       snprintf(buf, sizeof(buf), "%d", widget->pid);
+       bundle_add_str(b, AUL_K_PID, buf);
+       bundle_add_str(b, AUL_K_APPID, _app_status_get_appid(app_status));
+       bundle_add_str(b, AUL_K_PKGID, _app_status_get_pkgid(app_status));
+       bundle_add_str(b, AUL_K_EXEC, _app_status_get_app_path(app_status));
+       bundle_add_str(b, AUL_K_WIDGET_ID, widget->widget_id);
+
+       return b;
+}
+
+static int __send_running_info(widget_t *widget, int fd)
+{
+       char buf[MAX_PID_STR_BUFSZ];
+       const char *instance_id;
+       unsigned int surf;
+       bundle_raw *b_raw = NULL;
+       int len = 0;
+       GList *iter;
+       bundle *b;
+       int r;
+
+       b = __create_bundle(widget);
+       if (b == NULL) {
+               _E("Failed to create bundle");
+               aul_sock_send_raw_with_fd(fd, APP_GET_INFO_ERROR,
+                               NULL, 0, AUL_SOCK_NOREPLY);
+               return -1;
+       }
+
+       iter = widget->instances;
+       while (iter) {
+               instance_id = (const char *)iter->data;
+               surf = _screen_connector_get_surface_id(instance_id,
+                               widget->uid);
+               snprintf(buf, sizeof(buf), "%u", surf);
+               bundle_del(b, AUL_K_WID);
+               bundle_add_str(b, AUL_K_WID, buf);
+               bundle_del(b, AUL_K_WIDGET_INSTANCE_ID);
+               bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id);
+
+               bundle_encode(b, &b_raw, &len);
+               if (b_raw == NULL) {
+                       _E("Failed to encode bundle");
+                       aul_sock_send_raw_with_fd(fd, APP_GET_INFO_ERROR,
+                                       NULL, 0, AUL_SOCK_NOREPLY);
+                       bundle_free(b);
+                       return -1;
+               }
+
+               r = aul_sock_send_raw_with_fd(fd, APP_GET_INFO_OK,
+                               (unsigned char *)b_raw, len,
+                               AUL_SOCK_ASYNC | AUL_SOCK_BUNDLE);
+               if (r < 0) {
+                       _E("Failed to send raw data: %d", r);
+                       free(b_raw);
+                       bundle_free(b);
+                       return -1;
+               }
+               free(b_raw);
+               b_raw = NULL;
+
+               iter = g_list_next(iter);
+       }
+       free(b_raw);
+       bundle_free(b);
+
+       return 0;
+}
+
+int _widget_send_running_info(request_h req)
+{
+       uid_t target_uid = _request_get_target_uid(req);
+       int fd = _request_remove_fd(req);
+       widget_t *widget;
+       GList *iter;
+       int count = 0;
+       int r;
+
+       iter = __widgets;
+       while (iter) {
+               widget = (widget_t *)iter->data;
+               if (widget && widget->uid == target_uid)
+                       count += g_list_length(widget->instances);
+
+               iter = g_list_next(iter);
+       }
+
+       if (count == 0) {
+               _E("Widget doesn't exist");
+               _send_result_to_client(fd, -1);
+               return -1;
+       }
+       _send_result_to_client_v2(fd, count);
+
+       iter = __widgets;
+       while (iter) {
+               widget = (widget_t *)iter->data;
+               if (widget && widget->uid == target_uid) {
+                       r = __send_running_info(widget, fd);
+                       if (r < 0)
+                               break;
+               }
+               iter = g_list_next(iter);
+       }
+       close(fd);
+
+       return 0;
+}