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

Commit feb5af6b authored by Riddle Hsu's avatar Riddle Hsu Committed by Automerger Merge Worker
Browse files

Add fixed rotation display adjustments am: ca70b013

Change-Id: I4153ed3a90e359f9e77b674b9d03331a7860a0cd
parents e3f85802 ca70b013
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -103,6 +103,14 @@ public final class Display {
    private int mCachedAppWidthCompat;
    private int mCachedAppHeightCompat;

    /**
     * Indicates that the application is started in a different rotation than the real display, so
     * the display information may be adjusted. That ensures the methods {@link #getRotation},
     * {@link #getRealSize}, {@link #getRealMetrics}, and {@link #getCutout} are consistent with how
     * the application window is laid out.
     */
    private boolean mMayAdjustByFixedRotation;

    /**
     * The default Display id, which is the id of the primary display assuming there is one.
     */
@@ -804,7 +812,9 @@ public final class Display {
    public int getRotation() {
        synchronized (this) {
            updateDisplayInfoLocked();
            return mDisplayInfo.rotation;
            return mMayAdjustByFixedRotation
                    ? getDisplayAdjustments().getRotation(mDisplayInfo.rotation)
                    : mDisplayInfo.rotation;
        }
    }

@@ -828,7 +838,9 @@ public final class Display {
    public DisplayCutout getCutout() {
        synchronized (this) {
            updateDisplayInfoLocked();
            return mDisplayInfo.displayCutout;
            return mMayAdjustByFixedRotation
                    ? getDisplayAdjustments().getDisplayCutout(mDisplayInfo.displayCutout)
                    : mDisplayInfo.displayCutout;
        }
    }

@@ -1140,6 +1152,9 @@ public final class Display {
            updateDisplayInfoLocked();
            outSize.x = mDisplayInfo.logicalWidth;
            outSize.y = mDisplayInfo.logicalHeight;
            if (mMayAdjustByFixedRotation) {
                getDisplayAdjustments().adjustSize(outSize, mDisplayInfo.rotation);
            }
        }
    }

@@ -1159,6 +1174,9 @@ public final class Display {
            updateDisplayInfoLocked();
            mDisplayInfo.getLogicalMetrics(outMetrics,
                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
            if (mMayAdjustByFixedRotation) {
                getDisplayAdjustments().adjustMetrics(outMetrics, mDisplayInfo.rotation);
            }
        }
    }

@@ -1225,6 +1243,11 @@ public final class Display {
                }
            }
        }

        // TODO(b/147213487): Replace the condition with per-resources state.
        mMayAdjustByFixedRotation = mIsValid && mResources != null
                && mResources.getConfiguration().windowConfiguration.getRotation()
                != mDisplayInfo.rotation;
    }

    private void updateCachedAppSizeIfNeededLocked() {
@@ -1243,9 +1266,12 @@ public final class Display {
    public String toString() {
        synchronized (this) {
            updateDisplayInfoLocked();
            mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
            final DisplayAdjustments adjustments = getDisplayAdjustments();
            mDisplayInfo.getAppMetrics(mTempMetrics, adjustments);
            return "Display id " + mDisplayId + ": " + mDisplayInfo
                    + ", " + mTempMetrics + ", isValid=" + mIsValid;
                    + (mMayAdjustByFixedRotation
                            ? (", " + adjustments.getFixedRotationAdjustments() + ", ") : ", ")
                    + mTempMetrics + ", isValid=" + mIsValid;
        }
    }

+150 −2
Original line number Diff line number Diff line
@@ -21,6 +21,10 @@ import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayMetrics;

import java.util.Objects;

@@ -30,6 +34,7 @@ public class DisplayAdjustments {

    private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
    private final Configuration mConfiguration = new Configuration(Configuration.EMPTY);
    private FixedRotationAdjustments mFixedRotationAdjustments;

    @UnsupportedAppUsage
    public DisplayAdjustments() {
@@ -44,6 +49,7 @@ public class DisplayAdjustments {
    public DisplayAdjustments(@NonNull DisplayAdjustments daj) {
        setCompatibilityInfo(daj.mCompatInfo);
        mConfiguration.setTo(daj.getConfiguration());
        mFixedRotationAdjustments = daj.mFixedRotationAdjustments;
    }

    @UnsupportedAppUsage
@@ -84,11 +90,78 @@ public class DisplayAdjustments {
        return mConfiguration;
    }

    public void setFixedRotationAdjustments(FixedRotationAdjustments fixedRotationAdjustments) {
        mFixedRotationAdjustments = fixedRotationAdjustments;
    }

    public FixedRotationAdjustments getFixedRotationAdjustments() {
        return mFixedRotationAdjustments;
    }

    /** Returns {@code false} if the width and height of display should swap. */
    private boolean noFlip(@Surface.Rotation int realRotation) {
        final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
        if (rotationAdjustments == null) {
            return true;
        }
        // Check if the delta is rotated by 90 degrees.
        return (realRotation - rotationAdjustments.mRotation + 4) % 2 == 0;
    }

    /** Adjusts the given size if possible. */
    public void adjustSize(@NonNull Point size, @Surface.Rotation int realRotation) {
        if (noFlip(realRotation)) {
            return;
        }
        final int w = size.x;
        size.x = size.y;
        size.y = w;
    }

    /** Adjusts the given metrics if possible. */
    public void adjustMetrics(@NonNull DisplayMetrics metrics, @Surface.Rotation int realRotation) {
        if (noFlip(realRotation)) {
            return;
        }
        int w = metrics.widthPixels;
        metrics.widthPixels = metrics.heightPixels;
        metrics.heightPixels = w;

        w = metrics.noncompatWidthPixels;
        metrics.noncompatWidthPixels = metrics.noncompatHeightPixels;
        metrics.noncompatHeightPixels = w;

        float x = metrics.xdpi;
        metrics.xdpi = metrics.ydpi;
        metrics.ydpi = x;

        x = metrics.noncompatXdpi;
        metrics.noncompatXdpi = metrics.noncompatYdpi;
        metrics.noncompatYdpi = x;
    }

    /** Returns the adjusted cutout if available. Otherwise the original cutout is returned. */
    @Nullable
    public DisplayCutout getDisplayCutout(@Nullable DisplayCutout realCutout) {
        final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
        return rotationAdjustments != null && rotationAdjustments.mRotatedDisplayCutout != null
                ? rotationAdjustments.mRotatedDisplayCutout
                : realCutout;
    }

    /** Returns the adjusted rotation if available. Otherwise the original rotation is returned. */
    @Surface.Rotation
    public int getRotation(@Surface.Rotation int realRotation) {
        final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
        return rotationAdjustments != null ? rotationAdjustments.mRotation : realRotation;
    }

    @Override
    public int hashCode() {
        int hash = 17;
        hash = hash * 31 + Objects.hashCode(mCompatInfo);
        hash = hash * 31 + Objects.hashCode(mConfiguration);
        hash = hash * 31 + Objects.hashCode(mFixedRotationAdjustments);
        return hash;
    }

@@ -98,7 +171,82 @@ public class DisplayAdjustments {
            return false;
        }
        DisplayAdjustments daj = (DisplayAdjustments)o;
        return Objects.equals(daj.mCompatInfo, mCompatInfo) &&
                Objects.equals(daj.mConfiguration, mConfiguration);
        return Objects.equals(daj.mCompatInfo, mCompatInfo)
                && Objects.equals(daj.mConfiguration, mConfiguration)
                && Objects.equals(daj.mFixedRotationAdjustments, mFixedRotationAdjustments);
    }

    /**
     * An application can be launched in different rotation than the real display. This class
     * provides the information to adjust the values returned by {@link #Display}.
     * @hide
     */
    public static class FixedRotationAdjustments implements Parcelable {
        /** The application-based rotation. */
        @Surface.Rotation
        final int mRotation;

        /** Non-null if the device has cutout. */
        @Nullable
        final DisplayCutout mRotatedDisplayCutout;

        public FixedRotationAdjustments(@Surface.Rotation int rotation, DisplayCutout cutout) {
            mRotation = rotation;
            mRotatedDisplayCutout = cutout;
        }

        @Override
        public int hashCode() {
            int hash = 17;
            hash = hash * 31 + mRotation;
            hash = hash * 31 + Objects.hashCode(mRotatedDisplayCutout);
            return hash;
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof FixedRotationAdjustments)) {
                return false;
            }
            final FixedRotationAdjustments other = (FixedRotationAdjustments) o;
            return mRotation == other.mRotation
                    && Objects.equals(mRotatedDisplayCutout, other.mRotatedDisplayCutout);
        }

        @Override
        public String toString() {
            return "FixedRotationAdjustments{rotation=" + Surface.rotationToString(mRotation)
                    + " cutout=" + mRotatedDisplayCutout + "}";
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mRotation);
            dest.writeTypedObject(
                    new DisplayCutout.ParcelableWrapper(mRotatedDisplayCutout), flags);
        }

        private FixedRotationAdjustments(Parcel in) {
            mRotation = in.readInt();
            final DisplayCutout.ParcelableWrapper cutoutWrapper =
                    in.readTypedObject(DisplayCutout.ParcelableWrapper.CREATOR);
            mRotatedDisplayCutout = cutoutWrapper != null ? cutoutWrapper.get() : null;
        }

        public static final Creator<FixedRotationAdjustments> CREATOR =
                new Creator<FixedRotationAdjustments>() {
            public FixedRotationAdjustments createFromParcel(Parcel in) {
                return new FixedRotationAdjustments(in);
            }

            public FixedRotationAdjustments[] newArray(int size) {
                return new FixedRotationAdjustments[size];
            }
        };
    }
}
+37 −0
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package android.view;
import static org.junit.Assert.assertEquals;

