我是靠谱客的博主 陶醉抽屉,最近开发中收集的这篇文章主要介绍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中配置启动的。

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服务端流程解析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部