赞
踩
前面提到过java SensorService的主要实现则是由native SensorService来完成的,而后者则是由前者启动的。这里java层和native层之间相互调用的技术则是通过JNI(JAVA Native Interface)来实现的。这种方式打破了java 语言跨平台的特性,但也因此获得了高性能的特性。
前面提到 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;
}
其中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));
}
这部分代码则用于获取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"
可见 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);
}
...
}
onProximityActive的回调则在proxy sensor的状态变化。
将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)
},
...
};
在上一章提到过,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);
}
可见返回的指针指向类 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);
}
}
第一次启动 native SensorService,获取system_init.startsensorservice时为 true。所以此时构造函数 NativeSensorService 中做如下两件事
下面是对应的类图
从类图上可以看出,其顶层父类为 RefBase,并且Thread也是其父类之一,所以SensorService的初始化序列如下
1) SensorService 构造方法
2) onFirstRef
3) 在调用run后,Thread也就创建并启动了,其启动时序如下
3.1) readyToRun
3.2) threadLoop,自定义的任务会放在此方法内。内部任务则分为两种,一种是循环处理的,另一种则是单词运行的。前者需要在任务结束时,返回true即return true。后者则返回false即return false。
下面看下 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);
}
构造方法比较简单,因为大部分初始化工作都放在了 onFirstRef 中去了。
mInitCheck
代表 SensorService的初始化状态,定义如下
//frameworks\native\services\sensorservice\SensorService.h
enum {
OK = 0, // Preferred constant for checking success.
...
NO_INIT = -ENODEV,
..
};
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本身的功能实现。
主要的初始化操作都在onFirstRef中,所以这部分的代码量还是有的。下面按功能分开讲解来说明。
SensorDevice& dev(SensorDevice::getInstance());
SensorDevice如其名,用于管理Sensor的硬件操作,将SensorService和Sensor HAL很好的隔离开来。对于它的实例化将放在下一章。
在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]));
}
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; ... };
下面看下 HardwareSensor 的实例化,先看看类图
从类图看,一个Sensor所支持的操作主要位于SensorInterface中,其本身则是一个接口类和java中的interface是一个概念,内部只包含纯虚函数。下面则是HardwareSensor实例化的过程
HardwareSensor(list[i])
BaseSensor(sensor/* list[i] */)
mSensorDevice(SensorDevice::getInstance())
mSensor(&sensor/* list[i] */, mSensorDevice.getHalDeviceVersion())
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) 添加到 SensorService 自带的sensorlist中,供后续调用
//frameworks\native\services\sensorservice\SensorService.h
SensorServiceUtil::SensorList mSensors;
2) mRecentEvent 中创建一个 <handle, RecentEventLogger> 键值对,用于存储近期的sensorevent,供debug使用。
//register Fusion sensor
SensorFusion::getInstance();
if ((hasGyro || hasGyroUncalibrated) && hasAccel && hasMag){
registerSensor(new RotationVectorSensor(), !needRotationVector, true);
}
和上面提到的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; }
...
}
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; }
mSocketBufferSize用于初始化BitTube的buffer容量,决定sensorservice这个中转站能够存储sensor_event_t事件的数量,依据支持batch的sensor所要求的保留fifo大小来决定,最大不超过 /proc/sys/net/core/wmem_max 结点的值。
Looper实际上就是对epoll机制的封装,用于接收及事件的触发。
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
通过SensorDeivce.poll接口获取的sensor_event则存于该buffer,最终这部分buffer内容会被派发到各监听者。
//step 1
onFirstRef
mAckReceiver = new SensorEventAckReceiver(this);
mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
//step 1
bool SensorService::SensorEventAckReceiver::threadLoop() {
ALOGD("new thread SensorEventAckReceiver");
}
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);
上面则是Threads的run执行后的一系列动作,最终还是使用POSIX接口 pthread_creat e来进行线程的创建 _threadLoop 则是对应线程的回调方法。可见在自己的 threadLoop 中是不需要再编写循环体的。
值得一提的是,每次循环都会判断通过弱引用指针来获取本实例的强引用指针,从而判断实例是否还存在,如果不存在的话,本线程也就会随着退出了,不过这并不是同步进行的,即创建的线程也有可能会在对象释放后才退出。
随着 SensorService::run被调用后,其对应的 threadLoop 也将被执行
bool SensorService::threadLoop() {
SensorDevice& device(SensorDevice::getInstance());
do{
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
...
}while (!Thread::exitPending());
}
在 SensorService 的线程里则是在等待 SensorEvent的到来,然后再进行数据的处理及上报。
将 SensorService 的实例注册到 ServiceManager中去,此时注册的 SensorService则是支持跨进程调用的,即可以通过 getService来获取使用它的实例的。getServiceName()为静态方法,返回sensorservice字符串,其定义如下
//frameworks\native\services\sensorservice\SensorService.h
class SensorService
static char const* getServiceName() ANDROID_API { return "sensorservice"; }
};
系统启动后,也可以通过dumpsys命令查看系统服务 sensorservice。
board:/ # dumpsys sensorservice
Captured at: 17:49:19.799
Sensor Device:
Total 8 h/w sensors, 8 running 0 disabled clients:
...
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。