4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
28 #include <sys/types.h>
32 #include <linux/limits.h>
39 #include "appcore-internal.h"
41 #define SQLITE_FLUSH_MAX (1024*1024)
43 #define PKGNAME_MAX 256
44 #define PATH_APP_ROOT "/opt/apps"
45 #define PATH_RES "/res"
46 #define PATH_LOCALE "/locale"
48 static struct appcore core;
51 static enum appcore_event to_ae[SE_MAX] = {
52 APPCORE_EVENT_UNKNOWN, /* SE_UNKNOWN */
53 APPCORE_EVENT_LOW_MEMORY, /* SE_LOWMEM */
54 APPCORE_EVENT_LOW_BATTERY, /* SE_LOWBAT */
55 APPCORE_EVENT_LANG_CHANGE, /* SE_LANGCGH */
56 APPCORE_EVENT_REGION_CHANGE,
60 enum cb_type { /* callback */
70 enum appcore_event sys;
75 int (*cb_pre) (void *);
77 int (*cb_post) (void *);
79 int (*vcb_pre) (void *, void *);
80 int (*vcb) (void *, void *);
81 int (*vcb_post) (void *, void *);
84 static int __app_terminate(void *data);
85 static int __app_resume(void *data);
86 static int __app_reset(void *data, bundle *k);
88 static int __sys_lowmem_post(void *data, void *evt);
89 static int __sys_lowmem(void *data, void *evt);
90 static int __sys_lowbatt(void *data, void *evt);
91 static int __sys_langchg_pre(void *data, void *evt);
92 static int __sys_langchg(void *data, void *evt);
93 static int __sys_regionchg_pre(void *data, void *evt);
94 static int __sys_regionchg(void *data, void *evt);
96 static struct evt_ops evtops[] = {
99 .key.vkey = VCONFKEY_SYSMAN_LOW_MEMORY,
100 .vcb_post = __sys_lowmem_post,
105 .key.vkey = VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
106 .vcb = __sys_lowbatt,
110 .key.vkey = VCONFKEY_LANGSET,
111 .vcb_pre = __sys_langchg_pre,
112 .vcb = __sys_langchg,
116 .key.vkey = VCONFKEY_REGIONFORMAT,
117 .vcb_pre = __sys_regionchg_pre,
118 .vcb = __sys_regionchg,
122 .key.vkey = VCONFKEY_REGIONFORMAT_TIME1224,
123 .vcb = __sys_regionchg,
127 static int __get_dir_name(char *dirname)
129 char pkg_name[PKGNAME_MAX];
137 aul_app_get_pkgname_bypid(pid, pkg_name, PKGNAME_MAX);
139 r = snprintf(dirname, PATH_MAX, PATH_APP_ROOT "/%s" PATH_RES PATH_LOCALE,pkg_name);
147 static int __get_cmd(char *buf)
151 char fname[FILENAME_MAX];
153 r = snprintf(fname, sizeof(fname), "/proc/%d/cmdline", getpid());
157 fp = fopen(fname, "r");
162 if (fgets(buf, PATH_MAX, fp) == NULL)
170 static int __update_rua(bundle *b)
182 _DBG("[APP %d] rua init error", _pid);
186 memset(&rec, 0, sizeof(rec));
188 rec.pkg_name = getenv("PKG_NAME");
192 bundle_encode(b, (bundle_raw **)&rec.arg, NULL);
194 r = rua_add_history(&rec);
196 _DBG("[APP %d] rua add history error", _pid);
206 static int __app_terminate(void *data)
208 struct appcore *ac = data;
210 _retv_if(ac == NULL || ac->ops == NULL, -1);
211 _retv_if(ac->ops->cb_app == NULL, 0);
213 ac->ops->cb_app(AE_TERMINATE, ac->ops->data, NULL);
218 static gboolean __prt_ltime(gpointer data)
222 msec = appcore_measure_time_from(NULL);
224 _DBG("[APP %d] first idle after reset: %d msec", _pid, msec);
229 static int __app_reset(void *data, bundle * k)
231 struct appcore *ac = data;
232 _retv_if(ac == NULL || ac->ops == NULL, -1);
233 _retv_if(ac->ops->cb_app == NULL, 0);
235 g_idle_add(__prt_ltime, ac);
237 ac->ops->cb_app(AE_RESET, ac->ops->data, k);
243 static int __app_resume(void *data)
245 x_raise_win(getpid());
250 static int __def_lowbatt(struct appcore *ac)
252 return __app_terminate(ac);
255 static int __sys_do_default(struct appcore *ac, enum sys_event event)
261 /*r = __def_lowbatt(ac);*/
272 static int __sys_do(struct appcore *ac, enum sys_event event)
276 _retv_if(ac == NULL || event >= SE_MAX, -1);
278 op = &ac->sops[event];
280 if (op->func == NULL)
281 return __sys_do_default(ac, event);
283 return op->func(op->data);
286 static int __sys_lowmem_post(void *data, void *evt)
288 #if defined(MEMORY_FLUSH_ACTIVATE)
289 struct appcore *ac = data;
290 ac->ops->cb_app(AE_LOWMEM_POST, ac->ops->data, NULL);
297 static int __sys_lowmem(void *data, void *evt)
299 return __sys_do(data, SE_LOWMEM);
302 static int __sys_lowbatt(void *data, void *evt)
304 keynode_t *key = evt;
307 val = vconf_keynode_get_int(key);
309 /* VCONFKEY_SYSMAN_BAT_CRITICAL_LOW or VCONFKEY_SYSMAN_POWER_OFF */
310 if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW)
311 return __sys_do(data, SE_LOWBAT);
316 static int __sys_langchg_pre(void *data, void *evt)
322 static int __sys_langchg(void *data, void *evt)
324 return __sys_do(data, SE_LANGCHG);
327 static int __sys_regionchg_pre(void *data, void *evt)
333 static int __sys_regionchg(void *data, void *evt)
335 return __sys_do(data, SE_REGIONCHG);
338 static void __vconf_do(struct evt_ops *eo, keynode_t * key, void *data)
343 eo->vcb_pre(data, key);
349 eo->vcb_post(data, key);
352 static void __vconf_cb(keynode_t *key, void *data)
357 name = vconf_keynode_get_name(key);
358 _ret_if(name == NULL);
360 _DBG("[APP %d] vconf changed: %s", _pid, name);
362 for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) {
363 struct evt_ops *eo = &evtops[i];
367 if (!strcmp(name, eo->key.vkey))
368 __vconf_do(eo, key, data);
377 static int __add_vconf(struct appcore *ac)
382 for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) {
383 struct evt_ops *eo = &evtops[i];
387 r = vconf_notify_key_changed(eo->key.vkey, __vconf_cb,
399 static int __del_vconf(void)
404 for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) {
405 struct evt_ops *eo = &evtops[i];
409 r = vconf_ignore_key_changed(eo->key.vkey, __vconf_cb);
420 static int __aul_handler(aul_type type, bundle *b, void *data)
424 _DBG("[APP %d] AUL event: AUL_START", _pid);
425 __app_reset(data, b);
428 _DBG("[APP %d] AUL event: AUL_RESUME", _pid);
432 _DBG("[APP %d] AUL event: AUL_TERMINATE", _pid);
433 __app_terminate(data);
436 _DBG("[APP %d] AUL event: %d", _pid, type);
445 static void __clear(struct appcore *ac)
447 memset(ac, 0, sizeof(struct appcore));
450 EXPORT_API int appcore_set_event_callback(enum appcore_event event,
451 int (*cb) (void *), void *data)
453 struct appcore *ac = &core;
457 for (se = SE_UNKNOWN; se < SE_MAX; se++) {
458 if (event == to_ae[se])
462 if (se == SE_UNKNOWN || se >= SE_MAX) {
463 _ERR("Unregistered event");
478 EXPORT_API int appcore_init(const char *name, const struct ui_ops *ops,
479 int argc, char **argv)
482 char dirname[PATH_MAX];
484 if (core.state != 0) {
485 _ERR("Already in use");
490 if (ops == NULL || ops->cb_app == NULL) {
491 _ERR("ops or callback function is null");
496 r = __get_dir_name(dirname);
497 r = set_i18n(name, dirname);
498 _retv_if(r == -1, -1);
500 r = __add_vconf(&core);
502 _ERR("Add vconf callback failed");
506 r = aul_launch_init(__aul_handler, &core);
508 _ERR("Aul init failed: %d", r);
512 r = aul_launch_argv_handler(argc, argv);
514 _ERR("Aul argv handler failed: %d", r);
519 core.state = 1; /* TODO: use enum value */
530 EXPORT_API void appcore_exit(void)
538 EXPORT_API int appcore_flush_memory(void)
540 int (*flush_fn) (int);
543 struct appcore *ac = &core;
546 _ERR("Appcore not initialized");
550 _DBG("[APP %d] Flushing memory ...", _pid);
552 if (ac->ops->cb_app) {
553 ac->ops->cb_app(AE_MEM_FLUSH, ac->ops->data, NULL);
556 flush_fn = dlsym(RTLD_DEFAULT, "sqlite3_release_memory");
558 size = flush_fn(SQLITE_FLUSH_MAX);
563 *Disabled - the impact of stack_trim() is unclear
567 _DBG("[APP %d] Flushing memory DONE", _pid);