本文基于Android 12源码整理,包含如下内容:
- 通信架构
- 应用层实现
- 使用方式
- SensorManager抽象接口具体实现
- fwk层的实现
- native中的SensorManager的初始化流程
- native中的消息队列初始化与数据读取
- sensorservice实现
- HAL层的实现
通信架构
应用层实现
涉及代码:
framework/base/core/java/android/hardware/SensorManager.java
framework/base/core/java/android/hardware/SystemSensorManager.java
framework/base/core/java/android/hardware/SensorEvent.java
使用方式
应用层主要使用fwk提供的SensorManager 来监听获取指定传感器的数据,主要实现如下,
回调的参数SensorEvent是一个包含传感器参数与当前值的数据结构,不同的传感器数据均从其values的float数组中获取值,如光感传感器的值只有一个就是values[0], 陀螺仪有三个值就是values[0],values[1],values[2]等。
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
val sm = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sm.registerListener(object : SensorEventListener{
override fun onSensorChanged(event: SensorEvent?) {
val x = event?.values?.get(0)
val y = event?.values?.get(1)
val z = event?.values?.get(2)
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
//传感器精度回调
}
}, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL)
SensorManager抽象接口具体实现
SensorManager是一个抽象函数,部分抽象函数的具体的功能实现是在SystemSensorManager类中, 其构造函数主要做的工作依次如下:
- 初始化jni接口
- 创建一个SensorManager的native层实例
- 检查当前进程是否具备高速传输传感器数据的权限
- 初始化本机的sensor设备列表
public SystemSensorManager(Context context, Looper mainLooper) {
synchronized (sLock) {
if (!sNativeClassInited) {
sNativeClassInited = true;
//初始化jni接口
nativeClassInit();
}
}
mMainLooper = mainLooper;
ApplicationInfo appInfo = context.getApplicationInfo();
mTargetSdkLevel = appInfo.targetSdkVersion;
mContext = context;
//创建一个SensorManager的native层实例
mNativeInstance = nativeCreate(context.getOpPackageName());
mIsPackageDebuggable = (0 != (appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE));
PackageManager packageManager = context.getPackageManager();
//检查当前进程是否具备高速传输传感器数据的权限
mHasHighSamplingRateSensorsPermission =
(PERMISSION_GRANTED == packageManager.checkPermission(
HIGH_SAMPLING_RATE_SENSORS_PERMISSION,
appInfo.packageName));
// initialize the sensor list
for (int index = 0;; ++index) {
Sensor sensor = new Sensor();
//初始化本机的sensor设备列表
if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
mFullSensorsList.add(sensor);
mHandleToSensor.put(sensor.getHandle(), sensor);
}
}
每个app在通过getSystemService获取class类型为SensorManager的对象时,获取的都是SystemSensorManager对象,实例的初始化在SystemServiceRegistry的静态域中初始化,代码如下:
registerService(Context.SENSOR_SERVICE, SensorManager.class,
new CachedServiceFetcher<SensorManager>() {
@Override
public SensorManager createService(ContextImpl ctx) {
Return new SystemSensorManager(ctx.getOuterContext(),
ctx.mMainThread.getHandler().getLooper());
}});
再跟一下监听函数registerListener,最终会走到SystemSensorManager的registerListenerImpl函数中,实现功能如下:
- 检查注册参数是否符合要求
- 获取监听器实例的所有事件队列
-> 如果队列为空
1.创建新的队列实例
2.队列实例中加入当前监听的Sensor对象
3.将事件队列加入到监听器的HashMap中对应保存
-> 如果队列不为空
1.队列实例中加入当前监听的Sensor对象
实现代码如下:
// Invariants to preserve:
// - one Looper per SensorEventListener
// - one Looper per SensorEventQueue
// We map SensorEventListener to a SensorEventQueue, which holds the looper
synchronized (mSensorListeners) {
SensorEventQueue queue = mSensorListeners.get(listener);
if (queue == null) {
Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
final String fullClassName =listener.getClass().getEnclosingClass() != null
? listener.getClass().getEnclosingClass().getName()
: listener.getClass().getName();
queue = new SensorEventQueue(listener, looper, this, fullClassName);
if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
queue.dispose();
return false;
}
mSensorListeners.put(listener, queue);
return true;
} else {
return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
}
}
SensorEventQueue 是定义在SystemSensorManager.java文件中的一个静态内部类,其父类类型为BaseEventQueue,BaseEventQueue中定义了enableSensor, 在app注册了监听器后,BaseEventQueue会调用nativeEnableSensor去激活该Sensor. SensorEventQueue中还实现了dispatchSensorEvent函数,当底层上报数据的时候,JNI层会回调该函数,将数据传给listener实例。
protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
long timestamp) {
final Sensor sensor = mManager.mHandleToSensor.get(handle);
if (sensor == null) {
// sensor disconnected
return;
}
SensorEvent t = null;
synchronized (mSensorsEvents) {
t = mSensorsEvents.get(handle);
}
if (t == null) {
// This may happen if the client has unregistered and there are pending events in
// the queue waiting to be delivered. Ignore.
return;
}
// Copy from the values array.
System.arraycopy(values, 0, t.values, 0, t.values.length);
t.timestamp = timestamp;
t.accuracy = inAccuracy;
t.sensor = sensor;
// call onAccuracyChanged() only if the value changes
final int accuracy = mSensorAccuracies.get(handle);
if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
mSensorAccuracies.put(handle, t.accuracy);
mListener.onAccuracyChanged(t.sensor, t.accuracy);
}
mListener.onSensorChanged(t);
}
fwk层的实现
涉及代码如下:
frameworks/base/core/jni/android_hardware_SensorManager.cpp
frameworks/native/libs/sensor/*
frameworks/native/services/sensorservice/*
SensorManager的jni实现,定义在android_hardware_SensorManager.cpp这个文件中,这里不全部介绍每个本地函数的功能,只挑几个重要的
native中的SensorManager的初始化流程
android_hardware_SensorManager.cpp
//初始化native层SensorManager
static jlong
nativeCreate(JNIEnv *env, jclass clazz, jstring opPackageName)
{
ScopedUtfChars opPackageNameUtf(env, opPackageName);
return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
}
SensorManager.cpp文件路径在frameworks/native/libs/sensor文件夹下,该库编译后生成libsensor.so给到libandroid_server.so依赖,该库是一个通信中间件,实现了Sensor数据的同一进程内unix域通信,以及通过binder通信来实现部分Sensor的设置项实现。Sensor的jni类就是靠引入该库的头文件来实现与Sensor Service通信的。
获取SensorManager实例
frameworks/native/libs/sensor/SensorManager.cpp
SensorManager& SensorManager::getInstanceForPackage(const String16& packageName) {
waitForSensorService(nullptr);
Mutex::Autolock _l(sLock);
SensorManager* sensorManager;
//sPackageInstances是一个map数据结构,key是const String16,value是SensorManager指针
auto iterator = sPackageInstances.find(packageName);
//如果这个包已经获取过SensorManager,直接把返回该实例的指针
if (iterator != sPackageInstances.end()) {
sensorManager = iterator->second;
} else {
String16 opPackageName = packageName;
//权限检测,判断当前调用的包名是不是有权限访问sensor
if (opPackageName.size() <= 0) {
sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
if (binder != nullptr) {
const uid_t uid = IPCThreadState::self()->getCallingUid();
Vector<String16> packages;
interface_cast<IPermissionController>(binder)->getPackagesForUid(uid, packages);
if (!packages.isEmpty()) {
opPackageName = packages[0];
} else {
ALOGE("No packages for calling UID");
}
} else {
ALOGE("Cannot get permission service");
}
}
//创建一个新的SensorManager对象
sensorManager = new SensorManager(opPackageName);
// If we had no package name, we looked it up from the UID and the sensor
// manager instance we created should also be mapped to the empty package
// name, to avoid looking up the packages for a UID and get the same result.
if (packageName.size() <= 0) {
sPackageInstances.insert(std::make_pair(String16(), sensorManager));
}
// Stash the per package sensor manager.
sPackageInstances.insert(std::make_pair(opPackageName, sensorManager));
}
return *sensorManager;
}
native中的消息队列初始化与数据读取
上图包括了一个native中消息队列创建的完整流程,在之前讲过registerListener的数据主要来自SensorEventQueue的dispatchSensorEvent, 这个java层的方法回调是由JNI实现中的Receiver函数来触发的,Receiver是LooperCallback的子类,实际可以看成Handler的Native样式,这个函数的dispatchEvent中会一直循环从native层的SensorEventQueue中去read数据,read函数的实现在libsensor.so库中的BitTube.cpp实现,因为sensorservice与sensor jni均运行在system_server进程内,故这里数据的读写使用unix同进程内的域通信来实现的。具体的通信实现可以看BitTube.cpp这个文件。
sensorservice实现
上面一节分析完了,Sensor数据是在jni中的Receiver中通过JNI反射java层函数,调用Java层的SensorEventQueue中的dispatchSensorEvent函数发给各个app的, Receiver通过libsensor.so不断从server端去read数据,这里Receiver可以看作是一个客户端,那么服务端的实现就是sensorservice, 其实现在frameworks/native/services/sensorservice下,这个服务的作用就是起到承上启下的作用,对上作为aidl的BnBinder端供BpBinder调用,作为Socket的Server端,往Client端写数据;对下,则是作为一个hidl的client端,通过调用hal层的sensor服务接口,来联通上下层。其主要流程如下:
- threadLoop函数中循环通过SensorDevice去poll数据,并通过SensorEventConnect的sendEvents发送到jni函数的Receiver中
- SensorDevice.cpp 顾名思义就是传感器设备,该类实现了HIDL的接口,并通过hidl与hal层实现数据的poll以及设置的接口调用,列表的初始化等。
- SensorEventConnection.cpp是一个事件处理通道,保持了与client进行unix域通信的双句柄,通过调用SensorEventQueue的write函数实现将sensor数据发送到client端(JNI中的Receiver类)。
threadLoop函数poll数据的实现:
SensorService.cpp
bool SensorService::threadLoop() {
ALOGD("nuSensorService thread starting...");
...
...
//SensorDevice是单例模式的
SensorDevice& device(SensorDevice::getInstance());
//获取hal层版本
const int halVersion = device.getHalDeviceVersion();
do {
//poll数据
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
if (count < 0) {
if(count == DEAD_OBJECT && device.isReconnecting()) {
device.reconnect();
continue;
} else {
ALOGE("sensor poll failed (%s)", strerror(-count));
break;
}
}
// Reset sensors_event_t.flags to zero for all events in the buffer.
for (int i = 0; i < count; i++) {
mSensorEventBuffer[i].flags = 0;
}
//省略了很多代码
//将数据发送到所有通道
for (const sp<SensorEventConnection>& connection : activeConnections) {
//发送数据
connection->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
mMapFlushEventsToConnections);
needsWakeLock |= connection->needsWakeLock();
// If the connection has one-shot sensors, it may be cleaned up after first trigger.
// Early check for one-shot sensors.
if (connection->hasOneShotSensors()) {
cleanupAutoDisabledSensorLocked(connection, mSensorEventBuffer, count);
}
}
}while (!Thread::exitPending());
}
SensorDevice的poll功能实现
ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
if (mSensors == nullptr) return NO_INIT;
ssize_t eventsRead = 0;
if (mSensors->supportsMessageQueues()) {
eventsRead = pollFmq(buffer, count);//从mSensors的消息队列读值
} else if (mSensors->supportsPolling()) {
eventsRead = pollHal(buffer, count); //调用mSensors的poll函数取值
} else {
ALOGE("Must support polling or FMQ");
eventsRead = -1;
}
return eventsRead;
}
mSensors变量类型定义如下:
sp<::android::hardware::sensors::V2_1::implementation::ISensorsWrapperBase> mSensors;
这个类型是由hidl生成的,定义在hardware/interfaces/sensors/2.1/default下,厂商自定义实现该功能。
SensorEventConnection sendEvents的实现
SensorEventConnection.cpp
status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t const* buffer, size_t numEvents,
sensors_event_t* scratch,
wp<const SensorEventConnection> const * mapFlushEventsToConnections)
//... 省略很多代码
ssize_t size = SensorEventQueue::write(mChannel,
reinterpret_cast<ASensorEvent const*>(scratch), count);
//... 省略很多代码
}
SensorEventQueue实现在libsensor.so里面,write函数就是调用了内部的网络通信封装的类BitTube.cpp来实现写入。
HAL层的实现
hal层的实现基本上每个厂商的实现都不一样,这里只跟了一下原生的,涉及到的源码如下:
hardware/libhardware/include/hardware/sensors.h
hardware/libhardware/include/hardware/sensors-base.h
hardware/interfaces/sensors/*
sensors.h定义了sensor的各类数据结构,如sensor的数据格式,sensor对应hal层的module,sensor device格式,以及实现了动态管理客制化的sensor hal实现的库或者驱动的接口。
/** convenience API for opening and closing a device */
static inline int sensors_open(const struct hw_module_t* module,
struct sensors_poll_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_POLL, TO_HW_DEVICE_T_OPEN(device));
}
static inline int sensors_close(struct sensors_poll_device_t* device) {
return device->common.close(&device->common);
}
static inline int sensors_open_1(const struct hw_module_t* module,
sensors_poll_device_1_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_POLL, TO_HW_DEVICE_T_OPEN(device));
}
static inline int sensors_close_1(sensors_poll_device_1_t* device) {
return device->common.close(&device->common);
}
sensors-base.h则定义了SENSOR设备类型的值。
hardware/interfaces/sensors/1.0/default/Sensors.cpp中实现了对sensor module的load,以及设备的加载。
Sensors::Sensors()
: mInitCheck(NO_INIT),
mSensorModule(nullptr),
mSensorDevice(nullptr) {
status_t err = OK;
if (UseMultiHal()) {
mSensorModule = ::get_multi_hal_module_info();
} else {
//hal层动态加载module的so库, hw_get_module的实现在hardware/libhardware/hardware.c中,是要是动过dlopen动态加载so库。
err = hw_get_module(
SENSORS_HARDWARE_MODULE_ID,
(hw_module_t const **)&mSensorModule);
}
if (mSensorModule == NULL) {
err = UNKNOWN_ERROR;
}
if (err != OK) {
LOG(ERROR) << "Couldn't load "
<< SENSORS_HARDWARE_MODULE_ID
<< " module ("
<< strerror(-err)
<< ")";
mInitCheck = err;
return;
}
//从module涨获取到sensor设备,后续的操作都需要mSensorDevice才能与真实的硬件设备通讯
err = sensors_open_1(&mSensorModule->common, &mSensorDevice);