概述
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中配置启动的。
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中。
/*!
@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方法中完成的,我们接下来分析这个方法。
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。我们回顾下:
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方法创建了一个管道,用于唤醒及主线程退出。
/* 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。
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 */
}
读取的文件即如下:
/* 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中创建的,其逻辑如下:
# 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,因此我们还是应该再这个文件里面找答案。
// 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方法会调用他:
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方法:
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的过程。
sensor1_error_e sensor1_init( void )
{
#if defined( SNS_BLAST )
return SENSOR1_SUCCESS;
#else
return (sensor1_error_e) sns_init();
#endif
}
这里走的是else分支调用sns_init,继续:
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的方式是一样的,
都是通过启动一个线程在线程里进行初始化工作,并且该初始化只会执行一次。
/* 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);
}
# 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(五)--- 之 Android SensorDaemon服务端流程解析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复