Upload
jin-yoon
View
365
Download
0
Embed Size (px)
Citation preview
윤진
Tizen Native ApplicationOptimization
Optimization
마른걸레를짜다
Explicit Launch
Implicit Launch vs
Explicit Launch 주체 : Launcher
방법 : app_control APIs
대상 : Application ID TIZEN 2.3 기준
Samsung Z1
Explicit Launch
주체 : Launcher
방법 : app_control APIs
대상 : Application ID
“ 여러분도손쉽게앱을띄울수있습니다”
참고 : Package Information
Implicit Launch 주체 : 앱
방법 : app_control APIs
대상 : operation, mime, uri
Implicit Launch
주체 : 앱
방법 : app_control APIs
대상 : operation, mime, uri
단지 uri 만필요한경우도있고 ,
위의세개가모두필요한경우도있음
복수로설정가능 .
복수인경우교집합으로앱선택
Implicit Launch
/* Help contents */
app_control_h app_control; app_control_create(&app_control); app_control_set_operation(app_control, APP_CONTROL_OPERATION_CREATE_CONTENT);app_control_set_mime(app_control, "text/plain"); if (app_control_send_launch_request(app_control, app_control_result, NULL) == APP_CONTROL_ERROR_NONE) { dlog_print(DLOG_INFO, TAG, "Succeeded: the application is launched.");} else { dlog_print(DLOG_ERROR, TAG, "Failed to launch an application.");} app_control_destroy(app_control);
Implicit Launch
/* Help contents */static void app_control(app_control_h app_control, void* user_data) { struct appdata *ad = (struct appdata *)user_data; char *operation; char *mime; app_control_h reply; char *app_id; app_control_get_operation(app_control, &operation); if (!strcmp(operation, APP_CONTROL_OPERATION_CREATE_CONTENT)) { app_control_get_mime(app_control, &mime); if (!strcmp(mime, "text/plain")) { app_control_create(&reply); app_get_app_id(&app_id); app_control_add_extra_data(reply, APP_CONTROL_DATA_SELECTED, app_id); app_control_reply_to_launch_request(reply, app_control, APP_CONTROL_RESULT_SUCCEEDED); app_control_destroy(reply); } }}
Application Lifecycle
관리모듈 : App Core Framework
관리방법 : App 에서등록한 Lifecycle Callback 관리하기
Application
App CoreFramework
int main(int argc, char *argv[]){ struct appdata ad; ui_app_lifecycle_callback_s event_callback; event_callback.create = app_create; event_callback.terminate = app_terminate; event_callback.pause = app_pause; event_callback.resume = app_resume; event_callback.app_control = app_control; memset(&ad, 0x0, sizeof(struct appdata)); return ui_app_main(argc, argv, &event_callback, &ad);}
Application Lifecycle
/* SDK Gallery Sample */
static void create_base_gui(appdata_s *ad){ /* 생략 */ ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE); elm_win_conformant_set(ad->win, EINA_TRUE); elm_win_autodel_set(ad->win, EINA_TRUE);
/* 생략 */ evas_object_show(ad->win);}
static bool app_create(void *data){/* Hook to take necessary actions before main event loop starts Initialize UI resources and application's data If this function returns true, the main loop of application starts If this function returns false, the application is terminated */ appdata_s *ad = data;
elm_app_base_scale_set(1.8); create_base_gui(ad);
return true;}
Application Lifecycle/* TIZEN App-core Base */
int aul_initialize(){ if (aul_initialized) { //_E("aul already initialized"); return AUL_R_ECANCELED; }
aul_fd = __create_server_sock(getpid()); if (aul_fd < 0) { _E("aul_init create sock failed"); return AUL_R_ECOMM; } return aul_fd;}
int aul_launch_init( int (*aul_handler) (aul_type type, bundle *, void *), void *data){ /* 생략 */ fd = aul_initialize(); if (fd < 0) return fd;
src = g_source_new(&funcs, sizeof(GSource));
gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD)); gpollfd->events = POLLIN; gpollfd->fd = fd;
g_source_add_poll(src, gpollfd); /* 생략 */}
Application
App CoreFramework
Application Lifecycle
/* TIZEN Gallery Base */
static void app_control(app_control_h app_control, void *data){/* 생략 */ if(__gallery_parse_param(data, app_control) != 0) { if (ad->albuminfo.aul_launch_by_mime == false && ad->albuminfo.aul_launch_type == GL_AUL_T_NONE) { int view_m = gl_get_view_mode(ad); gl_dbg("view_m: %d", view_m); /* Launch Gallery at the first time */ if (view_m == GL_VIEW_NONE) { gl_dbg("Set view mode as GL_VIEW_ALBUMS"); gl_set_view_mode(ad, GL_VIEW_ALBUMS); } else { gl_dbg("Update view"); gl_update_view(ad, GL_UPDATE_VIEW_NORMAL); } } else { gl_dbgE("Failed to parse parameters, update view!"); gl_update_view(ad, GL_UPDATE_VIEW_NORMAL); } elm_win_activate(ad->maininfo.win); return; }}
Application Lifecycle
/* TIZEN Menu-screen Base */
static void _resume_cb(void *data){ _D("START RESUME");
do { // Focus Evas_Object *layout = evas_object_data_get(menu_screen_info.win, "layout"); break_if(NULL == layout);
Evas_Object *all_apps = evas_object_data_get(layout, "all_apps"); break_if(NULL == all_apps);
Evas_Object *scroller = elm_object_part_content_get(all_apps, "content"); break_if(NULL == scroller);
page_scroller_focus(scroller); } while (0);
menu_screen_info.state = APP_STATE_RESUME;}
Application Lifecycle
/* TIZEN Quickpanel Base */
static void _app_resume_cb(void *data){ DBG(""); struct appdata *ad = data; retif(ad == NULL,, "invalid data.");
ad->is_suspended = 0; _ui_handler_enable_set(EINA_FALSE);
quickpanel_modules_resume(data);
sim_controller_resume();}
/* TIZEN Quickpanel Base */
tatic void _app_pause_cb(void *data){ DBG(""); struct appdata *ad = data; retif(ad == NULL,, "invalid data.");
quickpanel_modules_suspend(ad);
ad->is_suspended = 1;
if (ad->evas != NULL) { _ui_efl_cache_flush(ad->evas); evas_event_feed_mouse_cancel(ad->evas , ecore_time_get(), NULL); }}
Application Lifecycle
/* TIZEN App-core Base */
static void __add_climsg_cb(struct ui_priv *ui) { _ret_if(ui == NULL); ui->hshow = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui); ui->hhide = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui); ui->hvchange = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, __visibility_cb, ui);
/* Add client message callback for WM_ROTATE */ if(!__check_wm_rotation_support()) { ui->hcmsg = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, __cmsg_cb, ui); ui->wm_rot_supported = 1; appcore_set_wm_rotation(&wm_rotate); } }
Application
App CoreFramework
Application Lifecycle
/* TIZEN Menu-screen Base */
static void _terminate_cb(void *data){ Evas_Object *conformant; Evas_Object *layout;
pkgmgr_fini();
evas_object_hide(menu_screen_info.win);
key_unregister(); mouse_unregister();
layout = evas_object_data_del(menu_screen_info.win, "layout"); if (layout) layout_destroy(layout);
conformant = evas_object_data_del(menu_screen_info.win, "conformant"); if (conformant) _destroy_conformant(conformant);
_destroy_bg(); _destroy_canvas(); _fini_theme(); evas_object_del(menu_screen_info.win);}
Mainloop
Mainloop
- EFL Ecore 라이브러리에서관리
- Event driven
- 이벤트를체크하고처리하는루틴을무한루프돌며
반복
- 복잡한앱도하나의 thread 처리가능
- 물론다수의 thread 를가지는앱도존재
단 , 이경우 main thread 에서만 rendering 실시
Mainloop
Idle
IdleEnter
IdleExit
File Descript
or Handling
Signal to Event
Event Handling
Timer Handling
Signal to Event
while (1)
Mainloop
Idle
IdleEnter
IdleExit FD
Signal to
EventEventTimer
Signal to
Event
Idle Enter
- Idle 상태진입직전에거치는단계
- Rendering : recalculate + redraw
Retained mode rendering
위치 , 크기 , 가시성 , 컬러가바뀌어도안보이면안그림
- EAPI Ecore_Idle_Enterer
*ecore_idle_enterer_add(Ecore_Task_Cb func, const
void *data);
- 앱 / 라이브러리개발자가등록한 Ecore_Idle_Enterer 수행
Mainloop
Idle
IdleEnter
IdleExit FD
Signal to
EventEventTimer
Signal to
Event
Idle
- if ( 처리해야할이벤트 ) goto Idle_Exit;
- else if (! 처리해야할이벤트 && Ecore_Idler)
ecore_idler_add() 로등록한 Ecore_Idler 콜백을수행
goto Idle_Exit;
- else goto Idle;
- Idle 동안 select() 함수로이벤트기다리며대기
- CPU 를소모하지않음 .
Mainloop
Idle
IdleEnter
IdleExit FD
Signal to
EventEventTimer
Signal to
Event
Idle Exit
- Idle 상태에서빠져나가면서거치는단계
- Idle Enter 혹은 Idle 에서부터진입
- EAPI Ecore_Idle_Exiter
*ecore_idle_exiter_add(Ecore_Task_Cb func, const void
*data);
- 앱 / 라이브러리개발자가등록한 Ecore_Idle_Exiter 수행
Mainloop
Idle
IdleEnter
IdleExit FD
Signal to
EventEventTimer
Signal to
EventFile Descriptor Handling
- Idler 를빠져나오자마자만나는첫단계
- File descriptor 를처리하는단계
- Ecore_Con(connection), Ecore_Pipe, Ecore_Ipc 로등록한
것만처리
- EAPI Ecore_Fd_Handler *ecore_main_fd_handler_add(int
fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func,
const void *data, Ecore_Fd_Cb buf_func, const void
*buf_data);
static Eina_Bool_my_cb_func(void *data, Ecore_Fd_Handler *handler){ char c; scanf("%c", &c); //Guaranteed not to block ... do stuff with c ...}ecore_main_fd_handler_add(STDIN_FILENO, ECORE_FD_READ , _my_cb_func, NULL, NULL, NULL);
Mainloop
Idle
IdleEnter
IdleExit FD
Signal to
EventEventTimer
Signal to
Event
Signal to Event
- FD Handling 직후에수행되는단계
- 시스템시그널을 Ecore 에서관리하는이벤트로변경
#define ECORE_EVENT_NONE 0
#define ECORE_EVENT_SIGNAL_USER 1 /**< User signal event */
#define ECORE_EVENT_SIGNAL_HUP 2 /**< Hup signal event */
#define ECORE_EVENT_SIGNAL_EXIT 3 /**< Exit signal event */
#define ECORE_EVENT_SIGNAL_POWER 4 /**< Power signal event */
#define ECORE_EVENT_SIGNAL_REALTIME 5 /**< Realtime signal event */
#define ECORE_EVENT_COUNT 6
Mainloop
Idle
IdleEnter
IdleExit FD
Signal to
EventEventTimer
Signal to
Event
Event Handling
- Signal to Event 직후에수행하는단계
- Ecore_Event 를 처리하는단계
- EAPI Ecore_Event_Handler *ecore_event_handler_add(int type,
Ecore_Event_Handler_Cb func, const void *data);
- 앱 / 라이브러리개발자가 ecore_event_handler_add() 로등록한
콜백을수행
- Ecore_Event 중에 Ecore_Job 도존재
- EAPI Ecore_Job *ecore_job_add(Ecore_Cb func, const void *data);
- Queue 방식으로이벤트가쌓이며 , FIFO 으로처리
Mainloop
Idle
IdleEnter
IdleExit FD
Signal to
EventEventTimer
Signal to
Event
Timing Handling
- Event Handling 직후에수행하는단계
- 사용자가추가한 timing 관련함수가실행
- EAPI Ecore_Timer *ecore_timer_add(double in,
Ecore_Task_Cb func, const void *data);
- EAPI Ecore_Animator *ecore_animator_add(Ecore_Task_Cb
func, const void *data);
- EAPI Ecore_Poller *ecore_poller_add(Ecore_Poller_Type type,
int interval, Ecore_Task_Cb func, const void *data);
- 앱 / 라이브러리개발자가등록한타이밍콜백수행
Launching Optimization
/* SDK Gallery Sample */
static void create_base_gui(appdata_s *ad){ ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE); elm_win_conformant_set(ad->win, EINA_TRUE); elm_win_autodel_set(ad->win, EINA_TRUE);
ad->conform = elm_conformant_add(ad->win); elm_win_indicator_mode_set(…); elm_win_indicator_opacity_set(…); elm_win_resize_object_add(ad->win, ad->conform); evas_object_show(ad->conform);
ad->bg = elm_bg_add(ad->conform); elm_object_style_set(bg, "indicator/headerbg"); elm_object_part_content_set(ad->conform, “…”, bg); evas_object_show(bg);}
static bool app_create(void *data){ appdata_s *ad = data;
elm_app_base_scale_set(1.8); create_base_gui(ad);
return true;}
/* SDK Gallery Sample */
static void reset_base_gui(appdata_s *ad){ ad->nf = create_main_view(ad); elm_object_content_set(ad->conform, ad->nf);
/* Show window after base gui is set up */ evas_object_show(ad->win);}
static voidapp_control(app_control_h app_control, void *data){ appdata_s *ad = data;
elm_app_base_scale_set(1.8); reset_base_gui(ad);
return true;}
Launching Optimization
/* TIZEN Menu-screen Base */static Eina_Bool _push_items_timer_cb(void *all_apps){ retv_if(NULL == list, ECORE_CALLBACK_CANCEL); goto_if(NULL == scroller, ERROR); goto_if(MENU_SCREEN_ERROR_OK != list_is_ended(list, &flag), ERROR); goto_if(flag == true, ERROR); goto_if(MENU_SCREEN_ERROR_OK != list_get_item(list, &item), ERROR); goto_if(MENU_SCREEN_ERROR_OK != _load_item(scroller, item), ERROR); goto_if(MENU_SCREEN_ERROR_OK != list_next(list), ERROR);
return ECORE_CALLBACK_RENEW;}static menu_screen_error_e _push_items(Evas_Object *all_apps){ app_list *list; Ecore_Timer *timer;
list = all_apps_list_create(); retv_if(MENU_SCREEN_ERROR_OK != list_first(list), MENU_SCREEN_ERROR_FAIL);
evas_object_data_set(all_apps, "list", list); idle_timer = ecore_timer_add(0.1f, _push_items_timer_cb, all_apps); retv_if(NULL == idle_timer, MENU_SCREEN_ERROR_FAIL);
return MENU_SCREEN_ERROR_OK;}
Memory Optimization
/* TIZEN Starter Base */
Evas_Object *popup_create(const char *title, const char *text){ win = _window_create(); goto_if(!win, ERROR);
popup = elm_popup_add(win); goto_if(!popup, ERROR); elm_popup_orient_set(popup, ELM_POPUP_ORIENT_BOTTOM); elm_object_part_text_set(popup, "title,text", title); elm_object_text_set(popup, text); evas_object_data_set(popup, DATA_KEY_WINDOW, win); evas_object_show(popup);
btn = elm_button_add(popup); goto_if(!btn, ERROR); elm_object_style_set(btn, "popup"); elm_object_text_set(btn, S_("IDS_COM_SK_CONFIRM")); elm_object_part_content_set(popup, "button1", btn);
return popup;}
/* TIZEN Starter Base */
static void _popup_destroy(Evas_Object *popup){ Evas_Object *win = NULL;
if (popup) { win = evas_object_data_del(popup, DATA_KEY_WINDOW); evas_object_del(popup);
if (win) { evas_object_del(win); } }}
Memory Optimization
/* TIZEN Starter Base */
Evas_Object *popup_create(const char *title, const char *text){ win = _window_create(); goto_if(!win, ERROR);
popup = elm_popup_add(win); goto_if(!popup, ERROR); elm_popup_orient_set(popup, ELM_POPUP_ORIENT_BOTTOM); elm_object_part_text_set(popup, "title,text", title); elm_object_text_set(popup, text); evas_object_data_set(popup, DATA_KEY_WINDOW, win); evas_object_show(popup);
btn = elm_button_add(popup); goto_if(!btn, ERROR); elm_object_style_set(btn, "popup"); elm_object_text_set(btn, S_(“Cancel")); elm_object_part_content_set(popup, "button1", btn);
return popup;}
/* TIZEN Starter Base */
static void _popup_destroy(Evas_Object *popup){ Evas_Object *win = NULL;
if (popup) { if (button) { evas_object_del(button); } win = evas_object_data_del(popup, DATA_KEY_WINDOW); evas_object_del(popup);
if (win) { evas_object_del(win); } }}
Memory Optimization