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

Commit 6da3cc02 authored by Robert Carr's avatar Robert Carr
Browse files

Implement seamless rotation mode.

Add a rotation mode which does not require freezing
the screen. For situations like Camera where only small
elements move on screen, this allows for seamless changes
of display orientation. This is achieved by transforming the
windows with their current buffer in the same transaction that
we rotate the display. We set things up so the windows are
frozen this way until they submit buffers in the new orientation.
There is a special case in the Camera window itself, and it's use
of NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY. In this case the buffer
contents are rotated by SurfaceFlinger and will never resize, for these
windows we just need to update the scaling matrix.

Bug: 28823590
Change-Id: I52dc6a86fcb3c08f736f0977ba3975a24fb8136c
parent d46ae2f7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ public class Surface implements Parcelable {

    private static native long nativeGetNextFrameNumber(long nativeObject);
    private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
    private static native void nativeSetBuffersTransform(long nativeObject, long transform);

    public static final Parcelable.Creator<Surface> CREATOR =
            new Parcelable.Creator<Surface>() {
+13 −5
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ public class SurfaceControl {

    private static native void nativeSetLayer(long nativeObject, int zorder);
    private static native void nativeSetPosition(long nativeObject, float x, float y);
    private static native void nativeSetPositionAppliesWithResize(long nativeObject);
    private static native void nativeSetGeometryAppliesWithResize(long nativeObject);
    private static native void nativeSetSize(long nativeObject, int w, int h);
    private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
    private static native void nativeSetAlpha(long nativeObject, float alpha);
@@ -89,6 +89,8 @@ public class SurfaceControl {
    private static native void nativeSetOverrideScalingMode(long nativeObject,
            int scalingMode);
    private static native IBinder nativeGetHandle(long nativeObject);
    private static native boolean nativeGetTransformToDisplayInverse(long nativeObject);

    private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);


@@ -393,6 +395,10 @@ public class SurfaceControl {
        return nativeGetHandle(mNativeObject);
    }

    public boolean getTransformToDisplayInverse() {
        return nativeGetTransformToDisplayInverse(mNativeObject);
    }

    /** flag the transaction as an animation */
    public static void setAnimationTransaction() {
        nativeSetAnimationTransaction();
@@ -409,13 +415,15 @@ public class SurfaceControl {
    }

    /**
     * If the size changes in this transaction, position updates specified
     * If the buffer size changes in this transaction, position and crop updates specified
     * in this transaction will not complete until a buffer of the new size
     * arrives.
     * arrives. As transform matrix and size are already frozen in this fashion,
     * this enables totally freezing the surface until the resize has completed
     * (at which point the geometry influencing aspects of this transaction will then occur)
     */
    public void setPositionAppliesWithResize() {
    public void setGeometryAppliesWithResize() {
        checkNotReleased();
        nativeSetPositionAppliesWithResize(mNativeObject);
        nativeSetGeometryAppliesWithResize(mNativeObject);
    }

    public void setSize(int w, int h) {
+2 −0
Original line number Diff line number Diff line
@@ -1410,4 +1410,6 @@ public interface WindowManagerPolicy {
     * Called when the configuration has changed, and it's safe to load new values from resources.
     */
    public void onConfigurationChanged();

    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation);
}
+17 −5
Original line number Diff line number Diff line
@@ -248,10 +248,10 @@ static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfl
    }
}

static void nativeSetPositionAppliesWithResize(JNIEnv* env, jclass clazz,
static void nativeSetGeometryAppliesWithResize(JNIEnv* env, jclass clazz,
        jlong nativeObject) {
    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    status_t err = ctrl->setPositionAppliesWithResize();
    status_t err = ctrl->setGeometryAppliesWithResize();
    if (err < 0 && err != NO_INIT) {
        doThrowIAE(env);
    }
@@ -626,6 +626,16 @@ static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
    return javaObjectForIBinder(env, ctrl->getHandle());
}

static jboolean nativeGetTransformToDisplayInverse(JNIEnv* env, jclass clazz, jlong nativeObject) {
    bool out = false;
    auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    status_t status = ctrl->getTransformToDisplayInverse(&out);
    if (status != NO_ERROR) {
        return false;
    }
    return out;
}

static jobject nativeGetHdrCapabilities(JNIEnv* env, jclass clazz, jobject tokenObject) {
    sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
    if (token == NULL) return NULL;
@@ -667,8 +677,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeSetLayer },
    {"nativeSetPosition", "(JFF)V",
            (void*)nativeSetPosition },
    {"nativeSetPositionAppliesWithResize", "(J)V",
            (void*)nativeSetPositionAppliesWithResize },
    {"nativeSetGeometryAppliesWithResize", "(J)V",
            (void*)nativeSetGeometryAppliesWithResize },
    {"nativeSetSize", "(JII)V",
            (void*)nativeSetSize },
    {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V",
@@ -722,7 +732,9 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
    {"nativeSetOverrideScalingMode", "(JI)V",
            (void*)nativeSetOverrideScalingMode },
    {"nativeGetHandle", "(J)Landroid/os/IBinder;",
            (void*)nativeGetHandle }
            (void*)nativeGetHandle },
    {"nativeGetTransformToDisplayInverse", "(J)Z",
            (void*)nativeGetTransformToDisplayInverse },
};

int register_android_view_SurfaceControl(JNIEnv* env)
+28 −0
Original line number Diff line number Diff line
@@ -7669,6 +7669,34 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        return true;
    }

    @Override
    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
        // For the upside down rotation we don't rotate seamlessly as the navigation
        // bar moves position.
        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
        // will not enter the reverse portrait orientation, so actually the
        // orientation won't change at all.
        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
            return false;
        }
        int delta = newRotation - oldRotation;
        if (delta < 0) delta += 4;
        // Likewise we don't rotate seamlessly for 180 degree rotations
        // in this case the surfaces never resize, and our logic to 
        // revert the transformations on size change will fail. We could
        // fix this in the future with the "tagged" frames idea.
        if (delta == Surface.ROTATION_180) {
            return false;
        }

        if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen &&
                mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation ==
                ROTATION_ANIMATION_JUMPCUT) {
            return true;
        }
        return false;
    }

    @Override
    public void dump(String prefix, PrintWriter pw, String[] args) {
        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
Loading