Framework基础:Native层的传感器服务器框架讲解

Framework基础:Native层的传感器服务器框架讲解_第1张图片
陈年.png

最近项目计步器传感器概率性没有值,就顺道研究下传感器框架。今天主要说下native层的框架

native层框架的实现路径
/frameworks/native/services/sensorservice/

文件大概有下面几个


Framework基础:Native层的传感器服务器框架讲解_第2张图片
Paste_Image.png

主入口是main_sensorservice.cpp,主要是把这个远程服务发布出去

int main(int /*argc*/, char** /*argv*/) {
    SensorService::publishAndJoinThreadPool();
    return 0;
}

看看这个SensorService的构造函数,主要是注册了一些sensor的服务,可以看到他获取的设备SensorDevice

Framework基础:Native层的传感器服务器框架讲解_第3张图片
SensorService继承结构.png
void SensorService::onFirstRef()
{
    ALOGD("nuSensorService starting...");
    SensorDevice& dev(SensorDevice::getInstance());

    if (dev.initCheck() == NO_ERROR) {
        sensor_t const* list;
        ssize_t count = dev.getSensorList(&list);  //获取sensor列表
        if (count > 0) {
            ssize_t orientationIndex = -1;
            bool hasGyro = false, hasAccel = false, hasMag = false;
            uint32_t virtualSensorsNeeds =
                    (1< 0) {
                    batchingSupported = true;
                    break;
                }
            }

            if (batchingSupported) {
                // Increase socket buffer size to a max of 100 KB for batching capabilities.
                mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
            } else {
                mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;
            }

            // Compare the socketBufferSize value against the system limits and limit
            // it to maxSystemSocketBufferSize if necessary.
            FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r");
            char line[128];
            if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
                line[sizeof(line) - 1] = '\0';
                size_t maxSystemSocketBufferSize;
                sscanf(line, "%zu", &maxSystemSocketBufferSize);
                if (mSocketBufferSize > maxSystemSocketBufferSize) {
                    mSocketBufferSize = maxSystemSocketBufferSize;
                }
            }
            if (fp) {
                fclose(fp);
            }

            mWakeLockAcquired = false;
            mLooper = new Looper(false);
            const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
            mSensorEventBuffer = new sensors_event_t[minBufferSize];
            mSensorEventScratch = new sensors_event_t[minBufferSize];
            mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
            mCurrentOperatingMode = NORMAL;

            mNextSensorRegIndex = 0;
            for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {
                mLastNSensorRegistrations.push();
            }

            mInitCheck = NO_ERROR;
            mAckReceiver = new SensorEventAckReceiver(this);
            mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
            run("SensorService", PRIORITY_URGENT_DISPLAY);
        }
    }
}

SensorDevice主要构架了hal层的接口和module的接口,hal接口跟硬件相关,而module则更高层一点

SensorDevice::SensorDevice()
    :  mSensorDevice(0),    //hal层接口
       mSensorModule(0)    //module
{
    status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
            (hw_module_t const**)&mSensorModule);

    ALOGE_IF(err, "couldn't load %s module (%s)",
            SENSORS_HARDWARE_MODULE_ID, strerror(-err));

    if (mSensorModule) {
        err = sensors_open_1(&mSensorModule->common, &mSensorDevice);  //打开设备

        ALOGE_IF(err, "couldn't open device for module %s (%s)",
                SENSORS_HARDWARE_MODULE_ID, strerror(-err));

        if (mSensorDevice) {
            if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 ||
                mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) {
                ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3");
            }

            sensor_t const* list;   //sensor list
            ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
            mActivationCount.setCapacity(count);
            Info model;
            for (size_t i=0 ; iactivate(
                        reinterpret_cast(mSensorDevice),
                        list[i].handle, 0);
            }
        }
    }
}

在SensorService的threadLoop来获取传感器数据,使用poll来获取数据

