diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2019-06-26 10:34:35 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-06-26 10:34:35 +0000 |
commit | da18b8e358a305e4ae90edc548eb48927f037696 (patch) | |
tree | c3a16bb1e5fdc4bb1b1eec559952870125007b50 | |
parent | 6876100ba52579196ab04acbb3aa1affef40468d (diff) | |
parent | 6bab881066053851a51a4d8d068fd5dd0ff45866 (diff) | |
download | support-da18b8e358a305e4ae90edc548eb48927f037696.tar.gz |
Merge "Exposing public CameraControl and rename the existing one to CameraControlInternal" into androidx-master-dev
18 files changed, 309 insertions, 242 deletions
diff --git a/camera/camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java b/camera/camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java index 9abd37da823..002859c2ab1 100644 --- a/camera/camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java +++ b/camera/camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java @@ -33,9 +33,10 @@ import android.os.Looper; import android.util.Size; import android.view.Surface; +import androidx.annotation.NonNull; import androidx.camera.camera2.impl.Camera2CameraControl; import androidx.camera.core.AppConfig; -import androidx.camera.core.CameraControl; +import androidx.camera.core.CameraControlInternal; import androidx.camera.core.CameraFactory; import androidx.camera.core.CameraX; import androidx.camera.core.CameraX.LensFacing; @@ -88,7 +89,7 @@ public final class PreviewTest { private String mCameraId; @Before - public void setUp() { + public void setUp() { assumeTrue(CameraUtil.deviceHasCamera()); // Instantiates OnPreviewOutputUpdateListener before each test run. mMockListener = mock(OnPreviewOutputUpdateListener.class); @@ -142,7 +143,7 @@ public final class PreviewTest { Preview useCase = new Preview(mDefaultConfig); useCase.updateSuggestedResolution(Collections.singletonMap(mCameraId, DEFAULT_RESOLUTION)); - CameraControl cameraControl = mock(CameraControl.class); + CameraControlInternal cameraControl = mock(CameraControlInternal.class); useCase.attachCameraControl(mCameraId, cameraControl); Rect rect = new Rect(/*left=*/ 200, /*top=*/ 200, /*right=*/ 800, /*bottom=*/ 800); @@ -162,7 +163,7 @@ public final class PreviewTest { Preview useCase = new Preview(mDefaultConfig); useCase.updateSuggestedResolution(Collections.singletonMap(mCameraId, DEFAULT_RESOLUTION)); - CameraControl cameraControl = mock(CameraControl.class); + CameraControlInternal cameraControl = mock(CameraControlInternal.class); useCase.attachCameraControl(mCameraId, cameraControl); Rect rect = new Rect(/*left=*/ 200, /*top=*/ 200, /*right=*/ 800, /*bottom=*/ 800); @@ -177,7 +178,7 @@ public final class PreviewTest { @UiThreadTest public void torchModeCanBeSet() { Preview useCase = new Preview(mDefaultConfig); - CameraControl cameraControl = getFakeCameraControl(); + CameraControlInternal cameraControl = getFakeCameraControl(); useCase.attachCameraControl(mCameraId, cameraControl); useCase.enableTorch(true); @@ -488,15 +489,17 @@ public final class PreviewTest { assertThat(surfaceTexture0).isNotNull(); } - private CameraControl getFakeCameraControl() { + private CameraControlInternal getFakeCameraControl() { return new Camera2CameraControl( - new CameraControl.ControlUpdateListener() { + new CameraControlInternal.ControlUpdateListener() { @Override - public void onCameraControlUpdateSessionConfig(SessionConfig sessionConfig) { + public void onCameraControlUpdateSessionConfig( + @NonNull SessionConfig sessionConfig) { } @Override - public void onCameraControlCaptureRequests(List<CaptureConfig> captureConfigs) { + public void onCameraControlCaptureRequests( + @NonNull List<CaptureConfig> captureConfigs) { } }, diff --git a/camera/camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraControlTest.java b/camera/camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraControlTest.java index 529b367b444..7b425fd9f4e 100644 --- a/camera/camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraControlTest.java +++ b/camera/camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2CameraControlTest.java @@ -37,7 +37,7 @@ import android.os.Handler; import android.os.HandlerThread; import androidx.camera.camera2.Camera2Config; -import androidx.camera.core.CameraControl; +import androidx.camera.core.CameraControlInternal; import androidx.camera.core.CaptureConfig; import androidx.camera.core.FlashMode; import androidx.camera.core.SessionConfig; @@ -63,7 +63,7 @@ public final class Camera2CameraControlTest { private static final long NO_TIMEOUT = 0; private Camera2CameraControl mCamera2CameraControl; - private CameraControl.ControlUpdateListener mControlUpdateListener; + private CameraControlInternal.ControlUpdateListener mControlUpdateListener; private ArgumentCaptor<SessionConfig> mSessionConfigArgumentCaptor = ArgumentCaptor.forClass(SessionConfig.class); @SuppressWarnings("unchecked") @@ -74,7 +74,7 @@ public final class Camera2CameraControlTest { @Before public void setUp() throws InterruptedException { - mControlUpdateListener = mock(CameraControl.ControlUpdateListener.class); + mControlUpdateListener = mock(CameraControlInternal.ControlUpdateListener.class); mHandlerThread = new HandlerThread("ControlThread"); mHandlerThread.start(); mHandler = HandlerCompat.createAsync(mHandlerThread.getLooper()); diff --git a/camera/camera2/src/androidTest/java/androidx/camera/camera2/impl/CameraImplTest.java b/camera/camera2/src/androidTest/java/androidx/camera/camera2/impl/CameraImplTest.java index bfdf6ca7dd4..feee7b783fa 100644 --- a/camera/camera2/src/androidTest/java/androidx/camera/camera2/impl/CameraImplTest.java +++ b/camera/camera2/src/androidTest/java/androidx/camera/camera2/impl/CameraImplTest.java @@ -603,7 +603,7 @@ public class CameraImplTest { } })); - mCamera.getCameraControl().submitCaptureRequests( + mCamera.getCameraControlInternal().submitCaptureRequests( Arrays.asList(captureConfigBuilder.build())); UseCase useCase2 = createUseCase(); @@ -650,7 +650,7 @@ public class CameraImplTest { })); - mCamera.getCameraControl().submitCaptureRequests( + mCamera.getCameraControlInternal().submitCaptureRequests( Arrays.asList(captureConfigBuilder.build())); mCamera.removeOnlineUseCase(Arrays.asList(useCase1)); diff --git a/camera/camera2/src/main/java/androidx/camera/camera2/impl/Camera.java b/camera/camera2/src/main/java/androidx/camera/camera2/impl/Camera.java index fd1415f9398..374cd65bb9f 100644 --- a/camera/camera2/src/main/java/androidx/camera/camera2/impl/Camera.java +++ b/camera/camera2/src/main/java/androidx/camera/camera2/impl/Camera.java @@ -35,7 +35,7 @@ import androidx.annotation.Nullable; import androidx.annotation.RestrictTo; import androidx.annotation.RestrictTo.Scope; import androidx.camera.core.BaseCamera; -import androidx.camera.core.CameraControl; +import androidx.camera.core.CameraControlInternal; import androidx.camera.core.CameraDeviceStateCallbacks; import androidx.camera.core.CameraInfo; import androidx.camera.core.CameraInfoUnavailableException; @@ -92,7 +92,7 @@ final class Camera implements BaseCamera { */ final AtomicReference<State> mState = new AtomicReference<>(State.UNINITIALIZED); /** The camera control shared across all use cases bound to this Camera. */ - private final CameraControl mCameraControl; + private final CameraControlInternal mCameraControlInternal; private final StateCallback mStateCallback = new StateCallback(); /** Information about the characteristics of this camera */ // Nullable because this is lazily instantiated @@ -128,7 +128,8 @@ final class Camera implements BaseCamera { ScheduledExecutorService executorScheduler = CameraXExecutors.newHandlerExecutor(mHandler); mUseCaseAttachState = new UseCaseAttachState(cameraId); mState.set(State.INITIALIZED); - mCameraControl = new Camera2CameraControl(this, executorScheduler, executorScheduler); + mCameraControlInternal = new Camera2CameraControl(this, executorScheduler, + executorScheduler); mCaptureSession = new CaptureSession(mHandler); } @@ -614,8 +615,8 @@ final class Camera implements BaseCamera { } if (validatingBuilder.isValid()) { - // Apply CameraControl's SessionConfig to let CameraControl be able to control - // Repeating Request and process results. + // Apply CameraControlInternal's SessionConfig to let CameraControlInternal be able + // to control Repeating Request and process results. validatingBuilder.add(mCameraControlSessionConfig); SessionConfig sessionConfig = validatingBuilder.build(); @@ -756,8 +757,8 @@ final class Camera implements BaseCamera { /** Returns the Camera2CameraControl attached to Camera */ @Override - public CameraControl getCameraControl() { - return mCameraControl; + public CameraControlInternal getCameraControlInternal() { + return mCameraControlInternal; } /** @@ -801,14 +802,14 @@ final class Camera implements BaseCamera { /** {@inheritDoc} */ @Override - public void onCameraControlUpdateSessionConfig(SessionConfig sessionConfig) { + public void onCameraControlUpdateSessionConfig(@NonNull SessionConfig sessionConfig) { mCameraControlSessionConfig = sessionConfig; updateCaptureSessionConfig(); } /** {@inheritDoc} */ @Override - public void onCameraControlCaptureRequests(List<CaptureConfig> captureConfigs) { + public void onCameraControlCaptureRequests(@NonNull List<CaptureConfig> captureConfigs) { submitCaptureRequests(captureConfigs); } diff --git a/camera/camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraControl.java b/camera/camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraControl.java index 79e4a3124c7..da2118eef7d 100644 --- a/camera/camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraControl.java +++ b/camera/camera2/src/main/java/androidx/camera/camera2/impl/Camera2CameraControl.java @@ -34,7 +34,7 @@ import androidx.annotation.RestrictTo; import androidx.annotation.VisibleForTesting; import androidx.annotation.WorkerThread; import androidx.camera.camera2.Camera2Config; -import androidx.camera.core.CameraControl; +import androidx.camera.core.CameraControlInternal; import androidx.camera.core.CaptureConfig; import androidx.camera.core.Config; import androidx.camera.core.FlashMode; @@ -53,12 +53,12 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; /** - * A Camera2 implementation for CameraControl interface + * A Camera2 implementation for CameraControlInternal interface * * @hide */ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public final class Camera2CameraControl implements CameraControl { +public final class Camera2CameraControl implements CameraControlInternal { private static final long DEFAULT_FOCUS_TIMEOUT_MS = 5000; private static final String TAG = "Camera2CameraControl"; @SuppressWarnings("WeakerAccess") /* synthetic accessor */ @@ -129,7 +129,7 @@ public final class Camera2CameraControl implements CameraControl { /** {@inheritDoc} */ @Override - public void setCropRegion(final Rect crop) { + public void setCropRegion(@Nullable final Rect crop) { mExecutor.execute(new Runnable() { @Override public void run() { @@ -176,6 +176,7 @@ public final class Camera2CameraControl implements CameraControl { }); } + @NonNull @Override public FlashMode getFlashMode() { return mFlashMode; @@ -183,7 +184,7 @@ public final class Camera2CameraControl implements CameraControl { /** {@inheritDoc} */ @Override - public void setFlashMode(FlashMode flashMode) { + public void setFlashMode(@NonNull FlashMode flashMode) { // update mFlashMode immediately so that following getFlashMode() returns correct value. mFlashMode = flashMode; @@ -266,7 +267,7 @@ public final class Camera2CameraControl implements CameraControl { /** {@inheritDoc} */ @Override - public void submitCaptureRequests(final List<CaptureConfig> captureConfigs) { + public void submitCaptureRequests(@NonNull final List<CaptureConfig> captureConfigs) { mExecutor.execute(new Runnable() { @Override public void run() { diff --git a/camera/core/src/androidTest/java/androidx/camera/core/CameraXTest.java b/camera/core/src/androidTest/java/androidx/camera/core/CameraXTest.java index 65c1cf175c4..c6a18c20912 100644 --- a/camera/core/src/androidTest/java/androidx/camera/core/CameraXTest.java +++ b/camera/core/src/androidTest/java/androidx/camera/core/CameraXTest.java @@ -26,6 +26,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.util.Size; +import androidx.annotation.NonNull; import androidx.camera.core.CameraX.ErrorCode; import androidx.camera.core.CameraX.ErrorListener; import androidx.camera.core.CameraX.LensFacing; @@ -61,7 +62,7 @@ public final class CameraXTest { static { String cameraId = sCameraFactory.cameraIdForLensFacing(LensFacing.BACK); sCameraFactory.insertCamera(cameraId, - new FakeCamera(new FakeCameraInfo(), mock(CameraControl.class))); + new FakeCamera(new FakeCameraInfo(), mock(CameraControlInternal.class))); } private String mCameraId; @@ -212,7 +213,8 @@ public final class CameraXTest { CameraX.bindToLifecycle(mLifecycle, fakeUseCase); - assertThat(fakeUseCase.getCameraControl(mCameraId)).isEqualTo(mCamera.getCameraControl()); + assertThat(fakeUseCase.getCameraControl(mCameraId)).isEqualTo( + mCamera.getCameraControlInternal()); } @Test @@ -235,12 +237,12 @@ public final class CameraXTest { CameraX.unbind(fakeUseCase); - // after unbind, Camera's CameraControl should be detached from Usecase + // after unbind, Camera's CameraControlInternal should be detached from Usecase assertThat(fakeUseCase.getCameraControl(mCameraId)).isNotEqualTo( - mCamera.getCameraControl()); - // UseCase still gets a non-null default CameraControl that does nothing. + mCamera.getCameraControlInternal()); + // UseCase still gets a non-null default CameraControlInternal that does nothing. assertThat(fakeUseCase.getCameraControl(mCameraId)).isEqualTo( - CameraControl.DEFAULT_EMPTY_INSTANCE); + CameraControlInternal.DEFAULT_EMPTY_INSTANCE); } @Test @@ -280,7 +282,7 @@ public final class CameraXTest { } @Override - public void onError(ErrorCode errorCode, String message) { + public void onError(@NonNull ErrorCode errorCode, @NonNull String message) { mCount.getAndIncrement(); mLatch.countDown(); } diff --git a/camera/core/src/androidTest/java/androidx/camera/core/ErrorHandlerTest.java b/camera/core/src/androidTest/java/androidx/camera/core/ErrorHandlerTest.java index 854daf1e269..5083503e568 100644 --- a/camera/core/src/androidTest/java/androidx/camera/core/ErrorHandlerTest.java +++ b/camera/core/src/androidTest/java/androidx/camera/core/ErrorHandlerTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import android.os.Handler; import android.os.HandlerThread; +import androidx.annotation.NonNull; import androidx.camera.core.CameraX.ErrorCode; import androidx.camera.core.CameraX.ErrorListener; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -99,7 +100,7 @@ public class ErrorHandlerTest { } @Override - public void onError(ErrorCode errorCode, String message) { + public void onError(@NonNull ErrorCode errorCode, @NonNull String message) { mCount.getAndIncrement(); mLatch.countDown(); } diff --git a/camera/core/src/main/java/androidx/camera/core/BaseCamera.java b/camera/core/src/main/java/androidx/camera/core/BaseCamera.java index be4031d6f37..8c7d14adb23 100644 --- a/camera/core/src/main/java/androidx/camera/core/BaseCamera.java +++ b/camera/core/src/main/java/androidx/camera/core/BaseCamera.java @@ -28,7 +28,7 @@ import java.util.Collection; */ @RestrictTo(Scope.LIBRARY_GROUP) public interface BaseCamera extends UseCase.StateChangeListener, - CameraControl.ControlUpdateListener { + CameraControlInternal.ControlUpdateListener { /** * Open the camera asynchronously. * @@ -65,8 +65,8 @@ public interface BaseCamera extends UseCase.StateChangeListener, */ void removeOnlineUseCase(Collection<UseCase> useCases); - /** Returns the global CameraControl attached to this camera. */ - CameraControl getCameraControl(); + /** Returns the global CameraControlInternal attached to this camera. */ + CameraControlInternal getCameraControlInternal(); /** Returns an interface to retrieve characteristics of the camera. */ CameraInfo getCameraInfo() throws CameraInfoUnavailableException; diff --git a/camera/core/src/main/java/androidx/camera/core/CameraControl.java b/camera/core/src/main/java/androidx/camera/core/CameraControl.java index d8e733dcdde..6d07f6f4344 100644 --- a/camera/core/src/main/java/androidx/camera/core/CameraControl.java +++ b/camera/core/src/main/java/androidx/camera/core/CameraControl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,166 +16,10 @@ package androidx.camera.core; -import android.annotation.SuppressLint; -import android.graphics.Rect; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RestrictTo; -import androidx.annotation.RestrictTo.Scope; - -import java.util.List; -import java.util.concurrent.Executor; - /** - * The CameraControl Interface. - * - * <p>CameraControl is used for global camera operations like zoom, focus, flash and triggering - * AF/AE. + * An interface for controlling camera's zoom, focus and metering across all use cases. * - * @hide + * <p>Applications can retrieve the interface via CameraX.getCameraControl. */ -@RestrictTo(Scope.LIBRARY_GROUP) public interface CameraControl { - /** - * Set the desired crop region of the sensor to read out for all capture requests. - * - * <p>This crop region can be used to implement digital zoom. It is applied to every single and - * re peating requests. - * - * @param crop rectangle with dimensions in sensor pixel coordinate. - */ - void setCropRegion(Rect crop); - - /** - * Adjusts the camera output according to the properties in some local regions with a callback - * called once focus scan has completed. - * - * <p>The auto-focus (AF), auto-exposure (AE) and auto-whitebalance (AWB) properties will be - * recalculated from the local regions. - * - * @param focus rectangle with dimensions in sensor coordinate frame for focus - * @param metering rectangle with dimensions in sensor coordinate frame for metering - * @param executor the executor which will be used to call the listener. - * @param listener listener for when focus has completed. - */ - @SuppressLint("LambdaLast") // Remove after https://issuetracker.google.com/135275901 - void focus( - @NonNull Rect focus, - @NonNull Rect metering, - @NonNull Executor executor, - @NonNull OnFocusListener listener); - - /** - * Adjusts the camera output according to the properties in some local regions. - * - * <p>The auto-focus (AF), auto-exposure (AE) and auto-whitebalance (AWB) properties will be - * recalculated from the local regions. - * - * @param focus rectangle with dimensions in sensor coordinate frame for focus - * @param metering rectangle with dimensions in sensor coordinate frame for metering - */ - void focus(@NonNull Rect focus, @NonNull Rect metering); - - /** Returns the current flash mode. */ - FlashMode getFlashMode(); - - /** - * Sets current flash mode - * - * @param flashMode the {@link FlashMode}. - */ - void setFlashMode(FlashMode flashMode); - - /** - * Enable the torch or disable the torch - * - * @param torch true to open the torch, false to close it. - */ - void enableTorch(boolean torch); - - /** Returns if current torch is enabled or not. */ - boolean isTorchOn(); - - /** Returns if the focus is currently locked or not. */ - boolean isFocusLocked(); - - /** Performs a AF trigger. */ - void triggerAf(); - - /** Performs a AE Precapture trigger. */ - void triggerAePrecapture(); - - /** Cancel AF trigger AND/OR AE Precapture trigger.* */ - void cancelAfAeTrigger(boolean cancelAfTrigger, boolean cancelAePrecaptureTrigger); - - /** - * Performs capture requests. - */ - void submitCaptureRequests(List<CaptureConfig> captureConfigs); - - CameraControl DEFAULT_EMPTY_INSTANCE = new CameraControl() { - @Override - public void setCropRegion(Rect crop) { - } - - @Override - public void focus(Rect focus, Rect metering, @Nullable Executor executor, - @Nullable OnFocusListener listener) { - } - - @Override - public void focus(Rect focus, Rect metering) { - } - - @Override - public FlashMode getFlashMode() { - return null; - } - - @Override - public void setFlashMode(FlashMode flashMode) { - } - - @Override - public void enableTorch(boolean torch) { - } - - @Override - public boolean isTorchOn() { - return false; - } - - @Override - public boolean isFocusLocked() { - return false; - } - - @Override - public void triggerAf() { - } - - @Override - public void triggerAePrecapture() { - } - - @Override - public void cancelAfAeTrigger(boolean cancelAfTrigger, boolean cancelAePrecaptureTrigger) { - - } - - @Override - public void submitCaptureRequests(List<CaptureConfig> captureConfigs) { - } - }; - - /** Listener called when CameraControl need to notify event. */ - interface ControlUpdateListener { - - /** Called when CameraControl has updated session configuration. */ - void onCameraControlUpdateSessionConfig(SessionConfig sessionConfig); - - /** Called when CameraControl need to send capture requests. */ - void onCameraControlCaptureRequests(List<CaptureConfig> captureConfigs); - } } diff --git a/camera/core/src/main/java/androidx/camera/core/CameraControlInternal.java b/camera/core/src/main/java/androidx/camera/core/CameraControlInternal.java new file mode 100644 index 00000000000..1e01a704a49 --- /dev/null +++ b/camera/core/src/main/java/androidx/camera/core/CameraControlInternal.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.camera.core; + +import android.annotation.SuppressLint; +import android.graphics.Rect; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; +import androidx.annotation.RestrictTo.Scope; + +import java.util.List; +import java.util.concurrent.Executor; + +/** + * The CameraControlInternal Interface. + * + * <p>CameraControlInternal is used for global camera operations like zoom, focus, flash and + * triggering + * AF/AE. + * + * @hide + */ +@RestrictTo(Scope.LIBRARY_GROUP) +public interface CameraControlInternal extends CameraControl { + /** + * Set the desired crop region of the sensor to read out for all capture requests. + * + * <p>This crop region can be used to implement digital zoom. It is applied to every single and + * re peating requests. + * + * @param crop rectangle with dimensions in sensor pixel coordinate. + */ + void setCropRegion(@Nullable Rect crop); + + /** + * Adjusts the camera output according to the properties in some local regions with a callback + * called once focus scan has completed. + * + * <p>The auto-focus (AF), auto-exposure (AE) and auto-whitebalance (AWB) properties will be + * recalculated from the local regions. + * + * @param focus rectangle with dimensions in sensor coordinate frame for focus + * @param metering rectangle with dimensions in sensor coordinate frame for metering + * @param executor the executor which will be used to call the listener. + * @param listener listener for when focus has completed. + */ + @SuppressLint("LambdaLast") + // Remove after https://issuetracker.google.com/135275901 + void focus( + @NonNull Rect focus, + @NonNull Rect metering, + @NonNull Executor executor, + @NonNull OnFocusListener listener); + + /** + * Adjusts the camera output according to the properties in some local regions. + * + * <p>The auto-focus (AF), auto-exposure (AE) and auto-whitebalance (AWB) properties will be + * recalculated from the local regions. + * + * @param focus rectangle with dimensions in sensor coordinate frame for focus + * @param metering rectangle with dimensions in sensor coordinate frame for metering + */ + void focus(@NonNull Rect focus, @NonNull Rect metering); + + /** Returns the current flash mode. */ + @NonNull + FlashMode getFlashMode(); + + /** + * Sets current flash mode + * + * @param flashMode the {@link FlashMode}. + */ + void setFlashMode(@NonNull FlashMode flashMode); + + /** + * Enable the torch or disable the torch + * + * @param torch true to open the torch, false to close it. + */ + void enableTorch(boolean torch); + + /** Returns if current torch is enabled or not. */ + boolean isTorchOn(); + + /** Returns if the focus is currently locked or not. */ + boolean isFocusLocked(); + + /** Performs a AF trigger. */ + void triggerAf(); + + /** Performs a AE Precapture trigger. */ + void triggerAePrecapture(); + + /** Cancel AF trigger AND/OR AE Precapture trigger.* */ + void cancelAfAeTrigger(boolean cancelAfTrigger, boolean cancelAePrecaptureTrigger); + + /** + * Performs capture requests. + */ + void submitCaptureRequests(@NonNull List<CaptureConfig> captureConfigs); + + CameraControlInternal DEFAULT_EMPTY_INSTANCE = new CameraControlInternal() { + @Override + public void setCropRegion(@Nullable Rect crop) { + } + + @Override + public void focus(@NonNull Rect focus, @NonNull Rect metering, @Nullable Executor executor, + @Nullable OnFocusListener listener) { + } + + @Override + public void focus(@NonNull Rect focus, @NonNull Rect metering) { + } + + @NonNull + @Override + public FlashMode getFlashMode() { + return FlashMode.OFF; + } + + @Override + public void setFlashMode(@NonNull FlashMode flashMode) { + } + + @Override + public void enableTorch(boolean torch) { + } + + @Override + public boolean isTorchOn() { + return false; + } + + @Override + public boolean isFocusLocked() { + return false; + } + + @Override + public void triggerAf() { + } + + @Override + public void triggerAePrecapture() { + } + + @Override + public void cancelAfAeTrigger(boolean cancelAfTrigger, boolean cancelAePrecaptureTrigger) { + + } + + @Override + public void submitCaptureRequests(@NonNull List<CaptureConfig> captureConfigs) { + } + }; + + /** Listener called when CameraControlInternal need to notify event. */ + interface ControlUpdateListener { + + /** Called when CameraControlInternal has updated session configuration. */ + void onCameraControlUpdateSessionConfig(@NonNull SessionConfig sessionConfig); + + /** Called when CameraControlInternal need to send capture requests. */ + void onCameraControlCaptureRequests(@NonNull List<CaptureConfig> captureConfigs); + } +} diff --git a/camera/core/src/main/java/androidx/camera/core/CameraX.java b/camera/core/src/main/java/androidx/camera/core/CameraX.java index bba93405c1b..8992048d850 100644 --- a/camera/core/src/main/java/androidx/camera/core/CameraX.java +++ b/camera/core/src/main/java/androidx/camera/core/CameraX.java @@ -21,6 +21,7 @@ import android.os.Handler; import android.util.Size; import androidx.annotation.MainThread; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RestrictTo; import androidx.annotation.RestrictTo.Scope; @@ -315,6 +316,25 @@ public final class CameraX { return INSTANCE.getCameraRepository().getCamera(cameraId).getCameraInfo(); } + + /** + * Returns the camera control for the camera with the given lens facing. + * + * @param lensFacing the lens facing of the camera + * @return the {@link CameraControl}. + * @throws CameraInfoUnavailableException if unable to access cameras, perhaps due to + * insufficient permissions. + * @hide + */ + @RestrictTo(Scope.LIBRARY_GROUP) + public static CameraControl getCameraControl(LensFacing lensFacing) + throws CameraInfoUnavailableException { + + String cameraId = getCameraWithLensFacing(lensFacing); + return (CameraControl) INSTANCE.getCameraRepository().getCamera( + cameraId).getCameraControlInternal(); + } + /** * Returns the {@link CameraDeviceSurfaceManager} which can be used to query for valid surface * configurations. @@ -422,7 +442,7 @@ public final class CameraX { } useCase.addStateChangeListener(camera); - useCase.attachCameraControl(cameraId, camera.getCameraControl()); + useCase.attachCameraControl(cameraId, camera.getCameraControlInternal()); } @@ -607,6 +627,6 @@ public final class CameraX { * @param error the type of error that occurred * @param message detailed message of the error condition */ - void onError(ErrorCode error, String message); + void onError(@NonNull ErrorCode error, @NonNull String message); } } diff --git a/camera/core/src/main/java/androidx/camera/core/ErrorHandler.java b/camera/core/src/main/java/androidx/camera/core/ErrorHandler.java index e4438fb429e..aa6d3f32eaf 100644 --- a/camera/core/src/main/java/androidx/camera/core/ErrorHandler.java +++ b/camera/core/src/main/java/androidx/camera/core/ErrorHandler.java @@ -21,6 +21,7 @@ import android.os.Looper; import android.util.Log; import androidx.annotation.GuardedBy; +import androidx.annotation.NonNull; import androidx.annotation.RestrictTo; import androidx.annotation.RestrictTo.Scope; import androidx.camera.core.CameraX.ErrorCode; @@ -85,7 +86,7 @@ public final class ErrorHandler { /** An error listener which logs the error message and returns. */ static final class PrintingErrorListener implements ErrorListener { @Override - public void onError(ErrorCode error, String message) { + public void onError(@NonNull ErrorCode error, @NonNull String message) { Log.e(TAG, "ErrorHandler occurred: " + error + " with message: " + message); } } diff --git a/camera/core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/core/src/main/java/androidx/camera/core/ImageCapture.java index 98d3868802f..f4117211bc1 100644 --- a/camera/core/src/main/java/androidx/camera/core/ImageCapture.java +++ b/camera/core/src/main/java/androidx/camera/core/ImageCapture.java @@ -232,12 +232,12 @@ public class ImageCapture extends UseCase { return null; } - private CameraControl getCurrentCameraControl() { + private CameraControlInternal getCurrentCameraControl() { String cameraId = getCameraIdUnchecked(mConfig.getLensFacing()); return getCameraControl(cameraId); } - /** Configures flash mode to CameraControl once it is ready. */ + /** Configures flash mode to CameraControlInternal once it is ready. */ @Override protected void onCameraControlReady(String cameraId) { getCameraControl(cameraId).setFlashMode(mFlashMode); diff --git a/camera/core/src/main/java/androidx/camera/core/Preview.java b/camera/core/src/main/java/androidx/camera/core/Preview.java index a5154e7e91c..b71e601ebc4 100644 --- a/camera/core/src/main/java/androidx/camera/core/Preview.java +++ b/camera/core/src/main/java/androidx/camera/core/Preview.java @@ -242,9 +242,9 @@ public class Preview extends UseCase { } } - // TODO: Timeout may be exposed as a PreviewConfig(moved to CameraControl) + // TODO: Timeout may be exposed as a PreviewConfig(moved to CameraControlInternal) - private CameraControl getCurrentCameraControl() { + private CameraControlInternal getCurrentCameraControl() { PreviewConfig config = (PreviewConfig) getUseCaseConfig(); String cameraId = getCameraIdUnchecked(config.getLensFacing()); return getCameraControl(cameraId); diff --git a/camera/core/src/main/java/androidx/camera/core/UseCase.java b/camera/core/src/main/java/androidx/camera/core/UseCase.java index 3259e012d0d..5cc74ec2cb1 100644 --- a/camera/core/src/main/java/androidx/camera/core/UseCase.java +++ b/camera/core/src/main/java/androidx/camera/core/UseCase.java @@ -51,11 +51,11 @@ public abstract class UseCase { private final Set<StateChangeListener> mListeners = new HashSet<>(); /** - * A map of camera id and CameraControl. A CameraControl will be attached into the usecase after - * usecase is bound to lifecycle. It is used for controlling zoom/focus/flash/triggering Af or - * AE. + * A map of camera id and CameraControlInternal. A CameraControlInternal will be attached + * into the usecase after usecase is bound to lifecycle. It is used for controlling + * zoom/focus/flash/triggering Af or AE. */ - private final Map<String, CameraControl> mAttachedCameraControlMap = new HashMap<>(); + private final Map<String, CameraControlInternal> mAttachedCameraControlMap = new HashMap<>(); /** * A map of the names of the {@link android.hardware.camera2.CameraDevice} to the {@link @@ -149,7 +149,7 @@ public abstract class UseCase { * <p>This is called during initialization of the class. Subclassess can override this method to * modify the behavior of combining user-supplied values and default values. * - * @param userConfig The user-supplied configuration. + * @param userConfig The user-supplied configuration. * @param defaultConfigBuilder A builder containing use-case default values. * @return The configuration that will be used by this use case. * @hide @@ -214,17 +214,17 @@ public abstract class UseCase { } /** - * Attach a CameraControl to this use case. + * Attach a CameraControlInternal to this use case. * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) - public final void attachCameraControl(String cameraId, CameraControl cameraControl) { + public final void attachCameraControl(String cameraId, CameraControlInternal cameraControl) { mAttachedCameraControlMap.put(cameraId, cameraControl); onCameraControlReady(cameraId); } - /** Detach a CameraControl from this use case. */ + /** Detach a CameraControlInternal from this use case. */ final void detachCameraControl(String cameraId) { mAttachedCameraControlMap.remove(cameraId); } @@ -263,6 +263,7 @@ public abstract class UseCase { /** * Notify all {@link StateChangeListener} that are listening to this UseCase that it has * transitioned to an active state. + * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) @@ -274,6 +275,7 @@ public abstract class UseCase { /** * Notify all {@link StateChangeListener} that are listening to this UseCase that it has * transitioned to an inactive state. + * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) @@ -285,6 +287,7 @@ public abstract class UseCase { /** * Notify all {@link StateChangeListener} that are listening to this UseCase that the * settings have been updated. + * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) @@ -297,6 +300,7 @@ public abstract class UseCase { /** * Notify all {@link StateChangeListener} that are listening to this UseCase that the use * case needs to be completely reset. + * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) @@ -309,6 +313,7 @@ public abstract class UseCase { /** * Notify all {@link StateChangeListener} that are listening to this UseCase of its current * state. + * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) @@ -346,7 +351,6 @@ public abstract class UseCase { * Retrieves the configuration used by this use case. * * @return the configuration used by this use case. - * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) @@ -359,7 +363,6 @@ public abstract class UseCase { * * @param cameraId the camera id for the desired surface. * @return the currently attached surface resolution for the given camera id. - * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) @@ -401,9 +404,9 @@ public abstract class UseCase { Map<String, Size> suggestedResolutionMap); /** - * Called when CameraControl is attached into the UseCase. UseCase may need to override this - * method to configure the CameraControl here. Ex. Setting correct flash mode by - * CameraControl.setFlashMode to enable correct AE mode and flash state. + * Called when CameraControlInternal is attached into the UseCase. UseCase may need to + * override this method to configure the CameraControlInternal here. Ex. Setting correct flash + * mode by CameraControlInternal.setFlashMode to enable correct AE mode and flash state. * * @hide */ @@ -426,15 +429,15 @@ public abstract class UseCase { } /** - * Retrieves a previously attached {@link CameraControl}. + * Retrieves a previously attached {@link CameraControlInternal}. * * @hide */ @RestrictTo(Scope.LIBRARY_GROUP) - protected CameraControl getCameraControl(String cameraId) { - CameraControl cameraControl = mAttachedCameraControlMap.get(cameraId); + protected CameraControlInternal getCameraControl(String cameraId) { + CameraControlInternal cameraControl = mAttachedCameraControlMap.get(cameraId); if (cameraControl == null) { - return CameraControl.DEFAULT_EMPTY_INSTANCE; + return CameraControlInternal.DEFAULT_EMPTY_INSTANCE; } return cameraControl; } @@ -514,6 +517,7 @@ public abstract class UseCase { /** * Called when use case was bound to the life cycle. + * * @param cameraId that current used. */ void onBind(String cameraId); diff --git a/camera/testing/src/main/java/androidx/camera/testing/CameraUtil.java b/camera/testing/src/main/java/androidx/camera/testing/CameraUtil.java index 9f70fcb6052..09c3e566362 100644 --- a/camera/testing/src/main/java/androidx/camera/testing/CameraUtil.java +++ b/camera/testing/src/main/java/androidx/camera/testing/CameraUtil.java @@ -141,7 +141,7 @@ public final class CameraUtil { UseCase... useCases) { camera.addOnlineUseCase(Arrays.asList(useCases)); for (UseCase useCase : useCases) { - useCase.attachCameraControl(cameraId, camera.getCameraControl()); + useCase.attachCameraControl(cameraId, camera.getCameraControlInternal()); camera.onUseCaseActive(useCase); } } diff --git a/camera/testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java b/camera/testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java index 98c1feb1839..6dd28a42db5 100644 --- a/camera/testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java +++ b/camera/testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java @@ -20,9 +20,10 @@ import android.text.TextUtils; import android.util.Log; import android.view.Surface; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.camera.core.BaseCamera; -import androidx.camera.core.CameraControl; +import androidx.camera.core.CameraControlInternal; import androidx.camera.core.CameraInfo; import androidx.camera.core.CaptureConfig; import androidx.camera.core.DeferrableSurface; @@ -42,7 +43,7 @@ import java.util.List; public class FakeCamera implements BaseCamera { private static final String TAG = "FakeCamera"; private static final String DEFAULT_CAMERA_ID = "0"; - private final CameraControl mCameraControl; + private final CameraControlInternal mCameraControlInternal; private final CameraInfo mCameraInfo; private String mCameraId; private UseCaseAttachState mUseCaseAttachState; @@ -63,17 +64,18 @@ public class FakeCamera implements BaseCamera { this(cameraId, new FakeCameraInfo(), /*cameraControl=*/null); } - public FakeCamera(CameraInfo cameraInfo, @Nullable CameraControl cameraControl) { + public FakeCamera(CameraInfo cameraInfo, @Nullable CameraControlInternal cameraControl) { this(DEFAULT_CAMERA_ID, cameraInfo, cameraControl); } public FakeCamera(String cameraId, CameraInfo cameraInfo, - @Nullable CameraControl cameraControl) { + @Nullable CameraControlInternal cameraControl) { mCameraInfo = cameraInfo; mCameraId = cameraId; mUseCaseAttachState = new UseCaseAttachState(cameraId); - mCameraControl = cameraControl == null ? new FakeCameraControl(this) : cameraControl; + mCameraControlInternal = cameraControl == null ? new FakeCameraControl(this) + : cameraControl; } @Override @@ -183,10 +185,11 @@ public class FakeCamera implements BaseCamera { updateCaptureSessionConfig(); } - // Returns fixed CameraControl instance in order to verify the instance is correctly attached. + // Returns fixed CameraControlInternal instance in order to verify the instance is correctly + // attached. @Override - public CameraControl getCameraControl() { - return mCameraControl; + public CameraControlInternal getCameraControlInternal() { + return mCameraControlInternal; } @Override @@ -195,13 +198,13 @@ public class FakeCamera implements BaseCamera { } @Override - public void onCameraControlUpdateSessionConfig(SessionConfig sessionConfig) { + public void onCameraControlUpdateSessionConfig(@NonNull SessionConfig sessionConfig) { mCameraControlSessionConfig = sessionConfig; updateCaptureSessionConfig(); } @Override - public void onCameraControlCaptureRequests(List<CaptureConfig> captureConfigs) { + public void onCameraControlCaptureRequests(@NonNull List<CaptureConfig> captureConfigs) { Log.d(TAG, "Capture requests submitted:\n " + TextUtils.join("\n ", captureConfigs)); } @@ -233,8 +236,8 @@ public class FakeCamera implements BaseCamera { validatingBuilder = mUseCaseAttachState.getActiveAndOnlineBuilder(); if (validatingBuilder.isValid()) { - // Apply CameraControl's SessionConfig to let CameraControl be able to control - // Repeating Request and process results. + // Apply CameraControlInternal's SessionConfig to let CameraControlInternal be able + // to control Repeating Request and process results. validatingBuilder.add(mCameraControlSessionConfig); mSessionConfig = validatingBuilder.build(); diff --git a/camera/testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java b/camera/testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java index 77cbcc69205..683f5fa8812 100644 --- a/camera/testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java +++ b/camera/testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java @@ -21,7 +21,8 @@ import android.graphics.Rect; import android.util.Log; import androidx.annotation.NonNull; -import androidx.camera.core.CameraControl; +import androidx.annotation.Nullable; +import androidx.camera.core.CameraControlInternal; import androidx.camera.core.CaptureConfig; import androidx.camera.core.FlashMode; import androidx.camera.core.OnFocusListener; @@ -31,9 +32,9 @@ import java.util.List; import java.util.concurrent.Executor; /** - * A fake implementation for the CameraControl interface. + * A fake implementation for the CameraControlInternal interface. */ -public final class FakeCameraControl implements CameraControl { +public final class FakeCameraControl implements CameraControlInternal { private static final String TAG = "FakeCameraControl"; private final ControlUpdateListener mControlUpdateListener; private final SessionConfig.Builder mSessionConfigBuilder = new SessionConfig.Builder(); @@ -46,7 +47,7 @@ public final class FakeCameraControl implements CameraControl { } @Override - public void setCropRegion(final Rect crop) { + public void setCropRegion(@Nullable final Rect crop) { Log.d(TAG, "setCropRegion(" + crop + ")"); } @@ -65,13 +66,14 @@ public final class FakeCameraControl implements CameraControl { Log.d(TAG, "focus(\n " + focus + ",\n " + metering + ")"); } + @NonNull @Override public FlashMode getFlashMode() { return mFlashMode; } @Override - public void setFlashMode(FlashMode flashMode) { + public void setFlashMode(@NonNull FlashMode flashMode) { mFlashMode = flashMode; Log.d(TAG, "setFlashMode(" + mFlashMode + ")"); } @@ -110,7 +112,7 @@ public final class FakeCameraControl implements CameraControl { } @Override - public void submitCaptureRequests(List<CaptureConfig> captureConfigs) { + public void submitCaptureRequests(@NonNull List<CaptureConfig> captureConfigs) { mControlUpdateListener.onCameraControlCaptureRequests(captureConfigs); } |