Camera: Avoid possible deadlock when closing advanced extension session
The advanced extension session request processor must not hold the 'mInterfaceLock' when calling the camera device implementation as it could result in a deadlock with the camera device close that can run at the same time and try to acquire the same locks in reverse order. The request processor will only read from 'mCameraConfigMap' which is initialized only once during session setup and will not change during the session lifetime. A sample stack trace will look like this: Service thread: 1) android.hardware.camera2.impl.CameraCaptureSessionImpl.stopRepeating 2) android.hardware.camera2.impl.CameraAdvancedExtensionSessionImpl$RequestProcessor.stopRepeating Client thread: 1) android.hardware.camera2.impl.CameraAdvancedExtensionSessionImpl.release 2) android.hardware.camera2.impl.CameraDeviceImpl.close Bug: 202074988 Test: Manual using application, Camera CTS Change-Id: If992667a7d7e54be5bea1fcc4b1d71ec1b895ca0
This commit is contained in:
@@ -873,21 +873,19 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
|
||||
@Override
|
||||
public int submitBurst(List<Request> requests, IRequestCallback callback) {
|
||||
int seqId = -1;
|
||||
synchronized (mInterfaceLock) {
|
||||
try {
|
||||
CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
|
||||
ArrayList<CaptureRequest> captureRequests = new ArrayList<>();
|
||||
for (Request request : requests) {
|
||||
captureRequests.add(initializeCaptureRequest(mCameraDevice, request,
|
||||
mCameraConfigMap));
|
||||
}
|
||||
seqId = mCaptureSession.captureBurstRequests(captureRequests,
|
||||
new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed to submit capture requests!");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Capture session closed!");
|
||||
try {
|
||||
CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
|
||||
ArrayList<CaptureRequest> captureRequests = new ArrayList<>();
|
||||
for (Request request : requests) {
|
||||
captureRequests.add(initializeCaptureRequest(mCameraDevice, request,
|
||||
mCameraConfigMap));
|
||||
}
|
||||
seqId = mCaptureSession.captureBurstRequests(captureRequests,
|
||||
new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed to submit capture requests!");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Capture session closed!");
|
||||
}
|
||||
|
||||
return seqId;
|
||||
@@ -896,18 +894,16 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
|
||||
@Override
|
||||
public int setRepeating(Request request, IRequestCallback callback) {
|
||||
int seqId = -1;
|
||||
synchronized (mInterfaceLock) {
|
||||
try {
|
||||
CaptureRequest repeatingRequest = initializeCaptureRequest(mCameraDevice,
|
||||
request, mCameraConfigMap);
|
||||
CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
|
||||
seqId = mCaptureSession.setSingleRepeatingRequest(repeatingRequest,
|
||||
new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed to enable repeating request!");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Capture session closed!");
|
||||
}
|
||||
try {
|
||||
CaptureRequest repeatingRequest = initializeCaptureRequest(mCameraDevice,
|
||||
request, mCameraConfigMap);
|
||||
CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
|
||||
seqId = mCaptureSession.setSingleRepeatingRequest(repeatingRequest,
|
||||
new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed to enable repeating request!");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Capture session closed!");
|
||||
}
|
||||
|
||||
return seqId;
|
||||
@@ -915,27 +911,23 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
|
||||
|
||||
@Override
|
||||
public void abortCaptures() {
|
||||
synchronized (mInterfaceLock) {
|
||||
try {
|
||||
mCaptureSession.abortCaptures();
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed during capture abort!");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Capture session closed!");
|
||||
}
|
||||
try {
|
||||
mCaptureSession.abortCaptures();
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed during capture abort!");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Capture session closed!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopRepeating() {
|
||||
synchronized (mInterfaceLock) {
|
||||
try {
|
||||
mCaptureSession.stopRepeating();
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed during repeating capture stop!");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Capture session closed!");
|
||||
}
|
||||
try {
|
||||
mCaptureSession.stopRepeating();
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed during repeating capture stop!");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Capture session closed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user