diff options
6 files changed, 93 insertions, 2 deletions
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index c9b78c08202e..1c3c5c7f4021 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -205,6 +205,15 @@ public abstract class PackageManagerInternal { int userId); /** + * Internal api to query the suspended state of a package. + * @param packageName The package to check. + * @param userId The user id to check for. + * @return {@code true} if the package is suspended, {@code false} otherwise. + * @see PackageManager#isPackageSuspended(String) + */ + public abstract boolean isPackageSuspended(String packageName, int userId); + + /** * Do a straight uid lookup for the given package/application in the given user. * @see PackageManager#getPackageUidAsUser(String, int, int) * @return The app's uid, or < 0 if the package was not found in that user diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 52bdea6cbf9a..935a244bdb34 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -23760,6 +23760,14 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } @Override + public boolean isPackageSuspended(String packageName, int userId) { + synchronized (mPackages) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + return (ps != null) ? ps.getSuspended(userId) : false; + } + } + + @Override public int getPackageUid(String packageName, int flags, int userId) { return PackageManagerService.this .getPackageUid(packageName, flags, userId); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 52d81777fd52..fd965fbc8ac7 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -417,6 +417,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { }, true /* traverseTopToBottom */); } + void updateHiddenWhileSuspendedState(final ArraySet<String> packages, final boolean suspended) { + forAllWindows((w) -> { + if (packages.contains(w.getOwningPackage())) { + w.setHiddenWhileSuspended(suspended); + } + }, false); + } + void updateAppOpsState() { forAllWindows((w) -> { w.updateAppOpsState(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f1cd46bc16d0..d2d505b03c68 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -128,6 +128,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.res.Configuration; import android.database.ContentObserver; import android.graphics.Bitmap; @@ -264,6 +265,7 @@ import java.lang.annotation.RetentionPolicy; import java.net.Socket; import java.text.DateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; /** {@hide} */ @@ -426,6 +428,7 @@ public class WindowManagerService extends IWindowManager.Stub final ActivityManagerInternal mAmInternal; final AppOpsManager mAppOps; + final PackageManagerInternal mPmInternal; final DisplaySettings mDisplaySettings; @@ -1006,6 +1009,22 @@ public class WindowManagerService extends IWindowManager.Stub mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener); mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); + mPmInternal = LocalServices.getService(PackageManagerInternal.class); + final IntentFilter suspendPackagesFilter = new IntentFilter(); + suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED); + suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED); + context.registerReceiverAsUser(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String[] affectedPackages = + intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); + final boolean suspended = + Intent.ACTION_PACKAGES_SUSPENDED.equals(intent.getAction()); + updateHiddenWhileSuspendedState(new ArraySet<>(Arrays.asList(affectedPackages)), + suspended); + } + }, UserHandle.ALL, suspendPackagesFilter, null, null); + // Get persisted window scale setting mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); @@ -1360,6 +1379,10 @@ public class WindowManagerService extends IWindowManager.Stub win.initAppOpsState(); + final boolean suspended = mPmInternal.isPackageSuspended(win.getOwningPackage(), + UserHandle.getUserId(win.getOwningUid())); + win.setHiddenWhileSuspended(suspended); + final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); @@ -1683,6 +1706,12 @@ public class WindowManagerService extends IWindowManager.Stub dc.computeImeTarget(true /* updateImeTarget */); } + private void updateHiddenWhileSuspendedState(ArraySet<String> packages, boolean suspended) { + synchronized (mWindowMap) { + mRoot.updateHiddenWhileSuspendedState(packages, suspended); + } + } + private void updateAppOpsState() { synchronized(mWindowMap) { mRoot.updateAppOpsState(); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 30bbfe0b83c4..b58c789115ea 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -20,6 +20,8 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.OP_NONE; +import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; +import static android.app.AppOpsManager.OP_TOAST_WINDOW; import static android.os.PowerManager.DRAW_WAKE_LOCK; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; @@ -64,7 +66,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; -import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; @@ -266,6 +267,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * animation is done. */ boolean mPolicyVisibilityAfterAnim = true; + // overlay window is hidden because the owning app is suspended + private boolean mHiddenWhileSuspended; private boolean mAppOpVisibility = true; boolean mPermanentlyHidden; // the window should never be shown again // This is a non-system overlay window that is currently force hidden. @@ -2489,6 +2492,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // to handle their windows being removed from under them. return false; } + if (mHiddenWhileSuspended) { + // Being hidden due to owner package being suspended. + return false; + } if (mForceHideNonSystemOverlayWindow) { // This is an alert window that is currently force hidden. return false; @@ -2585,6 +2592,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } + void setHiddenWhileSuspended(boolean hide) { + if (mOwnerCanAddInternalSystemWindow + || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) { + return; + } + if (mHiddenWhileSuspended == hide) { + return; + } + mHiddenWhileSuspended = hide; + if (hide) { + hideLw(true, true); + } else { + showLw(true, true); + } + } + private void setAppOpVisibilityLw(boolean state) { if (mAppOpVisibility != state) { mAppOpVisibility = state; @@ -3305,7 +3328,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.println(Integer.toHexString(mSystemUiVisibility)); } if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility - || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow) { + || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow + || mHiddenWhileSuspended) { pw.print(prefix); pw.print("mPolicyVisibility="); pw.print(mPolicyVisibility); pw.print(" mPolicyVisibilityAfterAnim="); @@ -3314,6 +3338,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.print(mAppOpVisibility); pw.print(" parentHidden="); pw.print(isParentWindowHidden()); pw.print(" mPermanentlyHidden="); pw.print(mPermanentlyHidden); + pw.print(" mHiddenWhileSuspended="); pw.print(mHiddenWhileSuspended); pw.print(" mForceHideNonSystemOverlayWindow="); pw.println( mForceHideNonSystemOverlayWindow); } diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java index 1248eaea7ae7..7b6ed1db1ff3 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java @@ -37,6 +37,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 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_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; @@ -51,6 +52,7 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; /** @@ -129,6 +131,16 @@ public class WindowStateTests extends WindowTestsBase { } @Test + public void testOverlayWindowHiddenWhenSuspended() { + final WindowState overlayWindow = spy(createWindow(null, TYPE_APPLICATION_OVERLAY, + "overlayWindow")); + overlayWindow.setHiddenWhileSuspended(true); + verify(overlayWindow).hideLw(true, true); + overlayWindow.setHiddenWhileSuspended(false); + verify(overlayWindow).showLw(true, true); + } + + @Test public void testGetTopParentWindow() throws Exception { final WindowState root = createWindow(null, TYPE_APPLICATION, "root"); final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1"); |