Android Sensor HAL層初始化流程(基於Qualcomm平臺)
從Android Native到HAL原始碼剖析,以sensor為例 一文中,我們分析到sensor通過hw_get_module以及sensors_open_1去load HAL層的庫以及開啟我們的sensor裝置,今天我們的文章就來分析這兩部分的流程。
Sensor HAL開啟/初始化過程
進入我們的hal模組,sensors_open,該方法實現在vendor/qcom/proprietary/sensors/dsps/libhalsensors/src/sensors_hal.cpp中,其方法體如下:
static int sensors_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device) { UNREFERENCED_PARAMETER(id); int ret = -EINVAL; SensorsContext *dev = SensorsContext::getInstance(); memset(&dev->device, 0, sizeof(sensors_poll_device_1_t)); dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_3; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = sensors_close; dev->device.activate = sensors_activate; dev->device.setDelay = sensors_set_delay; dev->device.poll = sensors_poll; dev->device.batch = sensors_batch; dev->device.flush = sensors_flush; *device = &dev->device.common; ret = 0; return ret; }
從方法體中,將hw_module_t結構體進行方法填充,其中最主要的一個是獲取SensorContext的單例物件,我們重點關注這個SensorContext物件。
SensorsContext::SensorsContext() : active_sensors(0), is_accel_available(false), is_gyro_available(false), is_mag_available(false), is_prox_available(false), smgr_version(0) { int i; int err; /* Enable logging */ enableLogging(); HAL_LOG_INFO("%s", __FUNCTION__); /* Release wakelock if it is NOT due to any reason */ release_wake_lock( SENSORS_WAKE_LOCK ); /* Init sensor1 before every sensor1 connection */ sensor1_init(); /* get the data_cb form the Utility class*/ data_cb = Utility::getDataCb(); /* smgr_sensor1_cb is used by the SMGR sensor1 connection */ smgr_sensor1_cb = SMGRSensor::getSMGRSensor1Cb(); /* sensor_info_sensor1_cb is used by the getting the SMGR sensor list */ sensor_info_sensor1_cb = new hal_sensor1_cb_t; memset(sensor_info_sensor1_cb, 0, sizeof(*sensor_info_sensor1_cb)); sensor_info_sensor1_cb->is_resp_arrived = false; sensor_info_sensor1_cb->error = false; /* Init the mSensors */ for( i = 0; i < MAX_NUM_SENSORS; i++ ) { mSensors[i] = NULL; } /* open the general SMGR sensors sensor1 connection */ err = sensor1_open(&smgr_sensor1_cb->sensor1_handle, &SMGRSensor_sensor1_cb, (intptr_t)this); if(SENSOR1_SUCCESS != err) { HAL_LOG_ERROR("sensor1 open failed!"); return; } /* open the sensor_info SMGR sensors sensor1 connection */ err = sensor1_open(&sensor_info_sensor1_cb->sensor1_handle, &context_sensor1_cb, (intptr_t)this); if(SENSOR1_SUCCESS != err) { HAL_LOG_ERROR("sensor1 open failed!"); return; } /* Check the NV3801 for Magnetic sensor source */ checkMagCalSource(); /* Init the mutex and cond */ pthread_mutex_init(&active_mutex, NULL); pthread_mutex_init(&(sensor_info_sensor1_cb->cb_mutex), NULL); pthread_cond_init(&(sensor_info_sensor1_cb->cb_cond), NULL); /* Time Service */ time_service = TimeSyncService::getTimeSyncService(); char wu_sensor[PROPERTY_VALUE_MAX] = "false"; property_get( HAL_PROP_WU_SENSORS, wu_sensor, "true" ); if (!strncmp("true", wu_sensor, 4)) { HAL_LOG_DEBUG("%s: Wake Up Sensors are enabled!", __FUNCTION__); } else { HAL_LOG_DEBUG("%s: Wake Up sensors disabled!", __FUNCTION__); } err = sendSMGRVersionReq(); if (err) { HAL_LOG_ERROR("%s: SMGR version request failed!", __FUNCTION__); } err = getSensorList(); if (err) { HAL_LOG_ERROR("%s: get sensor list failed!", __FUNCTION__); } for (i=0; i < ARRAY_SIZE(g_sensor_list_order); i++) { int handle = g_sensor_list_order[i]; /* Skip SMGR sensors as they are added above - in getSensorList */ if (handle < SAM_HANDLE_BASE) continue; /* Skip wake up sensors if they aren't enabled */ if (!strncmp("false", wu_sensor, 5) && ((handle < SAM_HANDLE_BASE && handle >= WU_HANDLE_BASE) || (handle < TXN_ID_BASE && handle >= WU_SAM_HANDLE_BASE))) continue; if (is_accel_available || handle == HANDLE_PROXIMITY || handle == HANDLE_PROXIMITY_NON_WAKE_UP || handle == HANDLE_SPEED_PULSE) { addSensor(handle); } } err = updateSensorList(); if (err) { HAL_LOG_ERROR("%s: update sensor list failed!", __FUNCTION__); } /* Close the sensor_info_sensor1_cb sensor1 connection and clean the data */ sensor1_close(sensor_info_sensor1_cb->sensor1_handle); pthread_mutex_destroy(&sensor_info_sensor1_cb->cb_mutex); pthread_cond_destroy(&sensor_info_sensor1_cb->cb_cond); delete sensor_info_sensor1_cb; /* Enable latency check */ Latency::latencyCheckMeasure(); }
進入SensorContext構造方法中,先將幾個屬性設定,比如當前存活的sensors數量,將加速度,陀螺儀,磁力等支援情況預設設定為false,後面根據實際的sensor情況在更新這些值。
其主要的工作如下:
1. 根據系統property屬性開啟log開關(提示:可以將persist.debug.sensors.hal屬性置為1,將會在開機log中抓取到sensor hal層的log)
2. 呼叫sensor1_init初始化
3. 開啟SMGR(SensorManager) 連線,傳入SMGRSensor_sensor1_cb以及context_sensor1_cb用於接收請求回傳的資料
4. 通過getSensorList獲取sensor列表,新增完成通過addSensor去新增已經預定義好的sensor
5. updateSensorList去更新/填充sensor結構體
接下來我們跟進sensor1_init分析。
sensor1 API詳解
sensor1_init是qualcomm sensor結構中sensor1的標準介面,其API介面包括如下:sensor1_error_e
sensor1_init( void );
API說明:
初始化sensor framework層,該方法應該再一個執行緒中處理,且只會呼叫一次。
sensor1_error_e
sensor1_open( sensor1_handle_s **hndl,
sensor1_notify_data_cb_t data_cbf,
intptr_t cb_data );
API說明:註冊一個外部client端socket到sensor framework,它會返回一個client端的handle控制代碼,這個控制代碼在後面會用於與sensor framework通訊。另外,他還註冊了一個callback,當有可用的資料達到時,會攜帶資料並回調該介面。receive的資料有兩種,一種是通過request請求得到的迴應reponse,一種是indication,即底層主動上報的資料。
sensor1_error_e
sensor1_close( sensor1_handle_s *hndl );
API說明:
登出之前open註冊的client,並且釋放分配的handle控制代碼。
sensor1_error_e
sensor1_write( sensor1_handle_s *hndl,
sensor1_msg_header_s *msg_hdr,
void *msg_ptr );
API說明:
向sensor framewok層寫入一個request msg,這個訊息最終會被QMI IDL封裝成C型別的用於傳輸。其中的msg_ptr需要使用sensor1_alloc_msg_buf分配記憶體後方可使用,如果client端傳送成功,隨後由sensor framework釋放記憶體,如果傳送失敗需要由client主動釋放(或者重傳)。
sensor1_error_e
sensor1_writable( sensor1_handle_s *hndl,
sensor1_write_cb_t cbf,
intptr_t cb_data,
uint32_t service_number );
API說明:
向sensor framework註冊一個callback,當framework中有可用的buffer空間來處理sensor1_write的請求時,callback將會被回撥通知lient端。注意:同時只有一個回撥被註冊進去,如果重複呼叫,將會產生覆蓋,且一次後失效。
sensor1_error_e
sensor1_alloc_msg_buf(sensor1_handle_s *hndl,
uint16_t size,
void **buffer );
sensor1_error_e
sensor1_free_msg_buf(sensor1_handle_s *hndl,
void *msg_buf );
API說明:
sensor framework層分配/釋放一段記憶體供客戶端封裝訊息使用。
接著看sensor1_init方法,前面說過,該API用於初始化hal層sensor framework,且只會call一次。sensor1_error_e
sensor1_init( void )
{
LOG_DEBUG("%s", __func__);
pthread_once( &init_ctl, sensor1_init_once );
return SENSOR1_SUCCESS;
}
通過執行緒去呼叫sensor1_init_once進行sensor framework(後文如無特殊宣告,這裡的framework指的是hal層)。void sensor1_init_once( void )
{
struct timespec ts;
int seed,
error,
debug_prop_len,
i;
pthread_mutexattr_t mutex_attr;
pthread_attr_t thread_attr;
char debug_prop[PROP_VALUE_MAX];
debug_prop_len = __system_property_get( LIBSENSOR1_DEBUG_PROP_NAME, debug_prop );
if( debug_prop_len == 1 ) {
switch( debug_prop[0] ) {
case '0':
g_log_level = LOG_LEVEL_DISABLED;
break;
case '1':
g_log_level = LOG_LEVEL_ALL;
break;
case 'v':
case 'V':
g_log_level = LOG_LEVEL_VERBOSE;
break;
case 'd':
case 'D':
g_log_level = LOG_LEVEL_DEBUG;
break;
case 'i':
case 'I':
g_log_level = LOG_LEVEL_INFO;
break;
case 'w':
case 'W':
g_log_level = LOG_LEVEL_WARN;
break;
case 'e':
case 'E':
g_log_level = LOG_LEVEL_ERROR;
break;
default:
break;
}
ALOGI("%s: Setting log level to %d", __FUNCTION__, g_log_level);
} else if( debug_prop_len > 1 ) {
LOG_ERROR("%s: invalid value for %s: %s. Enabling all logs", __FUNCTION__,
LIBSENSOR1_DEBUG_PROP_NAME, debug_prop );
g_log_level = LOG_LEVEL_ALL;
}
LOG_DEBUG("%s", __func__);
#if defined(SNS_LA_SIM)
ssc_present = true;
#else
struct stat stat_buf;
// Check device driver for A-family
ssc_present |= (-1 != stat("/dev/msm_dsps",&stat_buf));
// Check device driver for B-family
ssc_present |= (-1 != stat("/dev/sensors",&stat_buf));
#endif
clock_gettime( CLOCK_REALTIME, &ts );
seed = (int)ts.tv_nsec;
seed += (int)ts.tv_sec;
seed += getpid();
srandom( seed );
if( 0 != sem_init( &open_sem, 0, 0 ) ) {
LOG_ERROR("%s error initializing semaphore %i", __func__, errno );
}
memset( libsensor_cli_data,
0,
sizeof(libsensor_client_data_s) * MAX_CLIENTS );
error = pthread_mutexattr_init( &mutex_attr );
error |= pthread_mutexattr_settype( &mutex_attr, PTHREAD_MUTEX_ERRORCHECK );
if( error != 0 ) {
LOG_ERROR("%s error initializing mutex attribs %d", __func__, error );
}
error = pthread_mutex_init( &libsensor_cli_data_mutex, &mutex_attr );
if( error != 0 ) {
LOG_ERROR("%s error %d initializing mutex", __func__, error );
}
pthread_mutexattr_destroy(&mutex_attr);
error = pipe2( wakeup_pipe, O_NONBLOCK );
if( error != 0 ) {
LOG_ERROR("%s error %d creating wakeup pipe: %s", __func__, errno, strerror(errno) );
}
inotify_fd = inotify_init();
if( inotify_fd == -1 ) {
LOG_ERROR("%s error %d creating inotify listener: %s", __func__, errno, strerror(errno) );
}
pthread_mutexattr_init( &mutex_attr );
pthread_mutexattr_settype( &mutex_attr, PTHREAD_MUTEX_RECURSIVE );
for( i = 0; i < MAX_CLIENTS; i++ )
{
pthread_cond_init( &libsensor_cli_data[i].cb_q_cond, NULL );
pthread_mutex_init( &libsensor_cli_data[i].data_cbf_mutex, &mutex_attr );
pthread_mutex_init( &libsensor_cli_data[i].cb_q_mutex, NULL );
libsensor_cli_data[i].is_valid = false;
libsensor_cli_data[i].ctl_socket = -1;
}
pthread_mutexattr_destroy(&mutex_attr);
if( 0 != ( error = pthread_attr_init( &thread_attr ) ) ) {
LOG_ERROR( "%s pthread_attr_init failure %i", __func__, error );
} else {
if( 0 != ( error = pthread_attr_setdetachstate( &thread_attr, PTHREAD_CREATE_DETACHED ) ) ) {
LOG_ERROR( "%s pthread_attr_setdetachstate failure %i", __func__, error );
} else {
error = pthread_create( &listener_thread_id, &thread_attr,
libsensor_rx_thread, NULL );
}
if( error != 0 ) {
LOG_ERROR("%s error %d initializing thread", __func__, error );
}
pthread_attr_destroy( &thread_attr );
}
}
首先也是通過property去控制libsensor1的log,最後構建了libsensor_rx_thread用於接收來自底層的資料。
我們追蹤下libsensor_rx_thread方法。
static void*
libsensor_rx_thread( void *thread_data )
{
UNREFERENCED_PARAMETER(thread_data);
uint32_t err;
struct pollfd pollfd[MAX_ACTIVE_CLIENTS+2];
int num_fds = 0;
int i;
num_fds = libsensor_cli_db_to_pollfd( pollfd,
MAX_ACTIVE_CLIENTS+2,
POLLIN|POLLPRI );
while( true )
{
if( libsensor_cli_db_changed() ) {
num_fds = libsensor_cli_db_to_pollfd( pollfd,
MAX_ACTIVE_CLIENTS+2,
POLLIN|POLLPRI );
}
/* Note that the wakeup FD and the inotify FD are
* additional FDs at the end of the list after all of the clients */
#ifdef LOG_NDDEBUG
for( i = 0; i < num_fds; i++ ) {
LOG_DEBUG("%s: waiting on fd %d", __func__, pollfd[i].fd);
}
#endif /* LOG_NDDEBUG */
poll( pollfd, num_fds, -1 );
#ifdef LOG_NDDEBUG
if( pollfd[num_fds-2].revents != 0 ) {
LOG_DEBUG("%s: waking on wakeup pipe %d", __func__, pollfd[num_fds-2].fd);
}
#endif /* LOG_NDDEBUG */
for( i = 0; i < num_fds-2; i ++ ) {
if( pollfd[i].revents & (POLLIN|POLLPRI) ) {
LOG_DEBUG("%s: waking on fd %d", __func__, pollfd[i].fd);
err = libsensor_read_socket( pollfd[i].fd );
if( SENSOR1_SUCCESS != err && SENSOR1_EBUFFER != err ) {
libsensor_del_client( pollfd[i].fd );
i = 0;
}
pollfd[i].revents &= ~(POLLIN|POLLPRI);
}
}
if( pollfd[num_fds-1].revents != 0 ) {
char buf[500];
struct inotify_event *evt = (struct inotify_event *)buf;
read(pollfd[num_fds-1].fd, evt, 500);
LOG_DEBUG("%s: inotify: wd %d mask 0x%x name %s", __func__,
evt->wd, evt->mask, (evt->len > 0) ? evt->name:"<empty>");
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, SENSOR_CTL_FILENAME, evt->len)))) {
inotify_rm_watch( inotify_fd, evt->wd );
libsensor_notify_waiting_clients();
}
}
}
LOG_INFO( "%s: thread exiting", __func__ );
return NULL;
}
這裡可以看到,相當於建立了一個讀執行緒,通過poll方法不停的在讀訊息,讀到訊息後,會將訊息封裝,然後喚醒另外一個執行緒,這個執行緒是誰我們後面會揭曉答案。
在回過頭來看,SensorContext的建構函式。
/* open the general SMGR sensors sensor1 connection */
err = sensor1_open(&smgr_sensor1_cb->sensor1_handle, &SMGRSensor_sensor1_cb, (intptr_t)this);
if(SENSOR1_SUCCESS != err) {
HAL_LOG_ERROR("sensor1 open failed!");
return;
}
/* open the sensor_info SMGR sensors sensor1 connection */
err = sensor1_open(&sensor_info_sensor1_cb->sensor1_handle, &context_sensor1_cb, (intptr_t)this);
這幾行程式碼用於向sensor framework層註冊client,且獲得handle控制代碼,傳入callback方法,用於介面write request msg後得到底層資料的回撥。sensor1_open在呼叫sensors1_init完成後,接著建立了一個socket:
sensor1_open( sensor1_handle_s **hndl,
sensor1_notify_data_cb_t data_cbf,
intptr_t cb_data )
{
int sockfd;
/* Call sensor1_init() here, in case the client failed to do it */
sensor1_init();
if ( (sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1)
{
LOG_ERROR("%s: Error in socket() %s", __func__, strerror(errno));
return SENSOR1_ENOMEM;
}
/* connect socket to server */
if( -1 == connect(sockfd, (struct sockaddr *)&address, len) ) {
retries = 0;
eacces_retries = 0;
while( (errno == ENOENT || errno == ECONNREFUSED || errno == EACCES) &&
(retries < OPEN_RETRIES && eacces_retries < OPEN_EACCES_RETRIES) )
{
connect(sockfd, (struct sockaddr *)&address, len);
}
}
if( -1 == bind( sockfd, (struct sockaddr*)&address,
sizeof(address) ) ) {
LOG_ERROR("%s: Error in bind() errno=%d %s",
__func__, errno, strerror(errno));
close( sockfd );
return SENSOR1_EFAILED;
}
new_cli.ctl_socket = sockfd;
if( libsensor_add_client( &new_cli, false ) >= MAX_CLIENTS ) {
LOG_ERROR( "%s: Unable to add new client (%i)", __func__, new_cli.ctl_socket );
close( sockfd );
return SENSOR1_ENOMEM;
}
前面API說明中也有講到,Sensor1_open方法會建立一條客戶端連結,用於連結至sensor framework(server端的socket)。上面讀執行緒(libsensor_rx_thread中建立的libsensor_read_socket)讀到的訊息就是從server端傳送過來的。
static int
libsensor_add_client( libsensor_client_data_s const *cli_data, bool is_wait_clnt )
{
int i,
rv = MAX_CLIENTS,
error,
min_idx = is_wait_clnt ? MAX_ACTIVE_CLIENTS : 0,
max_idx = is_wait_clnt ? MAX_CLIENTS : MAX_ACTIVE_CLIENTS;
pthread_attr_t thread_attr;
pthread_mutex_lock( &libsensor_cli_data_mutex );
for( i = min_idx; i < max_idx; i++ ) {
if( !libsensor_cli_data[i].is_valid && -1 == libsensor_cli_data[i].ctl_socket ) {
LOG_VERBOSE( "%s Adding client index %i (%i)", __func__, i, cli_data->ctl_socket );
libsensor_cli_data[i].cb_data = cli_data->cb_data;
libsensor_cli_data[i].data_cbf = cli_data->data_cbf;
libsensor_cli_data[i].ctl_socket = cli_data->ctl_socket;
libsensor_cli_data[i].is_valid = true;
libsensor_cli_data[i].cb_q_head = NULL;
libsensor_cli_data[i].cb_q_tail = NULL;
// Initialize and start callback thread
if( 0 != ( error = pthread_attr_init( &thread_attr ) ) ) {
LOG_ERROR( "%s pthread_attr_init failure %i", __func__, error );
} else {
if( 0 != ( error = pthread_attr_setdetachstate( &thread_attr, PTHREAD_CREATE_DETACHED ) ) ) {
LOG_ERROR( "%s pthread_attr_setdetachstate failure %i", __func__, error );
} else {
error = pthread_create( &libsensor_cli_data[i].cb_thread, &thread_attr,
libsensor_cb_thread, &libsensor_cli_data[i] );
if( 0 != error ) {
LOG_ERROR( "%s error %d initializing thread", __func__, error );
}
}
}
pthread_attr_destroy( &thread_attr );
rv = i;
break;
}
}
pthread_mutex_unlock( &libsensor_cli_data_mutex );
WAKEUP_RX_THREAD();
return rv;
}
libsensor_add_client方法中又建立了一個callback回撥執行緒,當有訊息達到時,該執行緒喚醒,執行libsensor_cb_thread回撥。我們看看這個回撥的處理:
static void*
libsensor_cb_thread( void *thread_data )
{
libsensor_client_data_s *clnt_data = (libsensor_client_data_s*)thread_data;
sensor1_notify_data_cb_t data_cbf;
intptr_t cb_data = clnt_data->cb_data;
int rc = 0;
libsensor_cb_data_s *data;
pthread_mutex_lock( &clnt_data->cb_q_mutex );
for( ;; ) {
if( NULL == clnt_data->cb_q_head && clnt_data->is_valid ) {
rc = pthread_cond_wait( &clnt_data->cb_q_cond, &clnt_data->cb_q_mutex );
if( 0 != rc ) {
LOG_ERROR( "%s: pthread_cond_wait() rc=%d", __func__, rc );
}
}
while( NULL != (data = clnt_data->cb_q_head) ) {
clnt_data->cb_q_head = (struct libsensor_cb_data*)data->next;
// Need to release, otherwise may have deadlock in libsensor_read_socket
pthread_mutex_unlock( &clnt_data->cb_q_mutex );
// We do not want to continue using the cbf after the client has called
// sensor1_close, but we also do not want to accidentally use a NULL cbf.
pthread_mutex_lock( &clnt_data->data_cbf_mutex );
data_cbf = clnt_data->data_cbf;
pthread_mutex_unlock( &clnt_data->data_cbf_mutex );
if( data_cbf ) {
data_cbf( cb_data, &data->msg_hdr, data->msg_type, data->msg );
}
free( data );
pthread_mutex_lock( &clnt_data->cb_q_mutex );
if( !data_cbf ) {
clnt_data->is_valid = false;
break;
}
}
if( !clnt_data->is_valid )
break;
}
LOG_DEBUG( "%s: Exiting processing thread for socket %i", __func__, clnt_data->ctl_socket );
libsensor_del_client_data( clnt_data->cb_q_head );
clnt_data->cb_q_head = NULL;
clnt_data->cb_q_tail = NULL;
pthread_mutex_unlock( &clnt_data->cb_q_mutex );
pthread_mutex_lock( &libsensor_cli_data_mutex );
close( clnt_data->ctl_socket );
clnt_data->ctl_socket = -1;
pthread_mutex_unlock( &libsensor_cli_data_mutex );
return NULL;
}
那麼這個執行緒是怎樣被喚醒的,當然是sensor1_init在init_once中的那個讀執行緒(libsensor_rx_thread)嘛,沒錯,就是那個執行緒。。。這裡主要注意下面這段:
if( data_cbf ) {
data_cbf( cb_data, &data->msg_hdr, data->msg_type, data->msg );
}
這個方法就是call我們sensor1_open中傳入的引數註冊的那個回調了,即context_sensor1_cb或者SMGRSensor_sensor1_cb,對於具體的sensor資料,當然會回撥open過程註冊的cb了。
總結sensor1_open就是建立一個讀執行緒從socket服務端中讀資料,讀到資料後,就回調sensor.platform.so庫中的註冊的cb,進而上報資料做進一步回撥。
那問題來了,那個socket服務端又是怎麼回事呢。。。慢慢接近真相了。。。。
這裡先告訴大家,服務端就是我們的SensorDaemon守護程序了,這裡暫時不做分析,請關注後續文章。
我們繼續往下分析,sensor1_open完成後向sensor framework傳送了第一個請求:
err = sendSMGRVersionReq();
int SensorsContext::sendSMGRVersionReq()
{
sensor1_error_e error;
sensor1_msg_header_s msg_hdr;
sns_common_version_req_msg_v01 *smgr_version_req;
HAL_LOG_INFO("%s", __FUNCTION__);
pthread_mutex_lock(&sensor_info_sensor1_cb->cb_mutex);
/* Send SMGR version req */
msg_hdr.service_number = SNS_SMGR_SVC_ID_V01;
msg_hdr.msg_id = SNS_SMGR_VERSION_REQ_V01;
msg_hdr.msg_size = sizeof(sns_common_version_req_msg_v01);
msg_hdr.txn_id = 0;
error = sensor1_alloc_msg_buf(sensor_info_sensor1_cb->sensor1_handle,
sizeof(sns_common_version_req_msg_v01),
(void**)&smgr_version_req);
if (SENSOR1_SUCCESS != error) {
HAL_LOG_ERROR("%s: msg alloc failed: %d", __FUNCTION__, error );
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
return -1;
}
sensor_info_sensor1_cb->error = false;
if ((error = sensor1_write(sensor_info_sensor1_cb->sensor1_handle,
&msg_hdr, smgr_version_req)) != SENSOR1_SUCCESS) {
/* free the message buffer */
sensor1_free_msg_buf(sensor_info_sensor1_cb->sensor1_handle, smgr_version_req );
HAL_LOG_ERROR("%s: Error in sensor1_write() %s", __FUNCTION__, strerror(errno));
sensor_info_sensor1_cb->error = true;
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
return -1;
}
/* waiting for response */
if (Utility::waitForResponse(TIME_OUT_MS,
&sensor_info_sensor1_cb->cb_mutex,
&sensor_info_sensor1_cb->cb_cond,
&sensor_info_sensor1_cb->is_resp_arrived) == false) {
HAL_LOG_ERROR("%s: SMGR version request timed out", __FUNCTION__);
sensor_info_sensor1_cb->error = true;
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
return -1;
} else {
HAL_LOG_VERBOSE("%s: Received SMGR version response", __FUNCTION__);
}
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
return 0;
}
通過這個方法,我們可以窺探到client端向sensor framework層傳送請求時的訊息封裝流程了。
首先填充msg_hdr,包括service number,msg_id(SNS_SMGR_VERSION_REQ_V01),txn_id等,再通過sensor1_alloc_msg_buf向Sensor framework層分配smgr_version_req的請求buffer,最後通過sensor1_write方法將請求的訊息傳送到sensor framework,這條訊息最終會通過高通獨有的QMI的機制,將訊息從AP測傳送到modem端處理,modem端處理完畢後會回傳請求的資料在通過註冊的回撥來接收所請求的資料。
這裡的SMGR version請求的最後,通過工具類Utility的方法waitForResponse來等待訊息返回,確認訊息傳送情況。
由於這裡呼叫sensor1_write時我們傳入的handle為sensor_info_sensor1_cb,看到前面open過程中註冊的callback了嗎?所以這裡名為context_sensor1_cb的回撥將會被呼叫。
err = sensor1_open(&sensor_info_sensor1_cb->sensor1_handle, &context_sensor1_cb, (intptr_t)this);
error = sensor1_write(sensor_info_sensor1_cb->sensor1_handle,
&msg_hdr, smgr_version_req))
開啟log開關,我們可以看到具體的訊息傳送流程:
06-04 19:48:04.401 I/qti_sensors_hal: sendSMGRVersionReq
06-04 19:48:04.401 I/libsensor1: libsensor_log_ctl_write_pkt: fd 55; svc 0; msg 1; txn 0; cmd WRITE_QMI
06-04 19:48:04.401 D/qti_sensors_hal: waitForResponse: timeout=1000=
……………………………………省略無關資訊
06-04 19:48:04.404 D/libsensor1: libsensor_rx_thread: waking on fd 55
06-04 19:48:04.404 I/libsensor1: libsensor_log_read_pkt: fd 55; svc 0; msg 1; txn 0; type RESP; cmd WRITE_QMI
06-04 19:48:04.404 V/qti_sensors_hal: context_sensor1_cb: msg_type 1, Sn 0, msg Id 1, txn Id 0
06-04 19:48:04.405 D/qti_sensors_hal: processResp: 1
06-04 19:48:04.405 D/qti_sensors_hal: processResp: SMGR version=23
06-04 19:48:04.405 V/qti_sensors_hal: sendSMGRVersionReq: Received SMGR version response
如上log可知,SMGR的版本為23。這裡讀者大可不必太關注QMI訊息傳送流程,這個流程相當複雜,我後面會單獨講解QMI訊息怎麼封裝,並且通過QMUX客戶端和服務端訊息收發,再到modem的詳細流程,歡迎關注。
獲取sensor列表getSensorList
我們接著往後走便開始獲取sensor的列表了。
int SensorsContext::getSensorList()
{
sensor1_error_e error;
sensor1_msg_header_s msg_hdr;
sns_smgr_all_sensor_info_req_msg_v01 *smgr_req;
sns_smgr_sensor_datatype_info_s_v01* sensor_datatype = NULL;
HAL_LOG_INFO("%s", __FUNCTION__);
pthread_mutex_lock(&sensor_info_sensor1_cb->cb_mutex);
msg_hdr.service_number = SNS_SMGR_SVC_ID_V01;
msg_hdr.msg_id = SNS_SMGR_ALL_SENSOR_INFO_REQ_V01;
msg_hdr.msg_size = sizeof( sns_smgr_all_sensor_info_req_msg_v01 );
msg_hdr.txn_id = 0;
error = sensor1_alloc_msg_buf(sensor_info_sensor1_cb->sensor1_handle,
sizeof(sns_smgr_all_sensor_info_req_msg_v01),
(void**)&smgr_req);
if (SENSOR1_SUCCESS != error) {
HAL_LOG_ERROR("%s: msg alloc failed: %d", __FUNCTION__, error );
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
return -1;
}
sensor_info_sensor1_cb->error = false;
if ((error = sensor1_write(sensor_info_sensor1_cb->sensor1_handle,
&msg_hdr, smgr_req)) != SENSOR1_SUCCESS) {
sensor1_free_msg_buf(sensor_info_sensor1_cb->sensor1_handle, smgr_req );
HAL_LOG_ERROR("%s: Error in sensor1_write() %s", __FUNCTION__, strerror(errno));
sensor_info_sensor1_cb->error = true;
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
return -1;
}
/* waiting for response */
if (Utility::waitForResponse(TIME_OUT_MS,
&sensor_info_sensor1_cb->cb_mutex,
&sensor_info_sensor1_cb->cb_cond,
&sensor_info_sensor1_cb->is_resp_arrived) == false) {
HAL_LOG_ERROR("%s: Request timed out", __FUNCTION__);
sensor_info_sensor1_cb->error = true;
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
return -1;
} else {
HAL_LOG_VERBOSE("%s: Received Response", __FUNCTION__);
}
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
return 0;
}
原理同上面的SMGR version請求,封裝好訊息頭部,msg id為SNS_SMGR_ALL_SENSOR_INFO_REQ_V01,All sensor info, ^_^, 在通過sensor1_write介面將訊息傳送到驅動層處理,最後由驅動層返回sensor info資料。
我們看這個過程的log:
06-04 19:48:04.405 I/qti_sensors_hal: getSensorList
06-04 19:48:04.405 I/libsensor1: libsensor_log_ctl_write_pkt: fd 55; svc 0; msg 5; txn 0; cmd WRITE_QMI
06-04 19:48:04.405 D/qti_sensors_hal: waitForResponse: timeout=1000
06-04 19:48:04.407 D/libsensor1: libsensor_rx_thread: waking on fd 55
06-04 19:48:04.407 I/libsensor1: libsensor_log_read_pkt: fd 55; svc 0; msg 5; txn 0; type RESP; cmd WRITE_QMI
06-04 19:48:04.407 D/libsensor1: libsensor_rx_thread: waiting on fd 54
06-04 19:48:04.407 D/libsensor1: libsensor_rx_thread: waiting on fd 55
06-04 19:48:04.407 D/libsensor1: libsensor_rx_thread: waiting on fd 56
06-04 19:48:04.407 V/qti_sensors_hal: context_sensor1_cb: msg_type 1, Sn 0, msg Id 5, txn Id 0
06-04 19:48:04.407 D/libsensor1: libsensor_rx_thread: waiting on fd 57
06-04 19:48:04.407 D/libsensor1: libsensor_rx_thread: waiting on fd 51
06-04 19:48:04.407 D/qti_sensors_hal: processResp: 5
06-04 19:48:04.407 D/libsensor1: libsensor_rx_thread: waiting on fd 53
06-04 19:48:04.407 D/qti_sensors_hal: processAllSensorInfoResp: SensorInfo_len: 2
可知底層返回的sensor個數為2,即兩個sensor(很奇怪,這裡的資料為2, 根據感測器個數列印,不可能才兩個.....)。
在context_sensor1_cb函式中,由於我們的msg_type為SENSOR1_MSG_TYPE_RESP,如log所示,接著會呼叫processResp處理。
void SensorsContext::processResp(Sensor** mSensors, sensor1_msg_header_s *msg_hdr, void *msg_ptr)
{
HAL_LOG_DEBUG("%s: %d", __FUNCTION__, msg_hdr->msg_id);
switch(msg_hdr->msg_id) {
case SNS_SMGR_VERSION_RESP_V01: {
pthread_mutex_lock(&sensor_info_sensor1_cb->cb_mutex);
sns_common_version_resp_msg_v01* respMsgPtr = (sns_common_version_resp_msg_v01 *)msg_ptr;
if (respMsgPtr->resp.sns_result_t == 0) {
smgr_version = respMsgPtr->interface_version_number;
HAL_LOG_DEBUG("%s: SMGR version=%d", __FUNCTION__, smgr_version);
Utility::signalResponse(false, sensor_info_sensor1_cb);
}
else {
HAL_LOG_ERROR("%s: Error in getting SMGR version!", __FUNCTION__);
Utility::signalResponse(true, sensor_info_sensor1_cb);
}
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
} break;
case SNS_SMGR_ALL_SENSOR_INFO_RESP_V01: {
pthread_mutex_lock(&sensor_info_sensor1_cb->cb_mutex);
processAllSensorInfoResp(
(sns_smgr_all_sensor_info_resp_msg_v01*)msg_ptr);
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
} break;
case SNS_SMGR_SINGLE_SENSOR_INFO_RESP_V01: {
pthread_mutex_lock(&sensor_info_sensor1_cb->cb_mutex);
processSingleSensorInfoResp(mSensors, msg_hdr->txn_id,
(sns_smgr_single_sensor_info_resp_msg_v01*)msg_ptr);
pthread_mutex_unlock(&sensor_info_sensor1_cb->cb_mutex);
} break;
}
return;
}
msg id為SNS_SMGR_ALL_SENSOR_INFO_RESP_V01則會進入processAllSensorInfoResp分支。
void SensorsContext::processAllSensorInfoResp(sns_smgr_all_sensor_info_resp_msg_v01
*smgr_info_resp)
{
uint32_t i;
HAL_LOG_DEBUG("%s: SensorInfo_len: %d", __FUNCTION__,
smgr_info_resp->SensorInfo_len);
if (smgr_info_resp->Resp.sns_result_t != 0) {
HAL_LOG_ERROR("%s: R: %u, E: %u", __FUNCTION__,
smgr_info_resp->Resp.sns_result_t,
smgr_info_resp->Resp.sns_err_t );
Utility::signalResponse(true, sensor_info_sensor1_cb);
return;
}
if (smgr_info_resp->SensorInfo_len > 0) {
num_smgr_sensors = smgr_info_resp->SensorInfo_len;
for (i = 0; i < num_smgr_sensors; i++) {
singleSensorInfoRequest(i, smgr_info_resp->SensorInfo[i].SensorID);
}
} else {
Utility::signalResponse(false, sensor_info_sensor1_cb);
}
return;
}
接著會根據info length(2),開始呼叫singleSensorInfoRequest單獨對每個sensor info進行單獨請求,log如下:
06-04 19:48:04.407 D/qti_sensors_hal: processAllSensorInfoResp: SensorInfo_len: 2
06-04 19:48:04.407 D/qti_sensors_hal: singleSensorInfoRequest: 0
06-04 19:48:04.407 D/qti_sensors_hal: singleSensorInfoRequest: txn_id: 0 sensor_id: 0
06-04 19:48:04.407 I/libsensor1: libsensor_log_ctl_write_pkt: fd 55; svc 0; msg 6; txn 0; cmd WRITE_QMI
06-04 19:48:04.407 D/qti_sensors_hal: singleSensorInfoRequest: 10
06-04 19:48:04.407 D/qti_sensors_hal: singleSensorInfoRequest: txn_id: 1 sensor_id: 10
06-04 19:48:04.407 I/libsensor1: libsensor_log_ctl_write_pkt: fd 55; svc 0; msg 6; txn 1; cmd WRITE_QMI
從上面的log可以看到,我們的這兩個sensor handle id為0和10,查詢對應的sensor handle控制代碼定義,我們發現這兩個sensor是加速度感測器和磁力感測器:
// vendor/qcom/proprietary/sensors/dsps/libhalsensors/src/sensors_hal.h
/* sensor handle */
#define SENSORS_HANDLE_BASE 0
#define HANDLE_ACCELERATION (SENSORS_HANDLE_BASE+0)
#define HANDLE_MAGNETIC_FIELD (SENSORS_HANDLE_BASE+10)
06-04 19:48:04.409 V/qti_sensors_hal: context_sensor1_cb: msg_type 1, Sn 0, msg Id 6, txn Id 0
06-04 19:48:04.409 D/qti_sensors_hal: processResp: 6
06-04 19:48:04.409 D/qti_sensors_hal: processSingleSensorInfoResp: data_type_info_len: 2
06-04 19:48:04.409 D/qti_sensors_hal: processSingleSensorInfoResp: txn: 0, ns: 2
06-04 19:48:04.409 I/qti_sensors_hal: addSensor: handle:0
06-04 19:48:04.409 I/qti_sensors_hal: SMGRSensor: Sensor()
06-04 19:48:04.410 D/qti_sensors_hal: setSensorInfo: Accel, DTy: 0
06-04 19:48:04.410 I/qti_sensors_hal: processSingleSensorInfoResp: sensor1: name: BMI160 Accelerometer, vendor: BOSCH, maxRange: 10283018, res: 78,
power: 180, max_freq: 200 max_buffered_samples: 10000
接著每個具體的sensor info返回時,都會呼叫processSingleSensorInfoResp進一步處理,這個方法很長:
void SensorsContext::processSingleSensorInfoResp(Sensor** mSensors, uint8_t txn_id,
sns_smgr_single_sensor_info_resp_msg_v01* smgr_resp)
{
int i;
int handle = -1, handle_wakeup = -1;
for (i = 0; i < (int)smgr_resp->SensorInfo.data_type_info_len; i++) {
handle = -1, handle_wakeup = -1, error = false;
sensor_datatype = &smgr_resp->SensorInfo.data_type_info[i];
HAL_LOG_DEBUG("%s: txn: %u, ns: %u", __FUNCTION__, txn_id,
(unsigned int)num_smgr_sensors);
switch (sensor_datatype->SensorID) {
case SNS_SMGR_ID_ACCEL_V01:
if(SNS_SMGR_DATA_TYPE_PRIMARY_V01 == sensor_datatype->DataType) {
handle = HANDLE_ACCELERATION;
handle_wakeup = HANDLE_ACCELERATION_WAKE_UP;
is_accel_available = true;
}
else if (SNS_SMGR_DATA_TYPE_SECONDARY_V01 == sensor_datatype->DataType) {
/* Skip secondary data and replace with proper handle if needed */
error = true;
}
break;
case SNS_SMGR_ID_MAG_V01:
if (SNS_SMGR_DATA_TYPE_PRIMARY_V01 == sensor_datatype->DataType) {
handle = HANDLE_MAGNETIC_FIELD;
handle_wakeup = HANDLE_MAGNETIC_FIELD_WAKE_UP;
if (is_accel_available) {
is_mag_available = true;
}
}
else if (SNS_SMGR_DATA_TYPE_SECONDARY_V01 == sensor_datatype->DataType) {
/* Skip secondary data and replace with proper handle if needed */
error = true;
}
break;
case SNS_SMGR_ID_PROX_LIGHT_V01:
if (SNS_SMGR_DATA_TYPE_PRIMARY_V01 == sensor_datatype->DataType) {
handle = HANDLE_PROXIMITY;
handle_wakeup = HANDLE_PROXIMITY_NON_WAKE_UP;
is_prox_available = true;
}
else if (SNS_SMGR_DATA_TYPE_SECONDARY_V01 == sensor_datatype->DataType) {
handle = HANDLE_LIGHT;
handle_wakeup = HANDLE_LIGHT_WAKE_UP;
}
break;
default:
HAL_LOG_ERROR(" %s Unknown sensor type: %d", __FUNCTION__,
sensor_datatype->DataType);
error = true;
break;
}
if (handle != -1 && error == false) {
addSensor(handle);
if (mSensors[handle] != NULL) {
/* Fill each sensor info in sub sensor classes */
strlcpy(mSensors[handle]->getName(), sensor_datatype->SensorName,
SNS_MAX_SENSOR_NAME_SIZE);
strlcpy(mSensors[handle]->getVendor(), sensor_datatype->VendorName,
SNS_MAX_VENDOR_NAME_SIZE);
mSensors[handle]->setVersion(sensor_datatype->Version);
if (sensor_datatype->MaxSampleRate <= 500 ) {
mSensors[handle]->setMaxFreq(sensor_datatype->MaxSampleRate);
} else if (sensor_datatype->MaxSampleRate >= 2000) {
mSensors[handle]->setMaxFreq(1000.0 / sensor_datatype->MaxSampleRate);
} else {
mSensors[handle]->setMaxFreq(1);
HAL_LOG_ERROR(" %s Invalid sample rate: %u", __FUNCTION__,
sensor_datatype->MaxSampleRate);
}
/* Lower max rate if property overrides value returned from sensor */
switch (mSensors[handle]->getType()) {
case SENSOR_TYPE_ACCELEROMETER:
property_get(HAL_PROP_MAX_ACCEL, max_rate_prop_value,
FREQ_ACCEL_DEF_HZ_STR);
break;
case SENSOR_TYPE_MAGNETIC_FIELD:
case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
property_get(HAL_PROP_MAX_MAG, max_rate_prop_value,
FREQ_MAG_DEF_HZ_STR);
break;
case SENSOR_TYPE_GYROSCOPE:
property_get(HAL_PROP_MAX_GYRO, max_rate_prop_value,
FREQ_GYRO_DEF_HZ_STR);
break;
default:
max_rate_prop_value[0] = 0;
break;
}
errno = 0;
tmp_max_rate = strtol(max_rate_prop_value, &strtol_endptr, 0);
if (0 == errno && strtol_endptr != max_rate_prop_value) {
mSensors[handle]->setMaxFreq(MIN(mSensors[handle]->getMaxFreq(), tmp_max_rate));
}
if (mSensors[handle]->getMaxFreq() >= FREQ_FASTEST_HZ) {
mSensors[handle]->setMaxFreq(FREQ_FASTEST_HZ);
}
/* check SMGR version and set min freq accordingly to support subHz */
if (smgr_version >= SMGR_SUB_HZ_VERSION) {
mSensors[handle]->setMinFreq(SMGR_SUB_HZ_REPORT_RATE_MIN_HZ);
}
else {
mSensors[handle]->setMinFreq(SNS_SMGR_REPORT_RATE_MIN_HZ_V01);
}
mSensors[handle]->setPower((float)((float)sensor_datatype->MaxPower * UNIT_CONVERT_POWER));
mSensors[handle]->setAttribOK(true);
if (!smgr_resp->num_buffered_reports_valid ||
HANDLE_PROXIMITY == mSensors[handle]->getHandle()) {
mSensors[handle]->setMaxBufferedSamples(0);
}
else {
mSensors[handle]->setMaxBufferedSamples(smgr_resp->num_buffered_reports[i]);
}
/* check SMGR version and set Reserved FIFO accordingly */
if (smgr_version >= SMGR_RES_FIFO_VERSION &&
smgr_resp->num_reserved_buffered_reports_valid) {
mSensors[handle]->setResBufferedSamples(smgr_resp->num_reserved_buffered_reports[i]);
}
else {
mSensors[handle]->setResBufferedSamples(0);
}
(static_cast<SMGRSensor*>(mSensors[handle]))->setSensorInfo(sensor_datatype);
HAL_LOG_INFO("%s: sensor1: name: %s, vendor: %s, maxRange: %u, res: %u, \
power: %u, max_freq: %u max_buffered_samples: %u", __FUNCTION__,
sensor_datatype->SensorName, sensor_datatype->VendorName,
sensor_datatype->MaxRange, sensor_datatype->Resolution,
sensor_datatype->MaxPower, sensor_datatype->MaxSampleRate,
mSensors[handle]->getMaxBufferedSamples());
HAL_LOG_DEBUG("%s: HAL: name: %s, vendor: %s, maxRange: %f, res: %f, \
power: %f, max_freq: %f min_freq: %f", __FUNCTION__,
mSensors[handle]->getName(), mSensors[handle]->getVendor(), mSensors[handle]->getMaxRange(),
mSensors[handle]->getResolution(), mSensors[handle]->getPower(), mSensors[handle]->getMaxFreq(),
mSensors[handle]->getMinFreq());
}
}
else {
HAL_LOG_ERROR("%s: either handle is -1 or error is true or mSensors[handle] is NULL!", __FUNCTION__);
}
if (handle_wakeup != -1 && error == false && !strncmp("true", wu_sensor, 4))
{
addSensor(handle_wakeup);
if (mSensors[handle_wakeup] != NULL) {
/* Fill each sensor info in sub sensor classes */
strlcpy(mSensors[handle_wakeup]->getName(), sensor_datatype->SensorName,
SNS_MAX_SENSOR_NAME_SIZE);
strlcpy(mSensors[handle_wakeup]->getVendor(), sensor_datatype->VendorName,
SNS_MAX_VENDOR_NAME_SIZE);
mSensors[handle_wakeup]->setVersion(sensor_datatype->Version);
if (sensor_datatype->MaxSampleRate <= 500 ) {
mSensors[handle_wakeup]->setMaxFreq(sensor_datatype->MaxSampleRate);
} else if (sensor_datatype->MaxSampleRate >= 2000) {
mSensors[handle_wakeup]->setMaxFreq(1000.0 / sensor_datatype->MaxSampleRate);
} else {
mSensors[handle_wakeup]->setMaxFreq(1);
HAL_LOG_ERROR(" %s Invalid sample rate: %u", __FUNCTION__,
sensor_datatype->MaxSampleRate);
}
/* Lower max rate if property overrides value returned from sensor */
switch (mSensors[handle_wakeup]->getType()) {
case SENSOR_TYPE_ACCELEROMETER:
property_get(HAL_PROP_MAX_ACCEL, max_rate_prop_value,
FREQ_ACCEL_DEF_HZ_STR);
break;
case SENSOR_TYPE_MAGNETIC_FIELD:
case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
property_get(HAL_PROP_MAX_MAG, max_rate_prop_value,
FREQ_MAG_DEF_HZ_STR);
break;
case SENSOR_TYPE_GYROSCOPE:
property_get(HAL_PROP_MAX_GYRO, max_rate_prop_value,
FREQ_GYRO_DEF_HZ_STR);
break;
default:
max_rate_prop_value[0] = 0;
break;
}
errno = 0;
tmp_max_rate = strtol(max_rate_prop_value, &strtol_endptr, 0);
if (0 == errno && strtol_endptr != max_rate_prop_value) {
mSensors[handle_wakeup]->setMaxFreq(MIN(mSensors[handle_wakeup]->getMaxFreq(), tmp_max_rate));
}
if (mSensors[handle_wakeup]->getMaxFreq() >= FREQ_FASTEST_HZ) {
mSensors[handle_wakeup]->setMaxFreq(FREQ_FASTEST_HZ);
}
/* check SMGR version and set min freq accordingly to support subHz */
if (smgr_version >= SMGR_SUB_HZ_VERSION) {
mSensors[handle_wakeup]->setMinFreq(SMGR_SUB_HZ_REPORT_RATE_MIN_HZ);
}
else {
mSensors[handle_wakeup]->setMinFreq(SNS_SMGR_REPORT_RATE_MIN_HZ_V01);
}
mSensors[handle_wakeup]->setPower((float)((float)sensor_datatype->MaxPower * UNIT_CONVERT_POWER));
mSensors[handle_wakeup]->setAttribOK(true);
if (!smgr_resp->num_buffered_reports_valid ||
HANDLE_PROXIMITY_NON_WAKE_UP == mSensors[handle_wakeup]->getHandle()) {
mSensors[handle_wakeup]->setMaxBufferedSamples(0);
}
else {
mSensors[handle_wakeup]->setMaxBufferedSamples(smgr_resp->num_buffered_reports[i]);
}
(static_cast<SMGRSensor*>(mSensors[handle_wakeup]))->setSensorInfo(sensor_datatype);
HAL_LOG_INFO("%s: sensor1: name: %s, vendor: %s, maxRange: %u, res: %u, \
power: %u, max_freq: %u max_buffered_samples: %u", __FUNCTION__,
sensor_datatype->SensorName, sensor_datatype->VendorName,
sensor_datatype->MaxRange, sensor_datatype->Resolution,
sensor_datatype->MaxPower, sensor_datatype->MaxSampleRate,
mSensors[handle_wakeup]->getMaxBufferedSamples());
HAL_LOG_DEBUG("%s: HAL: name: %s, vendor: %s, maxRange: %f, res: %f, \
power: %f, max_freq: %f", __FUNCTION__,
mSensors[handle_wakeup]->getName(), mSensors[handle_wakeup]->getVendor(), mSensors[handle_wakeup]->getMaxRange(),
mSensors[handle_wakeup]->getResolution(), mSensors[handle_wakeup]->getPower(), mSensors[handle_wakeup]->getMaxFreq());
}
}
else {
HAL_LOG_ERROR("%s: either handle_wakeup is -1 or error is true or mSensors[handle_wakeup] is NULL!", __FUNCTION__);
}
}
HAL_LOG_DEBUG("%s: txn: %u, ns: %u, ss_resp: %u", __FUNCTION__, txn_id,
(unsigned int)num_smgr_sensors, sensor_responses);
if (sensor_responses == num_smgr_sensors) {
/* All responses received */
Utility::signalResponse(false, sensor_info_sensor1_cb);
}
return;
}
我們分析下主要工作:
1. 根據傳入的sensor ID來匹配對應的sensor,並設定響應的屬性。
2. 如果sensor handle控制代碼合法,呼叫addSensor構建hal層sensor 結構體。
3. 從回撥資料中獲取sensor的name,vendor,version,max freq,type以及其他attribute等等,在呼叫setSensorInfo設定對應的attri設定sensor info。
我們下面主要檢視addSensor過程。
addSensor具體過程
我們看看其方法體,邏輯很簡單,就是根據handle,建立對應的sensor例項,在將其放到對應的mSensors資料結構中,mSensors儲存著所有支援的sensor列表。通過傳入handle,可以檢視是否支援相應的sensor。
void SensorsContext::addSensor(int handle)
{
char add_sensor[PROPERTY_VALUE_MAX] = "false";
HAL_LOG_INFO("%s: handle:%d", __FUNCTION__, handle);
switch(handle){
/* SMGR sensors */
case HANDLE_ACCELERATION:
case HANDLE_ACCELERATION_WAKE_UP:
mSensors[handle] = new Accelerometer(handle);
break;
case HANDLE_GYRO:
case HANDLE_GYRO_WAKE_UP:
if (is_gyro_available) {
HAL_LOG_DEBUG("%s: GYRO enabled handle:%d",
__FUNCTION__, handle);
mSensors[handle] = new Gyroscope(handle);
} else {
HAL_LOG_DEBUG("%s: GYRO disabled!", __FUNCTION__);
}
break;
default:
HAL_LOG_WARN("%s : Not supported sensor with handle %d!", __FUNCTION__, handle);
break;
}
}
前面提到開始獲得的sensor為加速度感測器Accelerometer,我們往後跟一下。
mSensors[handle] = new Accelerometer(handle);
Accelerometer::Accelerometer(int handle)
:SMGRSensor(handle)
{
trigger_mode = SENSOR_MODE_CONT;
(handle == HANDLE_ACCELERATION_WAKE_UP)?(bWakeUp = true):(bWakeUp = false);
}
SMGRSensor::SMGRSensor(int handle)
:Sensor(handle),
last_event()
{
HAL_LOG_INFO("%s: Sensor(%s)", __FUNCTION__,Utility::SensorTypeToSensorString(getType()));
time_service = TimeSyncService::getTimeSyncService();
data_cb = Utility::getDataCb();
memset(reg_value, 0, sizeof(reg_value));
}
從前面的log我們也可知,這個加速度sensor及其廠商之前的資訊:
sensor1: name: BMI160 Accelerometer, vendor: BOSCH, maxRange: 10283018, res: 78,
power: 180, max_freq: 200 max_buffered_samples: 10000
addSensor完成後,通過獲取sensor的name,vendor,version,max freq,type以及其他attribute等等,在呼叫setSensorInfo設定對應的attri設定sensor info,基本上這個sensor的hal資訊基本上就算配置完成了。
void Accelerometer::setSensorInfo(sns_smgr_sensor_datatype_info_s_v01* datatype)
{
HAL_LOG_DEBUG("%s: Accel, DTy: %d", __FUNCTION__, datatype->DataType);
setType(SENSOR_TYPE_ACCELEROMETER);
if(bWakeUp == false) {
setFlags(SENSOR_FLAG_CONTINUOUS_MODE);
} else {
setFlags(SENSOR_FLAG_CONTINUOUS_MODE|SENSOR_FLAG_WAKE_UP);
strlcat(name, " -Wakeup", sizeof(name));
}
setResolution((float)((float)datatype->Resolution *
UNIT_CONVERT_ACCELERATION));
setMaxRange((float)((float)datatype->MaxRange *
UNIT_CONVERT_ACCELERATION));
setMinFreq(SNS_SMGR_REPORT_RATE_MIN_HZ_V01);
return;
}
隨後也會處理我們handle為10的磁力感測器,此時,getSensorList完畢。
新增其他的sensor
上面的getSensorList過程我們只得到了兩個sensor,然而系統中還有多的sensor沒有配置,那麼是在哪裡配置的呢?
跟進程式碼我們發現,在getSensorList完成後,有一個for迴圈如下:
for (i=0; i < ARRAY_SIZE(g_sensor_list_order); i++) {
int handle = g_sensor_list_order[i];
/* Skip SMGR sensors as they are added above - in getSensorList */
if (handle < SAM_HANDLE_BASE)
continue;
/* Skip wake up sensors if they aren't enabled */
if (!strncmp("false", wu_sensor, 5) &&
((handle < SAM_HANDLE_BASE && handle >= WU_HANDLE_BASE) ||
(handle < TXN_ID_BASE && handle >= WU_SAM_HANDLE_BASE)))
continue;
if (is_accel_available ||
handle == HANDLE_PROXIMITY ||
handle == HANDLE_PROXIMITY_NON_WAKE_UP ||
handle == HANDLE_SPEED_PULSE) {
addSensor(handle);
}
}
g_sensor_list_order是個什麼東東?
它是定義的sensors_hal.h中全域性變數,裡面配置了所有當前系統可能支援的sensor列表:
const int g_sensor_list_order[] = {
/* Physical sensors */
HANDLE_ACCELERATION,
HANDLE_MAGNETIC_FIELD,
HANDLE_MAGNETIC_FIELD_UNCALIBRATED,
HANDLE_MAGNETIC_FIELD_SAM,
HANDLE_MAGNETIC_FIELD_UNCALIBRATED_SAM,
HANDLE_GYRO,
HANDLE_GYRO_UNCALIBRATED,
HANDLE_PROXIMITY,
HANDLE_THRESH,
HANDLE_LIGHT,
HANDLE_PRESSURE,
HANDLE_RELATIVE_HUMIDITY,
HANDLE_AMBIENT_TEMPERATURE,
/* SMGR wake up sensors */
HANDLE_ACCELERATION_WAKE_UP,
HANDLE_MAGNETIC_FIELD_WAKE_UP,
HANDLE_MAGNETIC_FIELD_UNCALIBRATED_WAKE_UP,
HANDLE_MAGNETIC_FIELD_SAM_WAKE_UP,
HANDLE_MAGNETIC_FIELD_UNCALIBRATED_SAM_WAKE_UP,
HANDLE_GYRO_WAKE_UP,
HANDLE_GYRO_UNCALIBRATED_WAKE_UP,
HANDLE_PROXIMITY_NON_WAKE_UP,
HANDLE_THRESH_NON_WAKE_UP,
HANDLE_LIGHT_WAKE_UP,
HANDLE_PRESSURE_WAKE_UP,
HANDLE_RELATIVE_HUMIDITY_WAKE_UP,
HANDLE_AMBIENT_TEMPERATURE_WAKE_UP,
/* Android virtual sensors via SAM: */
HANDLE_GRAVITY,
HANDLE_LINEAR_ACCEL,
HANDLE_ROTATION_VECTOR,
HANDLE_SAM_STEP_DETECTOR,
HANDLE_SAM_STEP_COUNTER,
HANDLE_SIGNIFICANT_MOTION,
HANDLE_GAME_ROTATION_VECTOR,
HANDLE_GEOMAGNETIC_ROTATION_VECTOR,
HANDLE_ORIENTATION,
HANDLE_TILT_DETECTOR,
HANDLE_PICK_UP_GESTURE,
HANDLE_QHEART,
HANDLE_WRIST_TILT,
/* SAM wake up sensors */
HANDLE_GRAVITY_WAKE_UP,
HANDLE_LINEAR_ACCEL_WAKE_UP,
HANDLE_ROTATION_VECTOR_WAKE_UP,
HANDLE_SAM_STEP_DETECTOR_WAKE_UP,
HANDLE_SAM_STEP_COUNTER_WAKE_UP,
HANDLE_GAME_ROTATION_VECTOR_WAKE_UP,
HANDLE_GEOMAGNETIC_ROTATION_VECTOR_WAKE_UP,
HANDLE_ORIENTATION_WAKE_UP,
HANDLE_QHEART_WAKE_UP,
/* Android virtual sensors via SMGR: */
HANDLE_SMGR_STEP_DETECTOR,
HANDLE_SMGR_STEP_COUNT,
HANDLE_SMGR_SMD,
HANDLE_SMGR_GAME_RV,
/* SMGR wake up sensors */
HANDLE_SMGR_STEP_DETECTOR_WAKE_UP,
HANDLE_SMGR_STEP_COUNT_WAKE_UP,
HANDLE_SMGR_GAME_RV_WAKE_UP,
/* QTI value added sensors: */
HANDLE_GESTURE_FACE_N_SHAKE,
HANDLE_GESTURE_BRING_TO_EAR,
HANDLE_MOTION_ABSOLUTE,
HANDLE_MOTION_RELATIVE,
HANDLE_MOTION_VEHICLE,
HANDLE_GESTURE_BASIC_GESTURES,
HANDLE_GESTURE_TAP,
HANDLE_GESTURE_FACING,
HANDLE_GESTURE_TILT,
HANDLE_GESTURE_GYRO_TAP,
HANDLE_PEDOMETER,
HANDLE_PAM,
HANDLE_MOTION_ACCEL,
HANDLE_CMC,
HANDLE_RGB,
HANDLE_IR_GESTURE,
HANDLE_SAR,
HANDLE_HALL_EFFECT,
HANDLE_FAST_AMD,
HANDLE_UV,
HANDLE_THERMOPILE,
HANDLE_CCT,
HANDLE_IOD,
HANDLE_DPC,
HANDLE_MULTISHAKE,
HANDLE_SPEED_PULSE
};
這樣一來就簡單了,for迴圈一次新增我們列表中配置的sensor,都是調addSensor方法進行處理,可以看到我們的計步器sensor step counter以及step decetcor也在其中,其配置時的log如下:
06-04 19:48:04.420 D/qti_sensors_hal: addSensor: STEP DETECTOR enabled handle:48
06-04 19:48:04.421 I/qti_sensors_hal: sendAlgoAttribReq:sensor(android.sensor.step_detector) svc no:37 handle:48
06-04 19:48:04.423 I/qti_sensors_hal: processAlgoAttribResp:sensor(android.sensor.step_detector) Received response 0 for svc_num 37 handle 48
06-04 19:48:04.423 D/libsensor1: libsensor_rx_thread: waiting on fd 51
06-04 19:48:04.423 D/libsensor1: libsensor_rx_thread: waiting on fd 53
06-04 19:48:04.423 I/qti_sensors_hal: processAlgoAttribResp:sensor(android.sensor.step_detector) sensor1 Version:1 Power:11796 MaxFreq:65536
MinFreq:18 MaxSampleFreq:3276800 MinSampleFreq:3276800 MaxBuffSamples:20208 ResBuffSamples:100
06-04 19:48:04.423 I/qti_sensors_hal: processAlgoAttribResp:sensor(android.sensor.step_detector) HAL Version:2 Power:0.179993 MaxFreq:1.000000 MinFreq:0.000275
MaxSampleFreq:50.000000 MinSampleFreq:50.000000 MaxBuffSamples:0.000275 ResBuffSamples:3276800.000000
06-04 19:48:04.423 D/qti_sensors_hal: sendAlgoAttribReq: Received Response: 0
06-04 19:48:04.423 I/qti_sensors_hal: addSensor: handle:49
06-04 19:48:04.423 D/qti_sensors_hal: addSensor: STEP COUNTER enabled handle:49
06-04 19:48:04.423 D/libsensor1: sensor1_init
06-04 19:48:04.423 V/libsensor1: libsensor_add_client Adding client index 7 (62)
06-04 19:48:04.423 D/libsensor1: libsensor_add_client: waking up rx thread 51 52
06-04 19:48:04.423 D/libsensor1: libsensor_rx_thread: waking on wakeup pipe 51
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waking on fd 62
06-04 19:48:04.424 D/libsensor1: libsensor_read_socket: socket received open success response
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 54
06-04 19:48:04.424 I/libsensor1: sensor1_open: Adding new client fd 62
06-04 19:48:04.424 I/qti_sensors_hal: SAMSensor: sensor() is_attrib_ok=1
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 55
06-04 19:48:04.424 I/qti_sensors_hal: StepCounter: handle:49
06-04 19:48:04.424 I/qti_sensors_hal: sendAlgoAttribReq:sensor(android.sensor.step_counter) svc no:37 handle:49
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 56
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 57
06-04 19:48:04.424 I/libsensor1: libsensor_log_ctl_write_pkt: fd 62; svc 37; msg 36; txn 0; cmd WRITE_QMI
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 59
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 60
06-04 19:48:04.424 D/qti_sensors_hal: waitForResponse: timeout=1000
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waking on fd 62
06-04 19:48:04.426 I/libsensor1: libsensor_log_read_pkt: fd 62; svc 37; msg 36; txn 0; type RESP; cmd WRITE_QMI
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 54
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 55
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 56
06-04 19:48:04.426 V/qti_sensors_hal: SAMSensor_sensor1_cb: msg_type 1, Sn 37, msg Id 36, txn Id 0
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 57
06-04 19:48:04.426 I/qti_sensors_hal: processResp: handle:49
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 59
06-04 19:48:04.426 D/qti_sensors_hal: processResp: Received SNS_SAM_PED_GET_ATTRIBUTES_RESP_V01
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 60
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 61
06-04 19:48:04.426 I/qti_sensors_hal: processAlgoAttribResp:sensor(android.sensor.step_counter) Received response 0 for svc_num 37 handle 49
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 62
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 51
06-04 19:48:04.426 I/qti_sensors_hal: processAlgoAttribResp:sensor(android.sensor.step_counter) sensor1 Version:1 Power:11796 MaxFreq:65536
MinFreq:18 MaxSampleFreq:3276800 MinSampleFreq:3276800 MaxBuffSamples:20208 ResBuffSamples:100
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 53
06-04 19:48:04.426 I/qti_sensors_hal: processAlgoAttribResp:sensor(android.sensor.step_counter) HAL Version:2 Power:0.179993 MaxFreq:1.000000 MinFreq:0.000275
MaxSampleFreq:50.000000 MinSampleFreq:50.000000 MaxBuffSamples:0.000275 ResBuffSamples:3276800.000000
StepCounter::StepCounter(int handle)
:SAMSensor(handle),
step_counter_running_total(0),
step_counter_running_instance(0),
step_counter_current_instance(0),
step_counter_is_timer_created(false)
{
if(getAttribOK() == true) {
batch_support = true;
svc_num = SNS_SAM_PED_SVC_ID_V01;
trigger_mode = SENSOR_MODE_EVENT;
HAL_LOG_INFO("%s: handle:%d", __FUNCTION__, handle);
setName("Step Counter");
setVendor("QTI");
setType(SENSOR_TYPE_STEP_COUNTER);
if(handle == HANDLE_SAM_STEP_COUNTER_WAKE_UP) {
bWakeUp = true;
setName("Step Counter -Wakeup");
setFlags(SENSOR_FLAG_ON_CHANGE_MODE|SENSOR_FLAG_WAKE_UP);
} else if(handle == HANDLE_SAM_STEP_COUNTER) {
bWakeUp = false;
setFlags(SENSOR_FLAG_ON_CHANGE_MODE);
}
setMaxRange(1);
setResolution(1);
/* Send Algo Attributes Request */
sendAlgoAttribReq();
}
}
此過程完成後,系統中的sensor基本上就已經配置完成了,因此簽名getSensorList時只返回兩個,而最終所有的sensor都是在這個全域性變數裡配置新增的。
updateSensorList更新裝置列表
列表已經得到,接著需要呼叫update更新下sensor資料結構。
在updateSensorList方法中會對一些特殊的sensor進行校驗,並且再次通過setSensoeInfo設定sensor的屬性值。
06-04 19:48:04.508 I/qti_sensors_hal: sensors_get_sensors_list: Number of sensors: 26
06-04 19:48:04.508 I/qti_sensors_hal: sensors_get_sensors_list
06-04 19:48:04.508 I/qti_sensors_hal: sensors_get_sensors_list: Already have the list of sensors
06-04 19:48:04.508 V/qti_sensors_hal: activate: handle is 0, en is 0
06-04 19:48:04.508 V/qti_sensors_hal: activate sensors is 0
06-04 19:48:04.508 I/qti_sensors_hal: enable: Sensor android.sensor.accelerometer is already enabled/disabled 0
06-04 19:48:04.508 V/qti_sensors_hal: activate: handle is 2, en is 0
06-04 19:48:04.508 V/qti_sensors_hal: activate sensors is 0
06-04 19:48:04.508 I/qti_sensors_hal: enable: Sensor android.sensor.gyroscope is already enabled/disabled 0
06-04 19:48:04.508 V/qti_sensors_hal: activate: handle is 8, en is 0
06-04 19:48:04.508 V/qti_sensors_hal: activate sensors is 0
06-04 19:48:04.508 I/qti_sensors_hal: enable: Sensor android.sensor.gyroscope_uncalibrated is already