Android T(13)--SensorDevice 的初始化(三)

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.
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值