diff options
-rw-r--r-- | core/api/system-current.txt | 4 | ||||
-rw-r--r-- | core/java/android/view/WindowManager.java | 18 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 13 | ||||
-rw-r--r-- | packages/Shell/AndroidManifest.xml | 3 | ||||
-rw-r--r-- | services/core/java/com/android/server/policy/PhoneWindowManager.java | 6 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/Session.java | 9 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowState.java | 8 |
7 files changed, 56 insertions, 5 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 730fce7c049a..1509c1b464b1 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -241,6 +241,7 @@ package android { field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"; field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON"; field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS"; + field public static final String SYSTEM_APPLICATION_OVERLAY = "android.permission.SYSTEM_APPLICATION_OVERLAY"; field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA"; field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED"; field public static final String TOGGLE_AUTOMOTIVE_PROJECTION = "android.permission.TOGGLE_AUTOMOTIVE_PROJECTION"; @@ -13332,9 +13333,10 @@ package android.view { method public final void setUserActivityTimeout(long); field @RequiresPermission(android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS) public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000 field @RequiresPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) public static final int SYSTEM_FLAG_SHOW_FOR_ALL_USERS = 16; // 0x10 + field @RequiresPermission(android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY) public static final int SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY = 8; // 0x8 } - @IntDef(flag=true, prefix={"SYSTEM_FLAG_"}, value={android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowManager.LayoutParams.SystemFlags { + @IntDef(flag=true, prefix={"SYSTEM_FLAG_"}, value={android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS, android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowManager.LayoutParams.SystemFlags { } } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 7f639fff20e6..4f7e841bd072 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -2131,6 +2131,16 @@ public interface WindowManager extends ViewManager { */ public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004; + /** + * When set {@link LayoutParams#TYPE_APPLICATION_OVERLAY} windows will stay visible, even if + * {@link LayoutParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} is set for another + * visible window. + * @hide + */ + @SystemApi + @RequiresPermission(permission.SYSTEM_APPLICATION_OVERLAY) + public static final int SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY = 0x00000008; + /** In a multiuser system if this flag is set and the owner is a system process then this * window will appear on all user screens. This overrides the default behavior of window * types that normally only appear on the owning user's screen. Refer to each window type @@ -2328,6 +2338,7 @@ public interface WindowManager extends ViewManager { @IntDef(flag = true, prefix = { "SYSTEM_FLAG_" }, value = { SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, SYSTEM_FLAG_SHOW_FOR_ALL_USERS, + SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY, }) public @interface SystemFlags {} @@ -2361,6 +2372,7 @@ public interface WindowManager extends ViewManager { PRIVATE_FLAG_TRUSTED_OVERLAY, PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME, PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP, + SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY, }) public @interface PrivateFlags {} @@ -2473,7 +2485,11 @@ public interface WindowManager extends ViewManager { @ViewDebug.FlagToString( mask = PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP, equals = PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP, - name = "INTERCEPT_GLOBAL_DRAG_AND_DROP") + name = "INTERCEPT_GLOBAL_DRAG_AND_DROP"), + @ViewDebug.FlagToString( + mask = SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY, + equals = SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY, + name = "SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY") }) @PrivateFlags @TestApi diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index c18e15ef9f5c..51fb264cfeb8 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2682,6 +2682,19 @@ android:description="@string/permdesc_systemAlertWindow" android:protectionLevel="signature|appop|installer|pre23|development|recents" /> + <!-- @SystemApi @hide Allows an application to create windows using the type + {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}, + shown on top of all other apps. + + Allows an application to use + {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY} + to create overlays that will stay visible, even if another window is requesting overlays to + be hidden through {@link android.view.Window#setHideOverlayWindows(boolean)}. + + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY" + android:protectionLevel="signature|wellbeing"/> + <!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND} @hide --> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 1415119117f8..a1bb66ea640a 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -369,8 +369,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 --> + <!-- Permissions required for CTS test - HideOverlayWindowsTest --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> + <uses-permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY"/> <!-- Permission required for CTS test - CtsHdmiCecHostTestCases --> <uses-permission android:name="android.permission.HDMI_CEC" /> diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index aa2e1ff68ced..7caf739a9986 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -18,6 +18,7 @@ package com.android.server.policy; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; +import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY; import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; import static android.app.AppOpsManager.OP_TOAST_WINDOW; import static android.content.Context.CONTEXT_RESTRICTED; @@ -2191,6 +2192,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED; } + if (mContext.checkCallingOrSelfPermission(SYSTEM_APPLICATION_OVERLAY) + == PERMISSION_GRANTED) { + return ADD_OKAY; + } + // check if user has enabled this operation. SecurityException will be thrown if this app // has not been allowed by the user. The reason to use "noteOp" (instead of checkOp) is to // make sure the usage is logged. diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 0cefa9592757..ff2509b9ffc7 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -21,6 +21,7 @@ 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.Manifest.permission.SYSTEM_APPLICATION_OVERLAY; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; @@ -104,6 +105,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { // If non-system overlays from this process can be hidden by the user or app using // HIDE_NON_SYSTEM_OVERLAY_WINDOWS. final boolean mOverlaysCanBeHidden; + final boolean mCanCreateSystemApplicationOverlay; final boolean mCanHideNonSystemOverlayWindows; final boolean mCanAcquireSleepToken; private AlertWindowNotification mAlertWindowNotification; @@ -127,6 +129,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED || service.mContext.checkCallingOrSelfPermission(HIDE_OVERLAY_WINDOWS) == PERMISSION_GRANTED; + mCanCreateSystemApplicationOverlay = + service.mContext.checkCallingOrSelfPermission(SYSTEM_APPLICATION_OVERLAY) + == PERMISSION_GRANTED; mOverlaysCanBeHidden = !mCanAddInternalSystemWindow && !mService.mAtmInternal.isCallerRecents(mUid); mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER) @@ -673,8 +678,8 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { boolean changed; - if (mOverlaysCanBeHidden) { - // We want to track non-system signature apps adding alert windows so we can post an + if (mOverlaysCanBeHidden && !mCanCreateSystemApplicationOverlay) { + // We want to track non-system apps adding alert windows so we can post an // on-going notification for the user to control their visibility. if (visible) { changed = mAlertWindowSurfaces.add(surfaceController); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b35e3e41afd7..bb57a2836a2e 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -67,10 +67,12 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; @@ -3034,6 +3036,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) { return; } + + if (mAttrs.type == TYPE_APPLICATION_OVERLAY && mSession.mCanCreateSystemApplicationOverlay + && (mAttrs.privateFlags & SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY) != 0) { + return; + } + if (mForceHideNonSystemOverlayWindow == forceHide) { return; } |