当前位置:   article > 正文

Android T(13)--Native 层的SensorService的启动(二)

sensorservice

1.概述

  前面提到过java SensorService的主要实现则是由native SensorService来完成的,而后者则是由前者启动的。这里java层和native层之间相互调用的技术则是通过JNI(JAVA Native Interface)来实现的。这种方式打破了java 语言跨平台的特性,但也因此获得了高性能的特性。

2.SensorService JNI接口的注册

  前面提到 SystemServer 是运行在system_server进程的虚拟机之中的,在虚拟机运行的时候JNI_OnLoad方法也会被运行,SensorService JNI的接口注册就在其中,对应代码如下

//frameworks/base/services/core/jni/onload.cpp
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
    ...
    register_android_server_sensor_SensorService(vm, env);
    return JNI_VERSION_1_4;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

  其中JavaVM指针也就指向了SystemServer所在的虚拟机。对于SensorService中的JNI接口注册则位于register_android_server_sensor_SensorService中,其对应代码如下

int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env) {
    sJvm = vm;
    //block1:getProximityActiveListenerFromJava
    jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS);
    sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V");
    //block2:register-jni
    return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods, NELEM(methods));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.1 block1:getProximityActiveListenerFromJava

  这部分代码则用于获取java中的类PROXIMITY_ACTIVE_CLASS的 onProximityActive 方法,PROXIMITY_ACTIVE_CLASS的定义如下

//frameworks/base/services/core/java/com/android/server/sensors/SensorManagerInternal.java
#define PROXIMITY_ACTIVE_CLASS \
    "com/android/server/sensors/SensorManagerInternal$ProximityActiveListener"

  • 1
  • 2
  • 3
  • 4

  可见 onProximityActive 位于为SensorManagerInternal内部类ProximityActiveListener,对应的java类如下

//frameworks/base/services/core/java/com/android/server/sensors/SensorManagerInternal.java
public abstract class SensorManagerInternal {
    ...
    public interface ProximityActiveListener {
        void onProximityActive(boolean isActive);
    }
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  onProximityActive的回调则在proxy sensor的状态变化。

2.2 block2:register-jni

  将methods方法注册到java类com.android.server.sensors.SensorService中去,其定义如下

// frameworks\base\services\core\jni\com_android_server_sensor_SensorService.cpp
static const JNINativeMethod methods[] = {
    {
            "startSensorServiceNative", "(L" PROXIMITY_ACTIVE_CLASS ";)J",
            reinterpret_cast<void*>(startSensorServiceNative)
    },
    ...
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3. startSensorServiceNative

  在上一章提到过,java SensorService 的实现位于 native SensorService中,并且是通过调用后者返回的指针实现的,对应的指针是通过native方法 startSensorServiceNative获得的。

static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) {
    NativeSensorService* service = new NativeSensorService(env, listener);
    return reinterpret_cast<jlong>(service);
}
  • 1
  • 2
  • 3
  • 4

  可见返回的指针指向类 NativeSensorService 的一个实例,下面看下其对应的构造方法

NativeSensorService::NativeSensorService(JNIEnv* env, jobject listener)
      : mProximityActiveListenerDelegate(new ProximityActiveListenerDelegate(env, listener)) {
    if (base::GetBoolProperty("system_init.startsensorservice", true)) {
        sp<IServiceManager> sm(defaultServiceManager());
        mService = new SensorService();
        sm->addService(String16(SensorService::getServiceName()), mService,
                       false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

  第一次启动 native SensorService,获取system_init.startsensorservice时为 true。所以此时构造函数 NativeSensorService 中做如下两件事

3.1. 实例化类 SensorService

  下面是对应的类图
在这里插入图片描述

  从类图上可以看出,其顶层父类为 RefBase,并且Thread也是其父类之一,所以SensorService的初始化序列如下
  1) SensorService 构造方法
  2) onFirstRef
  3) 在调用run后,Thread也就创建并启动了,其启动时序如下
    3.1) readyToRun
    3.2) threadLoop,自定义的任务会放在此方法内。内部任务则分为两种,一种是循环处理的,另一种则是单词运行的。前者需要在任务结束时,返回true即return true。后者则返回false即return false。
  下面看下 SensorService 各个阶段所处理的事项

