diff options
author | Xin Li <delphij@google.com> | 2023-08-17 16:51:49 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2023-08-17 16:51:49 -0700 |
commit | 84671535a80b9e539bce8b2f84021f1da2dafa2d (patch) | |
tree | d9fcf894623a722156bf9425ec22399dea661f53 | |
parent | 106fc1baf9e9144376d6cd41798795e685acfbb0 (diff) | |
parent | ff47dc7f6fd6d2cb9250f413d3a1f19801006c1f (diff) | |
download | Camera2-84671535a80b9e539bce8b2f84021f1da2dafa2d.tar.gz |
Merge Android U (ab/10368041)tmp_amf_298295554
Bug: 291102124
Merged-In: I227e8d9e2ace18119a37ddb0c2c4ddf4c3be6209
Change-Id: If162efac9ca0fe5aa4000f0b95bfbafc08a70178
8 files changed, 118 insertions, 5 deletions
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java index 1068bcf52..32417f60e 100644 --- a/src/com/android/camera/CaptureModule.java +++ b/src/com/android/camera/CaptureModule.java @@ -91,6 +91,9 @@ import com.android.camera2.R; import com.android.ex.camera2.portability.CameraAgent.CameraProxy; import com.google.common.logging.eventprotos; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -110,7 +113,8 @@ public class CaptureModule extends CameraModule implements OneCamera.PictureCallback, OneCamera.FocusStateListener, OneCamera.ReadyStateChangedListener, - RemoteCameraModule { + RemoteCameraModule, + OneCameraManager.AvailabilityCallback { private static final Tag TAG = new Tag("CaptureModule"); /** Enable additional debug output. */ @@ -168,6 +172,9 @@ public class CaptureModule extends CameraModule implements private OneCameraCharacteristics mCameraCharacteristics; final private PreviewTransformCalculator mPreviewTransformCalculator; + private ScheduledExecutorService mOnCameraAccessService; + private ScheduledFuture mOnCameraAccessFuture; + /** The listener to listen events from the CaptureModuleUI. */ private final CaptureModuleUI.CaptureModuleUIListener mUIListener = new CaptureModuleUI.CaptureModuleUIListener() { @@ -405,12 +412,14 @@ public class CaptureModule extends CameraModule implements thread.start(); mCameraHandler = new Handler(thread.getLooper()); mOneCameraOpener = mAppController.getCameraOpener(); + mOnCameraAccessService = Executors.newSingleThreadScheduledExecutor(); try { mOneCameraManager = OneCameraModule.provideOneCameraManager(); } catch (OneCameraException e) { Log.e(TAG, "Unable to provide a OneCameraManager. ", e); } + mOneCameraManager.setAvailabilityCallback(this, mCameraHandler); mDisplayRotation = CameraUtil.getDisplayRotation(activity); mCameraFacing = getFacingFromCameraId( mSettingsManager.getInteger(mAppController.getModuleScope(), Keys.KEY_CAMERA_ID)); @@ -503,6 +512,27 @@ public class CaptureModule extends CameraModule implements } } + @Override + public void onCameraAccessPrioritiesChanged() { + Log.d(TAG, "onCameraAccessPrioritiesChanged"); + Runnable runnable = () -> { + mMainThread.execute(() -> { + if (!mPaused && mCamera == null && !mAppController.isPaused()) { + openCameraAndStartPreview(); + } + }); + }; + + // onCameraAccessPrioritiesChanged callbacks come in rapid fire due to the way process oom + // scores are updated. To avoid redundantly opening the camera, wait for 300 ms of silence + // before trying on the main thread. + if (mOnCameraAccessFuture != null) { + mOnCameraAccessFuture.cancel(false); + } + mOnCameraAccessFuture = mOnCameraAccessService.schedule(runnable, 300, + TimeUnit.MILLISECONDS); + } + private void decorateSessionAtCaptureTime(CaptureSession session) { String flashSetting = @@ -1393,6 +1423,27 @@ public class CaptureModule extends CameraModule implements } @Override + public void onCameraInUse() { + Log.w(TAG, "Camera in use."); + if (mCamera != null) { + mCamera.close(); + } + mCamera = null; + mCameraOpenCloseLock.release(); + } + + @Override + public void onCameraInterrupted() { + Log.w(TAG, "Camera disconnected during active session."); + AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { + @Override + public void run() { + closeCamera(); + } + }); + } + + @Override public void onCameraClosed() { mCamera = null; mCameraOpenCloseLock.release(); diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java index 038deb197..68c68d6a1 100644 --- a/src/com/android/camera/VideoModule.java +++ b/src/com/android/camera/VideoModule.java @@ -858,7 +858,7 @@ public class VideoModule extends CameraModule intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); intentFilter.addDataScheme("file"); mReceiver = new MyBroadcastReceiver(); - mActivity.registerReceiver(mReceiver, intentFilter); + mActivity.registerReceiver(mReceiver, intentFilter, Context.RECEIVER_EXPORTED); } private void setDisplayOrientation() { diff --git a/src/com/android/camera/captureintent/state/StateOpeningCamera.java b/src/com/android/camera/captureintent/state/StateOpeningCamera.java index 1b27c6c21..91dc06c24 100644 --- a/src/com/android/camera/captureintent/state/StateOpeningCamera.java +++ b/src/com/android/camera/captureintent/state/StateOpeningCamera.java @@ -78,11 +78,21 @@ public final class StateOpeningCamera extends StateImpl { } @Override + public void onCameraInUse() { + getStateMachine().processEvent(new EventOnOpenCameraFailed()); + } + + @Override public void onCameraClosed() { // Not used anymore. } @Override + public void onCameraInterrupted() { + // Not used. + } + + @Override public void onCameraOpened(@Nonnull final OneCamera camera) { getStateMachine().processEvent(new EventOnOpenCameraSucceeded(camera)); } diff --git a/src/com/android/camera/one/OneCamera.java b/src/com/android/camera/one/OneCamera.java index 07c368945..c56bac48c 100644 --- a/src/com/android/camera/one/OneCamera.java +++ b/src/com/android/camera/one/OneCamera.java @@ -89,10 +89,20 @@ public interface OneCamera { public void onFailure(); /** + * Called if the camera is currently being used by a higher priority application. + **/ + public void onCameraInUse(); + + /** * Called if the camera is closed or disconnected while attempting to * open. */ public void onCameraClosed(); + + /** + * Called if the camera is disconnected after successfully opening + */ + public void onCameraInterrupted(); } /** diff --git a/src/com/android/camera/one/OneCameraManager.java b/src/com/android/camera/one/OneCameraManager.java index d17188c25..26b2e9f69 100644 --- a/src/com/android/camera/one/OneCameraManager.java +++ b/src/com/android/camera/one/OneCameraManager.java @@ -16,6 +16,8 @@ package com.android.camera.one; +import android.os.Handler; + import com.android.camera.device.CameraId; import com.android.camera.one.OneCamera.Facing; @@ -59,6 +61,12 @@ public interface OneCameraManager { public OneCameraCharacteristics getOneCameraCharacteristics(CameraId cameraId) throws OneCameraAccessException; + public void setAvailabilityCallback(AvailabilityCallback callback, Handler handler); + + public interface AvailabilityCallback { + public void onCameraAccessPrioritiesChanged(); + } + public static class Factory { } diff --git a/src/com/android/camera/one/v1/LegacyOneCameraManagerImpl.java b/src/com/android/camera/one/v1/LegacyOneCameraManagerImpl.java index 68f66a18d..a72a27fcf 100644 --- a/src/com/android/camera/one/v1/LegacyOneCameraManagerImpl.java +++ b/src/com/android/camera/one/v1/LegacyOneCameraManagerImpl.java @@ -17,6 +17,7 @@ package com.android.camera.one.v1; import android.hardware.Camera; +import android.os.Handler; import com.android.camera.debug.Log; import com.android.camera.debug.Log.Tag; @@ -160,6 +161,11 @@ public class LegacyOneCameraManagerImpl implements OneCameraManager { return null; } + @Override + public void setAvailabilityCallback(AvailabilityCallback callback, Handler handler) { + // Do nothing + } + public OneCameraCharacteristics computeCameraCharacteristics(CameraId key) throws OneCameraAccessException { OneCameraCharacteristics characteristics; diff --git a/src/com/android/camera/one/v2/Camera2OneCameraManagerImpl.java b/src/com/android/camera/one/v2/Camera2OneCameraManagerImpl.java index d1e0b5b8d..be5ddc93c 100644 --- a/src/com/android/camera/one/v2/Camera2OneCameraManagerImpl.java +++ b/src/com/android/camera/one/v2/Camera2OneCameraManagerImpl.java @@ -22,6 +22,7 @@ import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraManager; import android.os.Build.VERSION_CODES; +import android.os.Handler; import com.android.camera.debug.Log; import com.android.camera.debug.Log.Tag; @@ -42,7 +43,8 @@ import javax.annotation.Nonnull; * Pick camera ids from a list of devices based on defined characteristics. */ @TargetApi(VERSION_CODES.LOLLIPOP) -public class Camera2OneCameraManagerImpl implements OneCameraManager { +public class Camera2OneCameraManagerImpl extends CameraManager.AvailabilityCallback + implements OneCameraManager { private static final Tag TAG = new Tag("Camera2OneCamMgr"); /** * Create a new camera2 api hardware manager. @@ -65,6 +67,7 @@ public class Camera2OneCameraManagerImpl implements OneCameraManager { private final CameraManager mCameraManager; private Hashtable<Facing, String> mCameraFacingCache = new Hashtable<Facing, String>(); + private AvailabilityCallback mAvailabilityCallback; public Camera2OneCameraManagerImpl(CameraManager cameraManger) { mCameraManager = cameraManger; @@ -122,6 +125,12 @@ public class Camera2OneCameraManagerImpl implements OneCameraManager { return new OneCameraCharacteristicsImpl(getCameraCharacteristics(key)); } + @Override + public void setAvailabilityCallback(AvailabilityCallback callback, Handler handler) { + mAvailabilityCallback = callback; + mCameraManager.registerAvailabilityCallback(this, handler); + } + public CameraCharacteristics getCameraCharacteristics( @Nonnull CameraId key) throws OneCameraAccessException { @@ -132,6 +141,13 @@ public class Camera2OneCameraManagerImpl implements OneCameraManager { } } + @Override + public void onCameraAccessPrioritiesChanged() { + if (mAvailabilityCallback != null) { + mAvailabilityCallback.onCameraAccessPrioritiesChanged(); + } + } + /** Returns the ID of the first camera facing the given direction. */ private String findCameraId(Facing facing) { String id = mCameraFacingCache.get(facing); diff --git a/src/com/android/camera/one/v2/Camera2OneCameraOpenerImpl.java b/src/com/android/camera/one/v2/Camera2OneCameraOpenerImpl.java index 3529310e8..f0a0ce637 100644 --- a/src/com/android/camera/one/v2/Camera2OneCameraOpenerImpl.java +++ b/src/com/android/camera/one/v2/Camera2OneCameraOpenerImpl.java @@ -131,6 +131,9 @@ public class Camera2OneCameraOpenerImpl implements OneCameraOpener { // then we must call close. device.close(); openCallback.onCameraClosed(); + } else { + // Disconnected during active session + openCallback.onCameraInterrupted(); } } @@ -144,7 +147,12 @@ public class Camera2OneCameraOpenerImpl implements OneCameraOpener { @Override public void onError(CameraDevice device, int error) { - if (isFirstCallback) { + if (error == CameraDevice.StateCallback.ERROR_CAMERA_IN_USE) { + // Tolerate ERROR_CAMERA_IN_USE for split-screen. + isFirstCallback = false; + device.close(); + openCallback.onCameraInUse(); + } else if (isFirstCallback) { isFirstCallback = false; device.close(); openCallback.onFailure(); @@ -197,7 +205,11 @@ public class Camera2OneCameraOpenerImpl implements OneCameraOpener { handler.post(new Runnable() { @Override public void run() { - openCallback.onFailure(); + if (ex.getReason() == CameraAccessException.CAMERA_IN_USE) { + openCallback.onCameraInUse(); + } else { + openCallback.onFailure(); + } } }); } catch (UnsupportedOperationException ex) { |