OSDN Git Service

Add a timeout for releasing SensorService wake_lock.
authorAravind Akella <aakella@google.com>
Thu, 30 Oct 2014 00:55:20 +0000 (17:55 -0700)
committerAravind Akella <aakella@google.com>
Sun, 2 Nov 2014 01:19:25 +0000 (18:19 -0700)
 If SensorService is holding a wake_lock and there are no acknowledgements
 from ANY app within 5 seconds, release the wake_lock and reset the wake_lock
 refcounts for all connections.

Bug: 16874240
Change-Id: I5e950dd393c20173c439cbd5a4ba614ee09d61f4

services/sensorservice/SensorService.cpp
services/sensorservice/SensorService.h

index dc8fa64..c316ef6 100644 (file)
@@ -191,6 +191,8 @@ void SensorService::onFirstRef()
             mSensorEventScratch = new sensors_event_t[minBufferSize];
             mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
 
+            mAckReceiver = new SensorEventAckReceiver(this);
+            mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
             mInitCheck = NO_ERROR;
             run("SensorService", PRIORITY_URGENT_DISPLAY);
         }
@@ -386,8 +388,6 @@ bool SensorService::threadLoop()
     SensorDevice& device(SensorDevice::getInstance());
     const size_t vcount = mVirtualSensorList.size();
 
-    SensorEventAckReceiver sender(this);
-    sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
     const int halVersion = device.getHalDeviceVersion();
     do {
         ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
@@ -408,16 +408,7 @@ bool SensorService::threadLoop()
         // 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;
-        {
-            Mutex::Autolock _l(mLock);
-            for (size_t i=0 ; i < mActiveConnections.size(); ++i) {
-                sp<SensorEventConnection> connection(mActiveConnections[i].promote());
-                if (connection != 0) {
-                    activeConnections.add(connection);
-                }
-            }
-        }
-
+        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,
@@ -433,8 +424,7 @@ bool SensorService::threadLoop()
         }
 
         if (bufferHasWakeUpEvent && !mWakeLockAcquired) {
-            acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
-            mWakeLockAcquired = true;
+            setWakeLockAcquiredLocked(true);
         }
         recordLastValueLocked(mSensorEventBuffer, count);
 
@@ -522,8 +512,7 @@ bool SensorService::threadLoop()
         }
 
         if (mWakeLockAcquired && !needsWakeLock) {
-            release_wake_lock(WAKE_LOCK_NAME);
-            mWakeLockAcquired = false;
+            setWakeLockAcquiredLocked(false);
         }
     } while (!Thread::exitPending());
 
@@ -536,11 +525,52 @@ sp<Looper> SensorService::getLooper() const {
     return mLooper;
 }
 
+void SensorService::resetAllWakeLockRefCounts() {
+    SortedVector< sp<SensorEventConnection> > activeConnections;
+    populateActiveConnections(&activeConnections);
+    {
+        Mutex::Autolock _l(mLock);
+        for (size_t i=0 ; i < activeConnections.size(); ++i) {
+            if (activeConnections[i] != 0) {
+                activeConnections[i]->resetWakeLockRefCount();
+            }
+        }
+        setWakeLockAcquiredLocked(false);
+    }
+}
+
+void SensorService::setWakeLockAcquiredLocked(bool acquire) {
+    if (acquire) {
+        if (!mWakeLockAcquired) {
+            acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
+            mWakeLockAcquired = true;
+        }
+        mLooper->wake();
+    } else {
+        if (mWakeLockAcquired) {
+            release_wake_lock(WAKE_LOCK_NAME);
+            mWakeLockAcquired = false;
+        }
+    }
+}
+
+
+bool SensorService::isWakeLockAcquired() {
+    Mutex::Autolock _l(mLock);
+    return mWakeLockAcquired;
+}
+
 bool SensorService::SensorEventAckReceiver::threadLoop() {
     ALOGD("new thread SensorEventAckReceiver");
+    sp<Looper> looper = mService->getLooper();
     do {
-        sp<Looper> looper = mService->getLooper();
-        looper->pollOnce(-1);
+        bool wakeLockAcquired = mService->isWakeLockAcquired();
+        int timeout = -1;
+        if (wakeLockAcquired) timeout = 5000;
+        int ret = looper->pollOnce(timeout);
+        if (ret == ALOOPER_POLL_TIMEOUT) {
+           mService->resetAllWakeLockRefCounts();
+        }
     } while(!Thread::exitPending());
     return false;
 }
