Merge "Camera: release extension when extension app crash" into udc-qpr-dev

This commit is contained in:
Treehugger Robot
2023-06-28 19:59:49 +00:00
committed by Android (Google) Code Review
8 changed files with 266 additions and 142 deletions

View File

@@ -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<Integer> getSupportedExtensions() {
ArrayList<Integer> 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<Size> 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<Size> 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<CaptureRequest.Key> 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<IPreviewExtenderImpl, IImageCaptureExtenderImpl> 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<CaptureResult.Key> 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<IPreviewExtenderImpl, IImageCaptureExtenderImpl> 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<CaptureResult.Key<?>> crKeyTyped = (Class<CaptureResult.Key<?>>)crKey;
Class<CaptureResult.Key<?>> crKeyTyped = (Class<CaptureResult.Key<?>>) 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);

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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<String, CameraMetadataNative> 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);

View File

@@ -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<String, CameraMetadataNative> 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<Integer, ImageReader> 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<String, CameraCharacteristics> 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<String, CameraMetadataNative> 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<CameraOutputConfig> outputConfigs = sessionConfig.outputConfigs;
ArrayList<OutputConfiguration> 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;

View File

@@ -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<CaptureRequest.Key> mSupportedRequestKeys;
private final Set<CaptureResult.Key> 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<Size> 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<CaptureRequest.Key> requestKeys,
@Nullable Set<CaptureResult.Key> 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;

View File

@@ -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<Long> mActiveClients = new ArraySet<>();
private ArraySet<IBinder> mActiveClients = new ArraySet<>();
private HashMap<IBinder, ArraySet<IBinder.DeathRecipient>> 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<IBinder.DeathRecipient> recipients = mClientDeathRecipient.get(token);
recipients.add(recipient);
}
}
}
public void unregisterDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) {
synchronized (mLock) {
if (mClientDeathRecipient.containsKey(token)) {
ArraySet<IBinder.DeathRecipient> 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<String, CameraMetadataNative> 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 {