3.1.1. SensorService::SensorService()
SensorService::SensorService()
    : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
      mWakeLockAcquired(false), mLastReportedProxIsActive(false) {
    mUidPolicy = new UidPolicy(this);
    mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
    mMicSensorPrivacyPolicy = new MicrophonePrivacyPolicy(this);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

  构造方法比较简单,因为大部分初始化工作都放在了 onFirstRef 中去了。
mInitCheck
  代表 SensorService的初始化状态,定义如下

//frameworks\native\services\sensorservice\SensorService.h
enum {
    OK                = 0,    // Preferred constant for checking success.
    ...
    NO_INIT             = -ENODEV,
    ..
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

mSocketBufferSize
  决定sensorservice这个中转站能够存储sensor_event_t事件的数量,依据支持batch的sensor所要求的保留fifo大小来决定,最大不超过 /proc/sys/net/core/wmem_max 结点的值。
mWakeLockAcquired
  记录唤醒锁的使用状态,唤醒锁被持有时,设备是无法休眠的,用于解决 sensorhub wakeup 事件上报的实时性。
mLastReportedProxIsActive
  The last proximity sensor active state reported to listeners.
  剩下的部分则是关于应用访问sensor的权限控制内容,这部分会单独拎出去讲,本章还是关注sensor本身的功能实现。

3.1.2. onFirstRef()

  主要的初始化操作都在onFirstRef中,所以这部分的代码量还是有的。下面按功能分开讲解来说明。

3.1.2.1. SensorDevice的实例获取
SensorDevice& dev(SensorDevice::getInstance());
  • 1

  SensorDevice如其名,用于管理Sensor的硬件操作,将SensorService和Sensor HAL很好的隔离开来。对于它的实例化将放在下一章。

3.1.2.2. Hardware Sensor 的注册

  在android中的senosr有两大类,一类是有硬件实体的sensor,例如磁力传感器、加速度,另一类就是基于有硬件实体的sensor数据通过软件算法实现的sensor,在SensorService这一层统一称作 Fusion sensor。下面的SENSOR_TYPE_ACCELEROMETER则对应一个harware sensor。

ssize_t count = dev.getSensorList(&list);
for (ssize_t i=0 ; i<count ; i++) {
    bool useThisSensor = true;
    switch (list[i].type) {
        case SENSOR_TYPE_ACCELEROMETER:
            hasAccel = true;
    }
    if(useThisSensor)
        registerSensor(new HardwareSensor(list[i]));

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

  dev.getSensorList 则会通过 HAL接口获取到设备能够支持的Sensor,从HAL获取的Sensor都会用类HardwareSensor来重新封装,并调用接口registerSensor进行注册。通过getSensorList获取的sensor用类型 sensor_t 表示,其定义如下

//file:hardware/libhardware/include/hardware/sensors.h
struct sensor_t {
    /* Name of this sensor.
     * All sensors of the same "type" must have a different "name".
     */
    const char*     name;

    /* vendor of the hardware part */
    const char*     vendor;
    /* handle that identifies this sensors. This handle is used to reference
     * this sensor throughout the HAL API.
     */
    int             handle;
    /* this sensor's type. */
    int             type;
    int32_t         minDelay;
    uint32_t        fifoMaxEventCount;
    const char*    stringType;
    ...
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

  下面看下 HardwareSensor 的实例化,先看看类图
在这里插入图片描述

  从类图看,一个Sensor所支持的操作主要位于SensorInterface中,其本身则是一个接口类和java中的interface是一个概念,内部只包含纯虚函数。下面则是HardwareSensor实例化的过程

HardwareSensor(list[i])
    BaseSensor(sensor/* list[i] */)
        mSensorDevice(SensorDevice::getInstance())
        mSensor(&sensor/* list[i] */, mSensorDevice.getHalDeviceVersion())
  • 1
  • 2
  • 3
  • 4

  mSensor的类型为 Sensor ,其类图如下
在这里插入图片描述

  最终HAL传上来的sensor_t类型则会被类Sensor所替代存于类BaseSensor的mSensor私有数据中去。
  值得一提的是,每一个HardwareSensor除了包含配置Sensor的接口,还包括对原始数据进行处理的接口 process,供不同sensor对sensor event调整使用。
  下面则是 registerSensor 的实现

//frameworks\native\services\sensorservice\SensorService.cpp
const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
    int handle = s->getSensor().getHandle();
    int type = s->getSensor().getType();
    if (mSensors.add(handle, s, isDebug, isVirtual)){
        mRecentEvent.emplace(handle, new SensorServiceUtil::RecentEventLogger(type));
        return s->getSensor();
    else
        return mSensors.getNonSensor();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

  注册的实现非常的简单,总结流程如下
    1) 添加到 SensorService 自带的sensorlist中,供后续调用

//frameworks\native\services\sensorservice\SensorService.h
SensorServiceUtil::SensorList mSensors;
  • 1
  • 2

    2) mRecentEvent 中创建一个 <handle, RecentEventLogger> 键值对,用于存储近期的sensorevent,供debug使用。

    

3.1.2.3. Fursion Sensor的注册
//register Fusion sensor
SensorFusion::getInstance();
if ((hasGyro || hasGyroUncalibrated) && hasAccel && hasMag){
    registerSensor(new RotationVectorSensor(), !needRotationVector, true);
}
  • 1
  • 2
  • 3
  • 4
  • 5

  和上面提到的HardwareSensor初始化而言并没有太大的差别,唯一的区别则是 Fusion sensor 是需要依赖一个或者多个 HardwareSensor 的,例如此处的 RotationVectorSensor 则需要依赖 Gyro(陀螺仪)、Accel(加速度)、Mag(磁力计)这三个HardwareSensor。下面给出 RotationVectorSensor的类图
在这里插入图片描述

  可见之间多了一层VirtualSensor父类,其主要作用就是设置函数 isVirtual返回true

//frameworks\native\services\sensorservice\SensorInterface.h
class VirtualSensor : public BaseSensor{
    ...
public:
    virtual bool isVirtual() const override { return true; }
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3.1.2.4. BitTube 容量设置
mSensors.forEachSensor(
[&batchingSupported] (const Sensor& s) -> bool {
    if (s.getFifoMaxEventCount() > 0) {
        batchingSupported = true;
    }
    return !batchingSupported;
});

if (batchingSupported) {
    // Increase socket buffer size to a max of 100 KB for batching capabilities.
    mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
} else {
    mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;
}

// Compare the socketBufferSize value against the system limits and limit
// it to maxSystemSocketBufferSize if necessary.
FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r");

    mSocketBufferSize = maxSystemSocketBufferSize;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

  mSocketBufferSize用于初始化BitTube的buffer容量,决定sensorservice这个中转站能够存储sensor_event_t事件的数量,依据支持batch的sensor所要求的保留fifo大小来决定,最大不超过 /proc/sys/net/core/wmem_max 结点的值。

3.1.2.5. 创建事件跟踪器–Looper

  Looper实际上就是对epoll机制的封装,用于接收及事件的触发。

3.1.2.6. sensor事件存储器–mSensorEventBuffer
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
  • 1
  • 2

  通过SensorDeivce.poll接口获取的sensor_event则存于该buffer,最终这部分buffer内容会被派发到各监听者。

3.1.2.7. SensorEventAckReceiver 的注册及运行
//step 1
onFirstRef
    mAckReceiver = new SensorEventAckReceiver(this);
    mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
//step 1
bool SensorService::SensorEventAckReceiver::threadLoop() {
    ALOGD("new thread SensorEventAckReceiver");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
3.1.2.8. SensorService 线程启动
run("SensorService", PRIORITY_URGENT_DISPLAY)
    //system\core\libutils\Threads.cpp 
    A1.androidCreateRawThreadEtc(_threadLoop/* entryFunction */,
                this, name, priority, stack, &mThread)
        B1.pthread_create(&thread, entryFunction);

    A2._threadLoop
        sp<Thread> strong(self->mHoldSelf);
        wp<Thread> weak(strong);
        self->mHoldSelf.clear();
        do {
            self->mStatus = self->readyToRun();
            result = self->threadLoop();
        }while(strong != nullptr);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

  上面则是Threads的run执行后的一系列动作,最终还是使用POSIX接口 pthread_creat e来进行线程的创建 _threadLoop 则是对应线程的回调方法。可见在自己的 threadLoop 中是不需要再编写循环体的。
  值得一提的是,每次循环都会判断通过弱引用指针来获取本实例的强引用指针,从而判断实例是否还存在,如果不存在的话,本线程也就会随着退出了,不过这并不是同步进行的,即创建的线程也有可能会在对象释放后才退出。

3.1.3. after the function of run called–run()

  随着 SensorService::run被调用后,其对应的 threadLoop 也将被执行

bool SensorService::threadLoop() {
    SensorDevice& device(SensorDevice::getInstance());
    do{
        ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
        ...
    }while (!Thread::exitPending());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

  在 SensorService 的线程里则是在等待 SensorEvent的到来,然后再进行数据的处理及上报。

3.2. native SensorService 的注册

  将 SensorService 的实例注册到 ServiceManager中去,此时注册的 SensorService则是支持跨进程调用的,即可以通过 getService来获取使用它的实例的。getServiceName()为静态方法,返回sensorservice字符串,其定义如下

//frameworks\native\services\sensorservice\SensorService.h
class SensorService
    static char const* getServiceName() ANDROID_API { return "sensorservice"; }
};
  • 1
  • 2
  • 3
  • 4

  系统启动后,也可以通过dumpsys命令查看系统服务 sensorservice。

board:/ # dumpsys sensorservice
Captured at: 17:49:19.799
Sensor Device:
Total 8 h/w sensors, 8 running 0 disabled clients:
...
  • 1
  • 2
  • 3
  • 4
  • 5

4. 涉及类定义源码路径

frameworks\native\services\sensorservice\SensorDevice.h
frameworks\native\services\sensorservice\RotationVectorSensor.h
frameworks\native\services\sensorservice\SensorInterface.h
system\core\libutils\include\utils\LightRefBase.h
system/core/libutils/include/utils/Singleton.h
frameworks\native\services\sensorservice\ISensorHalWrapper.h
frameworks\native\services\sensorservice\SensorServiceUtils.h
frameworks\native\libs\sensor\include\sensor\Sensor.h
system\core\libutils\include\utils\Flattenable.h
system\core\libutils\include\utils\Thread.h
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5. 时序图

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/778970
推荐阅读
相关标签
  

闽ICP备14008679号