bool SensorService::threadLoop()
{
    ALOGD("nuSensorService thread starting...");

    // each virtual sensor could generate an event per "real" event, that's why we need
    // to size numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.
    // in practice, this is too aggressive, but guaranteed to be enough.
    const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
    const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());

    SensorDevice& device(SensorDevice::getInstance());
    const size_t vcount = mVirtualSensorList.size();

    const int halVersion = device.getHalDeviceVersion();
    do {
        ssize_t count = device.poll(mSensorEventBuffer, numEventMax); 
       //poll获取数据,数据保存到mSensorEventBuffer
        if (count < 0) {
            ALOGE("sensor poll failed (%s)", strerror(-count));
            break;
        }

        // Reset sensors_event_t.flags to zero for all events in the buffer.
        for (int i = 0; i < count; i++) {
             mSensorEventBuffer[i].flags = 0;
        }

        // Make a copy of the connection vector as some connections may be removed during the
        // course of this loop (especially when one-shot sensor events are present in the
        // sensor_event buffer). Promote all connections to StrongPointers before the lock is
        // acquired. If the destructor of the sp gets called when the lock is acquired, it may
        // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for
        // cleanup. So copy all the strongPointers to a vector before the lock is acquired.
        SortedVector< sp > activeConnections;
        populateActiveConnections(&activeConnections);
        Mutex::Autolock _l(mLock);
        // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
        // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
        // sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should
        // not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and
        // releasing the wakelock.
        bool bufferHasWakeUpEvent = false;
        for (int i = 0; i < count; i++) {
            if (isWakeUpSensorEvent(mSensorEventBuffer[i])) {
                bufferHasWakeUpEvent = true;
                break;
            }
        }

        if (bufferHasWakeUpEvent && !mWakeLockAcquired) {
            setWakeLockAcquiredLocked(true);
        }
        recordLastValueLocked(mSensorEventBuffer, count);

        // handle virtual sensors
        if (count && vcount) {
            sensors_event_t const * const event = mSensorEventBuffer;
            const size_t activeVirtualSensorCount = mActiveVirtualSensors.size();
            if (activeVirtualSensorCount) {
                size_t k = 0;
                SensorFusion& fusion(SensorFusion::getInstance());
                if (fusion.isEnabled()) {
                    for (size_t i=0 ; i= minBufferSize) {
                            ALOGE("buffer too small to hold all events: "
                                    "count=%zd, k=%zu, size=%zu",
                                    count, k, minBufferSize);
                            break;
                        }
                        sensors_event_t out;
                        SensorInterface* si = mActiveVirtualSensors.valueAt(j);
                        if (si->process(&out, event[i])) {
                            mSensorEventBuffer[count + k] = out;
                            k++;
                        }
                    }
                }
                if (k) {
                    // record the last synthesized values
                    recordLastValueLocked(&mSensorEventBuffer[count], k);
                    count += k;
                    // sort the buffer by time-stamps
                    sortEventBuffer(mSensorEventBuffer, count);
                }
            }
        }

        // handle backward compatibility for RotationVector sensor
        if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {
            for (int i = 0; i < count; i++) {
                if (mSensorEventBuffer[i].type == SENSOR_TYPE_ROTATION_VECTOR) {
                    // All the 4 components of the quaternion should be available
                    // No heading accuracy. Set it to -1
                    mSensorEventBuffer[i].data[4] = -1;
                }
            }
        }

        // Map flush_complete_events in the buffer to SensorEventConnections which called
        // flush on the hardware sensor. mapFlushEventsToConnections[i] will be the
        // SensorEventConnection mapped to the corresponding flush_complete_event in
        // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
        for (int i = 0; i < count; ++i) {
            mMapFlushEventsToConnections[i] = NULL;
            if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
                const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
                SensorRecord* rec = mActiveSensors.valueFor(sensor_handle);
                if (rec != NULL) {
                    mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection();
                    rec->removeFirstPendingFlushConnection();
                }
            }
        }

        // Send our events to clients. Check the state of wake lock for each client and release the
        // lock if none of the clients need it.
        bool needsWakeLock = false;
        size_t numConnections = activeConnections.size();
        for (size_t i=0 ; i < numConnections; ++i) {
            if (activeConnections[i] != 0) {
                //通过activeConnections发送传感器事件
                activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
                        mMapFlushEventsToConnections);
                needsWakeLock |= activeConnections[i]->needsWakeLock();
                // If the connection has one-shot sensors, it may be cleaned up after first trigger.
                // Early check for one-shot sensors.
                if (activeConnections[i]->hasOneShotSensors()) {
                    cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,
                            count);
                }
            }
        }

        if (mWakeLockAcquired && !needsWakeLock) {
            setWakeLockAcquiredLocked(false);
        }
    } while (!Thread::exitPending());

    ALOGW("Exiting SensorService::threadLoop => aborting...");
    abort();
    return false;
}

