Add exception code for pkgmgrinfo
[apps/native/menu-screen.git] / src / menu_screen.c
1 /*
2  * MENU-SCREEN
3  *
4  * Copyright (c) 2009-2014 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Jin Yoon <jinny.yoon@samsung.com>
7  *          Junkyu Han <junkyu.han@samsung.com>
8
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #include <ail.h>
24 #include <app.h>
25 #include <appcore-efl.h>
26 #include <aul.h>
27 #include <Elementary.h>
28 #include <stdbool.h>
29 #include <system_info.h>
30 #include <vconf.h>
31 #include <app_preference.h>
32 #include <system_settings.h>
33 #include <pkgmgr-info.h>
34
35 #include "conf.h"
36 #include "item.h"
37 #include "key.h"
38 #include "layout.h"
39 #include "mapbuf.h"
40 #include "menu_screen.h"
41 #include "mouse.h"
42 #include "page.h"
43 #include "page_scroller.h"
44 #include "pkgmgr.h"
45 #include "util.h"
46
47 #define MENU_SCREEN_ENGINE "file/private/org.tizen.menu-screen/engine"
48
49 #define LAYOUT_EDJE_PORTRAIT EDJEDIR"/layout_portrait.edj"
50 #define LAYOUT_GROUP_NAME "layout"
51
52
53
54 // Define prototype of the "hidden API of AUL"
55 extern int aul_listen_app_dead_signal(int (*func)(int signal, void *data), void *data);
56 static struct {
57         int state;
58         int root_width;
59         int root_height;
60         int is_tts;
61         int booting_state;
62         Evas *evas;
63         Ecore_Evas *ee;
64         Evas_Object *win;
65         Elm_Theme *theme;
66         bool is_done;
67 } menu_screen_info = {
68         .state = APP_STATE_PAUSE,
69         .is_tts = false,
70         .booting_state = 0,
71         .evas = NULL,
72         .ee = NULL,
73         .win = NULL,
74         .theme = NULL,
75         .is_done = false,
76 };
77
78
79
80 HAPI Evas *menu_screen_get_evas(void)
81 {
82         return menu_screen_info.evas;
83 }
84
85
86
87 HAPI int menu_screen_get_root_width(void)
88 {
89         return menu_screen_info.root_width;
90 }
91
92
93
94 HAPI int menu_screen_get_root_height(void)
95 {
96         return menu_screen_info.root_height;
97 }
98
99
100
101 HAPI Evas_Object *menu_screen_get_win(void)
102 {
103         return menu_screen_info.win;
104 }
105
106
107
108 HAPI Elm_Theme *menu_screen_get_theme(void)
109 {
110         return menu_screen_info.theme;
111 }
112
113
114
115 HAPI bool menu_screen_get_done(void)
116 {
117         return menu_screen_info.is_done;
118 }
119
120
121
122 HAPI void menu_screen_set_done(bool is_done)
123 {
124         menu_screen_info.is_done = is_done;
125 }
126
127
128
129 HAPI int menu_screen_get_state(void)
130 {
131         return menu_screen_info.state;
132 }
133
134
135
136 HAPI int menu_screen_is_tts(void)
137 {
138         return menu_screen_info.is_tts;
139 }
140
141
142 static Eina_Bool _appcore_flush_cb(void *data)
143 {
144         if (APP_STATE_PAUSE != menu_screen_info.state) return ECORE_CALLBACK_CANCEL;
145         if (0 != appcore_flush_memory()) _E("Cannot flush memory");
146         return ECORE_CALLBACK_CANCEL;
147 }
148
149
150
151 HAPI void menu_screen_inc_booting_state(void)
152 {
153         menu_screen_info.booting_state++;
154         if (BOOTING_STATE_DONE > menu_screen_info.booting_state) return;
155
156         menu_screen_error_e ret = MENU_SCREEN_ERROR_OK;
157         do {
158                 ret = pkgmgr_reserve_list_pop_request();
159         } while (MENU_SCREEN_ERROR_OK == ret);
160
161         /*  Cache memory is cleared when the application paused (every time, after 5 seconds (in appcore)),
162         *  but after running in a minimized mode (HIDE_LAUNCH) application have status AS_RUNNING.
163         *  Application have status AS_PAUSED only after change of visibility to hidden condition by user (on hiding window)
164         *  Cleaning must be performed only once after application loading in hidden condition
165         *  (and stay in a hidden condition at time of cleaning).
166         */
167         if (APP_STATE_PAUSE == menu_screen_info.state)
168                 ecore_timer_add(5, _appcore_flush_cb, NULL);
169 }
170
171
172
173 HAPI void menu_screen_dec_booting_state(void)
174 {
175         menu_screen_info.booting_state --;
176 }
177
178
179
180 HAPI int menu_screen_get_booting_state(void)
181 {
182         return menu_screen_info.booting_state;
183 }
184
185
186
187 static bool _is_emulator_on(void)
188 {
189         int ret;
190         char *model;
191
192         ret = system_info_get_platform_string("tizen.org/system/model_name", &model);
193         if (SYSTEM_INFO_ERROR_NONE != ret) {
194                 if (model) {
195                         free(model);
196                 }
197                 return false;
198         }
199
200         if (!strncmp(model, "Emulator", strlen(model))) {
201                 _D("This model is on Emulator");
202                 free(model);
203                 return true;
204         }
205
206         _D("This model is NOT on Emulator");
207         free(model);
208         return false;
209 }
210
211
212
213 static menu_screen_error_e _create_canvas(char *name, char *title)
214 {
215         //Ecore_X_Atom ATOM_WM_WINDOW_ROLE;
216         char *buf;
217
218         if (_is_emulator_on()) {
219                 _D("ELM_ENGINE is set as [software_x11]");
220                 elm_config_accel_preference_set("opengl");
221         } else {
222                 buf = vconf_get_str(MENU_SCREEN_ENGINE);
223                 if (buf) {
224                         _D("ELM_ENGINE is set as [%s]", buf);
225                         elm_config_accel_preference_set(buf);
226                         free(buf);
227                 } else {
228                         _D("ELM_ENGINE is set as [gl]");
229                         elm_config_accel_preference_set("gl");
230                 }
231         }
232
233         menu_screen_info.win = elm_win_add(NULL, name, ELM_WIN_BASIC);
234         retv_if(NULL == menu_screen_info.win, MENU_SCREEN_ERROR_FAIL);
235
236         if (title) {
237                 elm_win_title_set(menu_screen_info.win, title);
238         }
239         elm_win_borderless_set(menu_screen_info.win, EINA_TRUE);
240         elm_win_screen_size_get(menu_screen_info.win, NULL, NULL, &menu_screen_info.root_width, &menu_screen_info.root_height);
241
242 #if 0
243         ecore_x_icccm_name_class_set(elm_win_xwindow_get(menu_screen_info.win), "MENU_SCREEN", "MENU_SCREEN");
244         ATOM_WM_WINDOW_ROLE = ecore_x_atom_get("WM_WINDOW_ROLE");
245         if (ATOM_WM_WINDOW_ROLE) {
246                 ecore_x_window_prop_string_set(elm_win_xwindow_get(menu_screen_info.win), ATOM_WM_WINDOW_ROLE, "MENU_SCREEN");
247         } else {
248                 _D("Failed to set the window role as MENU_SCREEN");
249         }
250 #endif
251
252         elm_win_role_set(menu_screen_info.win, "MENU_SCREEN");
253         evas_object_resize(menu_screen_info.win, menu_screen_get_root_width(), menu_screen_get_root_height());
254
255         menu_screen_info.evas = evas_object_evas_get(menu_screen_info.win);
256         if (!menu_screen_info.evas) {
257                 _E("[%s] Failed to get the evas object", __func__);
258         }
259
260         menu_screen_info.ee = ecore_evas_ecore_evas_get(menu_screen_info.evas);
261         if (!menu_screen_info.ee) {
262                 _E("[%s] Failed to get ecore_evas object", __func__);
263         }
264
265         evas_object_size_hint_min_set(menu_screen_info.win, menu_screen_info.root_width, menu_screen_info.root_height);
266         evas_object_size_hint_max_set(menu_screen_info.win, menu_screen_info.root_width, menu_screen_info.root_height);
267         evas_object_resize(menu_screen_info.win, menu_screen_info.root_width, menu_screen_info.root_height);
268         evas_object_show(menu_screen_info.win);
269
270         return MENU_SCREEN_ERROR_OK;
271 }
272
273
274
275 static void _destroy_canvas(void)
276 {
277         evas_object_del(menu_screen_info.win);
278 }
279
280
281
282 static int _dead_cb(int pid, void *data)
283 {
284         return EXIT_SUCCESS;
285 }
286
287
288
289 static void _create_bg(void)
290 {
291         _D("Create BG");
292         char *buf = NULL;
293         Evas_Coord w;
294         Evas_Coord h;
295         Evas_Object *bg;
296         double f, wf, hf;
297         static int trigger = 0;
298         const char *key;
299         int width;
300         int height;
301         int ret = SYSTEM_SETTINGS_ERROR_NONE;
302
303         if (system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, &buf) < 0) {
304                 _E("Failed to get a wallpaper: %d\n", SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN);
305         }
306         _D("Menu-screen bg's image : %s", buf);
307
308         width = menu_screen_get_root_width();
309         height = menu_screen_get_root_height();
310
311         bg = evas_object_data_get(menu_screen_get_win(), "bg");
312         if (!bg) {
313                 Evas_Object *rect;
314                 rect = evas_object_rectangle_add(menu_screen_get_evas());
315                 goto_if(!rect, ERROR);
316                 evas_object_data_set(menu_screen_get_win(), "rect", rect);
317                 evas_object_color_set(rect, 0, 0, 0, 255);
318                 evas_object_size_hint_min_set(rect, width, height);
319                 evas_object_size_hint_max_set(rect, width, height);
320                 elm_win_resize_object_add(menu_screen_get_win(), rect);
321                 evas_object_show(rect);
322
323                 bg = evas_object_image_add(menu_screen_get_evas());
324                 if (!bg) {
325                     if (rect) {
326                         evas_object_del(rect);
327                     }
328                     goto ERROR;
329                 }
330                 evas_object_image_load_orientation_set(bg, EINA_TRUE);
331                 evas_object_data_set(menu_screen_get_win(), "bg", bg);
332         }
333
334         if (trigger == 0) {
335                 key = "/";
336                 trigger = 1;
337         } else {
338                 key = NULL;
339                 trigger = 0;
340         }
341
342         evas_object_image_file_set(bg, buf, key);
343         evas_object_image_size_get(bg, &w, &h);
344         if (w == 0 || h == 0) {
345             _E("There's something wrong, width or height is ZERO");
346             goto ERROR;
347         }
348         evas_object_image_filled_set(bg, 1);
349
350         wf = (double) width / (double) w;
351         hf = (double) height / (double) h;
352
353         f = wf < hf ? hf : wf;
354
355         w = (int) ((double) f * (double) w);
356         h = (int) ((double) f * (double) h);
357
358         evas_object_image_load_size_set(bg, w, h);
359         evas_object_image_fill_set(bg, 0, 0, w, h);
360         elm_win_resize_object_add(menu_screen_get_win(), bg);
361         evas_object_show(bg);
362
363 ERROR:
364         if (buf) {
365                 free(buf);
366         }
367 }
368
369
370
371
372 static void _destroy_bg()
373 {
374         Evas_Object *rect;
375         Evas_Object *bg;
376
377         rect = evas_object_data_del(menu_screen_get_win(), "rect");
378         evas_object_del(rect);
379
380         bg = evas_object_data_del(menu_screen_get_win(), "bg");
381         evas_object_del(bg);
382 }
383
384
385
386 static void _change_bg_cb(system_settings_key_e key, void *data)
387 {
388         _D("Background image is changed.");
389         _create_bg();
390 }
391
392
393
394 static void _init_theme(void)
395 {
396         menu_screen_info.theme = elm_theme_new();
397         elm_theme_ref_set(menu_screen_info.theme, NULL);
398         elm_theme_extension_add(menu_screen_info.theme, EDJEDIR"/index.edj");
399 }
400
401
402
403 static void _fini_theme(void)
404 {
405         elm_theme_extension_del(menu_screen_info.theme, EDJEDIR"/index.edj");
406         elm_theme_free(menu_screen_info.theme);
407         menu_screen_info.theme = NULL;
408
409 }
410
411
412
413 static Evas_Object *_create_conformant(Evas_Object *win)
414 {
415         Evas_Object *conformant;
416
417         conformant = elm_conformant_add(win);
418         retv_if(NULL == conformant, NULL);
419
420         evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
421         elm_win_indicator_mode_set(menu_screen_info.win, ELM_WIN_INDICATOR_SHOW);
422         elm_object_signal_emit(conformant, "elm,state,indicator,overlap", "elm");
423         evas_object_data_set(conformant, "win", win);
424         evas_object_show(conformant);
425
426         elm_win_resize_object_add(win, conformant);
427         elm_win_conformant_set(win, EINA_TRUE);
428
429         return conformant;
430 }
431
432
433
434 static void _destroy_conformant(Evas_Object *conformant)
435 {
436         evas_object_data_del(conformant, "win");
437         evas_object_del(conformant);
438 }
439
440
441 static char *_replace_str(char *str, const char *before, const char *after)
442 {
443         retv_if(NULL == str, NULL);
444         retv_if(NULL == before, NULL);
445         retv_if(NULL == after, NULL);
446
447         size_t before_len = strlen(before);
448         retv_if(before_len < 1, str);
449
450         size_t after_len = strlen(after);
451         size_t i, count = 0;
452         if (after_len != before_len) {
453                 for (i = 0; str[i] != '\0';) {
454                         if (0 == memcmp(&str[i], before, before_len)) {
455                                 count++;
456                                 i += before_len;
457                         } else {
458                                 i++;
459                         }
460                 }
461         } else {
462                 i = strlen(str);
463         }
464
465         char *result;
466         result = malloc(i + 1 + count * (after_len - before_len));
467         retv_if(result == NULL, NULL);
468
469         char *sr;
470         sr = result;
471         while (*str) {
472                 if (0 == memcmp(str, before, before_len)) {
473                         memcpy(sr, after, after_len);
474                         sr += after_len;
475                         str += before_len;
476                 } else {
477                         *sr++ = *str++;
478                 }
479         }
480         *sr = '\0';
481
482         return result;
483 }
484
485
486
487 static bool _create_cb(void *data)
488 {
489         Evas_Object *conformant;
490
491         _init_theme();
492         retv_if(MENU_SCREEN_ERROR_FAIL == _create_canvas(PACKAGE, PACKAGE), false);
493
494         if (system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, _change_bg_cb, NULL) < 0) {
495                 _E("Failed to register a settings change cb for %d\n", SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN);
496         }
497         _create_bg();
498
499         conformant = _create_conformant(menu_screen_info.win);
500         retv_if(NULL == conformant, false);
501         evas_object_data_set(menu_screen_info.win, "conformant", conformant);
502
503         Evas_Object *layout;
504         layout = layout_create(conformant, LAYOUT_EDJE_PORTRAIT,
505                                 LAYOUT_GROUP_NAME, MENU_SCREEN_ROTATE_PORTRAIT);
506         if (NULL == layout) {
507                 _E("Failed to load an edje object");
508                 evas_object_del(menu_screen_info.win);
509                 return false;
510         }
511         evas_object_data_set(menu_screen_info.win, "layout", layout);
512
513         elm_object_content_set(conformant, layout);
514
515         mouse_register();
516         aul_listen_app_dead_signal(_dead_cb, NULL);
517         key_register();
518
519         // FIXME : This will be enabled after rebuilding the routine for appid <-> pkgid.
520         pkgmgr_init();
521
522         return true;
523 }
524
525
526
527 static void _terminate_cb(void *data)
528 {
529         Evas_Object *conformant;
530         Evas_Object *layout;
531
532         // FIXME : This will be enabled after rebuilding the routine for appid <-> pkgid.
533         pkgmgr_fini();
534
535         if (system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN) < 0) {
536                 _E("Failed to remove bgset [%s]\n", SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN);
537         }
538
539         evas_object_hide(menu_screen_info.win);
540
541         key_unregister();
542         mouse_unregister();
543
544         layout = evas_object_data_del(menu_screen_info.win, "layout");
545         if (layout) layout_destroy(layout);
546
547         conformant = evas_object_data_del(menu_screen_info.win, "conformant");
548         if (conformant) _destroy_conformant(conformant);
549
550         _destroy_bg();
551         _destroy_canvas();
552         _fini_theme();
553         evas_object_del(menu_screen_info.win);
554 }
555
556
557
558 static void _pause_cb(void *data)
559 {
560         _D("Pause start");
561
562         menu_screen_info.state = APP_STATE_PAUSE;
563 }
564
565
566
567 static void _resume_cb(void *data)
568 {
569         _D("START RESUME");
570
571         do { // Focus
572                 Evas_Object *layout = evas_object_data_get(menu_screen_info.win, "layout");
573                 break_if(NULL == layout);
574
575                 Evas_Object *all_apps = evas_object_data_get(layout, "all_apps");
576                 break_if(NULL == all_apps);
577
578                 Evas_Object *scroller = elm_object_part_content_get(all_apps, "content");
579                 break_if(NULL == scroller);
580
581                 page_scroller_focus(scroller);
582         } while (0);
583
584         menu_screen_info.state = APP_STATE_RESUME;
585 }
586
587
588
589 static void _app_control_cb(app_control_h service, void *data)
590 {
591         _D("START RESET : %d", menu_screen_info.state);
592
593         do { // Focus
594                 Evas_Object *layout = evas_object_data_get(menu_screen_info.win, "layout");
595                 break_if(NULL == layout);
596
597                 Evas_Object *all_apps = evas_object_data_get(layout, "all_apps");
598                 break_if(NULL == all_apps);
599
600                 Evas_Object *scroller = elm_object_part_content_get(all_apps, "content");
601                 break_if(NULL == scroller);
602
603                 page_scroller_focus(scroller);
604         } while (0);
605 }
606
607
608
609 static void _language_changed_cb(app_event_info_h event_info, void *data)
610 {
611         register unsigned int i;
612         register unsigned int j;
613         unsigned int count;
614         Evas_Object *layout;
615         Evas_Object *all_apps;
616         Evas_Object *scroller;
617         Evas_Object *page;
618         Evas_Object *item;
619         unsigned int page_max_app;
620
621         _D("Language is changed");
622
623         if (false == menu_screen_info.is_done) {
624                 elm_exit();
625         }
626
627         layout = evas_object_data_get(menu_screen_info.win, "layout");
628         ret_if(NULL == layout);
629         all_apps = evas_object_data_get(layout, "all_apps");
630         ret_if(NULL == all_apps);
631         scroller = elm_object_part_content_get(all_apps, "content");
632         ret_if(NULL == scroller);
633
634         count = page_scroller_count_page(scroller);
635         page_max_app = (unsigned int) evas_object_data_get(scroller, "page_max_app");
636         for (i = 0; i < count; i ++) {
637                 page = page_scroller_get_page_at(scroller, i);
638                 if (!page) continue;
639                 if (mapbuf_is_enabled(page)) {
640                         mapbuf_disable(page, 1);
641                 }
642
643                 for (j = 0; j < page_max_app; j ++) {
644                         pkgmgrinfo_appinfo_h appinfo_h = NULL;
645                         char *name;
646
647                         item = page_get_item_at(page, j);
648                         if (!item) continue;
649
650                         if (pkgmgrinfo_appinfo_get_appinfo(item_get_package(item), &appinfo_h) < 0) {
651                                 pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h);
652                                 continue;
653                         }
654                         if (pkgmgrinfo_appinfo_get_label(appinfo_h, &name) < 0) {
655                                 pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h);
656                                 continue;
657                         }
658
659                         if (!name) {
660                                 _D("Failed to get name for %s", item_get_package(item));
661                                 pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h);
662                                 continue;
663                         }
664
665                         item_set_name(item, name, 0);
666                         pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h);
667                 }
668
669                 mapbuf_enable(page, 1);
670         }
671 }
672
673
674
675 static void _init(ui_app_lifecycle_callback_s *lifecycle_callback, app_event_handler_h *event_handlers)
676 {
677         lifecycle_callback->create = _create_cb;
678         lifecycle_callback->terminate = _terminate_cb;
679         lifecycle_callback->pause = _pause_cb;
680         lifecycle_callback->resume = _resume_cb;
681         lifecycle_callback->app_control = _app_control_cb;
682
683         ui_app_add_event_handler(&event_handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, NULL, NULL);
684         ui_app_add_event_handler(&event_handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, NULL, NULL);
685         ui_app_add_event_handler(&event_handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, NULL, NULL);
686         ui_app_add_event_handler(&event_handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, _language_changed_cb, NULL);
687         ui_app_add_event_handler(&event_handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, NULL, NULL);
688
689 }
690
691
692
693 static void _fini(app_event_handler_h *event_handlers)
694 {
695         ui_app_remove_event_handler(event_handlers[APP_EVENT_LOW_BATTERY]);
696         ui_app_remove_event_handler(event_handlers[APP_EVENT_LOW_MEMORY]);
697         ui_app_remove_event_handler(event_handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED]);
698         ui_app_remove_event_handler(event_handlers[APP_EVENT_LANGUAGE_CHANGED]);
699         ui_app_remove_event_handler(event_handlers[APP_EVENT_REGION_FORMAT_CHANGED]);
700
701 }
702
703
704
705 static void _init_reference_value(void)
706 {
707         preference_set_string(MENU_SCREEN_ENGINE, "gl");
708 }
709
710
711 int main(int argc, char *argv[])
712 {
713         char *buf;
714         ui_app_lifecycle_callback_s lifecycle_callback = {0, };
715         app_event_handler_h event_handlers[5] = {NULL, };
716
717         _init(&lifecycle_callback, event_handlers);
718         ui_app_main(argc, argv, &lifecycle_callback, NULL);
719         _fini(event_handlers);
720
721         return EXIT_SUCCESS;
722 }
723
724
725
726 // End of a file