Allow 3p apps to hide non system overlay windows

SAW permission is added to the shell to allow it to create
TYPE_APPLICATION_OVERLAY windows during testing.

Test: atest CtsWindowManagerDeviceTestCases:HideOverlayWindowsTest
Bug: 159616727
Change-Id: I503cd8da24ff4d2b928f930ac61090e6782c1546
This commit is contained in:
Linus Tufvesson
2020-11-06 13:07:44 +00:00
parent e386b0a3df
commit f57a88f03b
6 changed files with 40 additions and 2 deletions

View File

@@ -87,6 +87,7 @@ package android {
field public static final String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
field @Deprecated public static final String GET_TASKS = "android.permission.GET_TASKS";
field public static final String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
field public static final String HIDE_OVERLAY_WINDOWS = "android.permission.HIDE_OVERLAY_WINDOWS";
field public static final String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
field public static final String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
field public static final String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT";
@@ -54221,6 +54222,7 @@ package android.view {
method public void setFlags(int, int);
method public void setFormat(int);
method public void setGravity(int);
method @RequiresPermission(android.Manifest.permission.HIDE_OVERLAY_WINDOWS) public final void setHideOverlayWindows(boolean);
method public void setIcon(@DrawableRes int);
method public void setLayout(int, int);
method public void setLocalFocus(boolean, boolean);

View File

@@ -93,7 +93,7 @@ package android {
field public static final String HANDLE_CAR_MODE_CHANGES = "android.permission.HANDLE_CAR_MODE_CHANGES";
field public static final String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
field public static final String HDMI_CEC = "android.permission.HDMI_CEC";
field public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
field @Deprecated public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
field public static final String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
field public static final String INSTALL_DYNAMIC_SYSTEM = "android.permission.INSTALL_DYNAMIC_SYSTEM";
field public static final String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS";

View File

@@ -16,7 +16,11 @@
package android.view;
import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
@@ -24,6 +28,7 @@ import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.StyleRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -990,6 +995,26 @@ public abstract class Window {
mRestrictedCaptionAreaRect = listener != null ? new Rect() : null;
}
/**
* Prevent non-system overlay windows from being drawn on top of this window.
*
* @param hide whether non-system overlay windows should be hidden.
*/
@RequiresPermission(HIDE_OVERLAY_WINDOWS)
public final void setHideOverlayWindows(boolean hide) {
// This permission check is here to throw early and let the developer know that they need
// to hold HIDE_OVERLAY_WINDOWS for the flag to have any effect. The WM verifies that the
// owner of the window has the permission before applying the flag, but this is done
// asynchronously.
if (mContext.checkSelfPermission(HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != PERMISSION_GRANTED
&& mContext.checkSelfPermission(HIDE_OVERLAY_WINDOWS) != PERMISSION_GRANTED) {
throw new SecurityException(
"Permission denial: setHideOverlayWindows: HIDE_OVERLAY_WINDOWS");
}
setPrivateFlags(hide ? SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS : 0,
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
}
/**
* Take ownership of this window's surface. The window's view hierarchy
* will no longer draw into the surface, though it will otherwise continue

View File

@@ -2730,6 +2730,10 @@
<permission android:name="android.permission.TOGGLE_AUTOMOTIVE_PROJECTION"
android:protectionLevel="signature|privileged" />
<!-- Allows an app to prevent non-system-overlay windows from being drawn on top of it -->
<permission android:name="android.permission.HIDE_OVERLAY_WINDOWS"
android:protectionLevel="normal" />
<!-- ================================== -->
<!-- Permissions affecting the system wallpaper -->
<!-- ================================== -->
@@ -3284,6 +3288,7 @@
{@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
to hide non-system-overlay windows.
<p>Not for use by third-party applications.
@deprecated Use {@link android.Manifest.permission#HIDE_OVERLAY_WINDOWS} instead
@hide
-->
<permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"

View File

@@ -362,6 +362,9 @@
<!-- Permissions required for CTS tests to close system dialogs -->
<uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" />
<!-- Permission required for CTS test - HideOverlayWindowsTest -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"

View File

@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.Manifest.permission.DEVICE_POWER;
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.START_TASKS_FROM_RECENTS;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
@@ -124,7 +125,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED
|| service.mContext.checkCallingOrSelfPermission(HIDE_OVERLAY_WINDOWS)
== PERMISSION_GRANTED;
mOverlaysCanBeHidden = !mCanAddInternalSystemWindow
&& !mService.mAtmInternal.isCallerRecents(mUid);
mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)