APP注册SensorEventListener-Android12
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
记录SensorEventListener
与SensorEventQueue
一一对应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相关推荐
- Facebook APP 注册 登录
一.前言 1.说明Facebook App 注册创建流程. 2.使用JavaScript.Java抓取Facebook会员信息. 3.一些常用Facebook常用帮助链接. 二.创建Fa ...
- 【HTML第二个综合案例】----相亲App注册页面
HTML第二个综合案例 第一部分标题: 第二部分表格: 相亲App注册页面:一个用于收集用户的表单(也能起到表格展示数据的作用) 最终效果图---------- 观察可知,该表单包含两部分 上部:标题 ...
- APP注册登录那点事
转载地址:http://www.woshipm.com/pd/206667.html?utm_source=tuicool APP注册登录那点事 2015/09/21 阅读 3.2万 评论 6 收藏 ...
- EOS注册账号小白篇, 使用app注册EOS账号
我前面有关EOS账号相关的文章都相对专业一点,涉及编译,命令执行,都是专业人士才能操作的.但是有些伙伴是刚接触EOS,也希望能够玩玩EOS.今天就和大家分享一下使用App注册EOS账号的流程.最新更新 ...
- 无人机实验平台开发随笔(五)App注册,建立和无人机的连接-1
DJI Developer 详细内容请参见DJI提供的开发者文档,这里讨论在执行过程中的一些细节. APP注册与认证 在上篇随笔中已经谈到最终选择的技术路线,也就是基于DJI MobileSDK进行开 ...
- Django创建应用,app注册,Filed字段类型解析,魔术方法str使用。
这篇博客根据上文Django创建第一个项目- ,从而在项目中跟进创建一个应用,以及app的注册, 模型models中的filed字段类型解析, 魔术方法 str 的使用. 工具: pycharm202 ...
- 云闪付持卡人认证信息失败_云闪付app注册登录常见问答
云闪付app注册登录常见问答 1.如何注册成为云闪付App用户? 持卡人可通过以下方式注册成为云闪付APP用户: (1)通过持卡人服务网站(www.95516.com): (2)通过云闪付App. 通 ...
- APP注册发送验证码
APP注册时用户收到的验证码是该APP采用了第三方短信服务商提供的短信送达服务.各大短信服务商提供SDK和API接口,在APP里集成短信SDK然后调用API即可. 验证码平台聚焦短信服务,产品有国内短 ...
- APP 注册功能,用例怎么写 ?
读者提问:APP 注册功能,用例怎么写 ? 阿常回答:假定该注册为手机号发送验证码的注册方式,注册界面存在 3个输入框(手机号,密码,验证码), 2个按钮(发送验证码,注册),和 1个同意用户协议勾选 ...
最新文章
- 从事JAVA 20年最终却败给了Python,哭了!
- 专栏 | 基于 Jupyter 的特征工程手册:特征选择(四)
- [scala-spark]11. RDD控制操作
- VTK:可视化算法之LOxSeeds
- leetcode110. 平衡二叉树(递归)
- centos6.5 nginx1.8 php mysql,CentOS6.5 源码安装Nginx1.8 + PHP7.0.6 + MySQL5.7.12
- linux变量循环赋值,shell脚本 循环变量赋值cf当前页面
- IOS中的多线程之GCD
- 小米线刷包需要解压么_小米10刷机教程,线刷升级更新官方系统包
- Objective-C 信息传递模型 [ ] 发送消息
- splunk 日志分析软件 简介
- java设计模式之组合设计模式
- qq代理服务器传输文件失败,qq接收文件时显示传输文件失败?
- 清华社英语在线自动教程python版
- Timer Class(计时器类别)
- 计算机主机电池,台式机主板电池没电不换有什么影响?教你更换电脑主板电池的方法...
- 浅谈市场降温后的区块链发展前景
- 【CSP-J】【图论】【最短路】加工零件
- 【linux-centos7重新分配分区】
- 四大亮点不容错过,TDengine 开发者大会全议程公布!