Framework基礎:Native層的傳感器服務器框架講解

陳年.png

最近項目計步器傳感器概率性沒有值捎泻,就順道研究下傳感器框架厌丑。今天主要說下native層的框架

native層框架的實現(xiàn)路徑
/frameworks/native/services/sensorservice/

文件大概有下面幾個


Paste_Image.png

主入口是main_sensorservice.cpp,主要是把這個遠程服務發(fā)布出去

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

看看這個SensorService的構(gòu)造函數(shù),主要是注冊了一些sensor的服務耕驰,可以看到他獲取的設備SensorDevice

SensorService繼承結(jié)構(gòu).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<<SENSOR_TYPE_GRAVITY) |
                    (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
                    (1<<SENSOR_TYPE_ROTATION_VECTOR);

            mLastEventSeen.setCapacity(count);
            for (ssize_t i=0 ; i<count ; i++) {
                registerSensor( new HardwareSensor(list[i]) ); //注冊sensor
                switch (list[i].type) {
                    case SENSOR_TYPE_ACCELEROMETER:
                        hasAccel = true;
                        break;
                    case SENSOR_TYPE_MAGNETIC_FIELD:
                        hasMag = true;
                        break;
                    case SENSOR_TYPE_ORIENTATION:
                        orientationIndex = i;
                        break;
                    case SENSOR_TYPE_GYROSCOPE:
                    case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
                        hasGyro = true;
                        break;
                    case SENSOR_TYPE_GRAVITY:
                    case SENSOR_TYPE_LINEAR_ACCELERATION:
                    case SENSOR_TYPE_ROTATION_VECTOR:
                        virtualSensorsNeeds &= ~(1<<list[i].type);
                        break;
                }
            }

            // it's safe to instantiate the SensorFusion object here
            // (it wants to be instantiated after h/w sensors have been
            // registered)
            const SensorFusion& fusion(SensorFusion::getInstance());

            // build the sensor list returned to users
            mUserSensorList = mSensorList;  //用戶空間sensor list

            if (hasGyro && hasAccel && hasMag) {
                Sensor aSensor;

                // Add Android virtual sensors if they're not already
                // available in the HAL

                aSensor = registerVirtualSensor( new RotationVectorSensor() );
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
                    mUserSensorList.add(aSensor);
                }

                aSensor = registerVirtualSensor( new GravitySensor(list, count) );
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
                    mUserSensorList.add(aSensor);
                }
                 //注冊虛擬傳感器
                aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
                    mUserSensorList.add(aSensor);
                }

                aSensor = registerVirtualSensor( new OrientationSensor() );
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
                    // if we are doing our own rotation-vector, also add
                    // the orientation sensor and remove the HAL provided one.
                    mUserSensorList.replaceAt(aSensor, orientationIndex);
                }

                // virtual debugging sensors are not added to mUserSensorList
                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
                registerVirtualSensor( new GyroDriftSensor() );
            }

            // debugging sensor list
            mUserSensorListDebug = mSensorList;

            // Check if the device really supports batching by looking at the FIFO event
            // counts for each sensor.
            bool batchingSupported = false;
            for (size_t i = 0; i < mSensorList.size(); ++i) {
                if (mSensorList[i].getFifoMaxEventCount() > 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主要構(gòu)架了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 ; i<size_t(count) ; i++) {
                mActivationCount.add(list[i].handle, model);
                mSensorDevice->activate(
                        reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
                        list[i].handle, 0);
            }
        }
    }
}

在SensorService的threadLoop來獲取傳感器數(shù)據(jù)球订,使用poll來獲取數(shù)據(jù)

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獲取數(shù)據(jù),數(shù)據(jù)保存到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<SensorEventConnection> > 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<size_t(count) ; i++) {
                        fusion.process(event[i]);
                    }
                }
                for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
                    for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
                        if (count + k >= 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發(fā)送傳感器事件
                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;
}

說下幾個關鍵的數(shù)據(jù)結(jié)構(gòu)
/hardware/libhardware/include/hardware/
sensor_t 用來保存sensor的結(jié)構(gòu)。常用來做指針,指向一個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;          //用于區(qū)分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;  //權(quán)限

    /* 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 類是署驻,封裝了獲取結(jié)構(gòu)體數(shù)據(jù)的方法
/frameworks/native/libs/gui/Sensor.cpp

sensor

sensor的注冊接口HardwareSensor,注冊是生成了一個list結(jié)構(gòu)mSensorList和一個map結(jié)構(gòu)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,他的函數(shù)sendEvents用來發(fā)送sensor數(shù)據(jù)給framework層

    class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
        friend class SensorService;
        virtual ~SensorEventConnection();
        virtual void onFirstRef();
        virtual sp<BitTube> 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>& looper);
        void updateLooperRegistrationLocked(const sp<Looper>& looper);

        sp<SensorService> const mService;
        sp<BitTube> 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<int, FlushInfo> 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<SensorService>& 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系統(tǒng)移植與平臺開發(fā)(十四) - Sensor HAL框架分析之四
SensorService啟動分析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奥帘,一起剝皮案震驚了整個濱河市松蒜,隨后出現(xiàn)的幾起案子运褪,更是在濱河造成了極大的恐慌檀咙,老刑警劉巖劣欢,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡膳算,警方通過查閱死者的電腦和手機华匾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門旭旭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娱俺,“玉大人模庐,你說我怎么就攤上這事°擦耍” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵违寿,是天一觀的道長。 經(jīng)常有香客問我熟空,道長藤巢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任息罗,我火速辦了婚禮掂咒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己绍刮,他們只是感情好温圆,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著孩革,像睡著了一般岁歉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上膝蜈,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天锅移,我揣著相機與錄音,去河邊找鬼饱搏。 笑死非剃,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的推沸。 我是一名探鬼主播备绽,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鬓催!你這毒婦竟也來了肺素?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤深浮,失蹤者是張志新(化名)和其女友劉穎压怠,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體飞苇,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡菌瘫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了布卡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雨让。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖忿等,靈堂內(nèi)的尸體忽然破棺而出栖忠,到底是詐尸還是另有隱情,我是刑警寧澤贸街,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布庵寞,位于F島的核電站,受9級特大地震影響薛匪,放射性物質(zhì)發(fā)生泄漏捐川。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一逸尖、第九天 我趴在偏房一處隱蔽的房頂上張望古沥。 院中可真熱鬧瘸右,春花似錦、人聲如沸岩齿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盹沈。三九已至龄章,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間襟诸,已是汗流浹背瓦堵。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留歌亲,地道東北人菇用。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像陷揪,于是被迫代替她去往敵國和親惋鸥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容