引言:近期在项目上遇到一个“FLP”问题。 本文借此问题来分析:同一个sensor被多个App监听SensorEventListener事件时,app client被"First flush Pending"问题;
1. App Java层的常规步骤
private void registerListener() {
Log.d(TAG, "registerListener");
mAccel = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mGyro = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
mSensorManager.registerListener(mSensorEventListener, mAccel,
SENSOR_DELAY_NORMAL, SENSOR_DELAY_NORMAL, mHandler);
mSensorManager.registerListener(mSensorEventListener, mGyro,
SENSOR_DELAY_NORMAL, SENSOR_DELAY_NORMAL, mHandler);
}
2. registerListener()函数
App侧调用的registerListener()接口,将会调用 SensorManager中的相应接口。进而调用SystemSensorManager中的registerListenerImpl()接口。
public boolean registerListener(SensorEventListener listener, Sensor sensor,
int samplingPeriodUs, int maxReportLatencyUs, Handler handler) {
int delayUs = getDelay(samplingPeriodUs);
return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0);
}
3. registerListenerImpl()函数
从代码上看:
①. Sensor Events的种类有:REPORTING_MODE_CONTINUOUS、REPORTING_MODE_ON_CHANGE、REPORTING_MODE_ONE_SHOT三种类型;
②. 在SystemSersorManager中,最多的Listerner Client数量为128个;
③. 获取SensorEventQueue,执行addSensor()操作;
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
if (listener == null || sensor == null) {
Log.e(TAG, "sensor or listener is null");
return false;
}
// Trigger Sensors should use the requestTriggerSensor call.
if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
return false;
}
if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
return false;
}
if (mSensorListeners.size() >= MAX_LISTENER_COUNT) { // MAX_LISTENER_COUNT:128
throw new IllegalStateException("register failed, "
+ "the sensor listeners size has exceeded the maximum limit "
+ MAX_LISTENER_COUNT);
}
// 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();
// 一个App,将会创建一个新的queue
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);
}
}
}
4. addSensor()函数
先判断同一个App,是否对同一个sensor进行的注册监听。如果,同一个App之前已经对相同 的Sensor进行了操作,则直接返回;
如果是一个App的第一次操作,则执行enableSensor()操作;
public boolean addSensor(
Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
// Check if already present.
int handle = sensor.getHandle();
if (mActiveSensors.get(handle)) return false;
// Get ready to receive events before calling enable.
mActiveSensors.put(handle, true);
addSensorEvent(sensor);
if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
// Try continuous mode if batching fails.
if (maxBatchReportLatencyUs == 0
|| maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
removeSensor(sensor, false);
return false;
}
}
return true;
}
5. enableSensor()函数
enableSensor()调用native的方法:nativeEnableSensor()
private int enableSensor(
Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
if (mNativeSensorEventQueue == 0) throw new NullPointerException();
if (sensor == null) throw new NullPointerException();
if (mManager.isSensorInCappedSet(sensor.getType())
&& rateUs < CAPPED_SAMPLING_PERIOD_US
&& mManager.mIsPackageDebuggable
&& !mManager.hasHighSamplingRateSensorsPermission()
&& Compatibility.isChangeEnabled(CHANGE_ID_SAMPLING_RATE_SENSORS_PERMISSION)) {
throw new SecurityException("To use the sampling rate of " + rateUs
+ " microseconds, app needs to declare the normal permission"
+ " HIGH_SAMPLING_RATE_SENSORS.");
}
return nativeEnableSensor(mNativeSensorEventQueue, sensor.getHandle(), rateUs,
maxBatchReportLatencyUs);
}
6. nativeEnableSensor()函数
receiver->getSensorEventQueue()返回的是SensorEventQueue,即nativeEnableSensor()调用的是SensorEventQueue中的enableSensor()接口
// file located in: frameworks/base/core/jni/android_hardware_SensorManager.cpp
static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
jobject eventQWeak, jobject msgQ, jstring packageName,
jint mode, jstring opPackageName, jstring attributionTag) {
// native层的SensorManager
SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
//省略部分代码
// native层的SensorService
sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode, attributionTagName));
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
//省略部分代码
sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
receiver->incStrong((void*)nativeInitSensorEventQueue);
return jlong(receiver.get());
}
static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
jint maxBatchReportLatency) {
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
0);
}
static const JNINativeMethod gBaseEventQueueMethods[] = {
{"nativeInitBaseEventQueue",
"(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/"
"String;Ljava/lang/String;)J",
(void *)nativeInitSensorEventQueue},
{"nativeEnableSensor", "(JIII)I", (void *)nativeEnableSensor},
{"nativeDisableSensor", "(JI)I", (void *)nativeDisableSensor},
{"nativeDestroySensorEventQueue", "(J)V", (void *)nativeDestroySensorEventQueue},
{"nativeFlushSensor", "(J)I", (void *)nativeFlushSensor},
{"nativeInjectSensorData", "(JI[FIJ)I", (void *)nativeInjectSensorData},
};
7. SensorEventQueue的enableSensor()函数
从代码上看可知:enable时,会设置一个默认的采样率;
同时 ,会调用SensorEventConnection中的enableDisable()接口;
// file located in: frameworks/native/libs/sensor/SensorEventQueue.cpp
status_t SensorEventQueue::enableSensor(Sensor const* sensor) const {
return enableSensor(sensor, SENSOR_DELAY_NORMAL);
}
status_t SensorEventQueue::enableSensor(Sensor const* sensor, int32_t samplingPeriodUs) const {
return mSensorEventConnection->enableDisable(sensor->getHandle(), true,
us2ns(samplingPeriodUs), 0, 0);
}
8. SensorEventConnection中的enableDisable()函数
从代码上看,最终调用了SensorService的enable()接口
status_t SensorService::SensorEventConnection::enableDisable(
int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
int reservedFlags)
{
// 省略部分代码;
status_t err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
reservedFlags, mOpPackageName);
if (err == OK && isSensorCapped) {
if ((requestedSamplingPeriodNs >= SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) ||
!isRateCappedBasedOnPermission()) {
mMicSamplingPeriodBackup[handle] = requestedSamplingPeriodNs;
} else {
mMicSamplingPeriodBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
}
}
} else {
err = mService->disable(this, handle);
mMicSamplingPeriodBackup.erase(handle);
}
return err;
}
9. SensorService的enable()函数
①. 一个App会有一个connection;
②. 一个类型的Sensor仅有一个SensorRecord;
③. 一个SensorRecord可以对应多个connection,但之后的connnection会被设置为"First flush pending"状态;
// filed located in: frameworks/native/services/sensorservice/SensorService.cpp#
status_t SensorService::enable(const sp<SensorEventConnection>& connection,
int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
const String16& opPackageName) {
// 省略部分代码;
SensorRecord* rec = mActiveSensors.valueFor(handle);
if (rec == nullptr) {
rec = new SensorRecord(connection);
mActiveSensors.add(handle, rec);
// 省略部分代码;
} else {
if (rec->addConnection(connection)) {
// 省略部分代码;
}
}
if (connection->addSensor(handle)) {
// 省略部分代码;
} else {
ALOGW("sensor %08x already enabled in connection %p (ignoring)",
handle, connection.get());
}
// Check maximum delay for the sensor.
nsecs_t maxDelayNs = sensor->getSensor().getMaxDelay() * 1000LL;
if (maxDelayNs > 0 && (samplingPeriodNs > maxDelayNs)) {
samplingPeriodNs = maxDelayNs;
}
nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs();
if (samplingPeriodNs < minDelayNs) {
samplingPeriodNs = minDelayNs;
}
// 调用SensorHal的batch()
status_t err = sensor->batch(connection.get(), handle, 0, samplingPeriodNs,
maxBatchReportLatencyNs);
// Call flush() before calling activate() on the sensor. Wait for a first
// flush complete event before sending events on this connection. Ignore
// one-shot sensors which don't support flush(). Ignore on-change sensors
// to maintain the on-change logic (any on-change events except the initial
// one should be trigger by a change in value). Also if this sensor isn't
// already active, don't call flush().
if (err == NO_ERROR &&
sensor->getSensor().getReportingMode() == AREPORTING_MODE_CONTINUOUS &&
rec->getNumConnections() > 1) {
connection->setFirstFlushPending(handle, true);
status_t err_flush = sensor->flush(connection.get(), handle);
// Flush may return error if the underlying h/w sensor uses an older HAL.
if (err_flush == NO_ERROR) {
rec->addPendingFlushConnection(connection.get());
} else {
connection->setFirstFlushPending(handle, false);
}
}
// 调用SensorHal的activate()方法
if (err == NO_ERROR) {
ALOGD_IF(DEBUG_CONNECTIONS, "Calling activate on %d", handle);
err = sensor->activate(connection.get(), true);
}
// 省略部分代码;
}
9.1 getNumConnections() > 1的处理
在检测到同一个类型的sensor有不同的App connect连接后:
①. 先把first flush pending状态切为true;
② 然后调用SensorHal层的flush;
从代码上看,想要支持多client,可在SensorHal层的flush操作后,返回给系统一个非0值,将first flush pending状态切为false,即可;