四:Sensor SLPI层SAM Sensor实例分析
上文中,我们大致了解了物理sensor driver整个流程,但在项目中,一般写这种sensor driver的情况很少。这种sensor driver基本上都是各个vendor厂商提供的,我们也只需要看懂即可。
但是SAM sensor我们完全是可以自己写的,根据一些物理sensor的数据,来实现一些算法。
比如,实现拿起唤醒功能,这个功能在oem手机中非常常见。
基本功能就是:当用户拿起手机时,手机屏幕亮起,此时可以通过脸部识别,来解锁手机等等。
这时好多人可能会说,这不是很简单吗?在framework层就可以做,注册一个加速度传感器,并根据data做一定算法处理。根本不需要再SLPI侧再实现一个SAM sensor。这种思维就是典型的应用层程序员的思想,系统层程序员如果有这种思想,那就很危险了。
为什么不能再framework层上做算法处理呢?
framework层进行算法处理,当系统睡下去怎么办?若是注册Non-Wakeup的sensor的话,在系统suspend时,不会有任何数据上报,如何唤醒系统呢?若是注册Wakeup的sensor的话,系统会被wakelock住,根本睡不下去,这时系统功耗非常高。
可见在framework层做的想法是在系统层面不可能实施的。
那么在SLPI侧实现pick up sensor的思路是什么呢?
pick up sensor在LPSS侧是work的,APSS侧是可以suspend的,当pick up Sensor获取accel sensor的数据满足算法时,会publish event给APSS中client,此时会唤醒系统。唤醒系统后,framework层会根据该sensor type,做相应的操作,比如亮屏、震动等等。。。
Ok,下面我们以该pickup sensor为例,解析下SLPI 侧 SAM Sensor driver。
高通给我们参考的oem sensor实例,下面我们在oem sensor实例上实现pickup sensor。
1:build脚本
根据上文中介绍。各个sensor都是通过xxxx.scons静态添加sensor的。
oem sensor的source code在/slpi/ssc/sensors/oem1中。
if 'USES_SSC_STATIC_LIB_BUILDER' in env:
env.AddSSCSU(inspect.getfile(inspect.currentframe()),
register_func_name = "sns_oem1_register",
clean_pack_list = oem1_clean_pack_list,
binary_lib = oem1_binary_lib,
add_island_files = oem1_island_enable,
diag_ssid = ssid)
build脚本会通过register_func_name = “sns_oem1_register”,调到sns_oem1_register函数。
2:Initialization
sns_rc sns_oem1_register(sns_register_cb const *register_api)
{
register_api->init_sensor(sizeof(sns_oem1_sensor_state),
&sns_oem1_api,
&sns_oem1_sensor_instance_api);
return SNS_RC_SUCCESS;
}
sns_sensor_api sns_oem1_api =
{
.struct_len = sizeof(sns_sensor_api),
.init = &sns_oem1_init,
.deinit = &sns_oem1_deinit,
.get_sensor_uid = &sns_oem1_get_sensor_uid,
.set_client_request = &sns_oem1_set_client_request,
.notify_event = &sns_oem1_notify_event,
};
根据前文介绍。sns_register_sensor()注册函数后,会执行sns_sensor_api的init函数。
.init
sns_rc
sns_oem1_init(sns_sensor *const this)
{
sns_oem1_sensor_state *state = (sns_oem1_sensor_state*)this->state->state;
struct sns_service_manager *smgr = this->cb->get_service_manager(this);
float data[3];
state->diag_service = (sns_diag_service*)
smgr->get_service(smgr, SNS_DIAG_SERVICE);
// set default output value corresponding to OEM1_FACING_DOWN to 50. will
// rewrite if registry sensor is available
state->config.down_value = 50.0;
state->first_pass = true;
// determine encoded output event size
state->config.encoded_data_event_len =
pb_get_encoded_size_sensor_stream_event(data, 3);
SNS_SUID_LOOKUP_INIT(state->suid_lookup_data, NULL);
sns_suid_lookup_add(this, &state->suid_lookup_data, "accel");//No.1
sns_suid_lookup_add(this, &state->suid_lookup_data, "amd"); //No.2
#ifndef SUPPORT_DIRECT_SENSOR_REQUEST
sns_suid_lookup_add(this, &state->suid_lookup_data, "resampler");//No.3
#endif
publish_attributes(this); //No.4
SNS_PRINTF(MED, this, "OEM1 init success and attributes published");
return SNS_RC_SUCCESS;
}
No.1:sns_suid_look_add添加所需要的sensor。
No.2:添加amd sensor。
No.3:添加resampler sensor。
No.4:并pushlish atrribute。比如sensor name、type、vendor等,Client层会根据该attribute,设置sensor的一些属性,比如on_change、streaming等等
.get_sensor_uid
static sns_sensor_uid const*
sns_oem1_get_sensor_uid(sns_sensor const *this)
{
UNUSED_VAR(this);
static const sns_sensor_uid oem1_suid = OEM1_SUID;
return &oem1_suid;
}
oem1_suid是指定的,返回的是oem_suid。
.notify
sns_rc
sns_oem1_notify_event(sns_sensor *const this)
{
sns_oem1_sensor_state *state = (sns_oem1_sensor_state*)this->state->state;
SNS_PRINTF(LOW, this, "sns_oem1_notify_event");
sns_suid_lookup_handle(this, &state->suid_lookup_data);
#ifdef SUPPORT_REGISTRY
if(NULL != state->registry_stream)
{
handle_oem1_registry_event(this);
}
#endif
if(sns_suid_lookup_complete(&state->suid_lookup_data))
{
#ifdef SUPPORT_REGISTRY
if(state->first_pass == true){
state->