summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2023-08-17 16:51:49 -0700
committerXin Li <delphij@google.com>2023-08-17 16:51:49 -0700
commit84671535a80b9e539bce8b2f84021f1da2dafa2d (patch)
treed9fcf894623a722156bf9425ec22399dea661f53
parent106fc1baf9e9144376d6cd41798795e685acfbb0 (diff)
parentff47dc7f6fd6d2cb9250f413d3a1f19801006c1f (diff)
downloadCamera2-84671535a80b9e539bce8b2f84021f1da2dafa2d.tar.gz
Merge Android U (ab/10368041)tmp_amf_298295554
Bug: 291102124 Merged-In: I227e8d9e2ace18119a37ddb0c2c4ddf4c3be6209 Change-Id: If162efac9ca0fe5aa4000f0b95bfbafc08a70178
-rw-r--r--src/com/android/camera/CaptureModule.java53
-rw-r--r--src/com/android/camera/VideoModule.java2
-rw-r--r--src/com/android/camera/captureintent/state/StateOpeningCamera.java10
-rw-r--r--src/com/android/camera/one/OneCamera.java10
-rw-r--r--src/com/android/camera/one/OneCameraManager.java8
-rw-r--r--src/com/android/camera/one/v1/LegacyOneCameraManagerImpl.java6
-rw-r--r--src/com/android/camera/one/v2/Camera2OneCameraManagerImpl.java18
-rw-r--r--src/com/android/camera/one/v2/Camera2OneCameraOpenerImpl.java16
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) {