Camera: Add logic to switch between vendor and fallback extension impl
- Enables extensions to switch to a fallback software implementation
if the vendor does not support an extension that is equipped with a
fallback
- Changes the way extensions connect to the proxy service by enabling
a connection per extension. This allows multiple proxy service
connections simultaneously.
Test: Camera CTS Test
Bug: 302582551
Change-Id: I25b4ee7089e4c1e83cde51854322f32d4176e8bb
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index 7abe821..3b10e0d 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -19,7 +19,9 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
@@ -40,6 +42,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.util.IntArray;
import android.util.Log;
import android.util.Pair;
@@ -53,6 +56,7 @@
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;
@@ -243,16 +247,19 @@
private static final String PROXY_SERVICE_NAME =
"com.android.cameraextensions.CameraExtensionsProxyService";
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ private static final int FALLBACK_PACKAGE_NAME =
+ com.android.internal.R.string.config_extensionFallbackPackageName;
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ private static final int FALLBACK_SERVICE_NAME =
+ com.android.internal.R.string.config_extensionFallbackServiceName;
+
// Singleton instance
private static final CameraExtensionManagerGlobal GLOBAL_CAMERA_MANAGER =
new CameraExtensionManagerGlobal();
private final Object mLock = new Object();
private final int PROXY_SERVICE_DELAY_MS = 2000;
- private InitializerFuture mInitFuture = null;
- private ServiceConnection mConnection = null;
- private int mConnectionCount = 0;
- private ICameraExtensionsProxyService mProxy = null;
- private boolean mSupportsAdvancedExtensions = false;
+ private ExtensionConnectionManager mConnectionManager = new ExtensionConnectionManager();
// Singleton, don't allow construction
private CameraExtensionManagerGlobal() {}
@@ -261,17 +268,17 @@
return GLOBAL_CAMERA_MANAGER;
}
- private void releaseProxyConnectionLocked(Context ctx) {
- if (mConnection != null ) {
- ctx.unbindService(mConnection);
- mConnection = null;
- mProxy = null;
- mConnectionCount = 0;
+ private void releaseProxyConnectionLocked(Context ctx, int extension) {
+ if (mConnectionManager.getConnection(extension) != null) {
+ ctx.unbindService(mConnectionManager.getConnection(extension));
+ mConnectionManager.setConnection(extension, null);
+ mConnectionManager.setProxy(extension, null);
+ mConnectionManager.resetConnectionCount(extension);
}
}
- private void connectToProxyLocked(Context ctx) {
- if (mConnection == null) {
+ private void connectToProxyLocked(Context ctx, int extension, boolean useFallback) {
+ if (mConnectionManager.getConnection(extension) == null) {
Intent intent = new Intent();
intent.setClassName(PROXY_PACKAGE_NAME, PROXY_SERVICE_NAME);
String vendorProxyPackage = SystemProperties.get(
@@ -287,34 +294,55 @@
+ vendorProxyService);
intent.setClassName(vendorProxyPackage, vendorProxyService);
}
- mInitFuture = new InitializerFuture();
- mConnection = new ServiceConnection() {
+
+ if (Flags.concertMode() && useFallback) {
+ String packageName = ctx.getResources().getString(FALLBACK_PACKAGE_NAME);
+ String serviceName = ctx.getResources().getString(FALLBACK_SERVICE_NAME);
+
+ if (!packageName.isEmpty() && !serviceName.isEmpty()) {
+ Log.v(TAG,
+ "Choosing the fallback software implementation package: "
+ + packageName);
+ Log.v(TAG,
+ "Choosing the fallback software implementation service: "
+ + serviceName);
+ intent.setClassName(packageName, serviceName);
+ }
+ }
+
+ InitializerFuture initFuture = new InitializerFuture();
+ ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName component) {
- mConnection = null;
- mProxy = null;
+ mConnectionManager.setConnection(extension, null);
+ mConnectionManager.setProxy(extension, null);
}
@Override
public void onServiceConnected(ComponentName component, IBinder binder) {
- mProxy = ICameraExtensionsProxyService.Stub.asInterface(binder);
- if (mProxy == null) {
+ ICameraExtensionsProxyService proxy =
+ ICameraExtensionsProxyService.Stub.asInterface(binder);
+ mConnectionManager.setProxy(extension, proxy);
+ if (mConnectionManager.getProxy(extension) == null) {
throw new IllegalStateException("Camera Proxy service is null");
}
try {
- mSupportsAdvancedExtensions = mProxy.advancedExtensionsSupported();
+ mConnectionManager.setAdvancedExtensionsSupported(extension,
+ mConnectionManager.getProxy(extension)
+ .advancedExtensionsSupported());
} catch (RemoteException e) {
Log.e(TAG, "Remote IPC failed!");
}
- mInitFuture.setStatus(true);
+ initFuture.setStatus(true);
}
};
ctx.bindService(intent, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT |
Context.BIND_ABOVE_CLIENT | Context.BIND_NOT_VISIBLE,
- android.os.AsyncTask.THREAD_POOL_EXECUTOR, mConnection);
+ android.os.AsyncTask.THREAD_POOL_EXECUTOR, connection);
+ mConnectionManager.setConnection(extension, connection);
try {
- mInitFuture.get(PROXY_SERVICE_DELAY_MS, TimeUnit.MILLISECONDS);
+ initFuture.get(PROXY_SERVICE_DELAY_MS, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
Log.e(TAG, "Timed out while initializing proxy service!");
}
@@ -366,64 +394,102 @@
}
}
- public boolean registerClient(Context ctx, IBinder token) {
+ public boolean registerClientHelper(Context ctx, IBinder token, int extension,
+ boolean useFallback) {
synchronized (mLock) {
boolean ret = false;
- connectToProxyLocked(ctx);
- if (mProxy == null) {
+ connectToProxyLocked(ctx, extension, useFallback);
+ if (mConnectionManager.getProxy(extension) == null) {
return false;
}
- mConnectionCount++;
+ mConnectionManager.incrementConnectionCount(extension);
try {
- ret = mProxy.registerClient(token);
+ ret = mConnectionManager.getProxy(extension).registerClient(token);
} catch (RemoteException e) {
Log.e(TAG, "Failed to initialize extension! Extension service does "
+ " not respond!");
}
if (!ret) {
- mConnectionCount--;
+ mConnectionManager.decrementConnectionCount(extension);
}
- if (mConnectionCount <= 0) {
- releaseProxyConnectionLocked(ctx);
+ if (mConnectionManager.getConnectionCount(extension) <= 0) {
+ releaseProxyConnectionLocked(ctx, extension);
}
return ret;
}
}
- public void unregisterClient(Context ctx, IBinder token) {
+ @SuppressLint("NonUserGetterCalled")
+ public boolean registerClient(Context ctx, IBinder token, int extension,
+ String cameraId, Map<String, CameraMetadataNative> characteristicsMapNative) {
+ boolean ret = registerClientHelper(ctx, token, extension, false /*useFallback*/);
+
+ if (Flags.concertMode()) {
+ // Check if user enabled fallback impl
+ ContentResolver resolver = ctx.getContentResolver();
+ int userEnabled = Settings.Secure.getInt(resolver,
+ Settings.Secure.CAMERA_EXTENSIONS_FALLBACK, 1);
+
+ boolean vendorImpl = true;
+ if (ret && (mConnectionManager.getProxy(extension) != null) && (userEnabled == 1)) {
+ // At this point, we are connected to either CameraExtensionsProxyService or
+ // the vendor extension proxy service. If the vendor does not support the
+ // extension, unregisterClient and re-register client with the proxy service
+ // containing the fallback impl
+ vendorImpl = isExtensionSupported(cameraId, extension,
+ characteristicsMapNative);
+ }
+
+ if (!vendorImpl) {
+ unregisterClient(ctx, token, extension);
+ ret = registerClientHelper(ctx, token, extension, true /*useFallback*/);
+
+ }
+ }
+
+ return ret;
+ }
+
+ public void unregisterClient(Context ctx, IBinder token, int extension) {
synchronized (mLock) {
- if (mProxy != null) {
+ if (mConnectionManager.getProxy(extension) != null) {
try {
- mProxy.unregisterClient(token);
+ mConnectionManager.getProxy(extension).unregisterClient(token);
} catch (RemoteException e) {
Log.e(TAG, "Failed to de-initialize extension! Extension service does"
+ " not respond!");
} finally {
- mConnectionCount--;
- if (mConnectionCount <= 0) {
- releaseProxyConnectionLocked(ctx);
+ mConnectionManager.decrementConnectionCount(extension);
+ if (mConnectionManager.getConnectionCount(extension) <= 0) {
+ releaseProxyConnectionLocked(ctx, extension);
}
}
}
}
}
- public void initializeSession(IInitializeSessionCallback cb) throws RemoteException {
+ public void initializeSession(IInitializeSessionCallback cb, int extension)
+ throws RemoteException {
synchronized (mLock) {
- if (mProxy != null) {
- mProxy.initializeSession(cb);
+ if (mConnectionManager.getProxy(extension) != null
+ && !mConnectionManager.isSessionInitialized()) {
+ mConnectionManager.getProxy(extension).initializeSession(cb);
+ mConnectionManager.setSessionInitialized(true);
+ } else {
+ cb.onFailure();
}
}
}
- public void releaseSession() {
+ public void releaseSession(int extension) {
synchronized (mLock) {
- if (mProxy != null) {
+ if (mConnectionManager.getProxy(extension) != null) {
try {
- mProxy.releaseSession();
+ mConnectionManager.getProxy(extension).releaseSession();
+ mConnectionManager.setSessionInitialized(false);
} catch (RemoteException e) {
Log.e(TAG, "Failed to release session! Extension service does"
+ " not respond!");
@@ -432,77 +498,157 @@
}
}
- public boolean areAdvancedExtensionsSupported() {
- return mSupportsAdvancedExtensions;
+ public boolean areAdvancedExtensionsSupported(int extension) {
+ return mConnectionManager.areAdvancedExtensionsSupported(extension);
}
- public IPreviewExtenderImpl initializePreviewExtension(int extensionType)
+ public IPreviewExtenderImpl initializePreviewExtension(int extension)
throws RemoteException {
synchronized (mLock) {
- if (mProxy != null) {
- return mProxy.initializePreviewExtension(extensionType);
+ if (mConnectionManager.getProxy(extension) != null) {
+ return mConnectionManager.getProxy(extension)
+ .initializePreviewExtension(extension);
} else {
return null;
}
}
}
- public IImageCaptureExtenderImpl initializeImageExtension(int extensionType)
+ public IImageCaptureExtenderImpl initializeImageExtension(int extension)
throws RemoteException {
synchronized (mLock) {
- if (mProxy != null) {
- return mProxy.initializeImageExtension(extensionType);
+ if (mConnectionManager.getProxy(extension) != null) {
+ return mConnectionManager.getProxy(extension)
+ .initializeImageExtension(extension);
} else {
return null;
}
}
}
- public IAdvancedExtenderImpl initializeAdvancedExtension(int extensionType)
+ public IAdvancedExtenderImpl initializeAdvancedExtension(int extension)
throws RemoteException {
synchronized (mLock) {
- if (mProxy != null) {
- return mProxy.initializeAdvancedExtension(extensionType);
+ if (mConnectionManager.getProxy(extension) != null) {
+ return mConnectionManager.getProxy(extension)
+ .initializeAdvancedExtension(extension);
} else {
return null;
}
}
}
+
+ private class ExtensionConnectionManager {
+ // Maps extension to ExtensionConnection
+ private Map<Integer, ExtensionConnection> mConnections = new HashMap<>();
+ private boolean mSessionInitialized = false;
+
+ public ExtensionConnectionManager() {
+ IntArray extensionList = new IntArray(EXTENSION_LIST.length);
+ extensionList.addAll(EXTENSION_LIST);
+ if (Flags.concertMode()) {
+ extensionList.add(EXTENSION_EYES_FREE_VIDEOGRAPHY);
+ }
+
+ for (int extensionType : extensionList.toArray()) {
+ mConnections.put(extensionType, new ExtensionConnection());
+ }
+ }
+
+ public ICameraExtensionsProxyService getProxy(@Extension int extension) {
+ return mConnections.get(extension).mProxy;
+ }
+
+ public ServiceConnection getConnection(@Extension int extension) {
+ return mConnections.get(extension).mConnection;
+ }
+
+ public int getConnectionCount(@Extension int extension) {
+ return mConnections.get(extension).mConnectionCount;
+ }
+
+ public boolean areAdvancedExtensionsSupported(@Extension int extension) {
+ return mConnections.get(extension).mSupportsAdvancedExtensions;
+ }
+
+ public boolean isSessionInitialized() {
+ return mSessionInitialized;
+ }
+
+ public void setProxy(@Extension int extension, ICameraExtensionsProxyService proxy) {
+ mConnections.get(extension).mProxy = proxy;
+ }
+
+ public void setConnection(@Extension int extension, ServiceConnection connection) {
+ mConnections.get(extension).mConnection = connection;
+ }
+
+ public void incrementConnectionCount(@Extension int extension) {
+ mConnections.get(extension).mConnectionCount++;
+ }
+
+ public void decrementConnectionCount(@Extension int extension) {
+ mConnections.get(extension).mConnectionCount--;
+ }
+
+ public void resetConnectionCount(@Extension int extension) {
+ mConnections.get(extension).mConnectionCount = 0;
+ }
+
+ public void setAdvancedExtensionsSupported(@Extension int extension,
+ boolean advancedExtSupported) {
+ mConnections.get(extension).mSupportsAdvancedExtensions = advancedExtSupported;
+ }
+
+ public void setSessionInitialized(boolean initialized) {
+ mSessionInitialized = initialized;
+ }
+
+ private class ExtensionConnection {
+ public ICameraExtensionsProxyService mProxy = null;
+ public ServiceConnection mConnection = null;
+ public int mConnectionCount = 0;
+ public boolean mSupportsAdvancedExtensions = false;
+ }
+ }
}
/**
* @hide
*/
- public static boolean registerClient(Context ctx, IBinder token) {
- return CameraExtensionManagerGlobal.get().registerClient(ctx, token);
+ public static boolean registerClient(Context ctx, IBinder token, int extension,
+ String cameraId, Map<String, CameraMetadataNative> characteristicsMapNative) {
+ return CameraExtensionManagerGlobal.get().registerClient(ctx, token, extension, cameraId,
+ characteristicsMapNative);
}
/**
* @hide
*/
- public static void unregisterClient(Context ctx, IBinder token) {
- CameraExtensionManagerGlobal.get().unregisterClient(ctx, token);
+ public static void unregisterClient(Context ctx, IBinder token, int extension) {
+ CameraExtensionManagerGlobal.get().unregisterClient(ctx, token, extension);
}
/**
* @hide
*/
- public static void initializeSession(IInitializeSessionCallback cb) throws RemoteException {
- CameraExtensionManagerGlobal.get().initializeSession(cb);
+ public static void initializeSession(IInitializeSessionCallback cb, int extension)
+ throws RemoteException {
+ CameraExtensionManagerGlobal.get().initializeSession(cb, extension);
}
/**
* @hide
*/
- public static void releaseSession() {
- CameraExtensionManagerGlobal.get().releaseSession();
+ public static void releaseSession(int extension) {
+ CameraExtensionManagerGlobal.get().releaseSession(extension);
}
/**
* @hide
*/
- public static boolean areAdvancedExtensionsSupported() {
- return CameraExtensionManagerGlobal.get().areAdvancedExtensionsSupported();
+ public static boolean areAdvancedExtensionsSupported(int extension) {
+ return CameraExtensionManagerGlobal.get().areAdvancedExtensionsSupported(extension);
}
/**
@@ -510,7 +656,7 @@
*/
public static boolean isExtensionSupported(String cameraId, int extensionType,
Map<String, CameraMetadataNative> characteristicsMap) {
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extensionType)) {
try {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extensionType);
return extender.isExtensionAvailable(cameraId, characteristicsMap);
@@ -600,24 +746,24 @@
public @NonNull List<Integer> getSupportedExtensions() {
ArrayList<Integer> ret = new ArrayList<>();
final IBinder token = new Binder(TAG + "#getSupportedExtensions:" + mCameraId);
- boolean success = registerClient(mContext, token);
- if (!success) {
- return Collections.unmodifiableList(ret);
- }
IntArray extensionList = new IntArray(EXTENSION_LIST.length);
extensionList.addAll(EXTENSION_LIST);
if (Flags.concertMode()) {
extensionList.add(EXTENSION_EYES_FREE_VIDEOGRAPHY);
}
- try {
- for (int extensionType : extensionList.toArray()) {
- if (isExtensionSupported(mCameraId, extensionType, mCharacteristicsMapNative)) {
+
+ for (int extensionType : extensionList.toArray()) {
+ try {
+ boolean success = registerClient(mContext, token, extensionType, mCameraId,
+ mCharacteristicsMapNative);
+ if (success && isExtensionSupported(mCameraId, extensionType,
+ mCharacteristicsMapNative)) {
ret.add(extensionType);
}
+ } finally {
+ unregisterClient(mContext, token, extensionType);
}
- } finally {
- unregisterClient(mContext, token);
}
return Collections.unmodifiableList(ret);
@@ -643,7 +789,8 @@
public <T> @Nullable T get(@Extension int extension,
@NonNull CameraCharacteristics.Key<T> key) {
final IBinder token = new Binder(TAG + "#get:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -653,7 +800,7 @@
throw new IllegalArgumentException("Unsupported extension");
}
- if (areAdvancedExtensionsSupported() && getKeys(extension).contains(key)) {
+ if (areAdvancedExtensionsSupported(extension) && getKeys(extension).contains(key)) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
CameraMetadataNative metadata =
@@ -670,7 +817,7 @@
Log.e(TAG, "Failed to query the extension for the specified key! Extension "
+ "service does not respond!");
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
return null;
}
@@ -691,7 +838,8 @@
public @NonNull Set<CameraCharacteristics.Key> getKeys(@Extension int extension) {
final IBinder token =
new Binder(TAG + "#getKeys:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -703,7 +851,7 @@
throw new IllegalArgumentException("Unsupported extension");
}
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
CameraMetadataNative metadata =
@@ -732,7 +880,7 @@
Log.e(TAG, "Failed to query the extension for all available keys! Extension "
+ "service does not respond!");
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
return Collections.unmodifiableSet(ret);
}
@@ -755,7 +903,8 @@
*/
public boolean isPostviewAvailable(@Extension int extension) {
final IBinder token = new Binder(TAG + "#isPostviewAvailable:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -765,7 +914,7 @@
throw new IllegalArgumentException("Unsupported extension");
}
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
return extender.isPostviewAvailable();
@@ -779,7 +928,7 @@
Log.e(TAG, "Failed to query the extension for postview availability! Extension "
+ "service does not respond!");
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
return false;
@@ -813,7 +962,8 @@
public List<Size> getPostviewSupportedSizes(@Extension int extension,
@NonNull Size captureSize, int format) {
final IBinder token = new Binder(TAG + "#getPostviewSupportedSizes:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -831,7 +981,7 @@
StreamConfigurationMap streamMap = mCharacteristicsMap.get(mCameraId).get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
switch(format) {
case ImageFormat.YUV_420_888:
case ImageFormat.JPEG:
@@ -879,7 +1029,7 @@
+ "service does not respond!");
return Collections.emptyList();
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
}
@@ -917,7 +1067,8 @@
// ambiguity is resolved in b/169799538.
final IBinder token = new Binder(TAG + "#getExtensionSupportedSizes:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -929,7 +1080,7 @@
StreamConfigurationMap streamMap = mCharacteristicsMap.get(mCameraId).get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
return generateSupportedSizes(
@@ -948,7 +1099,7 @@
+ " not respond!");
return new ArrayList<>();
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
}
@@ -978,7 +1129,8 @@
List<Size> getExtensionSupportedSizes(@Extension int extension, int format) {
try {
final IBinder token = new Binder(TAG + "#getExtensionSupportedSizes:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -990,7 +1142,7 @@
StreamConfigurationMap streamMap = mCharacteristicsMap.get(mCameraId).get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
switch(format) {
case ImageFormat.YUV_420_888:
case ImageFormat.JPEG:
@@ -1035,7 +1187,7 @@
}
}
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to query the extension supported sizes! Extension service does"
@@ -1073,7 +1225,8 @@
}
final IBinder token = new Binder(TAG + "#getEstimatedCaptureLatencyRangeMillis:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -1087,7 +1240,7 @@
new android.hardware.camera2.extension.Size();
sz.width = captureOutputSize.getWidth();
sz.height = captureOutputSize.getHeight();
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
LatencyRange latencyRange = extender.getEstimatedCaptureLatencyRange(mCameraId,
@@ -1126,7 +1279,7 @@
Log.e(TAG, "Failed to query the extension capture latency! Extension service does"
+ " not respond!");
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
return null;
@@ -1143,7 +1296,8 @@
*/
public boolean isCaptureProcessProgressAvailable(@Extension int extension) {
final IBinder token = new Binder(TAG + "#isCaptureProcessProgressAvailable:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -1153,7 +1307,7 @@
throw new IllegalArgumentException("Unsupported extension");
}
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
return extender.isCaptureProcessProgressAvailable();
@@ -1167,7 +1321,7 @@
Log.e(TAG, "Failed to query the extension progress callbacks! Extension service does"
+ " not respond!");
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
return false;
@@ -1195,7 +1349,8 @@
@NonNull
public Set<CaptureRequest.Key> getAvailableCaptureRequestKeys(@Extension int extension) {
final IBinder token = new Binder(TAG + "#getAvailableCaptureRequestKeys:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -1208,7 +1363,7 @@
}
CameraMetadataNative captureRequestMeta = null;
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
captureRequestMeta = extender.getAvailableCaptureRequestKeys(mCameraId);
@@ -1250,7 +1405,7 @@
} catch (RemoteException e) {
throw new IllegalStateException("Failed to query the available capture request keys!");
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
return Collections.unmodifiableSet(ret);
@@ -1282,7 +1437,8 @@
@NonNull
public Set<CaptureResult.Key> getAvailableCaptureResultKeys(@Extension int extension) {
final IBinder token = new Binder(TAG + "#getAvailableCaptureResultKeys:" + mCameraId);
- boolean success = registerClient(mContext, token);
+ boolean success = registerClient(mContext, token, extension, mCameraId,
+ mCharacteristicsMapNative);
if (!success) {
throw new IllegalArgumentException("Unsupported extensions");
}
@@ -1294,7 +1450,7 @@
}
CameraMetadataNative captureResultMeta = null;
- if (areAdvancedExtensionsSupported()) {
+ if (areAdvancedExtensionsSupported(extension)) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
captureResultMeta = extender.getAvailableCaptureResultKeys(mCameraId);
@@ -1336,7 +1492,7 @@
} catch (RemoteException e) {
throw new IllegalStateException("Failed to query the available capture result keys!");
} finally {
- unregisterClient(mContext, token);
+ unregisterClient(mContext, token, extension);
}
return Collections.unmodifiableSet(ret);
diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
index f6c8f36..b2032fa 100644
--- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
@@ -102,6 +102,8 @@
private boolean mInitialized;
private boolean mSessionClosed;
+ private int mExtensionType;
+
private final Context mContext;
@@ -205,7 +207,7 @@
CameraAdvancedExtensionSessionImpl ret = new CameraAdvancedExtensionSessionImpl(ctx,
extender, cameraDevice, characteristicsMapNative, repeatingRequestSurface,
burstCaptureSurface, postviewSurface, config.getStateCallback(),
- config.getExecutor(), sessionId, token);
+ config.getExecutor(), sessionId, token, config.getExtension());
ret.mStatsAggregator.setClientName(ctx.getOpPackageName());
ret.mStatsAggregator.setExtensionType(config.getExtension());
@@ -223,7 +225,8 @@
@Nullable Surface postviewSurface,
@NonNull StateCallback callback, @NonNull Executor executor,
int sessionId,
- @NonNull IBinder token) {
+ @NonNull IBinder token,
+ int extension) {
mContext = ctx;
mAdvancedExtender = extender;
mCameraDevice = cameraDevice;
@@ -242,6 +245,7 @@
mSessionId = sessionId;
mToken = token;
mInterfaceLock = cameraDevice.mInterfaceLock;
+ mExtensionType = extension;
mStatsAggregator = new ExtensionSessionStatsAggregator(mCameraDevice.getId(),
/*isAdvanced=*/true);
@@ -583,9 +587,9 @@
if (mToken != null) {
if (mInitialized || (mCaptureSession != null)) {
notifyClose = true;
- CameraExtensionCharacteristics.releaseSession();
+ CameraExtensionCharacteristics.releaseSession(mExtensionType);
}
- CameraExtensionCharacteristics.unregisterClient(mContext, mToken);
+ CameraExtensionCharacteristics.unregisterClient(mContext, mToken, mExtensionType);
}
mInitialized = false;
mToken = null;
@@ -654,7 +658,8 @@
}
try {
- CameraExtensionCharacteristics.initializeSession(mInitializeHandler);
+ CameraExtensionCharacteristics.initializeSession(
+ mInitializeHandler, mExtensionType);
} catch (RemoteException e) {
Log.e(TAG, "Failed to initialize session! Extension service does"
+ " not respond!");
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index ccb24e7..f03876b 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -2559,13 +2559,16 @@
boolean initializationFailed = true;
IBinder token = new Binder(TAG + " : " + mNextSessionId++);
try {
- boolean ret = CameraExtensionCharacteristics.registerClient(mContext, token);
+ boolean ret = CameraExtensionCharacteristics.registerClient(mContext, token,
+ extensionConfiguration.getExtension(), mCameraId,
+ CameraExtensionUtils.getCharacteristicsMapNative(characteristicsMap));
if (!ret) {
token = null;
throw new UnsupportedOperationException("Unsupported extension!");
}
- if (CameraExtensionCharacteristics.areAdvancedExtensionsSupported()) {
+ if (CameraExtensionCharacteristics.areAdvancedExtensionsSupported(
+ extensionConfiguration.getExtension())) {
mCurrentAdvancedExtensionSession =
CameraAdvancedExtensionSessionImpl.createCameraAdvancedExtensionSession(
this, characteristicsMap, mContext, extensionConfiguration,
@@ -2580,7 +2583,8 @@
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR);
} finally {
if (initializationFailed && (token != null)) {
- CameraExtensionCharacteristics.unregisterClient(mContext, token);
+ CameraExtensionCharacteristics.unregisterClient(mContext, token,
+ extensionConfiguration.getExtension());
}
}
}
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index db7055b..725b413 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -118,6 +118,7 @@
// In case the client doesn't explicitly enable repeating requests, the framework
// will do so internally.
private boolean mInternalRepeatingRequestEnabled = true;
+ private int mExtensionType;
private final Context mContext;
@@ -244,7 +245,8 @@
sessionId,
token,
extensionChars.getAvailableCaptureRequestKeys(config.getExtension()),
- extensionChars.getAvailableCaptureResultKeys(config.getExtension()));
+ extensionChars.getAvailableCaptureResultKeys(config.getExtension()),
+ config.getExtension());
session.mStatsAggregator.setClientName(ctx.getOpPackageName());
session.mStatsAggregator.setExtensionType(config.getExtension());
@@ -266,7 +268,8 @@
int sessionId,
@NonNull IBinder token,
@NonNull Set<CaptureRequest.Key> requestKeys,
- @Nullable Set<CaptureResult.Key> resultKeys) {
+ @Nullable Set<CaptureResult.Key> resultKeys,
+ int extension) {
mContext = ctx;
mImageExtender = imageExtender;
mPreviewExtender = previewExtender;
@@ -289,6 +292,7 @@
mSupportedResultKeys = resultKeys;
mCaptureResultsSupported = !resultKeys.isEmpty();
mInterfaceLock = cameraDevice.mInterfaceLock;
+ mExtensionType = extension;
mStatsAggregator = new ExtensionSessionStatsAggregator(mCameraDevice.getId(),
/*isAdvanced=*/false);
@@ -881,9 +885,9 @@
if (mToken != null) {
if (mInitialized || (mCaptureSession != null)) {
notifyClose = true;
- CameraExtensionCharacteristics.releaseSession();
+ CameraExtensionCharacteristics.releaseSession(mExtensionType);
}
- CameraExtensionCharacteristics.unregisterClient(mContext, mToken);
+ CameraExtensionCharacteristics.unregisterClient(mContext, mToken, mExtensionType);
}
mInitialized = false;
mToken = null;
@@ -1000,7 +1004,8 @@
mStatsAggregator.commit(/*isFinal*/false);
try {
finishPipelineInitialization();
- CameraExtensionCharacteristics.initializeSession(mInitializeHandler);
+ CameraExtensionCharacteristics.initializeSession(
+ mInitializeHandler, mExtensionType);
} catch (RemoteException e) {
Log.e(TAG, "Failed to initialize session! Extension service does"
+ " not respond!");
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 95edb61..3f4a7228 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11833,6 +11833,7 @@
* Whether to enable camera extensions software fallback.
* @hide
*/
+ @Readable
public static final String CAMERA_EXTENSIONS_FALLBACK = "camera_extensions_fallback";
/**
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d4e727e..c6bc589 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2141,6 +2141,12 @@
<item>com.android.location.fused</item>
</string-array>
+ <!-- Package name of the extension software fallback. -->
+ <string name="config_extensionFallbackPackageName" translatable="false"></string>
+
+ <!-- Service name of the extension software fallback. -->
+ <string name="config_extensionFallbackServiceName" translatable="false"></string>
+
<!-- Package name(s) of Advanced Driver Assistance applications. These packages have additional
management of access to location, specific to driving assistance use-cases. They must be system
packages. This configuration is only applicable to devices that declare
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 58427b1..e232346 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2153,6 +2153,8 @@
<java-symbol type="string" name="config_systemImageEditor" />
<java-symbol type="string" name="config_datause_iface" />
<java-symbol type="string" name="config_activityRecognitionHardwarePackageName" />
+ <java-symbol type="string" name="config_extensionFallbackPackageName" />
+ <java-symbol type="string" name="config_extensionFallbackServiceName" />
<java-symbol type="string" name="config_fusedLocationProviderPackageName" />
<java-symbol type="string" name="config_gnssLocationProviderPackageName" />
<java-symbol type="string" name="config_geocoderProviderPackageName" />