import android.content.res.Configuration;
import android.graphics.Point;
import android.util.DisplayMetrics;
import android.view.DisplayAdjustments.FixedRotationAdjustments;

import androidx.test.ext.junit.runners.AndroidJUnit4;

@@ -67,4 +70,38 @@ public class DisplayAdjustmentsTests {

        assertEquals(configuration, newAdjustments.getConfiguration());
    }

    @Test
    public void testFixedRotationAdjustments() {
        final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
        final int realRotation = Surface.ROTATION_0;
        final int fixedRotation = Surface.ROTATION_90;

        mDisplayAdjustments.setFixedRotationAdjustments(
                new FixedRotationAdjustments(fixedRotation, null /* cutout */));

        final int w = 1000;
        final int h = 2000;
        final Point size = new Point(w, h);
        mDisplayAdjustments.adjustSize(size, realRotation);

        assertEquals(fixedRotation, mDisplayAdjustments.getRotation(realRotation));
        assertEquals(new Point(h, w), size);

        final DisplayMetrics metrics = new DisplayMetrics();
        metrics.xdpi = metrics.noncompatXdpi = w;
        metrics.widthPixels = metrics.noncompatWidthPixels = w;
        metrics.ydpi = metrics.noncompatYdpi = h;
        metrics.heightPixels = metrics.noncompatHeightPixels = h;

        final DisplayMetrics flippedMetrics = new DisplayMetrics();
        flippedMetrics.xdpi = flippedMetrics.noncompatXdpi = h;
        flippedMetrics.widthPixels = flippedMetrics.noncompatWidthPixels = h;
        flippedMetrics.ydpi = flippedMetrics.noncompatYdpi = w;
        flippedMetrics.heightPixels = flippedMetrics.noncompatHeightPixels = w;

        mDisplayAdjustments.adjustMetrics(metrics, realRotation);

        assertEquals(flippedMetrics, metrics);
    }
}