@@ -714,10 +744,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
                 sensors_event_t& event(mLastEventSeen.editValueFor(handle));
                 if (event.version == sizeof(sensors_event_t)) {
                     if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
-                        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
-                        mWakeLockAcquired = true;
-                        ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock for on_change sensor %s",
-                                                        WAKE_LOCK_NAME);
+                        setWakeLockAcquiredLocked(true);
                     }
                     connection->sendEvents(&event, 1, NULL);
                     if (!connection->needsWakeLock() && mWakeLockAcquired) {
@@ -922,8 +949,26 @@ void SensorService::checkWakeLockStateLocked() {
         }
     }
     if (releaseLock) {
-        release_wake_lock(WAKE_LOCK_NAME);
-        mWakeLockAcquired = false;
+        setWakeLockAcquiredLocked(false);
+    }
+}
+
+void SensorService::sendEventsFromCache(const sp<SensorEventConnection>& connection) {
+    Mutex::Autolock _l(mLock);
+    connection->writeToSocketFromCache();
+    if (connection->needsWakeLock()) {
+        setWakeLockAcquiredLocked(true);
+    }
+}
+
+void SensorService::populateActiveConnections(
+        SortedVector< sp<SensorEventConnection> >* activeConnections) {
+    Mutex::Autolock _l(mLock);
+    for (size_t i=0 ; i < mActiveConnections.size(); ++i) {
+        sp<SensorEventConnection> connection(mActiveConnections[i].promote());
+        if (connection != 0) {
+            activeConnections->add(connection);
+        }
     }
 }
 
@@ -1013,6 +1058,11 @@ bool SensorService::SensorEventConnection::needsWakeLock() {
     return !mDead && mWakeLockRefCount > 0;
 }
 
+void SensorService::SensorEventConnection::resetWakeLockRefCount() {
+    Mutex::Autolock _l(mConnectionLock);
+    mWakeLockRefCount = 0;
+}
+
 void SensorService::SensorEventConnection::dump(String8& result) {
     Mutex::Autolock _l(mConnectionLock);
     result.appendFormat("\t WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n",
@@ -1334,11 +1384,14 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
         while (flushInfo.mPendingFlushEventsToSend > 0) {
             const int sensor_handle = mSensorInfo.keyAt(i);
             flushCompleteEvent.meta_data.sensor = sensor_handle;
-            if (mService->getSensorFromHandle(sensor_handle).isWakeUpSensor()) {
+            bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor();
+            if (wakeUpSensor) {
+               ++mWakeLockRefCount;
                flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
             }
             ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
             if (size < 0) {
+                if (wakeUpSensor) --mWakeLockRefCount;
                 return;
             }
             ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
@@ -1348,11 +1401,12 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
     }
 }
 
-void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() {
+void SensorService::SensorEventConnection::writeToSocketFromCache() {
     // At a time write at most half the size of the receiver buffer in SensorEventQueue OR
     // half the size of the socket buffer allocated in BitTube whichever is smaller.
     const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2,
             int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2)));
+    Mutex::Autolock _l(mConnectionLock);
     // Send pending flush complete events (if any)
     sendPendingFlushEventsLocked();
     for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
@@ -1503,9 +1557,8 @@ int SensorService::SensorEventConnection::handleEvent(int fd, int events, void*
     }
 
     if (events & ALOOPER_EVENT_OUTPUT) {
-        // send sensor data that is stored in mEventCache.
-        Mutex::Autolock _l(mConnectionLock);
-        writeToSocketFromCacheLocked();
+        // send sensor data that is stored in mEventCache for this connection.
+        mService->sendEventsFromCache(this);
     }
     return 1;
 }
index 5e3eeb5..8719487 100644 (file)
@@ -101,7 +101,7 @@ class SensorService :
         void sendPendingFlushEventsLocked();
 
         // Writes events from mEventCache to the socket.
-        void writeToSocketFromCacheLocked();
+        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
@@ -182,6 +182,7 @@ class SensorService :
         void setFirstFlushPending(int32_t handle, bool value);
         void dump(String8& result);
         bool needsWakeLock();
+        void resetWakeLockRefCount();
 
         uid_t getUid() const { return mUid; }
     };
@@ -230,12 +231,29 @@ class SensorService :
     // corresponding applications, if yes the wakelock is released.
     void checkWakeLockState();
     void checkWakeLockStateLocked();
+    bool isWakeLockAcquired();
     bool isWakeUpSensorEvent(const sensors_event_t& event) const;
 
     SensorRecord * getSensorRecord(int handle);
 
     sp<Looper> getLooper() const;
 
+    // Reset mWakeLockRefCounts for all SensorEventConnections to zero. This may happen if
+    // SensorService did not receive any acknowledgements from apps which have registered for
+    // wake_up sensors.
+    void resetAllWakeLockRefCounts();
+
+    // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to
+    // 5 seconds and wake the looper.
+    void setWakeLockAcquiredLocked(bool acquire);
+
+    // Send events from the event cache for this particular connection.
+    void sendEventsFromCache(const sp<SensorEventConnection>& connection);
+
+    // Promote all weak referecences in mActiveConnections vector to strong references and add them
+    // to the output vector.
+    void populateActiveConnections(SortedVector< sp<SensorEventConnection> >* activeConnections);
+
     // constants
     Vector<Sensor> mSensorList;
     Vector<Sensor> mUserSensorListDebug;
@@ -247,6 +265,7 @@ class SensorService :
     // supported or not.
     uint32_t mSocketBufferSize;
     sp<Looper> mLooper;
+    sp<SensorEventAckReceiver> mAckReceiver;
 
     // protected by mLock
     mutable Mutex mLock;