diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java index d48e20e128b9f..6baf91d720c3d 100644 --- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java @@ -34,6 +34,7 @@ import android.hardware.camera2.impl.CameraExtensionUtils; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.params.ExtensionSessionConfiguration; import android.hardware.camera2.params.StreamConfigurationMap; +import android.os.Binder; import android.os.ConditionVariable; import android.os.IBinder; import android.os.RemoteException; @@ -48,7 +49,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -346,28 +346,29 @@ public final class CameraExtensionCharacteristics { } } - public long registerClient(Context ctx) { + public boolean registerClient(Context ctx, IBinder token) { synchronized (mLock) { connectToProxyLocked(ctx); - if (mProxy != null) { - try { - return mProxy.registerClient(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to initialize extension! Extension service does " - + " not respond!"); - return -1; - } - } else { - return -1; + if (mProxy == null) { + return false; } + + try { + return mProxy.registerClient(token); + } catch (RemoteException e) { + Log.e(TAG, "Failed to initialize extension! Extension service does " + + " not respond!"); + } + + return false; } } - public void unregisterClient(long clientId) { + public void unregisterClient(IBinder token) { synchronized (mLock) { if (mProxy != null) { try { - mProxy.unregisterClient(clientId); + mProxy.unregisterClient(token); } catch (RemoteException e) { Log.e(TAG, "Failed to de-initialize extension! Extension service does" + " not respond!"); @@ -438,15 +439,15 @@ public final class CameraExtensionCharacteristics { /** * @hide */ - public static long registerClient(Context ctx) { - return CameraExtensionManagerGlobal.get().registerClient(ctx); + public static boolean registerClient(Context ctx, IBinder token) { + return CameraExtensionManagerGlobal.get().registerClient(ctx, token); } /** * @hide */ - public static void unregisterClient(long clientId) { - CameraExtensionManagerGlobal.get().unregisterClient(clientId); + public static void unregisterClient(IBinder token) { + CameraExtensionManagerGlobal.get().unregisterClient(token); } /** @@ -564,8 +565,9 @@ public final class CameraExtensionCharacteristics { */ public @NonNull List getSupportedExtensions() { ArrayList ret = new ArrayList<>(); - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#getSupportedExtensions:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { return Collections.unmodifiableList(ret); } @@ -576,7 +578,7 @@ public final class CameraExtensionCharacteristics { } } } finally { - unregisterClient(clientId); + unregisterClient(token); } return Collections.unmodifiableList(ret); @@ -599,8 +601,9 @@ public final class CameraExtensionCharacteristics { * supported device-specific extension */ public boolean isPostviewAvailable(@Extension int extension) { - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#isPostviewAvailable:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { throw new IllegalArgumentException("Unsupported extensions"); } @@ -623,7 +626,7 @@ public final class CameraExtensionCharacteristics { Log.e(TAG, "Failed to query the extension for postview availability! Extension " + "service does not respond!"); } finally { - unregisterClient(clientId); + unregisterClient(token); } return false; @@ -656,9 +659,9 @@ public final class CameraExtensionCharacteristics { @NonNull public List getPostviewSupportedSizes(@Extension int extension, @NonNull Size captureSize, int format) { - - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#getPostviewSupportedSizes:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { throw new IllegalArgumentException("Unsupported extensions"); } @@ -719,7 +722,7 @@ public final class CameraExtensionCharacteristics { + "service does not respond!"); return Collections.emptyList(); } finally { - unregisterClient(clientId); + unregisterClient(token); } } @@ -756,8 +759,9 @@ public final class CameraExtensionCharacteristics { // TODO: Revisit this code once the Extension preview processor output format // ambiguity is resolved in b/169799538. - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#getExtensionSupportedSizes:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { throw new IllegalArgumentException("Unsupported extensions"); } @@ -787,7 +791,7 @@ public final class CameraExtensionCharacteristics { + " not respond!"); return new ArrayList<>(); } finally { - unregisterClient(clientId); + unregisterClient(token); } } @@ -814,8 +818,9 @@ public final class CameraExtensionCharacteristics { public @NonNull List getExtensionSupportedSizes(@Extension int extension, int format) { try { - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#getExtensionSupportedSizes:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { throw new IllegalArgumentException("Unsupported extensions"); } @@ -867,7 +872,7 @@ public final class CameraExtensionCharacteristics { } } } finally { - unregisterClient(clientId); + unregisterClient(token); } } catch (RemoteException e) { Log.e(TAG, "Failed to query the extension supported sizes! Extension service does" @@ -888,7 +893,6 @@ public final class CameraExtensionCharacteristics { * @param format device-specific extension output format * @return the range of estimated minimal and maximal capture latency in milliseconds * or null if no capture latency info can be provided - * * @throws IllegalArgumentException in case of format different from {@link ImageFormat#JPEG} / * {@link ImageFormat#YUV_420_888}; or unsupported extension. */ @@ -903,8 +907,9 @@ public final class CameraExtensionCharacteristics { throw new IllegalArgumentException("Unsupported format: " + format); } - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#getEstimatedCaptureLatencyRangeMillis:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { throw new IllegalArgumentException("Unsupported extensions"); } @@ -952,7 +957,7 @@ public final class CameraExtensionCharacteristics { Log.e(TAG, "Failed to query the extension capture latency! Extension service does" + " not respond!"); } finally { - unregisterClient(clientId); + unregisterClient(token); } return null; @@ -968,8 +973,9 @@ public final class CameraExtensionCharacteristics { * @throws IllegalArgumentException in case of an unsupported extension. */ public boolean isCaptureProcessProgressAvailable(@Extension int extension) { - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#isCaptureProcessProgressAvailable:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { throw new IllegalArgumentException("Unsupported extensions"); } @@ -992,7 +998,7 @@ public final class CameraExtensionCharacteristics { Log.e(TAG, "Failed to query the extension progress callbacks! Extension service does" + " not respond!"); } finally { - unregisterClient(clientId); + unregisterClient(token); } return false; @@ -1013,8 +1019,9 @@ public final class CameraExtensionCharacteristics { */ @NonNull public Set getAvailableCaptureRequestKeys(@Extension int extension) { - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#getAvailableCaptureRequestKeys:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { throw new IllegalArgumentException("Unsupported extensions"); } @@ -1033,10 +1040,11 @@ public final class CameraExtensionCharacteristics { } else { Pair extenders = initializeExtension(extension); - extenders.second.onInit(mCameraId, mCharacteristicsMapNative.get(mCameraId)); + extenders.second.onInit(token, mCameraId, + mCharacteristicsMapNative.get(mCameraId)); extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId)); captureRequestMeta = extenders.second.getAvailableCaptureRequestKeys(); - extenders.second.onDeInit(); + extenders.second.onDeInit(token); } if (captureRequestMeta != null) { @@ -1067,7 +1075,7 @@ public final class CameraExtensionCharacteristics { } catch (RemoteException e) { throw new IllegalStateException("Failed to query the available capture request keys!"); } finally { - unregisterClient(clientId); + unregisterClient(token); } return Collections.unmodifiableSet(ret); @@ -1092,8 +1100,9 @@ public final class CameraExtensionCharacteristics { */ @NonNull public Set getAvailableCaptureResultKeys(@Extension int extension) { - long clientId = registerClient(mContext); - if (clientId < 0) { + final IBinder token = new Binder(TAG + "#getAvailableCaptureResultKeys:" + mCameraId); + boolean success = registerClient(mContext, token); + if (!success) { throw new IllegalArgumentException("Unsupported extensions"); } @@ -1111,10 +1120,11 @@ public final class CameraExtensionCharacteristics { } else { Pair extenders = initializeExtension(extension); - extenders.second.onInit(mCameraId, mCharacteristicsMapNative.get(mCameraId)); + extenders.second.onInit(token, mCameraId, + mCharacteristicsMapNative.get(mCameraId)); extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId)); captureResultMeta = extenders.second.getAvailableCaptureResultKeys(); - extenders.second.onDeInit(); + extenders.second.onDeInit(token); } if (captureResultMeta != null) { @@ -1126,7 +1136,7 @@ public final class CameraExtensionCharacteristics { } CameraCharacteristics resultChars = new CameraCharacteristics(captureResultMeta); Object crKey = CaptureResult.Key.class; - Class> crKeyTyped = (Class>)crKey; + Class> crKeyTyped = (Class>) crKey; ret.addAll(resultChars.getAvailableKeyList(CaptureResult.class, crKeyTyped, resultKeys, /*includeSynthetic*/ true)); @@ -1145,7 +1155,7 @@ public final class CameraExtensionCharacteristics { } catch (RemoteException e) { throw new IllegalStateException("Failed to query the available capture result keys!"); } finally { - unregisterClient(clientId); + unregisterClient(token); } return Collections.unmodifiableSet(ret); diff --git a/core/java/android/hardware/camera2/extension/ICameraExtensionsProxyService.aidl b/core/java/android/hardware/camera2/extension/ICameraExtensionsProxyService.aidl index b52c650086f4a..3b7d801afd859 100644 --- a/core/java/android/hardware/camera2/extension/ICameraExtensionsProxyService.aidl +++ b/core/java/android/hardware/camera2/extension/ICameraExtensionsProxyService.aidl @@ -20,11 +20,13 @@ import android.hardware.camera2.extension.IPreviewExtenderImpl; import android.hardware.camera2.extension.IImageCaptureExtenderImpl; import android.hardware.camera2.extension.IInitializeSessionCallback; +import android.os.IBinder; + /** @hide */ interface ICameraExtensionsProxyService { - long registerClient(); - void unregisterClient(long clientId); + boolean registerClient(in IBinder token); + void unregisterClient(in IBinder token); boolean advancedExtensionsSupported(); void initializeSession(in IInitializeSessionCallback cb); void releaseSession(); diff --git a/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl b/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl index 754f8f6625c9f..5a2241820534f 100644 --- a/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl +++ b/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl @@ -24,11 +24,13 @@ import android.hardware.camera2.extension.LatencyRange; import android.hardware.camera2.extension.Size; import android.hardware.camera2.extension.SizeList; +import android.os.IBinder; + /** @hide */ interface IImageCaptureExtenderImpl { - void onInit(in String cameraId, in CameraMetadataNative cameraCharacteristics); - void onDeInit(); + void onInit(in IBinder token, in String cameraId, in CameraMetadataNative cameraCharacteristics); + void onDeInit(in IBinder token); @nullable CaptureStageImpl onPresetSession(); @nullable CaptureStageImpl onEnableSession(); @nullable CaptureStageImpl onDisableSession(); diff --git a/core/java/android/hardware/camera2/extension/IPreviewExtenderImpl.aidl b/core/java/android/hardware/camera2/extension/IPreviewExtenderImpl.aidl index 01046d01233cc..9ea8a74070492 100644 --- a/core/java/android/hardware/camera2/extension/IPreviewExtenderImpl.aidl +++ b/core/java/android/hardware/camera2/extension/IPreviewExtenderImpl.aidl @@ -22,11 +22,13 @@ import android.hardware.camera2.extension.IPreviewImageProcessorImpl; import android.hardware.camera2.extension.IRequestUpdateProcessorImpl; import android.hardware.camera2.extension.SizeList; +import android.os.IBinder; + /** @hide */ interface IPreviewExtenderImpl { - void onInit(in String cameraId, in CameraMetadataNative cameraCharacteristics); - void onDeInit(); + void onInit(in IBinder token, in String cameraId, in CameraMetadataNative cameraCharacteristics); + void onDeInit(in IBinder token); @nullable CaptureStageImpl onPresetSession(); @nullable CaptureStageImpl onEnableSession(); @nullable CaptureStageImpl onDisableSession(); diff --git a/core/java/android/hardware/camera2/extension/ISessionProcessorImpl.aidl b/core/java/android/hardware/camera2/extension/ISessionProcessorImpl.aidl index 13b93a8c5e922..0581ec08a131a 100644 --- a/core/java/android/hardware/camera2/extension/ISessionProcessorImpl.aidl +++ b/core/java/android/hardware/camera2/extension/ISessionProcessorImpl.aidl @@ -25,13 +25,15 @@ import android.hardware.camera2.extension.LatencyPair; import android.hardware.camera2.extension.LatencyRange; import android.hardware.camera2.extension.OutputSurface; +import android.os.IBinder; + /** @hide */ interface ISessionProcessorImpl { - CameraSessionConfig initSession(in String cameraId, + CameraSessionConfig initSession(in IBinder token, in String cameraId, in Map charsMap, in OutputSurface previewSurface, in OutputSurface imageCaptureSurface, in OutputSurface postviewSurface); - void deInitSession(); + void deInitSession(in IBinder token); void onCaptureSessionStart(IRequestProcessorImpl requestProcessor); void onCaptureSessionEnd(); int startRepeating(in ICaptureCallback callback); diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java index 7e3acdbb3ed54..ae700a0a3c417 100644 --- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java @@ -60,6 +60,7 @@ import android.media.ImageReader; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; +import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.util.Size; @@ -79,7 +80,6 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes private final Executor mExecutor; private CameraDevice mCameraDevice; private final Map mCharacteristicsMap; - private final long mExtensionClientId; private final Handler mHandler; private final HandlerThread mHandlerThread; private final CameraExtensionSession.StateCallback mCallbacks; @@ -90,6 +90,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes private final HashMap mReaderMap = new HashMap<>(); private RequestProcessor mRequestProcessor = new RequestProcessor(); private final int mSessionId; + private final IBinder mToken; private Surface mClientRepeatingRequestSurface; private Surface mClientCaptureSurface; @@ -114,8 +115,9 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes @NonNull Map characteristicsMap, @NonNull Context ctx, @NonNull ExtensionSessionConfiguration config, int sessionId) throws CameraAccessException, RemoteException { - long clientId = CameraExtensionCharacteristics.registerClient(ctx); - if (clientId < 0) { + final IBinder token = new Binder(TAG + " : " + sessionId); + boolean success = CameraExtensionCharacteristics.registerClient(ctx, token); + if (!success) { throw new UnsupportedOperationException("Unsupported extension!"); } @@ -202,11 +204,10 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes IAdvancedExtenderImpl extender = CameraExtensionCharacteristics.initializeAdvancedExtension( config.getExtension()); extender.init(cameraId, characteristicsMapNative); - - CameraAdvancedExtensionSessionImpl ret = new CameraAdvancedExtensionSessionImpl(clientId, - extender, cameraDevice, characteristicsMapNative, repeatingRequestSurface, + CameraAdvancedExtensionSessionImpl ret = new CameraAdvancedExtensionSessionImpl(extender, + cameraDevice, characteristicsMapNative, repeatingRequestSurface, burstCaptureSurface, postviewSurface, config.getStateCallback(), - config.getExecutor(), sessionId); + config.getExecutor(), sessionId, token); ret.mStatsAggregator.setClientName(ctx.getOpPackageName()); ret.mStatsAggregator.setExtensionType(config.getExtension()); @@ -216,15 +217,13 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes return ret; } - private CameraAdvancedExtensionSessionImpl(long extensionClientId, - @NonNull IAdvancedExtenderImpl extender, + private CameraAdvancedExtensionSessionImpl(@NonNull IAdvancedExtenderImpl extender, @NonNull CameraDeviceImpl cameraDevice, Map characteristicsMap, @Nullable Surface repeatingRequestSurface, @Nullable Surface burstCaptureSurface, @Nullable Surface postviewSurface, @NonNull StateCallback callback, @NonNull Executor executor, - int sessionId) { - mExtensionClientId = extensionClientId; + int sessionId, @NonNull IBinder token) { mAdvancedExtender = extender; mCameraDevice = cameraDevice; mCharacteristicsMap = characteristicsMap; @@ -240,6 +239,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes mSessionClosed = false; mInitializeHandler = new InitializeSessionHandler(); mSessionId = sessionId; + mToken = token; mInterfaceLock = cameraDevice.mInterfaceLock; mStatsAggregator = new ExtensionSessionStatsAggregator(mCameraDevice.getId(), @@ -260,7 +260,8 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes OutputSurface postviewSurface = initializeParcelable(mClientPostviewSurface); mSessionProcessor = mAdvancedExtender.getSessionProcessor(); - CameraSessionConfig sessionConfig = mSessionProcessor.initSession(mCameraDevice.getId(), + CameraSessionConfig sessionConfig = mSessionProcessor.initSession(mToken, + mCameraDevice.getId(), mCharacteristicsMap, previewSurface, captureSurface, postviewSurface); List outputConfigs = sessionConfig.outputConfigs; ArrayList outputList = new ArrayList<>(); @@ -569,7 +570,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes if (!mSessionClosed) { mSessionProcessor.onCaptureSessionEnd(); } - mSessionProcessor.deInitSession(); + mSessionProcessor.deInitSession(mToken); } catch (RemoteException e) { Log.e(TAG, "Failed to de-initialize session processor, extension service" + " does not respond!") ; @@ -577,12 +578,10 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes mSessionProcessor = null; } - if (mExtensionClientId >= 0) { - CameraExtensionCharacteristics.unregisterClient(mExtensionClientId); - if (mInitialized || (mCaptureSession != null)) { - notifyClose = true; - CameraExtensionCharacteristics.releaseSession(); - } + CameraExtensionCharacteristics.unregisterClient(mToken); + if (mInitialized || (mCaptureSession != null)) { + notifyClose = true; + CameraExtensionCharacteristics.releaseSession(); } mInitialized = false; diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java index 9e95d4968d310..1db4808b64309 100644 --- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java @@ -56,6 +56,7 @@ import android.media.ImageWriter; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; +import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.util.LongSparseArray; @@ -79,7 +80,6 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { private final Executor mExecutor; private final CameraDevice mCameraDevice; - private final long mExtensionClientId; private final IImageCaptureExtenderImpl mImageExtender; private final IPreviewExtenderImpl mPreviewExtender; private final Handler mHandler; @@ -91,6 +91,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { private final Set mSupportedRequestKeys; private final Set mSupportedResultKeys; private final ExtensionSessionStatsAggregator mStatsAggregator; + private final IBinder mToken; private boolean mCaptureResultsSupported; private CameraCaptureSession mCaptureSession = null; @@ -136,8 +137,9 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { @NonNull ExtensionSessionConfiguration config, int sessionId) throws CameraAccessException, RemoteException { - long clientId = CameraExtensionCharacteristics.registerClient(ctx); - if (clientId < 0) { + final IBinder token = new Binder(TAG + " : " + sessionId); + boolean success = CameraExtensionCharacteristics.registerClient(ctx, token); + if (!success) { throw new UnsupportedOperationException("Unsupported extension!"); } @@ -225,15 +227,16 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } extenders.first.init(cameraId, characteristicsMap.get(cameraId).getNativeMetadata()); - extenders.first.onInit(cameraId, characteristicsMap.get(cameraId).getNativeMetadata()); + extenders.first.onInit(token, cameraId, + characteristicsMap.get(cameraId).getNativeMetadata()); extenders.second.init(cameraId, characteristicsMap.get(cameraId).getNativeMetadata()); - extenders.second.onInit(cameraId, characteristicsMap.get(cameraId).getNativeMetadata()); + extenders.second.onInit(token, cameraId, + characteristicsMap.get(cameraId).getNativeMetadata()); CameraExtensionSessionImpl session = new CameraExtensionSessionImpl( extenders.second, extenders.first, supportedPreviewSizes, - clientId, cameraDevice, repeatingRequestSurface, burstCaptureSurface, @@ -241,6 +244,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { config.getStateCallback(), config.getExecutor(), sessionId, + token, extensionChars.getAvailableCaptureRequestKeys(config.getExtension()), extensionChars.getAvailableCaptureResultKeys(config.getExtension())); @@ -255,7 +259,6 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { public CameraExtensionSessionImpl(@NonNull IImageCaptureExtenderImpl imageExtender, @NonNull IPreviewExtenderImpl previewExtender, @NonNull List previewSizes, - long extensionClientId, @NonNull android.hardware.camera2.impl.CameraDeviceImpl cameraDevice, @Nullable Surface repeatingRequestSurface, @Nullable Surface burstCaptureSurface, @@ -263,9 +266,9 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { @NonNull StateCallback callback, @NonNull Executor executor, int sessionId, + @NonNull IBinder token, @NonNull Set requestKeys, @Nullable Set resultKeys) { - mExtensionClientId = extensionClientId; mImageExtender = imageExtender; mPreviewExtender = previewExtender; mCameraDevice = cameraDevice; @@ -282,6 +285,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { mSessionClosed = false; mInitializeHandler = new InitializeSessionHandler(); mSessionId = sessionId; + mToken = token; mSupportedRequestKeys = requestKeys; mSupportedResultKeys = resultKeys; mCaptureResultsSupported = !resultKeys.isEmpty(); @@ -867,19 +871,17 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { mPreviewExtender.onDisableSession(); mImageExtender.onDisableSession(); } - mPreviewExtender.onDeInit(); - mImageExtender.onDeInit(); + mPreviewExtender.onDeInit(mToken); + mImageExtender.onDeInit(mToken); } catch (RemoteException e) { Log.e(TAG, "Failed to release extensions! Extension service does not" + " respond!"); } - if (mExtensionClientId >= 0) { - CameraExtensionCharacteristics.unregisterClient(mExtensionClientId); - if (mInitialized || (mCaptureSession != null)) { - notifyClose = true; - CameraExtensionCharacteristics.releaseSession(); - } + CameraExtensionCharacteristics.unregisterClient(mToken); + if (mInitialized || (mCaptureSession != null)) { + notifyClose = true; + CameraExtensionCharacteristics.releaseSession(); } mInitialized = false; diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java index c2ebddf00fb42..502ee4db80c83 100644 --- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java +++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java @@ -75,6 +75,7 @@ import android.util.Range; import android.util.Size; import android.view.Surface; +import androidx.annotation.NonNull; import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl; import androidx.camera.extensions.impl.AutoPreviewExtenderImpl; import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl; @@ -204,7 +205,7 @@ public class CameraExtensionsProxyService extends Service { * A per-process global camera extension manager instance, to track and * initialize/release extensions depending on client activity. */ - private static final class CameraExtensionManagerGlobal { + private static final class CameraExtensionManagerGlobal implements IBinder.DeathRecipient { private static final String TAG = "CameraExtensionManagerGlobal"; private final int EXTENSION_DELAY_MS = 1000; @@ -212,8 +213,9 @@ public class CameraExtensionsProxyService extends Service { private final HandlerThread mHandlerThread; private final Object mLock = new Object(); - private long mCurrentClientCount = 0; - private ArraySet mActiveClients = new ArraySet<>(); + private ArraySet mActiveClients = new ArraySet<>(); + private HashMap> mClientDeathRecipient = + new HashMap<>(); private IInitializeSessionCallback mInitializeCb = null; // Singleton instance @@ -314,8 +316,20 @@ public class CameraExtensionsProxyService extends Service { return GLOBAL_CAMERA_MANAGER; } - public long registerClient(Context ctx) { + public boolean registerClient(Context ctx, IBinder token) { synchronized (mLock) { + if (mActiveClients.contains(token)) { + Log.e(TAG, "Failed to register existing client!"); + return false; + } + + try { + token.linkToDeath(this, 0); + } catch (RemoteException e) { + Log.e(TAG, "Failed to link to binder token!"); + return false; + } + if (INIT_API_SUPPORTED) { if (mActiveClients.isEmpty()) { InitializerFuture status = new InitializerFuture(); @@ -327,47 +341,80 @@ public class CameraExtensionsProxyService extends Service { TimeUnit.MILLISECONDS); } catch (TimeoutException e) { Log.e(TAG, "Timed out while initializing camera extensions!"); - return -1; + return false; } if (!initSuccess) { Log.e(TAG, "Failed while initializing camera extensions!"); - return -1; + return false; } } } - long ret = mCurrentClientCount; - mCurrentClientCount++; - if (mCurrentClientCount < 0) { - mCurrentClientCount = 0; - } - mActiveClients.add(ret); + mActiveClients.add(token); + mClientDeathRecipient.put(token, new ArraySet<>()); - return ret; + return true; } } - public void unregisterClient(long clientId) { + public void unregisterClient(IBinder token) { synchronized (mLock) { - if (mActiveClients.remove(clientId) && mActiveClients.isEmpty() && - INIT_API_SUPPORTED) { - InitializerFuture status = new InitializerFuture(); - InitializerImpl.deinit(new ReleaseHandler(status), - new HandlerExecutor(mHandler)); - boolean releaseSuccess; - try { - releaseSuccess = status.get(EXTENSION_DELAY_MS, TimeUnit.MILLISECONDS); - } catch (TimeoutException e) { - Log.e(TAG, "Timed out while releasing camera extensions!"); - return; - } - if (!releaseSuccess) { - Log.e(TAG, "Failed while releasing camera extensions!"); + if (mActiveClients.remove(token)) { + token.unlinkToDeath(this, 0); + mClientDeathRecipient.remove(token); + if (mActiveClients.isEmpty() && INIT_API_SUPPORTED) { + InitializerFuture status = new InitializerFuture(); + InitializerImpl.deinit(new ReleaseHandler(status), + new HandlerExecutor(mHandler)); + boolean releaseSuccess; + try { + releaseSuccess = status.get(EXTENSION_DELAY_MS, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + Log.e(TAG, "Timed out while releasing camera extensions!"); + return; + } + if (!releaseSuccess) { + Log.e(TAG, "Failed while releasing camera extensions!"); + } } } } } + @Override + public void binderDied() { + // Do nothing, handled below + } + + @Override + public void binderDied(@NonNull IBinder who) { + synchronized (mLock) { + if (mClientDeathRecipient.containsKey(who)) { + mClientDeathRecipient.get(who).stream().forEach( + recipient -> recipient.binderDied(who)); + } + unregisterClient(who); + } + } + + public void registerDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) { + synchronized (mLock) { + if (mClientDeathRecipient.containsKey(token)) { + ArraySet recipients = mClientDeathRecipient.get(token); + recipients.add(recipient); + } + } + } + + public void unregisterDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) { + synchronized (mLock) { + if (mClientDeathRecipient.containsKey(token)) { + ArraySet recipients = mClientDeathRecipient.get(token); + recipients.remove(recipient); + } + } + } + private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { @@ -406,21 +453,35 @@ public class CameraExtensionsProxyService extends Service { /** * @hide */ - private static long registerClient(Context ctx) { + private static boolean registerClient(Context ctx, IBinder token) { if (!EXTENSIONS_PRESENT) { - return -1; + return false; } - return CameraExtensionManagerGlobal.get().registerClient(ctx); + return CameraExtensionManagerGlobal.get().registerClient(ctx, token); } /** * @hide */ - public static void unregisterClient(long clientId) { + public static void unregisterClient(IBinder token) { if (!EXTENSIONS_PRESENT) { return; } - CameraExtensionManagerGlobal.get().unregisterClient(clientId); + CameraExtensionManagerGlobal.get().unregisterClient(token); + } + + /** + * @hide + */ + private static void registerDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) { + CameraExtensionManagerGlobal.get().registerDeathRecipient(token, recipient); + } + + /** + * @hide + */ + private static void unregisterDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) { + CameraExtensionManagerGlobal.get().unregisterDeathRecipient(token, recipient); } /** @@ -649,13 +710,14 @@ public class CameraExtensionsProxyService extends Service { private class CameraExtensionsProxyServiceStub extends ICameraExtensionsProxyService.Stub { @Override - public long registerClient() { - return CameraExtensionsProxyService.registerClient(CameraExtensionsProxyService.this); + public boolean registerClient(IBinder token) { + return CameraExtensionsProxyService.registerClient(CameraExtensionsProxyService.this, + token); } @Override - public void unregisterClient(long clientId) { - CameraExtensionsProxyService.unregisterClient(clientId); + public void unregisterClient(IBinder token) { + CameraExtensionsProxyService.unregisterClient(token); } private boolean checkCameraPermission() { @@ -1192,16 +1254,18 @@ public class CameraExtensionsProxyService extends Service { } } - private class SessionProcessorImplStub extends ISessionProcessorImpl.Stub { + private class SessionProcessorImplStub extends ISessionProcessorImpl.Stub implements + IBinder.DeathRecipient { private final SessionProcessorImpl mSessionProcessor; private String mCameraId = null; + private IBinder mToken; public SessionProcessorImplStub(SessionProcessorImpl sessionProcessor) { mSessionProcessor = sessionProcessor; } @Override - public CameraSessionConfig initSession(String cameraId, + public CameraSessionConfig initSession(IBinder token, String cameraId, Map charsMapNative, OutputSurface previewSurface, OutputSurface imageCaptureSurface, OutputSurface postviewSurface) { OutputSurfaceImplStub outputPreviewSurfaceImpl = @@ -1253,12 +1317,14 @@ public class CameraExtensionsProxyService extends Service { ret.sessionParameter = initializeParcelableMetadata( sessionConfig.getSessionParameters(), cameraId); mCameraId = cameraId; - + mToken = token; + CameraExtensionsProxyService.registerDeathRecipient(mToken, this); return ret; } @Override - public void deInitSession() { + public void deInitSession(IBinder token) { + CameraExtensionsProxyService.unregisterDeathRecipient(mToken, this); mSessionProcessor.deInitSession(); } @@ -1330,6 +1396,11 @@ public class CameraExtensionsProxyService extends Service { return null; } + + @Override + public void binderDied() { + mSessionProcessor.deInitSession(); + } } private class OutputSurfaceConfigurationImplStub implements OutputSurfaceConfigurationImpl { @@ -1395,24 +1466,31 @@ public class CameraExtensionsProxyService extends Service { } } - private class PreviewExtenderImplStub extends IPreviewExtenderImpl.Stub { + private class PreviewExtenderImplStub extends IPreviewExtenderImpl.Stub implements + IBinder.DeathRecipient { private final PreviewExtenderImpl mPreviewExtender; private String mCameraId = null; + private boolean mSessionEnabled; + private IBinder mToken; public PreviewExtenderImplStub(PreviewExtenderImpl previewExtender) { mPreviewExtender = previewExtender; } @Override - public void onInit(String cameraId, CameraMetadataNative cameraCharacteristics) { + public void onInit(IBinder token, String cameraId, + CameraMetadataNative cameraCharacteristics) { mCameraId = cameraId; CameraCharacteristics chars = new CameraCharacteristics(cameraCharacteristics); mCameraManager.registerDeviceStateListener(chars); mPreviewExtender.onInit(cameraId, chars, CameraExtensionsProxyService.this); + mToken = token; + CameraExtensionsProxyService.registerDeathRecipient(mToken, this); } @Override - public void onDeInit() { + public void onDeInit(IBinder token) { + CameraExtensionsProxyService.unregisterDeathRecipient(mToken, this); mPreviewExtender.onDeInit(); } @@ -1423,11 +1501,13 @@ public class CameraExtensionsProxyService extends Service { @Override public CaptureStageImpl onEnableSession() { + mSessionEnabled = true; return initializeParcelable(mPreviewExtender.onEnableSession(), mCameraId); } @Override public CaptureStageImpl onDisableSession() { + mSessionEnabled = false; return initializeParcelable(mPreviewExtender.onDisableSession(), mCameraId); } @@ -1516,26 +1596,41 @@ public class CameraExtensionsProxyService extends Service { } return null; } + + @Override + public void binderDied() { + if (mSessionEnabled) { + mPreviewExtender.onDisableSession(); + } + mPreviewExtender.onDeInit(); + } } - private class ImageCaptureExtenderImplStub extends IImageCaptureExtenderImpl.Stub { + private class ImageCaptureExtenderImplStub extends IImageCaptureExtenderImpl.Stub implements + IBinder.DeathRecipient { private final ImageCaptureExtenderImpl mImageExtender; private String mCameraId = null; + private boolean mSessionEnabled; + private IBinder mToken; public ImageCaptureExtenderImplStub(ImageCaptureExtenderImpl imageExtender) { mImageExtender = imageExtender; } @Override - public void onInit(String cameraId, CameraMetadataNative cameraCharacteristics) { + public void onInit(IBinder token, String cameraId, + CameraMetadataNative cameraCharacteristics) { CameraCharacteristics chars = new CameraCharacteristics(cameraCharacteristics); mCameraManager.registerDeviceStateListener(chars); mImageExtender.onInit(cameraId, chars, CameraExtensionsProxyService.this); mCameraId = cameraId; + mToken = token; + CameraExtensionsProxyService.registerDeathRecipient(mToken, this); } @Override - public void onDeInit() { + public void onDeInit(IBinder token) { + CameraExtensionsProxyService.unregisterDeathRecipient(mToken, this); mImageExtender.onDeInit(); } @@ -1564,11 +1659,13 @@ public class CameraExtensionsProxyService extends Service { @Override public CaptureStageImpl onEnableSession() { + mSessionEnabled = true; return initializeParcelable(mImageExtender.onEnableSession(), mCameraId); } @Override public CaptureStageImpl onDisableSession() { + mSessionEnabled = false; return initializeParcelable(mImageExtender.onDisableSession(), mCameraId); } @@ -1737,6 +1834,14 @@ public class CameraExtensionsProxyService extends Service { return null; } + + @Override + public void binderDied() { + if (mSessionEnabled) { + mImageExtender.onDisableSession(); + } + mImageExtender.onDeInit(); + } } private class ProcessResultCallback implements ProcessResultImpl {