android sensor 框架分析---客户端和服务端的连接

4,客户端和服务端的连接

在上一章初始化的过程中论述到, SensorManager.cpp会通过binder机制调用sensor服务的getSensorList方法获取sensor的相关信息。

那数据是通过binder机制调用服务端获取的吗?

其实, java层的SystemSensorManager.java和SensorManager.cpp是对应的;

java层的SensorEventQueue和SensorEventQueue.cpp是对应的;

4.1 连接流程分析

android_hardware_SensorManager.cpp中对应的nativeInitBaseEventQueue为nativeInitSensorEventQueue,主要逻辑如下,

1,调用SensorManager的createEventQueue方法,

SensorManager* mgr = reinterpret_cast(sensorManager);
•••
sp queue(mgr->createEventQueue(clientName, mode));

2,构造Receiver对象,

sp receiver = new Receiver(queue, messageQueue, eventQWeak, scratch);

createEventQueue方法之后的调用流程图如下,

android sensor 框架分析---客户端和服务端的连接_第1张图片

SensorService.cpp的createSensorEventConnection逻辑如下,

1,首先在客户端和服务端之间构造一个连接,

sp result(new SensorEventConnection(this, uid, packageName,
            requestedMode == DATA_INJECTION, opPackageName));

2,将该连接加入到mActiveConnections变量中。

if (mActiveConnections.indexOf(result) < 0) {
            mActiveConnections.add(result);
        }

mActiveConnections中保存着服务端和不同客户端的连接对象。

一个android系统中虽然只有一个服务端,但是可以有很多不同的客户端,客户端以进程的uid和包名区分。

当然,对于同一种sensor,也可以同时有不同的客户端进行连接。

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];
        mSendFd = sockets[1];
    } else {
        mReceiveFd = -errno;
        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
    }
}

由此可见,服务端进程和客户端进程采用管道流的方式进行通信,并且是单向通信。

服务端的端口为mReceiveFd,只进行数据的发送,

客户端的端口为mSendFd,只进行数据的读取。

并且客户端还可以通过getFd方法来获取mSendFd进行读取数据。

4.2 nativeEnableSensor分析

android_hardware_SensorManager.cpp的nativeEnableSensor方法如下,

static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
                               jint maxBatchReportLatency) {
    sp receiver(reinterpret_cast(eventQ));
    return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency, 0);
}

内部类receiver和SensorEventQueue.cpp是在Java层构造SensorEventQueue对象是调用nativeInitBaseEventQueue方法

而在对应的JNI方法中完成初始化的。

调用流程图如下,

android sensor 框架分析---客户端和服务端的连接_第2张图片

SensorEventQueue.cpp的enableSensor方法如下,

status_t SensorEventQueue::enableSensor(int32_t handle, int32_t samplingPeriodUs,
                                        int maxBatchReportLatencyUs, int reservedFlags) const {
    return mSensorEventConnection->enableDisable(handle, true, us2ns(samplingPeriodUs),
                                                 us2ns(maxBatchReportLatencyUs), reservedFlags);
}

mSensorEventConnection就是sensor服务端SensorEventConnection在客户端的一个代理, SensorEventConnection

是SensorService.cpp的内部类。

4.3 Receiver分析

前面2个步骤主要是为了获取sensor数据做准备工作,读取数据主要是android_hardware_SensorManager.cpp的内部类

Receiver继承于LooperCallback,

class Receiver : public LooperCallback {

onFirstRef方法会调用BitTube的getFd方法来获取mSendFd进行读取数据。

mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
                ALOOPER_EVENT_INPUT, this, mSensorQueue.get());

回调handleEvent方法首先会读取服务端写入的sensor数据,

while ((n = q->read(buffer, 16)) > 0) {

然后回调Java层的dispatchSensorEvent方法。

env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchSensorEvent,
        buffer[i].sensor, mScratch, status, buffer[i].timestamp);

你可能感兴趣的:(---【sensor框架分析】)