summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2021-12-31 04:02:34 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-12-31 04:02:34 +0000
commit0edef3c3f3bda6cfea089ecc90a0ca79ee325c45 (patch)
treec4a2227d338e9ceed7304411538dbb11a8a91285
parentdaa7fb226d00750cae36a6453100c8276054430c (diff)
parentc82b3c669ed29718b8e7f74c7a9b5883a0d70b14 (diff)
Merge "Introduce package state mutation APIs"
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java82
-rw-r--r--services/core/java/com/android/server/pm/DeletePackageHelper.java1
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java346
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java30
-rw-r--r--services/core/java/com/android/server/pm/SettingBase.java6
-rw-r--r--services/core/java/com/android/server/pm/Settings.java614
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageStateInternal.java4
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java42
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java1
-rw-r--r--services/core/java/com/android/server/pm/pkg/SuspendParams.java30
-rw-r--r--services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java333
-rw-r--r--services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java41
-rw-r--r--services/core/java/com/android/server/pm/pkg/mutate/PackageUserStateWrite.java63
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java42
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java4
15 files changed, 1185 insertions, 454 deletions
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 6fe2806e8139..9b2948f42ed8 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -50,6 +50,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.AndroidPackageApi;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.mutate.PackageStateMutator;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -885,17 +886,6 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
public abstract boolean userNeedsBadging(int userId);
/**
- * Perform the given action for each package.
- * Note that packages lock will be held while performing the actions.
- *
- * If the caller does not need all packages, prefer the potentially non-locking
- * {@link #withPackageSettingsSnapshot(Consumer)}.
- *
- * @param actionLocked action to be performed
- */
- public abstract void forEachPackage(Consumer<AndroidPackage> actionLocked);
-
- /**
* Perform the given action for each {@link PackageSetting}.
* Note that packages lock will be held while performing the actions.
*
@@ -918,12 +908,24 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
public abstract void forEachPackageState(boolean locked, Consumer<PackageStateInternal> action);
/**
+ * {@link #forEachPackageState(boolean, Consumer)} but filtered to only states with packages
+ * on device where {@link PackageStateInternal#getPkg()} is not null.
+ */
+ public abstract void forEachPackage(Consumer<AndroidPackage> action);
+
+ /**
* Perform the given action for each installed package for a user.
* Note that packages lock will be held while performing the actions.
*/
public abstract void forEachInstalledPackage(
@NonNull Consumer<AndroidPackage> actionLocked, @UserIdInt int userId);
+ /**
+ * Perform the given action for each installed package for a user.
+ */
+ public abstract void forEachInstalledPackage(boolean locked,
+ @NonNull Consumer<AndroidPackage> action, @UserIdInt int userId);
+
/** Returns the list of enabled components */
public abstract ArraySet<String> getEnabledComponents(String packageName, int userId);
@@ -1265,4 +1267,62 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
*/
public abstract void reconcileAppsData(int userId, @StorageManager.StorageFlags int flags,
boolean migrateAppsData);
+
+ /**
+ * Initiates a package state mutation request, returning the current state as known by
+ * PackageManager. This allows the later commit request to compare the initial values and
+ * determine if any state was changed or any packages were updated since the whole request
+ * was initiated.
+ *
+ * As a concrete example, consider the following steps:
+ * <ol>
+ * <li>Read a package state without taking a lock</li>
+ * <li>Check some values in that state, determine that a mutation needs to occur</li>
+ * <li>Call to commit the change with the new value, takes lock</li>
+ * </ol>
+ *
+ * Between steps 1 and 3, because the lock was not taken for the entire flow, it's possible
+ * a package state was changed by another consumer or a package was updated/installed.
+ *
+ * If anything has changed,
+ * {@link #commitPackageStateMutation(PackageStateMutator.InitialState, Consumer)} will return
+ * a {@link PackageStateMutator.Result} indicating so. If the caller has not indicated it can
+ * ignore changes, it can opt to re-run the commit logic from the top with a true write lock
+ * around all of its read-logic-commit loop.
+ *
+ * Note that if the caller does not care about potential race conditions or package/state
+ * changes between steps 1 and 3, it can simply opt to not call this method and pass in null
+ * for the initial state. This is useful to avoid long running data structure locks when the
+ * caller is changing a value as part of a one-off request. Perhaps from an app side API which
+ * mutates only a single package, where it doesn't care what the state of that package is or
+ * any other packages on the devices.
+ *
+ * Important to note is that if no locking is enforced, callers themselves will not be
+ * synchronized with themselves. The caller may be relying on the PackageManager lock to
+ * enforce ordering within their own code path, and that has to be adjusted if migrated off
+ * the lock.
+ */
+ @NonNull
+ public abstract PackageStateMutator.InitialState recordInitialState();
+
+ /**
+ * Some questions to ask when designing a mutation:
+ * <ol>
+ * <li>What external system state is required and is it synchronized properly?</li>
+ * <li>Are there any package/state changes that could happen to the target (or another)
+ * package that could result in the commit being invalid?</li>
+ * <li>Is the caller synchronized with itself and can handle multiple mutations being
+ * requested from different threads?</li>
+ * <li>What should be done in case of a conflict and the commit can't be finished?</li>
+ * </ol>
+ *
+ * @param state See {@link #recordInitialState()}. If null, no result is returned.
+ * @param consumer Lean wrapper around just the logic that changes state values
+ * @return result if anything changed since initial state, or null if nothing changed and
+ * commit was successful
+ */
+ @Nullable
+ public abstract PackageStateMutator.Result commitPackageStateMutation(
+ @Nullable PackageStateMutator.InitialState state,
+ @NonNull Consumer<PackageStateMutator> consumer);
}
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index e84d990b5d21..c26f3b3b2cf2 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -547,7 +547,6 @@ final class DeletePackageHelper {
true /*notLaunched*/,
false /*hidden*/,
0 /*distractionFlags*/,
- false /*suspended*/,
null /*suspendParams*/,
false /*instantApp*/,
false /*virtualPreload*/,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b2cd642a8fc7..248944e476ad 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -239,6 +239,9 @@ import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.SuspendParams;
+import com.android.server.pm.pkg.mutate.PackageStateMutator;
+import com.android.server.pm.pkg.mutate.PackageStateWrite;
+import com.android.server.pm.pkg.mutate.PackageUserStateWrite;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.DomainVerificationService;
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy;
@@ -594,6 +597,16 @@ public class PackageManagerService extends IPackageManager.Stub
// the suffix "Locked". Some methods may use the legacy suffix "LP"
final PackageManagerTracedLock mLock;
+ // Lock alias for doing package state mutation
+ private final PackageManagerTracedLock mPackageStateWriteLock;
+
+ // Lock alias to track syncing a consistent Computer
+ private final PackageManagerTracedLock mLiveComputerSyncLock;
+
+ private final PackageStateMutator mPackageStateMutator = new PackageStateMutator(
+ this::getPackageSettingForMutation,
+ this::getDisabledPackageSettingForMutation);
+
// Keys are String (package name), values are Package.
@Watched
@GuardedBy("mLock")
@@ -1608,6 +1621,8 @@ public class PackageManagerService extends IPackageManager.Stub
mInstaller = injector.getInstaller();
mInstallLock = injector.getInstallLock();
mLock = injector.getLock();
+ mPackageStateWriteLock = mLock;
+ mLiveComputerSyncLock = mLock;
mPermissionManager = injector.getPermissionManagerServiceInternal();
mSettings = injector.getSettings();
mUserManager = injector.getUserManagerService();
@@ -1713,6 +1728,8 @@ public class PackageManagerService extends IPackageManager.Stub
mInjector.bootstrap(this);
mLock = injector.getLock();
+ mPackageStateWriteLock = mLock;
+ mLiveComputerSyncLock = mLock;
mInstallLock = injector.getInstallLock();
LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
@@ -4553,8 +4570,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (pus.isSuspended()) {
for (int i = 0; i < pus.getSuspendParams().size(); i++) {
final SuspendParams params = pus.getSuspendParams().valueAt(i);
- if (params != null && params.appExtras != null) {
- allExtras.putAll(params.appExtras);
+ if (params != null && params.getAppExtras() != null) {
+ allExtras.putAll(params.getAppExtras());
}
}
}
@@ -4627,9 +4644,9 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mLock) {
for (String packageName : packagesToChange) {
final PackageSetting ps = mSettings.getPackageLPr(packageName);
- if (ps != null && ps.getSuspended(userId)) {
+ if (ps != null && ps.getUserStateOrDefault(userId).isSuspended()) {
ps.removeSuspension(suspendingPackagePredicate, userId);
- if (!ps.getSuspended(userId)) {
+ if (!ps.getUserStateOrDefault(userId).isSuspended()) {
unsuspendedPackages.add(ps.getPackageName());
unsuspendedUids.add(UserHandle.getUid(userId, ps.getAppId()));
}
@@ -7413,8 +7430,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (userState.isSuspended()) {
for (int i = 0; i < userState.getSuspendParams().size(); i++) {
final SuspendParams params = userState.getSuspendParams().valueAt(i);
- if (params != null && params.launcherExtras != null) {
- allExtras.putAll(params.launcherExtras);
+ if (params != null && params.getLauncherExtras() != null) {
+ allExtras.putAll(params.getLauncherExtras());
}
}
}
@@ -7503,7 +7520,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
final SuspendParams suspendParams = suspendParamsMap.get(suspendingPackage);
- return (suspendParams != null) ? suspendParams.dialogInfo : null;
+ return (suspendParams != null) ? suspendParams.getDialogInfo() : null;
}
@Override
@@ -7949,7 +7966,13 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> actionLocked,
@UserIdInt int userId) {
- PackageManagerService.this.forEachInstalledPackage(actionLocked, userId);
+ forEachInstalledPackage(true, actionLocked, userId);
+ }
+
+ @Override
+ public void forEachInstalledPackage(boolean locked,
+ @NonNull Consumer<AndroidPackage> action, int userId) {
+ PackageManagerService.this.forEachInstalledPackage(locked, action, userId);
}
@Override
@@ -8222,51 +8245,24 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void withPackageSettingsSnapshot(
@NonNull Consumer<Function<String, PackageStateInternal>> block) {
- final Computer snapshot = snapshotComputer();
-
- // This method needs to either lock or not lock consistently throughout the method,
- // so if the live computer is returned, force a wrapping sync block.
- if (snapshot == mLiveComputer) {
- synchronized (mLock) {
- block.accept(snapshot::getPackageStateInternal);
- }
- } else {
- block.accept(snapshot::getPackageStateInternal);
- }
+ executeWithConsistentComputer(computer ->
+ block.accept(computer::getPackageStateInternal));
}
@Override
public <Output> Output withPackageSettingsSnapshotReturning(
@NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageStateInternal>,
Output> block) {
- final Computer snapshot = snapshotComputer();
-
- // This method needs to either lock or not lock consistently throughout the method,
- // so if the live computer is returned, force a wrapping sync block.
- if (snapshot == mLiveComputer) {
- synchronized (mLock) {
- return block.apply(snapshot::getPackageStateInternal);
- }
- } else {
- return block.apply(snapshot::getPackageStateInternal);
- }
+ return executeWithConsistentComputerReturning(computer ->
+ block.apply(computer::getPackageStateInternal));
}
@Override
public <ExceptionType extends Exception> void withPackageSettingsSnapshotThrowing(
@NonNull FunctionalUtils.ThrowingCheckedConsumer<Function<String,
PackageStateInternal>, ExceptionType> block) throws ExceptionType {
- final Computer snapshot = snapshotComputer();
-
- // This method needs to either lock or not lock consistently throughout the method,
- // so if the live computer is returned, force a wrapping sync block.
- if (snapshot == mLiveComputer) {
- synchronized (mLock) {
- block.accept(snapshot::getPackageStateInternal);
- }
- } else {
- block.accept(snapshot::getPackageStateInternal);
- }
+ executeWithConsistentComputerThrowing(computer ->
+ block.accept(computer::getPackageStateInternal));
}
@Override
@@ -8276,17 +8272,9 @@ public class PackageManagerService extends IPackageManager.Stub
Function<String, PackageStateInternal>, ExceptionOne,
ExceptionTwo> block)
throws ExceptionOne, ExceptionTwo {
- final Computer snapshot = snapshotComputer();
-
- // This method needs to either lock or not lock consistently throughout the method,
- // so if the live computer is returned, force a wrapping sync block.
- if (snapshot == mLiveComputer) {
- synchronized (mLock) {
- block.accept(snapshot::getPackageStateInternal);
- }
- } else {
- block.accept(snapshot::getPackageStateInternal);
- }
+ executeWithConsistentComputerThrowing2(
+ (FunctionalUtils.ThrowingChecked2Consumer<Computer, ExceptionOne,
+ ExceptionTwo>) computer -> block.accept(computer::getPackageStateInternal));
}
@Override
@@ -8296,17 +8284,8 @@ public class PackageManagerService extends IPackageManager.Stub
Function<String, PackageStateInternal>, Output,
ExceptionType> block)
throws ExceptionType {
- final Computer snapshot = snapshotComputer();
-
- // This method needs to either lock or not lock consistently throughout the method,
- // so if the live computer is returned, force a wrapping sync block.
- if (snapshot == mLiveComputer) {
- synchronized (mLock) {
- return block.apply(snapshot::getPackageStateInternal);
- }
- } else {
- return block.apply(snapshot::getPackageStateInternal);
- }
+ return executeWithConsistentComputerReturningThrowing(computer ->
+ block.apply(computer::getPackageStateInternal));
}
@Override
@@ -8315,6 +8294,20 @@ public class PackageManagerService extends IPackageManager.Stub
PackageManagerService.this.mAppDataHelper.reconcileAppsData(userId, flags,
migrateAppsData);
}
+
+ @NonNull
+ @Override
+ public PackageStateMutator.InitialState recordInitialState() {
+ return PackageManagerService.this.recordInitialState();
+ }
+
+ @Nullable
+ @Override
+ public PackageStateMutator.Result commitPackageStateMutation(
+ @Nullable PackageStateMutator.InitialState state,
+ @NonNull Consumer<PackageStateMutator> consumer) {
+ return PackageManagerService.this.commitPackageStateMutation(state, consumer);
+ }
}
@Override
@@ -8357,7 +8350,15 @@ public class PackageManagerService extends IPackageManager.Stub
@Nullable
@GuardedBy("mLock")
PackageSetting getPackageSettingForMutation(String packageName) {
- return (PackageSetting) mComputer.getPackageStateInternal(packageName);
+ return mSettings.getPackageLPr(packageName);
+ }
+
+ // TODO: Remove
+ @Deprecated
+ @Nullable
+ @GuardedBy("mLock")
+ PackageSetting getDisabledPackageSettingForMutation(String packageName) {
+ return mSettings.getDisabledSystemPkgLPr(packageName);
}
@VisibleForTesting(visibility = Visibility.PRIVATE)
@@ -8365,7 +8366,7 @@ public class PackageManagerService extends IPackageManager.Stub
PackageStateInternal getPackageStateInternal(String packageName) {
Computer computer = snapshotComputer();
if (computer == mLiveComputer) {
- synchronized (mLock) {
+ synchronized (mLiveComputerSyncLock) {
PackageSetting pkgSetting =
(PackageSetting) computer.getPackageStateInternal(packageName);
if (pkgSetting == null) {
@@ -8374,15 +8375,16 @@ public class PackageManagerService extends IPackageManager.Stub
return new PackageSetting(pkgSetting);
}
+ } else {
+ return computer.getPackageStateInternal(packageName);
}
- return computer.getPackageStateInternal(packageName);
}
@Nullable
PackageStateInternal getPackageStateInternal(String packageName, int callingUid) {
Computer computer = snapshotComputer();
if (computer == mLiveComputer) {
- synchronized (mLock) {
+ synchronized (mLiveComputerSyncLock) {
PackageSetting pkgSetting =
(PackageSetting) computer.getPackageStateInternal(packageName, callingUid);
if (pkgSetting == null) {
@@ -8391,8 +8393,9 @@ public class PackageManagerService extends IPackageManager.Stub
return new PackageSetting(pkgSetting);
}
+ } else {
+ return computer.getPackageStateInternal(packageName, callingUid);
}
- return computer.getPackageStateInternal(packageName, callingUid);
}
@Nullable
@@ -8400,7 +8403,7 @@ public class PackageManagerService extends IPackageManager.Stub
int callingUid, @UserIdInt int userId) {
Computer computer = snapshotComputer();
if (computer == mLiveComputer) {
- synchronized (mLock) {
+ synchronized (mLiveComputerSyncLock) {
PackageSetting pkgSetting =
(PackageSetting) filterPackageStateForInstalledAndFiltered(computer,
packageName, callingUid, userId);
@@ -8409,9 +8412,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
return new PackageSetting(pkgSetting);
}
+ } else {
+ return filterPackageStateForInstalledAndFiltered(computer, packageName, callingUid,
+ userId);
}
-
- return filterPackageStateForInstalledAndFiltered(computer, packageName, callingUid, userId);
}
@Nullable
@@ -8439,16 +8443,8 @@ public class PackageManagerService extends IPackageManager.Stub
Computer computer = snapshotComputer();
if (computer == mLiveComputer) {
return new ArrayMap<>(computer.getPackageStates());
- }
- return computer.getPackageStates();
- }
-
- void forEachPackage(Consumer<AndroidPackage> actionLocked) {
- synchronized (mLock) {
- int numPackages = mPackages.size();
- for (int i = 0; i < numPackages; i++) {
- actionLocked.accept(mPackages.valueAt(i));
- }
+ } else {
+ return computer.getPackageStates();
}
}
@@ -8461,17 +8457,31 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- private void forEachPackageState(boolean locked, Consumer<PackageStateInternal> action) {
+ void forEachPackageState(boolean locked, Consumer<PackageStateInternal> action) {
if (locked) {
- forEachPackageSetting(action::accept);
+ synchronized (mLiveComputerSyncLock) {
+ forEachPackageState(mComputer.getPackageStates(), action);
+ }
} else {
Computer computer = snapshotComputer();
if (computer == mLiveComputer) {
- synchronized (mLock) {
+ synchronized (mLiveComputerSyncLock) {
forEachPackageState(computer.getPackageStates(), action);
- };
+ }
+ } else {
+ forEachPackageState(computer.getPackageStates(), action);
+ }
+ }
+ }
+
+ void forEachPackage(Consumer<AndroidPackage> action) {
+ Computer computer = snapshotComputer();
+ if (computer == mLiveComputer) {
+ synchronized (mLiveComputerSyncLock) {
+ forEachPackage(computer.getPackageStates(), action);
}
- forEachPackageState(computer.getPackageStates(), action);
+ } else {
+ forEachPackage(computer.getPackageStates(), action);
}
}
@@ -8485,18 +8495,103 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> actionLocked,
+ private void forEachPackage(
+ @NonNull ArrayMap<String, ? extends PackageStateInternal> packageStates,
+ @NonNull Consumer<AndroidPackage> consumer) {
+ int size = packageStates.size();
+ for (int index = 0; index < size; index++) {
+ PackageStateInternal packageState = packageStates.valueAt(index);
+ if (packageState.getPkg() != null) {
+ consumer.accept(packageState.getPkg());
+ }
+ }
+ }
+
+ void forEachInstalledPackage(boolean locked, @NonNull Consumer<AndroidPackage> action,
@UserIdInt int userId) {
- synchronized (mLock) {
- int numPackages = mPackages.size();
- for (int i = 0; i < numPackages; i++) {
- AndroidPackage pkg = mPackages.valueAt(i);
- PackageSetting setting = mSettings.getPackageLPr(pkg.getPackageName());
- if (setting == null || !setting.getInstalled(userId)) {
- continue;
+ Consumer<PackageStateInternal> actionWrapped = packageState -> {
+ if (packageState.getPkg() != null
+ && packageState.getUserStateOrDefault(userId).isInstalled()) {
+ action.accept(packageState.getPkg());
+ }
+ };
+ if (locked) {
+ synchronized (mLiveComputerSyncLock) {
+ forEachPackageState(mComputer.getPackageStates(), actionWrapped);
+ }
+ } else {
+ Computer computer = snapshotComputer();
+ if (computer == mLiveComputer) {
+ synchronized (mLiveComputerSyncLock) {
+ forEachPackageState(computer.getPackageStates(), actionWrapped);
}
- actionLocked.accept(pkg);
+ } else {
+ forEachPackageState(computer.getPackageStates(), actionWrapped);
+ }
+ }
+ }
+
+ private void executeWithConsistentComputer(
+ @NonNull FunctionalUtils.ThrowingConsumer<Computer> consumer) {
+ Computer computer = snapshotComputer();
+ if (computer == mLiveComputer) {
+ synchronized (mLiveComputerSyncLock) {
+ consumer.accept(computer);
+ }
+ } else {
+ consumer.accept(computer);
+ }
+ }
+
+ private <T> T executeWithConsistentComputerReturning(
+ @NonNull FunctionalUtils.ThrowingFunction<Computer, T> function) {
+ Computer computer = snapshotComputer();
+ if (computer == mLiveComputer) {
+ synchronized (mLiveComputerSyncLock) {
+ return function.apply(computer);
+ }
+ } else {
+ return function.apply(computer);
+ }
+ }
+
+ private <ExceptionType extends Exception> void executeWithConsistentComputerThrowing(
+ @NonNull FunctionalUtils.ThrowingCheckedConsumer<Computer, ExceptionType> consumer)
+ throws ExceptionType {
+ Computer computer = snapshotComputer();
+ if (computer == mLiveComputer) {
+ synchronized (mLiveComputerSyncLock) {
+ consumer.accept(computer);
+ }
+ } else {
+ consumer.accept(computer);
+ }
+ }
+
+ private <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
+ executeWithConsistentComputerThrowing2(
+ @NonNull FunctionalUtils.ThrowingChecked2Consumer<Computer, ExceptionOne,
+ ExceptionTwo> consumer) throws ExceptionOne, ExceptionTwo {
+ Computer computer = snapshotComputer();
+ if (computer == mLiveComputer) {
+ synchronized (mLiveComputerSyncLock) {
+ consumer.accept(computer);
}
+ } else {
+ consumer.accept(computer);
+ }
+ }
+
+ private <T, ExceptionType extends Exception> T executeWithConsistentComputerReturningThrowing(
+ @NonNull FunctionalUtils.ThrowingCheckedFunction<Computer, T, ExceptionType> function)
+ throws ExceptionType {
+ Computer computer = snapshotComputer();
+ if (computer == mLiveComputer) {
+ synchronized (mLiveComputerSyncLock) {
+ return function.apply(computer);
+ }
+ } else {
+ return function.apply(computer);
}
}
@@ -8695,7 +8790,8 @@ public class PackageManagerService extends IPackageManager.Stub
enforceOwnerRights(packageName, Binder.getCallingUid());
final boolean changed;
synchronized (mLock) {
- changed = mSettings.getPackageLPr(packageName).setMimeGroup(mimeGroup, mimeTypes);
+ changed = mSettings.getPackageLPr(packageName).setMimeGroup(mimeGroup,
+ new ArraySet<>(mimeTypes));
}
if (changed) {
applyMimeGroupChanges(packageName, mimeGroup);
@@ -9198,4 +9294,62 @@ public class PackageManagerService extends IPackageManager.Stub
return new Pair<>(rescanFlags, reparseFlags);
}
+
+ /**
+ * @see PackageManagerInternal#recordInitialState()
+ */
+ @NonNull
+ public PackageStateMutator.InitialState recordInitialState() {
+ return mPackageStateMutator.initialState(mChangedPackagesSequenceNumber);
+ }
+
+ /**
+ * @see PackageManagerInternal#commitPackageStateMutation(PackageStateMutator.InitialState,
+ * Consumer)
+ */
+ @NonNull
+ public PackageStateMutator.Result commitPackageStateMutation(
+ @Nullable PackageStateMutator.InitialState initialState,
+ @NonNull Consumer<PackageStateMutator> consumer) {
+ synchronized (mPackageStateWriteLock) {
+ final PackageStateMutator.Result result = mPackageStateMutator.generateResult(
+ initialState, mChangedPackagesSequenceNumber);
+ if (result != PackageStateMutator.Result.SUCCESS) {
+ return result;
+ }
+
+ consumer.accept(mPackageStateMutator);
+ onChanged();
+ }
+
+ return PackageStateMutator.Result.SUCCESS;
+ }
+
+ /**
+ * @see PackageManagerInternal#commitPackageStateMutation(PackageStateMutator.InitialState,
+ * Consumer)
+ */
+ @NonNull
+ public PackageStateMutator.Result commitPackageStateMutation(
+ @Nullable PackageStateMutator.InitialState initialState, @NonNull String packageName,
+ @NonNull Consumer<PackageStateWrite> consumer) {
+ synchronized (mPackageStateWriteLock) {
+ final PackageStateMutator.Result result = mPackageStateMutator.generateResult(
+ initialState, mChangedPackagesSequenceNumber);
+ if (result != PackageStateMutator.Result.SUCCESS) {
+ return result;
+ }
+
+ PackageStateWrite state = mPackageStateMutator.forPackage(packageName);
+ if (state == null) {
+ return PackageStateMutator.Result.SPECIFIC_PACKAGE_NULL;
+ } else {
+ consumer.accept(state);
+ }
+
+ onChanged();
+ }
+
+ return PackageStateMutator.Result.SUCCESS;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 923a133338ab..0da57bcf9c0a 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -395,14 +395,13 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
return this;
}
- public boolean setMimeGroup(String mimeGroup, List<String> mimeTypes) {
+ public boolean setMimeGroup(String mimeGroup, ArraySet<String> newMimeTypes) {
Set<String> oldMimeTypes = mimeGroups == null ? null : mimeGroups.get(mimeGroup);
if (oldMimeTypes == null) {
throw new IllegalArgumentException("Unknown MIME group " + mimeGroup
+ " for package " + mName);
}
- ArraySet<String> newMimeTypes = new ArraySet<>(mimeTypes);
boolean hasChanges = !newMimeTypes.equals(oldMimeTypes);
mimeGroups.put(mimeGroup, newMimeTypes);
if (hasChanges) {
@@ -670,6 +669,15 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
return state;
}
+ public PackageUserStateImpl getOrCreateUserState(@UserIdInt int userId) {
+ PackageUserStateImpl state = mUserStates.get(userId);
+ if (state == null) {
+ state = new PackageUserStateImpl();
+ mUserStates.put(userId, state);
+ }
+ return state;
+ }
+
@NonNull
public PackageUserStateInternal readUserState(int userId) {
PackageUserStateInternal state = mUserStates.get(userId);
@@ -832,7 +840,6 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
}
final SuspendParams oldSuspendParams =
existingUserState.getSuspendParams().put(suspendingPackage, newSuspendParams);
- existingUserState.setSuspended(true);
onChanged();
return !Objects.equals(oldSuspendParams, newSuspendParams);
}
@@ -848,7 +855,6 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
existingUserState.setSuspendParams(null);
}
}
- existingUserState.setSuspended((existingUserState.getSuspendParams() != null));
onChanged();
return wasModified;
}
@@ -866,7 +872,6 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
existingUserState.setSuspendParams(null);
}
}
- existingUserState.setSuspended((existingUserState.getSuspendParams() != null));
onChanged();
}
@@ -889,7 +894,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
}
void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
- boolean notLaunched, boolean hidden, int distractionFlags, boolean suspended,
+ boolean notLaunched, boolean hidden, int distractionFlags,
ArrayMap<String, SuspendParams> suspendParams, boolean instantApp,
boolean virtualPreload, String lastDisableAppCaller,
ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
@@ -904,7 +909,6 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
.setNotLaunched(notLaunched)
.setHidden(hidden)
.setDistractionFlags(distractionFlags)
- .setSuspended(suspended)
.setLastDisableAppCaller(lastDisableAppCaller)
.setEnabledComponents(enabledComponents)
.setDisabledComponents(disabledComponents)
@@ -919,11 +923,9 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
void setUserState(int userId, PackageUserStateInternal otherState) {
setUserState(userId, otherState.getCeDataInode(), otherState.getEnabledState(),
- otherState.isInstalled(),
- otherState.isStopped(), otherState.isNotLaunched(), otherState.isHidden(),
- otherState.getDistractionFlags(), otherState.isSuspended(),
- otherState.getSuspendParams(),
- otherState.isInstantApp(),
+ otherState.isInstalled(), otherState.isStopped(), otherState.isNotLaunched(),
+ otherState.isHidden(), otherState.getDistractionFlags(),
+ otherState.getSuspendParams(), otherState.isInstantApp(),
otherState.isVirtualPreload(), otherState.getLastDisableAppCaller(),
new ArraySet<>(otherState.getEnabledComponentsNoCopy()),
new ArraySet<>(otherState.getDisabledComponentsNoCopy()),
@@ -1553,10 +1555,10 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
}
@DataClass.Generated(
- time = 1635870549646L,
+ time = 1636145878985L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/PackageSetting.java",
- inputSignatures = "private int sharedUserId\nprivate @android.annotation.Nullable java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mimeGroups\nprivate @java.lang.Deprecated @android.annotation.Nullable java.util.Set<java.lang.String> mOldCodePaths\nprivate @android.annotation.Nullable java.lang.String[] usesStaticLibraries\nprivate @android.annotation.Nullable long[] usesStaticLibrariesVersions\nprivate @android.annotation.Nullable @java.lang.Deprecated java.lang.String legacyNativeLibraryPath\nprivate @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.Nullable java.lang.String mRealName\nprivate int mAppId\nprivate @android.annotation.Nullable com.android.server.pm.parsing.pkg.AndroidPackage pkg\nprivate @android.annotation.Nullable com.android.server.pm.SharedUserSetting sharedUser\nprivate @android.annotation.NonNull java.io.File mPath\nprivate @android.annotation.NonNull java.lang.String mPathString\nprivate float mLoadingProgress\nprivate @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate long mLastModifiedTime\nprivate long firstInstallTime\nprivate long lastUpdateTime\nprivate long versionCode\nprivate @android.annotation.NonNull com.android.server.pm.PackageSignatures signatures\nprivate boolean installPermissionsFixed\nprivate @android.annotation.NonNull com.android.server.pm.PackageKeySetData keySetData\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserStateImpl> mUserStates\nprivate @android.annotation.NonNull com.android.server.pm.InstallSource installSource\nprivate @android.annotation.Nullable java.lang.String volumeUuid\nprivate int categoryOverride\nprivate boolean updateAvailable\nprivate boolean forceQueryableOverride\nprivate @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized pkgState\nprivate @android.annotation.NonNull java.util.UUID mDomainSetId\nprivate final @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> mSnapshot\nprivate com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> makeCache()\npublic com.android.server.pm.PackageSetting snapshot()\npublic void dumpDebug(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\npublic java.util.List<java.lang.String> getMimeGroup(java.lang.String)\nprivate java.util.Set<java.lang.String> getMimeGroupInternal(java.lang.String)\npublic boolean isSharedUser()\npublic com.android.server.pm.PackageSetting setAppId(int)\npublic com.android.server.pm.PackageSetting setCpuAbiOverride(java.lang.String)\npublic com.android.server.pm.PackageSetting setFirstInstallTime(long)\npublic com.android.server.pm.PackageSetting setForceQueryableOverride(boolean)\npublic com.android.server.pm.PackageSetting setInstallerPackageName(java.lang.String)\npublic com.android.server.pm.PackageSetting setInstallSource(com.android.server.pm.InstallSource)\n com.android.server.pm.PackageSetting removeInstallerPackage(java.lang.String)\npublic com.android.server.pm.PackageSetting setIsOrphaned(boolean)\npublic com.android.server.pm.PackageSetting setKeySetData(com.android.server.pm.PackageKeySetData)\npublic com.android.server.pm.PackageSetting setLastModifiedTime(long)\npublic com.android.server.pm.PackageSetting setLastUpdateTime(long)\npublic com.android.server.pm.PackageSetting setLongVersionCode(long)\npublic boolean setMimeGroup(java.lang.String,java.util.List<java.lang.String>)\npublic com.android.server.pm.PackageSetting setPkg(com.android.server.pm.parsing.pkg.AndroidPackage)\npublic com.android.server.pm.PackageSetting setPrimaryCpuAbi(java.lang.String)\npublic com.android.server.pm.PackageSetting setSecondaryCpuAbi(java.lang.String)\npublic com.android.server.pm.PackageSetting setSignatures(com.android.server.pm.PackageSignatures)\npublic com.android.server.pm.PackageSetting setVolumeUuid(java.lang.String)\npublic @java.lang.Override boolean isExternalStorage()\npublic com.android.server.pm.PackageSetting setUpdateAvailable(boolean)\npublic int getSharedUserIdInt()\npublic @java.lang.Override java.lang.String toString()\nprotected void copyMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic void updateFrom(com.android.server.pm.PackageSetting)\n com.android.server.pm.PackageSetting updateMimeGroups(java.util.Set<java.lang.String>)\npublic @java.lang.Deprecated @java.lang.Override com.android.server.pm.permission.LegacyPermissionState getLegacyPermissionState()\npublic com.android.server.pm.PackageSetting setInstallPermissionsFixed(boolean)\npublic boolean isPrivileged()\npublic boolean isOem()\npublic boolean isVendor()\npublic boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic boolean isSystemExt()\npublic boolean isOdm()\npublic boolean isSystem()\npublic android.content.pm.SigningDetails getSigningDetails()\npublic com.android.server.pm.PackageSetting setSigningDetails(android.content.pm.SigningDetails)\npublic void copyPackageSetting(com.android.server.pm.PackageSetting)\n @com.android.internal.annotations.VisibleForTesting com.android.server.pm.pkg.PackageUserStateImpl modifyUserState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateInternal readUserState(int)\n void setEnabled(int,int,java.lang.String)\n int getEnabled(int)\n java.lang.String getLastDisabledAppCaller(int)\n void setInstalled(boolean,int)\n boolean getInstalled(int)\n int getInstallReason(int)\n void setInstallReason(int,int)\n int getUninstallReason(int)\n void setUninstallReason(int,int)\n boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths,int)\n @android.annotation.NonNull android.content.pm.overlay.OverlayPaths getOverlayPaths(int)\n boolean setOverlayPathsForLibrary(java.lang.String,android.content.pm.overlay.OverlayPaths,int)\n @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> getOverlayPathsForLibrary(int)\n boolean isAnyInstalled(int[])\n int[] queryInstalledUsers(int[],boolean)\n long getCeDataInode(int)\n void setCeDataInode(long,int)\n boolean getStopped(int)\n void setStopped(boolean,int)\n boolean getNotLaunched(int)\n void setNotLaunched(boolean,int)\n boolean getHidden(int)\n void setHidden(boolean,int)\n int getDistractionFlags(int)\n void setDistractionFlags(int,int)\n boolean getSuspended(int)\n boolean addOrUpdateSuspension(java.lang.String,android.content.pm.SuspendDialogInfo,android.os.PersistableBundle,android.os.PersistableBundle,int)\n boolean removeSuspension(java.lang.String,int)\n void removeSuspension(java.util.function.Predicate<java.lang.String>,int)\npublic boolean getInstantApp(int)\n void setInstantApp(boolean,int)\n boolean getVirtualPreload(int)\n void setVirtualPreload(boolean,int)\n void setUserState(int,long,int,boolean,boolean,boolean,boolean,int,boolean,android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams>,boolean,boolean,java.lang.String,android.util.ArraySet<java.lang.String>,android.util.ArraySet<java.lang.String>,int,int,java.lang.String,java.lang.String)\n void setUserState(int,com.android.server.pm.pkg.PackageUserStateInternal)\n android.util.ArraySet<java.lang.String> getEnabledComponents(int)\n android.util.ArraySet<java.lang.String> getDisabledComponents(int)\n void setEnabledComponents(android.util.ArraySet<java.lang.String>,int)\n void setDisabledComponents(android.util.ArraySet<java.lang.String>,int)\n void setEnabledComponentsCopy(android.util.ArraySet<java.lang.String>,int)\n void setDisabledComponentsCopy(android.util.ArraySet<java.lang.String>,int)\n com.android.server.pm.pkg.PackageUserStateImpl modifyUserStateComponents(int,boolean,boolean)\n void addDisabledComponent(java.lang.String,int)\n void addEnabledComponent(java.lang.String,int)\n boolean enableComponentLPw(java.lang.String,int)\n boolean disableComponentLPw(java.lang.String,int)\n boolean restoreComponentLPw(java.lang.String,int)\n int getCurrentEnabledStateLPr(java.lang.String,int)\n void removeUser(int)\npublic int[] getNotInstalledUserIds()\n void writePackageUserPermissionsProto(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\nprotected void writeUsersInfoToProto(android.util.proto.ProtoOutputStream,long)\n void setHarmfulAppWarning(int,java.lang.String)\n java.lang.String getHarmfulAppWarning(int)\n com.android.server.pm.PackageSetting setPath(java.io.File)\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideNonLocalizedLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer,int)\npublic void resetOverrideComponentLabelIcon(int)\npublic void setSplashScreenTheme(int,java.lang.String)\npublic @android.annotation.Nullable java.lang.String getSplashScreenTheme(int)\npublic boolean isLoading()\npublic com.android.server.pm.PackageSetting setLoadingProgress(float)\npublic @android.annotation.NonNull @java.lang.Override long getVersionCode()\npublic @android.annotation.Nullable @java.lang.Override java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getMimeGroups()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String getPackageName()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.pm.pkg.AndroidPackageApi getAndroidPackage()\npublic @android.annotation.Nullable @java.lang.Override java.lang.Integer getSharedUserId()\npublic @android.annotation.NonNull android.content.pm.SigningInfo getSigningInfo()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesStaticLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesStaticLibrariesVersions()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<android.content.pm.SharedLibraryInfo> getUsesLibraryInfos()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<java.lang.String> getUsesLibraryFiles()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @android.annotation.NonNull @java.lang.Override long[] getLastPackageUsageTime()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic com.android.server.pm.PackageSetting setDomainSetId(java.util.UUID)\npublic com.android.server.pm.PackageSetting setSharedUser(com.android.server.pm.SharedUserSetting)\npublic com.android.server.pm.PackageSetting setCategoryOverride(int)\npublic com.android.server.pm.PackageSetting setLegacyNativeLibraryPath(java.lang.String)\npublic com.android.server.pm.PackageSetting setMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic com.android.server.pm.PackageSetting setOldCodePaths(java.util.Set<java.lang.String>)\npublic com.android.server.pm.PackageSetting setUsesStaticLibraries(java.lang.String[])\npublic com.android.server.pm.PackageSetting setUsesStaticLibrariesVersions(long[])\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageStateUnserialized getTransientState()\npublic @android.annotation.NonNull android.util.SparseArray<? extends PackageUserStateInternal> getUserStates()\nclass PackageSetting extends com.android.server.pm.SettingBase implements [com.android.server.pm.pkg.PackageStateInternal]\n@com.android.internal.util.DataClass(genGetters=true, genConstructor=false, genSetters=false, genBuilder=false)")
+ inputSignatures = "private int sharedUserId\nprivate @android.annotation.Nullable java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mimeGroups\nprivate @java.lang.Deprecated @android.annotation.Nullable java.util.Set<java.lang.String> mOldCodePaths\nprivate @android.annotation.Nullable java.lang.String[] usesStaticLibraries\nprivate @android.annotation.Nullable long[] usesStaticLibrariesVersions\nprivate @android.annotation.Nullable @java.lang.Deprecated java.lang.String legacyNativeLibraryPath\nprivate @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.Nullable java.lang.String mRealName\nprivate int mAppId\nprivate @android.annotation.Nullable com.android.server.pm.parsing.pkg.AndroidPackage pkg\nprivate @android.annotation.Nullable com.android.server.pm.SharedUserSetting sharedUser\nprivate @android.annotation.NonNull java.io.File mPath\nprivate @android.annotation.NonNull java.lang.String mPathString\nprivate float mLoadingProgress\nprivate @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate long mLastModifiedTime\nprivate long firstInstallTime\nprivate long lastUpdateTime\nprivate long versionCode\nprivate @android.annotation.NonNull com.android.server.pm.PackageSignatures signatures\nprivate boolean installPermissionsFixed\nprivate @android.annotation.NonNull com.android.server.pm.PackageKeySetData keySetData\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserStateImpl> mUserStates\nprivate @android.annotation.NonNull com.android.server.pm.InstallSource installSource\nprivate @android.annotation.Nullable java.lang.String volumeUuid\nprivate int categoryOverride\nprivate boolean updateAvailable\nprivate boolean forceQueryableOverride\nprivate @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized pkgState\nprivate @android.annotation.NonNull java.util.UUID mDomainSetId\nprivate final @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> mSnapshot\nprivate com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> makeCache()\npublic com.android.server.pm.PackageSetting snapshot()\npublic void dumpDebug(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\npublic boolean isSharedUser()\npublic com.android.server.pm.PackageSetting setAppId(int)\npublic com.android.server.pm.PackageSetting setCpuAbiOverride(java.lang.String)\npublic com.android.server.pm.PackageSetting setFirstInstallTime(long)\npublic com.android.server.pm.PackageSetting setForceQueryableOverride(boolean)\npublic com.android.server.pm.PackageSetting setInstallerPackageName(java.lang.String)\npublic com.android.server.pm.PackageSetting setInstallSource(com.android.server.pm.InstallSource)\n com.android.server.pm.PackageSetting removeInstallerPackage(java.lang.String)\npublic com.android.server.pm.PackageSetting setIsOrphaned(boolean)\npublic com.android.server.pm.PackageSetting setKeySetData(com.android.server.pm.PackageKeySetData)\npublic com.android.server.pm.PackageSetting setLastModifiedTime(long)\npublic com.android.server.pm.PackageSetting setLastUpdateTime(long)\npublic com.android.server.pm.PackageSetting setLongVersionCode(long)\npublic boolean setMimeGroup(java.lang.String,java.util.List<java.lang.String>)\npublic com.android.server.pm.PackageSetting setPkg(com.android.server.pm.parsing.pkg.AndroidPackage)\npublic com.android.server.pm.PackageSetting setPrimaryCpuAbi(java.lang.String)\npublic com.android.server.pm.PackageSetting setSecondaryCpuAbi(java.lang.String)\npublic com.android.server.pm.PackageSetting setSignatures(com.android.server.pm.PackageSignatures)\npublic com.android.server.pm.PackageSetting setVolumeUuid(java.lang.String)\npublic @java.lang.Override boolean isExternalStorage()\npublic com.android.server.pm.PackageSetting setUpdateAvailable(boolean)\npublic int getSharedUserIdInt()\npublic @java.lang.Override java.lang.String toString()\nprotected void copyMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic void updateFrom(com.android.server.pm.PackageSetting)\n com.android.server.pm.PackageSetting updateMimeGroups(java.util.Set<java.lang.String>)\npublic @java.lang.Deprecated @java.lang.Override com.android.server.pm.permission.LegacyPermissionState getLegacyPermissionState()\npublic com.android.server.pm.PackageSetting setInstallPermissionsFixed(boolean)\npublic boolean isPrivileged()\npublic boolean isOem()\npublic boolean isVendor()\npublic boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic boolean isSystemExt()\npublic boolean isOdm()\npublic boolean isSystem()\npublic android.content.pm.SigningDetails getSigningDetails()\npublic com.android.server.pm.PackageSetting setSigningDetails(android.content.pm.SigningDetails)\npublic void copyPackageSetting(com.android.server.pm.PackageSetting)\n @com.android.internal.annotations.VisibleForTesting com.android.server.pm.pkg.PackageUserStateImpl modifyUserState(int)\npublic com.android.server.pm.pkg.PackageUserStateImpl getOrCreateUserState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateInternal readUserState(int)\n void setEnabled(int,int,java.lang.String)\n int getEnabled(int)\n java.lang.String getLastDisabledAppCaller(int)\n void setInstalled(boolean,int)\n boolean getInstalled(int)\n int getInstallReason(int)\n void setInstallReason(int,int)\n int getUninstallReason(int)\n void setUninstallReason(int,int)\n boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths,int)\n @android.annotation.NonNull android.content.pm.overlay.OverlayPaths getOverlayPaths(int)\n boolean setOverlayPathsForLibrary(java.lang.String,android.content.pm.overlay.OverlayPaths,int)\n @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> getOverlayPathsForLibrary(int)\n boolean isAnyInstalled(int[])\n int[] queryInstalledUsers(int[],boolean)\n long getCeDataInode(int)\n void setCeDataInode(long,int)\n boolean getStopped(int)\n void setStopped(boolean,int)\n boolean getNotLaunched(int)\n void setNotLaunched(boolean,int)\n boolean getHidden(int)\n void setHidden(boolean,int)\n int getDistractionFlags(int)\n void setDistractionFlags(int,int)\npublic boolean getInstantApp(int)\n void setInstantApp(boolean,int)\n boolean getVirtualPreload(int)\n void setVirtualPreload(boolean,int)\n void setUserState(int,long,int,boolean,boolean,boolean,boolean,int,android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams>,boolean,boolean,java.lang.String,android.util.ArraySet<java.lang.String>,android.util.ArraySet<java.lang.String>,int,int,java.lang.String,java.lang.String)\n void setUserState(int,com.android.server.pm.pkg.PackageUserStateInternal)\n android.util.ArraySet<java.lang.String> getEnabledComponents(int)\n android.util.ArraySet<java.lang.String> getDisabledComponents(int)\n void setEnabledComponents(android.util.ArraySet<java.lang.String>,int)\n void setDisabledComponents(android.util.ArraySet<java.lang.String>,int)\n void setEnabledComponentsCopy(android.util.ArraySet<java.lang.String>,int)\n void setDisabledComponentsCopy(android.util.ArraySet<java.lang.String>,int)\n com.android.server.pm.pkg.PackageUserStateImpl modifyUserStateComponents(int,boolean,boolean)\n void addDisabledComponent(java.lang.String,int)\n void addEnabledComponent(java.lang.String,int)\n boolean enableComponentLPw(java.lang.String,int)\n boolean disableComponentLPw(java.lang.String,int)\n boolean restoreComponentLPw(java.lang.String,int)\n int getCurrentEnabledStateLPr(java.lang.String,int)\n void removeUser(int)\npublic int[] getNotInstalledUserIds()\n void writePackageUserPermissionsProto(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\nprotected void writeUsersInfoToProto(android.util.proto.ProtoOutputStream,long)\n void setHarmfulAppWarning(int,java.lang.String)\n java.lang.String getHarmfulAppWarning(int)\n com.android.server.pm.PackageSetting setPath(java.io.File)\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideNonLocalizedLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer,int)\npublic void resetOverrideComponentLabelIcon(int)\npublic void setSplashScreenTheme(int,java.lang.String)\npublic @android.annotation.Nullable java.lang.String getSplashScreenTheme(int)\npublic boolean isLoading()\npublic com.android.server.pm.PackageSetting setLoadingProgress(float)\npublic @android.annotation.NonNull @java.lang.Override long getVersionCode()\npublic @android.annotation.Nullable @java.lang.Override java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getMimeGroups()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String getPackageName()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.pm.pkg.AndroidPackageApi getAndroidPackage()\npublic @android.annotation.Nullable @java.lang.Override java.lang.Integer getSharedUserId()\npublic @android.annotation.NonNull android.content.pm.SigningInfo getSigningInfo()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesStaticLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesStaticLibrariesVersions()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<android.content.pm.SharedLibraryInfo> getUsesLibraryInfos()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<java.lang.String> getUsesLibraryFiles()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @android.annotation.NonNull @java.lang.Override long[] getLastPackageUsageTime()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic com.android.server.pm.PackageSetting setDomainSetId(java.util.UUID)\npublic com.android.server.pm.PackageSetting setSharedUser(com.android.server.pm.SharedUserSetting)\npublic com.android.server.pm.PackageSetting setCategoryOverride(int)\npublic com.android.server.pm.PackageSetting setLegacyNativeLibraryPath(java.lang.String)\npublic com.android.server.pm.PackageSetting setMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic com.android.server.pm.PackageSetting setOldCodePaths(java.util.Set<java.lang.String>)\npublic com.android.server.pm.PackageSetting setUsesStaticLibraries(java.lang.String[])\npublic com.android.server.pm.PackageSetting setUsesStaticLibrariesVersions(long[])\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageStateUnserialized getTransientState()\npublic @android.annotation.NonNull android.util.SparseArray<? extends PackageUserStateInternal> getUserStates()\nclass PackageSetting extends com.android.server.pm.SettingBase implements [com.android.server.pm.pkg.PackageStateInternal]\n@com.android.internal.util.DataClass(genGetters=true, genConstructor=false, genSetters=false, genBuilder=false)")
@Deprecated
private void __metadata() {}
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index ed85ff9fa291..4345d5136fb9 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -22,6 +22,7 @@ import android.content.pm.ApplicationInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.permission.LegacyPermissionState;
+import com.android.server.pm.pkg.mutate.PackageStateMutator;
import com.android.server.utils.Snappable;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableImpl;
@@ -88,6 +89,7 @@ public abstract class SettingBase implements Watchable, Snappable {
* Notify listeners that this object has changed.
*/
protected void onChanged() {
+ PackageStateMutator.onPackageStateChanged();
dispatchChange(this);
}
@@ -122,7 +124,7 @@ public abstract class SettingBase implements Watchable, Snappable {
return mLegacyPermissionsState;
}
- SettingBase setFlags(int pkgFlags) {
+ public SettingBase setFlags(int pkgFlags) {
this.mPkgFlags = pkgFlags
& (ApplicationInfo.FLAG_SYSTEM
| ApplicationInfo.FLAG_EXTERNAL_STORAGE
@@ -131,7 +133,7 @@ public abstract class SettingBase implements Watchable, Snappable {
return this;
}
- SettingBase setPrivateFlags(int pkgPrivateFlags) {
+ public SettingBase setPrivateFlags(int pkgPrivateFlags) {
this.mPkgPrivateFlags = pkgPrivateFlags
& (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
| ApplicationInfo.PRIVATE_FLAG_OEM
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index b1ce6a2a5366..6c47eb09cf07 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -114,6 +114,7 @@ import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.LegacyPermissionSettings;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.permission.LegacyPermissionState.PermissionState;
+import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.SuspendParams;
@@ -162,6 +163,7 @@ import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
+import java.util.function.Consumer;
/**
* Holds information about dynamic settings.
@@ -257,7 +259,7 @@ public final class Settings implements Watchable, Snappable {
public static final int SIGNATURE_MALFORMED_RECOVER = 3;
}
- private static final boolean DEBUG_STOPPED = false;
+ static final boolean DEBUG_STOPPED = false;
private static final boolean DEBUG_MU = false;
private static final boolean DEBUG_KERNEL = false;
private static final boolean DEBUG_PARSER = false;
@@ -625,7 +627,15 @@ public final class Settings implements Watchable, Snappable {
mOtherAppIds = new WatchedSparseArray<>();
mPermissions = new LegacyPermissionSettings(lock);
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
- runtimePermissionsPersistence);
+ runtimePermissionsPersistence, new Consumer<Integer>() {
+ @Override
+ public void accept(Integer userId) {
+ synchronized (mLock) {
+ mRuntimePermissionsPersistence.writeStateForUserSync(userId,
+ mPermissionDataProvider, mPackages, mSharedUsers);
+ }
+ }
+ });
mPermissionDataProvider = permissionDataProvider;
mSystemDir = new File(dataDir, "system");
@@ -989,7 +999,6 @@ public final class Settings implements Watchable, Snappable {
true /*notLaunched*/,
false /*hidden*/,
0 /*distractionFlags*/,
- false /*suspended*/,
null /*suspendParams*/,
instantApp,
virtualPreload,
@@ -1423,7 +1432,7 @@ public final class Settings implements Watchable, Snappable {
void writeAllRuntimePermissionsLPr() {
for (int userId : UserManagerService.getInstance().getUserIds()) {
- mRuntimePermissionsPersistence.writeStateForUserAsyncLPr(userId);
+ mRuntimePermissionsPersistence.writeStateForUserAsync(userId);
}
}
@@ -1432,15 +1441,15 @@ public final class Settings implements Watchable, Snappable {
}
void updateRuntimePermissionsFingerprintLPr(@UserIdInt int userId) {
- mRuntimePermissionsPersistence.updateRuntimePermissionsFingerprintLPr(userId);
+ mRuntimePermissionsPersistence.updateRuntimePermissionsFingerprint(userId);
}
int getDefaultRuntimePermissionsVersionLPr(int userId) {
- return mRuntimePermissionsPersistence.getVersionLPr(userId);
+ return mRuntimePermissionsPersistence.getVersion(userId);
}
void setDefaultRuntimePermissionsVersionLPr(int version, int userId) {
- mRuntimePermissionsPersistence.setVersionLPr(version, userId);
+ mRuntimePermissionsPersistence.setVersion(version, userId);
}
void setPermissionControllerVersion(long version) {
@@ -1646,7 +1655,6 @@ public final class Settings implements Watchable, Snappable {
false /*notLaunched*/,
false /*hidden*/,
0 /*distractionFlags*/,
- false /*suspended*/,
null /*suspendParams*/,
false /*instantApp*/,
false /*virtualPreload*/,
@@ -1816,10 +1824,9 @@ public final class Settings implements Watchable, Snappable {
setBlockUninstallLPw(userId, name, true);
}
ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
- hidden, distractionFlags, suspended, suspendParamsMap,
- instantApp, virtualPreload, enabledCaller, enabledComponents,
- disabledComponents, installReason, uninstallReason, harmfulAppWarning,
- splashScreenTheme);
+ hidden, distractionFlags, suspendParamsMap, instantApp, virtualPreload,
+ enabledCaller, enabledComponents, disabledComponents, installReason,
+ uninstallReason, harmfulAppWarning, splashScreenTheme);
mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
} else if (tagName.equals("preferred-activities")) {
@@ -3100,7 +3107,8 @@ public final class Settings implements Watchable, Snappable {
}
for (UserInfo user : users) {
- mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id);
+ mRuntimePermissionsPersistence.readStateForUserSync(user.id, getInternalVersion(),
+ mPackages, mSharedUsers, getUserRuntimePermissionsFile(user.id));
}
/*
@@ -3124,7 +3132,8 @@ public final class Settings implements Watchable, Snappable {
}
void readPermissionStateForUserSyncLPr(@UserIdInt int userId) {
- mRuntimePermissionsPersistence.readStateForUserSyncLPr(userId);
+ mRuntimePermissionsPersistence.readStateForUserSync(userId, getInternalVersion(),
+ mPackages, mSharedUsers, getUserRuntimePermissionsFile(userId));
}
void applyDefaultPreferredAppsLPw(int userId) {
@@ -4120,7 +4129,7 @@ public final class Settings implements Watchable, Snappable {
file.delete();
removeCrossProfileIntentFiltersLPw(userId);
- mRuntimePermissionsPersistence.onUserRemovedLPw(userId);
+ mRuntimePermissionsPersistence.onUserRemoved(userId);
mDomainVerificationManager.clearUser(userId);
writePackageListLPr();
@@ -4485,24 +4494,25 @@ public final class Settings implements Watchable, Snappable {
}
}
for (UserInfo user : users) {
+ final PackageUserStateInternal userState = ps.getUserStateOrDefault(user.id);
pw.print(checkinTag);
pw.print("-");
pw.print("usr");
pw.print(",");
pw.print(user.id);
pw.print(",");
- pw.print(ps.getInstalled(user.id) ? "I" : "i");
- pw.print(ps.getHidden(user.id) ? "B" : "b");
- pw.print(ps.getSuspended(user.id) ? "SU" : "su");
- pw.print(ps.getStopped(user.id) ? "S" : "s");
- pw.print(ps.getNotLaunched(user.id) ? "l" : "L");
- pw.print(ps.getInstantApp(user.id) ? "IA" : "ia");
- pw.print(ps.getVirtualPreload(user.id) ? "VPI" : "vpi");
- String harmfulAppWarning = ps.getHarmfulAppWarning(user.id);
+ pw.print(userState.isInstalled() ? "I" : "i");
+ pw.print(userState.isHidden() ? "B" : "b");
+ pw.print(userState.isSuspended() ? "SU" : "su");
+ pw.print(userState.isStopped() ? "S" : "s");
+ pw.print(userState.isNotLaunched() ? "l" : "L");
+ pw.print(userState.isInstantApp() ? "IA" : "ia");
+ pw.print(userState.isVirtualPreload() ? "VPI" : "vpi");
+ String harmfulAppWarning = userState.getHarmfulAppWarning();
pw.print(harmfulAppWarning != null ? "HA" : "ha");
pw.print(",");
- pw.print(ps.getEnabled(user.id));
- String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
+ pw.print(userState.getEnabledState());
+ String lastDisabledAppCaller = userState.getLastDisableAppCaller();
pw.print(",");
pw.print(lastDisabledAppCaller != null ? lastDisabledAppCaller : "?");
pw.print(",");
@@ -4819,48 +4829,48 @@ public final class Settings implements Watchable, Snappable {
}
for (UserInfo user : users) {
+ final PackageUserStateInternal userState = ps.getUserStateOrDefault(user.id);
pw.print(prefix); pw.print(" User "); pw.print(user.id); pw.print(": ");
pw.print("ceDataInode=");
- pw.print(ps.getCeDataInode(user.id));
+ pw.print(userState.getCeDataInode());
pw.print(" installed=");
- pw.print(ps.getInstalled(user.id));
+ pw.print(userState.isInstalled());
pw.print(" hidden=");
- pw.print(ps.getHidden(user.id));
+ pw.print(userState.isHidden());
pw.print(" suspended=");
- pw.print(ps.getSuspended(user.id));
+ pw.print(userState.isSuspended());
pw.print(" distractionFlags=");
- pw.print(ps.getDistractionFlags(user.id));
+ pw.print(userState.getDistractionFlags());
pw.print(" stopped=");
- pw.print(ps.getStopped(user.id));
+ pw.print(userState.isStopped());
pw.print(" notLaunched=");
- pw.print(ps.getNotLaunched(user.id));
+ pw.print(userState.isNotLaunched());
pw.print(" enabled=");
- pw.print(ps.getEnabled(user.id));
+ pw.print(userState.getEnabledState());
pw.print(" instant=");
- pw.print(ps.getInstantApp(user.id));
+ pw.print(userState.isInstantApp());
pw.print(" virtual=");
- pw.print(ps.getVirtualPreload(user.id));
+ pw.println(userState.isVirtualPreload());
pw.print(" installReason=");
- pw.println(ps.getInstallReason(user.id));
+ pw.println(userState.getInstallReason());
- if (ps.getSuspended(user.id)) {
+ if (userState.isSuspended()) {
pw.print(prefix);
pw.println(" Suspend params:");
- final PackageUserStateInternal pus = ps.readUserState(user.id);
- for (int i = 0; i < pus.getSuspendParams().size(); i++) {
+ for (int i = 0; i < userState.getSuspendParams().size(); i++) {
pw.print(prefix);
pw.print(" suspendingPackage=");
- pw.print(pus.getSuspendParams().keyAt(i));
- final SuspendParams params = pus.getSuspendParams().valueAt(i);
+ pw.print(userState.getSuspendParams().keyAt(i));
+ final SuspendParams params = userState.getSuspendParams().valueAt(i);
if (params != null) {
pw.print(" dialogInfo=");
- pw.print(params.dialogInfo);
+ pw.print(params.getDialogInfo());
}
pw.println();
}
}
- final OverlayPaths overlayPaths = ps.getOverlayPaths(user.id);
+ final OverlayPaths overlayPaths = userState.getOverlayPaths();
if (overlayPaths != null) {
if (!overlayPaths.getOverlayPaths().isEmpty()) {
pw.print(prefix);
@@ -4883,7 +4893,7 @@ public final class Settings implements Watchable, Snappable {
}
final Map<String, OverlayPaths> sharedLibraryOverlayPaths =
- ps.getOverlayPathsForLibrary(user.id);
+ userState.getSharedLibraryOverlayPaths();
if (sharedLibraryOverlayPaths != null) {
for (Map.Entry<String, OverlayPaths> libOverlayPaths :
sharedLibraryOverlayPaths.entrySet()) {
@@ -4916,7 +4926,7 @@ public final class Settings implements Watchable, Snappable {
}
}
- String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
+ String lastDisabledAppCaller = userState.getLastDisableAppCaller();
if (lastDisabledAppCaller != null) {
pw.print(prefix); pw.print(" lastDisabledCaller: ");
pw.println(lastDisabledAppCaller);
@@ -4929,21 +4939,21 @@ public final class Settings implements Watchable, Snappable {
.getPermissionStates(user.id), dumpAll);
}
- String harmfulAppWarning = ps.getHarmfulAppWarning(user.id);
+ String harmfulAppWarning = userState.getHarmfulAppWarning();
if (harmfulAppWarning != null) {
pw.print(prefix); pw.print(" harmfulAppWarning: ");
pw.println(harmfulAppWarning);
}
if (permissionNames == null) {
- ArraySet<String> cmp = ps.getDisabledComponents(user.id);
+ Set<String> cmp = userState.getDisabledComponents();
if (cmp != null && cmp.size() > 0) {
pw.print(prefix); pw.println(" disabledComponents:");
for (String s : cmp) {
pw.print(prefix); pw.print(" "); pw.println(s);
}
}
- cmp = ps.getEnabledComponents(user.id);
+ cmp = userState.getEnabledComponents();
if (cmp != null && cmp.size() > 0) {
pw.print(prefix); pw.println(" enabledComponents:");
for (String s : cmp) {
@@ -5291,9 +5301,10 @@ public final class Settings implements Watchable, Snappable {
public void writePermissionStateForUserLPr(int userId, boolean sync) {
if (sync) {
- mRuntimePermissionsPersistence.writeStateForUserSyncLPr(userId);
+ mRuntimePermissionsPersistence.writeStateForUserSync(userId, mPermissionDataProvider,
+ mPackages, mSharedUsers);
} else {
- mRuntimePermissionsPersistence.writeStateForUserAsyncLPr(userId);
+ mRuntimePermissionsPersistence.writeStateForUserAsync(userId);
}
}
@@ -5368,7 +5379,7 @@ public final class Settings implements Watchable, Snappable {
}
}
- private final class RuntimePermissionPersistence {
+ private static final class RuntimePermissionPersistence {
private static final long WRITE_PERMISSIONS_DELAY_MILLIS = 200;
private static final long MAX_WRITE_PERMISSIONS_DELAY_MILLIS = 2000;
@@ -5381,6 +5392,8 @@ public final class Settings implements Watchable, Snappable {
private final Handler mHandler = new MyHandler();
+ private final Object mLock = new Object();
+
@GuardedBy("mLock")
private final SparseBooleanArray mWriteScheduled = new SparseBooleanArray();
@@ -5400,45 +5413,58 @@ public final class Settings implements Watchable, Snappable {
// The mapping keys are user ids.
private final SparseBooleanArray mPermissionUpgradeNeeded = new SparseBooleanArray();
- public RuntimePermissionPersistence(RuntimePermissionsPersistence persistence) {
+ // This is a hack to allow this class to invoke a write using Settings's data structures,
+ // to facilitate moving to a finer scoped lock without a significant refactor.
+ private final Consumer<Integer> mInvokeWriteUserStateAsyncCallback;
+
+ public RuntimePermissionPersistence(RuntimePermissionsPersistence persistence,
+ Consumer<Integer> invokeWriteUserStateAsyncCallback) {
mPersistence = persistence;
+ mInvokeWriteUserStateAsyncCallback = invokeWriteUserStateAsyncCallback;
}
- @GuardedBy("Settings.this.mLock")
- int getVersionLPr(int userId) {
- return mVersions.get(userId, INITIAL_VERSION);
+ int getVersion(int userId) {
+ synchronized (mLock) {
+ return mVersions.get(userId, INITIAL_VERSION);
+ }
}
- @GuardedBy("Settings.this.mLock")
- void setVersionLPr(int version, int userId) {
- mVersions.put(userId, version);
- writeStateForUserAsyncLPr(userId);
+ void setVersion(int version, int userId) {
+ synchronized (mLock) {
+ mVersions.put(userId, version);
+ writeStateForUserAsync(userId);
+ }
}
- @GuardedBy("Settings.this.mLock")
public boolean isPermissionUpgradeNeeded(int userId) {
- return mPermissionUpgradeNeeded.get(userId, true);
+ synchronized (mLock) {
+ return mPermissionUpgradeNeeded.get(userId, true);
+ }
}
- @GuardedBy("Settings.this.mLock")
- public void updateRuntimePermissionsFingerprintLPr(@UserIdInt int userId) {
- if (mExtendedFingerprint == null) {
- throw new RuntimeException("The version of the permission controller hasn't been "
- + "set before trying to update the fingerprint.");
+ public void updateRuntimePermissionsFingerprint(@UserIdInt int userId) {
+ synchronized (mLock) {
+ if (mExtendedFingerprint == null) {
+ throw new RuntimeException(
+ "The version of the permission controller hasn't been "
+ + "set before trying to update the fingerprint.");
+ }
+ mFingerprints.put(userId, mExtendedFingerprint);
+ writeStateForUserAsync(userId);
}
- mFingerprints.put(userId, mExtendedFingerprint);
- writeStateForUserAsyncLPr(userId);
}
public void setPermissionControllerVersion(long version) {
- int numUser = mFingerprints.size();
- mExtendedFingerprint = getExtendedFingerprint(version);
+ synchronized (mLock) {
+ int numUser = mFingerprints.size();
+ mExtendedFingerprint = getExtendedFingerprint(version);
- for (int i = 0; i < numUser; i++) {
- int userId = mFingerprints.keyAt(i);
- String fingerprint = mFingerprints.valueAt(i);
- mPermissionUpgradeNeeded.put(userId,
- !TextUtils.equals(mExtendedFingerprint, fingerprint));
+ for (int i = 0; i < numUser; i++) {
+ int userId = mFingerprints.keyAt(i);
+ String fingerprint = mFingerprints.valueAt(i);
+ mPermissionUpgradeNeeded.put(userId,
+ !TextUtils.equals(mExtendedFingerprint, fingerprint));
+ }
}
}
@@ -5446,84 +5472,92 @@ public final class Settings implements Watchable, Snappable {
return PackagePartitions.FINGERPRINT + "?pc_version=" + version;
}
- public void writeStateForUserAsyncLPr(int userId) {
- final long currentTimeMillis = SystemClock.uptimeMillis();
+ public void writeStateForUserAsync(int userId) {
+ synchronized (mLock) {
+ final long currentTimeMillis = SystemClock.uptimeMillis();
- if (mWriteScheduled.get(userId)) {
- mHandler.removeMessages(userId);
+ if (mWriteScheduled.get(userId)) {
+ mHandler.removeMessages(userId);
- // If enough time passed, write without holding off anymore.
- final long lastNotWrittenMutationTimeMillis = mLastNotWrittenMutationTimesMillis
- .get(userId);
- final long timeSinceLastNotWrittenMutationMillis = currentTimeMillis
- - lastNotWrittenMutationTimeMillis;
- if (timeSinceLastNotWrittenMutationMillis >= MAX_WRITE_PERMISSIONS_DELAY_MILLIS) {
- mHandler.obtainMessage(userId).sendToTarget();
- return;
- }
+ // If enough time passed, write without holding off anymore.
+ final long lastNotWrittenMutationTimeMillis = mLastNotWrittenMutationTimesMillis
+ .get(userId);
+ final long timeSinceLastNotWrittenMutationMillis = currentTimeMillis
+ - lastNotWrittenMutationTimeMillis;
+ if (timeSinceLastNotWrittenMutationMillis
+ >= MAX_WRITE_PERMISSIONS_DELAY_MILLIS) {
+ mHandler.obtainMessage(userId).sendToTarget();
+ return;
+ }
- // Hold off a bit more as settings are frequently changing.
- final long maxDelayMillis = Math.max(lastNotWrittenMutationTimeMillis
- + MAX_WRITE_PERMISSIONS_DELAY_MILLIS - currentTimeMillis, 0);
- final long writeDelayMillis = Math.min(WRITE_PERMISSIONS_DELAY_MILLIS,
- maxDelayMillis);
+ // Hold off a bit more as settings are frequently changing.
+ final long maxDelayMillis = Math.max(lastNotWrittenMutationTimeMillis
+ + MAX_WRITE_PERMISSIONS_DELAY_MILLIS - currentTimeMillis, 0);
+ final long writeDelayMillis = Math.min(WRITE_PERMISSIONS_DELAY_MILLIS,
+ maxDelayMillis);
- Message message = mHandler.obtainMessage(userId);
- mHandler.sendMessageDelayed(message, writeDelayMillis);
- } else {
- mLastNotWrittenMutationTimesMillis.put(userId, currentTimeMillis);
- Message message = mHandler.obtainMessage(userId);
- mHandler.sendMessageDelayed(message, WRITE_PERMISSIONS_DELAY_MILLIS);
- mWriteScheduled.put(userId, true);
+ Message message = mHandler.obtainMessage(userId);
+ mHandler.sendMessageDelayed(message, writeDelayMillis);
+ } else {
+ mLastNotWrittenMutationTimesMillis.put(userId, currentTimeMillis);
+ Message message = mHandler.obtainMessage(userId);
+ mHandler.sendMessageDelayed(message, WRITE_PERMISSIONS_DELAY_MILLIS);
+ mWriteScheduled.put(userId, true);
+ }
}
}
- public void writeStateForUserSyncLPr(int userId) {
- mHandler.removeMessages(userId);
- mWriteScheduled.delete(userId);
-
- mPermissionDataProvider.writeLegacyPermissionStateTEMP();
-
- int version = mVersions.get(userId, INITIAL_VERSION);
-
- String fingerprint = mFingerprints.get(userId);
+ public void writeStateForUserSync(int userId, @NonNull LegacyPermissionDataProvider
+ legacyPermissionDataProvider,
+ @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
+ @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers) {
+ synchronized (mLock) {
+ mHandler.removeMessages(userId);
+ mWriteScheduled.delete(userId);
+
+ legacyPermissionDataProvider.writeLegacyPermissionStateTEMP();
+
+ int version = mVersions.get(userId, INITIAL_VERSION);
+
+ String fingerprint = mFingerprints.get(userId);
+
+ Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
+ new ArrayMap<>();
+ int packagesSize = packageStates.size();
+ for (int i = 0; i < packagesSize; i++) {
+ String packageName = packageStates.keyAt(i);
+ PackageStateInternal packageState = packageStates.valueAt(i);
+ if (packageState.getSharedUser() == null) {
+ List<RuntimePermissionsState.PermissionState> permissions =
+ getPermissionsFromPermissionsState(
+ packageState.getLegacyPermissionState(), userId);
+ if (permissions.isEmpty() && !packageState.isInstallPermissionsFixed()) {
+ // Storing an empty state means the package is known to the system and
+ // its install permissions have been granted and fixed. If this is not
+ // the case, we should not store anything.
+ continue;
+ }
+ packagePermissions.put(packageName, permissions);
+ }
+ }
- Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
- new ArrayMap<>();
- int packagesSize = mPackages.size();
- for (int i = 0; i < packagesSize; i++) {
- String packageName = mPackages.keyAt(i);
- PackageSetting packageSetting = mPackages.valueAt(i);
- if (packageSetting.getSharedUser() == null) {
+ Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions =
+ new ArrayMap<>();
+ final int sharedUsersSize = sharedUsers.size();
+ for (int i = 0; i < sharedUsersSize; i++) {
+ String sharedUserName = sharedUsers.keyAt(i);
+ SharedUserSetting sharedUserSetting = sharedUsers.valueAt(i);
List<RuntimePermissionsState.PermissionState> permissions =
getPermissionsFromPermissionsState(
- packageSetting.getLegacyPermissionState(), userId);
- if (permissions.isEmpty() && !packageSetting.isInstallPermissionsFixed()) {
- // Storing an empty state means the package is known to the system and its
- // install permissions have been granted and fixed. If this is not the case,
- // we should not store anything.
- continue;
- }
- packagePermissions.put(packageName, permissions);
+ sharedUserSetting.getLegacyPermissionState(), userId);
+ sharedUserPermissions.put(sharedUserName, permissions);
}
- }
- Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions =
- new ArrayMap<>();
- final int sharedUsersSize = mSharedUsers.size();
- for (int i = 0; i < sharedUsersSize; i++) {
- String sharedUserName = mSharedUsers.keyAt(i);
- SharedUserSetting sharedUserSetting = mSharedUsers.valueAt(i);
- List<RuntimePermissionsState.PermissionState> permissions =
- getPermissionsFromPermissionsState(
- sharedUserSetting.getLegacyPermissionState(), userId);
- sharedUserPermissions.put(sharedUserName, permissions);
- }
+ RuntimePermissionsState runtimePermissions = new RuntimePermissionsState(version,
+ fingerprint, packagePermissions, sharedUserPermissions);
- RuntimePermissionsState runtimePermissions = new RuntimePermissionsState(version,
- fingerprint, packagePermissions, sharedUserPermissions);
-
- mPersistence.writeForUser(runtimePermissions, UserHandle.of(userId));
+ mPersistence.writeForUser(runtimePermissions, UserHandle.of(userId));
+ }
}
@NonNull
@@ -5541,82 +5575,91 @@ public final class Settings implements Watchable, Snappable {
return permissions;
}
- @GuardedBy("Settings.this.mLock")
- private void onUserRemovedLPw(int userId) {
- // Make sure we do not
- mHandler.removeMessages(userId);
+ private void onUserRemoved(int userId) {
+ synchronized (mLock) {
+ // Make sure we do not
+ mHandler.removeMessages(userId);
- mPermissionUpgradeNeeded.delete(userId);
- mVersions.delete(userId);
- mFingerprints.remove(userId);
+ mPermissionUpgradeNeeded.delete(userId);
+ mVersions.delete(userId);
+ mFingerprints.remove(userId);
+ }
}
public void deleteUserRuntimePermissionsFile(int userId) {
- mPersistence.deleteForUser(UserHandle.of(userId));
- }
-
- @GuardedBy("Settings.this.mLock")
- public void readStateForUserSyncLPr(int userId) {
- RuntimePermissionsState runtimePermissions = mPersistence.readForUser(UserHandle.of(
- userId));
- if (runtimePermissions == null) {
- readLegacyStateForUserSyncLPr(userId);
- writeStateForUserAsyncLPr(userId);
- return;
- }
+ synchronized (mLock) {
+ mPersistence.deleteForUser(UserHandle.of(userId));
+ }
+ }
+
+ public void readStateForUserSync(int userId, @NonNull VersionInfo internalVersion,
+ @NonNull WatchedArrayMap<String, PackageSetting> packageSettings,
+ @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers,
+ @NonNull File userRuntimePermissionsFile) {
+ synchronized (mLock) {
+ RuntimePermissionsState runtimePermissions = mPersistence.readForUser(UserHandle.of(
+ userId));
+ if (runtimePermissions == null) {
+ readLegacyStateForUserSync(userId, userRuntimePermissionsFile, packageSettings,
+ sharedUsers);
+ writeStateForUserAsync(userId);
+ return;
+ }
- // If the runtime permissions file exists but the version is not set this is
- // an upgrade from P->Q. Hence mark it with the special UPGRADE_VERSION.
- int version = runtimePermissions.getVersion();
- if (version == RuntimePermissionsState.NO_VERSION) {
- version = UPGRADE_VERSION;
- }
- mVersions.put(userId, version);
+ // If the runtime permissions file exists but the version is not set this is
+ // an upgrade from P->Q. Hence mark it with the special UPGRADE_VERSION.
+ int version = runtimePermissions.getVersion();
+ if (version == RuntimePermissionsState.NO_VERSION) {
+ version = UPGRADE_VERSION;
+ }
+ mVersions.put(userId, version);
- String fingerprint = runtimePermissions.getFingerprint();
- mFingerprints.put(userId, fingerprint);
+ String fingerprint = runtimePermissions.getFingerprint();
+ mFingerprints.put(userId, fingerprint);
- boolean isUpgradeToR = getInternalVersion().sdkVersion < Build.VERSION_CODES.R;
+ boolean isUpgradeToR = internalVersion.sdkVersion < Build.VERSION_CODES.R;
- Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
- runtimePermissions.getPackagePermissions();
- int packagesSize = mPackages.size();
- for (int i = 0; i < packagesSize; i++) {
- String packageName = mPackages.keyAt(i);
- PackageSetting packageSetting = mPackages.valueAt(i);
+ Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
+ runtimePermissions.getPackagePermissions();
+ int packagesSize = packageSettings.size();
+ for (int i = 0; i < packagesSize; i++) {
+ String packageName = packageSettings.keyAt(i);
+ PackageSetting packageSetting = packageSettings.valueAt(i);
- List<RuntimePermissionsState.PermissionState> permissions =
- packagePermissions.get(packageName);
- if (permissions != null) {
- readPermissionsStateLpr(permissions, packageSetting.getLegacyPermissionState(),
- userId);
- packageSetting.setInstallPermissionsFixed(true);
- } else if (packageSetting.getSharedUser() == null && !isUpgradeToR) {
- Slog.w(TAG, "Missing permission state for package: " + packageName);
- packageSetting.getLegacyPermissionState().setMissing(true, userId);
+ List<RuntimePermissionsState.PermissionState> permissions =
+ packagePermissions.get(packageName);
+ if (permissions != null) {
+ readPermissionsState(permissions,
+ packageSetting.getLegacyPermissionState(),
+ userId);
+ packageSetting.setInstallPermissionsFixed(true);
+ } else if (packageSetting.getSharedUser() == null && !isUpgradeToR) {
+ Slog.w(TAG, "Missing permission state for package: " + packageName);
+ packageSetting.getLegacyPermissionState().setMissing(true, userId);
+ }
}
- }
- Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions =
- runtimePermissions.getSharedUserPermissions();
- int sharedUsersSize = mSharedUsers.size();
- for (int i = 0; i < sharedUsersSize; i++) {
- String sharedUserName = mSharedUsers.keyAt(i);
- SharedUserSetting sharedUserSetting = mSharedUsers.valueAt(i);
+ Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions =
+ runtimePermissions.getSharedUserPermissions();
+ int sharedUsersSize = sharedUsers.size();
+ for (int i = 0; i < sharedUsersSize; i++) {
+ String sharedUserName = sharedUsers.keyAt(i);
+ SharedUserSetting sharedUserSetting = sharedUsers.valueAt(i);
- List<RuntimePermissionsState.PermissionState> permissions =
- sharedUserPermissions.get(sharedUserName);
- if (permissions != null) {
- readPermissionsStateLpr(permissions,
- sharedUserSetting.getLegacyPermissionState(), userId);
- } else if (!isUpgradeToR) {
- Slog.w(TAG, "Missing permission state for shared user: " + sharedUserName);
- sharedUserSetting.getLegacyPermissionState().setMissing(true, userId);
+ List<RuntimePermissionsState.PermissionState> permissions =
+ sharedUserPermissions.get(sharedUserName);
+ if (permissions != null) {
+ readPermissionsState(permissions,
+ sharedUserSetting.getLegacyPermissionState(), userId);
+ } else if (!isUpgradeToR) {
+ Slog.w(TAG, "Missing permission state for shared user: " + sharedUserName);
+ sharedUserSetting.getLegacyPermissionState().setMissing(true, userId);
+ }
}
}
}
- private void readPermissionsStateLpr(
+ private void readPermissionsState(
@NonNull List<RuntimePermissionsState.PermissionState> permissions,
@NonNull LegacyPermissionState permissionsState, @UserIdInt int userId) {
int permissionsSize = permissions.size();
@@ -5630,77 +5673,86 @@ public final class Settings implements Watchable, Snappable {
}
}
- @GuardedBy("Settings.this.mLock")
- private void readLegacyStateForUserSyncLPr(int userId) {
- File permissionsFile = getUserRuntimePermissionsFile(userId);
- if (!permissionsFile.exists()) {
- return;
- }
+ private void readLegacyStateForUserSync(int userId, @NonNull File permissionsFile,
+ @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
+ @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers) {
+ synchronized (mLock) {
+ if (!permissionsFile.exists()) {
+ return;
+ }
- FileInputStream in;
- try {
- in = new AtomicFile(permissionsFile).openRead();
- } catch (FileNotFoundException fnfe) {
- Slog.i(PackageManagerService.TAG, "No permissions state");
- return;
- }
+ FileInputStream in;
+ try {
+ in = new AtomicFile(permissionsFile).openRead();
+ } catch (FileNotFoundException fnfe) {
+ Slog.i(PackageManagerService.TAG, "No permissions state");
+ return;
+ }
- try {
- final TypedXmlPullParser parser = Xml.resolvePullParser(in);
- parseLegacyRuntimePermissionsLPr(parser, userId);
+ try {
+ final TypedXmlPullParser parser = Xml.resolvePullParser(in);
+ parseLegacyRuntimePermissions(parser, userId, packageStates, sharedUsers);
- } catch (XmlPullParserException | IOException e) {
- throw new IllegalStateException("Failed parsing permissions file: "
- + permissionsFile, e);
- } finally {
- IoUtils.closeQuietly(in);
+ } catch (XmlPullParserException | IOException e) {
+ throw new IllegalStateException("Failed parsing permissions file: "
+ + permissionsFile, e);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
}
}
- // Private internals
-
- @GuardedBy("Settings.this.mLock")
- private void parseLegacyRuntimePermissionsLPr(TypedXmlPullParser parser, int userId)
+ private void parseLegacyRuntimePermissions(TypedXmlPullParser parser, int userId,
+ @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
+ @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers)
throws IOException, XmlPullParserException {
- final int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
+ synchronized (mLock) {
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
- switch (parser.getName()) {
- case TAG_RUNTIME_PERMISSIONS: {
- // If the permisions settings file exists but the version is not set this is
- // an upgrade from P->Q. Hence mark it with the special UPGRADE_VERSION
- int version = parser.getAttributeInt(null, ATTR_VERSION, UPGRADE_VERSION);
- mVersions.put(userId, version);
- String fingerprint = parser.getAttributeValue(null, ATTR_FINGERPRINT);
- mFingerprints.put(userId, fingerprint);
- } break;
-
- case TAG_PACKAGE: {
- String name = parser.getAttributeValue(null, ATTR_NAME);
- PackageSetting ps = mPackages.get(name);
- if (ps == null) {
- Slog.w(PackageManagerService.TAG, "Unknown package:" + name);
- XmlUtils.skipCurrentTag(parser);
- continue;
+ switch (parser.getName()) {
+ case TAG_RUNTIME_PERMISSIONS: {
+ // If the permisions settings file exists but the version is not set this is
+ // an upgrade from P->Q. Hence mark it with the special UPGRADE_VERSION
+ int version = parser.getAttributeInt(null, ATTR_VERSION,
+ UPGRADE_VERSION);
+ mVersions.put(userId, version);
+ String fingerprint = parser.getAttributeValue(null, ATTR_FINGERPRINT);
+ mFingerprints.put(userId, fingerprint);
}
- parseLegacyPermissionsLPr(parser, ps.getLegacyPermissionState(), userId);
- } break;
-
- case TAG_SHARED_USER: {
- String name = parser.getAttributeValue(null, ATTR_NAME);
- SharedUserSetting sus = mSharedUsers.get(name);
- if (sus == null) {
- Slog.w(PackageManagerService.TAG, "Unknown shared user:" + name);
- XmlUtils.skipCurrentTag(parser);
- continue;
+ break;
+
+ case TAG_PACKAGE: {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ PackageStateInternal ps = packageStates.get(name);
+ if (ps == null) {
+ Slog.w(PackageManagerService.TAG, "Unknown package:" + name);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ parseLegacyPermissionsLPr(parser, ps.getLegacyPermissionState(),
+ userId);
+ }
+ break;
+
+ case TAG_SHARED_USER: {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ SharedUserSetting sus = sharedUsers.get(name);
+ if (sus == null) {
+ Slog.w(PackageManagerService.TAG, "Unknown shared user:" + name);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ parseLegacyPermissionsLPr(parser, sus.getLegacyPermissionState(),
+ userId);
}
- parseLegacyPermissionsLPr(parser, sus.getLegacyPermissionState(), userId);
- } break;
+ break;
+ }
}
}
}
@@ -5708,25 +5760,27 @@ public final class Settings implements Watchable, Snappable {
private void parseLegacyPermissionsLPr(TypedXmlPullParser parser,
LegacyPermissionState permissionsState, int userId)
throws IOException, XmlPullParserException {
- final int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
+ synchronized (mLock) {
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
- switch (parser.getName()) {
- case TAG_ITEM: {
- String name = parser.getAttributeValue(null, ATTR_NAME);
- final boolean granted =
- parser.getAttributeBoolean(null, ATTR_GRANTED, true);
- final int flags =
- parser.getAttributeIntHex(null, ATTR_FLAGS, 0);
- permissionsState.putPermissionState(new PermissionState(name, true,
- granted, flags), userId);
+ switch (parser.getName()) {
+ case TAG_ITEM: {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ final boolean granted =
+ parser.getAttributeBoolean(null, ATTR_GRANTED, true);
+ final int flags =
+ parser.getAttributeIntHex(null, ATTR_FLAGS, 0);
+ permissionsState.putPermissionState(new PermissionState(name, true,
+ granted, flags), userId);
+ }
+ break;
}
- break;
}
}
}
@@ -5740,9 +5794,7 @@ public final class Settings implements Watchable, Snappable {
public void handleMessage(Message message) {
final int userId = message.what;
Runnable callback = (Runnable) message.obj;
- synchronized (mLock) {
- writeStateForUserSyncLPr(userId);
- }
+ mInvokeWriteUserStateAsyncCallback.accept(userId);
if (callback != null) {
callback.run();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
index 5460afa665e6..56f62ab87933 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
@@ -23,6 +23,7 @@ import android.content.pm.SigningDetails;
import android.util.SparseArray;
import com.android.server.pm.InstallSource;
+import com.android.server.pm.PackageKeySetData;
import com.android.server.pm.SharedUserSetting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.LegacyPermissionState;
@@ -82,4 +83,7 @@ public interface PackageStateInternal extends PackageState {
String getPathString();
float getLoadingProgress();
+
+ @NonNull
+ PackageKeySetData getKeySetData();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
index 32a9cf1bdb3d..6fafb242201a 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
@@ -28,6 +28,7 @@ import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DataClass;
import java.util.Objects;
@@ -49,7 +50,6 @@ public class PackageUserStateImpl implements PackageUserStateInternal {
private boolean mNotLaunched;
private boolean mHidden; // Is the app restricted by owner / admin
private int mDistractionFlags;
- private boolean mSuspended;
private boolean mInstantApp;
private boolean mVirtualPreload;
private int mEnabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
@@ -101,7 +101,6 @@ public class PackageUserStateImpl implements PackageUserStateInternal {
mNotLaunched = other.mNotLaunched;
mHidden = other.mHidden;
mDistractionFlags = other.mDistractionFlags;
- mSuspended = other.mSuspended;
mInstantApp = other.mInstantApp;
mVirtualPreload = other.mVirtualPreload;
mEnabledState = other.mEnabledState;
@@ -256,6 +255,28 @@ public class PackageUserStateImpl implements PackageUserStateInternal {
return mComponentLabelIconOverrideMap.get(componentName);
}
+ @Override
+ public boolean isSuspended() {
+ return !CollectionUtils.isEmpty(mSuspendParams);
+ }
+
+ public PackageUserStateImpl putSuspendParams(@NonNull String suspendingPackage,
+ @NonNull SuspendParams suspendParams) {
+ if (mSuspendParams == null) {
+ mSuspendParams = new ArrayMap<>();
+ }
+ mSuspendParams.put(suspendingPackage, suspendParams);
+ return this;
+ }
+
+ public PackageUserStateImpl removeSuspension(@NonNull String suspendingPackage) {
+ if (mSuspendParams != null) {
+ mSuspendParams.remove(suspendingPackage);
+ }
+ return this;
+ }
+
+
// Code below generated by codegen v1.0.23.
@@ -312,11 +333,6 @@ public class PackageUserStateImpl implements PackageUserStateInternal {
}
@DataClass.Generated.Member
- public boolean isSuspended() {
- return mSuspended;
- }
-
- @DataClass.Generated.Member
public boolean isInstantApp() {
return mInstantApp;
}
@@ -433,12 +449,6 @@ public class PackageUserStateImpl implements PackageUserStateInternal {
}
@DataClass.Generated.Member
- public @NonNull PackageUserStateImpl setSuspended( boolean value) {
- mSuspended = value;
- return this;
- }
-
- @DataClass.Generated.Member
public @NonNull PackageUserStateImpl setInstantApp( boolean value) {
mInstantApp = value;
return this;
@@ -532,7 +542,6 @@ public class PackageUserStateImpl implements PackageUserStateInternal {
&& mNotLaunched == that.mNotLaunched
&& mHidden == that.mHidden
&& mDistractionFlags == that.mDistractionFlags
- && mSuspended == that.mSuspended
&& mInstantApp == that.mInstantApp
&& mVirtualPreload == that.mVirtualPreload
&& mEnabledState == that.mEnabledState
@@ -563,7 +572,6 @@ public class PackageUserStateImpl implements PackageUserStateInternal {
_hash = 31 * _hash + Boolean.hashCode(mNotLaunched);
_hash = 31 * _hash + Boolean.hashCode(mHidden);
_hash = 31 * _hash + mDistractionFlags;
- _hash = 31 * _hash + Boolean.hashCode(mSuspended);
_hash = 31 * _hash + Boolean.hashCode(mInstantApp);
_hash = 31 * _hash + Boolean.hashCode(mVirtualPreload);
_hash = 31 * _hash + mEnabledState;
@@ -581,10 +589,10 @@ public class PackageUserStateImpl implements PackageUserStateInternal {
}
@DataClass.Generated(
- time = 1633983318771L,
+ time = 1636145886996L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java",
- inputSignatures = "protected @android.annotation.Nullable android.util.ArraySet<java.lang.String> mDisabledComponents\nprotected @android.annotation.Nullable android.util.ArraySet<java.lang.String> mEnabledComponents\nprivate long mCeDataInode\nprivate boolean mInstalled\nprivate boolean mStopped\nprivate boolean mNotLaunched\nprivate boolean mHidden\nprivate int mDistractionFlags\nprivate boolean mSuspended\nprivate boolean mInstantApp\nprivate boolean mVirtualPreload\nprivate int mEnabledState\nprivate @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprotected @android.annotation.Nullable android.content.pm.overlay.OverlayPaths mOverlayPaths\nprotected @android.annotation.Nullable android.util.ArrayMap<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate @android.annotation.Nullable java.lang.String mSplashScreenTheme\nprivate @android.annotation.Nullable android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams> mSuspendParams\nprivate @android.annotation.Nullable android.content.pm.overlay.OverlayPaths mCachedOverlayPaths\nprivate @android.annotation.Nullable android.util.ArrayMap<android.content.ComponentName,android.util.Pair<java.lang.String,java.lang.Integer>> mComponentLabelIconOverrideMap\npublic @android.annotation.Nullable boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths)\npublic boolean setSharedLibraryOverlayPaths(java.lang.String,android.content.pm.overlay.OverlayPaths)\npublic @android.annotation.Nullable @java.lang.Override android.util.ArraySet<java.lang.String> getDisabledComponentsNoCopy()\npublic @android.annotation.Nullable @java.lang.Override android.util.ArraySet<java.lang.String> getEnabledComponentsNoCopy()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer)\npublic void resetOverrideComponentLabelIcon()\npublic @android.annotation.Nullable android.util.Pair<java.lang.String,java.lang.Integer> getOverrideLabelIconForComponent(android.content.ComponentName)\nclass PackageUserStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageUserStateInternal]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false, genEqualsHashCode=true)")
+ inputSignatures = "protected @android.annotation.Nullable android.util.ArraySet<java.lang.String> mDisabledComponents\nprotected @android.annotation.Nullable android.util.ArraySet<java.lang.String> mEnabledComponents\nprivate long mCeDataInode\nprivate boolean mInstalled\nprivate boolean mStopped\nprivate boolean mNotLaunched\nprivate boolean mHidden\nprivate int mDistractionFlags\nprivate boolean mInstantApp\nprivate boolean mVirtualPreload\nprivate int mEnabledState\nprivate @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprotected @android.annotation.Nullable android.content.pm.overlay.OverlayPaths mOverlayPaths\nprotected @android.annotation.Nullable android.util.ArrayMap<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate @android.annotation.Nullable java.lang.String mSplashScreenTheme\nprivate @android.annotation.Nullable android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams> mSuspendParams\nprivate @android.annotation.Nullable android.content.pm.overlay.OverlayPaths mCachedOverlayPaths\nprivate @android.annotation.Nullable android.util.ArrayMap<android.content.ComponentName,android.util.Pair<java.lang.String,java.lang.Integer>> mComponentLabelIconOverrideMap\npublic @android.annotation.Nullable boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths)\npublic boolean setSharedLibraryOverlayPaths(java.lang.String,android.content.pm.overlay.OverlayPaths)\npublic @android.annotation.Nullable @java.lang.Override android.util.ArraySet<java.lang.String> getDisabledComponentsNoCopy()\npublic @android.annotation.Nullable @java.lang.Override android.util.ArraySet<java.lang.String> getEnabledComponentsNoCopy()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer)\npublic void resetOverrideComponentLabelIcon()\npublic @android.annotation.Nullable android.util.Pair<java.lang.String,java.lang.Integer> getOverrideLabelIconForComponent(android.content.ComponentName)\npublic @java.lang.Override boolean isSuspended()\npublic com.android.server.pm.pkg.PackageUserStateImpl putSuspendParams(java.lang.String,com.android.server.pm.pkg.SuspendParams)\npublic com.android.server.pm.pkg.PackageUserStateImpl removeSuspension(java.lang.String)\nclass PackageUserStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageUserStateInternal]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false, genEqualsHashCode=true)")
@Deprecated
private void __metadata() {}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java
index 6f3331223bff..bd8b3ab61140 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java
@@ -32,6 +32,7 @@ public interface PackageUserStateInternal extends PackageUserState {
PackageUserStateInternal DEFAULT = new PackageUserStateDefault();
+ // TODO: Make non-null with emptyMap()
@Nullable
ArrayMap<String, SuspendParams> getSuspendParams();
diff --git a/services/core/java/com/android/server/pm/pkg/SuspendParams.java b/services/core/java/com/android/server/pm/pkg/SuspendParams.java
index 71512dc84088..d24ce96bb4b6 100644
--- a/services/core/java/com/android/server/pm/pkg/SuspendParams.java
+++ b/services/core/java/com/android/server/pm/pkg/SuspendParams.java
@@ -42,11 +42,15 @@ public final class SuspendParams {
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 final SuspendDialogInfo dialogInfo;
+ private final PersistableBundle appExtras;
+ private final PersistableBundle launcherExtras;
- private SuspendParams() {
+ private SuspendParams(SuspendDialogInfo dialogInfo, PersistableBundle appExtras,
+ PersistableBundle launcherExtras) {
+ this.dialogInfo = dialogInfo;
+ this.appExtras = appExtras;
+ this.launcherExtras = launcherExtras;
}
/**
@@ -60,11 +64,7 @@ public final class SuspendParams {
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;
+ return new SuspendParams(dialogInfo, appExtras, launcherExtras);
}
@Override
@@ -172,4 +172,16 @@ public final class SuspendParams {
}
return getInstanceOrNull(readDialogInfo, readAppExtras, readLauncherExtras);
}
+
+ public SuspendDialogInfo getDialogInfo() {
+ return dialogInfo;
+ }
+
+ public PersistableBundle getAppExtras() {
+ return appExtras;
+ }
+
+ public PersistableBundle getLauncherExtras() {
+ return launcherExtras;
+ }
}
diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java
new file mode 100644
index 000000000000..35d4d9e82fbe
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.pkg.mutate;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.overlay.OverlayPaths;
+import android.util.ArraySet;
+
+import com.android.server.pm.PackageSetting;
+import com.android.server.pm.pkg.PackageUserStateImpl;
+import com.android.server.pm.pkg.SuspendParams;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
+
+public class PackageStateMutator {
+
+ private static final AtomicLong sStateChangeSequence = new AtomicLong();
+
+ private final StateWriteWrapper mStateWrite = new StateWriteWrapper();
+
+ private final Function<String, PackageSetting> mActiveStateFunction;
+ private final Function<String, PackageSetting> mDisabledStateFunction;
+
+ public PackageStateMutator(@NonNull Function<String, PackageSetting> activeStateFunction,
+ @NonNull Function<String, PackageSetting> disabledStateFunction) {
+ mActiveStateFunction = activeStateFunction;
+ mDisabledStateFunction = disabledStateFunction;
+ }
+
+ public static void onPackageStateChanged() {
+ sStateChangeSequence.incrementAndGet();
+ }
+
+ @NonNull
+ public PackageStateWrite forPackage(@NonNull String packageName) {
+ return mStateWrite.setState(mActiveStateFunction.apply(packageName));
+ }
+
+ @Nullable
+ public PackageStateWrite forPackageNullable(@NonNull String packageName) {
+ final PackageSetting packageState = mActiveStateFunction.apply(packageName);
+ mStateWrite.setState(packageState);
+ if (packageState == null) {
+ return null;
+ }
+
+ return mStateWrite.setState(packageState);
+ }
+
+ @NonNull
+ public PackageStateWrite forDisabledSystemPackage(@NonNull String packageName) {
+ return mStateWrite.setState(mDisabledStateFunction.apply(packageName));
+ }
+
+ @Nullable
+ public PackageStateWrite forDisabledSystemPackageNullable(@NonNull String packageName) {
+ final PackageSetting packageState = mDisabledStateFunction.apply(packageName);
+ if (packageState == null) {
+ return null;
+ }
+
+ return mStateWrite.setState(packageState);
+ }
+
+ @NonNull
+ public InitialState initialState(int changedPackagesSequenceNumber) {
+ return new InitialState(changedPackagesSequenceNumber, sStateChangeSequence.get());
+ }
+
+ /**
+ * @return null if initial state is null or if nothing has changed, otherwise return result
+ * with what changed
+ */
+ @Nullable
+ public Result generateResult(@Nullable InitialState state, int changedPackagesSequenceNumber) {
+ if (state == null) {
+ return Result.SUCCESS;
+ }
+
+ boolean packagesChanged = changedPackagesSequenceNumber != state.mPackageSequence;
+ boolean stateChanged = sStateChangeSequence.get() != state.mStateSequence;
+ if (packagesChanged && stateChanged) {
+ return Result.PACKAGES_AND_STATE_CHANGED;
+ } else if (packagesChanged) {
+ return Result.PACKAGES_CHANGED;
+ } else if (stateChanged) {
+ return Result.STATE_CHANGED;
+ } else {
+ return Result.SUCCESS;
+ }
+ }
+
+ public static class InitialState {
+
+ private final int mPackageSequence;
+ private final long mStateSequence;
+
+ public InitialState(int packageSequence, long stateSequence) {
+ mPackageSequence = packageSequence;
+ mStateSequence = stateSequence;
+ }
+ }
+
+ public static class Result {
+
+ public static final Result SUCCESS = new Result(true, false, false, false);
+ public static final Result PACKAGES_CHANGED = new Result(false, true, false, false);
+ public static final Result STATE_CHANGED = new Result(false, false, true, false);
+ public static final Result PACKAGES_AND_STATE_CHANGED = new Result(false, true, true, false);
+ public static final Result SPECIFIC_PACKAGE_NULL = new Result(false, false, true, true);
+
+ private final boolean mCommitted;
+ private final boolean mPackagesChanged;
+ private final boolean mStateChanged;
+ private final boolean mSpecificPackageNull;
+
+ public Result(boolean committed, boolean packagesChanged, boolean stateChanged,
+ boolean specificPackageNull) {
+ mCommitted = committed;
+ mPackagesChanged = packagesChanged;
+ mStateChanged = stateChanged;
+ mSpecificPackageNull = specificPackageNull;
+ }
+
+ public boolean isCommitted() {
+ return mCommitted;
+ }
+
+ public boolean isPackagesChanged() {
+ return mPackagesChanged;
+ }
+
+ public boolean isStateChanged() {
+ return mStateChanged;
+ }
+
+ public boolean isSpecificPackageNull() {
+ return mSpecificPackageNull;
+ }
+ }
+
+ private static class StateWriteWrapper implements PackageStateWrite {
+
+ private final UserStateWriteWrapper mUserStateWrite = new UserStateWriteWrapper();
+
+ @NonNull
+ private PackageSetting mState;
+
+ public StateWriteWrapper setState(PackageSetting state) {
+ this.mState = state;
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite userState(int userId) {
+ return mUserStateWrite.setStates(
+ mState == null ? null : mState.getOrCreateUserState(userId));
+ }
+
+ @Override
+ public PackageStateWrite setLastPackageUsageTime(int reason, long timeInMillis) {
+ if (mState != null) {
+ mState.getTransientState().setLastPackageUsageTimeInMills(reason, timeInMillis);
+ }
+ return this;
+ }
+
+ @Override
+ public PackageStateWrite setHiddenUntilInstalled(boolean value) {
+ if (mState != null) {
+ mState.getTransientState().setHiddenUntilInstalled(value);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageStateWrite setRequiredForSystemUser(boolean requiredForSystemUser) {
+ if (mState != null) {
+ if (requiredForSystemUser) {
+ mState.setPrivateFlags(mState.getPrivateFlags()
+ | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
+ } else {
+ mState.setPrivateFlags(mState.getPrivateFlags()
+ & ~ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
+ }
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageStateWrite setMimeGroup(@NonNull String mimeGroup,
+ @NonNull ArraySet<String> mimeTypes) {
+ if (mState != null) {
+ mState.setMimeGroup(mimeGroup, mimeTypes);
+ }
+ return this;
+ }
+
+ private static class UserStateWriteWrapper implements PackageUserStateWrite {
+
+ @Nullable
+ private PackageUserStateImpl mUserState;
+
+ public UserStateWriteWrapper setStates(@Nullable PackageUserStateImpl userState) {
+ mUserState = userState;
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setInstalled(boolean installed) {
+ if (mUserState != null) {
+ mUserState.setInstalled(installed);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setUninstallReason(int reason) {
+ if (mUserState != null) {
+ mUserState.setUninstallReason(reason);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setDistractionFlags(
+ @PackageManager.DistractionRestriction int restrictionFlags) {
+ if (mUserState != null) {
+ mUserState.setDistractionFlags(restrictionFlags);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite putSuspendParams(@NonNull String suspendingPackage,
+ @Nullable SuspendParams suspendParams) {
+ if (mUserState != null) {
+ mUserState.putSuspendParams(suspendingPackage, suspendParams);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite removeSuspension(@NonNull String suspendingPackage) {
+ if (mUserState != null) {
+ mUserState.removeSuspension(suspendingPackage);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setHidden(boolean hidden) {
+ if (mUserState != null) {
+ mUserState.setHidden(hidden);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setStopped(boolean stopped) {
+ if (mUserState != null) {
+ mUserState.setStopped(stopped);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setNotLaunched(boolean notLaunched) {
+ if (mUserState != null) {
+ mUserState.setNotLaunched(notLaunched);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setOverlayPaths(@NonNull OverlayPaths overlayPaths) {
+ if (mUserState != null) {
+ mUserState.setOverlayPaths(overlayPaths);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setOverlayPathsForLibrary(@NonNull String libraryName,
+ @Nullable OverlayPaths overlayPaths) {
+ if (mUserState != null) {
+ mUserState.setSharedLibraryOverlayPaths(libraryName, overlayPaths);
+ }
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public PackageUserStateWrite setHarmfulAppWarning(@Nullable String warning) {
+ if (mUserState != null) {
+ mUserState.setHarmfulAppWarning(warning);
+ }
+ return this;
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java
new file mode 100644
index 000000000000..585becee55c0
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.pkg.mutate;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.content.pm.PackageManager;
+import android.util.ArraySet;
+
+public interface PackageStateWrite {
+
+ @NonNull
+ PackageUserStateWrite userState(@UserIdInt int userId);
+
+ @NonNull
+ PackageStateWrite setLastPackageUsageTime(@PackageManager.NotifyReason int reason,
+ long timeInMillis);
+
+ @NonNull
+ PackageStateWrite setHiddenUntilInstalled(boolean hiddenUntilInstalled);
+
+ @NonNull
+ PackageStateWrite setRequiredForSystemUser(boolean requiredForSystemUser);
+
+ @NonNull
+ PackageStateWrite setMimeGroup(@NonNull String mimeGroup, @NonNull ArraySet<String> mimeTypes);
+}
diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageUserStateWrite.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageUserStateWrite.java
new file mode 100644
index 000000000000..e23a1b604a49
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageUserStateWrite.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.pkg.mutate;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageManager;
+import android.content.pm.overlay.OverlayPaths;
+
+import com.android.server.pm.pkg.SuspendParams;
+
+public interface PackageUserStateWrite {
+
+ @NonNull
+ PackageUserStateWrite setInstalled(boolean installed);
+
+ @NonNull
+ PackageUserStateWrite setUninstallReason(@PackageManager.UninstallReason int reason);
+
+ @NonNull
+ PackageUserStateWrite setDistractionFlags(
+ @PackageManager.DistractionRestriction int restrictionFlags);
+
+ @NonNull
+ PackageUserStateWrite putSuspendParams(@NonNull String suspendingPackage,
+ @Nullable SuspendParams suspendParams);
+
+ @NonNull
+ PackageUserStateWrite removeSuspension(@NonNull String suspendingPackage);
+
+ @NonNull
+ PackageUserStateWrite setHidden(boolean hidden);
+
+ @NonNull
+ PackageUserStateWrite setStopped(boolean stopped);
+
+ @NonNull
+ PackageUserStateWrite setNotLaunched(boolean notLaunched);
+
+ @NonNull
+ PackageUserStateWrite setOverlayPaths(@Nullable OverlayPaths overlayPaths);
+
+ @NonNull
+ PackageUserStateWrite setOverlayPathsForLibrary(@NonNull String libraryName,
+ @Nullable OverlayPaths overlayPaths);
+
+ @NonNull
+ PackageUserStateWrite setHarmfulAppWarning(@Nullable String warning);
+}
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 6c9f8fee25b0..1b898fac2f06 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -264,17 +264,17 @@ public class PackageManagerSettingsTests {
final SuspendParams params = packageUserState1.getSuspendParams().valueAt(0);
watcher.verifyNoChangeReported("fetch user state");
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.getNeutralButtonAction(), is(BUTTON_ACTION_MORE_DETAILS));
- assertThat(params.dialogInfo.getDialogMessageResId(), is(ID_NULL));
+ assertThat(params.getAppExtras().size(), is(1));
+ assertThat(params.getAppExtras().getString("app_extra_string"), is("value"));
+ assertThat(params.getLauncherExtras().size(), is(1));
+ assertThat(params.getLauncherExtras().getLong("launcher_extra_long"), is(4L));
+ assertThat(params.getDialogInfo(), is(notNullValue()));
+ assertThat(params.getDialogInfo().getDialogMessage(), is("Dialog Message"));
+ assertThat(params.getDialogInfo().getTitleResId(), is(ID_NULL));
+ assertThat(params.getDialogInfo().getIconResId(), is(TEST_RESOURCE_ID));
+ assertThat(params.getDialogInfo().getNeutralButtonTextResId(), is(ID_NULL));
+ assertThat(params.getDialogInfo().getNeutralButtonAction(), is(BUTTON_ACTION_MORE_DETAILS));
+ assertThat(params.getDialogInfo().getDialogMessageResId(), is(ID_NULL));
}
@Test
@@ -351,18 +351,18 @@ public class PackageManagerSettingsTests {
final SuspendParams params11 = readPus1.getSuspendParams().valueAt(0);
watcher.verifyNoChangeReported("read package param");
assertThat(params11, is(notNullValue()));
- assertThat(params11.dialogInfo, is(dialogInfo1));
- assertThat(BaseBundle.kindofEquals(params11.appExtras, appExtras1), is(true));
- assertThat(BaseBundle.kindofEquals(params11.launcherExtras, launcherExtras1),
+ assertThat(params11.getDialogInfo(), is(dialogInfo1));
+ assertThat(BaseBundle.kindofEquals(params11.getAppExtras(), appExtras1), is(true));
+ assertThat(BaseBundle.kindofEquals(params11.getLauncherExtras(), launcherExtras1),
is(true));
watcher.verifyNoChangeReported("read package param");
assertThat(readPus1.getSuspendParams().keyAt(1), is("suspendingPackage2"));
final SuspendParams params12 = readPus1.getSuspendParams().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),
+ assertThat(params12.getDialogInfo(), is(dialogInfo2));
+ assertThat(BaseBundle.kindofEquals(params12.getAppExtras(), appExtras2), is(true));
+ assertThat(BaseBundle.kindofEquals(params12.getLauncherExtras(), launcherExtras2),
is(true));
watcher.verifyNoChangeReported("read package param");
@@ -373,9 +373,9 @@ public class PackageManagerSettingsTests {
assertThat(readPus2.getSuspendParams().keyAt(0), is("suspendingPackage3"));
final SuspendParams params21 = readPus2.getSuspendParams().valueAt(0);
assertThat(params21, is(notNullValue()));
- assertThat(params21.dialogInfo, is(nullValue()));
- assertThat(BaseBundle.kindofEquals(params21.appExtras, appExtras1), is(true));
- assertThat(params21.launcherExtras, is(nullValue()));
+ assertThat(params21.getDialogInfo(), is(nullValue()));
+ assertThat(BaseBundle.kindofEquals(params21.getAppExtras(), appExtras1), is(true));
+ assertThat(params21.getLauncherExtras(), is(nullValue()));
watcher.verifyNoChangeReported("read package param");
final PackageUserStateInternal readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3)
@@ -388,7 +388,7 @@ public class PackageManagerSettingsTests {
@Test
public void testPackageRestrictionsSuspendedDefault() {
final PackageSetting defaultSetting = createPackageSetting(PACKAGE_NAME_1);
- assertThat(defaultSetting.getSuspended(0), is(false));
+ assertThat(defaultSetting.getUserStateOrDefault(0).isSuspended(), is(false));
}
@Test
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 828d419c02ff..1e4134ec25d8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -82,7 +82,8 @@ public class PackageUserStateTest {
assertThat(testUserState.equals(oldUserState), is(false));
oldUserState = new PackageUserStateImpl();
- oldUserState.setSuspended(true);
+ oldUserState.putSuspendParams("suspendingPackage",
+ SuspendParams.getInstanceOrNull(null, new PersistableBundle(), null));
assertThat(testUserState.equals(oldUserState), is(false));
oldUserState = new PackageUserStateImpl();
@@ -231,7 +232,6 @@ public class PackageUserStateTest {
final PackageUserStateImpl testUserState1 = new PackageUserStateImpl();
- testUserState1.setSuspended(true);
testUserState1.setSuspendParams(paramsMap1);
PackageUserStateImpl testUserState2 =