Merge "Camera: Avoid holding locks during extension initialization" am: 558b16bb25

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2454926

Change-Id: Iffa2d70b68d68d3bdb7253d9257bee5512f0c59a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot
2023-03-14 16:52:51 +00:00
committed by Automerger Merge Worker
2 changed files with 105 additions and 81 deletions

View File

@@ -98,15 +98,15 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
// Lock to synchronize cross-thread access to device public interface // Lock to synchronize cross-thread access to device public interface
final Object mInterfaceLock = new Object(); // access from this class and Session only! final Object mInterfaceLock;
/** /**
* @hide * @hide
*/ */
@RequiresPermission(android.Manifest.permission.CAMERA) @RequiresPermission(android.Manifest.permission.CAMERA)
public static CameraAdvancedExtensionSessionImpl createCameraAdvancedExtensionSession( public static CameraAdvancedExtensionSessionImpl createCameraAdvancedExtensionSession(
@NonNull CameraDevice cameraDevice, @NonNull Context ctx, @NonNull android.hardware.camera2.impl.CameraDeviceImpl cameraDevice,
@NonNull ExtensionSessionConfiguration config, int sessionId) @NonNull Context ctx, @NonNull ExtensionSessionConfiguration config, int sessionId)
throws CameraAccessException, RemoteException { throws CameraAccessException, RemoteException {
long clientId = CameraExtensionCharacteristics.registerClient(ctx); long clientId = CameraExtensionCharacteristics.registerClient(ctx);
if (clientId < 0) { if (clientId < 0) {
@@ -183,7 +183,8 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
} }
private CameraAdvancedExtensionSessionImpl(long extensionClientId, private CameraAdvancedExtensionSessionImpl(long extensionClientId,
@NonNull IAdvancedExtenderImpl extender, @NonNull CameraDevice cameraDevice, @NonNull IAdvancedExtenderImpl extender,
@NonNull android.hardware.camera2.impl.CameraDeviceImpl cameraDevice,
@Nullable Surface repeatingRequestSurface, @Nullable Surface burstCaptureSurface, @Nullable Surface repeatingRequestSurface, @Nullable Surface burstCaptureSurface,
@NonNull CameraExtensionSession.StateCallback callback, @NonNull Executor executor, @NonNull CameraExtensionSession.StateCallback callback, @NonNull Executor executor,
int sessionId) { int sessionId) {
@@ -200,6 +201,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
mInitialized = false; mInitialized = false;
mInitializeHandler = new InitializeSessionHandler(); mInitializeHandler = new InitializeSessionHandler();
mSessionId = sessionId; mSessionId = sessionId;
mInterfaceLock = cameraDevice.mInterfaceLock;
} }
/** /**
@@ -511,13 +513,14 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
public void onConfigured(@NonNull CameraCaptureSession session) { public void onConfigured(@NonNull CameraCaptureSession session) {
synchronized (mInterfaceLock) { synchronized (mInterfaceLock) {
mCaptureSession = session; mCaptureSession = session;
try { }
CameraExtensionCharacteristics.initializeSession(mInitializeHandler);
} catch (RemoteException e) { try {
Log.e(TAG, "Failed to initialize session! Extension service does" CameraExtensionCharacteristics.initializeSession(mInitializeHandler);
+ " not respond!"); } catch (RemoteException e) {
notifyConfigurationFailure(); Log.e(TAG, "Failed to initialize session! Extension service does"
} + " not respond!");
notifyConfigurationFailure();
} }
} }
} }
@@ -525,46 +528,56 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
private class InitializeSessionHandler extends IInitializeSessionCallback.Stub { private class InitializeSessionHandler extends IInitializeSessionCallback.Stub {
@Override @Override
public void onSuccess() { public void onSuccess() {
boolean status = true; mHandler.post(new Runnable() {
synchronized (mInterfaceLock) { @Override
try { public void run() {
if (mSessionProcessor != null) { boolean status = true;
mSessionProcessor.onCaptureSessionStart(mRequestProcessor); synchronized (mInterfaceLock) {
mInitialized = true; try {
} else { if (mSessionProcessor != null) {
Log.v(TAG, "Failed to start capture session, session released before " + mSessionProcessor.onCaptureSessionStart(mRequestProcessor);
"extension start!"); mInitialized = true;
status = false; } else {
mCaptureSession.close(); Log.v(TAG, "Failed to start capture session, session " +
" released before extension start!");
status = false;
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to start capture session,"
+ " extension service does not respond!");
status = false;
mInitialized = false;
}
} }
} catch (RemoteException e) {
Log.e(TAG, "Failed to start capture session,"
+ " extension service does not respond!");
status = false;
mCaptureSession.close();
}
}
if (status) { if (status) {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
mExecutor.execute( mExecutor.execute(() -> mCallbacks.onConfigured(
() -> mCallbacks.onConfigured(CameraAdvancedExtensionSessionImpl.this)); CameraAdvancedExtensionSessionImpl.this));
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
}
} else {
onFailure();
}
} }
} else { });
notifyConfigurationFailure();
}
} }
@Override @Override
public void onFailure() { public void onFailure() {
mCaptureSession.close(); mHandler.post(new Runnable() {
Log.e(TAG, "Failed to initialize proxy service session!" @Override
+ " This can happen when trying to configure multiple " public void run() {
+ "concurrent extension sessions!"); mCaptureSession.close();
notifyConfigurationFailure();
Log.e(TAG, "Failed to initialize proxy service session!"
+ " This can happen when trying to configure multiple "
+ "concurrent extension sessions!");
notifyConfigurationFailure();
}
});
} }
} }

View File

@@ -114,7 +114,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
private boolean mInternalRepeatingRequestEnabled = true; private boolean mInternalRepeatingRequestEnabled = true;
// Lock to synchronize cross-thread access to device public interface // Lock to synchronize cross-thread access to device public interface
final Object mInterfaceLock = new Object(); // access from this class and Session only! final Object mInterfaceLock;
private static int nativeGetSurfaceFormat(Surface surface) { private static int nativeGetSurfaceFormat(Surface surface) {
return SurfaceUtils.getSurfaceFormat(surface); return SurfaceUtils.getSurfaceFormat(surface);
@@ -125,7 +125,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
*/ */
@RequiresPermission(android.Manifest.permission.CAMERA) @RequiresPermission(android.Manifest.permission.CAMERA)
public static CameraExtensionSessionImpl createCameraExtensionSession( public static CameraExtensionSessionImpl createCameraExtensionSession(
@NonNull CameraDevice cameraDevice, @NonNull android.hardware.camera2.impl.CameraDeviceImpl cameraDevice,
@NonNull Context ctx, @NonNull Context ctx,
@NonNull ExtensionSessionConfiguration config, @NonNull ExtensionSessionConfiguration config,
int sessionId) int sessionId)
@@ -223,7 +223,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
@NonNull IPreviewExtenderImpl previewExtender, @NonNull IPreviewExtenderImpl previewExtender,
@NonNull List<Size> previewSizes, @NonNull List<Size> previewSizes,
long extensionClientId, long extensionClientId,
@NonNull CameraDevice cameraDevice, @NonNull android.hardware.camera2.impl.CameraDeviceImpl cameraDevice,
@Nullable Surface repeatingRequestSurface, @Nullable Surface repeatingRequestSurface,
@Nullable Surface burstCaptureSurface, @Nullable Surface burstCaptureSurface,
@NonNull StateCallback callback, @NonNull StateCallback callback,
@@ -249,6 +249,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
mSupportedRequestKeys = requestKeys; mSupportedRequestKeys = requestKeys;
mSupportedResultKeys = resultKeys; mSupportedResultKeys = resultKeys;
mCaptureResultsSupported = !resultKeys.isEmpty(); mCaptureResultsSupported = !resultKeys.isEmpty();
mInterfaceLock = cameraDevice.mInterfaceLock;
} }
private void initializeRepeatingRequestPipeline() throws RemoteException { private void initializeRepeatingRequestPipeline() throws RemoteException {
@@ -856,46 +857,56 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
private class InitializeSessionHandler extends IInitializeSessionCallback.Stub { private class InitializeSessionHandler extends IInitializeSessionCallback.Stub {
@Override @Override
public void onSuccess() { public void onSuccess() {
boolean status = true; mHandler.post(new Runnable() {
ArrayList<CaptureStageImpl> initialRequestList = @Override
compileInitialRequestList(); public void run() {
if (!initialRequestList.isEmpty()) { boolean status = true;
try { ArrayList<CaptureStageImpl> initialRequestList =
setInitialCaptureRequest(initialRequestList, compileInitialRequestList();
new InitialRequestHandler( if (!initialRequestList.isEmpty()) {
mRepeatingRequestImageCallback)); try {
} catch (CameraAccessException e) { setInitialCaptureRequest(initialRequestList,
Log.e(TAG, new InitialRequestHandler(
"Failed to initialize the initial capture " mRepeatingRequestImageCallback));
+ "request!"); } catch (CameraAccessException e) {
status = false; Log.e(TAG,
} "Failed to initialize the initial capture "
} else { + "request!");
try { status = false;
setRepeatingRequest(mPreviewExtender.getCaptureStage(), }
new PreviewRequestHandler(null, null, null, } else {
mRepeatingRequestImageCallback)); try {
} catch (CameraAccessException | RemoteException e) { setRepeatingRequest(mPreviewExtender.getCaptureStage(),
Log.e(TAG, new PreviewRequestHandler(null, null, null,
"Failed to initialize internal repeating " mRepeatingRequestImageCallback));
+ "request!"); } catch (CameraAccessException | RemoteException e) {
status = false; Log.e(TAG,
} "Failed to initialize internal repeating "
+ "request!");
status = false;
}
} }
if (!status) { if (!status) {
notifyConfigurationFailure(); notifyConfigurationFailure();
} }
}
});
} }
@Override @Override
public void onFailure() { public void onFailure() {
mCaptureSession.close(); mHandler.post(new Runnable() {
Log.e(TAG, "Failed to initialize proxy service session!" @Override
+ " This can happen when trying to configure multiple " public void run() {
+ "concurrent extension sessions!"); mCaptureSession.close();
notifyConfigurationFailure(); Log.e(TAG, "Failed to initialize proxy service session!"
+ " This can happen when trying to configure multiple "
+ "concurrent extension sessions!");
notifyConfigurationFailure();
}
});
} }
} }