summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java9
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java8
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java29
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java29
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java12
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");