1.概览
上一章提到过,SensorDevice如其名,用于管理Sensor的硬件操作,将SensorService和Sensor HAL很好的隔离开来。像Android这种需要大量人员同时维护的项目,通过适当的分层以及解耦让各个功能的开发可以并行进行,如此能提高开发效率和降低维的难度。
2.流程图
先放上整体的流程图,方便查看。去掉了一些细枝末节的部分。
3.SensorHal的连接–connectHalService
SensorService中的部分 HardwareSensor是依赖硬件sensor的,所以对SensorHal的调用是不可避免,既然这部分被SensorDevice所隔离,那么也就意味着 SensorDeivce 承当了这部分职责了。sensorHal是以HIDL-service的形式提供服务的,其为独立进程和 SensorService/SensorDeivce 不属于同一个进程,SensorService/SensorDeivce 实例则是位于system_server进程的线程中。这也意味着SensorService/SensorDeivce是无法直接调用sensorHal内部方法的。所以在使用HIDL-service前,则需通过hwservicemanager获取到sensorHal的HIDL-service句柄。
在SensorDeivce中又使用类 HidlSensorHalWrapper 对使用sensorHal的操作进行了封装。下面先看看类图
SensorDeviceCallback 为ISensorHalWrapper的内部类,因为没找到UML类图中对内部类更好的表示,这里使用组合的关系去表示。
3.1 代码实现–new HidlSensorHalWrapper
//frameworks\native\services\sensorservice\SensorDevice.cpp
SensorDevice
connectHalService()
std::unique_ptr<ISensorHalWrapper> hidl_wrapper = std::make_unique<HidlSensorHalWrapper>();
hidl_wrapper->connect(this)
mHalWrapper = std::move(hidl_wrapper);
最终HidlSensorHalWrapper的实例指针被存储于 mHalWrapper 中,其定义如下
//file://frameworks\native\services\sensorservice\SensorDevice.h
class SensorDevice : ...{
private:
std::unique_ptr<ISensorHalWrapper> mHalWrapper;
}
3.2 代码实现–HidlSensorHalWrapper->connect
connect的方法是继承自类 ISensorHalWrapper,下面是它的定义
/**
* A wrapper for various types of HAL implementation, e.g. to distinguish HIDL and AIDL versions.
*/
class ISensorHalWrapper {
public:
class SensorDeviceCallback {
...
}
virtual bool connect(SensorDeviceCallback *callback) = 0;
}
注释非常的清晰,用于对各种HAL实现的包装,说白了就是为了SensorDevice隔离SensorHal的不同接口的,例如HIDL/AIDL等。其入参为 SensorDeviceCallback,此处传入SensorDevice实例本身this,从上一章SensorDevice的类图能看出,SensorDeviceCallback为SensorDevice父类ISensorHalWrapper中的一个内部类,其定义如上。
下面是connect接口的实现位于HidlSensorHalWrapper中
//frameworks\native\services\sensorservice\HidlSensorHalWrapper.cpp
bool HidlSensorHalWrapper::connect(SensorDeviceCallback* callback) {
mSensorDeviceCallback = callback;
connectHidlService();
return ret;
}
代码非常简单,只有两个步骤
1)记录由SensorDevice实现的SensorDeviceCallback实例指针,用于后续回调通知SensorDevice。
2)获取SensorHal的实现并进行设置,例如配置用于传递sensor event的FMQ大小。在流程图上的调用流程为A1->B2->C3->D2对于其代码实现这里就不放了,因为和流程图上的并无差别。
3.3 SensorHal实现的选择
在connectHalService中也可以看出,如果connectHidlService没有找到合适的HDIL实现,那么也会去找对应的aidl实现
bool SensorDevice::connectHalService() {
std::unique_ptr<ISensorHalWrapper> hidl_wrapper = std::make_unique<HidlSensorHalWrapper>();
if (hidl_wrapper->connect(this)) {
mHalWrapper = std::move(hidl_wrapper);
return true;
}
std::unique_ptr<ISensorHalWrapper> aidl_wrapper = std::make_unique<AidlSensorHalWrapper>();
if (aidl_wrapper->connect(this)) {
mHalWrapper = std::move(aidl_wrapper);
return true;
}
}
此处我们选择使用HIDL的方式进行讲解,AIDL的方式放在拓展章节进行讲解。
bool HidlSensorHalWrapper::connectHidlService() {
HalConnectionStatus status = connectHidlServiceV2_1();
if (status == HalConnectionStatus::DOES_NOT_EXIST) {
status = connectHidlServiceV2_0();
}
if (status == HalConnectionStatus::DOES_NOT_EXIST) {
status = connectHidlServiceV1_0();
}
}
从这里也能看出SensorFramework对选择SensorHal的HIDL实现的先后顺序为 V2.1->V2.0->V1.0。
3.3 ISensorWrapperV2_0的初始化
由于 HIDL的实现又分为 2.1、2.0、1.0,为了做到兼容,SensorFramework引入了一系列中间类,ISensorsWrapperV1_0、ISensorsWrapperV2_0、ISensorsWrapperV2_1。此处我们使用的HIDL版本为2.0,故看看 ISensorsWrapperV2_0的实现
ISensorsWrapperV2_0(sp<hardware::sensors::V2_0::ISensors> sensors)
: SensorsWrapperBase(sensors) {
auto eventQueue = std::make_unique<EventMessageQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,true);
mEventQueue = std::make_unique<EventMessageQueueWrapperV1_0>(eventQueue);
};
构造函数做两件事,
1)保存从ISensor获取的SensorHal句柄
SensorsWrapperBase(sensors)
mSensors(sensors)
SensorsWrapperBase为ISensorsWrapperV2_0父类,sensors则由HidlSensorHalWrapper::connectHidlServiceV2_0 中传入
sp<android::hardware::sensors::V2_0::ISensors> sensors =
android::hardware::sensors::V2_0::ISensors::getService();
至于最终获取到的句柄对应到哪个类的实例,这部分内容将放在HIDL-service SensorHal的初始化中去。
2)创建 EventMessageQueue ,用于sensorEvent的传输,并且是FMQ方式的,这种方式的好处是内存交换时并不涉及kernel操作以及多次拷贝的问题。
typedef MessageQueue<::android::hardware::sensors::V1_0::Event,
::android::hardware::kSynchronizedReadWrite>
EventMessageQueue;
EventMessageQueue实际上就是MessageQueue,对于 MessageQueue的说明见google的 fmq 文档
3.4 初始化SensorHal–initializeHidlServiceV2_X
获取到SensorHal后,那么就是对其进行设置以符合SensorDevice的应用要求了。下面是对应的代码,我们只关心初始化骨架
ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::initializeHidlServiceV2_X() {
HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
//SensorHal的初始化
mCallback = sp<HidlSensorsCallback>::make(mSensorDeviceCallback);
mSensors->initialize(*mWakeLockQueue->getDesc(), mCallback)
//死亡回调注册
connectionStatus = HalConnectionStatus::CONNECTED;
mSensorsHalDeathReceiver = new SensorsHalDeathReceiver(this);
mSensors->linkToDeath(mSensorsHalDeathReceiver, 0 /* cookie */);
return connectionStatus;
}
3.4.1 SensorHal的初始化
这部分代码最终会调用到ISensor.hal的initialize接口,真正对SensorHal进行初始化了,对应的代码如下
//hardware\interfaces\sensors\common\utils\ISensorsWrapper.h
Return<Result> initialize(const MQDescriptorSync<uint32_t>& wakeLockDesc,
const ::android::sp<ISensorsCallback>& callback) override {
return mSensors->initialize(*mEventQueue->getDesc(), wakeLockDesc, callback);
}
从这里能看出,SensorHal上报的sensor event所用的队列是来自于SensorDevice进程的。如果SensorHal回调callback,SensorDevice中实现的接口也会被调用。HidlSensorsCallback的类图如下
这里又对SensorDevice的实现做了一层包装,除了可以兼容2.1版本的HDIL接口,还将HIDL的ISensorsCallback接口作为SensorDevice为接口 SensorDeviceCallback 实现的代理类,从而让SensorDeviceCallback支持了跨进程调用,即SensorHal调用到SensorDevice。
//frameworks\native\services\sensorservice\HidlSensorHalWrapper.cpp
using android::hardware::sensors::V2_1::ISensorsCallback;
struct HidlSensorsCallback : public ISensorsCallback{
private:
ISensorHalWrapper::SensorDeviceCallback* mSensorDeviceCallback;
};
3.4.2 死亡回调注册
因为SensorDevice和SensorHal的实现是位于两个不同的进程中的,所以后者的死亡前者是无法知悉的,所以前者注册后者的死亡接口是为了解决SensorHal的真实状态和SensorDevice中所记录它的状态无法同步的问题。注册也非常的简单,
//file:frameworks\native\services\sensorservice\HidlSensorHalWrapper.cpp
void SensorsHalDeathReceiver::serviceDied(
uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
ALOGW("Sensors HAL died, attempting to reconnect.");
mHidlSensorHalWrapper->prepareForReconnect();
}
如此在SensorHal所在进程死亡后,serviceDied 则会被回调。
在SensorDevice中已经获取到SensorHal和设置完成了,最后提一下SensorDevice如果像调用SensorHal的实现,是通过类HidlSensorHalWrapper的,在SensorDevice的内部使用 std::unique_ptr mHalWrapper来指向它。
4.从SensorHal获取Senor信息–initializeSensorList
initializeSensorList在SensorDevice的构造方法中就被调用了。
void SensorDevice::initializeSensorList() {
auto list = mHalWrapper->getSensorsList();
const size_t count = list.size();
for (size_t i = 0; i < count; i++) {
sensor_t sensor = list[i];
//code 1
sensor.resolution = SensorDeviceUtils::resolutionForSensor(sensor);
sensor.power = MIN_POWER_MA;
sensor.maxRange = quantizedRange;
//code 2
mSensorList.push_back(sensor);
mActivationCount.add(list[i].handle, model);
}
}
mHalWrapper->getSensorsList最终调用到了SensorHal的接口并获得到了sensor,每个sensor的类型使用 sensor_t 表示,和SensorHal中保持一致。
code 1 中主要是对sensor的信息重新整理或做兼容处理。
code 2 SensorDevice中对这部分sensor信息进行存储,如此下次使用时则不用再次调用SensorHal的接口了,毕竟这个过程是跨进程的,需要内核进行调度操作的。
class SensorDevice:...{
private:
std::vector<sensor_t> mSensorList;
};
mActivationCount 则是用于记录sensor的额外信息,索引则是使用sensor的handle值。当然初始化过程并无使用,对Info的说明注释说的还是比较清除的。
//file:frameworks\native\services\sensorservice\SensorDevice.h
Store batch parameters in the KeyedVector and the optimal batch_rate and timeout
inbestBatchParams. For every batch() call corresponding params are stored in
batchParamsvector. A continuous mode request is batch(... timeout=0 ..) followed by activate().
A batch mode request is batch(... timeout > 0 ...) followed by activate(). Info is a
per-sensor data structure which contains the batch parameters for each client that has
registered for this sensor.