Android Sensor调用从上层到底层

2023-11-29 20:52

本文主要是介绍Android Sensor调用从上层到底层,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. Sensor应用层调用
SensorManager mSensorManager;
Sensor mSensor;
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); //获取sensor服务
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE); //获取默认sensor类型mSensorManager.registerListener(mSensorEventListener, mSensor, SensorManager.SENSOR_DELAY_NORMAL);//注册sensor,提供sensor监听器,监听状态变化mSensorManager.unregisterListener(mSensorEventListener,mSensor);//取消注册sensor监听器

2.SensorManager接口\frameworks\base\core\java\android\hardware\SensorManager.java
以registerListener举例

public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs) {return registerListener(listener, sensor, samplingPeriodUs, null);}
public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs, int maxReportLatencyUs) {int delay = getDelay(samplingPeriodUs);return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0);}protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags);

3.frameworks\base\core\java\android\hardware\SystemSensorManager.java
SystemSensorManager.java继承SensorManager.java实现registerListenerImpl、unregisterListenerImpl等函数

    /** @hide */@Overrideprotected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {android.util.SeempLog.record_sensor_rate(381, sensor, delayUs);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) {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 loopersynchronized (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);}}}/** @hide */@Overrideprotected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {android.util.SeempLog.record_sensor(382, sensor);// Trigger Sensors should use the cancelTriggerSensor call.if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {return;}synchronized (mSensorListeners) {SensorEventQueue queue = mSensorListeners.get(listener);if (queue != null) {boolean result;if (sensor == null) {result = queue.removeAllSensors();} else {result = queue.removeSensor(sensor, true);}if (result && !queue.hasSensors()) {mSensorListeners.remove(listener);queue.dispose();}}}}

3.在registerListenerImpl中创建SensorEventQueue(SensorEventQueue queue = mSensorListeners.get(listener);)
添加到mSensorListeners queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);

 static final class SensorEventQueue extends BaseEventQueue{private final SensorEventListener mListener;private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();public SensorEventQueue(SensorEventListener listener, Looper looper,SystemSensorManager manager, String packageName) {super(looper, manager, OPERATING_MODE_NORMAL, packageName);mListener = listener;}@Overridepublic void addSensorEvent(Sensor sensor) {SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,mManager.mTargetSdkLevel));synchronized (mSensorsEvents) {mSensorsEvents.put(sensor.getHandle(), t);}}@Overridepublic void removeSensorEvent(Sensor sensor) {synchronized (mSensorsEvents) {mSensorsEvents.delete(sensor.getHandle());}}// Called from native code.@SuppressWarnings("unused")@Overrideprotected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,long timestamp) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}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 changesfinal 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);}// Called from native code.@SuppressWarnings("unused")@Overrideprotected void dispatchFlushCompleteEvent(int handle) {if (mListener instanceof SensorEventListener2) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}((SensorEventListener2) mListener).onFlushCompleted(sensor);}return;}// Called from native code.@SuppressWarnings("unused")@Overrideprotected void dispatchAdditionalInfoEvent(int handle, int type, int serial, float[] floatValues, int[] intValues) {if (mListener instanceof SensorEventCallback) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}SensorAdditionalInfo info =new SensorAdditionalInfo(sensor, type, serial, intValues, floatValues);((SensorEventCallback) mListener).onSensorAdditionalInfo(info);}}}

4.nativeInitBaseEventQueue()方法里边,通过jni调用\frameworks\base\core\jni\android_hardware_SensorManager.cpp中创建一个接收数据的Receiver对象

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;}private int enableSensor(Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {if (mNativeSensorEventQueue == 0) throw new NullPointerException();if (sensor == null) throw new NullPointerException();return nativeEnableSensor(mNativeSensorEventQueue, sensor.getHandle(), rateUs,maxBatchReportLatencyUs);
}

5.通过jni调用到frameworks\base\core\jni\android_hardware_SensorManager.cpp::nativeEnableSensor

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);
}

6.\frameworks\native\libs\sensor\SensorEventQueue.cpp SensorEventQueue::enableSensor

status_t SensorEventQueue::enableSensor(Sensor const* sensor, int32_t samplingPeriodUs) const {return mSensorEventConnection->enableDisable(sensor->getHandle(), true,us2ns(samplingPeriodUs), 0, 0);
}

7.frameworks\native\services\sensorservice\SensorEventConnection.cpp SensorService::SensorEventConnection::enableDisable

