Sensor系列三 Framework层分析_Client端

一、Sensor的Framework层框架

下图为sensor子系统的框架图,由图可以看出,整个Android Sensor系统主要五部分组成,包括App、framework、HAL、kernel和硬件,本文主要分析sensor framework层,以及与HAL层的数据交互等,hal层的介绍可以参考 Sensor HAL层分析


其中sensor数据的传输,在framework中主要由client和service部分组成,service段复制从HAL层读取数据,并将数据写道管道中,client端读取管道中的数据,反馈给app层,具体框架可以下图描叙:


二、Client端分析

2.1 Client端sensor的注册以及数据监控整体框架

(1)SensorManager类

该类主要封装了Sensor相关的API,提供给APP层使用

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

(2)SystemSensorManager类

该类实现了Sensormanager控制和数据获取的逻辑控制

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

(3)android_hardware_SensorManager.cpp

该文件复制java层和native层通信的JNI实现调用Native层提供的服务

./frameworks/base/core/jni/android_hardware_SensorManager.cpp

(4)SensorManager.cpp

Sensor在Native层的客户端,负责与服务端SensorService通信

frameworks/native/libs/gui/SensorManager.cpp
(5)SensorEventQueue.cpp

消息队列

./frameworks/native/libs/gui/SensorEventQueue.cpp

(6)Bittube

该类为单向字节通道,提供进程间单向数据通信功能,SensorEventConnect是基于Bittube实现的。

frameworks/native/libs/gui/BitTube.cpp

(7)下图可以描叙sensor client的框架图,其中下图可以分为两部分分析,一部分为初始化SystemSensorManager,获取SensorList列表,一部分为sensor数据的传输与监控。


2.2 sensorList获取

(1)系统开机启动时,会创建SystemSensorManager的实例,在改函数的构造函数中,主要完成以下:

a、初始化Sensor列表:调用JNI函数nativeCreate,对sensor模块进行初始化,创建了native层SensorManager的实例;
b、初始化JNI:调用JNI函数nativeClassInit进行初始化;
c、获取Sensor列表:调用JNI函数nativeGetSensorAtIndex获取sensor,并存在mFullSensorList和mHandleToSensor列表中实现注册监听器。

./frameworks/base/core/java/android/hardware/SensorManager.java 
public SystemSensorManager(Context context, Looper mainLooper) {
    mMainLooper = mainLooper;
    mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
    mContext = context;
    mNativeInstance = nativeCreate(context.getOpPackageName());

    synchronized(mLock) {
        if (!sSensorModuleInitialized) {
            sSensorModuleInitialized = true;
            nativeClassInit();//调用JNI函数进行初始化
        }
    }
    // initialize the sensor list
    for (int index = 0;;++index) {//获取sensorList
        Sensor sensor = new Sensor();
        if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
           mFullSensorsList.add(sensor);
           mHandleToSensor.append(sensor.getHandle(), sensor);
        }
}
./frameworks/base/core/jni/android_hardware_SensorManager.cpp 

static jlong nativeCreate(JNIEnv *env, jclass clazz, jstring opPackageName)
{
    ScopedUtfChars opPackageNameUtf(env, opPackageName);
    //创建native层的SensorManager,最终调用SensorManager的assertStateLocked()
    return (jlong) new SensorManager(String16(opPackageNameUtf.c_str()));
}
static void nativeClassInit (JNIEnv *_env, jclass _this)
{
    jclass sensorClass = _env->FindClass("android/hardware/Sensor");
    SensorOffsets& sensorOffsets = gSensorOffsets;
    sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
    sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
    Offsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
    sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
    sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
    sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");
    sensorOffsets.fifoReservedEventCount =
            _env->GetFieldID(sensorClass, "mFifoReservedEventCount",  "I");
    sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount",  "I");
    sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
    sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission","Ljava/lang/String;");
    sensorOffsets.maxDelay    = _env->GetFieldID(sensorClass, "mMaxDelay",  "I");
    sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");
    sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");

}

