From 2277bc5399985d048b8651ff1bb197bda19f4f34 Mon Sep 17 00:00:00 2001 From: Galia Peycheva Date: Thu, 27 Jan 2022 11:18:20 +0100 Subject: [PATCH] Add SystemApi USE_UNRESTRICTED_KEEP_CLEAR_AREAS Normal applications should have restrictions on how big/many keep-clear areas they can set. This is to prevent malicious apps from misusing the API and causing unexpected effects (like the Pip moving unexpectedly or too much around the screen). System apps, however, can be trusted to set any keep-clear areas. In this CL we introduce a new permission to allow system apps to set unrestricted keep-clear areas. We send two lists to Shell - one with restricted, the other one with unrestricted keep-clear areas. When moving floating windows away, the Shell can decide to always take into account unrestricted keep-clear areas and be more restrictive about the restricted ones. Bug: 209578131 Bug: 209577354 Test: atest CtsWindowManagerDeviceTestCases:KeepClearRectsTests Test: atest WindowStateTests Test: atest DisplayContentTests Change-Id: I68804c50fb81173b0795cf30dd71ea91abd02229 --- core/api/system-current.txt | 1 + .../android/view/IDisplayWindowListener.aidl | 2 +- core/res/AndroidManifest.xml | 9 ++++++ .../wm/shell/common/DisplayController.java | 14 ++++++--- .../server/camera/CameraServiceProxy.java | 3 +- .../com/android/server/wm/DisplayContent.java | 31 +++++++++++++++---- .../wm/DisplayWindowListenerController.java | 5 +-- .../java/com/android/server/wm/Session.java | 5 +++ .../wm/ActivityTaskManagerServiceTests.java | 3 +- 9 files changed, 57 insertions(+), 16 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 55a6df28df728..ece805c129cb9 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -301,6 +301,7 @@ package android { field public static final String SET_POINTER_SPEED = "android.permission.SET_POINTER_SPEED"; field public static final String SET_SCREEN_COMPATIBILITY = "android.permission.SET_SCREEN_COMPATIBILITY"; field public static final String SET_SYSTEM_AUDIO_CAPTION = "android.permission.SET_SYSTEM_AUDIO_CAPTION"; + field public static final String SET_UNRESTRICTED_KEEP_CLEAR_AREAS = "android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS"; field public static final String SET_VOLUME_KEY_LONG_PRESS_LISTENER = "android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER"; field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT"; field public static final String SET_WALLPAPER_DIM_AMOUNT = "android.permission.SET_WALLPAPER_DIM_AMOUNT"; diff --git a/core/java/android/view/IDisplayWindowListener.aidl b/core/java/android/view/IDisplayWindowListener.aidl index 449e9b325904b..67ae7430e0b7f 100644 --- a/core/java/android/view/IDisplayWindowListener.aidl +++ b/core/java/android/view/IDisplayWindowListener.aidl @@ -63,5 +63,5 @@ oneway interface IDisplayWindowListener { /** * Called when the keep clear ares on a display have changed. */ - void onKeepClearAreasChanged(int displayId, in List keepClearAreas); + void onKeepClearAreasChanged(int displayId, in List restricted, in List unrestricted); } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index c62d964cd5186..9c2c9826ef6da 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -6262,6 +6262,15 @@ + + + diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java index e2bc36028405d..9384e2b4dfdf9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java @@ -245,7 +245,8 @@ public class DisplayController { } } - private void onKeepClearAreasChanged(int displayId, List keepClearAreas) { + private void onKeepClearAreasChanged(int displayId, List restricted, + List unrestricted) { synchronized (mDisplays) { if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) { Slog.w(TAG, "Skipping onKeepClearAreasChanged on unknown" @@ -253,7 +254,8 @@ public class DisplayController { return; } for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) { - mDisplayChangedListeners.get(i).onKeepClearAreasChanged(displayId, keepClearAreas); + mDisplayChangedListeners.get(i) + .onKeepClearAreasChanged(displayId, restricted, unrestricted); } } } @@ -318,9 +320,10 @@ public class DisplayController { } @Override - public void onKeepClearAreasChanged(int displayId, List keepClearAreas) { + public void onKeepClearAreasChanged(int displayId, List restricted, + List unrestricted) { mMainExecutor.execute(() -> { - DisplayController.this.onKeepClearAreasChanged(displayId, keepClearAreas); + DisplayController.this.onKeepClearAreasChanged(displayId, restricted, unrestricted); }); } } @@ -361,6 +364,7 @@ public class DisplayController { /** * Called when keep-clear areas on a display have changed. */ - default void onKeepClearAreasChanged(int displayId, List keepClearAreas) {} + default void onKeepClearAreasChanged(int displayId, List restricted, + List unrestricted) {} } } diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index 1e00ea9161a86..1b0341c1ce26c 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -308,7 +308,8 @@ public class CameraServiceProxy extends SystemService public void onFixedRotationFinished(int displayId) { } @Override - public void onKeepClearAreasChanged(int displayId, List keepClearArea) { } + public void onKeepClearAreasChanged(int displayId, List restricted, + List unrestricted) { } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index a1c823e18ccdd..bc917bfa9f225 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -170,7 +170,6 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.ColorSpace; -import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; @@ -5490,26 +5489,46 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } void updateKeepClearAreas() { + final List restrictedKeepClearAreas = new ArrayList(); + final List unrestrictedKeepClearAreas = new ArrayList(); + getKeepClearAreas(restrictedKeepClearAreas, unrestrictedKeepClearAreas); mWmService.mDisplayNotificationController.dispatchKeepClearAreasChanged( - this, getKeepClearAreas()); + this, restrictedKeepClearAreas, unrestrictedKeepClearAreas); } /** - * Returns all keep-clear areas from visible windows on this display. + * Fills {@param outRestricted} with all keep-clear areas from visible, relevant windows + * on this display, which set restricted keep-clear areas. + * Fills {@param outUnrestricted} with keep-clear areas from visible, relevant windows on this + * display, which set unrestricted keep-clear areas. + * + * For context on restricted vs unrestricted keep-clear areas, see + * {@link android.Manifest.permission.USE_UNRESTRICTED_KEEP_CLEAR_AREAS}. */ - ArrayList getKeepClearAreas() { - final ArrayList keepClearAreas = new ArrayList(); + void getKeepClearAreas(List outRestricted, List outUnrestricted) { final Matrix tmpMatrix = new Matrix(); final float[] tmpFloat9 = new float[9]; forAllWindows(w -> { if (w.isVisible() && !w.inPinnedWindowingMode()) { - keepClearAreas.addAll(w.getKeepClearAreas(tmpMatrix, tmpFloat9)); + if (w.mSession.mSetsUnrestrictedKeepClearAreas) { + outUnrestricted.addAll(w.getKeepClearAreas(tmpMatrix, tmpFloat9)); + } else { + outRestricted.addAll(w.getKeepClearAreas(tmpMatrix, tmpFloat9)); + } } // We stop traversing when we reach the base of a fullscreen app. return w.getWindowType() == TYPE_BASE_APPLICATION && w.getWindowingMode() == WINDOWING_MODE_FULLSCREEN; }, true); + } + + /** + * Returns all keep-clear areas from visible, relevant windows on this display. + */ + ArrayList getKeepClearAreas() { + final ArrayList keepClearAreas = new ArrayList(); + getKeepClearAreas(keepClearAreas, keepClearAreas); return keepClearAreas; } diff --git a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java index 276dbe9c844aa..e18d5396831a2 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java +++ b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java @@ -120,12 +120,13 @@ class DisplayWindowListenerController { mDisplayListeners.finishBroadcast(); } - void dispatchKeepClearAreasChanged(DisplayContent display, List keepClearAreas) { + void dispatchKeepClearAreasChanged(DisplayContent display, List restricted, + List unrestricted) { int count = mDisplayListeners.beginBroadcast(); for (int i = 0; i < count; ++i) { try { mDisplayListeners.getBroadcastItem(i).onKeepClearAreasChanged( - display.mDisplayId, keepClearAreas); + display.mDisplayId, restricted, unrestricted); } catch (RemoteException e) { } } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 9b94f44be714a..dd7818cbd426e 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; +import static android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY; import static android.app.ActivityTaskManager.INVALID_TASK_ID; @@ -114,6 +115,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { private String mRelayoutTag; private final InsetsVisibilities mDummyRequestedVisibilities = new InsetsVisibilities(); private final InsetsSourceControl[] mDummyControls = new InsetsSourceControl[0]; + final boolean mSetsUnrestrictedKeepClearAreas; public Session(WindowManagerService service, IWindowSessionCallback callback) { mService = service; @@ -132,6 +134,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { == PERMISSION_GRANTED; mCanStartTasksFromRecents = service.mContext.checkCallingOrSelfPermission( START_TASKS_FROM_RECENTS) == PERMISSION_GRANTED; + mSetsUnrestrictedKeepClearAreas = + service.mContext.checkCallingOrSelfPermission(SET_UNRESTRICTED_KEEP_CLEAR_AREAS) + == PERMISSION_GRANTED; mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications; mDragDropController = mService.mDragDropController; StringBuilder sb = new StringBuilder(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java index 7c340ecac2c76..8ada97147dd3f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java @@ -191,7 +191,8 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { public void onFixedRotationFinished(int displayId) {} @Override - public void onKeepClearAreasChanged(int displayId, List keepClearAreas) {} + public void onKeepClearAreasChanged(int displayId, List restricted, + List unrestricted) {} }; int[] displayIds = mAtm.mWindowManager.registerDisplayWindowListener(listener); for (int i = 0; i < displayIds.length; i++) {