Merge "DisplayController refactoring for multiple displays" into main
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index a614327..ae6cfa0 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -142,15 +142,17 @@
mContext = context;
mDisplayController = displayController;
mSystemUiProxy = systemUiProxy;
+ // TODO (b/398195845): this needs updating so non-default displays do not rotate with the
+ // default display.
mDisplayId = DEFAULT_DISPLAY;
Resources resources = mContext.getResources();
mOrientationTouchTransformer = new OrientationTouchTransformer(resources, mMode,
() -> QuickStepContract.getWindowCornerRadius(mContext));
- // Register for navigation mode changes
- mDisplayController.addChangeListener(this);
- DisplayController.Info info = mDisplayController.getInfo();
+ // Register for navigation mode and rotation changes
+ mDisplayController.addChangeListenerForDisplay(this, mDisplayId);
+ DisplayController.Info info = mDisplayController.getInfoForDisplay(mDisplayId);
onDisplayInfoChanged(context, info, CHANGE_ALL);
mOrientationListener = new OrientationEventListener(mContext) {
@@ -174,7 +176,7 @@
};
lifeCycle.addCloseable(() -> {
- mDisplayController.removeChangeListener(this);
+ mDisplayController.removeChangeListenerForDisplay(this, mDisplayId);
mOrientationListener.disable();
TaskStackChangeListeners.getInstance()
.unregisterTaskStackListener(mFrozenTaskListener);
@@ -201,7 +203,8 @@
return;
}
- mOrientationTouchTransformer.createOrAddTouchRegion(mDisplayController.getInfo(),
+ mOrientationTouchTransformer.createOrAddTouchRegion(
+ mDisplayController.getInfoForDisplay(mDisplayId),
"RTH.updateGestureTouchRegions");
}
@@ -258,7 +261,8 @@
if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
NavigationMode newMode = info.getNavigationMode();
- mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayController.getInfo(),
+ mOrientationTouchTransformer.setNavigationMode(newMode,
+ mDisplayController.getInfoForDisplay(mDisplayId),
mContext.getResources());
TaskStackChangeListeners.getInstance()
@@ -280,7 +284,8 @@
*/
void setGesturalHeight(int newGesturalHeight) {
mOrientationTouchTransformer.setGesturalHeight(
- newGesturalHeight, mDisplayController.getInfo(), mContext.getResources());
+ newGesturalHeight, mDisplayController.getInfoForDisplay(mDisplayId),
+ mContext.getResources());
}
/**
@@ -296,7 +301,8 @@
}
private void enableMultipleRegions(boolean enable) {
- mOrientationTouchTransformer.enableMultipleRegions(enable, mDisplayController.getInfo());
+ mOrientationTouchTransformer.enableMultipleRegions(enable,
+ mDisplayController.getInfoForDisplay(mDisplayId));
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getQuickStepStartingRotation());
if (enable && !mInOverview && !TestProtocol.sDisableSensorRotation) {
// Clear any previous state from sensor manager
@@ -359,7 +365,8 @@
* notifies system UI of the primary rotation the user is interacting with
*/
private void toggleSecondaryNavBarsForRotation() {
- mOrientationTouchTransformer.setSingleActiveRegion(mDisplayController.getInfo());
+ mOrientationTouchTransformer.setSingleActiveRegion(
+ mDisplayController.getInfoForDisplay(mDisplayId));
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
}
diff --git a/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java
index d2a491d..de7fb89 100644
--- a/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
@@ -42,15 +44,20 @@
private OrientationRectF mOrientationRectF;
private OrientationRectF mTouchingOrientationRectF;
private int mViewRotation;
+ private final int mDisplayId;
@Inject
public SimpleOrientationTouchTransformer(@ApplicationContext Context context,
DisplayController displayController,
DaggerSingletonTracker tracker) {
- displayController.addChangeListener(this);
- tracker.addCloseable(() -> displayController.removeChangeListener(this));
+ // TODO (b/398195845): make sure non-default displays don't get affected by default display
+ // changes.
+ mDisplayId = DEFAULT_DISPLAY;
+ displayController.addChangeListenerForDisplay(this, mDisplayId);
+ tracker.addCloseable(
+ () -> displayController.removeChangeListenerForDisplay(this, mDisplayId));
- onDisplayInfoChanged(context, displayController.getInfo(), CHANGE_ALL);
+ onDisplayInfoChanged(context, displayController.getInfoForDisplay(mDisplayId), CHANGE_ALL);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.kt b/quickstep/src/com/android/quickstep/TaskIconCache.kt
index 6a7f1af..f0b9b7b 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.kt
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.kt
@@ -72,6 +72,8 @@
var taskVisualsChangeListener: TaskVisualsChangeListener? = null
init {
+ // TODO (b/397205964): this will need to be updated when we support caches for different
+ // displays.
displayController.addChangeListener(this)
}
diff --git a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index a0ec635..154d86d 100644
--- a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -300,7 +300,7 @@
@Test
public void testSimpleOrientationTouchTransformer() {
final DisplayController displayController = mock(DisplayController.class);
- doReturn(mInfo).when(displayController).getInfo();
+ doReturn(mInfo).when(displayController).getInfoForDisplay(anyInt());
final SimpleOrientationTouchTransformer transformer =
new SimpleOrientationTouchTransformer(getApplicationContext(), displayController,
mock(DaggerSingletonTracker.class));
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index ceece4d..52f8887 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -18,6 +18,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.launcher3.Flags.enableOverviewOnConnectedDisplays;
import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY;
import static com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE;
import static com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET;
@@ -42,9 +43,11 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.SparseArray;
import android.view.Display;
import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
@@ -63,8 +66,10 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -78,8 +83,7 @@
*/
@SuppressLint("NewApi")
@LauncherAppSingleton
-public class DisplayController implements ComponentCallbacks,
- DesktopVisibilityListener {
+public class DisplayController implements DesktopVisibilityListener {
private static final String TAG = "DisplayController";
private static final boolean DEBUG = false;
@@ -110,19 +114,18 @@
private final WindowManagerProxy mWMProxy;
- // Null for SDK < S
- private final Context mWindowContext;
+ private final @ApplicationContext Context mAppContext;
// The callback in this listener updates DeviceProfile, which other listeners might depend on
private DisplayInfoChangeListener mPriorityListener;
- private final CopyOnWriteArrayList<DisplayInfoChangeListener> mListeners =
- new CopyOnWriteArrayList<>();
+
+ private final SparseArray<PerDisplayInfo> mPerDisplayInfo =
+ new SparseArray<>();
// We will register broadcast receiver on main thread to ensure not missing changes on
// TARGET_OVERLAY_PACKAGE and ACTION_OVERLAY_CHANGED.
private final SimpleBroadcastReceiver mReceiver;
- private Info mInfo;
private boolean mDestroyed = false;
@Inject
@@ -130,18 +133,20 @@
WindowManagerProxy wmProxy,
LauncherPrefs prefs,
DaggerSingletonTracker lifecycle) {
+ mAppContext = context;
mWMProxy = wmProxy;
if (enableTaskbarPinning()) {
LauncherPrefChangeListener prefListener = key -> {
+ Info info = getInfo();
boolean isTaskbarPinningChanged = TASKBAR_PINNING_KEY.equals(key)
- && mInfo.mIsTaskbarPinned != prefs.get(TASKBAR_PINNING);
+ && info.mIsTaskbarPinned != prefs.get(TASKBAR_PINNING);
boolean isTaskbarPinningDesktopModeChanged =
TASKBAR_PINNING_DESKTOP_MODE_KEY.equals(key)
- && mInfo.mIsTaskbarPinnedInDesktopMode != prefs.get(
+ && info.mIsTaskbarPinnedInDesktopMode != prefs.get(
TASKBAR_PINNING_IN_DESKTOP_MODE);
if (isTaskbarPinningChanged || isTaskbarPinningDesktopModeChanged) {
- notifyConfigChange();
+ notifyConfigChange(DEFAULT_DISPLAY);
}
};
@@ -151,23 +156,49 @@
prefListener, TASKBAR_PINNING, TASKBAR_PINNING_IN_DESKTOP_MODE));
}
- Display display = context.getSystemService(DisplayManager.class)
- .getDisplay(DEFAULT_DISPLAY);
- mWindowContext = context.createWindowContext(display, TYPE_APPLICATION, null);
- mWindowContext.registerComponentCallbacks(this);
+ DisplayManager displayManager = context.getSystemService(DisplayManager.class);
+ Display defaultDisplay = displayManager.getDisplay(DEFAULT_DISPLAY);
+ PerDisplayInfo defaultPerDisplayInfo = getOrCreatePerDisplayInfo(defaultDisplay);
// Initialize navigation mode change listener
mReceiver = new SimpleBroadcastReceiver(context, MAIN_EXECUTOR, this::onIntent);
mReceiver.registerPkgActions(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED);
- mInfo = new Info(mWindowContext, wmProxy,
- wmProxy.estimateInternalDisplayBounds(mWindowContext));
wmProxy.registerDesktopVisibilityListener(this);
- FileLog.i(TAG, "(CTOR) perDisplayBounds: " + mInfo.mPerDisplayBounds);
+ FileLog.i(TAG, "(CTOR) perDisplayBounds: "
+ + defaultPerDisplayInfo.mInfo.mPerDisplayBounds);
+
+ if (enableOverviewOnConnectedDisplays()) {
+ final DisplayManager.DisplayListener displayListener =
+ new DisplayManager.DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ getOrCreatePerDisplayInfo(displayManager.getDisplay(displayId));
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ removePerDisplayInfo(displayId);
+ }
+ };
+ displayManager.registerDisplayListener(displayListener, MAIN_EXECUTOR.getHandler());
+ lifecycle.addCloseable(() -> {
+ displayManager.unregisterDisplayListener(displayListener);
+ });
+ // Add any PerDisplayInfos for already-connected displays.
+ Arrays.stream(displayManager.getDisplays())
+ .forEach((it) ->
+ getOrCreatePerDisplayInfo(
+ displayManager.getDisplay(it.getDisplayId())));
+ }
lifecycle.addCloseable(() -> {
mDestroyed = true;
- mWindowContext.unregisterComponentCallbacks(this);
+ defaultPerDisplayInfo.cleanup();
mReceiver.unregisterReceiverSafely();
wmProxy.unregisterDesktopVisibilityListener(this);
});
@@ -236,9 +267,7 @@
@Override
public void onIsInDesktopModeChanged(int displayId, boolean isInDesktopModeAndNotInOverview) {
- if (DEFAULT_DISPLAY == displayId) {
- notifyConfigChange();
- }
+ notifyConfigChange(displayId);
}
/**
@@ -261,60 +290,88 @@
}
if (ACTION_OVERLAY_CHANGED.equals(intent.getAction())) {
Log.d(TAG, "Overlay changed, notifying listeners");
- notifyConfigChange();
+ notifyConfigChange(DEFAULT_DISPLAY);
}
}
+ @VisibleForTesting
+ public void onConfigurationChanged(Configuration config) {
+ onConfigurationChanged(config, DEFAULT_DISPLAY);
+ }
+
@UiThread
- @Override
- public final void onConfigurationChanged(Configuration config) {
+ private void onConfigurationChanged(Configuration config, int displayId) {
Log.d(TASKBAR_NOT_DESTROYED_TAG, "DisplayController#onConfigurationChanged: " + config);
- if (config.densityDpi != mInfo.densityDpi
- || config.fontScale != mInfo.fontScale
- || !mInfo.mScreenSizeDp.equals(
- new PortraitSize(config.screenHeightDp, config.screenWidthDp))
- || mWindowContext.getDisplay().getRotation() != mInfo.rotation
- || mWMProxy.showLockedTaskbarOnHome(mWindowContext)
- != mInfo.showLockedTaskbarOnHome()
- || mWMProxy.showDesktopTaskbarForFreeformDisplay(mWindowContext)
- != mInfo.showDesktopTaskbarForFreeformDisplay()) {
- notifyConfigChange();
+ PerDisplayInfo perDisplayInfo = mPerDisplayInfo.get(displayId);
+ Context windowContext = perDisplayInfo.mWindowContext;
+ Info info = perDisplayInfo.mInfo;
+ if (config.densityDpi != info.densityDpi
+ || config.fontScale != info.fontScale
+ || !info.mScreenSizeDp.equals(
+ new PortraitSize(config.screenHeightDp, config.screenWidthDp))
+ || windowContext.getDisplay().getRotation() != info.rotation
+ || mWMProxy.showLockedTaskbarOnHome(windowContext)
+ != info.showLockedTaskbarOnHome()
+ || mWMProxy.showDesktopTaskbarForFreeformDisplay(windowContext)
+ != info.showDesktopTaskbarForFreeformDisplay()) {
+ notifyConfigChange(displayId);
}
}
- @Override
- public final void onLowMemory() { }
-
public void setPriorityListener(DisplayInfoChangeListener listener) {
mPriorityListener = listener;
}
public void addChangeListener(DisplayInfoChangeListener listener) {
- mListeners.add(listener);
+ addChangeListenerForDisplay(listener, DEFAULT_DISPLAY);
}
public void removeChangeListener(DisplayInfoChangeListener listener) {
- mListeners.remove(listener);
+ removeChangeListenerForDisplay(listener, DEFAULT_DISPLAY);
+ }
+
+ public void addChangeListenerForDisplay(DisplayInfoChangeListener listener, int displayId) {
+ PerDisplayInfo perDisplayInfo = mPerDisplayInfo.get(displayId);
+ if (perDisplayInfo != null) {
+ perDisplayInfo.addListener(listener);
+ }
+ }
+
+ public void removeChangeListenerForDisplay(DisplayInfoChangeListener listener, int displayId) {
+ PerDisplayInfo perDisplayInfo = mPerDisplayInfo.get(displayId);
+ if (perDisplayInfo != null) {
+ perDisplayInfo.removeListener(listener);
+ }
}
public Info getInfo() {
- return mInfo;
+ return mPerDisplayInfo.get(DEFAULT_DISPLAY).mInfo;
+ }
+
+ public @Nullable Info getInfoForDisplay(int displayId) {
+ if (enableOverviewOnConnectedDisplays()) {
+ PerDisplayInfo perDisplayInfo = mPerDisplayInfo.get(displayId);
+ if (perDisplayInfo != null) {
+ return perDisplayInfo.mInfo;
+ } else {
+ return null;
+ }
+ } else {
+ return getInfo();
+ }
}
@AnyThread
public void notifyConfigChange() {
- Info oldInfo = mInfo;
+ notifyConfigChange(DEFAULT_DISPLAY);
+ }
- Context displayInfoContext = mWindowContext;
- Info newInfo = new Info(displayInfoContext, mWMProxy, oldInfo.mPerDisplayBounds);
+ @AnyThread
+ public void notifyConfigChange(int displayId) {
+ notifyConfigChangeForDisplay(displayId);
+ }
- if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale
- || newInfo.getNavigationMode() != oldInfo.getNavigationMode()) {
- // Cache may not be valid anymore, recreate without cache
- newInfo = new Info(displayInfoContext, mWMProxy,
- mWMProxy.estimateInternalDisplayBounds(displayInfoContext));
- }
-
+ private int calculateChange(Info oldInfo, Info newInfo) {
int change = 0;
if (!newInfo.normalizedDisplayInfo.equals(oldInfo.normalizedDisplayInfo)) {
change |= CHANGE_ACTIVE_SCREEN;
@@ -336,7 +393,7 @@
}
if ((newInfo.mIsTaskbarPinned != oldInfo.mIsTaskbarPinned)
|| (newInfo.mIsTaskbarPinnedInDesktopMode
- != oldInfo.mIsTaskbarPinnedInDesktopMode)
+ != oldInfo.mIsTaskbarPinnedInDesktopMode)
|| newInfo.isPinnedTaskbar() != oldInfo.isPinnedTaskbar()) {
change |= CHANGE_TASKBAR_PINNING;
}
@@ -350,23 +407,68 @@
if (DEBUG) {
Log.d(TAG, "handleInfoChange - change: " + getChangeFlagsString(change));
}
+ return change;
+ }
- if (change != 0) {
- mInfo = newInfo;
- final int flags = change;
- MAIN_EXECUTOR.execute(() -> notifyChange(displayInfoContext, flags));
+ private Info getNewInfo(Info oldInfo, Context displayInfoContext) {
+ Info newInfo = new Info(displayInfoContext, mWMProxy, oldInfo.mPerDisplayBounds);
+
+ if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale
+ || newInfo.getNavigationMode() != oldInfo.getNavigationMode()) {
+ // Cache may not be valid anymore, recreate without cache
+ newInfo = new Info(displayInfoContext, mWMProxy,
+ mWMProxy.estimateInternalDisplayBounds(displayInfoContext));
+ }
+ return newInfo;
+ }
+
+ @AnyThread
+ public void notifyConfigChangeForDisplay(int displayId) {
+ PerDisplayInfo perDisplayInfo = mPerDisplayInfo.get(displayId);
+ if (perDisplayInfo == null) return;
+ Info oldInfo = perDisplayInfo.mInfo;
+ final Info newInfo = getNewInfo(oldInfo, perDisplayInfo.mWindowContext);
+ final int flags = calculateChange(oldInfo, newInfo);
+ if (flags != 0) {
+ MAIN_EXECUTOR.execute(() -> {
+ perDisplayInfo.mInfo = newInfo;
+ if (displayId == DEFAULT_DISPLAY && mPriorityListener != null) {
+ mPriorityListener.onDisplayInfoChanged(perDisplayInfo.mWindowContext, newInfo,
+ flags);
+ }
+ perDisplayInfo.notifyListeners(newInfo, flags);
+ });
}
}
- private void notifyChange(Context context, int flags) {
- if (mPriorityListener != null) {
- mPriorityListener.onDisplayInfoChanged(context, mInfo, flags);
+ private PerDisplayInfo getOrCreatePerDisplayInfo(Display display) {
+ int displayId = display.getDisplayId();
+ PerDisplayInfo perDisplayInfo = mPerDisplayInfo.get(displayId);
+ if (perDisplayInfo != null) {
+ return perDisplayInfo;
}
+ if (DEBUG) {
+ Log.d(TAG,
+ String.format("getOrCreatePerDisplayInfo - no cached value found for %d",
+ displayId));
+ }
+ Context windowContext = mAppContext.createWindowContext(display, TYPE_APPLICATION, null);
+ Info info = new Info(windowContext, mWMProxy,
+ mWMProxy.estimateInternalDisplayBounds(windowContext));
+ perDisplayInfo = new PerDisplayInfo(displayId, windowContext, info);
+ mPerDisplayInfo.put(displayId, perDisplayInfo);
+ return perDisplayInfo;
+ }
- int count = mListeners.size();
- for (int i = 0; i < count; i++) {
- mListeners.get(i).onDisplayInfoChanged(context, mInfo, flags);
- }
+ /**
+ * Clean up resources for the given display id.
+ * @param displayId The display id
+ */
+ void removePerDisplayInfo(int displayId) {
+ PerDisplayInfo info = mPerDisplayInfo.get(displayId);
+ if (info == null) return;
+ info.cleanup();
+ mPerDisplayInfo.remove(displayId);
}
public static class Info {
@@ -601,21 +703,29 @@
* Dumps the current state information
*/
public void dump(PrintWriter pw) {
- Info info = mInfo;
- pw.println("DisplayController.Info:");
- pw.println(" normalizedDisplayInfo=" + info.normalizedDisplayInfo);
- pw.println(" rotation=" + info.rotation);
- pw.println(" fontScale=" + info.fontScale);
- pw.println(" densityDpi=" + info.densityDpi);
- pw.println(" navigationMode=" + info.getNavigationMode().name());
- pw.println(" isTaskbarPinned=" + info.mIsTaskbarPinned);
- pw.println(" isTaskbarPinnedInDesktopMode=" + info.mIsTaskbarPinnedInDesktopMode);
- pw.println(" isInDesktopMode=" + info.mIsInDesktopMode);
- pw.println(" showLockedTaskbarOnHome=" + info.showLockedTaskbarOnHome());
- pw.println(" currentSize=" + info.currentSize);
- info.mPerDisplayBounds.forEach((key, value) -> pw.println(
- " perDisplayBounds - " + key + ": " + value));
- pw.println(" isTransientTaskbar=" + info.isTransientTaskbar());
+ int count = mPerDisplayInfo.size();
+ for (int i = 0; i < count; ++i) {
+ int displayId = mPerDisplayInfo.keyAt(i);
+ Info info = getInfoForDisplay(displayId);
+ if (info == null) {
+ continue;
+ }
+ pw.println(String.format(Locale.ENGLISH, "DisplayController.Info (displayId=%d):",
+ 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.getNavigationMode().name());
+ pw.println(" isTaskbarPinned=" + info.mIsTaskbarPinned);
+ pw.println(" isTaskbarPinnedInDesktopMode=" + info.mIsTaskbarPinnedInDesktopMode);
+ pw.println(" isInDesktopMode=" + info.mIsInDesktopMode);
+ pw.println(" showLockedTaskbarOnHome=" + info.showLockedTaskbarOnHome());
+ pw.println(" currentSize=" + info.currentSize);
+ info.mPerDisplayBounds.forEach((key, value) -> pw.println(
+ " perDisplayBounds - " + key + ": " + value));
+ pw.println(" isTransientTaskbar=" + info.isTransientTaskbar());
+ }
}
/**
@@ -643,4 +753,47 @@
}
}
+ private class PerDisplayInfo implements ComponentCallbacks {
+ final int mDisplayId;
+ final CopyOnWriteArrayList<DisplayInfoChangeListener> mListeners =
+ new CopyOnWriteArrayList<>();
+ final Context mWindowContext;
+ Info mInfo;
+
+ PerDisplayInfo(int displayId, Context windowContext, Info info) {
+ this.mDisplayId = displayId;
+ this.mWindowContext = windowContext;
+ this.mInfo = info;
+ windowContext.registerComponentCallbacks(this);
+ }
+
+ void addListener(DisplayInfoChangeListener listener) {
+ mListeners.add(listener);
+ }
+
+ void removeListener(DisplayInfoChangeListener listener) {
+ mListeners.remove(listener);
+ }
+
+ void notifyListeners(Info info, int flags) {
+ int count = mListeners.size();
+ for (int i = 0; i < count; ++i) {
+ mListeners.get(i).onDisplayInfoChanged(mWindowContext, info, flags);
+ }
+ }
+
+ @Override
+ public void onConfigurationChanged(@NonNull Configuration newConfig) {
+ DisplayController.this.onConfigurationChanged(newConfig, mDisplayId);
+ }
+
+ @Override
+ public void onLowMemory() {}
+
+ void cleanup() {
+ mWindowContext.unregisterComponentCallbacks(this);
+ mListeners.clear();
+ }
+ }
+
}