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
This commit is contained in:
@@ -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";
|
||||
|
||||
@@ -63,5 +63,5 @@ oneway interface IDisplayWindowListener {
|
||||
/**
|
||||
* Called when the keep clear ares on a display have changed.
|
||||
*/
|
||||
void onKeepClearAreasChanged(int displayId, in List<Rect> keepClearAreas);
|
||||
void onKeepClearAreasChanged(int displayId, in List<Rect> restricted, in List<Rect> unrestricted);
|
||||
}
|
||||
|
||||
@@ -6262,6 +6262,15 @@
|
||||
<permission android:name="android.permission.BIND_AMBIENT_CONTEXT_DETECTION_SERVICE"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- @SystemApi Allows an app to set keep-clear areas without restrictions on the size or
|
||||
number of keep-clear areas (see {@link android.view.View#setPreferKeepClearRects}).
|
||||
When the system arranges floating windows onscreen, it might decide to ignore keep-clear
|
||||
areas from windows, whose owner does not have this permission.
|
||||
@hide
|
||||
-->
|
||||
<permission android:name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS"
|
||||
android:protectionLevel="signature|privileged" />
|
||||
|
||||
<!-- Attribution for Geofencing service. -->
|
||||
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
|
||||
<!-- Attribution for Country Detector. -->
|
||||
|
||||
@@ -245,7 +245,8 @@ public class DisplayController {
|
||||
}
|
||||
}
|
||||
|
||||
private void onKeepClearAreasChanged(int displayId, List<Rect> keepClearAreas) {
|
||||
private void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
|
||||
List<Rect> 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<Rect> keepClearAreas) {
|
||||
public void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
|
||||
List<Rect> 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<Rect> keepClearAreas) {}
|
||||
default void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
|
||||
List<Rect> unrestricted) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +308,8 @@ public class CameraServiceProxy extends SystemService
|
||||
public void onFixedRotationFinished(int displayId) { }
|
||||
|
||||
@Override
|
||||
public void onKeepClearAreasChanged(int displayId, List<Rect> keepClearArea) { }
|
||||
public void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
|
||||
List<Rect> unrestricted) { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<Rect> restrictedKeepClearAreas = new ArrayList();
|
||||
final List<Rect> 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<Rect> getKeepClearAreas() {
|
||||
final ArrayList<Rect> keepClearAreas = new ArrayList<Rect>();
|
||||
void getKeepClearAreas(List<Rect> outRestricted, List<Rect> 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<Rect> getKeepClearAreas() {
|
||||
final ArrayList<Rect> keepClearAreas = new ArrayList<Rect>();
|
||||
getKeepClearAreas(keepClearAreas, keepClearAreas);
|
||||
return keepClearAreas;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,12 +120,13 @@ class DisplayWindowListenerController {
|
||||
mDisplayListeners.finishBroadcast();
|
||||
}
|
||||
|
||||
void dispatchKeepClearAreasChanged(DisplayContent display, List<Rect> keepClearAreas) {
|
||||
void dispatchKeepClearAreasChanged(DisplayContent display, List<Rect> restricted,
|
||||
List<Rect> 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) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -191,7 +191,8 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
|
||||
public void onFixedRotationFinished(int displayId) {}
|
||||
|
||||
@Override
|
||||
public void onKeepClearAreasChanged(int displayId, List<Rect> keepClearAreas) {}
|
||||
public void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
|
||||
List<Rect> unrestricted) {}
|
||||
};
|
||||
int[] displayIds = mAtm.mWindowManager.registerDisplayWindowListener(listener);
|
||||
for (int i = 0; i < displayIds.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user