OSDN Git Service

Camera3: Be busy as soon as work arrives.
authorEino-Ville Talvala <etalvala@google.com>
Thu, 29 Aug 2013 19:46:18 +0000 (12:46 -0700)
committerEino-Ville Talvala <etalvala@google.com>
Thu, 29 Aug 2013 19:51:00 +0000 (12:51 -0700)
RequestThread's internal busy flag (mPaused) was not being immediately
set when new work was submitted to it. This allowed for a race
condition where a capture() followed by an immediate
waitUntilDrained() would immediately return from the wait.

Set the mPaused flag to false immediately in capture() and
setStreamingRequest() to avoid this, instead of waiting until the end
of the next RequestThread iteration.

Bug: 10531739
Change-Id: I54a79fe5361d527ec717f41ad805e9b319a48cd8

services/camera/libcameraservice/device3/Camera3Device.cpp
services/camera/libcameraservice/device3/Camera3Device.h

index 7f2ec7a..47321e0 100644 (file)
@@ -1424,6 +1424,8 @@ status_t Camera3Device::RequestThread::queueRequest(
     Mutex::Autolock l(mRequestLock);
     mRequestQueue.push_back(request);
 
+    unpauseForNewRequests();
+
     return OK;
 }
 
@@ -1489,6 +1491,9 @@ status_t Camera3Device::RequestThread::setRepeatingRequests(
     mRepeatingRequests.clear();
     mRepeatingRequests.insert(mRepeatingRequests.begin(),
             requests.begin(), requests.end());
+
+    unpauseForNewRequests();
+
     return OK;
 }
 
@@ -1791,7 +1796,9 @@ sp<Camera3Device::CaptureRequest>
         mRequestQueue.erase(firstRequest);
     }
 
-    // Not paused
+    // In case we've been unpaused by setPaused clearing mDoPause, need to
+    // update internal pause state (capture/setRepeatingRequest unpause
+    // directly).
     Mutex::Autolock pl(mPauseLock);
     mPaused = false;
 
@@ -1824,6 +1831,16 @@ bool Camera3Device::RequestThread::waitIfPaused() {
     return false;
 }
 
+void Camera3Device::RequestThread::unpauseForNewRequests() {
+    // With work to do, mark thread as unpaused.
+    // If paused by request (setPaused), don't resume, to avoid
+    // extra signaling/waiting overhead to waitUntilPaused
+    Mutex::Autolock p(mPauseLock);
+    if (!mDoPause) {
+        mPaused = false;
+    }
+}
+
 void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
     sp<Camera3Device> parent = mParent.promote();
     if (parent != NULL) {
index 99e1cc8..6565048 100644 (file)
@@ -314,6 +314,7 @@ class Camera3Device :
 
         // Pause handling
         bool               waitIfPaused();
+        void               unpauseForNewRequests();
 
         // Relay error to parent device object setErrorState
         void               setErrorState(const char *fmt, ...);