CameraManager: Add TestApi entrypoints for setting overrideToPortrait.

Bug: 264434827
Test: Ran new CTS tests on cuttlefish / device with override.
Change-Id: Id3a86fa8133804323d924602ec4931bdf0d56590
This commit is contained in:
Austin Borger
2023-03-13 11:29:26 -07:00
parent 251260206a
commit 872659eaa1
2 changed files with 80 additions and 11 deletions

View File

@@ -1391,8 +1391,12 @@ package android.hardware.biometrics {
package android.hardware.camera2 {
public final class CameraManager {
method @NonNull public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(@NonNull String, boolean) throws android.hardware.camera2.CameraAccessException;
method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException;
method @RequiresPermission(android.Manifest.permission.CAMERA) public void openCamera(@NonNull String, boolean, @Nullable android.os.Handler, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
method @RequiresPermission(allOf={android.Manifest.permission.SYSTEM_CAMERA, android.Manifest.permission.CAMERA}) public void openCamera(@NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
method public static boolean shouldOverrideToPortrait(@Nullable android.content.pm.PackageManager, @Nullable String);
field public static final String LANDSCAPE_TO_PORTRAIT_PROP = "camera.enable_landscape_to_portrait";
field public static final long OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT = 250678880L; // 0xef10e60L
}

View File

@@ -121,6 +121,7 @@ public final class CameraManager {
* System property for allowing the above
* @hide
*/
@TestApi
public static final String LANDSCAPE_TO_PORTRAIT_PROP =
"camera.enable_landscape_to_portrait";
@@ -605,6 +606,16 @@ public final class CameraManager {
@NonNull
public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)
throws CameraAccessException {
return getCameraCharacteristics(cameraId, shouldOverrideToPortrait(mContext));
}
/**
* @hide
*/
@TestApi
@NonNull
public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId,
boolean overrideToPortrait) throws CameraAccessException {
CameraCharacteristics characteristics = null;
if (CameraManagerGlobal.sCameraServiceDisabled) {
throw new IllegalArgumentException("No cameras available on device");
@@ -618,7 +629,6 @@ public final class CameraManager {
try {
Size displaySize = getDisplaySize();
boolean overrideToPortrait = shouldOverrideToPortrait(mContext);
CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
mContext.getApplicationInfo().targetSdkVersion, overrideToPortrait);
try {
@@ -710,7 +720,7 @@ public final class CameraManager {
*/
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Executor executor, final int uid,
final int oomScoreOffset) throws CameraAccessException {
final int oomScoreOffset, boolean overrideToPortrait) throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
Map<String, CameraCharacteristics> physicalIdsToChars =
@@ -738,7 +748,6 @@ public final class CameraManager {
"Camera service is currently unavailable");
}
boolean overrideToPortrait = shouldOverrideToPortrait(mContext);
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion,
@@ -873,6 +882,43 @@ public final class CameraManager {
USE_CALLING_UID);
}
/**
* Open a connection to a camera with the given ID. Also specify overrideToPortrait for testing.
*
* @param cameraId
* The unique identifier of the camera device to open
* @param handler
* The handler on which the callback should be invoked, or
* {@code null} to use the current thread's {@link android.os.Looper looper}.
* @param callback
* The callback which is invoked once the camera is opened
* @param overrideToPortrait
* Whether to apply the landscape to portrait override, using rotate and crop.
*
* @throws CameraAccessException if the camera is disabled by device policy,
* has been disconnected, or is being used by a higher-priority camera API client.
*
* @throws IllegalArgumentException if cameraId, the callback or the executor was null,
* or the cameraId does not match any currently or previously available
* camera device.
*
* @throws SecurityException if the application does not have permission to
* access the camera
*
* @see #getCameraIdList
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*
* @hide
*/
@TestApi
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId, boolean overrideToPortrait,
@Nullable Handler handler,
@NonNull final CameraDevice.StateCallback callback) throws CameraAccessException {
openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
USE_CALLING_UID, /*oomScoreOffset*/0, overrideToPortrait);
}
/**
* Open a connection to a camera with the given ID.
*
@@ -977,7 +1023,8 @@ public final class CameraManager {
throw new IllegalArgumentException(
"oomScoreOffset < 0, cannot increase priority of camera client");
}
openCameraForUid(cameraId, callback, executor, USE_CALLING_UID, oomScoreOffset);
openCameraForUid(cameraId, callback, executor, USE_CALLING_UID, oomScoreOffset,
shouldOverrideToPortrait(mContext));
}
/**
@@ -999,7 +1046,8 @@ public final class CameraManager {
*/
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
int clientUid, int oomScoreOffset) throws CameraAccessException {
int clientUid, int oomScoreOffset, boolean overrideToPortrait)
throws CameraAccessException {
if (cameraId == null) {
throw new IllegalArgumentException("cameraId was null");
@@ -1010,7 +1058,8 @@ public final class CameraManager {
throw new IllegalArgumentException("No cameras available on device");
}
openCameraDeviceUserAsync(cameraId, callback, executor, clientUid, oomScoreOffset);
openCameraDeviceUserAsync(cameraId, callback, executor, clientUid, oomScoreOffset,
overrideToPortrait);
}
/**
@@ -1031,7 +1080,8 @@ public final class CameraManager {
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
int clientUid) throws CameraAccessException {
openCameraForUid(cameraId, callback, executor, clientUid, /*oomScoreOffset*/0);
openCameraForUid(cameraId, callback, executor, clientUid, /*oomScoreOffset*/0,
shouldOverrideToPortrait(mContext));
}
/**
@@ -1174,17 +1224,32 @@ public final class CameraManager {
* @hide
*/
public static boolean shouldOverrideToPortrait(@Nullable Context context) {
PackageManager packageManager = null;
String packageName = null;
if (context != null) {
packageManager = context.getPackageManager();
packageName = context.getOpPackageName();
}
return shouldOverrideToPortrait(packageManager, packageName);
}
/**
* @hide
*/
@TestApi
public static boolean shouldOverrideToPortrait(@Nullable PackageManager packageManager,
@Nullable String packageName) {
if (!CameraManagerGlobal.sLandscapeToPortrait) {
return false;
}
if (context != null) {
PackageManager packageManager = context.getPackageManager();
if (packageManager != null && packageName != null) {
try {
return packageManager.getProperty(
PackageManager.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT,
context.getOpPackageName()).getBoolean();
packageName).getBoolean();
} catch (PackageManager.NameNotFoundException e) {
// No such property
}