From 2c133360a4797c1c13f7ee71841960ac9c728703 Mon Sep 17 00:00:00 2001 From: Chris Li Date: Tue, 2 Feb 2021 15:28:25 -0800 Subject: [PATCH] Invoke organizer events when a display is added / removed. Before, when a display is added, we don't attach existing organizer to it. Now, we checked if there is an existing one by checking the feature id. At ag/13237565, we tried to do it at onParentChanged(), but mDisplayContent is not set for DAs when DAs are first attached. Change to do it from DisplayContent when it is ready. Fix: 179102157 Test: atest WmTests:DisplayAreaTest Change-Id: Ic2bb7447e9a1408ccdc17f79271b2cf58b2878c1 --- .../com/android/server/wm/DisplayArea.java | 16 +++++--- .../wm/DisplayAreaOrganizerController.java | 6 +++ .../com/android/server/wm/DisplayContent.java | 26 ++++++++++++ .../android/server/wm/DisplayAreaTest.java | 41 +++++++++++++++++++ 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 54ff6db99452f..759b7fe054bc3 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -504,6 +504,17 @@ public class DisplayArea extends WindowContainer { return false; } + @Override + void removeImmediately() { + setOrganizer(null); + super.removeImmediately(); + } + + @Override + DisplayArea getDisplayArea() { + return this; + } + /** * DisplayArea that contains WindowTokens, and orders them according to their type. */ @@ -584,11 +595,6 @@ public class DisplayArea extends WindowContainer { } } - @Override - DisplayArea getDisplayArea() { - return this; - } - /** * DisplayArea that can be dimmed. */ diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java index acfe10a6a25ae..2beb3780633e4 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java +++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java @@ -21,6 +21,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; import static com.android.server.wm.DisplayArea.Type.ANY; +import android.annotation.Nullable; import android.content.pm.ParceledListSlice; import android.os.Binder; import android.os.IBinder; @@ -77,6 +78,11 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl mService.enforceTaskPermission(func); } + @Nullable + IDisplayAreaOrganizer getOrganizerByFeature(int featureId) { + return mOrganizersByFeatureIds.get(featureId); + } + @Override public ParceledListSlice registerOrganizer( IDisplayAreaOrganizer organizer, int feature) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 112fe526f0a89..a11b0f23dddea 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -213,6 +213,7 @@ import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowManager.DisplayImePolicy; import android.view.WindowManagerPolicyConstants.PointerEventListener; +import android.window.IDisplayAreaOrganizer; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; @@ -1074,6 +1075,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Sets the display content for the children. onDisplayChanged(this); + updateDisplayAreaOrganizers(); mInputMonitor = new InputMonitor(mWmService, this); mInsetsPolicy = new InsetsPolicy(mInsetsStateController, this); @@ -2714,6 +2716,30 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mDisplayAreaPolicy.getDefaultTaskDisplayArea(); } + /** + * Checks for all non-organized {@link DisplayArea}s for if there is any existing organizer for + * their features. If so, registers them with the matched organizer. + */ + @VisibleForTesting + void updateDisplayAreaOrganizers() { + if (!isTrusted()) { + // No need to update for untrusted display. + return; + } + forAllDisplayAreas(displayArea -> { + if (displayArea.isOrganized()) { + return; + } + // Check if we have a registered organizer for the DA feature. + final IDisplayAreaOrganizer organizer = + mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController + .getOrganizerByFeature(displayArea.mFeatureId); + if (organizer != null) { + displayArea.setOrganizer(organizer); + } + }); + } + /** * Returns true if the input point is within an app window. */ diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java index 89b962b96baf8..d4c956db90a9b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java @@ -43,11 +43,15 @@ import static com.android.server.wm.testing.Assert.assertThrows; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -57,6 +61,7 @@ import android.platform.test.annotations.Presubmit; import android.view.SurfaceControl; import android.view.View; import android.view.WindowManager; +import android.window.IDisplayAreaOrganizer; import com.google.android.collect.Lists; @@ -525,6 +530,42 @@ public class DisplayAreaTest extends WindowTestsBase { assertThat(mDisplayContent.getOrientationRequestingTaskDisplayArea()).isEqualTo(tda); } + @Test + public void testDisplayContentUpdateDisplayAreaOrganizers_onDisplayAreaAppeared() { + final DisplayArea displayArea = new DisplayArea<>( + mWm, BELOW_TASKS, "NewArea", FEATURE_VENDOR_FIRST); + final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class); + spyOn(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController); + when(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController + .getOrganizerByFeature(FEATURE_VENDOR_FIRST)) + .thenReturn(mockDisplayAreaOrganizer); + + mDisplayContent.addChild(displayArea, 0); + mDisplayContent.updateDisplayAreaOrganizers(); + + assertEquals(mockDisplayAreaOrganizer, displayArea.mOrganizer); + verify(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController) + .onDisplayAreaAppeared( + eq(mockDisplayAreaOrganizer), + argThat(it -> it == displayArea && it.getSurfaceControl() != null)); + } + + @Test + public void testRemoveImmediately_onDisplayAreaVanished() { + final DisplayArea displayArea = new DisplayArea<>( + mWm, BELOW_TASKS, "NewArea", FEATURE_VENDOR_FIRST); + final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class); + displayArea.mOrganizer = mockDisplayAreaOrganizer; + spyOn(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController); + mDisplayContent.addChild(displayArea, 0); + + displayArea.removeImmediately(); + + assertNull(displayArea.mOrganizer); + verify(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController) + .onDisplayAreaVanished(mockDisplayAreaOrganizer, displayArea); + } + private static class TestDisplayArea extends DisplayArea { private TestDisplayArea(WindowManagerService wms, Rect bounds) { super(wms, ANY, "half display area");