Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5698b2c authored by Austin Borger's avatar Austin Borger Committed by Android (Google) Code Review
Browse files

Merge "CameraManager: Provide flag for overriding camera output to portrait."

parents 256d74dd 70ca84c4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1158,6 +1158,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 {
+20 −4
Original line number Diff line number Diff line
@@ -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();

+39 −4
Original line number Diff line number Diff line
@@ -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;
@@ -103,6 +107,24 @@ public final class CameraManager {
            "android.permission.CAMERA_OPEN_CLOSE_LISTENER";
    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
     */
@@ -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);
                    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;
        }
+47 −97
Original line number Diff line number Diff line
@@ -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",
        {"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;)I",
        {"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",
        {"native_release", "()V", (void *)android_hardware_Camera_release},
        {"setPreviewSurface", "(Landroid/view/Surface;)V",
         (void *)android_hardware_Camera_setPreviewSurface},
  { "setPreviewTexture",
    "(Landroid/graphics/SurfaceTexture;)V",
        {"setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V",
         (void *)android_hardware_Camera_setPreviewTexture},
  { "setPreviewCallbackSurface",
    "(Landroid/view/Surface;)V",
        {"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",
        {"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;",
        {"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",
        {"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},
        {"setAudioRestriction", "(I)V", (void *)android_hardware_Camera_setAudioRestriction},
        {"getAudioRestriction", "()I", (void *)android_hardware_Camera_getAudioRestriction},
};

struct field {
+6 −3
Original line number Diff line number Diff line
@@ -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));
Loading