APP注册SensorEventListener-Android12

android12-release


1. APP获取SensorService和传感器Sensor


可查看APP获取Sensor对象-Android12

2. 注册SensorEventListener监听

  • this 继承 SensorEventListener
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
  • listener == null || sensor == null 判断传入参数是否为null
  • mSensorListeners.size() >= MAX_LISTENER_COUNT注册监听限制MAX_LISTENER_COUNT = 128
  • mSensorListeners记录SensorEventListenerSensorEventQueue一一对应mSensorListeners.put(listener, queue)
  • new SensorEventQueue初始化连接Native层SensorEventQueue、SensorEventConnection
  • queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)并激活enableSensor()

frameworks/base/core/java/android/hardware/SystemSensorManager.java

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

2.1 JNI调用及初始化SensorEventQueue、SensorEventConnection

  • queue(mgr->createEventQueue(clientName, mode, attributionTagName))先binder调用mSensorServer->createSensorEventConnection()创建SensorEventConnection,在new SensorEventQueue(connection)
  • new Receiver()实例化后onFirstRef()mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), ... )Handler\Looper 添加mReceiveFd = sockets[0](SensorEventConnection基于BitTube.cpp实现socket)监听,LooperCallback 回调 handleEvent() 方法

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) {// ... ...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());
}class Receiver : public LooperCallback {// ... ...
public:Receiver(const sp<SensorEventQueue>& sensorQueue,const sp<MessageQueue>& messageQueue,jobject receiverWeak) {JNIEnv* env = AndroidRuntime::getJNIEnv();mSensorQueue = sensorQueue;mMessageQueue = messageQueue;mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));}// ... ...
private:virtual void onFirstRef() {LooperCallback::onFirstRef();mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,ALOOPER_EVENT_INPUT, this, mSensorQueue.get());}virtual int handleEvent(int fd, int events, void* data) {// ... ...}
};

frameworks/native/libs/sensor/SensorManager.cpp
frameworks/native/services/sensorservice/SensorService.cpp
frameworks/native/services/sensorservice/SensorEventConnection.cpp
frameworks/native/libs/sensor/BitTube.cpp
frameworks/native/libs/sensor/SensorEventQueue.cpp

void BitTube::init(size_t rcvbuf, size_t sndbuf) {int sockets[2];if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {size_t size = DEFAULT_SOCKET_BUFFER_SIZE;setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));// sine we don't use the "return channel", we keep it small...setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));fcntl(sockets[0], F_SETFL, O_NONBLOCK);fcntl(sockets[1], F_SETFL, O_NONBLOCK);mReceiveFd = sockets[0];mSendFd = sockets[1];} else {mReceiveFd = -errno;ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));}
}

2.2 mSendFd 在SensorService.cpp中初始化SensorEventConnectio时添加监听

  • looper->addFd(mChannel->getSendFd(), ...)

frameworks/native/services/sensorservice/SensorService.cpp

sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName,int requestedMode, const String16& opPackageName, const String16& attributionTag) {// ... ...sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,requestedMode == DATA_INJECTION, connOpPackageName, attributionTag));if (requestedMode == DATA_INJECTION) {mConnectionHolder.addEventConnectionIfNotPresent(result);// Add the associated file descriptor to the Looper for polling whenever there is data to// be injected.result->updateLooperRegistration(mLooper);}return result;
}

frameworks/native/services/sensorservice/SensorEventConnection.cpp

void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Looper>& looper) {Mutex::Autolock _l(mConnectionLock);updateLooperRegistrationLocked(looper);
}void SensorService::SensorEventConnection::updateLooperRegistrationLocked(const sp<Looper>& looper) {// ... ...// Add the file descriptor to the Looper for receiving acknowledegments if the app has// registered for wake-up sensors OR for sending events in the cache.int ret = looper->addFd(mChannel->getSendFd(), 0, looper_flags, this, nullptr);// ... ...
}

2.3 enableSensor()激活Sensor最终调用SensorService::enable

  • connection->sendEvents(&event, 1, nullptr) 此传感器已激活,如果请求的传感器不是“连续”传感器,则立即向下发送该传感器的最后一个已知值。
  • sensor->batch()sensor->flush()sensor->activate() 对应Sensor器件激活
  • connection->updateLooperRegistration(mLooper) 更新监听mSendFd

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) {// ... ...sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);// ... ...SensorRecord* rec = mActiveSensors.valueFor(handle);if (rec == nullptr) {rec = new SensorRecord(connection);mActiveSensors.add(handle, rec);// ... ...} 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);}}}}}}}// ... ...status_t err = sensor->batch(connection.get(), handle, 0, samplingPeriodNs,maxBatchReportLatencyNs);// ... ...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 (err != NO_ERROR) {// batch/activate has failed, reset our state.cleanupWithoutDisableLocked(connection, handle);}return err;
}

3. Receiver监听socket传递Sensor数据

  • 监听socket回调handleEvent
  • env->CallVoidMethod() JNI调用SystemSensorManager.java中SensorEventQueue对象的dispatchSensorEvent方法
