Sensor流程概述

1,156 阅读5分钟

目录:

  • 一、sensor HAL进程
    • HIDL 接口
    • 手机上的相关文件
    • 代码位置与编译文件
    • rc文件中的启动顺序
    • sensor hal 代码启动流程
  • 二、system_server 进程 sensorservice
    • 启动调用栈
    • SensorService::onFirstRef
    • SensorService::threadLoop
  • 三、App进程
    • 获取注册管理器 SensorManager
    • sensorManager.getDefaultSensor
    • sensorManager.registerListener

一、sensor HAL层

HIDL 接口

getSensorsList() 获取所有sensor链表
activate()       开启/关闭一个sensor
poll()           获取sensor数据
batch()          设置采样率  批处理
flush()          刷新缓冲区

手机上的相关文件:

/system/lib64/android.hardware.sensors@1.0.so          给system分区使用的hidl接口,主要给sensorservice调用
/vendor/etc/init/android.hardware.sensors@1.0-service.rc   hidl服务的rc文件
/vendor/bin/hw/android.hardware.sensors@1.0-service        hidl服务
/vendor/lib64/hw/android.hardware.sensors@1.0-impl.so      hidl服务实现
/vendor/etc/sensors/hals.conf                              各个子模块sensor实现的so库,multihal.cpp 中使用

代码位置与编译文件

hardware/interfaces/sensors/1.0/default/Sensors.h      头文件
hardware/interfaces/sensors/1.0/default/Sensors.cpp     编译到 android.hardware.sensors@1.0-impl.so
hardware/interfaces/sensors/1.0/default/service.cpp     编译到 android.hardware.sensors@1.0-service
hardware/interfaces/sensors/1.0/default/Android.bp      以上两个so库的编译配置文件

hardware/interfaces/sensors/1.0/ISensors.hal            编译到 android.hardware.sensors@1.0.so

//ninja 根据hal文件生产的c++源码:
out\soong.intermediates\hardware\interfaces\sensors\1.0\android.hardware.sensors@1.0_genc++_headers\gen\android\hardware\sensors\1.0\ISensors.h
#    static const char* descriptor;
//out\soong.intermediates\hardware\interfaces\sensors\1.0\android.hardware.sensors@1.0_genc++\gen\android\hardware\sensors\1.0\SensorsAll.cpp
hidl 服务描述符 赋值。这个值很重要,服务的实现,就是基于此名字找到的库文件:android.hardware.sensors@1.0-impl.so
    const char* ISensors::descriptor("android.hardware.sensors@1.0::ISensors");

hardware/libhardware/modules/sensors/multihal.cpp     //编译到静态库multihal.so  用于加载厂家sensor模块框架      

/vendor/qcom/proprietary/sensors-see/                     //高通各个常用sensor的实现

// 一些硬件抽象的结构体,模块结构体
// sensors_open 函数体在这个文件中,Sensors.h 会include入这个文件    
hardware/libhardware/include/hardware/sensors.h 
hardware/libhardware/include/hardware/hardware.h


system/libhidl/transport/ServiceManagement.cpp             //创建binder服务工具类

其他驱动相关,以及一些具体sensor的实现,暂不列出

rc文件中的启动顺序

  • rc文件中定义为 hal 类
    • on init
    • on late-init
      • trigger early-fs、trigger fs、trigger post-fs、trigger post-fs-data、trigger load_all_props_action
      • trigger zygote-start ### 启动zygote服务,接着启动SystemServer,启动SensorService服务
      • trigger early-boot
      • trigger boot
        • on boot
          • class_start hal //启动 android.hardware.sensors@1.0-service 进程
          • class_start core
    • 综上,在系统SystemServer之后启动sensor hal

android.hardware.sensors@1.0-service.rc

// hardware/interfaces/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
service vendor.sensors-hal-1-0 /vendor/bin/hw/android.hardware.sensors@1.0-service
    interface android.hardware.sensors@1.0::ISensors default
    class hal  //sensor hal 进程为 hal 类
    user system
    group system wakelock uhid context_hub
    capabilities BLOCK_SUSPEND
    rlimit rtprio 10 10

