Loading core/java/android/view/IDisplayWindowListener.aidl +10 −1 Original line number Diff line number Diff line Loading @@ -16,12 +16,16 @@ package android.view; import android.content.res.Configuration; /** * Interface to listen for changes to display window-containers. * * This differs from DisplayManager's DisplayListener: * This differs from DisplayManager's DisplayListener in a couple ways: * - onDisplayAdded is always called after the display is actually added to the WM hierarchy. * This corresponds to the DisplayContent and not the raw Dislay from DisplayManager. * - onDisplayConfigurationChanged is called for all configuration changes, not just changes * to displayinfo (eg. windowing-mode). * * @hide */ Loading @@ -32,6 +36,11 @@ oneway interface IDisplayWindowListener { */ void onDisplayAdded(int displayId); /** * Called when a display's window-container configuration has changed. */ void onDisplayConfigurationChanged(int displayId, in Configuration newConfig); /** * Called when a display is removed from the hierarchy. */ Loading packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java +33 −5 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ package com.android.systemui.wm; import android.content.res.Configuration; import android.os.Handler; import android.os.RemoteException; import android.util.Slog; import android.util.SparseArray; import android.view.IDisplayWindowListener; import android.view.IDisplayWindowRotationCallback; Loading @@ -40,6 +42,8 @@ import javax.inject.Singleton; */ @Singleton public class DisplayWindowController { private static final String TAG = "DisplayWindowController"; private final Handler mHandler; private final ArrayList<OnDisplayWindowRotationController> mRotationControllers = Loading Loading @@ -84,8 +88,26 @@ public class DisplayWindowController { DisplayRecord record = new DisplayRecord(); record.mDisplayId = displayId; mDisplays.put(displayId, record); for (DisplayWindowListener l : mDisplayChangedListeners) { l.onDisplayAdded(displayId); for (int i = 0; i < mDisplayChangedListeners.size(); ++i) { mDisplayChangedListeners.get(i).onDisplayAdded(displayId); } } }); } @Override public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { mHandler.post(() -> { synchronized (mDisplays) { DisplayRecord dr = mDisplays.get(displayId); if (dr == null) { Slog.w(TAG, "Skipping Display Configuration change on non-added" + " display."); return; } for (int i = 0; i < mDisplayChangedListeners.size(); ++i) { mDisplayChangedListeners.get(i).onDisplayConfigurationChanged( displayId, newConfig); } } }); Loading Loading @@ -118,8 +140,8 @@ public class DisplayWindowController { } /** * Add a display window-container listener. It will get notified when displays are * added/removed from the WM hierarchy. * Add a display window-container listener. It will get notified whenever a display's * configuration changes or when displays are added/removed from the WM hierarchy. */ public void addDisplayWindowListener(DisplayWindowListener listener) { synchronized (mDisplays) { Loading Loading @@ -165,7 +187,8 @@ public class DisplayWindowController { } /** * Gets notified when a display is added/removed to the WM hierarchy. * Gets notified when a display is added/removed to the WM hierarchy and when a display's * window-configuration changes. * * @see IDisplayWindowListener */ Loading @@ -175,6 +198,11 @@ public class DisplayWindowController { */ void onDisplayAdded(int displayId); /** * Called when a display's window-container configuration changes. */ void onDisplayConfigurationChanged(int displayId, Configuration newConfig); /** * Called when a display is removed. */ Loading services/core/java/com/android/server/wm/ActivityDisplay.java +2 −0 Original line number Diff line number Diff line Loading @@ -1080,6 +1080,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> { ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND); mService.mH.sendMessage(msg); } mService.mWindowManager.mDisplayNotificationController.dispatchDisplayChanged( this, getConfiguration()); } return changes; } Loading services/core/java/com/android/server/wm/DisplayWindowListenerController.java +23 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import android.content.res.Configuration; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.view.IDisplayWindowListener; Loading Loading @@ -62,6 +63,28 @@ class DisplayWindowListenerController { mDisplayListeners.finishBroadcast(); } void dispatchDisplayChanged(ActivityDisplay display, Configuration newConfig) { // Only report changed if this has actually been added to the hierarchy already. boolean isInHierarchy = false; for (int i = 0; i < display.getParent().getChildCount(); ++i) { if (display.getParent().getChildAt(i) == display) { isInHierarchy = true; } } if (!isInHierarchy) { return; } int count = mDisplayListeners.beginBroadcast(); for (int i = 0; i < count; ++i) { try { mDisplayListeners.getBroadcastItem(i).onDisplayConfigurationChanged( display.mDisplayId, newConfig); } catch (RemoteException e) { } } mDisplayListeners.finishBroadcast(); } void dispatchDisplayRemoved(ActivityDisplay display) { int count = mDisplayListeners.beginBroadcast(); for (int i = 0; i < count; ++i) { Loading services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +55 −0 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ import static org.junit.Assert.assertTrue; import android.app.Activity; import android.app.ActivityManager; import android.content.res.Configuration; import android.graphics.Rect; import android.view.IDisplayWindowListener; import android.view.WindowContainerTransaction; import androidx.test.filters.MediumTest; Loading @@ -35,6 +37,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; /** * Tests for the {@link ActivityTaskManagerService} class. * Loading Loading @@ -93,5 +97,56 @@ public class ActivityTaskManagerServiceTests extends ActivityTestsBase { mService.applyContainerTransaction(t); assertEquals(newBounds, stack.getBounds()); } @Test public void testDisplayWindowListener() { final ArrayList<Integer> added = new ArrayList<>(); final ArrayList<Integer> changed = new ArrayList<>(); final ArrayList<Integer> removed = new ArrayList<>(); IDisplayWindowListener listener = new IDisplayWindowListener.Stub() { @Override public void onDisplayAdded(int displayId) { added.add(displayId); } @Override public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { changed.add(displayId); } @Override public void onDisplayRemoved(int displayId) { removed.add(displayId); } }; mService.mWindowManager.registerDisplayWindowListener(listener); // Check that existing displays call added assertEquals(1, added.size()); assertEquals(0, changed.size()); assertEquals(0, removed.size()); added.clear(); // Check adding a display ActivityDisplay newDisp1 = new TestActivityDisplay.Builder(mService, 600, 800).build(); assertEquals(1, added.size()); assertEquals(0, changed.size()); assertEquals(0, removed.size()); added.clear(); // Check that changes are reported Configuration c = new Configuration(newDisp1.getRequestedOverrideConfiguration()); c.windowConfiguration.setBounds(new Rect(0, 0, 1000, 1300)); newDisp1.onRequestedOverrideConfigurationChanged(c); mService.mRootActivityContainer.ensureVisibilityAndConfig(null /* starting */, newDisp1.mDisplayId, false /* markFrozenIfConfigChanged */, false /* deferResume */); assertEquals(0, added.size()); assertEquals(1, changed.size()); assertEquals(0, removed.size()); changed.clear(); // Check that removal is reported newDisp1.remove(); assertEquals(0, added.size()); assertEquals(0, changed.size()); assertEquals(1, removed.size()); } } Loading
core/java/android/view/IDisplayWindowListener.aidl +10 −1 Original line number Diff line number Diff line Loading @@ -16,12 +16,16 @@ package android.view; import android.content.res.Configuration; /** * Interface to listen for changes to display window-containers. * * This differs from DisplayManager's DisplayListener: * This differs from DisplayManager's DisplayListener in a couple ways: * - onDisplayAdded is always called after the display is actually added to the WM hierarchy. * This corresponds to the DisplayContent and not the raw Dislay from DisplayManager. * - onDisplayConfigurationChanged is called for all configuration changes, not just changes * to displayinfo (eg. windowing-mode). * * @hide */ Loading @@ -32,6 +36,11 @@ oneway interface IDisplayWindowListener { */ void onDisplayAdded(int displayId); /** * Called when a display's window-container configuration has changed. */ void onDisplayConfigurationChanged(int displayId, in Configuration newConfig); /** * Called when a display is removed from the hierarchy. */ Loading
packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java +33 −5 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ package com.android.systemui.wm; import android.content.res.Configuration; import android.os.Handler; import android.os.RemoteException; import android.util.Slog; import android.util.SparseArray; import android.view.IDisplayWindowListener; import android.view.IDisplayWindowRotationCallback; Loading @@ -40,6 +42,8 @@ import javax.inject.Singleton; */ @Singleton public class DisplayWindowController { private static final String TAG = "DisplayWindowController"; private final Handler mHandler; private final ArrayList<OnDisplayWindowRotationController> mRotationControllers = Loading Loading @@ -84,8 +88,26 @@ public class DisplayWindowController { DisplayRecord record = new DisplayRecord(); record.mDisplayId = displayId; mDisplays.put(displayId, record); for (DisplayWindowListener l : mDisplayChangedListeners) { l.onDisplayAdded(displayId); for (int i = 0; i < mDisplayChangedListeners.size(); ++i) { mDisplayChangedListeners.get(i).onDisplayAdded(displayId); } } }); } @Override public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { mHandler.post(() -> { synchronized (mDisplays) { DisplayRecord dr = mDisplays.get(displayId); if (dr == null) { Slog.w(TAG, "Skipping Display Configuration change on non-added" + " display."); return; } for (int i = 0; i < mDisplayChangedListeners.size(); ++i) { mDisplayChangedListeners.get(i).onDisplayConfigurationChanged( displayId, newConfig); } } }); Loading Loading @@ -118,8 +140,8 @@ public class DisplayWindowController { } /** * Add a display window-container listener. It will get notified when displays are * added/removed from the WM hierarchy. * Add a display window-container listener. It will get notified whenever a display's * configuration changes or when displays are added/removed from the WM hierarchy. */ public void addDisplayWindowListener(DisplayWindowListener listener) { synchronized (mDisplays) { Loading Loading @@ -165,7 +187,8 @@ public class DisplayWindowController { } /** * Gets notified when a display is added/removed to the WM hierarchy. * Gets notified when a display is added/removed to the WM hierarchy and when a display's * window-configuration changes. * * @see IDisplayWindowListener */ Loading @@ -175,6 +198,11 @@ public class DisplayWindowController { */ void onDisplayAdded(int displayId); /** * Called when a display's window-container configuration changes. */ void onDisplayConfigurationChanged(int displayId, Configuration newConfig); /** * Called when a display is removed. */ Loading
services/core/java/com/android/server/wm/ActivityDisplay.java +2 −0 Original line number Diff line number Diff line Loading @@ -1080,6 +1080,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> { ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND); mService.mH.sendMessage(msg); } mService.mWindowManager.mDisplayNotificationController.dispatchDisplayChanged( this, getConfiguration()); } return changes; } Loading
services/core/java/com/android/server/wm/DisplayWindowListenerController.java +23 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import android.content.res.Configuration; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.view.IDisplayWindowListener; Loading Loading @@ -62,6 +63,28 @@ class DisplayWindowListenerController { mDisplayListeners.finishBroadcast(); } void dispatchDisplayChanged(ActivityDisplay display, Configuration newConfig) { // Only report changed if this has actually been added to the hierarchy already. boolean isInHierarchy = false; for (int i = 0; i < display.getParent().getChildCount(); ++i) { if (display.getParent().getChildAt(i) == display) { isInHierarchy = true; } } if (!isInHierarchy) { return; } int count = mDisplayListeners.beginBroadcast(); for (int i = 0; i < count; ++i) { try { mDisplayListeners.getBroadcastItem(i).onDisplayConfigurationChanged( display.mDisplayId, newConfig); } catch (RemoteException e) { } } mDisplayListeners.finishBroadcast(); } void dispatchDisplayRemoved(ActivityDisplay display) { int count = mDisplayListeners.beginBroadcast(); for (int i = 0; i < count; ++i) { Loading
services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +55 −0 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ import static org.junit.Assert.assertTrue; import android.app.Activity; import android.app.ActivityManager; import android.content.res.Configuration; import android.graphics.Rect; import android.view.IDisplayWindowListener; import android.view.WindowContainerTransaction; import androidx.test.filters.MediumTest; Loading @@ -35,6 +37,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; /** * Tests for the {@link ActivityTaskManagerService} class. * Loading Loading @@ -93,5 +97,56 @@ public class ActivityTaskManagerServiceTests extends ActivityTestsBase { mService.applyContainerTransaction(t); assertEquals(newBounds, stack.getBounds()); } @Test public void testDisplayWindowListener() { final ArrayList<Integer> added = new ArrayList<>(); final ArrayList<Integer> changed = new ArrayList<>(); final ArrayList<Integer> removed = new ArrayList<>(); IDisplayWindowListener listener = new IDisplayWindowListener.Stub() { @Override public void onDisplayAdded(int displayId) { added.add(displayId); } @Override public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { changed.add(displayId); } @Override public void onDisplayRemoved(int displayId) { removed.add(displayId); } }; mService.mWindowManager.registerDisplayWindowListener(listener); // Check that existing displays call added assertEquals(1, added.size()); assertEquals(0, changed.size()); assertEquals(0, removed.size()); added.clear(); // Check adding a display ActivityDisplay newDisp1 = new TestActivityDisplay.Builder(mService, 600, 800).build(); assertEquals(1, added.size()); assertEquals(0, changed.size()); assertEquals(0, removed.size()); added.clear(); // Check that changes are reported Configuration c = new Configuration(newDisp1.getRequestedOverrideConfiguration()); c.windowConfiguration.setBounds(new Rect(0, 0, 1000, 1300)); newDisp1.onRequestedOverrideConfigurationChanged(c); mService.mRootActivityContainer.ensureVisibilityAndConfig(null /* starting */, newDisp1.mDisplayId, false /* markFrozenIfConfigChanged */, false /* deferResume */); assertEquals(0, added.size()); assertEquals(1, changed.size()); assertEquals(0, removed.size()); changed.clear(); // Check that removal is reported newDisp1.remove(); assertEquals(0, added.size()); assertEquals(0, changed.size()); assertEquals(1, removed.size()); } }