Do not reload launcher when changing active display
> Updating IDP to use fixed bitmap sizes, so that the cache
stays valid
> Caching last known windowMetrices for non-active displays and
using estimation only when the cache is not available
> Only reloading model if IDP change could have affected the model
> Remove unnecessary listeners from IDP which are already controlled by
model lifecycle
Bug: 191657065
Test: Manual
Change-Id: Ia8e6dfafd0977e62aa3fcf367ad79f7a49b2df51
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 2e14823..a2189c9 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -57,6 +57,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -158,38 +159,6 @@
@VisibleForTesting
public InvariantDeviceProfile() {}
- private InvariantDeviceProfile(InvariantDeviceProfile p) {
- numRows = p.numRows;
- numColumns = p.numColumns;
- numFolderRows = p.numFolderRows;
- numFolderColumns = p.numFolderColumns;
- iconSize = p.iconSize;
- landscapeIconSize = p.landscapeIconSize;
- twoPanelPortraitIconSize = p.twoPanelPortraitIconSize;
- twoPanelLandscapeIconSize = p.twoPanelLandscapeIconSize;
- iconBitmapSize = p.iconBitmapSize;
- iconTextSize = p.iconTextSize;
- landscapeIconTextSize = p.landscapeIconTextSize;
- twoPanelPortraitIconTextSize = p.twoPanelPortraitIconTextSize;
- twoPanelLandscapeIconTextSize = p.twoPanelLandscapeIconTextSize;
- numShownHotseatIcons = p.numShownHotseatIcons;
- numDatabaseHotseatIcons = p.numDatabaseHotseatIcons;
- numAllAppsColumns = p.numAllAppsColumns;
- numDatabaseAllAppsColumns = p.numDatabaseAllAppsColumns;
- isScalable = p.isScalable;
- devicePaddingId = p.devicePaddingId;
- minCellHeight = p.minCellHeight;
- minCellWidth = p.minCellWidth;
- borderSpacing = p.borderSpacing;
- dbFile = p.dbFile;
- allAppsIconSize = p.allAppsIconSize;
- allAppsIconTextSize = p.allAppsIconTextSize;
- defaultLayoutId = p.defaultLayoutId;
- demoModeLayoutId = p.demoModeLayoutId;
- mExtraAttrs = p.mExtraAttrs;
- devicePaddings = p.devicePaddings;
- }
-
@TargetApi(23)
private InvariantDeviceProfile(Context context) {
String gridName = getCurrentGridName(context);
@@ -236,13 +205,13 @@
DisplayOption result = new DisplayOption(defaultDisplayOption.grid)
.add(myDisplayOption);
- result.iconSize = defaultDisplayOption.iconSize;
- result.landscapeIconSize = defaultDisplayOption.landscapeIconSize;
- if (defaultDisplayOption.allAppsIconSize < myDisplayOption.allAppsIconSize) {
- result.allAppsIconSize = defaultDisplayOption.allAppsIconSize;
- } else {
- result.allAppsIconSize = myDisplayOption.allAppsIconSize;
+ result.iconSizes[DisplayOption.INDEX_DEFAULT] =
+ defaultDisplayOption.iconSizes[DisplayOption.INDEX_DEFAULT];
+ for (int i = 1; i < DisplayOption.COUNT_TOTAL; i++) {
+ result.iconSizes[i] = Math.min(
+ defaultDisplayOption.iconSizes[i], myDisplayOption.iconSizes[i]);
}
+
result.minCellHeight = defaultDisplayOption.minCellHeight;
result.minCellWidth = defaultDisplayOption.minCellWidth;
result.borderSpacing = defaultDisplayOption.borderSpacing;
@@ -288,17 +257,21 @@
mExtraAttrs = closestProfile.extraAttrs;
- iconSize = displayOption.iconSize;
- landscapeIconSize = displayOption.landscapeIconSize;
- twoPanelPortraitIconSize = displayOption.twoPanelPortraitIconSize;
- twoPanelLandscapeIconSize = displayOption.twoPanelLandscapeIconSize;
+ iconSize = displayOption.iconSizes[DisplayOption.INDEX_DEFAULT];
+ landscapeIconSize = displayOption.iconSizes[DisplayOption.INDEX_LANDSCAPE];
+ twoPanelPortraitIconSize = displayOption.iconSizes[DisplayOption.INDEX_TWO_PANEL_PORTRAIT];
+ twoPanelLandscapeIconSize =
+ displayOption.iconSizes[DisplayOption.INDEX_TWO_PANEL_LANDSCAPE];
iconBitmapSize = ResourceUtils.pxFromDp(iconSize, metrics);
- iconTextSize = displayOption.iconTextSize;
- landscapeIconTextSize = displayOption.landscapeIconTextSize;
- twoPanelPortraitIconTextSize = displayOption.twoPanelPortraitIconTextSize;
- twoPanelLandscapeIconTextSize = displayOption.twoPanelLandscapeIconTextSize;
fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
+ iconTextSize = displayOption.textSizes[DisplayOption.INDEX_DEFAULT];
+ landscapeIconTextSize = displayOption.textSizes[DisplayOption.INDEX_LANDSCAPE];
+ twoPanelPortraitIconTextSize =
+ displayOption.textSizes[DisplayOption.INDEX_TWO_PANEL_PORTRAIT];
+ twoPanelLandscapeIconTextSize =
+ displayOption.textSizes[DisplayOption.INDEX_TWO_PANEL_LANDSCAPE];
+
minCellHeight = displayOption.minCellHeight;
minCellWidth = displayOption.minCellWidth;
borderSpacing = displayOption.borderSpacing;
@@ -312,8 +285,8 @@
? closestProfile.numDatabaseAllAppsColumns : closestProfile.numAllAppsColumns;
if (Utilities.isGridOptionsEnabled(context)) {
- allAppsIconSize = displayOption.allAppsIconSize;
- allAppsIconTextSize = displayOption.allAppsIconTextSize;
+ allAppsIconSize = displayOption.iconSizes[DisplayOption.INDEX_ALL_APPS];
+ allAppsIconTextSize = displayOption.textSizes[DisplayOption.INDEX_ALL_APPS];
} else {
allAppsIconSize = iconSize;
allAppsIconTextSize = iconTextSize;
@@ -374,13 +347,22 @@
MAIN_EXECUTOR.execute(() -> onConfigChanged(appContext));
}
+ private Object[] toModelState() {
+ return new Object[] {
+ numColumns, numRows, numDatabaseHotseatIcons, iconBitmapSize, fillResIconDpi,
+ numDatabaseAllAppsColumns, dbFile};
+ }
+
private void onConfigChanged(Context context) {
+ Object[] oldState = toModelState();
+
// Re-init grid
String gridName = getCurrentGridName(context);
initGrid(context, gridName);
+ boolean modelPropsChanged = !Arrays.equals(oldState, toModelState());
for (OnIDPChangeListener listener : mChangeListeners) {
- listener.onIdpChanged(this);
+ listener.onIdpChanged(modelPropsChanged);
}
}
@@ -533,22 +515,33 @@
Float.compare(dist(width, height, a.minWidthDps, a.minHeightDps),
dist(width, height, b.minWidthDps, b.minHeightDps)));
- GridOption closestOption = points.get(0).grid;
+ DisplayOption closestPoint = points.get(0);
+ GridOption closestOption = closestPoint.grid;
float weights = 0;
- DisplayOption p = points.get(0);
- if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) {
- return p;
+ if (dist(width, height, closestPoint.minWidthDps, closestPoint.minHeightDps) == 0) {
+ return closestPoint;
}
DisplayOption out = new DisplayOption(closestOption);
for (int i = 0; i < points.size() && i < KNEARESTNEIGHBOR; ++i) {
- p = points.get(i);
+ DisplayOption p = points.get(i);
float w = weight(width, height, p.minWidthDps, p.minHeightDps, WEIGHT_POWER);
weights += w;
out.add(new DisplayOption().add(p).multiply(w));
}
- return out.multiply(1.0f / weights);
+ out.multiply(1.0f / weights);
+
+ // Since the bitmaps are persisted, ensure that the default bitmap size is same as
+ // predefined size to avoid cache invalidation
+ out.iconSizes[DisplayOption.INDEX_DEFAULT] =
+ closestPoint.iconSizes[DisplayOption.INDEX_DEFAULT];
+ for (int i = DisplayOption.INDEX_DEFAULT + 1; i < DisplayOption.COUNT_TOTAL; i++) {
+ out.iconSizes[i] = Math.min(out.iconSizes[i],
+ out.iconSizes[DisplayOption.INDEX_DEFAULT]);
+ }
+
+ return out;
}
public DeviceProfile getDeviceProfile(Context context) {
@@ -614,7 +607,7 @@
/**
* Called when the device provide changes
*/
- void onIdpChanged(InvariantDeviceProfile profile);
+ void onIdpChanged(boolean modelPropertiesChanged);
}
@@ -695,6 +688,14 @@
@VisibleForTesting
static final class DisplayOption {
+ static final int INDEX_DEFAULT = 0;
+ static final int INDEX_LANDSCAPE = 1;
+ static final int INDEX_ALL_APPS = 2;
+ static final int INDEX_TWO_PANEL_PORTRAIT = 3;
+ static final int INDEX_TWO_PANEL_LANDSCAPE = 4;
+
+ static final int COUNT_TOTAL = 5;
+
public final GridOption grid;
private final float minWidthDps;
@@ -705,16 +706,8 @@
private float minCellWidth;
private float borderSpacing;
- private float iconSize;
- private float iconTextSize;
- private float landscapeIconSize;
- private float twoPanelPortraitIconSize;
- private float twoPanelLandscapeIconSize;
- private float landscapeIconTextSize;
- private float twoPanelPortraitIconTextSize;
- private float twoPanelLandscapeIconTextSize;
- private float allAppsIconSize;
- private float allAppsIconTextSize;
+ private final float[] iconSizes = new float[COUNT_TOTAL];
+ private final float[] textSizes = new float[COUNT_TOTAL];
DisplayOption(GridOption grid, Context context, AttributeSet attrs, int defaultFlagValue) {
this.grid = grid;
@@ -732,27 +725,36 @@
minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
borderSpacing = a.getFloat(R.styleable.ProfileDisplayOption_borderSpacingDps, 0);
- iconSize = a.getFloat(R.styleable.ProfileDisplayOption_iconImageSize, 0);
- landscapeIconSize = a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize,
- iconSize);
- twoPanelPortraitIconSize = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitIconSize, iconSize);
- twoPanelLandscapeIconSize = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeIconSize,
- landscapeIconSize);
- iconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
- landscapeIconTextSize = a.getFloat(
- R.styleable.ProfileDisplayOption_landscapeIconTextSize, iconTextSize);
- twoPanelPortraitIconTextSize = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitIconTextSize, iconTextSize);
- twoPanelLandscapeIconTextSize = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeIconTextSize,
- landscapeIconTextSize);
+ iconSizes[INDEX_DEFAULT] =
+ a.getFloat(R.styleable.ProfileDisplayOption_iconImageSize, 0);
+ iconSizes[INDEX_LANDSCAPE] =
+ a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize,
+ iconSizes[INDEX_DEFAULT]);
+ iconSizes[INDEX_ALL_APPS] =
+ a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconSize,
+ iconSizes[INDEX_DEFAULT]);
+ iconSizes[INDEX_TWO_PANEL_PORTRAIT] =
+ a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitIconSize,
+ iconSizes[INDEX_DEFAULT]);
+ iconSizes[INDEX_TWO_PANEL_LANDSCAPE] =
+ a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconSize,
+ iconSizes[INDEX_LANDSCAPE]);
- allAppsIconSize = a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconSize,
- iconSize);
- allAppsIconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconTextSize,
- iconTextSize);
+ textSizes[INDEX_DEFAULT] =
+ a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
+ textSizes[INDEX_LANDSCAPE] =
+ a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconTextSize,
+ textSizes[INDEX_DEFAULT]);
+ textSizes[INDEX_ALL_APPS] =
+ a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconTextSize,
+ textSizes[INDEX_DEFAULT]);
+ textSizes[INDEX_TWO_PANEL_PORTRAIT] =
+ a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitIconTextSize,
+ textSizes[INDEX_DEFAULT]);
+ textSizes[INDEX_TWO_PANEL_LANDSCAPE] =
+ a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconTextSize,
+ textSizes[INDEX_LANDSCAPE]);
+
a.recycle();
}
@@ -771,16 +773,10 @@
}
private DisplayOption multiply(float w) {
- iconSize *= w;
- landscapeIconSize *= w;
- twoPanelPortraitIconSize *= w;
- twoPanelLandscapeIconSize *= w;
- allAppsIconSize *= w;
- iconTextSize *= w;
- landscapeIconTextSize *= w;
- twoPanelPortraitIconTextSize *= w;
- twoPanelLandscapeIconTextSize *= w;
- allAppsIconTextSize *= w;
+ for (int i = 0; i < COUNT_TOTAL; i++) {
+ iconSizes[i] *= w;
+ textSizes[i] *= w;
+ }
minCellHeight *= w;
minCellWidth *= w;
borderSpacing *= w;
@@ -788,16 +784,10 @@
}
private DisplayOption add(DisplayOption p) {
- iconSize += p.iconSize;
- landscapeIconSize += p.landscapeIconSize;
- twoPanelPortraitIconSize += p.twoPanelPortraitIconSize;
- twoPanelLandscapeIconSize += p.twoPanelLandscapeIconSize;
- allAppsIconSize += p.allAppsIconSize;
- iconTextSize += p.iconTextSize;
- landscapeIconTextSize += p.landscapeIconTextSize;
- twoPanelPortraitIconTextSize += p.twoPanelPortraitIconTextSize;
- twoPanelLandscapeIconTextSize += p.twoPanelLandscapeIconTextSize;
- allAppsIconTextSize += p.allAppsIconTextSize;
+ for (int i = 0; i < COUNT_TOTAL; i++) {
+ iconSizes[i] += p.iconSizes[i];
+ textSizes[i] += p.textSizes[i];
+ }
minCellHeight += p.minCellHeight;
minCellWidth += p.minCellWidth;
borderSpacing += p.borderSpacing;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6ea7b17..3754dc1 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -558,7 +558,7 @@
public void onConfigurationChanged(Configuration newConfig) {
int diff = newConfig.diff(mOldConfig);
if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
- onIdpChanged(mDeviceProfile.inv);
+ onIdpChanged(false);
}
mOldConfig.setTo(newConfig);
@@ -566,8 +566,8 @@
}
@Override
- public void onIdpChanged(InvariantDeviceProfile idp) {
- initDeviceProfile(idp);
+ public void onIdpChanged(boolean modelPropertiesChanged) {
+ initDeviceProfile(mDeviceProfile.inv);
dispatchDeviceProfileChanged();
reapplyUi();
mDragLayer.recreateControllers();
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 702b73a..8adbcd9 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -83,7 +83,11 @@
Log.v(Launcher.TAG, "LauncherAppState initiated");
Preconditions.assertUIThread();
- mInvariantDeviceProfile.addOnChangeListener(idp -> refreshAndReloadLauncher());
+ mInvariantDeviceProfile.addOnChangeListener(modelPropertiesChanged -> {
+ if (modelPropertiesChanged) {
+ refreshAndReloadLauncher();
+ }
+ });
mContext.getSystemService(LauncherApps.class).registerCallback(mModel);
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index e2c0a32..7446181 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -23,6 +23,8 @@
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.WindowManagerCompat.MIN_TABLET_WIDTH;
+import static java.util.Collections.emptyMap;
+
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ComponentCallbacks;
@@ -34,10 +36,11 @@
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Build;
+import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.view.Display;
-import android.view.WindowMetrics;
import androidx.annotation.AnyThread;
import androidx.annotation.UiThread;
@@ -47,7 +50,7 @@
import com.android.launcher3.uioverrides.ApiWrapper;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -76,8 +79,8 @@
// Null for SDK < S
private final Context mWindowContext;
-
private final ArrayList<DisplayInfoChangeListener> mListeners = new ArrayList<>();
+
private Info mInfo;
private DisplayController(Context context) {
@@ -95,19 +98,24 @@
mContext.registerReceiver(configChangeReceiver,
new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
}
+ mInfo = new Info(getDisplayInfoContext(display), display,
+ getInternalDisplays(mDM), emptyMap());
+ mDM.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
+ }
- // Create a single holder for all internal displays. External display holders created
- // lazily.
- Set<PortraitSize> extraInternalDisplays = new ArraySet<>();
- for (Display d : mDM.getDisplays()) {
- if (ApiWrapper.isInternalDisplay(display) && d.getDisplayId() != DEFAULT_DISPLAY) {
+ private static ArrayMap<String, PortraitSize> getInternalDisplays(
+ DisplayManager displayManager) {
+ Display[] displays = displayManager.getDisplays();
+ ArrayMap<String, PortraitSize> internalDisplays = new ArrayMap<>();
+ for (Display display : displays) {
+ if (ApiWrapper.isInternalDisplay(display)) {
Point size = new Point();
- d.getRealSize(size);
- extraInternalDisplays.add(new PortraitSize(size.x, size.y));
+ display.getRealSize(size);
+ internalDisplays.put(ApiWrapper.getUniqueId(display),
+ new PortraitSize(size.x, size.y));
}
}
- mInfo = new Info(getDisplayInfoContext(display), display, extraInternalDisplays);
- mDM.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
+ return internalDisplays;
}
@Override
@@ -203,11 +211,16 @@
@AnyThread
private void handleInfoChange(Display display) {
Info oldInfo = mInfo;
- Set<PortraitSize> extraDisplaysSizes = oldInfo.mAllSizes.size() > 1
- ? oldInfo.mAllSizes : Collections.emptySet();
Context displayContext = getDisplayInfoContext(display);
- Info newInfo = new Info(displayContext, display, extraDisplaysSizes);
+ Info newInfo = new Info(displayContext, display,
+ oldInfo.mInternalDisplays, oldInfo.mPerDisplayBounds);
+
+ if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {
+ // Cache may not be valid anymore, recreate without cache
+ newInfo = new Info(displayContext, display, getInternalDisplays(mDM), emptyMap());
+ }
+
int change = 0;
if (!newInfo.mScreenSizeDp.equals(oldInfo.mScreenSizeDp)) {
change |= CHANGE_ACTIVE_SCREEN;
@@ -240,7 +253,6 @@
public static class Info {
- public final int id;
public final int singleFrameMs;
// Configuration properties
@@ -249,19 +261,21 @@
public final int densityDpi;
private final PortraitSize mScreenSizeDp;
- private final Set<PortraitSize> mAllSizes;
public final Point currentSize;
public final Set<WindowBounds> supportedBounds = new ArraySet<>();
+ private final Map<String, Set<WindowBounds>> mPerDisplayBounds = new ArrayMap<>();
+ private final ArrayMap<String, PortraitSize> mInternalDisplays;
public Info(Context context, Display display) {
- this(context, display, Collections.emptySet());
+ this(context, display, new ArrayMap<>(), emptyMap());
}
- private Info(Context context, Display display, Set<PortraitSize> extraDisplaysSizes) {
- id = display.getDisplayId();
-
+ private Info(Context context, Display display,
+ ArrayMap<String, PortraitSize> internalDisplays,
+ Map<String, Set<WindowBounds>> perDisplayBoundsCache) {
+ mInternalDisplays = internalDisplays;
rotation = display.getRotation();
Configuration config = context.getResources().getConfiguration();
@@ -271,32 +285,51 @@
singleFrameMs = getSingleFrameMs(display);
currentSize = new Point();
-
display.getRealSize(currentSize);
- if (extraDisplaysSizes.isEmpty() || !Utilities.ATLEAST_S) {
- Point smallestSize = new Point();
- Point largestSize = new Point();
- display.getCurrentSizeRange(smallestSize, largestSize);
+ String myDisplayId = ApiWrapper.getUniqueId(display);
+ Set<WindowBounds> currentSupportedBounds =
+ getSupportedBoundsForDisplay(display, currentSize);
+ mPerDisplayBounds.put(myDisplayId, currentSupportedBounds);
+ supportedBounds.addAll(currentSupportedBounds);
- int portraitWidth = Math.min(currentSize.x, currentSize.y);
- int portraitHeight = Math.max(currentSize.x, currentSize.y);
+ if (ApiWrapper.isInternalDisplay(display) && internalDisplays.size() > 1) {
+ int displayCount = internalDisplays.size();
+ for (int i = 0; i < displayCount; i++) {
+ String displayKey = internalDisplays.keyAt(i);
+ if (TextUtils.equals(myDisplayId, displayKey)) {
+ continue;
+ }
- supportedBounds.add(new WindowBounds(portraitWidth, portraitHeight,
- smallestSize.x, largestSize.y));
- supportedBounds.add(new WindowBounds(portraitHeight, portraitWidth,
- largestSize.x, smallestSize.y));
- mAllSizes = Collections.singleton(new PortraitSize(currentSize.x, currentSize.y));
- } else {
- mAllSizes = new ArraySet<>(extraDisplaysSizes);
- mAllSizes.add(new PortraitSize(currentSize.x, currentSize.y));
- Set<WindowMetrics> metrics = WindowManagerCompat.getDisplayProfiles(
- context, mAllSizes, densityDpi,
- ApiWrapper.TASKBAR_DRAWN_IN_PROCESS);
- metrics.forEach(wm -> supportedBounds.add(WindowBounds.fromWindowMetrics(wm)));
+ Set<WindowBounds> displayBounds = perDisplayBoundsCache.get(displayKey);
+ if (displayBounds == null) {
+ // We assume densityDpi is the same across all internal displays
+ displayBounds = WindowManagerCompat.estimateDisplayProfiles(
+ context, internalDisplays.valueAt(i), densityDpi,
+ ApiWrapper.TASKBAR_DRAWN_IN_PROCESS);
+ }
+
+ supportedBounds.addAll(displayBounds);
+ mPerDisplayBounds.put(displayKey, displayBounds);
+ }
}
}
+ private static Set<WindowBounds> getSupportedBoundsForDisplay(Display display, Point size) {
+ Point smallestSize = new Point();
+ Point largestSize = new Point();
+ display.getCurrentSizeRange(smallestSize, largestSize);
+
+ int portraitWidth = Math.min(size.x, size.y);
+ int portraitHeight = Math.max(size.x, size.y);
+ Set<WindowBounds> result = new ArraySet<>();
+ result.add(new WindowBounds(portraitWidth, portraitHeight,
+ smallestSize.x, largestSize.y));
+ result.add(new WindowBounds(portraitHeight, portraitWidth,
+ largestSize.x, smallestSize.y));
+ return result;
+ }
+
/**
* Returns true if the bounds represent a tablet
*/
diff --git a/src/com/android/launcher3/util/WindowManagerCompat.java b/src/com/android/launcher3/util/WindowManagerCompat.java
index 38a63de..bfdf1e4 100644
--- a/src/com/android/launcher3/util/WindowManagerCompat.java
+++ b/src/com/android/launcher3/util/WindowManagerCompat.java
@@ -24,6 +24,7 @@
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Build;
+import android.util.ArraySet;
import android.view.WindowInsets;
import android.view.WindowInsets.Type;
import android.view.WindowManager;
@@ -31,14 +32,14 @@
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
+import com.android.launcher3.Utilities;
import com.android.launcher3.util.DisplayController.PortraitSize;
-import java.util.Collection;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.Set;
/**
- * Utility class to simulate window manager APIs until proper APIs are available
+ * Utility class to estimate window manager values
*/
@TargetApi(Build.VERSION_CODES.S)
public class WindowManagerCompat {
@@ -46,51 +47,51 @@
public static final int MIN_TABLET_WIDTH = 600;
/**
- * Returns a set of supported render sizes for a set of internal displays.
- * This is a temporary workaround which assumes only nav-bar insets change across displays
+ * Returns a set of supported render sizes for a internal display.
+ * This is a temporary workaround which assumes only nav-bar insets change across displays, and
+ * is only used until we eventually get the real values
* @param consumeTaskBar if true, it assumes that task bar is part of the app window
* and ignores any insets because of task bar.
*/
- public static Set<WindowMetrics> getDisplayProfiles(
- Context windowContext, Collection<PortraitSize> allDisplaySizes,
- int densityDpi, boolean consumeTaskBar) {
- WindowInsets metrics = windowContext.getSystemService(WindowManager.class)
+ public static Set<WindowBounds> estimateDisplayProfiles(
+ Context windowContext, PortraitSize size, int densityDpi, boolean consumeTaskBar) {
+ if (!Utilities.ATLEAST_S) {
+ return Collections.emptySet();
+ }
+ WindowInsets defaultInsets = windowContext.getSystemService(WindowManager.class)
.getMaximumWindowMetrics().getWindowInsets();
boolean hasNavbar = ResourceUtils.getIntegerByName(
"config_navBarInteractionMode",
windowContext.getResources(),
INVALID_RESOURCE_HANDLE) != 0;
- WindowInsets.Builder insetsBuilder = new WindowInsets.Builder(metrics);
+ WindowInsets.Builder insetsBuilder = new WindowInsets.Builder(defaultInsets);
+ Set<WindowBounds> result = new ArraySet<>();
+ int swDP = (int) dpiFromPx(size.width, densityDpi);
+ boolean isTablet = swDP >= MIN_TABLET_WIDTH;
- Set<WindowMetrics> result = new HashSet<>();
- for (PortraitSize size : allDisplaySizes) {
- int swDP = (int) dpiFromPx(size.width, densityDpi);
- boolean isTablet = swDP >= MIN_TABLET_WIDTH;
-
- final Insets portraitNav, landscapeNav;
- if (isTablet && !consumeTaskBar) {
- portraitNav = landscapeNav = Insets.of(0, 0, 0, windowContext.getResources()
- .getDimensionPixelSize(R.dimen.taskbar_size));
- } else if (hasNavbar) {
- portraitNav = Insets.of(0, 0, 0,
- getSystemResource(windowContext, "navigation_bar_height", swDP));
- landscapeNav = isTablet
- ? Insets.of(0, 0, 0, getSystemResource(windowContext,
- "navigation_bar_height_landscape", swDP))
- : Insets.of(0, 0, getSystemResource(windowContext,
- "navigation_bar_width", swDP), 0);
- } else {
- portraitNav = landscapeNav = Insets.of(0, 0, 0, 0);
- }
-
- result.add(new WindowMetrics(
- new Rect(0, 0, size.width, size.height),
- insetsBuilder.setInsets(Type.navigationBars(), portraitNav).build()));
- result.add(new WindowMetrics(
- new Rect(0, 0, size.height, size.width),
- insetsBuilder.setInsets(Type.navigationBars(), landscapeNav).build()));
+ final Insets portraitNav, landscapeNav;
+ if (isTablet && !consumeTaskBar) {
+ portraitNav = landscapeNav = Insets.of(0, 0, 0, windowContext.getResources()
+ .getDimensionPixelSize(R.dimen.taskbar_size));
+ } else if (hasNavbar) {
+ portraitNav = Insets.of(0, 0, 0,
+ getSystemResource(windowContext, "navigation_bar_height", swDP));
+ landscapeNav = isTablet
+ ? Insets.of(0, 0, 0, getSystemResource(windowContext,
+ "navigation_bar_height_landscape", swDP))
+ : Insets.of(0, 0, getSystemResource(windowContext,
+ "navigation_bar_width", swDP), 0);
+ } else {
+ portraitNav = landscapeNav = Insets.of(0, 0, 0, 0);
}
+
+ result.add(WindowBounds.fromWindowMetrics(new WindowMetrics(
+ new Rect(0, 0, size.width, size.height),
+ insetsBuilder.setInsets(Type.navigationBars(), portraitNav).build())));
+ result.add(WindowBounds.fromWindowMetrics(new WindowMetrics(
+ new Rect(0, 0, size.height, size.width),
+ insetsBuilder.setInsets(Type.navigationBars(), landscapeNav).build())));
return result;
}