我是靠谱客的博主 陶醉抽屉,这篇文章主要介绍Qcom_Sensor(五)--- 之 Android SensorDaemon服务端流程解析,现在分享给大家,希望可以做个参考。

Qcom_Sensor(五)--- 之 Android SensorDaemon服务端流程解析

    • SensorDaemon启动
    • Sensor_init 过程



在前面的文章中,我们分析到Sensor HAL层的启动以及数据获取过程,
我们提到,SensorContext以及Sensor在初始化的时候会通过sensor1_open创建一个客户端的socket,
这个socket会不停的从服务端读取数据,并通过注册的回调来处理得到的数据
,这个服务端的socket就是我们今天分析的主角,SensorDaemon守护进程,

那么SensorDaemon在Sensor架构中到底起着怎样的作用呢? 我们拭目以待。

SensorDaemon启动

SensorDaemon是在init阶段通过device/qcom/common/rootdir/etc/init.qcom.rc中配置启动的。

复制代码
1
2
3
4
5
6
service sensors /system/bin/sensors.qcom class late_start user root group root disabled

因此我们直接跟进其main方法,相关的代码路径在vendor/qcom/proprietary/sensors/dsps/sensordaemon中,
而main方法定义在文件sns_main.c中。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*! @brief "Main" function for the sensor daemon process. Handles starting the process, initializing sockets and sensor1 API, and blocking for incoming data on sockets. @param[i] argc: Count of arguments on the command line. @param[i] argv: Array of strings contaning command line arguments. @return 0 - no error */ /*=========================================================================*/ int main( int argc, char *argv[] ) { sensor1_error_e sns_err; sns_main_data_s *srv_data; bool error = FALSE; pthread_mutexattr_t attr; if( 'd' == getopt( argc, argv, "d" ) ) { /* Put ourselves in a background daemon process */ sns_main_daemonize(); } else { printf("Use option "-d" to run as background process.n"); printf("Running in foreground...n"); } /* Start up the sensor library */ sns_err = sensor1_init(); if( SENSOR1_SUCCESS != sns_err ) { SNS_PRINTF_STRING_ERROR_1( SNS_DBG_MOD_APPS_MAIN, "Exiting! sensor1_init failed with %d", sns_err ); exit(6); } /* Initialize mutex */ pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK ); pthread_mutex_init( &sns_main_data_mutex, &attr ); /* Initialize server */ srv_data = sns_main_setup(); if( NULL == srv_data ) { SNS_PRINTF_STRING_ERROR_0( SNS_DBG_MOD_APPS_MAIN, "Exiting! Can't setup server socket" ); exit(4); } /* Check to ensure sensors are enabled */ sns_main_check_enabled( srv_data ); /* Drop all root privs */ error = sns_main_drop_root(); if( error != false ) { SNS_PRINTF_STRING_ERROR_0( SNS_DBG_MOD_APPS_MAIN, "Error dropping root privs. Exiting" ); exit(5); } initialized = true; sns_monitor_adsp_restart(); utime(SENSOR_CTL_SOCKET, NULL); while( !error ) { error = sns_main_sock_handle( srv_data ); } SNS_PRINTF_STRING_ERROR_1( SNS_DBG_MOD_APPS_MAIN, "Exiting! Err %d", error ); return 0; }

这里首先也调用了sensor1_init来初始化sensor,
这里的sensor1_init方法并不是之前libsensor1中的方法了,而是SensorDaemon自己定义的,
他在sns_acm.c中,这个文件是作为我们的application client manager来运作的,负责和后面会讲到的Sensor Message Router(SMR)通信以传递客户端请求到SensorManager(SMGR),并回传response给到对应的客户端,
init的内容最后会分析,这里先跳过。

server的初始化时在sns_main_setup方法中完成的,我们接下来分析这个方法。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
static sns_main_data_s* sns_main_setup( void ) { sns_main_data_s *srv_data; int error; srv_data = malloc( sizeof(*srv_data) ); if( NULL == srv_data ) { SNS_PRINTF_STRING_ERROR_0( SNS_DBG_MOD_APPS_MAIN, "malloc error" ); return NULL; } memset( srv_data, 0, sizeof(*srv_data) ); if( 0 != sns_main_setup_srv_sock( srv_data ) ) { free(srv_data); return NULL; } srv_data->enabled = true; srv_data->inotify_fd = inotify_init(); if( srv_data->inotify_fd == -1 ) { SNS_PRINTF_STRING_ERROR_1( SNS_DBG_MOD_APPS_MAIN, "inotify_init error %d", errno ); free(srv_data); return NULL; } error = pipe2( wakeup_pipe, O_NONBLOCK ); if( error != 0 ) { SNS_PRINTF_STRING_ERROR_1( SNS_DBG_MOD_APPS_MAIN, "pipe2 error %d", errno ); free(srv_data); return NULL; } return srv_data; }

