diff options
6 files changed, 464 insertions, 48 deletions
diff --git a/api/current.txt b/api/current.txt index c5fd77cd64db..5e7fa591385e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15727,6 +15727,8 @@ package android.hardware.camera2 { method public abstract void abortCaptures() throws android.hardware.camera2.CameraAccessException; method public abstract int capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; method public abstract int captureBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public int captureBurstRequests(java.util.List<android.hardware.camera2.CaptureRequest>, java.util.concurrent.Executor, android.hardware.camera2.CameraCaptureSession.CaptureCallback) throws android.hardware.camera2.CameraAccessException; + method public int captureSingleRequest(android.hardware.camera2.CaptureRequest, java.util.concurrent.Executor, android.hardware.camera2.CameraCaptureSession.CaptureCallback) throws android.hardware.camera2.CameraAccessException; method public abstract void close(); method public abstract void finalizeOutputConfigurations(java.util.List<android.hardware.camera2.params.OutputConfiguration>) throws android.hardware.camera2.CameraAccessException; method public abstract android.hardware.camera2.CameraDevice getDevice(); @@ -15734,7 +15736,9 @@ package android.hardware.camera2 { method public abstract boolean isReprocessable(); method public abstract void prepare(android.view.Surface) throws android.hardware.camera2.CameraAccessException; method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public int setRepeatingBurstRequests(java.util.List<android.hardware.camera2.CaptureRequest>, java.util.concurrent.Executor, android.hardware.camera2.CameraCaptureSession.CaptureCallback) throws android.hardware.camera2.CameraAccessException; method public abstract int setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public int setSingleRepeatingRequest(android.hardware.camera2.CaptureRequest, java.util.concurrent.Executor, android.hardware.camera2.CameraCaptureSession.CaptureCallback) throws android.hardware.camera2.CameraAccessException; method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException; method public void updateOutputConfiguration(android.hardware.camera2.params.OutputConfiguration) throws android.hardware.camera2.CameraAccessException; } @@ -15902,8 +15906,11 @@ package android.hardware.camera2 { method public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(java.lang.String) throws android.hardware.camera2.CameraAccessException; method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException; method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public void openCamera(java.lang.String, java.util.concurrent.Executor, android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException; method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler); + method public void registerAvailabilityCallback(java.util.concurrent.Executor, android.hardware.camera2.CameraManager.AvailabilityCallback); method public void registerTorchCallback(android.hardware.camera2.CameraManager.TorchCallback, android.os.Handler); + method public void registerTorchCallback(java.util.concurrent.Executor, android.hardware.camera2.CameraManager.TorchCallback); method public void setTorchMode(java.lang.String, boolean) throws android.hardware.camera2.CameraAccessException; method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback); method public void unregisterTorchCallback(android.hardware.camera2.CameraManager.TorchCallback); diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java index ff69bd89564c..eafe5938d38b 100644 --- a/core/java/android/hardware/camera2/CameraCaptureSession.java +++ b/core/java/android/hardware/camera2/CameraCaptureSession.java @@ -16,15 +16,16 @@ package android.hardware.camera2; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.camera2.params.OutputConfiguration; import android.os.Handler; import android.view.Surface; +import java.util.concurrent.Executor; import java.util.List; - /** * A configured capture session for a {@link CameraDevice}, used for capturing images from the * camera or reprocessing images captured from the camera in the same session previously. @@ -354,6 +355,50 @@ public abstract class CameraCaptureSession implements AutoCloseable { throws CameraAccessException; /** + * <p>Submit a request for an image to be captured by the camera device.</p> + * + * <p>The behavior of this method matches that of + * {@link #capture(CaptureRequest, CaptureCallback, Handler)}, + * except that it uses {@link java.util.concurrent.Executor} as an argument + * instead of {@link android.os.Handler}.</p> + * + * @param request the settings for this capture + * @param executor the executor which will be used for invoking the listener. + * @param listener The callback object to notify once this request has been + * processed. + * + * @return int A unique capture sequence ID used by + * {@link CaptureCallback#onCaptureSequenceCompleted}. + * + * @throws CameraAccessException if the camera device is no longer connected or has + * encountered a fatal error + * @throws IllegalStateException if this session is no longer active, either because the session + * was explicitly closed, a new session has been created + * or the camera device has been closed. + * @throws IllegalArgumentException if the request targets no Surfaces or Surfaces that are not + * configured as outputs for this session; or the request + * targets a set of Surfaces that cannot be submitted + * simultaneously in a reprocessable capture session; or a + * reprocess capture request is submitted in a + * non-reprocessable capture session; or the reprocess capture + * request was created with a {@link TotalCaptureResult} from + * a different session; or the capture targets a Surface in + * the middle of being {@link #prepare prepared}; or the + * executor is null, or the listener is not null. + * + * @see #captureBurst + * @see #setRepeatingRequest + * @see #setRepeatingBurst + * @see #abortCaptures + * @see CameraDevice#createReprocessableCaptureSession + */ + public int captureSingleRequest(@NonNull CaptureRequest request, + @NonNull @CallbackExecutor Executor executor, @NonNull CaptureCallback listener) + throws CameraAccessException { + throw new UnsupportedOperationException("Subclasses must override this method"); + } + + /** * Submit a list of requests to be captured in sequence as a burst. The * burst will be captured in the minimum amount of time possible, and will * not be interleaved with requests submitted by other capture or repeat @@ -416,6 +461,53 @@ public abstract class CameraCaptureSession implements AutoCloseable { throws CameraAccessException; /** + * Submit a list of requests to be captured in sequence as a burst. The + * burst will be captured in the minimum amount of time possible, and will + * not be interleaved with requests submitted by other capture or repeat + * calls. + * + * <p>The behavior of this method matches that of + * {@link #captureBurst(List, CaptureCallback, Handler)}, + * except that it uses {@link java.util.concurrent.Executor} as an argument + * instead of {@link android.os.Handler}.</p> + * + * @param requests the list of settings for this burst capture + * @param executor the executor which will be used for invoking the listener. + * @param listener The callback object to notify each time one of the + * requests in the burst has been processed. + * + * @return int A unique capture sequence ID used by + * {@link CaptureCallback#onCaptureSequenceCompleted}. + * + * @throws CameraAccessException if the camera device is no longer connected or has + * encountered a fatal error + * @throws IllegalStateException if this session is no longer active, either because the session + * was explicitly closed, a new session has been created + * or the camera device has been closed. + * @throws IllegalArgumentException If the requests target no Surfaces, or the requests target + * Surfaces not currently configured as outputs; or one of the + * requests targets a set of Surfaces that cannot be submitted + * simultaneously in a reprocessable capture session; or a + * reprocess capture request is submitted in a + * non-reprocessable capture session; or one of the reprocess + * capture requests was created with a + * {@link TotalCaptureResult} from a different session; or one + * of the captures targets a Surface in the middle of being + * {@link #prepare prepared}; or if the executor is null; or if + * the listener is null. + * + * @see #capture + * @see #setRepeatingRequest + * @see #setRepeatingBurst + * @see #abortCaptures + */ + public int captureBurstRequests(@NonNull List<CaptureRequest> requests, + @NonNull @CallbackExecutor Executor executor, @NonNull CaptureCallback listener) + throws CameraAccessException { + throw new UnsupportedOperationException("Subclasses must override this method"); + } + + /** * Request endlessly repeating capture of images by this capture session. * * <p>With this method, the camera device will continually capture images @@ -483,6 +575,45 @@ public abstract class CameraCaptureSession implements AutoCloseable { throws CameraAccessException; /** + * Request endlessly repeating capture of images by this capture session. + * + * <p>The behavior of this method matches that of + * {@link #setRepeatingRequest(CaptureRequest, CaptureCallback, Handler)}, + * except that it uses {@link java.util.concurrent.Executor} as an argument + * instead of {@link android.os.Handler}.</p> + * + * @param request the request to repeat indefinitely + * @param executor the executor which will be used for invoking the listener. + * @param listener The callback object to notify every time the + * request finishes processing. + * + * @return int A unique capture sequence ID used by + * {@link CaptureCallback#onCaptureSequenceCompleted}. + * + * @throws CameraAccessException if the camera device is no longer connected or has + * encountered a fatal error + * @throws IllegalStateException if this session is no longer active, either because the session + * was explicitly closed, a new session has been created + * or the camera device has been closed. + * @throws IllegalArgumentException If the request references no Surfaces or references Surfaces + * that are not currently configured as outputs; or the request + * is a reprocess capture request; or the capture targets a + * Surface in the middle of being {@link #prepare prepared}; or + * the executor is null; or the listener is null. + * + * @see #capture + * @see #captureBurst + * @see #setRepeatingBurst + * @see #stopRepeating + * @see #abortCaptures + */ + public int setSingleRepeatingRequest(@NonNull CaptureRequest request, + @NonNull @CallbackExecutor Executor executor, @NonNull CaptureCallback listener) + throws CameraAccessException { + throw new UnsupportedOperationException("Subclasses must override this method"); + } + + /** * <p>Request endlessly repeating capture of a sequence of images by this * capture session.</p> * @@ -555,6 +686,47 @@ public abstract class CameraCaptureSession implements AutoCloseable { throws CameraAccessException; /** + * <p>Request endlessly repeating capture of a sequence of images by this + * capture session.</p> + * + * <p>The behavior of this method matches that of + * {@link #setRepeatingBurst(List, CaptureCallback, Handler)}, + * except that it uses {@link java.util.concurrent.Executor} as an argument + * instead of {@link android.os.Handler}.</p> + * + * @param requests the list of requests to cycle through indefinitely + * @param executor the executor which will be used for invoking the listener. + * @param listener The callback object to notify each time one of the + * requests in the repeating bursts has finished processing. + * + * @return int A unique capture sequence ID used by + * {@link CaptureCallback#onCaptureSequenceCompleted}. + * + * @throws CameraAccessException if the camera device is no longer connected or has + * encountered a fatal error + * @throws IllegalStateException if this session is no longer active, either because the session + * was explicitly closed, a new session has been created + * or the camera device has been closed. + * @throws IllegalArgumentException If the requests reference no Surfaces or reference Surfaces + * not currently configured as outputs; or one of the requests + * is a reprocess capture request; or one of the captures + * targets a Surface in the middle of being + * {@link #prepare prepared}; or the executor is null; or the + * listener is null. + * + * @see #capture + * @see #captureBurst + * @see #setRepeatingRequest + * @see #stopRepeating + * @see #abortCaptures + */ + public int setRepeatingBurstRequests(@NonNull List<CaptureRequest> requests, + @NonNull @CallbackExecutor Executor executor, @NonNull CaptureCallback listener) + throws CameraAccessException { + throw new UnsupportedOperationException("Subclasses must override this method"); + } + + /** * <p>Cancel any ongoing repeating capture set by either * {@link #setRepeatingRequest setRepeatingRequest} or * {@link #setRepeatingBurst}. Has no effect on requests submitted through diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 4d642956b135..4124536d6adc 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -16,6 +16,7 @@ package android.hardware.camera2; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -134,6 +135,27 @@ public final class CameraManager { } /** + * Register a callback to be notified about camera device availability. + * + * <p>The behavior of this method matches that of + * {@link #registerAvailabilityCallback(AvailabilityCallback, Handler)}, + * except that it uses {@link java.util.concurrent.Executor} as an argument + * instead of {@link android.os.Handler}.</p> + * + * @param executor The executor which will be used to invoke the callback. + * @param callback the new callback to send camera availability notices to + * + * @throws IllegalArgumentException if the executor is {@code null}. + */ + public void registerAvailabilityCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull AvailabilityCallback callback) { + if (executor == null) { + throw new IllegalArgumentException("executor was null"); + } + CameraManagerGlobal.get().registerAvailabilityCallback(callback, executor); + } + + /** * Remove a previously-added callback; the callback will no longer receive connection and * disconnection callbacks. * @@ -173,6 +195,27 @@ public final class CameraManager { } /** + * Register a callback to be notified about torch mode status. + * + * <p>The behavior of this method matches that of + * {@link #registerTorchCallback(TorchCallback, Handler)}, + * except that it uses {@link java.util.concurrent.Executor} as an argument + * instead of {@link android.os.Handler}.</p> + * + * @param executor The executor which will be used to invoke the callback + * @param callback The new callback to send torch mode status to + * + * @throws IllegalArgumentException if the executor is {@code null}. + */ + public void registerTorchCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull TorchCallback callback) { + if (executor == null) { + throw new IllegalArgumentException("executor was null"); + } + CameraManagerGlobal.get().registerTorchCallback(callback, executor); + } + + /** * Remove a previously-added callback; the callback will no longer receive torch mode status * callbacks. * @@ -248,7 +291,7 @@ public final class CameraManager { * * @param cameraId The unique identifier of the camera device to open * @param callback The callback for the camera. Must not be null. - * @param handler The handler to invoke the callback on. Must not be null. + * @param executor The executor to invoke the callback with. Must not be null. * @param uid The UID of the application actually opening the camera. * Must be USE_CALLING_UID unless the caller is a service * that is trusted to open the device on behalf of an @@ -267,7 +310,7 @@ public final class CameraManager { * @see android.app.admin.DevicePolicyManager#setCameraDisabled */ private CameraDevice openCameraDeviceUserAsync(String cameraId, - CameraDevice.StateCallback callback, Handler handler, final int uid) + CameraDevice.StateCallback callback, Executor executor, final int uid) throws CameraAccessException { CameraCharacteristics characteristics = getCameraCharacteristics(cameraId); CameraDevice device = null; @@ -280,7 +323,7 @@ public final class CameraManager { new android.hardware.camera2.impl.CameraDeviceImpl( cameraId, callback, - handler, + executor, characteristics, mContext.getApplicationInfo().targetSdkVersion); @@ -421,7 +464,47 @@ public final class CameraManager { @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler) throws CameraAccessException { - openCameraForUid(cameraId, callback, handler, USE_CALLING_UID); + openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler), + USE_CALLING_UID); + } + + /** + * Open a connection to a camera with the given ID. + * + * <p>The behavior of this method matches that of + * {@link #openCamera(String, StateCallback, Handler)}, except that it uses + * {@link java.util.concurrent.Executor} as an argument instead of + * {@link android.os.Handler}.</p> + * + * @param cameraId + * The unique identifier of the camera device to open + * @param executor + * The executor which will be used when invoking the callback. + * @param callback + * The callback which is invoked once the camera is opened + * + * @throws CameraAccessException if the camera is disabled by device policy, + * has been disconnected, or is being used by a higher-priority camera API client. + * + * @throws IllegalArgumentException if cameraId, the callback or the executor was null, + * or the cameraId does not match any currently or previously available + * camera device. + * + * @throws SecurityException if the application does not have permission to + * access the camera + * + * @see #getCameraIdList + * @see android.app.admin.DevicePolicyManager#setCameraDisabled + */ + @RequiresPermission(android.Manifest.permission.CAMERA) + public void openCamera(@NonNull String cameraId, + @NonNull @CallbackExecutor Executor executor, + @NonNull final CameraDevice.StateCallback callback) + throws CameraAccessException { + if (executor == null) { + throw new IllegalArgumentException("executor was null"); + } + openCameraForUid(cameraId, callback, executor, USE_CALLING_UID); } /** @@ -440,7 +523,7 @@ public final class CameraManager { * @hide */ public void openCameraForUid(@NonNull String cameraId, - @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler, + @NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor, int clientUid) throws CameraAccessException { @@ -448,19 +531,12 @@ public final class CameraManager { throw new IllegalArgumentException("cameraId was null"); } else if (callback == null) { throw new IllegalArgumentException("callback was null"); - } else if (handler == null) { - if (Looper.myLooper() != null) { - handler = new Handler(); - } else { - throw new IllegalArgumentException( - "Handler argument is null, but no looper exists in the calling thread"); - } } if (CameraManagerGlobal.sCameraServiceDisabled) { throw new IllegalArgumentException("No cameras available on device"); } - openCameraDeviceUserAsync(cameraId, callback, handler, clientUid); + openCameraDeviceUserAsync(cameraId, callback, executor, clientUid); } /** diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index 9cac71c35645..a4640c1fa519 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -158,6 +158,49 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession @Override public int capture(CaptureRequest request, CaptureCallback callback, Handler handler) throws CameraAccessException { + checkCaptureRequest(request); + + synchronized (mDeviceImpl.mInterfaceLock) { + checkNotClosed(); + + handler = checkHandler(handler, callback); + + if (DEBUG) { + Log.v(TAG, mIdString + "capture - request " + request + ", callback " + callback + + " handler " + handler); + } + + return addPendingSequence(mDeviceImpl.capture(request, + createCaptureCallbackProxy(handler, callback), mDeviceExecutor)); + } + } + + @Override + public int captureSingleRequest(CaptureRequest request, Executor executor, + CaptureCallback callback) throws CameraAccessException { + if (executor == null) { + throw new IllegalArgumentException("executor must not be null"); + } else if (callback == null) { + throw new IllegalArgumentException("callback must not be null"); + } + checkCaptureRequest(request); + + synchronized (mDeviceImpl.mInterfaceLock) { + checkNotClosed(); + + executor = CameraDeviceImpl.checkExecutor(executor, callback); + + if (DEBUG) { + Log.v(TAG, mIdString + "capture - request " + request + ", callback " + callback + + " executor " + executor); + } + + return addPendingSequence(mDeviceImpl.capture(request, + createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor)); + } + } + + private void checkCaptureRequest(CaptureRequest request) { if (request == null) { throw new IllegalArgumentException("request must not be null"); } else if (request.isReprocess() && !isReprocessable()) { @@ -166,6 +209,12 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } else if (request.isReprocess() && request.getReprocessableSessionId() != mId) { throw new IllegalArgumentException("capture request was created for another session"); } + } + + @Override + public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback, + Handler handler) throws CameraAccessException { + checkCaptureRequests(requests); synchronized (mDeviceImpl.mInterfaceLock) { checkNotClosed(); @@ -173,18 +222,43 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession handler = checkHandler(handler, callback); if (DEBUG) { - Log.v(TAG, mIdString + "capture - request " + request + ", callback " + callback + - " handler " + handler); + CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]); + Log.v(TAG, mIdString + "captureBurst - requests " + Arrays.toString(requestArray) + + ", callback " + callback + " handler " + handler); } - return addPendingSequence(mDeviceImpl.capture(request, + return addPendingSequence(mDeviceImpl.captureBurst(requests, createCaptureCallbackProxy(handler, callback), mDeviceExecutor)); } } @Override - public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback, - Handler handler) throws CameraAccessException { + public int captureBurstRequests(List<CaptureRequest> requests, Executor executor, + CaptureCallback callback) throws CameraAccessException { + if (executor == null) { + throw new IllegalArgumentException("executor must not be null"); + } else if (callback == null) { + throw new IllegalArgumentException("callback must not be null"); + } + checkCaptureRequests(requests); + + synchronized (mDeviceImpl.mInterfaceLock) { + checkNotClosed(); + + executor = CameraDeviceImpl.checkExecutor(executor, callback); + + if (DEBUG) { + CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]); + Log.v(TAG, mIdString + "captureBurst - requests " + Arrays.toString(requestArray) + + ", callback " + callback + " executor " + executor); + } + + return addPendingSequence(mDeviceImpl.captureBurst(requests, + createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor)); + } + } + + private void checkCaptureRequests(List<CaptureRequest> requests) { if (requests == null) { throw new IllegalArgumentException("Requests must not be null"); } else if (requests.isEmpty()) { @@ -203,61 +277,65 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } } + } + + @Override + public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback, + Handler handler) throws CameraAccessException { + checkRepeatingRequest(request); + synchronized (mDeviceImpl.mInterfaceLock) { checkNotClosed(); handler = checkHandler(handler, callback); if (DEBUG) { - CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]); - Log.v(TAG, mIdString + "captureBurst - requests " + Arrays.toString(requestArray) + - ", callback " + callback + " handler " + handler); + Log.v(TAG, mIdString + "setRepeatingRequest - request " + request + ", callback " + + callback + " handler" + " " + handler); } - return addPendingSequence(mDeviceImpl.captureBurst(requests, + return addPendingSequence(mDeviceImpl.setRepeatingRequest(request, createCaptureCallbackProxy(handler, callback), mDeviceExecutor)); } } @Override - public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback, - Handler handler) throws CameraAccessException { - if (request == null) { - throw new IllegalArgumentException("request must not be null"); - } else if (request.isReprocess()) { - throw new IllegalArgumentException("repeating reprocess requests are not supported"); + public int setSingleRepeatingRequest(CaptureRequest request, Executor executor, + CaptureCallback callback) throws CameraAccessException { + if (executor == null) { + throw new IllegalArgumentException("executor must not be null"); + } else if (callback == null) { + throw new IllegalArgumentException("callback must not be null"); } + checkRepeatingRequest(request); synchronized (mDeviceImpl.mInterfaceLock) { checkNotClosed(); - handler = checkHandler(handler, callback); + executor = CameraDeviceImpl.checkExecutor(executor, callback); if (DEBUG) { Log.v(TAG, mIdString + "setRepeatingRequest - request " + request + ", callback " + - callback + " handler" + " " + handler); + callback + " executor" + " " + executor); } return addPendingSequence(mDeviceImpl.setRepeatingRequest(request, - createCaptureCallbackProxy(handler, callback), mDeviceExecutor)); + createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor)); + } + } + + private void checkRepeatingRequest(CaptureRequest request) { + if (request == null) { + throw new IllegalArgumentException("request must not be null"); + } else if (request.isReprocess()) { + throw new IllegalArgumentException("repeating reprocess requests are not supported"); } } @Override public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback callback, Handler handler) throws CameraAccessException { - if (requests == null) { - throw new IllegalArgumentException("requests must not be null"); - } else if (requests.isEmpty()) { - throw new IllegalArgumentException("requests must have at least one element"); - } - - for (CaptureRequest r : requests) { - if (r.isReprocess()) { - throw new IllegalArgumentException("repeating reprocess burst requests are not " + - "supported"); - } - } + checkRepeatingRequests(requests); synchronized (mDeviceImpl.mInterfaceLock) { checkNotClosed(); @@ -277,6 +355,48 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } @Override + public int setRepeatingBurstRequests(List<CaptureRequest> requests, Executor executor, + CaptureCallback callback) throws CameraAccessException { + if (executor == null) { + throw new IllegalArgumentException("executor must not be null"); + } else if (callback == null) { + throw new IllegalArgumentException("callback must not be null"); + } + checkRepeatingRequests(requests); + + synchronized (mDeviceImpl.mInterfaceLock) { + checkNotClosed(); + + executor = CameraDeviceImpl.checkExecutor(executor, callback); + + if (DEBUG) { + CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]); + Log.v(TAG, mIdString + "setRepeatingBurst - requests " + + Arrays.toString(requestArray) + ", callback " + callback + + " executor" + "" + executor); + } + + return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests, + createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor)); + } + } + + private void checkRepeatingRequests(List<CaptureRequest> requests) { + if (requests == null) { + throw new IllegalArgumentException("requests must not be null"); + } else if (requests.isEmpty()) { + throw new IllegalArgumentException("requests must have at least one element"); + } + + for (CaptureRequest r : requests) { + if (r.isReprocess()) { + throw new IllegalArgumentException("repeating reprocess burst requests are not " + + "supported"); + } + } + } + + @Override public void stopRepeating() throws CameraAccessException { synchronized (mDeviceImpl.mInterfaceLock) { checkNotClosed(); @@ -462,6 +582,11 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession final Executor executor = (callback != null) ? CameraDeviceImpl.checkAndWrapHandler( handler) : null; + return createCaptureCallbackProxyWithExecutor(executor, callback); + } + + private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxyWithExecutor( + Executor executor, CaptureCallback callback) { return new CameraDeviceImpl.CaptureCallback() { @Override public void onCaptureStarted(CameraDevice camera, diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java index 89f6172df656..3494a7f2801e 100644 --- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java @@ -193,6 +193,13 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl } @Override + public int captureSingleRequest(CaptureRequest request, Executor executor, + CaptureCallback listener) throws CameraAccessException { + throw new UnsupportedOperationException("Constrained high speed session doesn't support" + + " this method"); + } + + @Override public int captureBurst(List<CaptureRequest> requests, CaptureCallback listener, Handler handler) throws CameraAccessException { if (!isConstrainedHighSpeedRequestList(requests)) { @@ -204,6 +211,17 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl } @Override + public int captureBurstRequests(List<CaptureRequest> requests, Executor executor, + CaptureCallback listener) throws CameraAccessException { + if (!isConstrainedHighSpeedRequestList(requests)) { + throw new IllegalArgumentException( + "Only request lists created by createHighSpeedRequestList() can be submitted to " + + "a constrained high speed capture session"); + } + return mSessionImpl.captureBurstRequests(requests, executor, listener); + } + + @Override public int setRepeatingRequest(CaptureRequest request, CaptureCallback listener, Handler handler) throws CameraAccessException { throw new UnsupportedOperationException("Constrained high speed session doesn't support" @@ -211,6 +229,13 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl } @Override + public int setSingleRepeatingRequest(CaptureRequest request, Executor executor, + CaptureCallback listener) throws CameraAccessException { + throw new UnsupportedOperationException("Constrained high speed session doesn't support" + + " this method"); + } + + @Override public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback listener, Handler handler) throws CameraAccessException { if (!isConstrainedHighSpeedRequestList(requests)) { @@ -222,6 +247,17 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl } @Override + public int setRepeatingBurstRequests(List<CaptureRequest> requests, Executor executor, + CaptureCallback listener) throws CameraAccessException { + if (!isConstrainedHighSpeedRequestList(requests)) { + throw new IllegalArgumentException( + "Only request lists created by createHighSpeedRequestList() can be submitted to " + + "a constrained high speed capture session"); + } + return mSessionImpl.setRepeatingBurstRequests(requests, executor, listener); + } + + @Override public void stopRepeating() throws CameraAccessException { mSessionImpl.stopRepeating(); } diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 1f35f31b68ff..d967fbaf610c 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -240,14 +240,14 @@ public class CameraDeviceImpl extends CameraDevice } }; - public CameraDeviceImpl(String cameraId, StateCallback callback, Handler handler, + public CameraDeviceImpl(String cameraId, StateCallback callback, Executor executor, CameraCharacteristics characteristics, int appTargetSdkVersion) { - if (cameraId == null || callback == null || handler == null || characteristics == null) { + if (cameraId == null || callback == null || executor == null || characteristics == null) { throw new IllegalArgumentException("Null argument given"); } mCameraId = cameraId; mDeviceCallback = callback; - mDeviceExecutor = checkAndWrapHandler(handler); + mDeviceExecutor = executor; mCharacteristics = characteristics; mAppTargetSdkVersion = appTargetSdkVersion; @@ -2349,7 +2349,7 @@ public class CameraDeviceImpl extends CameraDevice * * <p>If the callback isn't null, check the executor, otherwise pass it through.</p> */ - static <T> Executor checkExecutor(Executor executor, T callback) { + public static <T> Executor checkExecutor(Executor executor, T callback) { return (callback != null) ? checkExecutor(executor) : executor; } |