OSDN Git Service

Camera2: Legacy: Add onRequestQueueEmpty callback
authorShuzhen Wang <shuzhenwang@google.com>
Fri, 11 Aug 2017 16:11:23 +0000 (09:11 -0700)
committerShuzhen Wang <shuzhenwang@google.com>
Fri, 11 Aug 2017 16:32:20 +0000 (09:32 -0700)
onRequestQueueEmpty callback needs to be supported for legacy HAL1
devices.

Test: Camera CTS
Bug: 64483624
Change-Id: I268a1fe7577788c4e4e13dfecd7bb7abe0d82e6c

core/java/android/hardware/camera2/legacy/CameraDeviceState.java
core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
core/java/android/hardware/camera2/legacy/RequestQueue.java
core/java/android/hardware/camera2/legacy/RequestThreadManager.java

index e48bce1..135d92b 100644 (file)
@@ -76,6 +76,7 @@ public class CameraDeviceState {
         void onBusy();
         void onCaptureStarted(RequestHolder holder, long timestamp);
         void onCaptureResult(CameraMetadataNative result, RequestHolder holder);
+        void onRequestQueueEmpty();
         void onRepeatingRequestError(long lastFrameNumber);
     }
 
@@ -218,6 +219,20 @@ public class CameraDeviceState {
     }
 
     /**
+     * Indicate that request queue (non-repeating) becomes empty.
+     *
+     * <p> Send notification that all non-repeating requests have been sent to camera device. </p>
+     */
+    public synchronized void setRequestQueueEmpty() {
+        mCurrentHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mCurrentListener.onRequestQueueEmpty();
+            }
+        });
+    }
+
+    /**
      * Set the listener for state transition callbacks.
      *
      * @param handler handler on which to call the callbacks.
index 1a05904..621ea84 100644 (file)
@@ -223,6 +223,25 @@ public class LegacyCameraDevice implements AutoCloseable {
         }
 
         @Override
+        public void onRequestQueueEmpty() {
+            mResultHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    if (DEBUG) {
+                        Log.d(TAG, "doing onRequestQueueEmpty callback");
+                    }
+                    try {
+                        mDeviceCallbacks.onRequestQueueEmpty();
+                    } catch (RemoteException e) {
+                        throw new IllegalStateException(
+                                "Received remote exception during onRequestQueueEmpty callback: ",
+                                e);
+                    }
+                }
+            });
+        }
+
+        @Override
         public void onCaptureResult(final CameraMetadataNative result, final RequestHolder holder) {
             final CaptureResultExtras extras = getExtrasFromRequest(holder);
 
index 8f252a1..407e5e6 100644 (file)
@@ -18,7 +18,6 @@ package android.hardware.camera2.legacy;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.utils.SubmitInfo;
 import android.util.Log;
-import android.util.Pair;
 
 import java.util.ArrayDeque;
 import java.util.List;
@@ -41,6 +40,28 @@ public class RequestQueue {
     private int mCurrentRequestId = 0;
     private final List<Long> mJpegSurfaceIds;
 
+    public final class RequestQueueEntry {
+        private final BurstHolder mBurstHolder;
+        private final Long mFrameNumber;
+        private final boolean mQueueEmpty;
+
+        public BurstHolder getBurstHolder() {
+            return mBurstHolder;
+        }
+        public Long getFrameNumber() {
+            return mFrameNumber;
+        }
+        public boolean isQueueEmpty() {
+            return mQueueEmpty;
+        }
+
+        public RequestQueueEntry(BurstHolder burstHolder, Long frameNumber, boolean queueEmpty) {
+            mBurstHolder = burstHolder;
+            mFrameNumber = frameNumber;
+            mQueueEmpty = queueEmpty;
+        }
+    }
+
     public RequestQueue(List<Long> jpegSurfaceIds) {
         mJpegSurfaceIds = jpegSurfaceIds;
     }
@@ -50,10 +71,12 @@ public class RequestQueue {
      *
      * <p>If a repeating burst is returned, it will not be removed.</p>
      *
-     * @return a pair containing the next burst and the current frame number, or null if none exist.
+     * @return an entry containing the next burst, the current frame number, and flag about whether
+     * request queue becomes empty. Null if no burst exists.
      */
-    public synchronized Pair<BurstHolder, Long> getNext() {
+    public synchronized RequestQueueEntry getNext() {
         BurstHolder next = mRequestQueue.poll();
+        boolean queueEmptied = (next != null && mRequestQueue.size() == 0);
         if (next == null && mRepeatingRequest != null) {
             next = mRepeatingRequest;
             mCurrentRepeatingFrameNumber = mCurrentFrameNumber +
@@ -64,7 +87,7 @@ public class RequestQueue {
             return null;
         }
 
-        Pair<BurstHolder, Long> ret =  new Pair<BurstHolder, Long>(next, mCurrentFrameNumber);
+        RequestQueueEntry ret =  new RequestQueueEntry(next, mCurrentFrameNumber, queueEmptied);
         mCurrentFrameNumber += next.getNumberOfRequests();
         return ret;
     }
index da62f54..527e60e 100644 (file)
@@ -713,7 +713,7 @@ public class RequestThreadManager {
                     boolean anyRequestOutputAbandoned = false;
 
                     // Get the next burst from the request queue.
-                    Pair<BurstHolder, Long> nextBurst = mRequestQueue.getNext();
+                    RequestQueue.RequestQueueEntry nextBurst = mRequestQueue.getNext();
 
                     if (nextBurst == null) {
                         // If there are no further requests queued, wait for any currently executing
@@ -748,11 +748,17 @@ public class RequestThreadManager {
                     if (nextBurst != null) {
                         // Queue another capture if we did not get the last burst.
                         handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
+
+                        // Check whether capture queue becomes empty
+                        if (nextBurst.isQueueEmpty()) {
+                            mDeviceState.setRequestQueueEmpty();
+                        }
                     }
 
                     // Complete each request in the burst
+                    BurstHolder burstHolder = nextBurst.getBurstHolder();
                     List<RequestHolder> requests =
-                            nextBurst.first.produceRequestHolders(nextBurst.second);
+                            burstHolder.produceRequestHolders(nextBurst.getFrameNumber());
                     for (RequestHolder holder : requests) {
                         CaptureRequest request = holder.getRequest();
 
@@ -918,8 +924,8 @@ public class RequestThreadManager {
                     }
 
                     // Stop the repeating request if any of its output surfaces is abandoned.
-                    if (anyRequestOutputAbandoned && nextBurst.first.isRepeating()) {
-                        long lastFrameNumber = cancelRepeating(nextBurst.first.getRequestId());
+                    if (anyRequestOutputAbandoned && burstHolder.isRepeating()) {
+                        long lastFrameNumber = cancelRepeating(burstHolder.getRequestId());
                         if (DEBUG) {
                             Log.d(TAG, "Stopped repeating request. Last frame number is " +
                                     lastFrameNumber);