class Receiver : public LooperCallback {// ... ...
private:virtual void onFirstRef() {LooperCallback::onFirstRef();mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,ALOOPER_EVENT_INPUT, this, mSensorQueue.get());}virtual int handleEvent(int fd, int events, void* data) {// ... ...if (receiverObj.get()) {env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchSensorEvent,buffer[i].sensor,mFloatScratch,status,buffer[i].timestamp);}// ... ...}
};

查看SensorService数据传递给APP-Android12

时序图

APP注册SensorEventListener-Android12相关推荐

  1. Facebook APP 注册 登录

    一.前言        1.说明Facebook App 注册创建流程. 2.使用JavaScript.Java抓取Facebook会员信息. 3.一些常用Facebook常用帮助链接. 二.创建Fa ...

  2. 【HTML第二个综合案例】----相亲App注册页面

    HTML第二个综合案例 第一部分标题: 第二部分表格: 相亲App注册页面:一个用于收集用户的表单(也能起到表格展示数据的作用) 最终效果图---------- 观察可知,该表单包含两部分 上部:标题 ...

  3. APP注册登录那点事

    转载地址:http://www.woshipm.com/pd/206667.html?utm_source=tuicool APP注册登录那点事 2015/09/21 阅读 3.2万  评论 6 收藏 ...

  4. EOS注册账号小白篇, 使用app注册EOS账号

    我前面有关EOS账号相关的文章都相对专业一点,涉及编译,命令执行,都是专业人士才能操作的.但是有些伙伴是刚接触EOS,也希望能够玩玩EOS.今天就和大家分享一下使用App注册EOS账号的流程.最新更新 ...

  5. 无人机实验平台开发随笔(五)App注册,建立和无人机的连接-1

    DJI Developer 详细内容请参见DJI提供的开发者文档,这里讨论在执行过程中的一些细节. APP注册与认证 在上篇随笔中已经谈到最终选择的技术路线,也就是基于DJI MobileSDK进行开 ...

  6. Django创建应用,app注册,Filed字段类型解析,魔术方法str使用。

    这篇博客根据上文Django创建第一个项目- ,从而在项目中跟进创建一个应用,以及app的注册, 模型models中的filed字段类型解析, 魔术方法 str 的使用. 工具: pycharm202 ...

  7. 云闪付持卡人认证信息失败_云闪付app注册登录常见问答

    云闪付app注册登录常见问答 1.如何注册成为云闪付App用户? 持卡人可通过以下方式注册成为云闪付APP用户: (1)通过持卡人服务网站(www.95516.com): (2)通过云闪付App. 通 ...

  8. APP注册发送验证码

    APP注册时用户收到的验证码是该APP采用了第三方短信服务商提供的短信送达服务.各大短信服务商提供SDK和API接口,在APP里集成短信SDK然后调用API即可. 验证码平台聚焦短信服务,产品有国内短 ...

  9. APP 注册功能,用例怎么写 ?

    读者提问:APP 注册功能,用例怎么写 ? 阿常回答:假定该注册为手机号发送验证码的注册方式,注册界面存在 3个输入框(手机号,密码,验证码), 2个按钮(发送验证码,注册),和 1个同意用户协议勾选 ...

最新文章

  1. 从事JAVA 20年最终却败给了Python,哭了!
  2. 专栏 | 基于 Jupyter 的特征工程手册:特征选择(四)
  3. [scala-spark]11. RDD控制操作
  4. VTK:可视化算法之LOxSeeds
  5. leetcode110. 平衡二叉树(递归)
  6. centos6.5 nginx1.8 php mysql,CentOS6.5 源码安装Nginx1.8 + PHP7.0.6 + MySQL5.7.12
  7. linux变量循环赋值,shell脚本 循环变量赋值cf当前页面
  8. IOS中的多线程之GCD
  9. 小米线刷包需要解压么_小米10刷机教程,线刷升级更新官方系统包
  10. Objective-C 信息传递模型 [ ] 发送消息
  11. splunk 日志分析软件 简介
  12. java设计模式之组合设计模式
  13. qq代理服务器传输文件失败,qq接收文件时显示传输文件失败?
  14. 清华社英语在线自动教程python版
  15. Timer Class(计时器类别)
  16. 计算机主机电池,台式机主板电池没电不换有什么影响?教你更换电脑主板电池的方法...
  17. 浅谈市场降温后的区块链发展前景
  18. 【CSP-J】【图论】【最短路】加工零件
  19. 【linux-centos7重新分配分区】
  20. 四大亮点不容错过,TDengine 开发者大会全议程公布!

热门文章

  1. UG模具设计之后模滑块成型
  2. 哪些软件是python编写出来的_用Python编程需要什么软件?
  3. excel爬虫相关学习1:简单的excel爬虫
  4. 【前端学习】React学习资料
  5. CAD进入选择状态前后对话框隐藏与显示(对话框发消息)
  6. Bing.com专题
  7. CSS科技感四角边框
  8. 关于新劳动法-违约金试用期
  9. Linux用户管理及权限设置
  10. linux alsa pcm,Linux中用ALSA驱动声卡流程详解(转)