首先通过sns_main_setup_srv_sock来创建server端的socket,通过bind,listen进行监听客户端的连接,这里的客户端就是我们的sensor1_open中创建的socket。我们回顾下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
sensor1_error_e sensor1_open( sensor1_handle_s **hndl, sensor1_notify_data_cb_t data_cbf, intptr_t cb_data ) { int sockfd; int retries, eacces_retries; int err; socklen_t len; struct sockaddr_un address; libsensor_client_data_s new_cli; struct timespec open_timeout; if( NULL == hndl ) { return SENSOR1_EBAD_PTR; } /* Call sensor1_init() here, in case the client failed to do it */ sensor1_init(); new_cli.data_cbf = data_cbf; new_cli.cb_data = cb_data; if( !ssc_present ) { LOG_WARN("%s: SSC not present", __func__); return SENSOR1_EFAILED; } if ( (sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1) { LOG_ERROR("%s: Error in socket() %s", __func__, strerror(errno)); return SENSOR1_ENOMEM; }

socket创建完成后,通过pipe方法创建了一个管道,用于唤醒及主线程退出。

复制代码
1
2
3
4
5
6
/* Wakeup file descriptors, used to wake up and exit the main thread */ static int wakeup_pipe[2]; error = pipe2( wakeup_pipe, O_NONBLOCK );

接着往下,socket创建完毕后,会读取系统中的一个setting文件,来确认sensor是否使能,这个方法是sns_main_check_enabled。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
static void sns_main_check_enabled( sns_main_data_s *srv_data ) { #ifdef SNS_LA_SIM srv_data->enabled = true; #else static int settings_fd = -1; char enabled; if( settings_fd == -1 ) { settings_fd = open( SENSORS_SETTINGS_DIR "/" SENSORS_SETTINGS_FILE, O_RDONLY | O_NOFOLLOW ); } if( settings_fd != -1 ) { /* File exists. */ /* Set up inotify to be notified of file changes */ inotify_add_watch( srv_data->inotify_fd, SENSORS_SETTINGS_DIR "/" SENSORS_SETTINGS_FILE, IN_CLOSE_WRITE ); /* Read value from settings file, and enable/disable as needed */ lseek( settings_fd, 0, SEEK_SET ); if( 1 == read( settings_fd, &enabled, 1 ) ) { if( enabled == '1' ) { SNS_PRINTF_STRING_HIGH_0( SNS_DBG_MOD_APPS_MAIN, "enabled=true"); srv_data->enabled = true; return; } } else { close( settings_fd ); settings_fd = -1; } } else { /* File does not exist */ SNS_PRINTF_STRING_ERROR_2( SNS_DBG_MOD_APPS_MAIN, "open error: settings file "%s", errno %d", (SENSORS_SETTINGS_DIR "/" SENSORS_SETTINGS_FILE), errno ); if( -1 == inotify_add_watch( srv_data->inotify_fd, SENSORS_SETTINGS_DIR, IN_CREATE ) ) { /* Error creating the watch */ SNS_PRINTF_STRING_ERROR_2( SNS_DBG_MOD_APPS_MAIN, "inotify error: settings path "%s", errno %d", SENSORS_SETTINGS_DIR, errno ); SNS_PRINTF_STRING_ERROR_0( SNS_DBG_MOD_APPS_MAIN, "***Sensor external clients cannot be enabled!!!***" ) } } SNS_PRINTF_STRING_ERROR_0( SNS_DBG_MOD_APPS_MAIN, "enabled=false"); srv_data->enabled = false; #endif /* SNS_LA_SIM */ }

读取的文件即如下:

复制代码
1
2
3
4
5
6
/* file path for sensors settings file */ /* If file exists and contains '0', then disable external sensor clients */ #define SENSORS_SETTINGS_DIR "/persist/sensors" #define SENSORS_SETTINGS_FILE "sensors_settings"

这个文件是在init.qcom.sh中创建的,其逻辑如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# Function to start sensors for DSPS enabled platforms # start_sensors() { if [ -c /dev/msm_dsps -o -c /dev/sensors ]; then chmod -h 775 /persist/sensors chmod -h 664 /persist/sensors/sensors_settings chown -h system.root /persist/sensors/sensors_settings mkdir -p /data/misc/sensors chmod -h 775 /data/misc/sensors start sensors fi } 如果在这个sensors_settings中读到1,则认为sensor是enable状态,设置SensorDaemon的成员属性srv_data->enabled值, 否则sensor处于关闭状态,SensorDaemon将不会接收到达的连接。另外该方法还对文件的修改动作进行了监听,用以动态控制服务端进程的监听机制。 sns_monitor_adsp_restart方法启动了一个线程sns_handle_adsp_restart用于监听adsp端进程的重启动作,重启后会进行一些qmi客户端的初始化动作,我们暂时不关注这里。 如果之前的socket创建没有问题,那么while循环调用sns_main_sock_handle方法进对连接的客户端进行处理,当没有连接事件需要处理时,该函数会block住。 ```c static bool sns_main_sock_handle( sns_main_data_s *data ) { fd_set read_fd; fd_set error_fd; int max_fd; sns_ctl_q_s *ctl_p; sns_ctl_q_s *prev_ctl_p; sensor1_error_e sns_err; int sel_err; bool error = true; max_fd = 0; FD_ZERO( &read_fd ); FD_ZERO( &error_fd ); FD_ADD( data->inotify_fd, &read_fd, max_fd ); FD_ADD( wakeup_pipe[0], &read_fd, max_fd ); if( data->enabled ) { /* Make sure server socket is opened */ if( data->ctl_fd == -1 ) { if( sns_main_setup_srv_sock( data ) != 0 ) { return true; } } if( data->ctl_fd >= 0 ) { FD_ADD( data->ctl_fd, &read_fd, max_fd ); } pthread_mutex_lock(&sns_main_data_mutex); prev_ctl_p = NULL; ctl_p = data->ctl_p; while (NULL != ctl_p) { /* Cleanup any disconnected clients */ if (ctl_p->sock_fd < 0) { if (prev_ctl_p != NULL) { prev_ctl_p->next = ctl_p->next; free(ctl_p); ctl_p = prev_ctl_p->next; } else { /* Handle first node in linked-list */ data->ctl_p = ctl_p->next; free(ctl_p); ctl_p = data->ctl_p; } } else { /* Add client handles to watch */ FD_ADD( ctl_p->sock_fd, &read_fd, max_fd ); prev_ctl_p = ctl_p; ctl_p = ctl_p->next; } } pthread_mutex_unlock(&sns_main_data_mutex); } else { /* Not enabled. Make sure server socket is closed */ if( data->ctl_fd >= 0 ) { unlink(SENSOR_CTL_SOCKET); close( data->ctl_fd ); } data->ctl_fd = -1; } error_fd = read_fd; max_fd++; errno = 0; RETRY_ON_EINTR(sel_err, select( max_fd, &read_fd, (fd_set *)NULL, &error_fd, (struct timeval*) NULL)); if (sel_err < 0 ) { return error; } if( FD_ISSET( wakeup_pipe[0], &read_fd ) ) { return error; } if( FD_ISSET( data->inotify_fd, &read_fd ) ) { /* Change in settings file */ char buf[500]; struct inotify_event *evt = (struct inotify_event *)buf; read(data->inotify_fd, evt, 500); if(evt->mask & IN_IGNORED) { /* Previous watch was removed. Nothing to do here */ } else if(evt->len == 0 || ( (evt->mask & IN_CREATE) && (0 == strncmp( evt->name, SENSORS_SETTINGS_FILE, evt->len)))) { inotify_rm_watch( data->inotify_fd, evt->wd ); sns_main_check_enabled( data ); } } /* Check to make sure sensors is enabled */ if( !data->enabled ) { sns_main_close_all_clients( data ); return false; } if( FD_ISSET( data->ctl_fd, &read_fd ) ) { /* incoming connection on ctl socket */ sns_err = sns_main_handle_ctl_srv_sock( data ); if( SENSOR1_ENOMEM != sns_err && SENSOR1_ENOTALLOWED != sns_err && SENSOR1_SUCCESS != sns_err ) { return true; } } prev_ctl_p = NULL; ctl_p = data->ctl_p; while( NULL != ctl_p ) { bool ctl_sock_err = false; if( (ctl_p->sock_fd >= 0) && FD_ISSET( ctl_p->sock_fd, &read_fd ) ) { /* Incoming data on a control socket */ ctl_sock_err = sns_main_handle_ctl_sock( data, &ctl_p, &prev_ctl_p ); } else { prev_ctl_p = ctl_p; ctl_p = ctl_p->next; } } error = false; return error; } sns_main_sock_handle首先会判断之前创建的ctl_fd是否有效,如果无效,会再次调用sns_main_setup_srv_sock创建有效的服务端socket。 srv_data->ctl_p链表则存储着所有客户端的链接结构,一旦链表非空,说明有数据达到,将链表中的第一个取出来处理; 通过select轮询读端read_fd,这里加入了两个,一个是inotify_fd用于监听前面settings文件的修改,另一个是我么能通过pipe创建的唤醒读端。 如果数据达到了,则会调用sns_main_handle_ctl_srv_sock来处理。 ```c static sensor1_error_e sns_main_handle_ctl_srv_sock( sns_main_data_s *data ) { sensor1_error_e sns_err; sns_ctl_q_s *new_ctl = malloc(sizeof(sns_ctl_q_s)); struct ucred cred; socklen_t len; int sns_ctl_unprivileged = 0; new_ctl->next = NULL; new_ctl->privileged_user = false; new_ctl->sock_fd = accept( data->ctl_fd, NULL, NULL ); if( -1 == new_ctl->sock_fd ) { free(new_ctl); return SENSOR1_EUNKNOWN; } else { sns_main_set_non_blocking( new_ctl->sock_fd ); /* get peer credentials- uid, gid, pid */ len = sizeof(struct ucred); if (getsockopt(new_ctl->sock_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) != -1) { SNS_PRINTF_STRING_LOW_3( SNS_DBG_MOD_APPS_MAIN, "Client PID=%d GID=%d UID=%d",(int)cred.pid,(int)cred.gid,(int)cred.uid ); if (sns_main_validate_group_access(&cred)) { new_ctl->privileged_user = true; } else { sns_ctl_q_s *ctl_p = data->ctl_p; while (NULL != ctl_p) { if (false == ctl_p->privileged_user) { sns_ctl_unprivileged++; } ctl_p = ctl_p->next; } if (sns_ctl_unprivileged > MAX_UNPRIVILEGED_CONN) { return SENSOR1_ENOTALLOWED; } } } else { SNS_PRINTF_STRING_ERROR_1( SNS_DBG_MOD_APPS_MAIN, "getsockopt returned error %d",errno ); close(new_ctl->sock_fd); free(new_ctl); return SENSOR1_ENOTALLOWED; } sns_err = sensor1_open( &new_ctl->sensor1_hndl, sns_main_notify_cb, (intptr_t)new_ctl ); if( SENSOR1_SUCCESS != sns_err ) { if(SENSOR1_ENOMEM == sns_err ) { sns_main_send_open_resp( new_ctl->sock_fd, SENSOR1_EWOULDBLOCK ); } close(new_ctl->sock_fd); free(new_ctl); } else { SNS_PRINTF_STRING_LOW_2( SNS_DBG_MOD_APPS_MAIN, "Incoming connection success! fd %d." "sensor1 handle 0x%"PRIxPTR, new_ctl->sock_fd, (uintptr_t)new_ctl->sensor1_hndl ); sns_main_add_ctl_cli( data, new_ctl ); sns_main_send_open_resp( new_ctl->sock_fd, SENSOR1_SUCCESS ); } } return sns_err; }

新建一个new_ctl链表,通过accept接受连接,如果连接fd有效,则设置非阻塞模式,再为这个new的fd通过sensor1_open注册一个回调方法sns_main_notify_cb,这个sensor1_open并非libsensor1中的那个,而是sensorDaemon自己的,定义在sns_acm.c中,如果open成功,则会调用sns_main_add_ctl_cli加到链表中,并且向client端发送open成功的消息。

这里创建的sns_main_notify_cb在什么情况下回回调呢?应该和之前的sensor1_open(libsensor1)一样,有个读线程来将其唤醒。

由于这里的sensor1_open调用的是sns_acm.c中的open,因此我们还是应该再这个文件里面找答案。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// vendor/qcom/proprietary/sensors/dsps/sensordaemon/apps/common/acm/src/sns_acm.c sensor1_error_e sensor1_open( sensor1_handle_s **hndl, sensor1_notify_data_cb_t notify_cb, intptr_t cb_data ) { sensor1_error_e rv; // Return value sensor1_handle_s *c_ptr; sns_log_sensor1_request_s *log_ptr; c_ptr = sns_acm_new_client_handle(); SNS_ACM_DEBUG1( LOW, "sensor1_open: allocating client %d", sns_acm_get_client_index( c_ptr ) ); if( NULL == c_ptr ) { hndl = NULL; SNS_PRINTF_STRING_ERROR_0( SNS_DBG_MOD_ACM, "sensor1_open: can't allocate client handle" ); rv = SENSOR1_ENOMEM; } else { c_ptr->notify_cb = notify_cb; c_ptr->notify_data = cb_data; *hndl = c_ptr; rv = SENSOR1_SUCCESS; } /* Generate and send log message */ sns_logpkt_malloc( SNS_LOG_SENSOR1_REQUEST, sizeof(sns_log_sensor1_request_s), (void**)(&log_ptr) ); if( NULL != log_ptr ) { sns_acm_log_api_call( SNS_LOG_SENSOR1_API_OPEN, (int32_t)rv, c_ptr, NULL, log_ptr ); } return rv; }

这里传入的notify_cb为sns_main_notify_cb,最终会赋值给类型为sensor1_handle_s的hndl句柄的notify_cb函数指针。

既然有了这个notify cb,那就一定有地方会调用它,我们在文件中发现只有一个sns_acm_handle_rx方法会调用他:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
void sns_acm_handle_rx( void * msg_ptr ) { sns_smr_header_s smr_header; sensor1_msg_header_s msg_hdr; sensor1_handle_s *client_ptr; sensor1_msg_type_e msg_type; uint8_t err; sns_smr_get_hdr( &smr_header, msg_ptr ); if( sns_acm_max_clients() <= smr_header.ext_clnt_id ) { SNS_PRINTF_STRING_ERROR_1( SNS_DBG_MOD_ACM, "bad client ID %dn", (int32_t)smr_header.ext_clnt_id ); sns_smr_msg_free( msg_ptr ); return; } client_ptr = sns_acm_client_handle( smr_header.ext_clnt_id ); msg_hdr.service_number = smr_header.svc_num; msg_hdr.msg_id = smr_header.msg_id; msg_hdr.txn_id = smr_header.txn_id; msg_hdr.msg_size = smr_header.body_len; sns_os_mutex_pend( sns_acm_db_mutex, 0, &err ); if( 0 == err ) { if ( smr_header.msg_type == SNS_SMR_MSG_TYPE_RESP ) { msg_type = SENSOR1_MSG_TYPE_RESP; client_ptr->outstanding_reqs--; sns_acm_peek_response( client_ptr, &msg_hdr, msg_ptr ); } else if ( smr_header.msg_type == SNS_SMR_MSG_TYPE_RESP_INT_ERR ) { msg_type = SENSOR1_MSG_TYPE_RESP_INT_ERR; client_ptr->outstanding_reqs--; sns_acm_peek_resp_error( client_ptr, &msg_hdr ); } else { msg_type = SENSOR1_MSG_TYPE_IND; } if( (SNS_ACM_CLI_STATE_OPENED == client_ptr->cli_state) && (NULL != client_ptr->notify_cb) ) { SNS_ACM_DEBUG1( LOW, "Delivering message to client %d", smr_header.ext_clnt_id ); sns_os_mutex_pend( sns_acm_log_mutex, 0, &err ); if( 0 == err ) { sns_acm_log_resp_or_ind( client_ptr, msg_type, &msg_hdr, msg_ptr ); sns_os_mutex_post( sns_acm_log_mutex ); } else { SNS_PRINTF_STRING_ERROR_1( SNS_DBG_MOD_ACM, "Error %d getting log mutex", (int32_t)err ); } client_ptr->notify_cb( client_ptr->notify_data, &msg_hdr, msg_type, msg_ptr ); } else { sns_smr_msg_free( msg_ptr ); } sns_os_mutex_post( sns_acm_db_mutex ); } else { SNS_PRINTF_STRING_ERROR_1( SNS_DBG_MOD_ACM, "Error %d getting mutex", (int32_t)err ); sns_smr_msg_free( msg_ptr ); } }

那么sns_acm_handle_rx方法又是谁驱动的呢?在/vendor/qcom/proprietary/sensors/dsps/sensordaemon/apps/common/acm/src/sns_acm_mr.c中被调用。

继续往回追,最终我们发现其逻辑如下,就是我们开头main方法中调过的sensor1_init方法:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
main() --> sns_main.c sns_init-->sns_init_la.c sns_init_once--> sns_init_la.c ==> sns_init_sns_err = init_ptrs[i].fcn(); sns_acm_init--> /vendor/xxx/xx/sns_acm.c sns_os_task_create--> sns_acm_rx_thread--> sns_acm_mr_handle--> /vendor/xx/xx/sns_acm_mr.c sns_acm_handle_rx-> client_ptr->notify_cb()

Sensor_init 过程

开头讲main函数的时候,我们直接跳过了sensor1_init的调用而直接分析了service的创建过程。这里我们跟进下init的过程。

复制代码
1
2
3
4
5
6
7
8
9
10
sensor1_error_e sensor1_init( void ) { #if defined( SNS_BLAST ) return SENSOR1_SUCCESS; #else return (sensor1_error_e) sns_init(); #endif }

这里走的是else分支调用sns_init,继续:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
sns_err_code_e sns_init( void ) { sns_init_sns_err = SNS_SUCCESS; if( 0 == pthread_once( &sns_init_once_ctl, sns_init_once ) ) { /* sns_init_once will update the error code, if necessary */ return sns_init_sns_err; } else { return SNS_ERR_FAILED; } }

可以看到,这里的init方式和libsensor1的方式是一样的,
都是通过启动一个线程在线程里进行初始化工作,并且该初始化只会执行一次。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* Call each module's init function */ for( i = 0; NULL != init_ptrs[i].fcn; i++ ) { SNS_PRINTF_STRING_HIGH_1(SNS_DBG_MOD_APPS_INIT, "initializing %s", (intptr_t)init_ptrs[i].fcn_name); sns_init_sns_err = init_ptrs[i].fcn(); if( SNS_SUCCESS != sns_init_sns_err ) { SNS_PRINTF_STRING_ERROR_2(SNS_DBG_MOD_APPS_INIT, "Error %d initializing %s", sns_init_sns_err, (intptr_t)init_ptrs[i].fcn_name); return; } SNS_PRINTF_STRING_HIGH_1(SNS_DBG_MOD_APPS_INIT, "Waiting for %s...", (intptr_t)init_ptrs[i].fcn_name); sem_wait( &sns_init_sem ); SNS_PRINTF_STRING_HIGH_1(SNS_DBG_MOD_APPS_INIT, "Done waiting for %s", (intptr_t)init_ptrs[i].fcn_name); }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# define SNS_INIT_FUNCTIONS { { sns_memmgr_init, "sns_memmgr_init" }, { sns_debug_test_init1, "sns_debug_test_init1" }, { sns_pwr_init, "sns_pwr_init" }, { sns_em_init, "sns_em_init" }, { sns_reg_init, "sns_reg_init" }, { sns_time_init, "sns_time_init" }, { sns_sam_init, "sns_sam_init" }, { sns_file_init, "sns_file_init" }, { sns_acm_init, "sns_acm_init" }, { NULL, ""} } # define SNS_INIT_OPT_FUNCTIONS { { sns_debug_test_init2, "sns_debug_test_init2" }, { NULL, ""} }

sns_init_once方法主体就是轮询init_ptrs结构体,将其定义的各个模块的init方法统统调用一遍,完成init,而这里涉及的acm_init就是在这里调用的。
init方法中还会有很多Qualcomm common client interface(QCCI)和Qualcomm common server interface(QCSI)相关的内容,我们会在后面详细分析这些具体的用于通信的API调用过程, 敬请关注。

所以回到前面,
SensorDaemon的open过程注册的notify_cb是上面的流程处理的,即这是modem端抛给SensorDaemon的数据,SensorDaemon在将此数据通过socket传递到hal层,
hal层再根据各个sensor自身数据结构将数据封装成sensor_event_t结构体,插入到Queue中,SensorService通过poll方法从这个Queue中读取数据,将此数据传递给对应的app。

最后

以上就是陶醉抽屉最近收集整理的关于Qcom_Sensor(五)--- 之 Android SensorDaemon服务端流程解析的全部内容,更多相关Qcom_Sensor(五)---内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(82)

评论列表共有 0 条评论

立即
投稿
返回
顶部