mmi.cpp
main
pre_config
parse_strings
launch_log
write_file(WAKE_LOCK, "mmi");
sem_init(&g_sem_exit, 0, 0);
sem_init(&g_msg_sem, 0, 0);
sem_init(&g_sem_accept_ready, 0, 0);
sem_init(&g_data_print_sem, 0, 0);
sem_init(&g_result_sem, 0, 0);
pthread_mutex_init(&g_cur_layout_mutex, NULL);
init_draw
create_func_map
is_create_mmi_cfg
create_mmi_cfg
int main函数
mmi.cpp
agent_main.cpp
diag_main.cpp
debug_main.cpp
misc启动进入mmi:
第一个进程:mmi mmi starting MMI_PROC_TYPE(MMI_PROC_TYPE_MMI)
第二个进程:log launch log process
主进程的flow:
mmi.cpp
pre_config
init_config /*Initialize configuration */
post_config
init_controller /*Load controller */
build_main_ui /*Initial the MMI screen */
start_threads /*Start threads */
launch_controller /*Launch threads */
launch_clients
is_autostart /*Start Background Test */
start_autorun
sem_wait
write_file //WAKE_UNLOCK
pre_config
parse_strings //加载各种bin执行、库、节点文件
launch_log /**start logcat process*/ fork 出一个进程来记录log
write_file //持一把wake lock,保持屏幕常亮
sem_init //初始化信号灯 g_sem_exit:mmi进程退出 g_msg_sem:同步消息的处理 g_sem_accept_ready:创建mmi_socket服务端 g_data_print_sem:sensor提示信息的打印 g_result_sem:各种RF传输外设的测试结果
pthread_mutex_init //创建互斥锁g_cur_layout_mutex 关于当前模块的layout界面
init_draw /**Init draw*/ MMI_ALOGI("start draw init!");
--> init_surface //MMI_ALOGI("start init surface");
--> sem_init //(draw_control_t) g_draw.sem 同步刷新ui界面
create_func_map //创建各种函数的调用map表
is_create_mmi_cfg //Check "/etc/mmi/mmi.xml" 等whether exist
create_mmi_cfg // parse file: "/etc/mmi/mmi.xml" 根据mmi.xml文件创建mmi.cfg // create file: "/cache/FTM_AP/mmi.cfg" mmi.cfg保存各种测试项的配置要求 ordered_ui_module module_ui_map // create file: "/cache/FTM_AP/mmi-pcba.cfg"
init_config
load_config // /cache/FTM_AP/mmi.cfg 初始化该配置文件,解析各个模块的测试要求 , 保存module_info数据到数据结构: g_ordered_modules g_modules_map
init_lang //加载语言、字体配置
init_layout // /*Load more layout */ /etc/mmi/layout/ 目录下的各种layout文件 各种layout.xml文件创建一个layout数据
--> load_layout 解析各个layout文件,并根据解析创建button等控件,保存其数据在对象layout中
g_layout_map:保存各个已经初始化后的layout对象
init_module_mode /*Initial all module running mode */ 迭代g_ordered_modules 指明所有模块的运行模式:module_info->mode = g_test_mode(ffbm-02)
init_nodup_map /*Initial the duplicate module map */ 迭代g_ordered_modules 在所有运行同一个lib库的模块中只保存最后一个数据:g_nodup_modules_map
g_res_file // /cache/FTM_AP/mmi.res 保存各种测试项的结果
post_config
restore_result /**Restore the latest result*/ g_res_file // MMI_ALOGI("start post config");
--> 根据g_res_file文件初始化各个模块的最近测试结果:module_info- >result = SUCCESS;
init_controller
--> /* used to store diag,debug module */ < string, module_info * > g_controller_map;
new module_info(CLIENT_DIAG_NAME) /**Init Diag module*/ /**Diag control mmi commands list*/
new module_info(CLIENT_DEBUG_NAME) /**Init debug module*/
g_controller_map : CLIENT_DIAG_NAME、CLIENT_DEBUG_NAME
build_main_ui
--> //MMI_ALOGI("start build main ui");
set_main_module(mod); /**Initial main module*/ 设定当前mod为主进程模块:g_main_module
write_file /**Turn on backlight*/
lay->m_listview->set_items(&g_ordered_modules); //初始化主界面main的listview
--> set_items //skip "MMI" module //skip "disabled" modules
--> m_item_per_page 一页10项
--> m_items.push_back(item);
switch_cur_layout_locked //切换当前layout为提供的模块
--> acquire_cur_layout
--> g_cur_layout = lay; g_cur_layout->module = mod;
--> release_cur_layout
register_home_screen /**register the main screen*/
--> g_home_screens.push_back(lay);
update_main_status
--> 更新主main.xml中的main_status
--> 内容:"%d P | %d F | %d L | %d R | %s %% B", pass_num, fail_num, remain_num,total_num, 电量
--> // MMI_ALOGD("pass item: %d, fail item: %d, remain item: %d\n", pass_num, fail_num, remain_num);
invalidate
start_threads
--> // MMI_ALOGI("start create threads");
create_input_threads
--> init_input /**Intial input system*/
--> pthread_mutex_init; // 创建互斥锁 runnable_mutex:没用到 g_listener_mutex:关于注册输入事件input监听
--> sem_init; // 初始化信号灯 g_sem_runable:输入事件的处理 并发调用
--> ev_init(input_callback, NULL);
--> opendir("/dev/input"); // 只打开event相关的设备文件
--> ioctl epoll_ctl /* read the evbits of the input device */
--> ev_fdinfo[ev_count].cb = input_cb;
input event回调:input_callback
* EV_SYN:- 用于事件间的分割标志。事件可能按时间或空间进行分割,就像在多点触摸协议中的例子。
* EV_KEY:- 用来描述键盘,按键或者类似键盘设备的状态变化。
* EV_REL:- 用来描述相对坐标轴上数值的变化,例如:鼠标向左方移动了5个单位。
* EV_ABS:-用来描述相对坐标轴上数值的变化,例如:描述触摸屏上坐标的值。
* EV_MSC:- 当不能匹配现有的类型时,使用该类型进行描述。
* EV_SW:- 用来描述具备两种状态的输入开关。
* EV_LED:- 用于控制设备上的LED灯的开和关。
* EV_SND:- 用来给设备输出提示声音。
* EV_REP:-用于可以自动重复的设备(autorepeating)。
* EV_FF:- 用来给输入设备发送强制回馈命令。(震动?)
* EV_PWR:- 特别用于电源开关的输入。.
* EV_FF_STATUS:- 用于接收设备的强制反馈状态。
--> ev_get_input
--> adjust_ev /**Adjust the value to match LCD resolution*/
--> hook_vkey /**Convert virtual key to KEY code*/
--> invoke_listener /**Call listener 把input event 传给监听的listener
--> EV_KEY :key_callback(ev.type, ev.code, ev.value);
EV_SW:sw_callback(ev.type, ev.code, ev.value);
EV_ABS || EV_SYN :touch_callback(&ev); --> process_touch_up --> enqueue_runnable_locked(&g_runnable_queue, r); //event 入列
--> get_ts_resolution // 获取触屏分辨率信息 touchscreen resolution input device name: msg22xx
--> pthread_create(&g_input_waiting_tid, NULL, input_waiting_thread, NULL);
--> ev_wait --> epoll_wait //等待之前ev_init设定的epollfd 监听事件
--> ev_dispatch --> cb(fdi->fd, polledevents[n].events, fdi->data); // cb 为input_cb (input_callback)(fd_info->cb)
--> pthread_create(&g_input_handle_tid, NULL, input_handle_thread, NULL);
--> dequeue_runnable_locked //event出列
--> r->cb(r->module); //layout.xml 中的button控件 onclick函数