说下几个关键的数据结构
/hardware/libhardware/include/hardware/
sensor_t 用来保存sensor的结构。常用来做指针,指向一个sensor list。

struct sensor_t {

    /* Name of this sensor.
     * All sensors of the same "type" must have a different "name".
     */
    const char*     name;            //传感器名字

    /* vendor of the hardware part */
    const char*     vendor;            //定制商

    /* version of the hardware part + driver. The value of this field
     * must increase when the driver is updated in a way that changes the
     * output of this sensor. This is important for fused sensors when the
     * fusion algorithm is updated.
     */
    int             version;

    /* handle that identifies this sensors. This handle is used to reference
     * this sensor throughout the HAL API.
     */
    int             handle;          //用于区分sensor

    /* this sensor's type. */
    int             type;                //类型

    /* maximum range of this sensor's value in SI units */
    float           maxRange;            //最大范围

    /* smallest difference between two values reported by this sensor */
    float           resolution;               //最小取分值

    /* rough estimate of this sensor's power consumption in mA */
    float           power;                //耗电

    /* this value depends on the reporting mode:
     *
     *   continuous: minimum sample period allowed in microseconds
     *   on-change : 0
     *   one-shot  :-1
     *   special   : 0, unless otherwise noted
     */
    int32_t         minDelay;

    /* number of events reserved for this sensor in the batch mode FIFO.
     * If there is a dedicated FIFO for this sensor, then this is the
     * size of this FIFO. If the FIFO is shared with other sensors,
     * this is the size reserved for that sensor and it can be zero.
     */
    uint32_t        fifoReservedEventCount;

    /* maximum number of events of this sensor that could be batched.
     * This is especially relevant when the FIFO is shared between
     * several sensors; this value is then set to the size of that FIFO.
     */
    uint32_t        fifoMaxEventCount;

    /* type of this sensor as a string. Set to corresponding
     * SENSOR_STRING_TYPE_*.
     * When defining an OEM specific sensor or sensor manufacturer specific
     * sensor, use your reserve domain name as a prefix.
     * ex: com.google.glass.onheaddetector
     * For sensors of known type, the android framework might overwrite this
     * string automatically.
     */
    const char*    stringType;  //类型

    /* permission required to see this sensor, register to it and receive data.
     * Set to "" if no permission is required. Some sensor types like the
     * heart rate monitor have a mandatory require_permission.
     * For sensors that always require a specific permission, like the heart
     * rate monitor, the android framework might overwrite this string
     * automatically.
     */
    const char*    requiredPermission;  //权限

    /* This value is defined only for continuous mode and on-change sensors. It is the delay between
     * two sensor events corresponding to the lowest frequency that this sensor supports. When lower
     * frequencies are requested through batch()/setDelay() the events will be generated at this
     * frequency instead. It can be used by the framework or applications to estimate when the batch
     * FIFO may be full.
     *
     * NOTE: 1) period_ns is in nanoseconds where as maxDelay/minDelay are in microseconds.
     *              continuous, on-change: maximum sampling period allowed in microseconds.
     *              one-shot, special : 0
     *   2) maxDelay should always fit within a 32 bit signed integer. It is declared as 64 bit
     *      on 64 bit architectures only for binary compatibility reasons.
     * Availability: SENSORS_DEVICE_API_VERSION_1_3
     */
    #ifdef __LP64__
       int64_t maxDelay;
    #else
       int32_t maxDelay;       //最大延迟
    #endif

