diff options
Diffstat (limited to 'services')
4 files changed, 86 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 08c0a4b01357..b5c4202dc107 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -16,6 +16,9 @@ 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 static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; @@ -67,6 +70,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; @@ -80,6 +85,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 ca2610af3f66..0d970591cb5c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -490,6 +490,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. */ @@ -2129,6 +2132,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_WM, "addWindow: " + token.appWindowToken @@ -2576,6 +2582,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_WM, "Final remove of window: " + win); @@ -11771,4 +11778,34 @@ public class WindowManagerService extends IWindowManager.Stub } } } + + 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); + } + } + } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index fbef2c626a9c..228ef1afb2a9 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -79,6 +79,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.MATCH_PARENT; 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.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; @@ -91,7 +92,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 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 android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; @@ -141,6 +144,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; @@ -167,6 +171,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { boolean mPolicyVisibilityAfterAnim = true; boolean mAppOpVisibility = true; boolean mPermanentlyHidden; // the window should never be shown again + // 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? @@ -522,6 +528,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) { @@ -1882,6 +1889,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { // to handle their windows being removed from under them. return false; } + if (mForceHideNonSystemOverlayWindow) { + // This is an alert window that is currently force hidden. + return false; + } if (mPolicyVisibility && mPolicyVisibilityAfterAnim) { // Already showing. return false; @@ -1955,6 +1966,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; @@ -2755,6 +2782,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)) + " " + getWindowTag(); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index aa8e781b1c07..ec3208b3cc6c 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -582,6 +582,7 @@ class WindowStateAnimator { //dump(); mLastHidden = true; if (mSurfaceController != null) { + mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mWin, false); mSurfaceController.hideInTransaction(reason); } } @@ -1814,6 +1815,7 @@ class WindowStateAnimator { if (!shown) return false; + mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mWin, true); if (mWin.mTurnOnScreen) { if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin); mWin.mTurnOnScreen = false; |