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

Commit b2663a24 authored by Jayant Chowdhary's avatar Jayant Chowdhary Committed by Android (Google) Code Review
Browse files

Merge changes from topic "cameraRotationOverride" into main

* changes:
  camera2 impl: Return rotation type from `shouldOverrideToPortrait`, and rename to `getRotationOverride`.
  camera2 impl: Allow connecting clients to specify rotation override
parents bc7de4ab 244ecbcf
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -1529,9 +1529,9 @@ package android.graphics.fonts {
package android.hardware {

  @Deprecated public class Camera {
    method @Deprecated public static void getCameraInfo(int, @NonNull android.content.Context, boolean, android.hardware.Camera.CameraInfo);
    method @Deprecated public static void getCameraInfo(int, @NonNull android.content.Context, int, android.hardware.Camera.CameraInfo);
    method @Deprecated public static int getNumberOfCameras(@NonNull android.content.Context);
    method @Deprecated public static android.hardware.Camera open(int, @NonNull android.content.Context, boolean);
    method @Deprecated public static android.hardware.Camera open(int, @NonNull android.content.Context, int);
    method @Deprecated public final void setPreviewSurface(android.view.Surface) throws java.io.IOException;
  }

@@ -1606,11 +1606,15 @@ 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 @FlaggedApi("com.android.window.flags.camera_compat_for_freeform") public static int getRotationOverrideInternal(@Nullable android.content.Context, @Nullable android.content.pm.PackageManager, @Nullable String);
    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
    field @FlaggedApi("com.android.window.flags.camera_compat_for_freeform") public static final int ROTATION_OVERRIDE_NONE = 0; // 0x0
    field @FlaggedApi("com.android.window.flags.camera_compat_for_freeform") public static final int ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT = 1; // 0x1
    field @FlaggedApi("com.android.window.flags.camera_compat_for_freeform") public static final int ROTATION_OVERRIDE_ROTATION_ONLY = 2; // 0x2
  }

  public abstract static class CameraManager.AvailabilityCallback {
+14 −14
Original line number Diff line number Diff line
@@ -308,8 +308,8 @@ public class Camera {
     */
    public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) {
        Context context = ActivityThread.currentApplication().getApplicationContext();
        boolean overrideToPortrait = CameraManager.shouldOverrideToPortrait(context);
        getCameraInfo(cameraId, context, overrideToPortrait, cameraInfo);
        final int rotationOverride = CameraManager.getRotationOverride(context);
        getCameraInfo(cameraId, context, rotationOverride, cameraInfo);
    }

    /**
@@ -320,8 +320,8 @@ public class Camera {
    @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
    @TestApi
    public static void getCameraInfo(int cameraId, @NonNull Context context,
            boolean overrideToPortrait, CameraInfo cameraInfo) {
        _getCameraInfo(cameraId, overrideToPortrait, context.getDeviceId(),
            int rotationOverride, CameraInfo cameraInfo) {
        _getCameraInfo(cameraId, rotationOverride, context.getDeviceId(),
                getDevicePolicyFromContext(context), cameraInfo);
        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
        IAudioService audioService = IAudioService.Stub.asInterface(b);
@@ -336,7 +336,7 @@ public class Camera {
        }
    }

    private native static void _getCameraInfo(int cameraId, boolean overrideToPortrait,
    private native static void _getCameraInfo(int cameraId, int rotationOverride,
            int deviceId, int devicePolicy, CameraInfo cameraInfo);

    private static int getDevicePolicyFromContext(Context context) {
@@ -441,8 +441,8 @@ public class Camera {
     */
    public static Camera open(int cameraId) {
        Context context = ActivityThread.currentApplication().getApplicationContext();
        boolean overrideToPortrait = CameraManager.shouldOverrideToPortrait(context);
        return open(cameraId, context, overrideToPortrait);
        final int rotationOverride = CameraManager.getRotationOverride(context);
        return open(cameraId, context, rotationOverride);
    }

    /**
@@ -452,8 +452,8 @@ public class Camera {
     */
    @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
    @TestApi
    public static Camera open(int cameraId, @NonNull Context context, boolean overrideToPortrait) {
        return new Camera(cameraId, context, overrideToPortrait);
    public static Camera open(int cameraId, @NonNull Context context, int rotationOverride) {
        return new Camera(cameraId, context, rotationOverride);
    }

    /**
@@ -524,7 +524,7 @@ public class Camera {
        return open(cameraId);
    }

    private int cameraInit(int cameraId, Context context, boolean overrideToPortrait) {
    private int cameraInit(int cameraId, Context context, int rotationOverride) {
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
@@ -544,7 +544,7 @@ public class Camera {

        boolean forceSlowJpegMode = shouldForceSlowJpegMode();
        return native_setup(new WeakReference<>(this), cameraId,
                ActivityThread.currentOpPackageName(), overrideToPortrait, forceSlowJpegMode,
                ActivityThread.currentOpPackageName(), rotationOverride, forceSlowJpegMode,
                context.getDeviceId(), getDevicePolicyFromContext(context));
    }

@@ -562,9 +562,9 @@ public class Camera {
    }

    /** used by Camera#open, Camera#open(int) */
    Camera(int cameraId, @NonNull Context context, boolean overrideToPortrait) {
    Camera(int cameraId, @NonNull Context context, int rotationOverride) {
        Objects.requireNonNull(context);
        int err = cameraInit(cameraId, context, overrideToPortrait);
        final int err = cameraInit(cameraId, context, rotationOverride);
        if (checkInitErrors(err)) {
            if (err == -EACCES) {
                throw new RuntimeException("Fail to connect to camera service");
@@ -629,7 +629,7 @@ public class Camera {

    @UnsupportedAppUsage
    private native int native_setup(Object cameraThis, int cameraId, String packageName,
            boolean overrideToPortrait, boolean forceSlowJpegMode, int deviceId, int devicePolicy);
            int rotationOverride, boolean forceSlowJpegMode, int deviceId, int devicePolicy);

    private native final void native_release();

+120 −14
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager;
import android.compat.annotation.ChangeId;
@@ -168,6 +170,36 @@ public final class CameraManager {
    public static final String LANDSCAPE_TO_PORTRAIT_PROP =
            "camera.enable_landscape_to_portrait";

    /**
     * Does not override landscape feed to portrait.
     *
     * @hide
     */
    @TestApi
    @FlaggedApi(com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM)
    public static final int ROTATION_OVERRIDE_NONE = ICameraService.ROTATION_OVERRIDE_NONE;

    /**
     * Crops and rotates landscape camera feed to portrait, and changes sensor orientation to
     * portrait.
     *
     * @hide
     */
    @TestApi
    @FlaggedApi(com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM)
    public static final int ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT =
            ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT;

    /**
     * Crops and rotates landscape camera feed to portrait, but doesn't change sensor orientation.
     *
     * @hide
     */
    @TestApi
    @FlaggedApi(com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM)
    public static final int ROTATION_OVERRIDE_ROTATION_ONLY =
            ICameraService.ROTATION_OVERRIDE_ROTATION_ONLY;

    /**
     * Enable physical camera availability callbacks when the logical camera is unavailable
     *
@@ -627,7 +659,8 @@ public final class CameraManager {
                CameraMetadataNative physicalCameraInfo =
                        cameraService.getCameraCharacteristics(physicalCameraId,
                                mContext.getApplicationInfo().targetSdkVersion,
                                /*overrideToPortrait*/ false, DEVICE_ID_DEFAULT,
                                /*rotationOverride*/ ICameraService.ROTATION_OVERRIDE_NONE,
                                DEVICE_ID_DEFAULT,
                                DEVICE_POLICY_DEFAULT);
                StreamConfiguration[] configs = physicalCameraInfo.get(
                        CameraCharacteristics.
@@ -674,7 +707,7 @@ public final class CameraManager {
    @NonNull
    public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)
            throws CameraAccessException {
        return getCameraCharacteristics(cameraId, shouldOverrideToPortrait(mContext));
        return getCameraCharacteristics(cameraId, getRotationOverride(mContext));
    }

    /**
@@ -699,7 +732,16 @@ public final class CameraManager {
    @NonNull
    public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId,
            boolean overrideToPortrait) throws CameraAccessException {
        CameraCharacteristics characteristics;
        return getCameraCharacteristics(cameraId,
                overrideToPortrait
                        ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                        : ICameraService.ROTATION_OVERRIDE_NONE);
    }

    @NonNull
    private CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId,
            int rotationOverride) throws CameraAccessException {
        CameraCharacteristics characteristics = null;
        if (CameraManagerGlobal.sCameraServiceDisabled) {
            throw new IllegalArgumentException("No cameras available on device");
        }
@@ -711,7 +753,7 @@ public final class CameraManager {
            }
            try {
                CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
                        mContext.getApplicationInfo().targetSdkVersion, overrideToPortrait,
                        mContext.getApplicationInfo().targetSdkVersion, rotationOverride,
                        mContext.getDeviceId(), getDevicePolicyFromContext(mContext));
                characteristics = prepareCameraCharacteristics(cameraId, info, cameraService);
            } catch (ServiceSpecificException e) {
@@ -926,7 +968,7 @@ public final class CameraManager {
     */
    private CameraDevice openCameraDeviceUserAsync(String cameraId,
            CameraDevice.StateCallback callback, Executor executor, final int uid,
            final int oomScoreOffset, boolean overrideToPortrait) throws CameraAccessException {
            final int oomScoreOffset, int rotationOverride) throws CameraAccessException {
        CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
        CameraDevice device = null;
        Map<String, CameraCharacteristics> physicalIdsToChars =
@@ -961,7 +1003,7 @@ public final class CameraManager {
                cameraUser = cameraService.connectDevice(callbacks, cameraId,
                    mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
                    oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion,
                    overrideToPortrait, mContext.getDeviceId(),
                        rotationOverride, mContext.getDeviceId(),
                        getDevicePolicyFromContext(mContext));
            } catch (ServiceSpecificException e) {
                if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
@@ -1126,7 +1168,10 @@ public final class CameraManager {
            @Nullable Handler handler,
            @NonNull final CameraDevice.StateCallback callback) throws CameraAccessException {
        openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
                         USE_CALLING_UID, /*oomScoreOffset*/0, overrideToPortrait);
                         USE_CALLING_UID, /*oomScoreOffset*/0,
                         overrideToPortrait
                                 ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                                 : ICameraService.ROTATION_OVERRIDE_NONE);
    }

    /**
@@ -1240,7 +1285,7 @@ public final class CameraManager {
                    "oomScoreOffset < 0, cannot increase priority of camera client");
        }
        openCameraForUid(cameraId, callback, executor, USE_CALLING_UID, oomScoreOffset,
                shouldOverrideToPortrait(mContext));
                getRotationOverride(mContext));
    }

    /**
@@ -1258,11 +1303,14 @@ public final class CameraManager {
     *             Must be USE_CALLING_UID unless the caller is a trusted service.
     * @param oomScoreOffset
     *             The minimum oom score that cameraservice must see for this client.
     * @param rotationOverride
     *             The type of rotation override (none, override_to_portrait, rotation_only)
     *             that should be followed for this camera id connection
     * @hide
     */
    public void openCameraForUid(@NonNull String cameraId,
            @NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
            int clientUid, int oomScoreOffset, boolean overrideToPortrait)
            int clientUid, int oomScoreOffset, int rotationOverride)
            throws CameraAccessException {

        if (cameraId == null) {
@@ -1275,7 +1323,7 @@ public final class CameraManager {
        }

        openCameraDeviceUserAsync(cameraId, callback, executor, clientUid, oomScoreOffset,
                overrideToPortrait);
                rotationOverride);
    }

    /**
@@ -1297,7 +1345,7 @@ public final class CameraManager {
            @NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
            int clientUid) throws CameraAccessException {
        openCameraForUid(cameraId, callback, executor, clientUid, /*oomScoreOffset*/0,
                shouldOverrideToPortrait(mContext));
                getRotationOverride(mContext));
    }

    /**
@@ -1442,7 +1490,7 @@ public final class CameraManager {
    /**
     * @hide
     */
    public static boolean shouldOverrideToPortrait(@Nullable Context context) {
    public static int getRotationOverride(@Nullable Context context) {
        PackageManager packageManager = null;
        String packageName = null;

@@ -1451,7 +1499,64 @@ public final class CameraManager {
            packageName = context.getOpPackageName();
        }

        return shouldOverrideToPortrait(packageManager, packageName);
        return getRotationOverride(context, packageManager, packageName);
    }

    /**
     * @hide
     */
    public static int getRotationOverride(@Nullable Context context,
            @Nullable PackageManager packageManager, @Nullable String packageName) {
        if (com.android.window.flags.Flags.cameraCompatForFreeform()) {
            return getRotationOverrideInternal(context, packageManager, packageName);
        } else {
            return shouldOverrideToPortrait(packageManager, packageName)
                        ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                        : ICameraService.ROTATION_OVERRIDE_NONE;
        }
    }

    /**
     * @hide
     */
    @FlaggedApi(com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM)
    @TestApi
    public static int getRotationOverrideInternal(@Nullable Context context,
            @Nullable PackageManager packageManager, @Nullable String packageName) {
        if (!CameraManagerGlobal.sLandscapeToPortrait) {
            return ICameraService.ROTATION_OVERRIDE_NONE;
        }

        if (context != null) {
            final ActivityManager activityManager =
                    context.getSystemService(ActivityManager.class);
            for (ActivityManager.AppTask appTask : activityManager.getAppTasks()) {
                final TaskInfo taskInfo = appTask.getTaskInfo();
                if (taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode
                        != 0
                        && taskInfo.topActivity != null
                        && taskInfo.topActivity.getPackageName().equals(packageName)) {
                    // WindowManager has requested rotation override.
                    return ICameraService.ROTATION_OVERRIDE_ROTATION_ONLY;
                }
            }
        }

        if (packageManager != null && packageName != null) {
            try {
                return packageManager.getProperty(
                        PackageManager.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT,
                        packageName).getBoolean()
                        ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                        : ICameraService.ROTATION_OVERRIDE_NONE;
            } catch (PackageManager.NameNotFoundException e) {
                // No such property
            }
        }

        return CompatChanges.isChangeEnabled(OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT)
                ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                : ICameraService.ROTATION_OVERRIDE_NONE;
    }

    /**
@@ -1477,6 +1582,7 @@ public final class CameraManager {
        return CompatChanges.isChangeEnabled(OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT);
    }


    /**
     * @hide
     */
+2 −1
Original line number Diff line number Diff line
@@ -134,7 +134,8 @@ public class CameraDeviceSetupImpl extends CameraDevice.CameraDeviceSetup {
            try {
                CameraMetadataNative metadata = cameraService.getSessionCharacteristics(
                        mCameraId, mTargetSdkVersion,
                        CameraManager.shouldOverrideToPortrait(mContext), sessionConfig,
                        CameraManager.getRotationOverride(mContext),
                        sessionConfig,
                        mContext.getDeviceId(),
                        mCameraManager.getDevicePolicyFromContext(mContext));

+7 −7
Original line number Diff line number Diff line
@@ -529,7 +529,7 @@ static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz
}

static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, jint cameraId,
                                                  jboolean overrideToPortrait, jint deviceId,
                                                  jint rotationOverride, jint deviceId,
                                                  jint devicePolicy, jobject info_obj) {
    CameraInfo cameraInfo;
    if (cameraId >= Camera::getNumberOfCameras(deviceId, devicePolicy) || cameraId < 0) {
@@ -538,7 +538,7 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, jin
        return;
    }

    status_t rc = Camera::getCameraInfo(cameraId, overrideToPortrait, deviceId, devicePolicy,
    status_t rc = Camera::getCameraInfo(cameraId, rotationOverride, deviceId, devicePolicy,
                                        &cameraInfo);
    if (rc != NO_ERROR) {
        jniThrowRuntimeException(env, "Fail to get camera info");
@@ -557,7 +557,7 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, jin
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
                                                 jint cameraId, jstring clientPackageName,
                                                 jboolean overrideToPortrait,
                                                 jint rotationOverride,
                                                 jboolean forceSlowJpegMode, jint deviceId,
                                                 jint devicePolicy) {
    // Convert jstring to String16
@@ -571,7 +571,7 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj
    int targetSdkVersion = android_get_application_target_sdk_version();
    sp<Camera> camera =
            Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID, Camera::USE_CALLING_PID,
                            targetSdkVersion, overrideToPortrait, forceSlowJpegMode, deviceId,
                            targetSdkVersion, rotationOverride, forceSlowJpegMode, deviceId,
                            devicePolicy);
    if (camera == NULL) {
        return -EACCES;
@@ -600,7 +600,7 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj

    // Update default display orientation in case the sensor is reverse-landscape
    CameraInfo cameraInfo;
    status_t rc = Camera::getCameraInfo(cameraId, overrideToPortrait, deviceId, devicePolicy,
    status_t rc = Camera::getCameraInfo(cameraId, rotationOverride, deviceId, devicePolicy,
                                        &cameraInfo);
    if (rc != NO_ERROR) {
        ALOGE("%s: getCameraInfo error: %d", __FUNCTION__, rc);
@@ -1057,9 +1057,9 @@ static int32_t android_hardware_Camera_getAudioRestriction(

static const JNINativeMethod camMethods[] = {
        {"_getNumberOfCameras", "(II)I", (void *)android_hardware_Camera_getNumberOfCameras},
        {"_getCameraInfo", "(IZIILandroid/hardware/Camera$CameraInfo;)V",
        {"_getCameraInfo", "(IIIILandroid/hardware/Camera$CameraInfo;)V",
         (void *)android_hardware_Camera_getCameraInfo},
        {"native_setup", "(Ljava/lang/Object;ILjava/lang/String;ZZII)I",
        {"native_setup", "(Ljava/lang/Object;ILjava/lang/String;IZII)I",
         (void *)android_hardware_Camera_native_setup},
        {"native_release", "()V", (void *)android_hardware_Camera_release},
        {"setPreviewSurface", "(Landroid/view/Surface;)V",
Loading