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

Commit 661f02de authored by Alex Chau's avatar Alex Chau
Browse files

Use normalized CachedDisplayInfo as key

- For system Launcher, migrate to use getPossibleMaximumWindowMetrics instead of getDisplays
- Removed usage of displayId
- In estimateInternalDisplayBounds, use CachedDisplayInfo directly as a key
- When cache retunrs null for the current display (e.g. the 3P launcher case), invalidate the cache and estimate again, and only add to supportedBounds if current display is not found in the new cache

Bug: 227459045
Bug: 198965093
Test: manual
Change-Id: Ibcc05ba483ed31a40d16e3cf49c3f3d43af68cf6
parent d3a7d37a
Loading
Loading
Loading
Loading
+25 −10
Original line number Diff line number Diff line
@@ -15,11 +15,20 @@
 */
package com.android.quickstep.util;

import static android.view.Display.DEFAULT_DISPLAY;

import android.content.Context;
import android.view.Display;
import android.util.ArrayMap;
import android.view.Surface;
import android.view.WindowManager;
import android.view.WindowMetrics;

import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.CachedDisplayInfo;
import com.android.launcher3.util.window.WindowManagerProxy;

import java.util.Set;

/**
 * Extension of {@link WindowManagerProxy} with some assumption for the default system Launcher
 */
@@ -30,17 +39,23 @@ public class SystemWindowManagerProxy extends WindowManagerProxy {
    }

    @Override
    protected String getDisplayId(Display display) {
        return display.getUniqueId();
    public int getRotation(Context displayInfoContext) {
        return displayInfoContext.getResources().getConfiguration().windowConfiguration
                .getRotation();
    }

    @Override
    public boolean isInternalDisplay(Display display) {
        return display.getType() == Display.TYPE_INTERNAL;
    public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
            Context displayInfoContext) {
        ArrayMap<CachedDisplayInfo, 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);
            result.put(info, bounds);
        }

    @Override
    public int getRotation(Context context) {
        return context.getResources().getConfiguration().windowConfiguration.getRotation();
        return result;
    }
}
+7 −6
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Size;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;