static jboolean nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
{
    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);

    Sensor const* const* sensorList;
    size_t count = mgr->getSensorList(&sensorList);//调用SensorManager的getSensorList获取sensorlist
    if (size_t(index) >= count) {
        return false;
    }
    Sensor const* const list = sensorList[index];
    const SensorOffsets& sensorOffsets(gSensorOffsets);
    jstring name = getInternedString(env, &list->getName());
    jstring vendor = getInternedString(env, &list->getVendor());
    jstring requiredPermission = getInternedString(env, &list->getRequiredPermission());
    env->SetObjectField(sensor, sensorOffsets.name,      name);
    ......
    env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());
    if (env->CallBooleanMethod(sensor, sensorOffsets.setType, list->getType()) == JNI_FALSE) {
        jstring stringType = getInternedString(env, &list->getStringType());
        env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
    }
    return true;
}
2.3 Sensor数据监控与传输
(1)app层在监控数据辩护时通常存在以下操作:

//获取指定类型的传感器对象  
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 
//注册监听器mSensorManager.registerListener(this, mSensor,SensorManager.SENSOR_DELAY_NORMAL);
// SENSOR_DELAY_GAME  //当sensor数据变化时会调用onSensorChanged获取数据
registerListener会调用sensorManager.java的   
public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs, Handler handler) {       
	int delay = getDelay(samplingPeriodUs);       
	return registerListenerImpl(listener, sensor, delay, handler, 0, 0);   
}
(2)由上面可以看出

registerListener最终会调用SystemSensorManager类的registerListenerImpl方法。
在registerListenerImpl中相应的sensor会被enable,会用注册线程的Looper或系统初始化线程的Looper来
循环等待SensorEvent时间,并读取来自服务端的数据。
接着实例化SensorEventQueue,通过Jni函数nativeBaseEventQueue来创建消息队列,JNI会调用Native的
SensorManager来完成真正的创建消息队列动作。
通过实例化的SensorEventQueue添加需要监听的sensor,并对其使能和设置采样事件等。

    protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
        int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
        synchronized (mSensorListeners) {
            SensorEventQueue queue = mSensorListeners.get(listener);
	    //判断该listener是否被注册过,如果注册过,则存在event queue与之对应
            if (queue == null) {
		//第一次注册,需要创建一个event queue
                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);
		//将该sensor放入queue中
                if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
                    queue.dispose();
                    return false;
                }
		//通知系统,该sensor需要进行监听
                mSensorListeners.put(listener, queue);
                return true;
            } else {
		//已有event queue ,故直接将该sensor放入queue中
                return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
            }
        }
    }
在queue.addsensor中会进行使能sensor的操作:

        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) {//使能sensor,最终会调用native的enale
                // Try continuous mode if batching fails.
                if (maxBatchReportLatencyUs == 0 ||
                    maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
                  removeSensor(sensor, false);
                  return false;
                }
            }
            return true;
        }
2.4 SensorManager类
SensorManager是Sensor在native层的客户端,负责与服务端SensorService通信,在服务端sensor初始化时会调用该类的方法。
./frameworks/native/libs/gui/SensorManager.cpp 

<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mode) {
    sp<SensorEventQueue> queue;

    Mutex::Autolock _l(mLock);
    while (assertStateLocked() == NO_ERROR) {
        sp<ISensorEventConnection> connection =
                mSensorServer->createSensorEventConnection(packageName, mode, mOpPackageName);
        if (connection == NULL) {
            // SensorService just died or the app doesn't have required permissions.
            ALOGE("createEventQueue: connection is NULL.");
            return NULL;
        }
        queue = new SensorEventQueue(connection);//这里是重点,创建了数据操作的queue
        break;
    }
    return queue;
}
SensorManager的CreateEventQueue会调用SensorEVentQueue中的函数,在SensorEVentQueue中会通过调用bitTube接口进行数据的读写操作,下面分析读取数据的流程代码,写数据的过程与读取数据的过程类似。
在读数据前先看看bitTube对象的init方法:

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];//返回读数据管道的套接字fd
        mSendFd = sockets[1];
    } else {
        mReceiveFd = -errno;
        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
    }
}
在这里创建了一对socketpair,分别用于读写操作,下面再看读取数据过程。
ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) {
    if (mAvailable == 0) {
	//调用bitTube的recvObjects读取读管道中的数据存放在mRecBuffer中
        ssize_t err = BitTube::recvObjects(mSensorChannel,
                mRecBuffer, MAX_RECEIVE_BUFFER_EVENT_COUNT);
        if (err < 0) {
            return err;
        }
        mAvailable = static_cast<size_t>(err);
        mConsumed = 0;
    }
    size_t count = min(numEvents, mAvailable);
    memcpy(events, mRecBuffer + mConsumed, count * sizeof(ASensorEvent));
    mAvailable -= count;
    mConsumed += count;
    return static_cast<ssize_t>(count);
}
ssize_t BitTube::read(void* vaddr, size_t size)
{
    ssize_t err, len;
    do {
	//以MSG_DONTWAIT方式从读管道中读取数据
        len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
        err = len < 0 ? errno : 0;
    } while (err == EINTR);//信号中断,没有读取到数据
    if (err == EAGAIN || err == EWOULDBLOCK) {
        // EAGAIN means that we have non-blocking I/O but there was
        // no data to be read. Nothing the client should care about.
        return 0;
    }
    return err == 0 ? len : -err;
}
到这里sensor client端,从注册到数据交互都介绍完毕,下面会分析Sensor service如何与hal层交互的工作流程分析。

