summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Winson <chiuwinson@google.com> 2021-12-21 14:40:04 -0800
committer Winson <chiuwinson@google.com> 2021-12-30 13:42:18 -0800
commitc82b3c669ed29718b8e7f74c7a9b5883a0d70b14 (patch)
tree3eacbd5db2f91ddafe3c3dd5fe88f08b432108e1
parente90bb5f637e4e57111c4dada447c1ff8d1033c47 (diff)
Introduce package state mutation APIs
Adds APIs to record a state at some time and use that state to commit changes to package state. Which allows reconcilation and retry of competing changes without needing to take the data model lock unless absolutely necessary. Also copies over data model/settings changes to make it compile. Split from actual usage to make review easier. Bug: 202291547 Test: presubmit, no usages yet Change-Id: I6738829185022efef4add1805b5a52b3de3d173a
-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 c6ec59a5811f..d73eb0e2a049 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;
@@ -597,6 +600,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")
@@ -1626,6 +1639,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();
@@ -1729,6 +1744,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,
@@ -4909,8 +4926,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());
}
}
}
@@ -4983,9 +5000,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()));
}
@@ -7769,8 +7786,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());
}
}
}
@@ -7859,7 +7876,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
@@ -8305,7 +8322,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
@@ -8578,51 +8601,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
@@ -8632,17 +8628,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
@@ -8652,17 +8640,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
@@ -8671,6 +8650,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
@@ -8713,7 +8706,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)
@@ -8721,7 +8722,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) {
@@ -8730,15 +8731,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) {
@@ -8747,8 +8749,9 @@ public class PackageManagerService extends IPackageManager.Stub
return new PackageSetting(pkgSetting);
}
+ } else {
+ return computer.getPackageStateInternal(packageName, callingUid);
}
- return computer.getPackageStateInternal(packageName, callingUid);
}
@Nullable
@@ -8756,7 +8759,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);
@@ -8765,9 +8768,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
@@ -8795,16 +8799,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();
}
}
@@ -8817,17 +8813,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);
}
}
@@ -8841,18 +8851,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);
}
}
@@ -9051,7 +9146,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);
@@ -9553,4 +9649,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 =