status_t SensorService::SensorEventConnection::enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,int reservedFlags)
{if (mDestroyed) {android_errorWriteLog(0x534e4554, "168211968");return DEAD_OBJECT;}status_t err;if (enabled) {nsecs_t requestedSamplingPeriodNs = samplingPeriodNs;bool isSensorCapped = false;sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);if (si != nullptr) {const Sensor& s = si->getSensor();if (mService->isSensorInCappedSet(s.getType())) {isSensorCapped = true;}}if (isSensorCapped) {err = mService->adjustSamplingPeriodBasedOnMicAndPermission(&samplingPeriodNs,String16(mOpPackageName));if (err != OK) {return err;}}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;
}

8.\frameworks\native\services\sensorservice\SensorService.cpp SensorService::enable

status_t SensorService::enable(const sp<SensorEventConnection>& connection,int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,const String16& opPackageName) {if (mInitCheck != NO_ERROR)return mInitCheck;sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);if (sensor == nullptr ||!canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {return BAD_VALUE;}ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);if (mCurrentOperatingMode != NORMAL&& !isWhiteListedPackage(connection->getPackageName())) {return INVALID_OPERATION;}SensorRecord* rec = mActiveSensors.valueFor(handle);if (rec == nullptr) {rec = new SensorRecord(connection);mActiveSensors.add(handle, rec);if (sensor->isVirtual()) {mActiveVirtualSensors.emplace(handle);}// There was no SensorRecord for this sensor which means it was previously disabled. Mark// the recent event as stale to ensure that the previous event is not sent to a client. This// ensures on-change events that were generated during a previous sensor activation are not// erroneously sent to newly connected clients, especially if a second client registers for// an on-change sensor before the first client receives the updated event. Once an updated// event is received, the recent events will be marked as current, and any new clients will// immediately receive the most recent event.if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {auto logger = mRecentEvent.find(handle);if (logger != mRecentEvent.end()) {logger->second->setLastEventStale();}}} else {if (rec->addConnection(connection)) {// this sensor is already activated, but we are adding a connection that uses it.// Immediately send down the last known value of the requested sensor if it's not a// "continuous" sensor.if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {// NOTE: The wake_up flag of this event may get set to// WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event.auto logger = mRecentEvent.find(handle);if (logger != mRecentEvent.end()) {sensors_event_t event;// Verify that the last sensor event was generated from the current activation// of the sensor. If not, it is possible for an on-change sensor to receive a// sensor event that is stale if two clients re-activate the sensor// simultaneously.if(logger->second->populateLastEventIfCurrent(&event)) {event.sensor = handle;if (event.version == sizeof(sensors_event_t)) {if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {setWakeLockAcquiredLocked(true);}connection->sendEvents(&event, 1, nullptr);if (!connection->needsWakeLock() && mWakeLockAcquired) {checkWakeLockStateLocked(&connLock);}}}}}}}if (connection->addSensor(handle)) {BatteryService::enableSensor(connection->getUid(), handle);// the sensor was added (which means it wasn't already there)// so, see if this connection becomes activemConnectionHolder.addEventConnectionIfNotPresent(connection);} 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;}ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d""rate=%" PRId64 " timeout== %" PRId64"",handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs);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);}}if (err == NO_ERROR) {ALOGD_IF(DEBUG_CONNECTIONS, "Calling activate on %d", handle);err = sensor->activate(connection.get(), true);}if (err == NO_ERROR) {connection->updateLooperRegistration(mLooper);if (sensor->getSensor().getRequiredPermission().size() > 0 &&sensor->getSensor().getRequiredAppOp() >= 0) {connection->mHandleToAppOp[handle] = sensor->getSensor().getRequiredAppOp();}mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex) =SensorRegistrationInfo(handle, connection->getPackageName(),samplingPeriodNs, maxBatchReportLatencyNs, true);mNextSensorRegIndex = (mNextSensorRegIndex + 1) % SENSOR_REGISTRATIONS_BUF_SIZE;}if (err != NO_ERROR) {// batch/activate has failed, reset our state.cleanupWithoutDisableLocked(connection, handle);}return err;
}

9.frameworks\native\services\sensorservice\SensorInterface.cpp HardwareSensor::activate

status_t HardwareSensor::activate(void* ident, bool enabled) {return mSensorDevice.activate(ident, mSensor.getHandle(), enabled);
}