@@ -290,15 +289,17 @@ public class OrientationTouchTransformerTest {
    private DisplayController.Info createDisplayInfo(Size screenSize, int rotation) {
        Point displaySize = new Point(screenSize.getWidth(), screenSize.getHeight());
        RotationUtils.rotateSize(displaySize, rotation);
        CachedDisplayInfo cdi = new CachedDisplayInfo(displaySize, rotation);
        WindowBounds wm = new WindowBounds(
        CachedDisplayInfo cachedDisplayInfo = new CachedDisplayInfo(displaySize, rotation);
        WindowBounds windowBounds = new WindowBounds(
                new Rect(0, 0, displaySize.x, displaySize.y),
                new Rect());
        WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
        doReturn(cdi).when(wmProxy).getDisplayInfo(any(), any());
        doReturn(wm).when(wmProxy).getRealBounds(any(), any(), any());
        doReturn(cachedDisplayInfo).when(wmProxy).getDisplayInfo(any());
        doReturn(windowBounds).when(wmProxy).getRealBounds(any(), any());
        ArrayMap<CachedDisplayInfo, WindowBounds[]> internalDisplayBounds = new ArrayMap<>();
        doReturn(internalDisplayBounds).when(wmProxy).estimateInternalDisplayBounds(any());
        return new DisplayController.Info(
                getApplicationContext(), mock(Display.class), wmProxy, new ArrayMap<>());
                getApplicationContext(), wmProxy, new ArrayMap<>());
    }

    private float generateTouchRegionHeight(Size screenSize, int rotation) {
+6 −8
Original line number Diff line number Diff line
@@ -23,8 +23,6 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.ArrayMap;
import android.util.Pair;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;

@@ -148,7 +146,7 @@ public class TaskViewSimulatorTest {
                int rotation = mDisplaySize.x > mDisplaySize.y
                        ? Surface.ROTATION_90 : Surface.ROTATION_0;
                CachedDisplayInfo cdi =
                        new CachedDisplayInfo("test-display", mDisplaySize, rotation , new Rect());
                        new CachedDisplayInfo(mDisplaySize, rotation, new Rect());
                WindowBounds wm = new WindowBounds(
                        new Rect(0, 0, mDisplaySize.x, mDisplaySize.y),
                        mDisplayInsets);
@@ -164,15 +162,15 @@ public class TaskViewSimulatorTest {
                }

                WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
                doReturn(cdi).when(wmProxy).getDisplayInfo(any(), any());
                doReturn(wm).when(wmProxy).getRealBounds(any(), any(), any());
                doReturn(cdi).when(wmProxy).getDisplayInfo(any());
                doReturn(wm).when(wmProxy).getRealBounds(any(), any());

                ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> perDisplayBoundsCache =
                ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache =
                        new ArrayMap<>();
                perDisplayBoundsCache.put(cdi.id, Pair.create(cdi.normalize(), allBounds));
                perDisplayBoundsCache.put(cdi.normalize(), allBounds);

                DisplayController.Info mockInfo = new Info(
                        helper.sandboxContext, mock(Display.class), wmProxy, perDisplayBoundsCache);
                        helper.sandboxContext, wmProxy, perDisplayBoundsCache);

                DisplayController controller =
                        DisplayController.INSTANCE.get(helper.sandboxContext);
+3 −2
Original line number Diff line number Diff line
@@ -234,7 +234,8 @@ public class InvariantDeviceProfile {
                        /*allowDisabledGrid=*/false),
                defaultDeviceType);

        Info myInfo = new Info(context, display);
        Context displayContext = context.createDisplayContext(display);
        Info myInfo = new Info(displayContext);
        @DeviceType int deviceType = getDeviceType(myInfo);
        DisplayOption myDisplayOption = invDistWeightedInterpolate(
                myInfo,
@@ -642,7 +643,7 @@ public class InvariantDeviceProfile {
                            + "\nconfig: " + config
                            + "\ndisplayMetrics: " + res.getDisplayMetrics()
                            + "\nrotation: " + rotation
                            + "\n" + stringWriter.toString(),
                            + "\n" + stringWriter,
                    new Exception());
        }
        return getBestMatch(screenWidth, screenHeight, rotation);
+47 −55
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import android.os.Build;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.view.Display;

import androidx.annotation.AnyThread;
@@ -117,8 +116,9 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
                getPackageFilter(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED));

        WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(context);
        mInfo = new Info(getDisplayInfoContext(display), display,
                wmProxy, wmProxy.estimateInternalDisplayBounds(context));
        Context displayInfoContext = getDisplayInfoContext(display);
        mInfo = new Info(displayInfoContext, wmProxy,
                wmProxy.estimateInternalDisplayBounds(displayInfoContext));
    }

    /**
@@ -216,18 +216,18 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
        WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(mContext);
        Info oldInfo = mInfo;

        Context displayContext = getDisplayInfoContext(display);
        Info newInfo = new Info(displayContext, display, wmProxy, oldInfo.mPerDisplayBounds);
        Context displayInfoContext = getDisplayInfoContext(display);
        Info newInfo = new Info(displayInfoContext, wmProxy, oldInfo.mPerDisplayBounds);

        if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale
                || newInfo.navigationMode != oldInfo.navigationMode) {
            // Cache may not be valid anymore, recreate without cache
            newInfo = new Info(displayContext, display, wmProxy,
                    wmProxy.estimateInternalDisplayBounds(displayContext));
            newInfo = new Info(displayInfoContext, wmProxy,
                    wmProxy.estimateInternalDisplayBounds(displayInfoContext));
        }

        int change = 0;
        if (!newInfo.displayId.equals(oldInfo.displayId)) {
        if (!newInfo.normalizedDisplayInfo.equals(oldInfo.normalizedDisplayInfo)) {
            change |= CHANGE_ACTIVE_SCREEN;
        }
        if (newInfo.rotation != oldInfo.rotation) {
@@ -242,35 +242,16 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
        if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)
                || !newInfo.mPerDisplayBounds.equals(oldInfo.mPerDisplayBounds)) {
            change |= CHANGE_SUPPORTED_BOUNDS;

            Point currentS = newInfo.currentSize;
            Pair<CachedDisplayInfo, WindowBounds[]> cachedBounds =
                    oldInfo.mPerDisplayBounds.get(newInfo.displayId);
            Point expectedS = cachedBounds == null ? null : cachedBounds.first.size;
            if (newInfo.supportedBounds.size() != oldInfo.supportedBounds.size()) {
                Log.e("b/198965093",
                        "Inconsistent number of displays"
                                + "\ndisplay state: " + display.getState()
                                + "\noldInfo.supportedBounds: " + oldInfo.supportedBounds
                                + "\nnewInfo.supportedBounds: " + newInfo.supportedBounds);
            }
            if (expectedS != null
                    && (Math.min(currentS.x, currentS.y) != Math.min(expectedS.x, expectedS.y)
                    || Math.max(currentS.x, currentS.y) != Math.max(expectedS.x, expectedS.y))
                    && display.getState() == Display.STATE_OFF) {
                Log.e("b/198965093",
                        "Display size changed while display is off, ignoring change");
                return;
            }
        }
        Log.d("b/198965093", "handleInfoChange"
                + "\n\tchange: " + change
                + "\n\tConfiguration diff: " + newInfo.mConfiguration.diff(oldInfo.mConfiguration));
                + "\n\tchange: 0b" + Integer.toBinaryString(change)
                + "\n\tConfiguration diff: 0x" + Integer.toHexString(
                        newInfo.mConfiguration.diff(oldInfo.mConfiguration)));

        if (change != 0) {
            mInfo = newInfo;
            final int flags = change;
            MAIN_EXECUTOR.execute(() -> notifyChange(displayContext, flags));
            MAIN_EXECUTOR.execute(() -> notifyChange(displayInfoContext, flags));
        }
    }

@@ -288,8 +269,8 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
    public static class Info {

        // Cached property
        public final CachedDisplayInfo normalizedDisplayInfo;
        public final int rotation;
        public final String displayId;
        public final Point currentSize;
        public final Rect cutout;

@@ -302,60 +283,71 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {

        public final Set<WindowBounds> supportedBounds = new ArraySet<>();

        private final ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> mPerDisplayBounds =
        private final ArrayMap<CachedDisplayInfo, WindowBounds[]> mPerDisplayBounds =
                new ArrayMap<>();

        // TODO(b/198965093): Remove after investigation
        private Configuration mConfiguration;

        public Info(Context context, Display display) {
        public Info(Context displayInfoContext) {
            /* don't need system overrides for external displays */
            this(context, display, new WindowManagerProxy(), new ArrayMap<>());
            this(displayInfoContext, new WindowManagerProxy(), new ArrayMap<>());
        }

        // Used for testing
        public Info(Context context, Display display,
        public Info(Context displayInfoContext,
                WindowManagerProxy wmProxy,
                ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> perDisplayBoundsCache) {
            CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(context, display);
                ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache) {
            CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(displayInfoContext);
            normalizedDisplayInfo = displayInfo.normalize();
            rotation = displayInfo.rotation;
            currentSize = displayInfo.size;
            displayId = displayInfo.id;
            cutout = displayInfo.cutout;

            Configuration config = context.getResources().getConfiguration();
            Configuration config = displayInfoContext.getResources().getConfiguration();
            fontScale = config.fontScale;
            densityDpi = config.densityDpi;
            mScreenSizeDp = new PortraitSize(config.screenHeightDp, config.screenWidthDp);
            navigationMode = parseNavigationMode(context);
            navigationMode = parseNavigationMode(displayInfoContext);

            // TODO(b/198965093): Remove after investigation
            mConfiguration = config;

            mPerDisplayBounds.putAll(perDisplayBoundsCache);
            Pair<CachedDisplayInfo, WindowBounds[]> cachedValue = mPerDisplayBounds.get(displayId);
            WindowBounds[] cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);

            WindowBounds realBounds = wmProxy.getRealBounds(context, display, displayInfo);
            WindowBounds realBounds = wmProxy.getRealBounds(displayInfoContext, displayInfo);
            if (cachedValue == null) {
                // Unexpected normalizedDisplayInfo is found, recreate the cache
                Log.e("b/198965093", "Unexpected normalizedDisplayInfo found, invalidating cache");
                mPerDisplayBounds.clear();
                mPerDisplayBounds.putAll(wmProxy.estimateInternalDisplayBounds(displayInfoContext));
                cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
                if (cachedValue == null) {
                    Log.e("b/198965093", "normalizedDisplayInfo not found in estimation: "
                            + normalizedDisplayInfo);
                    supportedBounds.add(realBounds);
            } else {
                }
            }

            if (cachedValue != null) {
                // Verify that the real bounds are a match
                WindowBounds expectedBounds = cachedValue.second[displayInfo.rotation];
                WindowBounds expectedBounds = cachedValue[displayInfo.rotation];
                if (!realBounds.equals(expectedBounds)) {
                    WindowBounds[] clone = new WindowBounds[4];
                    System.arraycopy(cachedValue.second, 0, clone, 0, 4);
                    System.arraycopy(cachedValue, 0, clone, 0, 4);
                    clone[displayInfo.rotation] = realBounds;
                    cachedValue = Pair.create(displayInfo.normalize(), clone);
                    mPerDisplayBounds.put(displayId, cachedValue);
                    mPerDisplayBounds.put(normalizedDisplayInfo, clone);
                }
            }
            mPerDisplayBounds.values().forEach(
                    pair -> Collections.addAll(supportedBounds, pair.second));
                    windowBounds -> Collections.addAll(supportedBounds, windowBounds));
            Log.e("b/198965093", "mConfiguration: " + mConfiguration);
            Log.d("b/198965093", "displayInfo: " + displayInfo);
            Log.d("b/198965093", "realBounds: " + realBounds);
            mPerDisplayBounds.values().forEach(pair -> Log.d("b/198965093",
                    "perDisplayBounds - " + pair.first + ": " + Arrays.deepToString(pair.second)));
            Log.d("b/198965093", "normalizedDisplayInfo: " + normalizedDisplayInfo);
            mPerDisplayBounds.forEach((key, value) -> Log.d("b/198965093",
                    "perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
        }

        /**
@@ -383,14 +375,14 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
    public void dump(PrintWriter pw) {
        Info info = mInfo;
        pw.println("DisplayController.Info:");
        pw.println("  id=" + info.displayId);
        pw.println("  normalizedDisplayInfo=" + info.normalizedDisplayInfo);
        pw.println("  rotation=" + info.rotation);
        pw.println("  fontScale=" + info.fontScale);
        pw.println("  densityDpi=" + info.densityDpi);
        pw.println("  navigationMode=" + info.navigationMode.name());
        pw.println("  currentSize=" + info.currentSize);
        info.mPerDisplayBounds.values().forEach(pair -> pw.println(
                "  perDisplayBounds - " + pair.first + ": " + Arrays.deepToString(pair.second)));
        info.mPerDisplayBounds.forEach((key, value) -> pw.println(
                "  perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
    }

    /**
Loading