IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android T(13)--SensorDevice 的初始化(三) -> 正文阅读

[移动开发]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.
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-06-20 23:05:27  更:2022-06-20 23:06:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 2:56:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码