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

Commit 7af659da authored by Alex Chau's avatar Alex Chau
Browse files

DisplayController should deep compare mPerDisplayBounds

- In CHANGE_SUPPORTED_BOUNDS check, it uses Map.equals, but as the value is a primitive array WindowBounds[], equals check does not deep compare the arrays and may result in false negative
- One example is when fontScale changes, DisplayController re-create bounds from WindowManagerProxy, result in new WindowBounds[] created, and the shallow compare results in unexpected CHANGE_SUPPORTED_BOUNDS

Fix: 282736623
Test: DisplayControllerTest
Change-Id: I3897595c58559192b951ecfee7c9f62a07dafe1f
parent fb51c85c
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.CachedDisplayInfo;
import com.android.launcher3.util.window.WindowManagerProxy;

import java.util.List;
import java.util.Set;

/**
@@ -53,15 +54,15 @@ public class SystemWindowManagerProxy extends WindowManagerProxy {
    }

    @Override
    public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
    public ArrayMap<CachedDisplayInfo, List<WindowBounds>> estimateInternalDisplayBounds(
            Context displayInfoContext) {
        ArrayMap<CachedDisplayInfo, WindowBounds[]> result = new ArrayMap<>();
        ArrayMap<CachedDisplayInfo, List<WindowBounds>> result = new ArrayMap<>();
        WindowManager windowManager = displayInfoContext.getSystemService(WindowManager.class);
        Set<WindowMetrics> possibleMaximumWindowMetrics =
                windowManager.getPossibleMaximumWindowMetrics(DEFAULT_DISPLAY);
        for (WindowMetrics windowMetrics : possibleMaximumWindowMetrics) {
            CachedDisplayInfo info = getDisplayInfo(windowMetrics, Surface.ROTATION_0);
            WindowBounds[] bounds = estimateWindowBounds(displayInfoContext, info);
            List<WindowBounds> bounds = estimateWindowBounds(displayInfoContext, info);
            result.put(info, bounds);
        }
        return result;
+3 −1
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;

import java.util.List;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class OrientationTouchTransformerTest {
@@ -296,7 +298,7 @@ public class OrientationTouchTransformerTest {
        WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
        doReturn(cachedDisplayInfo).when(wmProxy).getDisplayInfo(any());
        doReturn(windowBounds).when(wmProxy).getRealBounds(any(), any());
        ArrayMap<CachedDisplayInfo, WindowBounds[]> internalDisplayBounds = new ArrayMap<>();
        ArrayMap<CachedDisplayInfo, List<WindowBounds>> internalDisplayBounds = new ArrayMap<>();
        doReturn(internalDisplayBounds).when(wmProxy).estimateInternalDisplayBounds(any());
        return new DisplayController.Info(
                getApplicationContext(), wmProxy, new ArrayMap<>());
+6 −3
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@ import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.List;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskViewSimulatorTest {
@@ -150,7 +153,7 @@ public class TaskViewSimulatorTest {
                WindowBounds wm = new WindowBounds(
                        new Rect(0, 0, mDisplaySize.x, mDisplaySize.y),
                        mDisplayInsets);
                WindowBounds[] allBounds = new WindowBounds[4];
                List<WindowBounds> allBounds = new ArrayList<>(4);
                for (int i = 0; i < 4; i++) {
                    Rect boundsR = new Rect(wm.bounds);
                    Rect insetsR = new Rect(wm.insets);
@@ -158,7 +161,7 @@ public class TaskViewSimulatorTest {
                    RotationUtils.rotateRect(insetsR, RotationUtils.deltaRotation(rotation, i));
                    RotationUtils.rotateRect(boundsR, RotationUtils.deltaRotation(rotation, i));
                    boundsR.set(0, 0, Math.abs(boundsR.width()), Math.abs(boundsR.height()));
                    allBounds[i] = new WindowBounds(boundsR, insetsR);
                    allBounds.add(new WindowBounds(boundsR, insetsR));
                }

                WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
@@ -166,7 +169,7 @@ public class TaskViewSimulatorTest {
                doReturn(wm).when(wmProxy).getRealBounds(any(), any());
                doReturn(NavigationMode.NO_BUTTON).when(wmProxy).getNavigationMode(any());

                ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache =
                ArrayMap<CachedDisplayInfo, List<WindowBounds>> perDisplayBoundsCache =
                        new ArrayMap<>();
                perDisplayBoundsCache.put(cdi.normalize(), allBounds);

+12 −13
Original line number Diff line number Diff line
@@ -53,8 +53,8 @@ import com.android.launcher3.util.window.WindowManagerProxy;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -105,7 +105,8 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {

    private final LauncherPrefs mPrefs;

    private DisplayController(Context context) {
    @VisibleForTesting
    protected DisplayController(Context context) {
        mContext = context;
        mDM = context.getSystemService(DisplayManager.class);
        mPrefs = LauncherPrefs.get(context);
@@ -323,7 +324,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
        // WindowBounds
        public final WindowBounds realBounds;
        public final Set<WindowBounds> supportedBounds = new ArraySet<>();
        private final ArrayMap<CachedDisplayInfo, WindowBounds[]> mPerDisplayBounds =
        private final ArrayMap<CachedDisplayInfo, List<WindowBounds>> mPerDisplayBounds =
                new ArrayMap<>();

        public Info(Context displayInfoContext) {
@@ -334,7 +335,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
        // Used for testing
        public Info(Context displayInfoContext,
                WindowManagerProxy wmProxy,
                Map<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache) {
                Map<CachedDisplayInfo, List<WindowBounds>> perDisplayBoundsCache) {
            CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(displayInfoContext);
            normalizedDisplayInfo = displayInfo.normalize();
            rotation = displayInfo.rotation;
@@ -348,7 +349,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
            navigationMode = wmProxy.getNavigationMode(displayInfoContext);

            mPerDisplayBounds.putAll(perDisplayBoundsCache);
            WindowBounds[] cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
            List<WindowBounds> cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);

            realBounds = wmProxy.getRealBounds(displayInfoContext, displayInfo);
            if (cachedValue == null) {
@@ -366,22 +367,20 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {

            if (cachedValue != null) {
                // Verify that the real bounds are a match
                WindowBounds expectedBounds = cachedValue[displayInfo.rotation];
                WindowBounds expectedBounds = cachedValue.get(displayInfo.rotation);
                if (!realBounds.equals(expectedBounds)) {
                    WindowBounds[] clone = new WindowBounds[4];
                    System.arraycopy(cachedValue, 0, clone, 0, 4);
                    clone[displayInfo.rotation] = realBounds;
                    List<WindowBounds> clone = new ArrayList<>(cachedValue);
                    clone.set(displayInfo.rotation, realBounds);
                    mPerDisplayBounds.put(normalizedDisplayInfo, clone);
                }
            }
            mPerDisplayBounds.values().forEach(
                    windowBounds -> Collections.addAll(supportedBounds, windowBounds));
            mPerDisplayBounds.values().forEach(supportedBounds::addAll);
            if (DEBUG) {
                Log.d(TAG, "displayInfo: " + displayInfo);
                Log.d(TAG, "realBounds: " + realBounds);
                Log.d(TAG, "normalizedDisplayInfo: " + normalizedDisplayInfo);
                mPerDisplayBounds.forEach((key, value) -> Log.d(TAG,
                        "perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
                        "perDisplayBounds - " + key + ": " + value));
            }
        }

@@ -438,7 +437,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
        pw.println("  navigationMode=" + info.navigationMode.name());
        pw.println("  currentSize=" + info.currentSize);
        info.mPerDisplayBounds.forEach((key, value) -> pw.println(
                "  perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
                "  perDisplayBounds - " + key + ": " + value));
    }

    /**
+2 −1
Original line number Diff line number Diff line
@@ -131,7 +131,8 @@ public class MainThreadInitializedObject<T> {
         * Find a cached object from mObjectMap if we have already created one. If not, generate
         * an object using the provider.
         */
        private <T> T getObject(MainThreadInitializedObject<T> object, ObjectProvider<T> provider) {
        protected <T> T getObject(MainThreadInitializedObject<T> object,
                ObjectProvider<T> provider) {
            synchronized (mDestroyLock) {
                if (mDestroyed) {
                    Log.e(TAG, "Static object access with a destroyed context");
Loading