    /* Flags for sensor. See SENSOR_FLAG_* above. Only the least significant 32 bits are used here.
     * It is declared as 64 bit on 64 bit architectures only for binary compatibility reasons.
     * Availability: SENSORS_DEVICE_API_VERSION_1_3
     */
    #ifdef __LP64__
       uint64_t flags;
    #else
       uint32_t flags;
    #endif

    /* reserved fields, must be zero */
    void*           reserved[2];
};

对应的sensor 类是,封装了获取结构体数据的方法
/frameworks/native/libs/gui/Sensor.cpp

Framework基础:Native层的传感器服务器框架讲解_第4张图片
sensor

sensor的注册接口HardwareSensor,注册是生成了一个list结构mSensorList和一个map结构mSensorMap,mSensorList用于保存所有Sensor,mSensorMap保存handle到HardwareSensor的映射表。

Sensor SensorService::registerSensor(SensorInterface* s)
{
    sensors_event_t event;
    memset(&event, 0, sizeof(event));

    const Sensor sensor(s->getSensor());
    // add to the sensor list (returned to clients)
    mSensorList.add(sensor);
    // add to our handle->SensorInterface mapping
    mSensorMap.add(sensor.getHandle(), s);
    // create an entry in the mLastEventSeen array
    mLastEventSeen.add(sensor.getHandle(), NULL);

    return sensor;
}

class HardwareSensor : public SensorInterface
{
    SensorDevice& mSensorDevice;
    Sensor mSensor;

public:
    HardwareSensor(const sensor_t& sensor);

    virtual ~HardwareSensor();

    virtual bool process(sensors_event_t* outEvent,
            const sensors_event_t& event);

    virtual status_t activate(void* ident, bool enabled);
    virtual status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
                           int64_t maxBatchReportLatencyNs);
    virtual status_t setDelay(void* ident, int handle, int64_t ns);
    virtual status_t flush(void* ident, int handle);
    virtual Sensor getSensor() const;
    virtual bool isVirtual() const { return false; }
    virtual void autoDisable(void *ident, int handle);
};

