From 9d07e62689bef121e9648178700224f04c8399e4 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 21 Apr 2020 09:16:57 -0700 Subject: [PATCH] Added onDisplayAreaChanged and unregister for DisplayAreaOrganizer Notify DisplayAreaOrganzier when the registered DisplayArea has changed. Also added the ability to unregister a DisplayAreaOrganizer Test: DisplayAreaOrganizerTest Bug: 152114574 Change-Id: I9e8c537f8fe6aa7f5b007ef73535294be62dd806 --- .../android/window/DisplayAreaOrganizer.java | 22 +++++ .../android/window/IDisplayAreaOrganizer.aidl | 1 + .../IDisplayAreaOrganizerController.aidl | 5 + .../com/android/server/wm/DisplayArea.java | 9 ++ .../wm/DisplayAreaOrganizerController.java | 27 ++++++ .../server/wm/DisplayAreaOrganizerTest.java | 91 +++++++++++++++++++ 6 files changed, 155 insertions(+) create mode 100644 services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java index 79999bbe812e2..f3ef5a0c0aa26 100644 --- a/core/java/android/window/DisplayAreaOrganizer.java +++ b/core/java/android/window/DisplayAreaOrganizer.java @@ -52,10 +52,27 @@ public class DisplayAreaOrganizer extends WindowOrganizer { } } + /** + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public void unregisterOrganizer() { + try { + getController().unregisterOrganizer(mInterface); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo) {} public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) {} + /** + * @hide + */ + public void onDisplayAreaInfoChanged(@NonNull DisplayAreaInfo displayAreaInfo) {} + private final IDisplayAreaOrganizer mInterface = new IDisplayAreaOrganizer.Stub() { @Override @@ -67,6 +84,11 @@ public class DisplayAreaOrganizer extends WindowOrganizer { public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) { DisplayAreaOrganizer.this.onDisplayAreaVanished(displayAreaInfo); } + + @Override + public void onDisplayAreaInfoChanged(@NonNull DisplayAreaInfo displayAreaInfo) { + DisplayAreaOrganizer.this.onDisplayAreaInfoChanged(displayAreaInfo); + } }; private static IDisplayAreaOrganizerController getController() { diff --git a/core/java/android/window/IDisplayAreaOrganizer.aidl b/core/java/android/window/IDisplayAreaOrganizer.aidl index 18d4e88869b04..39a9235a42240 100644 --- a/core/java/android/window/IDisplayAreaOrganizer.aidl +++ b/core/java/android/window/IDisplayAreaOrganizer.aidl @@ -25,4 +25,5 @@ import android.window.DisplayAreaInfo; oneway interface IDisplayAreaOrganizer { void onDisplayAreaAppeared(in DisplayAreaInfo displayAreaInfo); void onDisplayAreaVanished(in DisplayAreaInfo displayAreaInfo); + void onDisplayAreaInfoChanged(in DisplayAreaInfo displayAreaInfo); } diff --git a/core/java/android/window/IDisplayAreaOrganizerController.aidl b/core/java/android/window/IDisplayAreaOrganizerController.aidl index fc6fbef39ce2f..41b9d027344ea 100644 --- a/core/java/android/window/IDisplayAreaOrganizerController.aidl +++ b/core/java/android/window/IDisplayAreaOrganizerController.aidl @@ -23,4 +23,9 @@ interface IDisplayAreaOrganizerController { /** Register a DisplayAreaOrganizer to manage display areas for a given feature. */ void registerOrganizer(in IDisplayAreaOrganizer organizer, int displayAreaFeature); + + /** + * Unregisters a previously registered display area organizer. + */ + void unregisterOrganizer(in IDisplayAreaOrganizer organizer); } diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index a7256c16a67c1..9b34bd17d0426 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -31,6 +31,7 @@ import static com.android.server.wm.DisplayAreaProto.WINDOW_CONTAINER; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.WindowContainerChildProto.DISPLAY_AREA; +import android.content.res.Configuration; import android.graphics.Rect; import android.util.proto.ProtoOutputStream; import android.window.DisplayAreaInfo; @@ -154,6 +155,14 @@ public class DisplayArea extends WindowContainer { mOrganizerController.onDisplayAreaVanished(mOrganizer, this); } + @Override + public void onConfigurationChanged(Configuration newParentConfig) { + super.onConfigurationChanged(newParentConfig); + if (mOrganizer != null) { + mOrganizerController.onDisplayAreaInfoChanged(mOrganizer, this); + } + } + @Override boolean isOrganized() { return mOrganizer != null; diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java index 2e7a8a3b31aca..2c8c8201c534f 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java +++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java @@ -92,6 +92,25 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl } } + @Override + public void unregisterOrganizer(IDisplayAreaOrganizer organizer) { + enforceStackPermission("unregisterTaskOrganizer()"); + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + mOrganizersByFeatureIds.entrySet().removeIf( + entry -> entry.getValue().asBinder() == organizer.asBinder()); + + mService.mRootWindowContainer.forAllDisplayAreas((da) -> { + if (da.mOrganizer != organizer) return; + da.setOrganizer(null); + }); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + void onDisplayAreaAppeared(IDisplayAreaOrganizer organizer, DisplayArea da) { try { organizer.onDisplayAreaAppeared(da.getDisplayAreaInfo()); @@ -107,4 +126,12 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl // Oh well... } } + + void onDisplayAreaInfoChanged(IDisplayAreaOrganizer organizer, DisplayArea da) { + try { + organizer.onDisplayAreaInfoChanged(da.getDisplayAreaInfo()); + } catch (RemoteException e) { + // Oh well... + } + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java new file mode 100644 index 0000000000000..307b40f1b0398 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.graphics.Rect; +import android.os.Binder; +import android.os.RemoteException; +import android.platform.test.annotations.Presubmit; +import android.window.IDisplayAreaOrganizer; + +import androidx.test.filters.SmallTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@Presubmit +@RunWith(WindowTestRunner.class) +public class DisplayAreaOrganizerTest extends WindowTestsBase { + + private DisplayArea mTestDisplayArea; + + @Before + public void setUp() { + WindowContainer parentWindow = mDisplayContent.getDefaultTaskDisplayArea().getParent(); + mTestDisplayArea = new DisplayArea(mWm, DisplayArea.Type.ANY, + "TestDisplayArea", FEATURE_VENDOR_FIRST); + parentWindow.addChild(mTestDisplayArea, + parentWindow.mChildren.indexOf(mDisplayContent.getDefaultTaskDisplayArea()) + 1); + } + + @After + public void tearDown() { + mTestDisplayArea.removeImmediately(); + } + + private IDisplayAreaOrganizer registerMockOrganizer(int feature) { + final IDisplayAreaOrganizer organizer = mock(IDisplayAreaOrganizer.class); + when(organizer.asBinder()).thenReturn(new Binder()); + + mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController + .registerOrganizer(organizer, feature); + return organizer; + } + + private void unregisterMockOrganizer(IDisplayAreaOrganizer organizer) { + mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController + .unregisterOrganizer(organizer); + } + + @Test + public void testAppearedVanished() throws RemoteException { + IDisplayAreaOrganizer organizer = registerMockOrganizer(FEATURE_VENDOR_FIRST); + verify(organizer).onDisplayAreaAppeared(any()); + + unregisterMockOrganizer(organizer); + verify(organizer).onDisplayAreaVanished(any()); + } + + @Test + public void testChanged() throws RemoteException { + IDisplayAreaOrganizer organizer = registerMockOrganizer(FEATURE_VENDOR_FIRST); + verify(organizer).onDisplayAreaAppeared(any()); + + mDisplayContent.setBounds(new Rect(0, 0, 1000, 1000)); + verify(organizer).onDisplayAreaInfoChanged(any()); + } +}