summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuprabh Shukla <suprabh@google.com>2019-08-27 15:58:03 -0700
committerSuprabh Shukla <suprabh@google.com>2019-09-25 17:11:17 -0700
commitd3278449d7d4d2a56d688fc27bb0c3eb36fb8ed2 (patch)
treee8d23c3b80486f5f31d8e65021c8e9e800816fae
parentb338ef16569b8e535128ee9e66807f334322139d (diff)
Allowing more than one app to suspend apps
We want to allow wellbeing apps to suspend in managed profiles. This requires changing the internal data design of package-suspend state to allow more than one suspending package, each with their own parameters, namely - dialog info, app extras and launcher extras. Also, removed the restriction of using setPackagesSuspendedAsUser when a PO/DO exists Test: atest com.android.server.pm.PackageUserStateTest atest com.android.server.pm.PackageManagerSettingsTests atest com.android.server.wm.ActivityStartInterceptorTest atest GtsSuspendAppsTestCases Bug: 138812320 Change-Id: If1263142fc9e6687e95af9b8d71ba8eff0c0fae9
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/app/ApplicationPackageManager.java5
-rw-r--r--core/java/android/content/Intent.java11
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl3
-rw-r--r--core/java/android/content/pm/LauncherApps.java4
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java4
-rw-r--r--core/java/android/content/pm/PackageUserState.java197
-rw-r--r--core/java/com/android/internal/content/PackageMonitor.java9
-rw-r--r--core/proto/android/service/package.proto2
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java5
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java27
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java190
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java46
-rw-r--r--services/core/java/com/android/server/pm/Settings.java132
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java137
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java121
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java4
19 files changed, 629 insertions, 277 deletions
diff --git a/api/current.txt b/api/current.txt
index eeaabf661e73..f56400c9a4db 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11392,7 +11392,7 @@ package android.content.pm {
method public abstract void onPackageRemoved(String, android.os.UserHandle);
method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean);
method public void onPackagesSuspended(String[], android.os.UserHandle);
- method public void onPackagesSuspended(String[], android.os.UserHandle, @Nullable android.os.Bundle);
+ method @Deprecated public void onPackagesSuspended(String[], android.os.UserHandle, @Nullable android.os.Bundle);
method public abstract void onPackagesUnavailable(String[], android.os.UserHandle, boolean);
method public void onPackagesUnsuspended(String[], android.os.UserHandle);
method public void onShortcutsChanged(@NonNull String, @NonNull java.util.List<android.content.pm.ShortcutInfo>, @NonNull android.os.UserHandle);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index d74399c54bda..a2013075b379 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2414,14 +2414,11 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public Bundle getSuspendedPackageAppExtras() {
- final PersistableBundle extras;
try {
- extras = mPM.getSuspendedPackageAppExtras(mContext.getOpPackageName(),
- getUserId());
+ return mPM.getSuspendedPackageAppExtras(mContext.getOpPackageName(), getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- return extras != null ? new Bundle(extras.deepCopy()) : null;
}
@Override
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3418b7be42d6..40d9a0dfb095 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2025,17 +2025,6 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
/**
- * Intent extra: A {@link Bundle} of extras supplied for the launcher when any packages on
- * device are suspended. Will be sent with {@link #ACTION_PACKAGES_SUSPENDED}.
- *
- * @see PackageManager#isPackageSuspended()
- * @see #ACTION_PACKAGES_SUSPENDED
- *
- * @hide
- */
- public static final String EXTRA_LAUNCHER_EXTRAS = "android.intent.extra.LAUNCHER_EXTRAS";
-
- /**
* Intent extra: ID of the shortcut used to send the share intent. Will be sent with
* {@link #ACTION_SEND}.
*
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c6beee2f898a..4d7c43ace923 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -50,6 +50,7 @@ import android.content.pm.VersionedPackage;
import android.content.pm.dex.IArtManager;
import android.graphics.Bitmap;
import android.net.Uri;
+import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.content.IntentSender;
@@ -280,7 +281,7 @@ interface IPackageManager {
boolean isPackageSuspendedForUser(String packageName, int userId);
- PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId);
+ Bundle getSuspendedPackageAppExtras(String packageName, int userId);
/**
* Backup/restore support - only the system uid may use these.
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index c74daa8eadfc..5650b25d73f0 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -248,7 +248,11 @@ public class LauncherApps {
* system, {@code null} otherwise.
* @see PackageManager#isPackageSuspended()
* @see #getSuspendedPackageLauncherExtras(String, UserHandle)
+ * @deprecated {@code launcherExtras} should be obtained by using
+ * {@link #getSuspendedPackageLauncherExtras(String, UserHandle)}. For all other cases,
+ * {@link #onPackagesSuspended(String[], UserHandle)} should be used.
*/
+ @Deprecated
public void onPackagesSuspended(String[] packageNames, UserHandle user,
@Nullable Bundle launcherExtras) {
onPackagesSuspended(packageNames, user);
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 24ee21360ed8..0a50125a7bb1 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -191,11 +191,13 @@ public abstract class PackageManagerInternal {
* suspended application.
*
* @param suspendedPackage The package that has been suspended.
+ * @param suspendingPackage
* @param userId The user for which to check.
* @return A {@link SuspendDialogInfo} object describing the dialog to be shown.
*/
@Nullable
- public abstract SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, int userId);
+ public abstract SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage,
+ String suspendingPackage, int userId);
/**
* Gets any distraction flags set via
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 249b6919fc28..5c74efb8ff1b 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -31,6 +31,7 @@ import android.annotation.UnsupportedAppUsage;
import android.os.BaseBundle;
import android.os.Debug;
import android.os.PersistableBundle;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.Slog;
@@ -38,6 +39,11 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
@@ -56,10 +62,7 @@ public class PackageUserState {
public boolean hidden; // Is the app restricted by owner / admin
public int distractionFlags;
public boolean suspended;
- public String suspendingPackage;
- public SuspendDialogInfo dialogInfo;
- public PersistableBundle suspendedAppExtras;
- public PersistableBundle suspendedLauncherExtras;
+ public ArrayMap<String, SuspendParams> suspendParams; // Suspending package to suspend params
public boolean instantApp;
public boolean virtualPreload;
public int enabled;
@@ -95,10 +98,7 @@ public class PackageUserState {
hidden = o.hidden;
distractionFlags = o.distractionFlags;
suspended = o.suspended;
- suspendingPackage = o.suspendingPackage;
- dialogInfo = o.dialogInfo;
- suspendedAppExtras = o.suspendedAppExtras;
- suspendedLauncherExtras = o.suspendedLauncherExtras;
+ suspendParams = new ArrayMap<>(o.suspendParams);
instantApp = o.instantApp;
virtualPreload = o.virtualPreload;
enabled = o.enabled;
@@ -231,19 +231,7 @@ public class PackageUserState {
return false;
}
if (suspended) {
- if (suspendingPackage == null
- || !suspendingPackage.equals(oldState.suspendingPackage)) {
- return false;
- }
- if (!Objects.equals(dialogInfo, oldState.dialogInfo)) {
- return false;
- }
- if (!BaseBundle.kindofEquals(suspendedAppExtras,
- oldState.suspendedAppExtras)) {
- return false;
- }
- if (!BaseBundle.kindofEquals(suspendedLauncherExtras,
- oldState.suspendedLauncherExtras)) {
+ if (!Objects.equals(suspendParams, oldState.suspendParams)) {
return false;
}
}
@@ -308,4 +296,171 @@ public class PackageUserState {
}
return true;
}
+
+ @Override
+ public int hashCode() {
+ int hashCode = Long.hashCode(ceDataInode);
+ hashCode = 31 * hashCode + Boolean.hashCode(installed);
+ hashCode = 31 * hashCode + Boolean.hashCode(stopped);
+ hashCode = 31 * hashCode + Boolean.hashCode(notLaunched);
+ hashCode = 31 * hashCode + Boolean.hashCode(hidden);
+ hashCode = 31 * hashCode + distractionFlags;
+ hashCode = 31 * hashCode + Boolean.hashCode(suspended);
+ hashCode = 31 * hashCode + Objects.hashCode(suspendParams);
+ hashCode = 31 * hashCode + Boolean.hashCode(instantApp);
+ hashCode = 31 * hashCode + Boolean.hashCode(virtualPreload);
+ hashCode = 31 * hashCode + enabled;
+ hashCode = 31 * hashCode + Objects.hashCode(lastDisableAppCaller);
+ hashCode = 31 * hashCode + domainVerificationStatus;
+ hashCode = 31 * hashCode + appLinkGeneration;
+ hashCode = 31 * hashCode + categoryHint;
+ hashCode = 31 * hashCode + installReason;
+ hashCode = 31 * hashCode + Objects.hashCode(disabledComponents);
+ hashCode = 31 * hashCode + Objects.hashCode(enabledComponents);
+ hashCode = 31 * hashCode + Objects.hashCode(harmfulAppWarning);
+ return hashCode;
+ }
+
+ /**
+ * Container to describe suspension parameters.
+ */
+ public static final class SuspendParams {
+ private static final String TAG_DIALOG_INFO = "dialog-info";
+ private static final String TAG_APP_EXTRAS = "app-extras";
+ private static final String TAG_LAUNCHER_EXTRAS = "launcher-extras";
+
+ public SuspendDialogInfo dialogInfo;
+ public PersistableBundle appExtras;
+ public PersistableBundle launcherExtras;
+
+ private SuspendParams() {
+ }
+
+ /**
+ * Returns a {@link SuspendParams} object with the given fields. Returns {@code null} if all
+ * the fields are {@code null}.
+ *
+ * @param dialogInfo
+ * @param appExtras
+ * @param launcherExtras
+ * @return A {@link SuspendParams} object or {@code null}.
+ */
+ public static SuspendParams getInstanceOrNull(SuspendDialogInfo dialogInfo,
+ PersistableBundle appExtras, PersistableBundle launcherExtras) {
+ if (dialogInfo == null && appExtras == null && launcherExtras == null) {
+ return null;
+ }
+ final SuspendParams instance = new SuspendParams();
+ instance.dialogInfo = dialogInfo;
+ instance.appExtras = appExtras;
+ instance.launcherExtras = launcherExtras;
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SuspendParams)) {
+ return false;
+ }
+ final SuspendParams other = (SuspendParams) obj;
+ if (!Objects.equals(dialogInfo, other.dialogInfo)) {
+ return false;
+ }
+ if (!BaseBundle.kindofEquals(appExtras, other.appExtras)) {
+ return false;
+ }
+ if (!BaseBundle.kindofEquals(launcherExtras, other.launcherExtras)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = Objects.hashCode(dialogInfo);
+ hashCode = 31 * hashCode + ((appExtras != null) ? appExtras.size() : 0);
+ hashCode = 31 * hashCode + ((launcherExtras != null) ? launcherExtras.size() : 0);
+ return hashCode;
+ }
+
+ /**
+ * Serializes this object into an xml format
+ * @param out the {@link XmlSerializer} object
+ * @throws IOException
+ */
+ public void saveToXml(XmlSerializer out) throws IOException {
+ if (dialogInfo != null) {
+ out.startTag(null, TAG_DIALOG_INFO);
+ dialogInfo.saveToXml(out);
+ out.endTag(null, TAG_DIALOG_INFO);
+ }
+ if (appExtras != null) {
+ out.startTag(null, TAG_APP_EXTRAS);
+ try {
+ appExtras.saveToXml(out);
+ } catch (XmlPullParserException e) {
+ Slog.e(LOG_TAG, "Exception while trying to write appExtras."
+ + " Will be lost on reboot", e);
+ }
+ out.endTag(null, TAG_APP_EXTRAS);
+ }
+ if (launcherExtras != null) {
+ out.startTag(null, TAG_LAUNCHER_EXTRAS);
+ try {
+ launcherExtras.saveToXml(out);
+ } catch (XmlPullParserException e) {
+ Slog.e(LOG_TAG, "Exception while trying to write launcherExtras."
+ + " Will be lost on reboot", e);
+ }
+ out.endTag(null, TAG_LAUNCHER_EXTRAS);
+ }
+ }
+
+ /**
+ * Parses this object from the xml format. Returns {@code null} if no object related
+ * information could be read.
+ * @param in the reader
+ * @return
+ */
+ public static SuspendParams restoreFromXml(XmlPullParser in) throws IOException {
+ SuspendDialogInfo readDialogInfo = null;
+ PersistableBundle readAppExtras = null;
+ PersistableBundle readLauncherExtras = null;
+
+ final int currentDepth = in.getDepth();
+ int type;
+ try {
+ while ((type = in.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || in.getDepth() > currentDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ switch (in.getName()) {
+ case TAG_DIALOG_INFO:
+ readDialogInfo = SuspendDialogInfo.restoreFromXml(in);
+ break;
+ case TAG_APP_EXTRAS:
+ readAppExtras = PersistableBundle.restoreFromXml(in);
+ break;
+ case TAG_LAUNCHER_EXTRAS:
+ readLauncherExtras = PersistableBundle.restoreFromXml(in);
+ break;
+ default:
+ Slog.w(LOG_TAG, "Unknown tag " + in.getName()
+ + " in SuspendParams. Ignoring");
+ break;
+ }
+ }
+ } catch (XmlPullParserException e) {
+ Slog.e(LOG_TAG, "Exception while trying to parse SuspendParams,"
+ + " some fields may default", e);
+ }
+ return getInstanceOrNull(readDialogInfo, readAppExtras, readLauncherExtras);
+ }
+ }
}
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index c928f3f39f03..d6dcb29e0682 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -22,11 +22,11 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.util.Slog;
+
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.Preconditions;
@@ -203,10 +203,6 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
public void onPackagesSuspended(String[] packages) {
}
- public void onPackagesSuspended(String[] packages, Bundle launcherExtras) {
- onPackagesSuspended(packages);
- }
-
public void onPackagesUnsuspended(String[] packages) {
}
@@ -446,9 +442,8 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
}
} else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- final Bundle launcherExtras = intent.getBundleExtra(Intent.EXTRA_LAUNCHER_EXTRAS);
mSomePackagesChanged = true;
- onPackagesSuspended(pkgList, launcherExtras);
+ onPackagesSuspended(pkgList);
} else if (Intent.ACTION_PACKAGES_UNSUSPENDED.equals(action)) {
String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
mSomePackagesChanged = true;
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index 6ffa0c943037..301fa13ce4d8 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -110,7 +110,7 @@ message PackageProto {
optional bool is_launched = 6;
optional EnabledState enabled_state = 7;
optional string last_disabled_app_caller = 8;
- optional string suspending_package = 9;
+ repeated string suspending_package = 9;
optional int32 distraction_flags = 10;
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index fea4e9047f83..81ce359cc078 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -631,8 +631,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
onClickIntent = mDevicePolicyManagerInternal.createShowAdminSupportIntent(
providerUserId, true);
} else {
- final SuspendDialogInfo dialogInfo = mPackageManagerInternal
- .getSuspendedDialogInfo(providerPackage, providerUserId);
+ final SuspendDialogInfo dialogInfo =
+ mPackageManagerInternal.getSuspendedDialogInfo(providerPackage,
+ suspendingPackage, providerUserId);
onClickIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(
providerPackage, suspendingPackage, dialogInfo, providerUserId);
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 3464cab99d93..2b6c347fe726 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -62,6 +62,7 @@ import android.os.UserManager;
import android.os.UserManagerInternal;
import android.provider.Settings;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -1024,8 +1025,22 @@ public class LauncherAppsService extends SystemService {
}
@Override
- public void onPackagesSuspended(String[] packages, Bundle launcherExtras) {
+ public void onPackagesSuspended(String[] packages) {
UserHandle user = new UserHandle(getChangingUserId());
+ PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+ final ArrayList<Pair<String, Bundle>> packagesWithExtras = new ArrayList<>();
+ final ArrayList<String> packagesWithoutExtras = new ArrayList<>();
+ for (String pkg : packages) {
+ final Bundle launcherExtras = pmi.getSuspendedPackageLauncherExtras(pkg,
+ user.getIdentifier());
+ if (launcherExtras != null) {
+ packagesWithExtras.add(new Pair<>(pkg, launcherExtras));
+ } else {
+ packagesWithoutExtras.add(pkg);
+ }
+ }
+ final String[] packagesNullExtras = packagesWithoutExtras.toArray(
+ new String[packagesWithoutExtras.size()]);
final int n = mListeners.beginBroadcast();
try {
for (int i = 0; i < n; i++) {
@@ -1033,7 +1048,13 @@ public class LauncherAppsService extends SystemService {
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
if (!isEnabledProfileOf(cookie.user, user, "onPackagesSuspended")) continue;
try {
- listener.onPackagesSuspended(user, packages, launcherExtras);
+ listener.onPackagesSuspended(user, packagesNullExtras, null);
+ for (int idx = 0; idx < packagesWithExtras.size(); idx++) {
+ Pair<String, Bundle> packageExtraPair = packagesWithExtras.get(idx);
+ listener.onPackagesSuspended(user,
+ new String[]{packageExtraPair.first},
+ packageExtraPair.second);
+ }
} catch (RemoteException re) {
Slog.d(TAG, "Callback failed ", re);
}
@@ -1041,8 +1062,6 @@ public class LauncherAppsService extends SystemService {
} finally {
mListeners.finishBroadcast();
}
-
- super.onPackagesSuspended(packages, launcherExtras);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fe3d2c8fa981..3c6016f8afc3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -372,7 +372,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
-import java.util.function.Predicate;
/**
* Keep track of all those APKs everywhere.
@@ -12665,14 +12664,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
private void sendPackagesSuspendedForUser(String[] pkgList, int[] uidList, int userId,
- boolean suspended, PersistableBundle launcherExtras) {
+ boolean suspended) {
final Bundle extras = new Bundle(3);
extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
- if (launcherExtras != null) {
- extras.putBundle(Intent.EXTRA_LAUNCHER_EXTRAS,
- new Bundle(launcherExtras.deepCopy()));
- }
sendPackageBroadcast(
suspended ? Intent.ACTION_PACKAGES_SUSPENDED
: Intent.ACTION_PACKAGES_UNSUSPENDED,
@@ -12937,8 +12932,6 @@ public class PackageManagerService extends IPackageManager.Stub
if (ownerUid == callingUid) {
return;
}
- throw new UnsupportedOperationException("Cannot suspend/unsuspend packages. User "
- + userId + " has an active DO or PO");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
@@ -12946,6 +12939,7 @@ public class PackageManagerService extends IPackageManager.Stub
final int packageUid = getPackageUid(callingPackage, 0, userId);
final boolean allowedPackageUid = packageUid == callingUid;
+ // TODO(b/139383163): remove special casing for shell and enforce INTERACT_ACROSS_USERS_FULL
final boolean allowedShell = callingUid == SHELL_UID
&& UserHandle.isSameApp(packageUid, callingUid);
@@ -12996,20 +12990,27 @@ public class PackageManagerService extends IPackageManager.Stub
unactionedPackages.add(packageName);
continue;
}
+ boolean packageUnsuspended;
synchronized (mLock) {
- pkgSetting.setSuspended(suspended, callingPackage, dialogInfo, appExtras,
- launcherExtras, userId);
+ if (suspended) {
+ pkgSetting.addOrUpdateSuspension(callingPackage, dialogInfo, appExtras,
+ launcherExtras, userId);
+ } else {
+ pkgSetting.removeSuspension(callingPackage, userId);
+ }
+ packageUnsuspended = !suspended && !pkgSetting.getSuspended(userId);
+ }
+ if (suspended || packageUnsuspended) {
+ changedPackagesList.add(packageName);
+ changedUids.add(UserHandle.getUid(userId, pkgSetting.appId));
}
- changedPackagesList.add(packageName);
- changedUids.add(UserHandle.getUid(userId, pkgSetting.appId));
}
if (!changedPackagesList.isEmpty()) {
final String[] changedPackages = changedPackagesList.toArray(
new String[changedPackagesList.size()]);
- sendPackagesSuspendedForUser(
- changedPackages, changedUids.toArray(), userId, suspended, launcherExtras);
- sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, appExtras, userId);
+ sendPackagesSuspendedForUser(changedPackages, changedUids.toArray(), userId, suspended);
+ sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, userId);
synchronized (mLock) {
scheduleWritePackageRestrictionsLocked(userId);
}
@@ -13018,38 +13019,40 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
- public PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId) {
+ public Bundle getSuspendedPackageAppExtras(String packageName, int userId) {
final int callingUid = Binder.getCallingUid();
if (getPackageUid(packageName, 0, userId) != callingUid) {
throw new SecurityException("Calling package " + packageName
+ " does not belong to calling uid " + callingUid);
}
+ return getSuspendedPackageAppExtrasInternal(packageName, userId);
+ }
+
+ private Bundle getSuspendedPackageAppExtrasInternal(String packageName, int userId) {
synchronized (mLock) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
+ if (ps == null) {
throw new IllegalArgumentException("Unknown target package: " + packageName);
}
- final PackageUserState packageUserState = ps.readUserState(userId);
- if (packageUserState.suspended) {
- return packageUserState.suspendedAppExtras;
+ final PackageUserState pus = ps.readUserState(userId);
+ final Bundle allExtras = new Bundle();
+ if (pus.suspended) {
+ for (int i = 0; i < pus.suspendParams.size(); i++) {
+ final PackageUserState.SuspendParams params = pus.suspendParams.valueAt(i);
+ if (params != null && params.appExtras != null) {
+ allExtras.putAll(params.appExtras);
+ }
+ }
}
- return null;
+ return (allExtras.size() > 0) ? allExtras : null;
}
}
private void sendMyPackageSuspendedOrUnsuspended(String[] affectedPackages, boolean suspended,
- PersistableBundle appExtras, int userId) {
- final String action;
- final Bundle intentExtras = new Bundle();
- if (suspended) {
- action = Intent.ACTION_MY_PACKAGE_SUSPENDED;
- if (appExtras != null) {
- final Bundle bundledAppExtras = new Bundle(appExtras.deepCopy());
- intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, bundledAppExtras);
- }
- } else {
- action = Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
- }
+ int userId) {
+ final String action = suspended
+ ? Intent.ACTION_MY_PACKAGE_SUSPENDED
+ : Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
mHandler.post(() -> {
try {
final IActivityManager am = ActivityManager.getService();
@@ -13060,6 +13063,16 @@ public class PackageManagerService extends IPackageManager.Stub
}
final int[] targetUserIds = new int[] {userId};
for (String packageName : affectedPackages) {
+ final Bundle appExtras = suspended
+ ? getSuspendedPackageAppExtrasInternal(packageName, userId)
+ : null;
+ final Bundle intentExtras;
+ if (appExtras != null) {
+ intentExtras = new Bundle(1);
+ intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, appExtras);
+ } else {
+ intentExtras = null;
+ }
doSendBroadcast(am, action, null, intentExtras,
Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
targetUserIds, false);
@@ -13092,57 +13105,32 @@ public class PackageManagerService extends IPackageManager.Stub
* <p><b>Should not be used on a frequent code path</b> as it flushes state to disk
* synchronously
*
- * @param packageName The package holding {@link Manifest.permission#SUSPEND_APPS} permission
- * @param affectedUser The user for which the changes are taking place.
- */
- void unsuspendForSuspendingPackage(final String packageName, int affectedUser) {
- final int[] userIds = (affectedUser == UserHandle.USER_ALL) ? mUserManager.getUserIds()
- : new int[] {affectedUser};
- for (int userId : userIds) {
- unsuspendForSuspendingPackages(packageName::equals, userId);
- }
- }
-
- /**
- * Immediately unsuspends any packages in the given users not suspended by the platform or root.
- * To be called when a profile owner or a device owner is added.
- *
- * <p><b>Should not be used on a frequent code path</b> as it flushes state to disk
- * synchronously
- *
- * @param userIds The users for which to unsuspend packages
+ * @param suspendingPackage The suspending package
+ * @param userId The user for which the changes are taking place.
*/
- void unsuspendForNonSystemSuspendingPackages(ArraySet<Integer> userIds) {
- final int sz = userIds.size();
- for (int i = 0; i < sz; i++) {
- unsuspendForSuspendingPackages(
- (suspendingPackage) -> !PLATFORM_PACKAGE_NAME.equals(suspendingPackage),
- userIds.valueAt(i));
- }
- }
-
- private void unsuspendForSuspendingPackages(Predicate<String> packagePredicate, int userId) {
- final List<String> affectedPackages = new ArrayList<>();
- final IntArray affectedUids = new IntArray();
+ private void unsuspendForSuspendingPackage(String suspendingPackage, int userId) {
+ final List<String> unsuspendedPackages = new ArrayList<>();
+ final IntArray unsuspendedUids = new IntArray();
synchronized (mLock) {
for (PackageSetting ps : mSettings.mPackages.values()) {
final PackageUserState pus = ps.readUserState(userId);
- if (pus.suspended && packagePredicate.test(pus.suspendingPackage)) {
- ps.setSuspended(false, null, null, null, null, userId);
- affectedPackages.add(ps.name);
- affectedUids.add(UserHandle.getUid(userId, ps.getAppId()));
+ if (pus.suspended) {
+ ps.removeSuspension(suspendingPackage, userId);
+ if (!ps.getSuspended(userId)) {
+ unsuspendedPackages.add(ps.name);
+ unsuspendedUids.add(UserHandle.getUid(userId, ps.getAppId()));
+ }
}
}
}
- if (!affectedPackages.isEmpty()) {
- final String[] packageArray = affectedPackages.toArray(
- new String[affectedPackages.size()]);
- sendMyPackageSuspendedOrUnsuspended(packageArray, false, null, userId);
- sendPackagesSuspendedForUser(
- packageArray, affectedUids.toArray(), userId, false, null);
- // Write package restrictions immediately to avoid an inconsistent state.
- mSettings.writePackageRestrictionsLPr(userId);
+ if (!unsuspendedPackages.isEmpty()) {
+ final String[] packageArray = unsuspendedPackages.toArray(
+ new String[unsuspendedPackages.size()]);
+ sendMyPackageSuspendedOrUnsuspended(packageArray, false, userId);
+ sendPackagesSuspendedForUser(packageArray, unsuspendedUids.toArray(), userId, false);
}
+ // Write package restrictions immediately to avoid an inconsistent state.
+ mSettings.writePackageRestrictionsLPr(userId);
}
@Override
@@ -18712,10 +18700,7 @@ public class PackageManagerService extends IPackageManager.Stub
false /*hidden*/,
0 /*distractionFlags*/,
false /*suspended*/,
- null /*suspendingPackage*/,
- null /*dialogInfo*/,
- null /*suspendedAppExtras*/,
- null /*suspendedLauncherExtras*/,
+ null /*suspendParams*/,
false /*instantApp*/,
false /*virtualPreload*/,
null /*lastDisableAppCaller*/,
@@ -23217,11 +23202,21 @@ public class PackageManagerService extends IPackageManager.Stub
public Bundle getSuspendedPackageLauncherExtras(String packageName, int userId) {
synchronized (mLock) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
- PersistableBundle launcherExtras = null;
+ final Bundle allExtras = new Bundle();
if (ps != null) {
- launcherExtras = ps.readUserState(userId).suspendedLauncherExtras;
+ final PackageUserState pus = ps.readUserState(userId);
+ if (pus.suspended) {
+ for (int i = 0; i < pus.suspendParams.size(); i++) {
+ final PackageUserState.SuspendParams params =
+ pus.suspendParams.valueAt(i);
+ if (params != null && params.launcherExtras != null) {
+ allExtras.putAll(params.launcherExtras);
+ }
+ }
+ }
+
}
- return (launcherExtras != null) ? new Bundle(launcherExtras.deepCopy()) : null;
+ return (allExtras.size() > 0) ? allExtras : null;
}
}
@@ -23237,16 +23232,38 @@ public class PackageManagerService extends IPackageManager.Stub
public String getSuspendingPackage(String suspendedPackage, int userId) {
synchronized (mLock) {
final PackageSetting ps = mSettings.mPackages.get(suspendedPackage);
- return (ps != null) ? ps.readUserState(userId).suspendingPackage : null;
+ if (ps != null) {
+ final PackageUserState pus = ps.readUserState(userId);
+ if (pus.suspended) {
+ String suspendingPackage = null;
+ for (int i = 0; i < pus.suspendParams.size(); i++) {
+ suspendingPackage = pus.suspendParams.keyAt(i);
+ if (PLATFORM_PACKAGE_NAME.equals(suspendingPackage)) {
+ return suspendingPackage;
+ }
+ }
+ return suspendingPackage;
+ }
+ }
+ return null;
}
}
@Override
- public SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, int userId) {
+ public SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage,
+ String suspendingPackage, int userId) {
synchronized (mLock) {
final PackageSetting ps = mSettings.mPackages.get(suspendedPackage);
- return (ps != null) ? ps.readUserState(userId).dialogInfo : null;
+ if (ps != null) {
+ final PackageUserState pus = ps.readUserState(userId);
+ if (pus.suspended) {
+ final PackageUserState.SuspendParams suspendParams =
+ pus.suspendParams.get(suspendingPackage);
+ return (suspendParams != null) ? suspendParams.dialogInfo : null;
+ }
+ }
}
+ return null;
}
@Override
@@ -23323,7 +23340,6 @@ public class PackageManagerService extends IPackageManager.Stub
usersWithPoOrDo.add(profileOwnerPackages.keyAt(i));
}
}
- unsuspendForNonSystemSuspendingPackages(usersWithPoOrDo);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index fe529a152364..64391c30fa5a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2044,7 +2044,9 @@ class PackageManagerShellCommand extends ShellCommand {
}
try {
mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
- appExtras, launcherExtras, info, callingPackage, userId);
+ ((appExtras.size() > 0) ? appExtras : null),
+ ((launcherExtras.size() > 0) ? launcherExtras : null),
+ info, callingPackage, userId);
pw.println("Package " + packageName + " new suspended state: "
+ mInterface.isPackageSuspendedForUser(packageName, userId));
return 0;
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 029673ffd87b..0da6b549f296 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -29,6 +29,7 @@ import android.content.pm.Signature;
import android.content.pm.SuspendDialogInfo;
import android.os.PersistableBundle;
import android.service.pm.PackageProto;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
@@ -405,14 +406,28 @@ public abstract class PackageSettingBase extends SettingBase {
return readUserState(userId).suspended;
}
- void setSuspended(boolean suspended, String suspendingPackage, SuspendDialogInfo dialogInfo,
+ void addOrUpdateSuspension(String suspendingPackage, SuspendDialogInfo dialogInfo,
PersistableBundle appExtras, PersistableBundle launcherExtras, int userId) {
final PackageUserState existingUserState = modifyUserState(userId);
- existingUserState.suspended = suspended;
- existingUserState.suspendingPackage = suspended ? suspendingPackage : null;
- existingUserState.dialogInfo = suspended ? dialogInfo : null;
- existingUserState.suspendedAppExtras = suspended ? appExtras : null;
- existingUserState.suspendedLauncherExtras = suspended ? launcherExtras : null;
+ final PackageUserState.SuspendParams newSuspendParams =
+ PackageUserState.SuspendParams.getInstanceOrNull(dialogInfo, appExtras,
+ launcherExtras);
+ if (existingUserState.suspendParams == null) {
+ existingUserState.suspendParams = new ArrayMap<>();
+ }
+ existingUserState.suspendParams.put(suspendingPackage, newSuspendParams);
+ existingUserState.suspended = true;
+ }
+
+ void removeSuspension(String suspendingPackage, int userId) {
+ final PackageUserState existingUserState = modifyUserState(userId);
+ if (existingUserState.suspendParams != null) {
+ existingUserState.suspendParams.remove(suspendingPackage);
+ if (existingUserState.suspendParams.size() == 0) {
+ existingUserState.suspendParams = null;
+ }
+ }
+ existingUserState.suspended = (existingUserState.suspendParams != null);
}
public boolean getInstantApp(int userId) {
@@ -433,9 +448,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
boolean notLaunched, boolean hidden, int distractionFlags, boolean suspended,
- String suspendingPackage,
- SuspendDialogInfo dialogInfo, PersistableBundle suspendedAppExtras,
- PersistableBundle suspendedLauncherExtras, boolean instantApp,
+ ArrayMap<String, PackageUserState.SuspendParams> suspendParams, boolean instantApp,
boolean virtualPreload, String lastDisableAppCaller,
ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
int domainVerifState, int linkGeneration, int installReason,
@@ -449,10 +462,7 @@ public abstract class PackageSettingBase extends SettingBase {
state.hidden = hidden;
state.distractionFlags = distractionFlags;
state.suspended = suspended;
- state.suspendingPackage = suspendingPackage;
- state.dialogInfo = dialogInfo;
- state.suspendedAppExtras = suspendedAppExtras;
- state.suspendedLauncherExtras = suspendedLauncherExtras;
+ state.suspendParams = suspendParams;
state.lastDisableAppCaller = lastDisableAppCaller;
state.enabledComponents = enabledComponents;
state.disabledComponents = disabledComponents;
@@ -467,9 +477,8 @@ public abstract class PackageSettingBase extends SettingBase {
void setUserState(int userId, PackageUserState otherState) {
setUserState(userId, otherState.ceDataInode, otherState.enabled, otherState.installed,
otherState.stopped, otherState.notLaunched, otherState.hidden,
- otherState.distractionFlags, otherState.suspended, otherState.suspendingPackage,
- otherState.dialogInfo, otherState.suspendedAppExtras,
- otherState.suspendedLauncherExtras, otherState.instantApp,
+ otherState.distractionFlags, otherState.suspended, otherState.suspendParams,
+ otherState.instantApp,
otherState.virtualPreload, otherState.lastDisableAppCaller,
otherState.enabledComponents, otherState.disabledComponents,
otherState.domainVerificationStatus, otherState.appLinkGeneration,
@@ -633,7 +642,10 @@ public abstract class PackageSettingBase extends SettingBase {
proto.write(PackageProto.UserInfoProto.DISTRACTION_FLAGS, state.distractionFlags);
proto.write(PackageProto.UserInfoProto.IS_SUSPENDED, state.suspended);
if (state.suspended) {
- proto.write(PackageProto.UserInfoProto.SUSPENDING_PACKAGE, state.suspendingPackage);
+ for (int j = 0; j < state.suspendParams.size(); j++) {
+ proto.write(PackageProto.UserInfoProto.SUSPENDING_PACKAGE,
+ state.suspendParams.keyAt(j));
+ }
}
proto.write(PackageProto.UserInfoProto.IS_STOPPED, state.stopped);
proto.write(PackageProto.UserInfoProto.IS_LAUNCHED, !state.notLaunched);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 597246884ca5..5f9cdb57e5f1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -203,9 +203,22 @@ public final class Settings {
private static final String TAG_DEFAULT_BROWSER = "default-browser";
private static final String TAG_DEFAULT_DIALER = "default-dialer";
private static final String TAG_VERSION = "version";
+ /**
+ * @deprecated Moved to {@link android.content.pm.PackageUserState.SuspendParams}
+ */
+ @Deprecated
private static final String TAG_SUSPENDED_DIALOG_INFO = "suspended-dialog-info";
+ /**
+ * @deprecated Moved to {@link android.content.pm.PackageUserState.SuspendParams}
+ */
+ @Deprecated
private static final String TAG_SUSPENDED_APP_EXTRAS = "suspended-app-extras";
+ /**
+ * @deprecated Moved to {@link android.content.pm.PackageUserState.SuspendParams}
+ */
+ @Deprecated
private static final String TAG_SUSPENDED_LAUNCHER_EXTRAS = "suspended-launcher-extras";
+ private static final String TAG_SUSPEND_PARAMS = "suspend-params";
public static final String ATTR_NAME = "name";
public static final String ATTR_PACKAGE = "package";
@@ -658,10 +671,7 @@ public final class Settings {
false /*hidden*/,
0 /*distractionFlags*/,
false /*suspended*/,
- null /*suspendingPackage*/,
- null /*dialogInfo*/,
- null /*suspendedAppExtras*/,
- null /*suspendedLauncherExtras*/,
+ null /*suspendParams*/,
instantApp,
virtualPreload,
null /*lastDisableAppCaller*/,
@@ -1548,10 +1558,7 @@ public final class Settings {
false /*hidden*/,
0 /*distractionFlags*/,
false /*suspended*/,
- null /*suspendingPackage*/,
- null /*dialogInfo*/,
- null /*suspendedAppExtras*/,
- null /*suspendedLauncherExtras*/,
+ null /*suspendParams*/,
false /*instantApp*/,
false /*virtualPreload*/,
null /*lastDisableAppCaller*/,
@@ -1626,12 +1633,12 @@ public final class Settings {
ATTR_DISTRACTION_FLAGS, 0);
final boolean suspended = XmlUtils.readBooleanAttribute(parser, ATTR_SUSPENDED,
false);
- String suspendingPackage = parser.getAttributeValue(null,
+ String oldSuspendingPackage = parser.getAttributeValue(null,
ATTR_SUSPENDING_PACKAGE);
final String dialogMessage = parser.getAttributeValue(null,
ATTR_SUSPEND_DIALOG_MESSAGE);
- if (suspended && suspendingPackage == null) {
- suspendingPackage = PLATFORM_PACKAGE_NAME;
+ if (suspended && oldSuspendingPackage == null) {
+ oldSuspendingPackage = PLATFORM_PACKAGE_NAME;
}
final boolean blockUninstall = XmlUtils.readBooleanAttribute(parser,
@@ -1661,9 +1668,10 @@ public final class Settings {
ArraySet<String> disabledComponents = null;
PersistableBundle suspendedAppExtras = null;
PersistableBundle suspendedLauncherExtras = null;
- SuspendDialogInfo suspendDialogInfo = null;
+ SuspendDialogInfo oldSuspendDialogInfo = null;
int packageDepth = parser.getDepth();
+ ArrayMap<String, PackageUserState.SuspendParams> suspendParamsMap = null;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
|| parser.getDepth() > packageDepth)) {
@@ -1685,26 +1693,48 @@ public final class Settings {
suspendedLauncherExtras = PersistableBundle.restoreFromXml(parser);
break;
case TAG_SUSPENDED_DIALOG_INFO:
- suspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
+ oldSuspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
+ break;
+ case TAG_SUSPEND_PARAMS:
+ final String suspendingPackage = parser.getAttributeValue(null,
+ ATTR_SUSPENDING_PACKAGE);
+ if (suspendingPackage == null) {
+ Slog.wtf(TAG, "No suspendingPackage found inside tag "
+ + TAG_SUSPEND_PARAMS);
+ continue;
+ }
+ if (suspendParamsMap == null) {
+ suspendParamsMap = new ArrayMap<>();
+ }
+ suspendParamsMap.put(suspendingPackage,
+ PackageUserState.SuspendParams.restoreFromXml(parser));
break;
default:
Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag "
+ TAG_PACKAGE);
}
}
- if (suspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
- suspendDialogInfo = new SuspendDialogInfo.Builder()
+ if (oldSuspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
+ oldSuspendDialogInfo = new SuspendDialogInfo.Builder()
.setMessage(dialogMessage)
.build();
}
+ if (suspended && suspendParamsMap == null) {
+ final PackageUserState.SuspendParams suspendParams =
+ PackageUserState.SuspendParams.getInstanceOrNull(
+ oldSuspendDialogInfo,
+ suspendedAppExtras,
+ suspendedLauncherExtras);
+ suspendParamsMap = new ArrayMap<>();
+ suspendParamsMap.put(oldSuspendingPackage, suspendParams);
+ }
if (blockUninstall) {
setBlockUninstallLPw(userId, name, true);
}
ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
- hidden, distractionFlags, suspended, suspendingPackage,
- suspendDialogInfo,
- suspendedAppExtras, suspendedLauncherExtras, instantApp, virtualPreload,
+ hidden, distractionFlags, suspended, suspendParamsMap,
+ instantApp, virtualPreload,
enabledCaller, enabledComponents, disabledComponents, verifState,
linkGeneration, installReason, harmfulAppWarning);
} else if (tagName.equals("preferred-activities")) {
@@ -2004,35 +2034,6 @@ public final class Settings {
}
if (ustate.suspended) {
serializer.attribute(null, ATTR_SUSPENDED, "true");
- if (ustate.suspendingPackage != null) {
- serializer.attribute(null, ATTR_SUSPENDING_PACKAGE,
- ustate.suspendingPackage);
- }
- if (ustate.dialogInfo != null) {
- serializer.startTag(null, TAG_SUSPENDED_DIALOG_INFO);
- ustate.dialogInfo.saveToXml(serializer);
- serializer.endTag(null, TAG_SUSPENDED_DIALOG_INFO);
- }
- if (ustate.suspendedAppExtras != null) {
- serializer.startTag(null, TAG_SUSPENDED_APP_EXTRAS);
- try {
- ustate.suspendedAppExtras.saveToXml(serializer);
- } catch (XmlPullParserException xmle) {
- Slog.wtf(TAG, "Exception while trying to write suspendedAppExtras for "
- + pkg + ". Will be lost on reboot", xmle);
- }
- serializer.endTag(null, TAG_SUSPENDED_APP_EXTRAS);
- }
- if (ustate.suspendedLauncherExtras != null) {
- serializer.startTag(null, TAG_SUSPENDED_LAUNCHER_EXTRAS);
- try {
- ustate.suspendedLauncherExtras.saveToXml(serializer);
- } catch (XmlPullParserException xmle) {
- Slog.wtf(TAG, "Exception while trying to write suspendedLauncherExtras"
- + " for " + pkg + ". Will be lost on reboot", xmle);
- }
- serializer.endTag(null, TAG_SUSPENDED_LAUNCHER_EXTRAS);
- }
}
if (ustate.instantApp) {
serializer.attribute(null, ATTR_INSTANT_APP, "true");
@@ -2065,6 +2066,19 @@ public final class Settings {
serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
ustate.harmfulAppWarning);
}
+ if (ustate.suspended) {
+ for (int i = 0; i < ustate.suspendParams.size(); i++) {
+ final String suspendingPackage = ustate.suspendParams.keyAt(i);
+ serializer.startTag(null, TAG_SUSPEND_PARAMS);
+ serializer.attribute(null, ATTR_SUSPENDING_PACKAGE, suspendingPackage);
+ final PackageUserState.SuspendParams params =
+ ustate.suspendParams.valueAt(i);
+ if (params != null) {
+ params.saveToXml(serializer);
+ }
+ serializer.endTag(null, TAG_SUSPEND_PARAMS);
+ }
+ }
if (!ArrayUtils.isEmpty(ustate.enabledComponents)) {
serializer.startTag(null, TAG_ENABLED_COMPONENTS);
for (final String name : ustate.enabledComponents) {
@@ -4755,13 +4769,6 @@ public final class Settings {
pw.print(ps.getHidden(user.id));
pw.print(" suspended=");
pw.print(ps.getSuspended(user.id));
- if (ps.getSuspended(user.id)) {
- final PackageUserState pus = ps.readUserState(user.id);
- pw.print(" suspendingPackage=");
- pw.print(pus.suspendingPackage);
- pw.print(" dialogInfo=");
- pw.print(pus.dialogInfo);
- }
pw.print(" stopped=");
pw.print(ps.getStopped(user.id));
pw.print(" notLaunched=");
@@ -4773,6 +4780,23 @@ public final class Settings {
pw.print(" virtual=");
pw.println(ps.getVirtulalPreload(user.id));
+ if (ps.getSuspended(user.id)) {
+ pw.print(prefix);
+ pw.println(" Suspend params:");
+ final PackageUserState pus = ps.readUserState(user.id);
+ for (int i = 0; i < pus.suspendParams.size(); i++) {
+ pw.print(prefix);
+ pw.print(" suspendingPackage=");
+ pw.print(pus.suspendParams.keyAt(i));
+ final PackageUserState.SuspendParams params = pus.suspendParams.valueAt(i);
+ if (params != null) {
+ pw.print(" dialogInfo=");
+ pw.print(params.dialogInfo);
+ }
+ pw.println();
+ }
+ }
+
String[] overlayPaths = ps.getOverlayPaths(user.id);
if (overlayPaths != null && overlayPaths.length > 0) {
pw.print(prefix); pw.println(" overlay paths:");
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 9d08e10c6dea..cc69b5a7205f 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -249,7 +249,8 @@ class ActivityStartInterceptor {
if (PLATFORM_PACKAGE_NAME.equals(suspendingPackage)) {
return interceptSuspendedByAdminPackage();
}
- final SuspendDialogInfo dialogInfo = pmi.getSuspendedDialogInfo(suspendedPackage, mUserId);
+ final SuspendDialogInfo dialogInfo = pmi.getSuspendedDialogInfo(suspendedPackage,
+ suspendingPackage, mUserId);
mIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(suspendedPackage,
suspendingPackage, dialogInfo, mUserId);
mCallingPid = mRealCallingPid;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 3fe9b52b8415..15032c5c5cbb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -20,8 +20,8 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.res.Resources.ID_NULL;
-import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
@@ -75,10 +75,11 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PackageManagerSettingsTests {
+ private static final String TAG = "PackageManagerSettingsTests";
+ private static final String PACKAGE_NAME_1 = "com.android.app1";
private static final String PACKAGE_NAME_2 = "com.android.app2";
private static final String PACKAGE_NAME_3 = "com.android.app3";
- private static final String PACKAGE_NAME_1 = "com.android.app1";
- public static final String TAG = "PackageManagerSettingsTests";
+ private static final int TEST_RESOURCE_ID = 2131231283;
@Mock
PermissionSettings mPermissionSettings;
@@ -158,7 +159,7 @@ public class PackageManagerSettingsTests {
assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT));
}
- private PersistableBundle getPersistableBundle(String packageName, long longVal,
+ private static PersistableBundle createPersistableBundle(String packageName, long longVal,
double doubleVal, boolean boolVal, String textVal) {
final PersistableBundle bundle = new PersistableBundle();
bundle.putString(packageName + ".TEXT_VALUE", textVal);
@@ -169,8 +170,8 @@ public class PackageManagerSettingsTests {
}
@Test
- public void testReadPackageRestrictions_oldSuspendInfo() {
- writePackageRestrictions_oldSuspendInfoXml(0);
+ public void testReadPackageRestrictions_noSuspendingPackage() {
+ writePackageRestrictions_noSuspendingPackageXml(0);
final Object lock = new Object();
final Context context = InstrumentationRegistry.getTargetContext();
final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, lock);
@@ -181,26 +182,61 @@ public class PackageManagerSettingsTests {
final PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
final PackageUserState packageUserState1 = ps1.readUserState(0);
assertThat(packageUserState1.suspended, is(true));
- assertThat("android".equals(packageUserState1.suspendingPackage), is(true));
+ assertThat(packageUserState1.suspendParams.size(), is(1));
+ assertThat(packageUserState1.suspendParams.keyAt(0), is("android"));
+ assertThat(packageUserState1.suspendParams.valueAt(0), is(nullValue()));
final PackageSetting ps2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2);
final PackageUserState packageUserState2 = ps2.readUserState(0);
assertThat(packageUserState2.suspended, is(false));
- assertThat(packageUserState2.suspendingPackage, is(nullValue()));
+ assertThat(packageUserState2.suspendParams, is(nullValue()));
}
@Test
- public void testReadWritePackageRestrictions_newSuspendInfo() {
+ public void testReadPackageRestrictions_noSuspendParamsMap() {
+ writePackageRestrictions_noSuspendParamsMapXml(0);
+ final Object lock = new Object();
+ final Context context = InstrumentationRegistry.getTargetContext();
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, lock);
+ settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
+ settingsUnderTest.readPackageRestrictionsLPr(0);
+
+ final PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
+ final PackageUserState packageUserState1 = ps1.readUserState(0);
+ assertThat(packageUserState1.suspended, is(true));
+ assertThat(packageUserState1.suspendParams.size(), is(1));
+ assertThat(packageUserState1.suspendParams.keyAt(0), is(PACKAGE_NAME_3));
+ final PackageUserState.SuspendParams params = packageUserState1.suspendParams.valueAt(0);
+ assertThat(params, is(notNullValue()));
+ assertThat(params.appExtras.size(), is(1));
+ assertThat(params.appExtras.getString("app_extra_string"), is("value"));
+ assertThat(params.launcherExtras.size(), is(1));
+ assertThat(params.launcherExtras.getLong("launcher_extra_long"), is(4L));
+ assertThat(params.dialogInfo, is(notNullValue()));
+ assertThat(params.dialogInfo.getDialogMessage(), is("Dialog Message"));
+ assertThat(params.dialogInfo.getTitleResId(), is(ID_NULL));
+ assertThat(params.dialogInfo.getIconResId(), is(TEST_RESOURCE_ID));
+ assertThat(params.dialogInfo.getNeutralButtonTextResId(), is(ID_NULL));
+ assertThat(params.dialogInfo.getDialogMessageResId(), is(ID_NULL));
+ }
+
+ @Test
+ public void testReadWritePackageRestrictions_suspendInfo() {
final Context context = InstrumentationRegistry.getTargetContext();
final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, new Object());
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
- final PersistableBundle appExtras1 = getPersistableBundle(
+ final PersistableBundle appExtras1 = createPersistableBundle(
PACKAGE_NAME_1, 1L, 0.01, true, "appString1");
- final PersistableBundle launcherExtras1 = getPersistableBundle(
+ final PersistableBundle appExtras2 = createPersistableBundle(
+ PACKAGE_NAME_2, 2L, 0.02, true, "appString2");
+
+ final PersistableBundle launcherExtras1 = createPersistableBundle(
PACKAGE_NAME_1, 10L, 0.1, false, "launcherString1");
+ final PersistableBundle launcherExtras2 = createPersistableBundle(
+ PACKAGE_NAME_2, 20L, 0.2, false, "launcherString2");
final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder()
.setIcon(0x11220001)
@@ -208,14 +244,23 @@ public class PackageManagerSettingsTests {
.setMessage("1st message")
.setNeutralButtonText(0x11220003)
.build();
+ final SuspendDialogInfo dialogInfo2 = new SuspendDialogInfo.Builder()
+ .setIcon(0x22220001)
+ .setTitle(0x22220002)
+ .setMessage("2nd message")
+ .setNeutralButtonText(0x22220003)
+ .build();
- ps1.setSuspended(true, "suspendingPackage1", dialogInfo1, appExtras1, launcherExtras1, 0);
+ ps1.addOrUpdateSuspension("suspendingPackage1", dialogInfo1, appExtras1, launcherExtras1,
+ 0);
+ ps1.addOrUpdateSuspension("suspendingPackage2", dialogInfo2, appExtras2, launcherExtras2,
+ 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
- ps2.setSuspended(true, "suspendingPackage2", null, null, null, 0);
+ ps2.addOrUpdateSuspension("suspendingPackage3", null, appExtras1, null, 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
- ps3.setSuspended(false, "irrelevant", dialogInfo1, null, null, 0);
+ ps3.removeSuspension("irrelevant", 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
settingsUnderTest.writePackageRestrictionsLPr(0);
@@ -229,27 +274,39 @@ public class PackageManagerSettingsTests {
final PackageUserState readPus1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1)
.readUserState(0);
assertThat(readPus1.suspended, is(true));
- assertThat(readPus1.suspendingPackage, equalTo("suspendingPackage1"));
- assertThat(readPus1.dialogInfo, equalTo(dialogInfo1));
- assertThat(BaseBundle.kindofEquals(readPus1.suspendedAppExtras, appExtras1), is(true));
- assertThat(BaseBundle.kindofEquals(readPus1.suspendedLauncherExtras, launcherExtras1),
+ assertThat(readPus1.suspendParams.size(), is(2));
+
+ assertThat(readPus1.suspendParams.keyAt(0), is("suspendingPackage1"));
+ final PackageUserState.SuspendParams params11 = readPus1.suspendParams.valueAt(0);
+ assertThat(params11, is(notNullValue()));
+ assertThat(params11.dialogInfo, is(dialogInfo1));
+ assertThat(BaseBundle.kindofEquals(params11.appExtras, appExtras1), is(true));
+ assertThat(BaseBundle.kindofEquals(params11.launcherExtras, launcherExtras1),
+ is(true));
+
+ assertThat(readPus1.suspendParams.keyAt(1), is("suspendingPackage2"));
+ final PackageUserState.SuspendParams params12 = readPus1.suspendParams.valueAt(1);
+ assertThat(params12, is(notNullValue()));
+ assertThat(params12.dialogInfo, is(dialogInfo2));
+ assertThat(BaseBundle.kindofEquals(params12.appExtras, appExtras2), is(true));
+ assertThat(BaseBundle.kindofEquals(params12.launcherExtras, launcherExtras2),
is(true));
final PackageUserState readPus2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2)
.readUserState(0);
assertThat(readPus2.suspended, is(true));
- assertThat(readPus2.suspendingPackage, equalTo("suspendingPackage2"));
- assertThat(readPus2.dialogInfo, is(nullValue()));
- assertThat(readPus2.suspendedAppExtras, is(nullValue()));
- assertThat(readPus2.suspendedLauncherExtras, is(nullValue()));
+ assertThat(readPus2.suspendParams.size(), is(1));
+ assertThat(readPus2.suspendParams.keyAt(0), is("suspendingPackage3"));
+ final PackageUserState.SuspendParams params21 = readPus2.suspendParams.valueAt(0);
+ assertThat(params21, is(notNullValue()));
+ assertThat(params21.dialogInfo, is(nullValue()));
+ assertThat(BaseBundle.kindofEquals(params21.appExtras, appExtras1), is(true));
+ assertThat(params21.launcherExtras, is(nullValue()));
final PackageUserState readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3)
.readUserState(0);
assertThat(readPus3.suspended, is(false));
- assertThat(readPus3.suspendingPackage, is(nullValue()));
- assertThat(readPus3.dialogInfo, is(nullValue()));
- assertThat(readPus3.suspendedAppExtras, is(nullValue()));
- assertThat(readPus3.suspendedLauncherExtras, is(nullValue()));
+ assertThat(readPus3.suspendParams, is(nullValue()));
}
@Test
@@ -940,10 +997,10 @@ public class PackageManagerSettingsTests {
+ "</packages>").getBytes());
}
- private void writePackageRestrictions_oldSuspendInfoXml(final int userId) {
+ private void writePackageRestrictions_noSuspendingPackageXml(final int userId) {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/users/"
+ userId + "/package-restrictions.xml"),
- ( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<package-restrictions>\n"
+ " <pkg name=\"" + PACKAGE_NAME_1 + "\" suspended=\"true\" />"
+ " <pkg name=\"" + PACKAGE_NAME_2 + "\" suspended=\"false\" />"
@@ -955,6 +1012,30 @@ public class PackageManagerSettingsTests {
.getBytes());
}
+ private void writePackageRestrictions_noSuspendParamsMapXml(final int userId) {
+ writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/users/"
+ + userId + "/package-restrictions.xml"),
+ ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<package-restrictions>\n"
+ + " <pkg name=\"" + PACKAGE_NAME_1 + "\" "
+ + " suspended=\"true\" suspending-package=\"" + PACKAGE_NAME_3 + "\">\n"
+ + " <suspended-dialog-info dialogMessage=\"Dialog Message\""
+ + " iconResId=\"" + TEST_RESOURCE_ID + "\"/>\n"
+ + " <suspended-app-extras>\n"
+ + " <string name=\"app_extra_string\">value</string>\n"
+ + " </suspended-app-extras>\n"
+ + " <suspended-launcher-extras>\n"
+ + " <long name=\"launcher_extra_long\" value=\"4\" />\n"
+ + " </suspended-launcher-extras>\n"
+ + " </pkg>\n"
+ + " <preferred-activities />\n"
+ + " <persistent-preferred-activities />\n"
+ + " <crossProfile-intent-filters />\n"
+ + " <default-apps />\n"
+ + "</package-restrictions>\n")
+ .getBytes());
+ }
+
private void writeStoppedPackagesXml() {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages-stopped.xml"),
( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index 8eaf35f6432f..fc5a0ba1af7b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -26,6 +26,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageUserState;
import android.content.pm.SuspendDialogInfo;
import android.os.PersistableBundle;
+import android.util.ArrayMap;
import android.util.ArraySet;
import androidx.test.filters.SmallTest;
@@ -175,18 +176,43 @@ public class PackageUserStateTest {
assertThat(testUserState03.equals(oldUserState), is(false));
}
+ private static PackageUserState.SuspendParams createSuspendParams(SuspendDialogInfo dialogInfo,
+ PersistableBundle appExtras, PersistableBundle launcherExtras) {
+ PackageUserState.SuspendParams obj = PackageUserState.SuspendParams.getInstanceOrNull(
+ dialogInfo, appExtras, launcherExtras);
+ return obj;
+ }
+
+ private static PersistableBundle createPersistableBundle(String lKey, long lValue, String sKey,
+ String sValue, String dKey, double dValue) {
+ final PersistableBundle result = new PersistableBundle(3);
+ if (lKey != null) {
+ result.putLong("com.unit_test." + lKey, lValue);
+ }
+ if (sKey != null) {
+ result.putString("com.unit_test." + sKey, sValue);
+ }
+ if (dKey != null) {
+ result.putDouble("com.unit_test." + dKey, dValue);
+ }
+ return result;
+ }
+
@Test
public void testPackageUserState05() {
- PersistableBundle appExtras1 = new PersistableBundle();
- PersistableBundle appExtras2 = new PersistableBundle();
- appExtras1.putInt("appExtraId", 1);
- appExtras2.putInt("appExtraId", 2);
- PersistableBundle launcherExtras1 = new PersistableBundle();
- PersistableBundle launcherExtras2 = new PersistableBundle();
- launcherExtras1.putString("name", "launcherExtras1");
- launcherExtras2.putString("name", "launcherExtras2");
+ final PersistableBundle appExtras1 = createPersistableBundle("appExtraId", 1, null, null,
+ null, 0);
+ final PersistableBundle appExtras2 = createPersistableBundle("appExtraId", 2, null, null,
+ null, 0);
+
+ final PersistableBundle launcherExtras1 = createPersistableBundle(null, 0, "name",
+ "launcherExtras1", null, 0);
+ final PersistableBundle launcherExtras2 = createPersistableBundle(null, 0, "name",
+ "launcherExtras2", null, 0);
+
final String suspendingPackage1 = "package1";
final String suspendingPackage2 = "package2";
+
final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder()
.setMessage("dialogMessage1")
.build();
@@ -194,38 +220,23 @@ public class PackageUserStateTest {
.setMessage("dialogMessage2")
.build();
+ final ArrayMap<String, PackageUserState.SuspendParams> paramsMap1 = new ArrayMap<>();
+ paramsMap1.put(suspendingPackage1, createSuspendParams(dialogInfo1, appExtras1,
+ launcherExtras1));
+ final ArrayMap<String, PackageUserState.SuspendParams> paramsMap2 = new ArrayMap<>();
+ paramsMap2.put(suspendingPackage2, createSuspendParams(dialogInfo2,
+ appExtras2, launcherExtras2));
+
+
final PackageUserState testUserState1 = new PackageUserState();
testUserState1.suspended = true;
- testUserState1.suspendedAppExtras = appExtras1;
- testUserState1.suspendedLauncherExtras = launcherExtras1;
- testUserState1.suspendingPackage = suspendingPackage1;
- testUserState1.dialogInfo = dialogInfo1;
+ testUserState1.suspendParams = paramsMap1;
PackageUserState testUserState2 = new PackageUserState(testUserState1);
assertThat(testUserState1.equals(testUserState2), is(true));
- testUserState2.suspendingPackage = suspendingPackage2;
- assertThat(testUserState1.equals(testUserState2), is(false));
-
- testUserState2 = new PackageUserState(testUserState1);
- testUserState2.suspendedAppExtras = appExtras2;
- assertThat(testUserState1.equals(testUserState2), is(false));
-
- testUserState2 = new PackageUserState(testUserState1);
- testUserState2.suspendedLauncherExtras = launcherExtras2;
- assertThat(testUserState1.equals(testUserState2), is(false));
-
- testUserState2 = new PackageUserState(testUserState1);
- testUserState2.dialogInfo = dialogInfo2;
+ testUserState2.suspendParams = paramsMap2;
+ // Should not be equal since suspendParams maps are different
assertThat(testUserState1.equals(testUserState2), is(false));
-
- testUserState2 = new PackageUserState(testUserState1);
- testUserState2.suspended = testUserState1.suspended = false;
- // Everything is different but irrelevant if suspended is false
- testUserState2.suspendingPackage = suspendingPackage2;
- testUserState2.dialogInfo = dialogInfo2;
- testUserState2.suspendedAppExtras = appExtras2;
- testUserState2.suspendedLauncherExtras = launcherExtras2;
- assertThat(testUserState1.equals(testUserState2), is(true));
}
@Test
@@ -243,4 +254,46 @@ public class PackageUserStateTest {
assertThat(userState1.equals(userState2), is(false));
}
+ @Test
+ public void testPackageUserState07() {
+ final PersistableBundle appExtras1 = createPersistableBundle("appExtraId", 1, null, null,
+ null, 0);
+ final PersistableBundle appExtras2 = createPersistableBundle("appExtraId", 2, null, null,
+ null, 0);
+
+ final PersistableBundle launcherExtras1 = createPersistableBundle(null, 0, "name",
+ "launcherExtras1", null, 0);
+ final PersistableBundle launcherExtras2 = createPersistableBundle(null, 0, "name",
+ "launcherExtras2", null, 0);
+
+ final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder()
+ .setMessage("dialogMessage1")
+ .build();
+ final SuspendDialogInfo dialogInfo2 = new SuspendDialogInfo.Builder()
+ .setMessage("dialogMessage2")
+ .build();
+
+ final PackageUserState.SuspendParams params1;
+ PackageUserState.SuspendParams params2;
+ params1 = createSuspendParams(dialogInfo1, appExtras1, launcherExtras1);
+ params2 = createSuspendParams(dialogInfo1, appExtras1, launcherExtras1);
+ // Everything is same
+ assertThat(params1.equals(params2), is(true));
+
+ params2 = createSuspendParams(dialogInfo2, appExtras1, launcherExtras1);
+ // DialogInfo is different
+ assertThat(params1.equals(params2), is(false));
+
+ params2 = createSuspendParams(dialogInfo1, appExtras2, launcherExtras1);
+ // app extras are different
+ assertThat(params1.equals(params2), is(false));
+
+ params2 = createSuspendParams(dialogInfo1, appExtras1, launcherExtras2);
+ // Launcher extras are different
+ assertThat(params1.equals(params2), is(false));
+
+ params2 = createSuspendParams(dialogInfo2, appExtras2, launcherExtras2);
+ // Everything is different
+ assertThat(params1.equals(params2), is(false));
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 350114c792bf..4165052fa675 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -175,8 +175,8 @@ public class ActivityStartInterceptorTest {
.build();
when(mPackageManagerInternal.getSuspendingPackage(TEST_PACKAGE_NAME, TEST_USER_ID))
.thenReturn(suspendingPackage);
- when(mPackageManagerInternal.getSuspendedDialogInfo(TEST_PACKAGE_NAME, TEST_USER_ID))
- .thenReturn(dialogInfo);
+ when(mPackageManagerInternal.getSuspendedDialogInfo(TEST_PACKAGE_NAME, suspendingPackage,
+ TEST_USER_ID)).thenReturn(dialogInfo);
// THEN calling intercept returns true
assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));