10.\frameworks\native\services\sensorservice\SensorDevice.cpp SensorDevice::activate

status_t SensorDevice::activate(void* ident, int handle, int enabled) {if (mHalWrapper == nullptr) return NO_INIT;Mutex::Autolock _l(mLock);return activateLocked(ident, handle, enabled);
}status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {bool activateHardware = false;status_t err(NO_ERROR);ssize_t activationIndex = mActivationCount.indexOfKey(handle);if (activationIndex < 0) {ALOGW("Handle %d cannot be found in activation record", handle);return BAD_VALUE;}Info& info(mActivationCount.editValueAt(activationIndex));ALOGD_IF(DEBUG_CONNECTIONS,"SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu", ident,handle, enabled, info.batchParams.size());if (enabled) {ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));if (isClientDisabledLocked(ident)) {ALOGW("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d", ident,handle);return NO_ERROR;}if (info.batchParams.indexOfKey(ident) >= 0) {if (info.numActiveClients() > 0 && !info.isActive) {activateHardware = true;}} else {// Log error. Every activate call should be preceded by a batch() call.ALOGE("\t >>>ERROR: activate called without batch");}} else {ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));// If a connected dynamic sensor is deactivated, remove it from the// dictionary.auto it = mConnectedDynamicSensors.find(handle);if (it != mConnectedDynamicSensors.end()) {mConnectedDynamicSensors.erase(it);}if (info.removeBatchParamsForIdent(ident) >= 0) {if (info.numActiveClients() == 0) {// This is the last connection, we need to de-activate the underlying h/w sensor.activateHardware = true;} else {// Call batch for this sensor with the previously calculated best effort// batch_rate and timeout. One of the apps has unregistered for sensor// events, and the best effort batch parameters might have changed.ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w batch 0x%08x %" PRId64 " %" PRId64,handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);mHalWrapper->batch(handle, info.bestBatchParams.mTSample,info.bestBatchParams.mTBatch);}} else {// sensor wasn't enabled for this ident}if (isClientDisabledLocked(ident)) {return NO_ERROR;}}if (activateHardware) {err = doActivateHardwareLocked(handle, enabled);if (err != NO_ERROR && enabled) {// Failure when enabling the sensor. Clean up on failure.info.removeBatchParamsForIdent(ident);} else {// Update the isActive flag if there is no error. If there is an error when disabling a// sensor, still set the flag to false since the batch parameters have already been// removed. This ensures that everything remains in-sync.info.isActive = enabled;}}return err;
}status_t SensorDevice::doActivateHardwareLocked(int handle, bool enabled) {ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,enabled);status_t err = mHalWrapper->activate(handle, enabled);ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,strerror(-err));return err;
}

11.以上是native层,之后是硬件抽象层(hal)
/hardware/libhardware/modules/sensors/dynamic_sensor/sensors.cpp

int SensorContext::activate(int handle, int enabled) {return mDynamicSensorManager->activate(handle, enabled);
}

12
/hardware/libhardware/modules/sensors/multihal.cpp

static int device__activate(struct sensors_poll_device_t *dev, int handle,int enabled) {sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev;return ctx->activate(handle, enabled);
}

这篇关于Android Sensor调用从上层到底层的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/434269

相关文章

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

python如何调用java的jar包

《python如何调用java的jar包》这篇文章主要为大家详细介绍了python如何调用java的jar包,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录一、安装包二、使用步骤三、代码演示四、自己写一个jar包五、打包步骤六、方法补充一、安装包pip3 install

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

Nacos注册中心和配置中心的底层原理全面解读

《Nacos注册中心和配置中心的底层原理全面解读》:本文主要介绍Nacos注册中心和配置中心的底层原理的全面解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录临时实例和永久实例为什么 Nacos 要将服务实例分为临时实例和永久实例?1.x 版本和2.x版本的区别

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

C/C++和OpenCV实现调用摄像头

《C/C++和OpenCV实现调用摄像头》本文主要介绍了C/C++和OpenCV实现调用摄像头,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录准备工作1. 打开摄像头2. 读取视频帧3. 显示视频帧4. 释放资源5. 获取和设置摄像头属性

使用Python实现调用API获取图片存储到本地的方法

《使用Python实现调用API获取图片存储到本地的方法》开发一个自动化工具,用于从JSON数据源中提取图像ID,通过调用指定API获取未经压缩的原始图像文件,并确保下载结果与Postman等工具直接... 目录使用python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现