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调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

java如何调用kettle设置变量和参数

《java如何调用kettle设置变量和参数》文章简要介绍了如何在Java中调用Kettle,并重点讨论了变量和参数的区别,以及在Java代码中如何正确设置和使用这些变量,避免覆盖Kettle中已设置... 目录Java调用kettle设置变量和参数java代码中变量会覆盖kettle里面设置的变量总结ja

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动