还有一个比较重要的是SensorEventConnection,他的函数sendEvents用来发送sensor数据给framework层

    class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
        friend class SensorService;
        virtual ~SensorEventConnection();
        virtual void onFirstRef();
        virtual sp getSensorChannel() const;
        virtual status_t enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs,
                                       nsecs_t maxBatchReportLatencyNs, int reservedFlags);
        virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
        virtual status_t flush();
        // Count the number of flush complete events which are about to be dropped in the buffer.
        // Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be
        // sent separately before the next batch of events.
        void countFlushCompleteEventsLocked(sensors_event_t const* scratch, int numEventsDropped);

        // Check if there are any wake up events in the buffer. If yes, return the index of the
        // first wake_up sensor event in the buffer else return -1. This wake_up sensor event will
        // have the flag WAKE_UP_SENSOR_EVENT_NEEDS_ACK set. Exactly one event per packet will have
        // the wake_up flag set. SOCK_SEQPACKET ensures that either the entire packet is read or
        // dropped.
        int findWakeUpSensorEventLocked(sensors_event_t const* scratch, int count);

        // Send pending flush_complete events. There may have been flush_complete_events that are
        // dropped which need to be sent separately before other events. On older HALs (1_0) this
        // method emulates the behavior of flush().
        void sendPendingFlushEventsLocked();

        // Writes events from mEventCache to the socket.
        void writeToSocketFromCache();

        // Compute the approximate cache size from the FIFO sizes of various sensors registered for
        // this connection. Wake up and non-wake up sensors have separate FIFOs but FIFO may be
        // shared amongst wake-up sensors and non-wake up sensors.
        int computeMaxCacheSizeLocked() const;

        // When more sensors register, the maximum cache size desired may change. Compute max cache
        // size, reallocate memory and copy over events from the older cache.
        void reAllocateCacheLocked(sensors_event_t const* scratch, int count);

        // LooperCallback method. If there is data to read on this fd, it is an ack from the
        // app that it has read events from a wake up sensor, decrement mWakeLockRefCount.
        // If this fd is available for writing send the data from the cache.
        virtual int handleEvent(int fd, int events, void* data);

        // Increment mPendingFlushEventsToSend for the given sensor handle.
        void incrementPendingFlushCount(int32_t handle);

        // Add or remove the file descriptor associated with the BitTube to the looper. If mDead is
        // set to true or there are no more sensors for this connection, the file descriptor is
        // removed if it has been previously added to the Looper. Depending on the state of the
        // connection FD may be added to the Looper. The flags to set are determined by the internal
        // state of the connection. FDs are added to the looper when wake-up sensors are registered
        // (to poll for acknowledgements) and when write fails on the socket when there are too many
        // error and the other end hangs up or when this client unregisters for this connection.
        void updateLooperRegistration(const sp& looper);
        void updateLooperRegistrationLocked(const sp& looper);

        sp const mService;
        sp mChannel;
        uid_t mUid;
        mutable Mutex mConnectionLock;
        // Number of events from wake up sensors which are still pending and haven't been delivered
        // to the corresponding application. It is incremented by one unit for each write to the
        // socket.
        uint32_t mWakeLockRefCount;

        // If this flag is set to true, it means that the file descriptor associated with the
        // BitTube has been added to the Looper in SensorService. This flag is typically set when
        // this connection has wake-up sensors associated with it or when write has failed on this
        // connection and we're storing some events in the cache.
        bool mHasLooperCallbacks;
        // If there are any errors associated with the Looper this flag is set to true and
        // mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if
        // this flag is set.
        bool mDead;

        bool mDataInjectionMode;
        struct FlushInfo {
            // The number of flush complete events dropped for this sensor is stored here.
            // They are sent separately before the next batch of events.
            int mPendingFlushEventsToSend;
            // Every activate is preceded by a flush. Only after the first flush complete is
            // received, the events for the sensor are sent on that *connection*.
            bool mFirstFlushPending;
            FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
        };
        // protected by SensorService::mLock. Key for this vector is the sensor handle.
        KeyedVector mSensorInfo;
        sensors_event_t *mEventCache;
        int mCacheSize, mMaxCacheSize;
        String8 mPackageName;
        const String16 mOpPackageName;
#if DEBUG_CONNECTIONS
        int mEventsReceived, mEventsSent, mEventsSentFromCache;
        int mTotalAcksNeeded, mTotalAcksReceived;
#endif

    public:
        SensorEventConnection(const sp& service, uid_t uid, String8 packageName,
                 bool isDataInjectionMode, const String16& opPackageName);

        status_t sendEvents(sensors_event_t const* buffer, size_t count,
                sensors_event_t* scratch,
                SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
        bool hasSensor(int32_t handle) const;
        bool hasAnySensor() const;
        bool hasOneShotSensors() const;
        bool addSensor(int32_t handle);
        bool removeSensor(int32_t handle);
        void setFirstFlushPending(int32_t handle, bool value);
        void dump(String8& result);
        bool needsWakeLock();
        void resetWakeLockRefCount();
        String8 getPackageName() const;

        uid_t getUid() const { return mUid; }
    };

参考:
深入浅出 - Android系统移植与平台开发(十四) - Sensor HAL框架分析之四
SensorService启动分析

你可能感兴趣的:(Framework基础:Native层的传感器服务器框架讲解)