作者:frank_zyp
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文无所谓版权,欢迎转载。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
static void sensor_data_task(void *args) { xQueueHandle sensor_queue = (xQueueHandle)args; static D_MsgData msg_data; static D_SensorData sensor_data; static D_SensorData sensor_data1; static D_S16 sensor_value; while(1) { if(xQueueReceive(sensor_queue, &msg_data,( TickType_t ) pdMS_TO_TICKS(1000))) { if (msg_data.msg_type == D_MSG_TYPE_AD_DATA) { d_drv_exit_low_power(); /*get pressure data*/ if (!d_drv_is_low_power()) { d_adc_sample_data(D_ADC_CHANNEL_SENSOR_DATA, &sensor_value); //D_DUMP("[sensor_data_task]: batterry_ad_value = %d", sensor_value); /*battery level check*/ if(sensor_value > D_ADC_BAT_HIPOWER) { sensor_data.battery_level = 100; } else if(sensor_value < D_ADC_BAT_LOPOWER) { sensor_data.battery_level = 0; } else { sensor_data.battery_level = (sensor_value - D_ADC_BAT_LOPOWER)*100/ (D_ADC_BAT_HIPOWER - D_ADC_BAT_LOPOWER); } D_DUMP("[sensor_data_task]: batterry_ad_value = %d, battery_level = %d", sensor_value, sensor_data.battery_level); sensor_data.sensor_type = D_SENSOR_TEMPERATURE; sensor_data.sensor_info.value = d_ds18b20_get_data(); warn_check(D_SENSOR_TEMPERATURE, &sensor_data.sensor_info); //D_DUMP("[sensor_data_task]: temperature_sensor_value = %d", sensor_data.sensor_info.value); sensor_data1.battery_level = sensor_data.battery_level; sensor_data1.sensor_type = D_SENSOR_VALVE; sensor_data1.sensor_info.value = (((D_U8)config_info.valve_controlled_type) << 4) |((D_U8)(10 - config_info.valve_status)); //D_DUMP("[sensor_data_task]: valve_sensor_value = %d", sensor_data1.sensor_info.value); } if (sensor_data_event_user_callback != NULL) { sensor_data_event_user_callback(&sensor_data); nrf_delay_us(1000); sensor_data_event_user_callback(&sensor_data1); } d_drv_enter_low_power(); } } } } 啥意思
07-25
这段代码是一个名为"sensor_data_task"的静态函数,它是一个任务函数。在这个任务中,它通过接收一个队列中的数据来获取传感器数据。首先,它会检查接收到的消息类型是否为AD数据类型。如果是AD数据类型,则会执行一系列操作。 首先,它会退出低功耗模式,然后获取压力传感器的数据值。接着,它会根据获取的AD值来判断电池电量的等级,并将结果保存到sensor_data结构体的battery_level字段中。 然后,它会设置sensor_data结构体的sensor_type字段为D_SENSOR_TEMPERATURE,并调用d_ds18b20_get_data()函数来获取温度传感器的数据值,并将结果保存到sensor_info结构体的value字段中。紧接着,它会调用warn_check()函数来检查温度传感器的数据,并进行相应的处理。 接下来,它会设置sensor_data1结构体的battery_level字段为sensor_data结构体中保存的电池电量值,并设置sensor_data1结构体的sensor_type字段为D_SENSOR_VALVE。然后,它会将阀门控制类型和阀门状态信息保存到sensor_info结构体的value字段中。 接着,它会检查是否注册了sensor_data_event_user_callback回调函数。如果注册了,则会依次调用该回调函数,并将sensor_data和sensor_data1作为参数传入。最后,它会进入低功耗模式。 总体来说,这段代码的功能是获取传感器数据,并通过回调函数将数据传递给其他模块进行处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值