summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/test-current.txt1
-rw-r--r--core/java/android/hardware/Camera.java24
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java43
-rw-r--r--core/jni/android_hardware_Camera.cpp144
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java9
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java5
6 files changed, 116 insertions, 110 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 25c4652e9112..16f09655b687 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1157,6 +1157,7 @@ package android.hardware.camera2 {
public final class CameraManager {
method public String[] getCameraIdListNoLazy() 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;
+ field public static final long OVERRIDE_FRONT_CAMERA_APP_COMPAT = 250678880L; // 0xef10e60L
}
public abstract static class CameraManager.AvailabilityCallback {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 3bdd39f5d7d7..5291d2b73891 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -29,12 +29,14 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.ActivityThread;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraManager;
import android.media.AudioAttributes;
import android.media.IAudioService;
import android.os.Build;
@@ -45,6 +47,7 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RSIllegalArgumentException;
@@ -281,6 +284,14 @@ public class Camera {
*/
public native static int getNumberOfCameras();
+ private static final boolean sLandscapeToPortrait =
+ SystemProperties.getBoolean(CameraManager.LANDSCAPE_TO_PORTRAIT_PROP, false);
+
+ private static boolean shouldOverrideToPortrait() {
+ return CompatChanges.isChangeEnabled(CameraManager.OVERRIDE_FRONT_CAMERA_APP_COMPAT)
+ && sLandscapeToPortrait;
+ }
+
/**
* Returns the information about a particular camera.
* If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1.
@@ -290,7 +301,9 @@ public class Camera {
* low-level failure).
*/
public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) {
- _getCameraInfo(cameraId, cameraInfo);
+ boolean overrideToPortrait = shouldOverrideToPortrait();
+
+ _getCameraInfo(cameraId, overrideToPortrait, cameraInfo);
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
IAudioService audioService = IAudioService.Stub.asInterface(b);
try {
@@ -303,7 +316,8 @@ public class Camera {
Log.e(TAG, "Audio service is unavailable for queries");
}
}
- private native static void _getCameraInfo(int cameraId, CameraInfo cameraInfo);
+ private native static void _getCameraInfo(int cameraId, boolean overrideToPortrait,
+ CameraInfo cameraInfo);
/**
* Information about a camera
@@ -484,8 +498,9 @@ public class Camera {
mEventHandler = null;
}
+ boolean overrideToPortrait = shouldOverrideToPortrait();
return native_setup(new WeakReference<Camera>(this), cameraId,
- ActivityThread.currentOpPackageName());
+ ActivityThread.currentOpPackageName(), overrideToPortrait);
}
/** used by Camera#open, Camera#open(int) */
@@ -555,7 +570,8 @@ public class Camera {
}
@UnsupportedAppUsage
- private native int native_setup(Object cameraThis, int cameraId, String packageName);
+ private native int native_setup(Object cameraThis, int cameraId, String packageName,
+ boolean overrideToPortrait);
private native final void native_release();
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index f858227a0f1d..127bb0fa3b4c 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -23,6 +23,10 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
+import android.compat.annotation.Overridable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Point;
@@ -104,6 +108,24 @@ public final class CameraManager {
private final boolean mHasOpenCloseListenerPermission;
/**
+ * Force camera output to be rotated to portrait orientation on landscape cameras.
+ * Many apps do not handle this situation and display stretched images otherwise.
+ * @hide
+ */
+ @ChangeId
+ @Overridable
+ @Disabled
+ @TestApi
+ public static final long OVERRIDE_FRONT_CAMERA_APP_COMPAT = 250678880L;
+
+ /**
+ * System property for allowing the above
+ * @hide
+ */
+ public static final String LANDSCAPE_TO_PORTRAIT_PROP =
+ "camera.enable_landscape_to_portrait";
+
+ /**
* @hide
*/
public CameraManager(Context context) {
@@ -526,7 +548,8 @@ public final class CameraManager {
for (String physicalCameraId : physicalCameraIds) {
CameraMetadataNative physicalCameraInfo =
cameraService.getCameraCharacteristics(physicalCameraId,
- mContext.getApplicationInfo().targetSdkVersion);
+ mContext.getApplicationInfo().targetSdkVersion,
+ /*overrideToPortrait*/false);
StreamConfiguration[] configs = physicalCameraInfo.get(
CameraCharacteristics.
SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS);
@@ -585,8 +608,9 @@ public final class CameraManager {
try {
Size displaySize = getDisplaySize();
+ boolean overrideToPortrait = shouldOverrideToPortrait();
CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
- mContext.getApplicationInfo().targetSdkVersion);
+ mContext.getApplicationInfo().targetSdkVersion, overrideToPortrait);
try {
info.setCameraId(Integer.parseInt(cameraId));
} catch (NumberFormatException e) {
@@ -703,9 +727,12 @@ public final class CameraManager {
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
+
+ boolean overrideToPortrait = shouldOverrideToPortrait();
cameraUser = cameraService.connectDevice(callbacks, cameraId,
- mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
- oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);
+ mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
+ oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion,
+ overrideToPortrait);
} catch (ServiceSpecificException e) {
if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
throw new AssertionError("Should've gone down the shim path");
@@ -1133,6 +1160,11 @@ public final class CameraManager {
return CameraManagerGlobal.get().getTorchStrengthLevel(cameraId);
}
+ private static boolean shouldOverrideToPortrait() {
+ return CompatChanges.isChangeEnabled(OVERRIDE_FRONT_CAMERA_APP_COMPAT)
+ && CameraManagerGlobal.sLandscapeToPortrait;
+ }
+
/**
* A callback for camera devices becoming available or unavailable to open.
*
@@ -1579,6 +1611,9 @@ public final class CameraManager {
public static final boolean sCameraServiceDisabled =
SystemProperties.getBoolean("config.disable_cameraservice", false);
+ public static final boolean sLandscapeToPortrait =
+ SystemProperties.getBoolean(LANDSCAPE_TO_PORTRAIT_PROP, false);
+
public static CameraManagerGlobal get() {
return gCameraManager;
}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 365a18d174c9..a8abe50a9755 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -529,9 +529,8 @@ static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz
return Camera::getNumberOfCameras();
}
-static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
- jint cameraId, jobject info_obj)
-{
+static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, jint cameraId,
+ jboolean overrideToPortrait, jobject info_obj) {
CameraInfo cameraInfo;
if (cameraId >= Camera::getNumberOfCameras() || cameraId < 0) {
ALOGE("%s: Unknown camera ID %d", __FUNCTION__, cameraId);
@@ -539,7 +538,7 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
return;
}
- status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
+ status_t rc = Camera::getCameraInfo(cameraId, overrideToPortrait, &cameraInfo);
if (rc != NO_ERROR) {
jniThrowRuntimeException(env, "Fail to get camera info");
return;
@@ -555,9 +554,9 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
}
// connect to camera service
-static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
- jobject weak_this, jint cameraId, jstring clientPackageName)
-{
+static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
+ jint cameraId, jstring clientPackageName,
+ jboolean overrideToPortrait) {
// Convert jstring to String16
const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
env->GetStringChars(clientPackageName, NULL));
@@ -567,8 +566,9 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
reinterpret_cast<const jchar*>(rawClientName));
int targetSdkVersion = android_get_application_target_sdk_version();
- sp<Camera> camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID,
- Camera::USE_CALLING_PID, targetSdkVersion);
+ sp<Camera> camera =
+ Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID, Camera::USE_CALLING_PID,
+ targetSdkVersion, overrideToPortrait);
if (camera == NULL) {
return -EACCES;
}
@@ -596,7 +596,7 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
// Update default display orientation in case the sensor is reverse-landscape
CameraInfo cameraInfo;
- status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
+ status_t rc = Camera::getCameraInfo(cameraId, overrideToPortrait, &cameraInfo);
if (rc != NO_ERROR) {
ALOGE("%s: getCameraInfo error: %d", __FUNCTION__, rc);
return rc;
@@ -1051,93 +1051,43 @@ static int32_t android_hardware_Camera_getAudioRestriction(
//-------------------------------------------------
static const JNINativeMethod camMethods[] = {
- { "getNumberOfCameras",
- "()I",
- (void *)android_hardware_Camera_getNumberOfCameras },
- { "_getCameraInfo",
- "(ILandroid/hardware/Camera$CameraInfo;)V",
- (void*)android_hardware_Camera_getCameraInfo },
- { "native_setup",
- "(Ljava/lang/Object;ILjava/lang/String;)I",
- (void*)android_hardware_Camera_native_setup },
- { "native_release",
- "()V",
- (void*)android_hardware_Camera_release },
- { "setPreviewSurface",
- "(Landroid/view/Surface;)V",
- (void *)android_hardware_Camera_setPreviewSurface },
- { "setPreviewTexture",
- "(Landroid/graphics/SurfaceTexture;)V",
- (void *)android_hardware_Camera_setPreviewTexture },
- { "setPreviewCallbackSurface",
- "(Landroid/view/Surface;)V",
- (void *)android_hardware_Camera_setPreviewCallbackSurface },
- { "startPreview",
- "()V",
- (void *)android_hardware_Camera_startPreview },
- { "_stopPreview",
- "()V",
- (void *)android_hardware_Camera_stopPreview },
- { "previewEnabled",
- "()Z",
- (void *)android_hardware_Camera_previewEnabled },
- { "setHasPreviewCallback",
- "(ZZ)V",
- (void *)android_hardware_Camera_setHasPreviewCallback },
- { "_addCallbackBuffer",
- "([BI)V",
- (void *)android_hardware_Camera_addCallbackBuffer },
- { "native_autoFocus",
- "()V",
- (void *)android_hardware_Camera_autoFocus },
- { "native_cancelAutoFocus",
- "()V",
- (void *)android_hardware_Camera_cancelAutoFocus },
- { "native_takePicture",
- "(I)V",
- (void *)android_hardware_Camera_takePicture },
- { "native_setParameters",
- "(Ljava/lang/String;)V",
- (void *)android_hardware_Camera_setParameters },
- { "native_getParameters",
- "()Ljava/lang/String;",
- (void *)android_hardware_Camera_getParameters },
- { "reconnect",
- "()V",
- (void*)android_hardware_Camera_reconnect },
- { "lock",
- "()V",
- (void*)android_hardware_Camera_lock },
- { "unlock",
- "()V",
- (void*)android_hardware_Camera_unlock },
- { "startSmoothZoom",
- "(I)V",
- (void *)android_hardware_Camera_startSmoothZoom },
- { "stopSmoothZoom",
- "()V",
- (void *)android_hardware_Camera_stopSmoothZoom },
- { "setDisplayOrientation",
- "(I)V",
- (void *)android_hardware_Camera_setDisplayOrientation },
- { "_enableShutterSound",
- "(Z)Z",
- (void *)android_hardware_Camera_enableShutterSound },
- { "_startFaceDetection",
- "(I)V",
- (void *)android_hardware_Camera_startFaceDetection },
- { "_stopFaceDetection",
- "()V",
- (void *)android_hardware_Camera_stopFaceDetection},
- { "enableFocusMoveCallback",
- "(I)V",
- (void *)android_hardware_Camera_enableFocusMoveCallback},
- { "setAudioRestriction",
- "(I)V",
- (void *)android_hardware_Camera_setAudioRestriction},
- { "getAudioRestriction",
- "()I",
- (void *)android_hardware_Camera_getAudioRestriction},
+ {"getNumberOfCameras", "()I", (void *)android_hardware_Camera_getNumberOfCameras},
+ {"_getCameraInfo", "(IZLandroid/hardware/Camera$CameraInfo;)V",
+ (void *)android_hardware_Camera_getCameraInfo},
+ {"native_setup", "(Ljava/lang/Object;ILjava/lang/String;Z)I",
+ (void *)android_hardware_Camera_native_setup},
+ {"native_release", "()V", (void *)android_hardware_Camera_release},
+ {"setPreviewSurface", "(Landroid/view/Surface;)V",
+ (void *)android_hardware_Camera_setPreviewSurface},
+ {"setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V",
+ (void *)android_hardware_Camera_setPreviewTexture},
+ {"setPreviewCallbackSurface", "(Landroid/view/Surface;)V",
+ (void *)android_hardware_Camera_setPreviewCallbackSurface},
+ {"startPreview", "()V", (void *)android_hardware_Camera_startPreview},
+ {"_stopPreview", "()V", (void *)android_hardware_Camera_stopPreview},
+ {"previewEnabled", "()Z", (void *)android_hardware_Camera_previewEnabled},
+ {"setHasPreviewCallback", "(ZZ)V", (void *)android_hardware_Camera_setHasPreviewCallback},
+ {"_addCallbackBuffer", "([BI)V", (void *)android_hardware_Camera_addCallbackBuffer},
+ {"native_autoFocus", "()V", (void *)android_hardware_Camera_autoFocus},
+ {"native_cancelAutoFocus", "()V", (void *)android_hardware_Camera_cancelAutoFocus},
+ {"native_takePicture", "(I)V", (void *)android_hardware_Camera_takePicture},
+ {"native_setParameters", "(Ljava/lang/String;)V",
+ (void *)android_hardware_Camera_setParameters},
+ {"native_getParameters", "()Ljava/lang/String;",
+ (void *)android_hardware_Camera_getParameters},
+ {"reconnect", "()V", (void *)android_hardware_Camera_reconnect},
+ {"lock", "()V", (void *)android_hardware_Camera_lock},
+ {"unlock", "()V", (void *)android_hardware_Camera_unlock},
+ {"startSmoothZoom", "(I)V", (void *)android_hardware_Camera_startSmoothZoom},
+ {"stopSmoothZoom", "()V", (void *)android_hardware_Camera_stopSmoothZoom},
+ {"setDisplayOrientation", "(I)V", (void *)android_hardware_Camera_setDisplayOrientation},
+ {"_enableShutterSound", "(Z)Z", (void *)android_hardware_Camera_enableShutterSound},
+ {"_startFaceDetection", "(I)V", (void *)android_hardware_Camera_startFaceDetection},
+ {"_stopFaceDetection", "()V", (void *)android_hardware_Camera_stopFaceDetection},
+ {"enableFocusMoveCallback", "(I)V",
+ (void *)android_hardware_Camera_enableFocusMoveCallback},
+ {"setAudioRestriction", "(I)V", (void *)android_hardware_Camera_setAudioRestriction},
+ {"getAudioRestriction", "()I", (void *)android_hardware_Camera_getAudioRestriction},
};
struct field {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index a2eae2c9579a..2b7bcbee79fd 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -85,7 +85,8 @@ public class CameraBinderTest extends AndroidTestCase {
public void testCameraInfo() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId);
+ CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId,
+ /*overrideToPortrait*/false);
assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
assertTrue("Orientation was not set for camera " + cameraId,
info.info.orientation != -1);
@@ -159,7 +160,8 @@ public class CameraBinderTest extends AndroidTestCase {
.connect(dummyCallbacks, cameraId, clientPackageName,
ICameraService.USE_CALLING_UID,
ICameraService.USE_CALLING_PID,
- getContext().getApplicationInfo().targetSdkVersion);
+ getContext().getApplicationInfo().targetSdkVersion,
+ /*overrideToPortrait*/false);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -264,7 +266,8 @@ public class CameraBinderTest extends AndroidTestCase {
dummyCallbacks, String.valueOf(cameraId),
clientPackageName, clientAttributionTag,
ICameraService.USE_CALLING_UID, 0 /*oomScoreOffset*/,
- getContext().getApplicationInfo().targetSdkVersion);
+ getContext().getApplicationInfo().targetSdkVersion,
+ /*overrideToPortrait*/false);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 0890346db198..9d09dcc5c440 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -244,7 +244,8 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
clientPackageName, clientAttributionTag, ICameraService.USE_CALLING_UID,
- /*oomScoreOffset*/0, getContext().getApplicationInfo().targetSdkVersion);
+ /*oomScoreOffset*/0, getContext().getApplicationInfo().targetSdkVersion,
+ /*overrideToPortrait*/false);
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
@@ -417,7 +418,7 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
@SmallTest
public void testCameraCharacteristics() throws RemoteException {
CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId,
- getContext().getApplicationInfo().targetSdkVersion);
+ getContext().getApplicationInfo().targetSdkVersion, /*overrideToPortrait*/false);
assertFalse(info.isEmpty());
assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));