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