sensor hal 代码启动流程

service.cpp--- main()
  | service.cpp 里边仅仅只有这一行代码
  * defaultPassthroughServiceImplementation<ISensors>(2); //LegacySupport.h
    * defaultPassthroughServiceImplementation
      * configureRpcThreadpool(maxThreads, true);
        * configureBinderRpcThreadpool
          * ProcessState::self()
            * ProcessState::init
              * new ProcessState
                * open_driver()
                  * int fd = open("/dev/hwbinder", O_RDWR | O_CLOEXEC); 打开hwbinder驱动
                  * status_t result = ioctl(fd, BINDER_VERSION, &vers);
                |  mmap映射内存
                * mVMStart = mmap(nullptr, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
          * ProcessState::setThreadPoolConfiguration
            | 配置binder线程
            * ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &kernelMaxThreads)
      * registerPassthroughServiceImplementation<Interface, ExpectInterface>(name)
        * registerServiceCb = details::registerAsServiceInternal(service, name);
        * registerPassthroughServiceImplementation(
              const std::string& interfaceName, const std::string& expectInterfaceName,
              RegisterServiceCb registerServiceCb, const std::string& serviceName)
          |  new sensor hidl 服务实例 hardware/interfaces/sensors/1.0/default/Sensors.cpp    
          * sp<IBase> service = getRawServiceInternal 
            * const sp<IServiceManager1_0> pm = getPassthroughServiceManager();
            * sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
              * openLibs  传入回调函数 eachLib
                * 查找so库,并调用回调函数 eachLib
                  * eachLib 回调函数调用hardware/interfaces/sensors/1.0/default/Sensors.cpp HIDL_FETCH_ISensors 方法
                  * hardware/interfaces/sensors/1.0/default/Sensors.cpp 定义了 HIDL_FETCH_ISensors 函数
                    * HIDL_FETCH_ISensors  中 new Sensors
                      * 内部调用 open_sensors 方法
                        * 从so配置文件加载so库 比如高通的,椭圆的 等等不同厂家so,一个so可能实现了几个sensor
                        * 使用相应的数据结构,缓存so库中的函数
                        * 对每个子模块 开启线程,调用 writerTask 方法
                        * writerTask 函数中又会调用每个模块的 poll 函数
                          * 拿到的数据缓存到 SensorEventQueue 中
                          * SensorService 调用 poll 接口,就是从这个 SensorEventQueue 中拿取数据
          * registerServiceCb(service, serviceName);
            * details::registerAsServiceInternal(service, name);
              * sp<IServiceManager1_2> sm = defaultServiceManager1_2();
              * service->interfaceChain // 构造 descriptor 链条 对象,传给 addWithChain 作为参数
                * sm->addWithChain
      * joinRpcThreadpool();
        * joinBinderRpcThreadpool();
          * IPCThreadState::joinThreadPool(bool isMain)
            * getAndExecuteCommand();
              * talkWithDriver----ioctl
              * ioctl 过程会阻塞 wait...
              * executeCommand----BHwBinder.transact----HwBinder.onTransact


二、system_server 进程 sensorservice

启动调用栈:

  • SystemServer.run
    • startBootstrapServices
      • startSensorService// 这是个 native 方法。// Android S 上改为调用 SensorService.java 中的代码再去启动服务
        • com_android_server_SystemServer.cpp//-----------------Android 11
          • android_server_SystemServer_startSensorService
            • SensorService::publish
              • sp sm(defaultServiceManager());
              • sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,dumpFlags);
              • // new SERVICE() = new SensorService();
              • // addService 的形参定义:sp& service
              • sp引用时调用 onFirstRef 函数
        • com_android_server_sensor_SensorService.cpp //-----Android 12
          • startSensorServiceNative
            • NativeSensorService* service = new NativeSensorService(env, listener);
              • mService = new SensorService(); // sp mService; // sp引用时调用 onFirstRef 函数
              • IServiceManager->addService
    • startOtherServices
      • startHidlServices();
        • android_server_SystemServer_startHidlServices
          • SensorManager.registerAsService();

