diff options
author | Phil Weaver <pweaver@google.com> | 2017-07-12 14:04:16 -0700 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-09-13 22:04:04 +0000 |
commit | ba8a607127127841cac6585812b26683699d89b3 (patch) | |
tree | ab335b523db388d8eb17aedb7c2aaa9202704d17 | |
parent | 3ac6f79bb09463af06247937b9d55ce314e5ad96 (diff) | |
download | base-ba8a607127127841cac6585812b26683699d89b3.tar.gz |
Back-port fixes for b/62196835
Bug: 62196835
Test: Created an accessibility service that displays a system
and a toast overlay, confirmed that it disappeared when we
reached the accessibility permission screen that uses this
flag.
Change-Id: Ic51ead670fc480e549512ba1d02f49d9c13bc3f0
(cherry picked from commit d4a5fd1ce32b25c8a8d7af35c4676011d64faa22)
-rw-r--r-- | api/system-current.txt | 1 | ||||
-rw-r--r-- | core/java/android/view/WindowManager.java | 28 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 9 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/Session.java | 10 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 37 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowState.java | 38 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowStateAnimator.java | 2 |
7 files changed, 125 insertions, 0 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 3c88e5979c8e..27119593d352 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -104,6 +104,7 @@ package android { field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH"; field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST"; field public static final java.lang.String HDMI_CEC = "android.permission.HDMI_CEC"; + field public static final java.lang.String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"; field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS"; field public static final java.lang.String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"; field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER"; diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 45bc1df33469..21b7f6116bbc 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -569,6 +569,25 @@ public interface WindowManager extends ViewManager { */ public static final int LAST_SYSTEM_WINDOW = 2999; + /** + * Return true if the window type is an alert window. + * + * @param type The window type. + * @return If the window type is an alert window. + * @hide + */ + public static boolean isSystemAlertWindowType(int type) { + switch (type) { + case TYPE_PHONE: + case TYPE_PRIORITY_PHONE: + case TYPE_SYSTEM_ALERT: + case TYPE_SYSTEM_ERROR: + case TYPE_SYSTEM_OVERLAY: + return true; + } + return false; + } + /** @deprecated this is ignored, this value is set automatically when needed. */ @Deprecated public static final int MEMORY_TYPE_NORMAL = 0; @@ -1128,6 +1147,15 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT = 0x00001000; /** + * Flag to indicate that any window added by an application process that is of type + * {@link #TYPE_TOAST} or that requires + * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when + * this window is visible. + * @hide + */ + public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000; + + /** * Control flags that are private to the platform. * @hide */ diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4b5445998d10..bb6bb4b82ceb 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1850,6 +1850,15 @@ <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" android:protectionLevel="signature" /> + <!-- @SystemApi Allows an application to use + {@link android.view.WindowManager.LayoutsParams#PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} + to hide non-system-overlay windows. + <p>Not for use by third-party applications. + @hide + --> + <permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" + android:protectionLevel="signature|installer" /> + <!-- @SystemApi Allows an application to manage (create, destroy, Z-order) application tokens in the window manager. <p>Not for use by third-party applications. diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index a8ba0f9ce6d8..adbf591d7458 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -16,6 +16,10 @@ package com.android.server.wm; +import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import android.view.IWindowId; import android.view.IWindowSessionCallback; import com.android.internal.view.IInputContext; @@ -61,6 +65,8 @@ final class Session extends IWindowSession.Stub final int mUid; final int mPid; final String mStringName; + final boolean mCanAddInternalSystemWindow; + final boolean mCanHideNonSystemOverlayWindows; SurfaceSession mSurfaceSession; int mNumWindow = 0; boolean mClientDead = false; @@ -74,6 +80,10 @@ final class Session extends IWindowSession.Stub mInputContext = inputContext; mUid = Binder.getCallingUid(); mPid = Binder.getCallingPid(); + mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission( + INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; + mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission( + HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED; mLastReportedAnimatorScale = service.getCurrentAnimatorScale(); StringBuilder sb = new StringBuilder(); sb.append("Session{"); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d695d936b0d4..dc722730b80d 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -415,6 +415,9 @@ public class WindowManagerService extends IWindowManager.Stub */ final ArrayList<WindowState> mForceRemoves = new ArrayList<>(); + /** List of window currently causing non-system overlay windows to be hidden. */ + private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<WindowState>(); + /** * Windows that clients are waiting to have drawn. */ @@ -2552,6 +2555,9 @@ public class WindowManagerService extends IWindowManager.Stub } } + final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); + win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); + if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { token.appWindowToken.startingWindow = win; if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken @@ -2834,6 +2840,7 @@ public class WindowManagerService extends IWindowManager.Stub mPendingRemove.remove(win); mResizingWindows.remove(win); + updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */); mWindowsChanged = true; if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); @@ -11859,6 +11866,36 @@ public class WindowManagerService extends IWindowManager.Stub return mWindowMap; } + void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) { + if (!win.hideNonSystemOverlayWindowsWhenVisible()) { + return; + } + final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty(); + if (surfaceShown) { + if (!mHidingNonSystemOverlayWindows.contains(win)) { + mHidingNonSystemOverlayWindows.add(win); + } + } else { + mHidingNonSystemOverlayWindows.remove(win); + } + + final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); + + if (systemAlertWindowsHidden == hideSystemAlertWindows) { + return; + } + + final int numDisplays = mDisplayContents.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); + final int numWindows = windows.size(); + for (int winNdx = 0; winNdx < numWindows; ++winNdx) { + final WindowState w = windows.get(winNdx); + w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); + } + } + } + private final class LocalService extends WindowManagerInternal { @Override public void requestTraversalFromDisplayManager() { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c2548de64ec2..3e77da7177ae 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -20,11 +20,14 @@ import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION; import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT; import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION; @@ -86,6 +89,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { final int mAppOp; // UserId and appId of the owner. Don't display windows of non-current user. final int mOwnerUid; + final boolean mOwnerCanAddInternalSystemWindow; final IWindowId mWindowId; WindowToken mToken; WindowToken mRootToken; @@ -111,6 +115,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { boolean mPolicyVisibility = true; boolean mPolicyVisibilityAfterAnim = true; boolean mAppOpVisibility = true; + // This is a non-system overlay window that is currently force hidden. + private boolean mForceHideNonSystemOverlayWindow; boolean mAppFreezing; boolean mAttachedHidden; // is our parent window hidden? boolean mWallpaperVisible; // for wallpaper, what was last vis report? @@ -376,6 +382,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { mAppOp = appOp; mToken = token; mOwnerUid = s.mUid; + mOwnerCanAddInternalSystemWindow = s.mCanAddInternalSystemWindow; mWindowId = new IWindowId.Stub() { @Override public void registerFocusObserver(IWindowFocusObserver observer) { @@ -1249,6 +1256,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { // Being hidden due to app op request. return false; } + if (mForceHideNonSystemOverlayWindow) { + // This is an alert window that is currently force hidden. + return false; + } if (mPolicyVisibility && mPolicyVisibilityAfterAnim) { // Already showing. return false; @@ -1322,6 +1333,22 @@ final class WindowState implements WindowManagerPolicy.WindowState { return true; } + void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) { + if (mOwnerCanAddInternalSystemWindow + || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) { + return; + } + if (mForceHideNonSystemOverlayWindow == forceHide) { + return; + } + mForceHideNonSystemOverlayWindow = forceHide; + if (forceHide) { + hideLw(true /* doAnimation */, true /* requestAnim */); + } else { + showLw(true /* doAnimation */, true /* requestAnim */); + } + } + public void setAppOpVisibilityLw(boolean state) { if (mAppOpVisibility != state) { mAppOpVisibility = state; @@ -1760,6 +1787,17 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } + /** + * Returns true if any window added by an application process that if of type + * {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires + * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when + * this window is visible. + */ + boolean hideNonSystemOverlayWindowsWhenVisible() { + return (mAttrs.privateFlags & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0 + && mSession.mCanHideNonSystemOverlayWindows; + } + String makeInputChannelName() { return Integer.toHexString(System.identityHashCode(this)) + " " + mAttrs.getTitle(); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 42042b94bc9f..bf78ed591a7f 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -498,6 +498,7 @@ class WindowStateAnimator { "HIDE (performLayout)", null); if (mSurfaceControl != null) { mSurfaceShown = false; + mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mWin, false); try { mSurfaceControl.hide(); } catch (RuntimeException e) { @@ -1783,6 +1784,7 @@ class WindowStateAnimator { if (mSurfaceControl != null) { mSurfaceShown = true; mSurfaceControl.show(); + mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mWin, true); if (mWin.mTurnOnScreen) { if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin); |