SensorService::onFirstRef

  • new SensorDevice

    • connectHidlService 获取hidl服务
  • 通过 SensorDevice,调用 Sensor HIDL 提供的 getSensorsList 接口,获取所支持的 Sensor 信息获,调用registerSensor函数把Sensor保存起来

  • SensorFusion功能,融合传感器;registerSensor 注册各种虚拟传感器

    • 注册就 把sensor 加入到这个对象中 SensorServiceUtil::SensorList mSensors
  • 创建一个 Looper, 用于 enable sensor 后,进行数据的接收

  • 初始化一些Buffer,用他们保存sensor硬件上报的数据

  • 创建SensorEventAckReceiver。SensorEventAckReceiver 则用于在 dispatch wake up sensor event 给上层后,接收上层返回的确认 ACK。

  • 调用run函数,执行threadLoop函数。循环读取sensor硬件上传上来的数据,然后分发给应用。

SensorService::threadLoop

  1. 通过poll往hal层取sensor数据, 若没有数据的时候就一直阻塞(该阻塞功能由HAL层实现),当有数据时该函数就会返回
  2. virtual sensors 相关数据计算后上报
  3. 通过SensorEventConnection中 sendEvents 将数据给到每个应用,每个应用都有自己的SensorEventConnection

三、App进程代码:

  • 获取注册管理器 SensorManager

    • SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    • 获取的实际是 SystemSensorManager 的实例
    • 实际是App进程,获取 SensorService 的binder代理对象 BpSensorServer ,并调用服务端 getSensorList 获取sensor列表
    • 然后赋值给App进程的 SystemSensorManager.mFullSensorsList
  • sensorManager.getDefaultSensor

    • 就是从 mFullSensorsList 列表中获取 Sensor
  • 注册回调

    • sensorManager.registerListener(new SensorEventListener(){})
      • new SensorEventQueue(listener, looper, this, fullClassName);
        • 创建Java层的SensorEventQueue,构造函数中又创建native层的 SensorEventQueue
        • native层的 调用 SensorService.createSensorEventConnection 获取 SensorEventConnection
          • 得到 SensorEventConnection 客户端代理对象 BpSensorEventConnection
            • 这个binder对象有个 getSensorChannel 接口,可以获取 BitTube 对象,即SensorEventConnection 客户服务 双向通讯的 socket 包装对象
          • 使用 BpSensorEventConnection 构造 native 层的 SensorEventQueue 对象
            • SensorEventQueue 差不多就是 BpSensorEventConnection 的包装,所有功能都是依靠 BpSensorEventConnection 的接口实现
        • native 层的SensorEventQueue 构造完成后,再次包装为Receiver对象,
          • Receiver.onFirstRef 函数中,把 mSensorQueue->getFd() 获取的 fd 加入到 loop 监听
            • mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0, ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
          • socket有数据时,调用 Receiver. handleEvent 方法
            • 方法中再回调到Java层的 SensorEventQueue.dispatchSensorEvent 方法
        • Receiver对象构造完成后,把指针返回给上层, 用于构造 Java 层的 SensorEventQueue 对象
      • queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs) //服务端发送enable消息
        • 保存激活的sensor属性
        • enableSensor 调用服务端,激活sensor

细节知识点

  • sensorservice onFirstRef 会通过 SensorDevice 类获取 sensor 列表
  • sensor hal 启动有问题会导致 systemserver 无法正常启动,进而导致开机问题
  • SensorService 启动后,会向 ActivityManager 注册 onUidStateChanged 回调,用于判断app是否处于活跃状态
  • one shot 模式
    • SensorService::threadLoop() 函数中实现 connection->hasOneShotSensors()
Sensor事件是否传给某个app -----判断权限、app活跃状态
/**
uid 是活跃的,或者在白名单里边
并且
isSensorPrivacyEnabled 返回true
**/    
bool SensorService::SensorEventConnection::hasSensorAccess() {
#if MI_SENSORSERVICE_FEATURE_ENABLE
    return (mService->isUidActive(mUid) || MiSensorServiceStub::isonwhitelist(getPackageName()))
        && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
#else
    return mService->isUidActive(mUid)
        && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
#endif
}