From 664792c2316f3c3c8f396c4b7cf2dec8779210ef Mon Sep 17 00:00:00 2001 From: Winson Date: Mon, 31 Jan 2022 22:23:46 -0800 Subject: [PATCH] Remove PMS snapshot lambdas Lambdas were used to ensure consistent locking around the snapshot, but since it's impossible to lock the snapshot now, this is no longer necessary, and all methods should just store a reference. Also migrates DomainVerificationService off PackageSetting lambdas, which cleans up a lot of extra emthods. Bug: 215403184 Test: atest com.android.server.pm.verify.domain Test: atest SuspendPackageHelperTest Change-Id: Ib4e3442e5c16e935b14b8421fbc33adff65dcf68 --- .../content/pm/PackageManagerInternal.java | 2 +- .../pm/PackageSettingsSnapshotProvider.java | 77 -- .../com/android/server/pm/ComputerEngine.java | 4 +- .../server/pm/DeletePackageHelper.java | 3 +- .../pm/DomainVerificationConnection.java | 45 +- .../server/pm/InstallPackageHelper.java | 14 +- .../com/android/server/pm/PackageHandler.java | 1 + .../server/pm/PackageManagerService.java | 558 +++++------- .../server/pm/PendingPackageBroadcasts.java | 121 ++- .../java/com/android/server/pm/Settings.java | 14 +- .../server/pm/SharedLibrariesImpl.java | 57 +- .../server/pm/SuspendPackageHelper.java | 204 +++-- .../domain/DomainVerificationDebug.java | 9 +- .../DomainVerificationManagerInternal.java | 44 +- .../domain/DomainVerificationService.java | 828 ++++++++---------- .../domain/DomainVerificationSettings.java | 17 +- .../domain/DomainVerificationShell.java | 6 +- ...geManagerComponentLabelIconOverrideTest.kt | 6 +- .../domain/DomainVerificationEnforcerTest.kt | 25 +- .../DomainVerificationManagerApiTest.kt | 15 +- .../domain/DomainVerificationPackageTest.kt | 47 +- .../DomainVerificationSettingsMutationTest.kt | 13 +- .../domain/DomainVerificationTestUtils.kt | 57 -- ...inVerificationUserSelectionOverrideTest.kt | 15 +- .../src/com/android/server/pm/MockSystem.kt | 2 +- .../server/pm/SharedLibrariesImplTest.kt | 24 +- .../server/pm/SuspendPackageHelperTest.kt | 87 +- .../pm/PackageManagerSettingsTests.java | 29 +- 28 files changed, 986 insertions(+), 1338 deletions(-) delete mode 100644 services/core/java/android/content/pm/PackageSettingsSnapshotProvider.java delete mode 100644 services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationTestUtils.kt diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index 09ef03c38188b..111bd340a3d1c 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -67,7 +67,7 @@ import java.util.function.Consumer; * * @hide Only for use within the system server. */ -public abstract class PackageManagerInternal implements PackageSettingsSnapshotProvider { +public abstract class PackageManagerInternal { @IntDef(prefix = "PACKAGE_", value = { PACKAGE_SYSTEM, PACKAGE_SETUP_WIZARD, diff --git a/services/core/java/android/content/pm/PackageSettingsSnapshotProvider.java b/services/core/java/android/content/pm/PackageSettingsSnapshotProvider.java deleted file mode 100644 index 221f172c34630..0000000000000 --- a/services/core/java/android/content/pm/PackageSettingsSnapshotProvider.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 android.content.pm; - -import android.annotation.NonNull; - -import com.android.internal.util.FunctionalUtils; -import com.android.server.pm.PackageManagerService; -import com.android.server.pm.PackageSetting; -import com.android.server.pm.pkg.PackageStateInternal; - -import java.util.function.Consumer; -import java.util.function.Function; - -/** @hide */ -public interface PackageSettingsSnapshotProvider { - - /** - * Run a function block that requires access to {@link PackageStateInternal} data. This will - * ensure the {@link PackageManagerService} lock is taken before any caller's internal lock - * to avoid deadlock. Note that this method may or may not lock. If a snapshot is available - * and valid, it will iterate the snapshot set of data. - */ - void withPackageSettingsSnapshot( - @NonNull Consumer> block); - - /** - * Variant which returns a value to the caller. - * @see #withPackageSettingsSnapshot(Consumer) - */ - Output withPackageSettingsSnapshotReturning( - @NonNull FunctionalUtils.ThrowingFunction, - Output> block); - - /** - * Variant which throws. - * @see #withPackageSettingsSnapshot(Consumer) - */ - void withPackageSettingsSnapshotThrowing( - @NonNull FunctionalUtils.ThrowingCheckedConsumer, - ExceptionType> block) throws ExceptionType; - - /** - * Variant which throws 2 exceptions. - * @see #withPackageSettingsSnapshot(Consumer) - */ - void - withPackageSettingsSnapshotThrowing2( - @NonNull FunctionalUtils.ThrowingChecked2Consumer< - Function, - ExceptionOne, ExceptionTwo> block) - throws ExceptionOne, ExceptionTwo; - - /** - * Variant which returns a value to the caller and throws. - * @see #withPackageSettingsSnapshot(Consumer) - */ - Output - withPackageSettingsSnapshotReturningThrowing( - @NonNull FunctionalUtils.ThrowingCheckedFunction< - Function, Output, ExceptionType> block) - throws ExceptionType; -} diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 9e87898a7491d..30ac1b85e7c33 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -3134,8 +3134,8 @@ public class ComputerEngine implements Computer { writer.println("Domain verification status:"); writer.increaseIndent(); try { - mDomainVerificationManager.printState(writer, packageName, - UserHandle.USER_ALL, mSettings::getPackage); + mDomainVerificationManager.printState(this, writer, packageName, + UserHandle.USER_ALL); } catch (Exception e) { pw.println("Failure printing domain verification information"); Slog.e(TAG, "Failure printing domain verification information", e); diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index 3220b31711782..58f9bb2c1902b 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -453,7 +453,8 @@ final class DeletePackageHelper { } for (final int affectedUserId : affectedUserIds) { if (hadSuspendAppsPermission.get(affectedUserId)) { - mPm.unsuspendForSuspendingPackage(packageName, affectedUserId); + mPm.unsuspendForSuspendingPackage(mPm.snapshotComputer(), packageName, + affectedUserId); mPm.removeAllDistractingPackageRestrictions(affectedUserId); } } diff --git a/services/core/java/com/android/server/pm/DomainVerificationConnection.java b/services/core/java/com/android/server/pm/DomainVerificationConnection.java index d24435e12593c..db8c6dc60b5ee 100644 --- a/services/core/java/com/android/server/pm/DomainVerificationConnection.java +++ b/services/core/java/com/android/server/pm/DomainVerificationConnection.java @@ -26,17 +26,12 @@ import android.os.Binder; import android.os.Message; import android.os.UserHandle; -import com.android.internal.util.FunctionalUtils; import com.android.server.DeviceIdleInternal; import com.android.server.pm.parsing.pkg.AndroidPackage; -import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.verify.domain.DomainVerificationService; import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV1; import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV2; -import java.util.function.Consumer; -import java.util.function.Function; - public final class DomainVerificationConnection implements DomainVerificationService.Connection, DomainVerificationProxyV1.Connection, DomainVerificationProxyV2.Connection { final PackageManagerService mPm; @@ -111,42 +106,8 @@ public final class DomainVerificationConnection implements DomainVerificationSer return mUmInternal.exists(userId); } - @Override - public void withPackageSettingsSnapshot( - @NonNull Consumer> block) { - mPmInternal.withPackageSettingsSnapshot(block); - } - - @Override - public Output withPackageSettingsSnapshotReturning( - @NonNull FunctionalUtils.ThrowingFunction, - Output> block) { - return mPmInternal.withPackageSettingsSnapshotReturning(block); - } - - @Override - public void withPackageSettingsSnapshotThrowing( - @NonNull FunctionalUtils.ThrowingCheckedConsumer, - ExceptionType> block) throws ExceptionType { - mPmInternal.withPackageSettingsSnapshotThrowing(block); - } - - @Override - public void - withPackageSettingsSnapshotThrowing2( - @NonNull FunctionalUtils.ThrowingChecked2Consumer< - Function, ExceptionOne, - ExceptionTwo> block) - throws ExceptionOne, ExceptionTwo { - mPmInternal.withPackageSettingsSnapshotThrowing2(block); - } - - @Override - public Output - withPackageSettingsSnapshotReturningThrowing( - @NonNull FunctionalUtils.ThrowingCheckedFunction< - Function, Output, ExceptionType> block) - throws ExceptionType { - return mPmInternal.withPackageSettingsSnapshotReturningThrowing(block); + @NonNull + public Computer snapshot() { + return (Computer) mPmInternal.snapshot(); } } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 234a2309d76b4..c09c904ff9317 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -36,7 +36,6 @@ import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_RESTORE; import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_SETUP; import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN; -import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD; import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4; import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile; import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED; @@ -145,6 +144,7 @@ import com.android.internal.content.F2fsUtils; import com.android.internal.content.InstallLocationUtils; import com.android.internal.security.VerityUtils; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.CollectionUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.server.EventLogTags; import com.android.server.pm.dex.ArtManagerService; @@ -2563,7 +2563,9 @@ final class InstallPackageHelper { Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); synchronized (mPm.mLock) { - size = mPm.mPendingBroadcasts.size(); + final SparseArray>> userIdToPackagesToComponents = + mPm.mPendingBroadcasts.copiedMap(); + size = userIdToPackagesToComponents.size(); if (size <= 0) { // Nothing to be done. Just return return; @@ -2573,11 +2575,11 @@ final class InstallPackageHelper { uids = new int[size]; int i = 0; // filling out the above arrays - for (int n = 0; n < mPm.mPendingBroadcasts.userIdCount(); n++) { - final int packageUserId = mPm.mPendingBroadcasts.userIdAt(n); + for (int n = 0; n < size; n++) { + final int packageUserId = userIdToPackagesToComponents.keyAt(n); final ArrayMap> componentsToBroadcast = - mPm.mPendingBroadcasts.packagesForUserId(packageUserId); - final int numComponents = componentsToBroadcast.size(); + userIdToPackagesToComponents.valueAt(n); + final int numComponents = CollectionUtils.size(componentsToBroadcast); for (int index = 0; i < size && index < numComponents; index++) { packages[i] = componentsToBroadcast.keyAt(index); components[i] = componentsToBroadcast.valueAt(index); diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java index 46e2aa3ff841e..b028a2cef2a56 100644 --- a/services/core/java/com/android/server/pm/PackageHandler.java +++ b/services/core/java/com/android/server/pm/PackageHandler.java @@ -382,6 +382,7 @@ final class PackageHandler extends Handler { case PRUNE_UNUSED_STATIC_SHARED_LIBRARIES: { try { mPm.mInjector.getSharedLibrariesImpl().pruneUnusedStaticSharedLibraries( + mPm.snapshotComputer(), Long.MAX_VALUE, Settings.Global.getLong(mPm.mContext.getContentResolver(), Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD, diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0b7a6a7cec458..c05faf14cae40 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -293,7 +293,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import java.util.function.Function; /** * Keep track of all those APKs everywhere. @@ -1898,7 +1897,8 @@ public class PackageManagerService extends IPackageManager.Stub t.traceEnd(); t.traceBegin("read user settings"); - mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers( + mFirstBoot = !mSettings.readLPw(mLiveComputer, + mInjector.getUserManagerInternal().getUsers( /* excludePartial= */ true, /* excludeDying= */ false, /* excludePreCreated= */ false)); @@ -2841,8 +2841,9 @@ public class PackageManagerService extends IPackageManager.Stub } if (file.getUsableSpace() >= bytes) return; + Computer computer = snapshotComputer(); // 5. Consider shared libraries with refcount=0 and age>min cache period - if (internalVolume && mSharedLibraries.pruneUnusedStaticSharedLibraries(bytes, + if (internalVolume && mSharedLibraries.pruneUnusedStaticSharedLibraries(computer, bytes, android.provider.Settings.Global.getLong(mContext.getContentResolver(), Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD, FREE_STORAGE_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD))) { @@ -2854,14 +2855,12 @@ public class PackageManagerService extends IPackageManager.Stub // 7. Consider installed instant apps unused longer than min cache period if (internalVolume) { - if (executeWithConsistentComputerReturning(computer -> - mInstantAppRegistry.pruneInstalledInstantApps(computer, bytes, - android.provider.Settings.Global.getLong( - mContext.getContentResolver(), - Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, - InstantAppRegistry - .DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) - ) { + if (mInstantAppRegistry.pruneInstalledInstantApps(computer, bytes, + android.provider.Settings.Global.getLong( + mContext.getContentResolver(), + Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, + InstantAppRegistry + .DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) { return; } } @@ -2881,14 +2880,12 @@ public class PackageManagerService extends IPackageManager.Stub // 10. Consider instant meta-data (uninstalled apps) older that min cache period if (internalVolume) { - if (executeWithConsistentComputerReturning(computer -> - mInstantAppRegistry.pruneUninstalledInstantApps(computer, bytes, - android.provider.Settings.Global.getLong( - mContext.getContentResolver(), - Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, - InstantAppRegistry - .DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) - ) { + if (mInstantAppRegistry.pruneUninstalledInstantApps(computer, bytes, + android.provider.Settings.Global.getLong( + mContext.getContentResolver(), + Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, + InstantAppRegistry + .DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) { return; } } @@ -3493,8 +3490,8 @@ public class PackageManagerService extends IPackageManager.Stub enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */, false /* checkShell */, "getEphemeralApplications"); - List instantApps = executeWithConsistentComputerReturning(computer -> - mInstantAppRegistry.getInstantApps(computer, userId)); + Computer computer = snapshotComputer(); + List instantApps = mInstantAppRegistry.getInstantApps(computer, userId); if (instantApps != null) { return new ParceledListSlice<>(instantApps); } @@ -3710,13 +3707,13 @@ public class PackageManagerService extends IPackageManager.Stub public void notifyPackageUse(String packageName, int reason) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - boolean notify = executeWithConsistentComputerReturning(computer -> { - if (getInstantAppPackageName(callingUid) != null) { - return isCallerSameApp(packageName, callingUid); - } else { - return !isInstantAppInternal(packageName, callingUserId, Process.SYSTEM_UID); - } - }); + Computer computer = snapshotComputer(); + final boolean notify; + if (getInstantAppPackageName(callingUid) != null) { + notify = isCallerSameApp(packageName, callingUid); + } else { + notify = !isInstantAppInternal(packageName, callingUserId, Process.SYSTEM_UID); + } if (!notify) { return; } @@ -4255,34 +4252,33 @@ public class PackageManagerService extends IPackageManager.Stub final List unactionedPackages = new ArrayList<>(packageNames.length); ArraySet changesToCommit = new ArraySet<>(); - executeWithConsistentComputer(computer -> { - final boolean[] canRestrict = (restrictionFlags != 0) - ? mSuspendPackageHelper.canSuspendPackageForUser(computer, packageNames, userId, - callingUid) : null; - for (int i = 0; i < packageNames.length; i++) { - final String packageName = packageNames[i]; - final PackageStateInternal packageState = - computer.getPackageStateInternal(packageName); - if (packageState == null - || shouldFilterApplication(packageState, callingUid, userId)) { - Slog.w(TAG, "Could not find package setting for package: " + packageName - + ". Skipping..."); - unactionedPackages.add(packageName); - continue; - } - if (canRestrict != null && !canRestrict[i]) { - unactionedPackages.add(packageName); - continue; - } - final int oldDistractionFlags = packageState.getUserStateOrDefault(userId) - .getDistractionFlags(); - if (restrictionFlags != oldDistractionFlags) { - changedPackagesList.add(packageName); - changedUids.add(UserHandle.getUid(userId, packageState.getAppId())); - changesToCommit.add(packageName); - } + Computer computer = snapshotComputer(); + final boolean[] canRestrict = (restrictionFlags != 0) + ? mSuspendPackageHelper.canSuspendPackageForUser(computer, packageNames, userId, + callingUid) : null; + for (int i = 0; i < packageNames.length; i++) { + final String packageName = packageNames[i]; + final PackageStateInternal packageState = + computer.getPackageStateInternal(packageName); + if (packageState == null + || computer.shouldFilterApplication(packageState, callingUid, userId)) { + Slog.w(TAG, "Could not find package setting for package: " + packageName + + ". Skipping..."); + unactionedPackages.add(packageName); + continue; } - }); + if (canRestrict != null && !canRestrict[i]) { + unactionedPackages.add(packageName); + continue; + } + final int oldDistractionFlags = packageState.getUserStateOrDefault(userId) + .getDistractionFlags(); + if (restrictionFlags != oldDistractionFlags) { + changedPackagesList.add(packageName); + changedUids.add(UserHandle.getUid(userId, packageState.getAppId())); + changesToCommit.add(packageName); + } + } commitPackageStateMutation(null, mutator -> { final int size = changesToCommit.size(); @@ -4341,8 +4337,9 @@ public class PackageManagerService extends IPackageManager.Stub final int callingUid = Binder.getCallingUid(); enforceCanSetPackagesSuspendedAsUser(callingPackage, callingUid, userId, "setPackagesSuspendedAsUser"); - return mSuspendPackageHelper.setPackagesSuspended(packageNames, suspended, appExtras, - launcherExtras, dialogInfo, callingPackage, userId, callingUid); + return mSuspendPackageHelper.setPackagesSuspended(snapshotComputer(), packageNames, + suspended, appExtras, launcherExtras, dialogInfo, callingPackage, userId, + callingUid); } @Override @@ -4361,11 +4358,12 @@ public class PackageManagerService extends IPackageManager.Stub return mComputer.isPackageSuspendedForUser(packageName, userId); } - void unsuspendForSuspendingPackage(String suspendingPackage, int userId) { + void unsuspendForSuspendingPackage(@NonNull Computer computer, String suspendingPackage, + @UserIdInt int userId) { // TODO: This can be replaced by a special parameter to iterate all packages, rather than // this weird pre-collect of all packages. - final String[] allPackages = getPackageStates().keySet().toArray(new String[0]); - mSuspendPackageHelper.removeSuspensionsBySuspendingPackage( + final String[] allPackages = computer.getPackageStates().keySet().toArray(new String[0]); + mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(computer, allPackages, suspendingPackage::equals, userId); } @@ -4424,7 +4422,7 @@ public class PackageManagerService extends IPackageManager.Stub throw new SecurityException("Calling uid " + callingUid + " cannot query getUnsuspendablePackagesForUser for user " + userId); } - return mSuspendPackageHelper.getUnsuspendablePackagesForUser( + return mSuspendPackageHelper.getUnsuspendablePackagesForUser(snapshotComputer(), packageNames, userId, callingUid); } @@ -4625,7 +4623,7 @@ public class PackageManagerService extends IPackageManager.Stub return true; }; PackageStateMutator.InitialState initialState = recordInitialState(); - boolean allowed = executeWithConsistentComputerReturningThrowing(implementation); + boolean allowed = implementation.apply(snapshotComputer()); if (allowed) { // TODO: Need to lock around here to handle mSettings.addInstallerPackageNames, // should find an alternative which avoids any race conditions @@ -4635,7 +4633,7 @@ public class PackageManagerService extends IPackageManager.Stub targetPackage, state -> state.setInstaller(installerPackageName)); if (result.isPackagesChanged() || result.isStateChanged()) { synchronized (mPackageStateWriteLock) { - allowed = executeWithConsistentComputerReturningThrowing(implementation); + allowed = implementation.apply(snapshotComputer()); if (allowed) { commitPackageStateMutation(null, targetPackage, state -> state.setInstaller(installerPackageName)); @@ -4685,12 +4683,12 @@ public class PackageManagerService extends IPackageManager.Stub } }; - PackageStateMutator.Result result = executeWithConsistentComputerReturning(implementation); + PackageStateMutator.Result result = implementation.apply(snapshotComputer()); if (result != null && result.isStateChanged() && !result.isSpecificPackageNull()) { // TODO: Specific return value of what state changed? // The installer on record might have changed, retry with lock synchronized (mPackageStateWriteLock) { - result = executeWithConsistentComputerReturning(implementation); + result = implementation.apply(snapshotComputer()); } } @@ -4988,7 +4986,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId) == PERMISSION_GRANTED) { - unsuspendForSuspendingPackage(packageName, userId); + unsuspendForSuspendingPackage(snapshotComputer(), packageName, userId); removeAllDistractingPackageRestrictions(userId); flushPackageRestrictionsAsUserInternalLocked(userId); } @@ -5080,17 +5078,7 @@ public class PackageManagerService extends IPackageManager.Stub updateInstantAppInstallerLocked(packageName); scheduleWritePackageRestrictions(userId); - final ArrayList pendingComponents = mPendingBroadcasts.get(userId, packageName); - if (pendingComponents == null) { - mPendingBroadcasts.put(userId, packageName, updatedComponents); - } else { - for (int i = 0; i < updatedComponents.size(); i++) { - final String updatedComponent = updatedComponents.get(i); - if (!pendingComponents.contains(updatedComponent)) { - pendingComponents.add(updatedComponent); - } - } - } + mPendingBroadcasts.addComponents(userId, packageName, updatedComponents); if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY); } @@ -5278,7 +5266,8 @@ public class PackageManagerService extends IPackageManager.Stub try { try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { TypedXmlSerializer serializer = Xml.resolveSerializer(output); - mDomainVerificationManager.writeSettings(serializer, true, userId); + mDomainVerificationManager.writeSettings(snapshotComputer(), serializer, true, + userId); return output.toByteArray(); } } catch (Exception e) { @@ -5301,7 +5290,7 @@ public class PackageManagerService extends IPackageManager.Stub // User ID input isn't necessary here as it assumes the user integers match and that // the only states inside the backup XML are for the target user. - mDomainVerificationManager.restoreSettings(parser); + mDomainVerificationManager.restoreSettings(snapshotComputer(), parser); input.close(); } catch (Exception e) { if (DEBUG_BACKUP) { @@ -5689,48 +5678,48 @@ public class PackageManagerService extends IPackageManager.Stub int callingUid = Binder.getCallingUid(); String componentPkgName = componentName.getPackageName(); - boolean changed = executeWithConsistentComputerReturning(computer -> { - int componentUid = getPackageUid(componentPkgName, 0, userId); - if (!UserHandle.isSameApp(callingUid, componentUid)) { - throw new SecurityException("The calling UID (" + callingUid + ")" - + " does not match the target UID"); - } + Computer computer = snapshotComputer(); - String allowedCallerPkg = - mContext.getString(R.string.config_overrideComponentUiPackage); - if (TextUtils.isEmpty(allowedCallerPkg)) { - throw new SecurityException( "There is no package defined as allowed to change a " - + "component's label or icon"); - } + int componentUid = computer.getPackageUid(componentPkgName, 0, userId); + if (!UserHandle.isSameApp(callingUid, componentUid)) { + throw new SecurityException("The calling UID (" + callingUid + ")" + + " does not match the target UID"); + } - int allowedCallerUid = getPackageUid(allowedCallerPkg, PackageManager.MATCH_SYSTEM_ONLY, - userId); - if (allowedCallerUid == -1 || !UserHandle.isSameApp(callingUid, allowedCallerUid)) { - throw new SecurityException("The calling UID (" + callingUid + ")" - + " is not allowed to change a component's label or icon"); - } - PackageStateInternal packageState = computer.getPackageStateInternal(componentPkgName); - if (packageState == null || packageState.getPkg() == null - || (!packageState.isSystem() - && !packageState.getTransientState().isUpdatedSystemApp())) { - throw new SecurityException( - "Changing the label is not allowed for " + componentName); - } + String allowedCallerPkg = + mContext.getString(R.string.config_overrideComponentUiPackage); + if (TextUtils.isEmpty(allowedCallerPkg)) { + throw new SecurityException( "There is no package defined as allowed to change a " + + "component's label or icon"); + } - if (!mComponentResolver.componentExists(componentName)) { - throw new IllegalArgumentException("Component " + componentName + " not found"); - } + int allowedCallerUid = computer.getPackageUid(allowedCallerPkg, + PackageManager.MATCH_SYSTEM_ONLY, userId); + if (allowedCallerUid == -1 || !UserHandle.isSameApp(callingUid, allowedCallerUid)) { + throw new SecurityException("The calling UID (" + callingUid + ")" + + " is not allowed to change a component's label or icon"); + } + PackageStateInternal packageState = computer.getPackageStateInternal(componentPkgName); + if (packageState == null || packageState.getPkg() == null + || (!packageState.isSystem() + && !packageState.getTransientState().isUpdatedSystemApp())) { + throw new SecurityException( + "Changing the label is not allowed for " + componentName); + } - Pair overrideLabelIcon = packageState.getUserStateOrDefault(userId) - .getOverrideLabelIconForComponent(componentName); + if (!computer.getComponentResolver().componentExists(componentName)) { + throw new IllegalArgumentException("Component " + componentName + " not found"); + } - String existingLabel = overrideLabelIcon == null ? null : overrideLabelIcon.first; - Integer existingIcon = overrideLabelIcon == null ? null : overrideLabelIcon.second; + Pair overrideLabelIcon = packageState.getUserStateOrDefault(userId) + .getOverrideLabelIconForComponent(componentName); - return !TextUtils.equals(existingLabel, nonLocalizedLabel) - || !Objects.equals(existingIcon, icon); - }); - if (!changed) { + String existingLabel = overrideLabelIcon == null ? null : overrideLabelIcon.first; + Integer existingIcon = overrideLabelIcon == null ? null : overrideLabelIcon.second; + + if (TextUtils.equals(existingLabel, nonLocalizedLabel) + && Objects.equals(existingIcon, icon)) { + // Nothing changed return; } @@ -5738,16 +5727,7 @@ public class PackageManagerService extends IPackageManager.Stub state -> state.userState(userId) .setComponentLabelIcon(componentName, nonLocalizedLabel, icon)); - ArrayList components = mPendingBroadcasts.get(userId, componentPkgName); - if (components == null) { - components = new ArrayList<>(); - mPendingBroadcasts.put(userId, componentPkgName, components); - } - - String className = componentName.getClassName(); - if (!components.contains(className)) { - components.add(className); - } + mPendingBroadcasts.addComponent(userId, componentPkgName, componentName.getClassName()); if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY); @@ -5956,6 +5936,7 @@ public class PackageManagerService extends IPackageManager.Stub // packageName -> list of components to send broadcasts now final ArrayMap> sendNowBroadcasts = new ArrayMap<>(targetSize); synchronized (mLock) { + Computer computer = snapshotComputer(); boolean scheduleBroadcastMessage = false; boolean isSynchronous = false; boolean anyChanged = false; @@ -5967,8 +5948,8 @@ public class PackageManagerService extends IPackageManager.Stub // update enabled settings final ComponentEnabledSetting setting = settings.get(i); final String packageName = setting.getPackageName(); - if (!setEnabledSettingInternalLocked(pkgSettings.get(packageName), setting, - userId, callingPackage)) { + if (!setEnabledSettingInternalLocked(computer, pkgSettings.get(packageName), + setting, userId, callingPackage)) { continue; } anyChanged = true; @@ -5979,26 +5960,18 @@ public class PackageManagerService extends IPackageManager.Stub // collect broadcast list for the package final String componentName = setting.isComponent() ? setting.getClassName() : packageName; - ArrayList componentList = sendNowBroadcasts.get(packageName); - if (componentList == null) { - componentList = mPendingBroadcasts.get(userId, packageName); - } - final boolean newPackage = componentList == null; - if (newPackage) { - componentList = new ArrayList<>(); - } - if (!componentList.contains(componentName)) { - componentList.add(componentName); - } if ((setting.getEnabledFlags() & PackageManager.DONT_KILL_APP) == 0) { + ArrayList componentList = sendNowBroadcasts.get(packageName); + componentList = componentList == null ? new ArrayList<>() : componentList; + if (!componentList.contains(componentName)) { + componentList.add(componentName); + } sendNowBroadcasts.put(packageName, componentList); // Purge entry from pending broadcast list if another one exists already // since we are sending one right away. mPendingBroadcasts.remove(userId, packageName); } else { - if (newPackage) { - mPendingBroadcasts.put(userId, packageName, componentList); - } + mPendingBroadcasts.addComponent(userId, packageName, componentName); scheduleBroadcastMessage = true; } } @@ -6041,8 +6014,9 @@ public class PackageManagerService extends IPackageManager.Stub } } - private boolean setEnabledSettingInternalLocked(PackageSetting pkgSetting, - ComponentEnabledSetting setting, int userId, String callingPackage) { + private boolean setEnabledSettingInternalLocked(@NonNull Computer computer, + PackageSetting pkgSetting, ComponentEnabledSetting setting, @UserIdInt int userId, + String callingPackage) { final int newState = setting.getEnabledState(); final String packageName = setting.getPackageName(); boolean success = false; @@ -6061,7 +6035,7 @@ public class PackageManagerService extends IPackageManager.Stub // This app should not generally be allowed to get disabled by the UI, but // if it ever does, we don't want to end up with some of the user's apps // permanently suspended. - unsuspendForSuspendingPackage(packageName, userId); + unsuspendForSuspendingPackage(computer, packageName, userId); removeAllDistractingPackageRestrictions(userId); } success = true; @@ -6152,11 +6126,8 @@ public class PackageManagerService extends IPackageManager.Stub public void setPackageStoppedState(String packageName, boolean stopped, int userId) { if (!mUserManager.exists(userId)) return; final int callingUid = Binder.getCallingUid(); - Pair wasNotLaunchedAndInstallerPackageName = - executeWithConsistentComputerReturningThrowing(computer -> { - if (computer.getInstantAppPackageName(callingUid) != null) { - return null; - } + final Computer computer = snapshotComputer(); + if (computer.getInstantAppPackageName(callingUid) == null) { final int permission = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); @@ -6171,36 +6142,30 @@ public class PackageManagerService extends IPackageManager.Stub true /* requireFullPermission */, true /* checkShell */, "stop package"); final PackageStateInternal packageState = computer.getPackageStateInternal(packageName); - final PackageUserState PackageUserState = packageState == null + final PackageUserState packageUserState = packageState == null ? null : packageState.getUserStateOrDefault(userId); - if (packageState == null - || computer.shouldFilterApplication(packageState, callingUid, userId) - || PackageUserState.isStopped() == stopped) { - return null; - } + if (packageState != null + && !computer.shouldFilterApplication(packageState, callingUid, userId) + && packageUserState.isStopped() != stopped) { + boolean wasNotLaunched = packageUserState.isNotLaunched(); + commitPackageStateMutation(null, packageName, state -> { + PackageUserStateWrite userState = state.userState(userId); + userState.setStopped(stopped); + if (wasNotLaunched) { + userState.setNotLaunched(false); + } + }); - return Pair.create(PackageUserState.isNotLaunched(), - packageState.getInstallSource().installerPackageName); - }); - if (wasNotLaunchedAndInstallerPackageName != null) { - boolean wasNotLaunched = wasNotLaunchedAndInstallerPackageName.first; - - commitPackageStateMutation(null, packageName, packageState -> { - PackageUserStateWrite userState = packageState.userState(userId); - userState.setStopped(stopped); if (wasNotLaunched) { - userState.setNotLaunched(false); + final String installerPackageName = + packageState.getInstallSource().installerPackageName; + if (installerPackageName != null) { + notifyFirstLaunch(packageName, installerPackageName, userId); + } } - }); - if (wasNotLaunched) { - final String installerPackageName = wasNotLaunchedAndInstallerPackageName.second; - if (installerPackageName != null) { - notifyFirstLaunch(packageName, installerPackageName, userId); - } + scheduleWritePackageRestrictions(userId); } - - scheduleWritePackageRestrictions(userId); } // If this would cause the app to leave force-stop, then also make sure to unhibernate the @@ -6687,7 +6652,7 @@ public class PackageManagerService extends IPackageManager.Stub "Only package verification agents can read the verifier device identity"); synchronized (mLock) { - return mSettings.getVerifierDeviceIdentityLPw(); + return mSettings.getVerifierDeviceIdentityLPw(mLiveComputer); } } @@ -7026,15 +6991,16 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void removeAllNonSystemPackageSuspensions(int userId) { - final String[] allPackages = mComputer.getAllAvailablePackageNames(); - mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(allPackages, + final Computer computer = snapshotComputer(); + final String[] allPackages = computer.getAllAvailablePackageNames(); + mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(computer, allPackages, (suspendingPackage) -> !PLATFORM_PACKAGE_NAME.equals(suspendingPackage), userId); } @Override public void removeNonSystemPackageSuspensions(String packageName, int userId) { - mSuspendPackageHelper.removeSuspensionsBySuspendingPackage( + mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(snapshotComputer(), new String[]{packageName}, (suspendingPackage) -> !PLATFORM_PACKAGE_NAME.equals(suspendingPackage), userId); @@ -7233,29 +7199,29 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void grantImplicitAccess(int userId, Intent intent, int recipientAppId, int visibleUid, boolean direct, boolean retainOnUpdate) { - boolean accessGranted = executeWithConsistentComputerReturning(computer -> { - final AndroidPackage visiblePackage = computer.getPackage(visibleUid); - final int recipientUid = UserHandle.getUid(userId, recipientAppId); - if (visiblePackage == null || computer.getPackage(recipientUid) == null) { - return false; - } + Computer computer = snapshotComputer(); + final AndroidPackage visiblePackage = computer.getPackage(visibleUid); + final int recipientUid = UserHandle.getUid(userId, recipientAppId); + if (visiblePackage == null || computer.getPackage(recipientUid) == null) { + return; + } - final boolean instantApp = computer.isInstantAppInternal( - visiblePackage.getPackageName(), userId, visibleUid); - if (instantApp) { - if (!direct) { - // if the interaction that lead to this granting access to an instant app - // was indirect (i.e.: URI permission grant), do not actually execute the - // grant. - return false; - } - return mInstantAppRegistry.grantInstantAccess(userId, intent, - recipientAppId, UserHandle.getAppId(visibleUid) /*instantAppId*/); - } else { - return mAppsFilter.grantImplicitAccess(recipientUid, visibleUid, - retainOnUpdate); + final boolean instantApp = computer.isInstantAppInternal( + visiblePackage.getPackageName(), userId, visibleUid); + final boolean accessGranted; + if (instantApp) { + if (!direct) { + // if the interaction that lead to this granting access to an instant app + // was indirect (i.e.: URI permission grant), do not actually execute the + // grant. + return; } - }); + accessGranted = mInstantAppRegistry.grantInstantAccess(userId, intent, + recipientAppId, UserHandle.getAppId(visibleUid) /*instantAppId*/); + } else { + accessGranted = mAppsFilter.grantImplicitAccess(recipientUid, visibleUid, + retainOnUpdate); + } if (accessGranted) { ApplicationPackageManager.invalidateGetPackagesForUidCache(); @@ -7271,8 +7237,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void pruneInstantApps() { - executeWithConsistentComputer(computer -> - mInstantAppRegistry.pruneInstantApps(computer)); + mInstantAppRegistry.pruneInstantApps(snapshotComputer()); } @Override @@ -7680,7 +7645,8 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void unsuspendForSuspendingPackage(final String packageName, int affectedUser) { - PackageManagerService.this.unsuspendForSuspendingPackage(packageName, affectedUser); + PackageManagerService.this.unsuspendForSuspendingPackage(snapshotComputer(), + packageName, affectedUser); } @Override @@ -7743,52 +7709,6 @@ public class PackageManagerService extends IPackageManager.Stub return PackageManagerService.this.deleteOatArtifactsOfPackage(packageName); } - @Override - public void withPackageSettingsSnapshot( - @NonNull Consumer> block) { - executeWithConsistentComputer(computer -> - block.accept(computer::getPackageStateInternal)); - } - - @Override - public Output withPackageSettingsSnapshotReturning( - @NonNull FunctionalUtils.ThrowingFunction, - Output> block) { - return executeWithConsistentComputerReturning(computer -> - block.apply(computer::getPackageStateInternal)); - } - - @Override - public void withPackageSettingsSnapshotThrowing( - @NonNull FunctionalUtils.ThrowingCheckedConsumer, ExceptionType> block) throws ExceptionType { - executeWithConsistentComputerThrowing(computer -> - block.accept(computer::getPackageStateInternal)); - } - - @Override - public void - withPackageSettingsSnapshotThrowing2( - @NonNull FunctionalUtils.ThrowingChecked2Consumer< - Function, ExceptionOne, - ExceptionTwo> block) - throws ExceptionOne, ExceptionTwo { - executeWithConsistentComputerThrowing2( - (FunctionalUtils.ThrowingChecked2Consumer) computer -> block.accept(computer::getPackageStateInternal)); - } - - @Override - public Output - withPackageSettingsSnapshotReturningThrowing( - @NonNull FunctionalUtils.ThrowingCheckedFunction< - Function, Output, - ExceptionType> block) - throws ExceptionType { - return executeWithConsistentComputerReturningThrowing(computer -> - block.apply(computer::getPackageStateInternal)); - } - @Override public void reconcileAppsData(int userId, @StorageManager.StorageFlags int flags, boolean migrateAppsData) { @@ -7834,70 +7754,59 @@ public class PackageManagerService extends IPackageManager.Stub @NonNull Set outUpdatedPackageNames) { synchronized (mOverlayPathsLock) { final ArrayMap> libNameToModifiedDependents = new ArrayMap<>(); - Boolean targetModified = executeWithConsistentComputerReturning(computer -> { - final PackageStateInternal packageState = computer.getPackageStateInternal( - targetPackageName); - final AndroidPackage targetPkg = - packageState == null ? null : packageState.getPkg(); - if (targetPackageName == null || targetPkg == null) { - Slog.e(TAG, "failed to find package " + targetPackageName); - return null; - } - - if (Objects.equals(packageState.getUserStateOrDefault(userId).getOverlayPaths(), - newOverlayPaths)) { - return false; - } - - if (targetPkg.getLibraryNames() != null) { - // Set the overlay paths for dependencies of the shared library. - for (final String libName : targetPkg.getLibraryNames()) { - ArraySet modifiedDependents = null; - - final SharedLibraryInfo info = computer.getSharedLibraryInfo(libName, - SharedLibraryInfo.VERSION_UNDEFINED); - if (info == null) { - continue; - } - final List dependents = computer - .getPackagesUsingSharedLibrary(info, 0, Process.SYSTEM_UID, userId); - if (dependents == null) { - continue; - } - for (final VersionedPackage dependent : dependents) { - final PackageStateInternal dependentState = - computer.getPackageStateInternal(dependent.getPackageName()); - if (dependentState == null) { - continue; - } - if (!Objects.equals(dependentState.getUserStateOrDefault(userId) - .getSharedLibraryOverlayPaths() - .get(libName), newOverlayPaths)) { - String dependentPackageName = dependent.getPackageName(); - modifiedDependents = ArrayUtils.add(modifiedDependents, - dependentPackageName); - outUpdatedPackageNames.add(dependentPackageName); - } - } - - if (modifiedDependents != null) { - libNameToModifiedDependents.put(libName, modifiedDependents); - } - } - } - - outUpdatedPackageNames.add(targetPackageName); - return true; - }); - - if (targetModified == null) { - // Null indicates error + Computer computer = snapshotComputer(); + final PackageStateInternal packageState = computer.getPackageStateInternal( + targetPackageName); + final AndroidPackage targetPkg = packageState == null ? null : packageState.getPkg(); + if (targetPackageName == null || targetPkg == null) { + Slog.e(TAG, "failed to find package " + targetPackageName); return false; - } else if (!targetModified) { - // Treat non-modification as a successful commit + } + + if (Objects.equals(packageState.getUserStateOrDefault(userId).getOverlayPaths(), + newOverlayPaths)) { return true; } + if (targetPkg.getLibraryNames() != null) { + // Set the overlay paths for dependencies of the shared library. + for (final String libName : targetPkg.getLibraryNames()) { + ArraySet modifiedDependents = null; + + final SharedLibraryInfo info = computer.getSharedLibraryInfo(libName, + SharedLibraryInfo.VERSION_UNDEFINED); + if (info == null) { + continue; + } + final List dependents = computer + .getPackagesUsingSharedLibrary(info, 0, Process.SYSTEM_UID, userId); + if (dependents == null) { + continue; + } + for (final VersionedPackage dependent : dependents) { + final PackageStateInternal dependentState = + computer.getPackageStateInternal(dependent.getPackageName()); + if (dependentState == null) { + continue; + } + if (!Objects.equals(dependentState.getUserStateOrDefault(userId) + .getSharedLibraryOverlayPaths() + .get(libName), newOverlayPaths)) { + String dependentPackageName = dependent.getPackageName(); + modifiedDependents = ArrayUtils.add(modifiedDependents, + dependentPackageName); + outUpdatedPackageNames.add(dependentPackageName); + } + } + + if (modifiedDependents != null) { + libNameToModifiedDependents.put(libName, modifiedDependents); + } + } + } + + outUpdatedPackageNames.add(targetPackageName); + commitPackageStateMutation(null, mutator -> { mutator.forPackage(targetPackageName) .userState(userId) @@ -8062,36 +7971,6 @@ public class PackageManagerService extends IPackageManager.Stub forEachPackageState(mComputer.getPackageStates(), actionWrapped); } - // TODO: Make private - void executeWithConsistentComputer( - @NonNull FunctionalUtils.ThrowingConsumer consumer) { - consumer.accept(snapshotComputer()); - } - - private T executeWithConsistentComputerReturning( - @NonNull FunctionalUtils.ThrowingFunction function) { - return function.apply(snapshotComputer()); - } - - private void executeWithConsistentComputerThrowing( - @NonNull FunctionalUtils.ThrowingCheckedConsumer consumer) - throws ExceptionType { - consumer.accept(snapshotComputer()); - } - - private void - executeWithConsistentComputerThrowing2( - @NonNull FunctionalUtils.ThrowingChecked2Consumer consumer) throws ExceptionOne, ExceptionTwo { - consumer.accept(snapshotComputer()); - } - - private T executeWithConsistentComputerReturningThrowing( - @NonNull FunctionalUtils.ThrowingCheckedFunction function) - throws ExceptionType { - return function.apply(snapshotComputer()); - } - boolean isHistoricalPackageUsageAvailable() { return mPackageUsage.isHistoricalPackageUsageAvailable(); } @@ -8357,7 +8236,7 @@ public class PackageManagerService extends IPackageManager.Stub */ void writeSettingsLPrTEMP() { mPermissionManager.writeLegacyPermissionsTEMP(mSettings.mPermissions); - mSettings.writeLPr(); + mSettings.writeLPr(mLiveComputer); } @Override @@ -8856,7 +8735,6 @@ public class PackageManagerService extends IPackageManager.Stub } void notifyInstantAppPackageInstalled(String packageName, int[] newUsers) { - executeWithConsistentComputer(computer -> - mInstantAppRegistry.onPackageInstalled(computer, packageName, newUsers)); + mInstantAppRegistry.onPackageInstalled(snapshotComputer(), packageName, newUsers); } } diff --git a/services/core/java/com/android/server/pm/PendingPackageBroadcasts.java b/services/core/java/com/android/server/pm/PendingPackageBroadcasts.java index 4e9a06a329a7b..6e2f756cad27b 100644 --- a/services/core/java/com/android/server/pm/PendingPackageBroadcasts.java +++ b/services/core/java/com/android/server/pm/PendingPackageBroadcasts.java @@ -16,12 +16,17 @@ package com.android.server.pm; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.util.ArrayMap; import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; +import java.util.List; /** * Set of pending broadcasts for aggregating enable/disable of components. @@ -29,65 +34,111 @@ import java.util.ArrayList; @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public final class PendingPackageBroadcasts { + private final Object mLock = new PackageManagerTracedLock(); + // for each user id, a map of components within that package> + @GuardedBy("mLock") final SparseArray>> mUidMap; public PendingPackageBroadcasts() { mUidMap = new SparseArray<>(2); } - public ArrayList get(int userId, String packageName) { - ArrayMap> packages = getOrAllocate(userId); - return packages.get(packageName); + public boolean hasPackage(@UserIdInt int userId, @NonNull String packageName) { + synchronized (mLock) { + final ArrayMap> packages = mUidMap.get(userId); + return packages != null && packages.containsKey(packageName); + } } public void put(int userId, String packageName, ArrayList components) { - ArrayMap> packages = getOrAllocate(userId); - packages.put(packageName, components); + synchronized (mLock) { + ArrayMap> packages = getOrAllocate(userId); + packages.put(packageName, components); + } + } + + public void addComponent(@UserIdInt int userId, @NonNull String packageName, + @NonNull String componentClassName) { + synchronized (mLock) { + ArrayList components = getOrAllocate(userId, packageName); + if (!components.contains(componentClassName)) { + components.add(componentClassName); + } + } + } + + public void addComponents(@UserIdInt int userId, @NonNull String packageName, + @NonNull List componentClassNames) { + synchronized (mLock) { + ArrayList components = getOrAllocate(userId, packageName); + for (int index = 0; index < componentClassNames.size(); index++) { + String componentClassName = componentClassNames.get(index); + if (!components.contains(componentClassName)) { + components.add(componentClassName); + } + } + } } public void remove(int userId, String packageName) { - ArrayMap> packages = mUidMap.get(userId); - if (packages != null) { - packages.remove(packageName); + synchronized (mLock) { + ArrayMap> packages = mUidMap.get(userId); + if (packages != null) { + packages.remove(packageName); + } } } public void remove(int userId) { - mUidMap.remove(userId); - } - - public int userIdCount() { - return mUidMap.size(); - } - - public int userIdAt(int n) { - return mUidMap.keyAt(n); - } - - public ArrayMap> packagesForUserId(int userId) { - return mUidMap.get(userId); - } - - public int size() { - // total number of pending broadcast entries across all userIds - int num = 0; - for (int i = 0; i < mUidMap.size(); i++) { - num += mUidMap.valueAt(i).size(); + synchronized (mLock) { + mUidMap.remove(userId); + } + } + + @Nullable + public SparseArray>> copiedMap() { + synchronized (mLock) { + SparseArray>> copy = new SparseArray<>(); + for (int userIdIndex = 0; userIdIndex < mUidMap.size(); userIdIndex++) { + final ArrayMap> packages = mUidMap.valueAt(userIdIndex); + ArrayMap> packagesCopy = new ArrayMap<>(); + for (int packagesIndex = 0; packagesIndex < packages.size(); packagesIndex++) { + packagesCopy.put(packages.keyAt(packagesIndex), + new ArrayList<>(packages.valueAt(packagesIndex))); + } + copy.put(mUidMap.keyAt(userIdIndex), packagesCopy); + } + return copy; } - return num; } public void clear() { - mUidMap.clear(); + synchronized (mLock) { + mUidMap.clear(); + } } private ArrayMap> getOrAllocate(int userId) { - ArrayMap> map = mUidMap.get(userId); - if (map == null) { - map = new ArrayMap<>(); - mUidMap.put(userId, map); + synchronized (mLock) { + ArrayMap> map = mUidMap.get(userId); + if (map == null) { + map = new ArrayMap<>(); + mUidMap.put(userId, map); + } + return map; + } + } + + private ArrayList getOrAllocate(int userId, @NonNull String packageName) { + synchronized (mLock) { + ArrayMap> map = mUidMap.get(userId); + if (map == null) { + map = new ArrayMap<>(); + mUidMap.put(userId, map); + } + + return map.computeIfAbsent(packageName, k -> new ArrayList<>()); } - return map; } } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 2ad35b7acf504..394c8fb731562 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -2432,7 +2432,7 @@ public final class Settings implements Watchable, Snappable { } } - void writeLPr() { + void writeLPr(@NonNull Computer computer) { //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024); final long startTime = SystemClock.uptimeMillis(); @@ -2524,8 +2524,8 @@ public final class Settings implements Watchable, Snappable { } } - mDomainVerificationManager.writeSettings(serializer, false /* includeSignatures */, - UserHandle.USER_ALL); + mDomainVerificationManager.writeSettings(computer, serializer, + false /* includeSignatures */, UserHandle.USER_ALL); mKeySetManagerService.writeKeySetManagerServiceLPr(serializer); @@ -2967,7 +2967,7 @@ public final class Settings implements Watchable, Snappable { } } - boolean readLPw(@NonNull List users) { + boolean readLPw(@NonNull Computer computer, @NonNull List users) { FileInputStream str = null; if (mBackupSettingsFilename.exists()) { try { @@ -3111,7 +3111,7 @@ public final class Settings implements Watchable, Snappable { ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION); ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT); } else if (tagName.equals(DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) { - mDomainVerificationManager.readSettings(parser); + mDomainVerificationManager.readSettings(computer, parser); } else if (tagName.equals( DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) { mDomainVerificationManager.readLegacySettings(parser); @@ -4287,11 +4287,11 @@ public final class Settings implements Watchable, Snappable { return Process.FIRST_APPLICATION_UID + size; } - public VerifierDeviceIdentity getVerifierDeviceIdentityLPw() { + public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) { if (mVerifierDeviceIdentity == null) { mVerifierDeviceIdentity = VerifierDeviceIdentity.generate(); - writeLPr(); + writeLPr(computer); } return mVerifierDeviceIdentity; diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java index 0638d5eee98b7..3fe079034cf2e 100644 --- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java +++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java @@ -321,7 +321,8 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable * on the device. * @return {@code true} if the available storage space is reached. */ - boolean pruneUnusedStaticSharedLibraries(long neededSpace, long maxCachePeriod) + boolean pruneUnusedStaticSharedLibraries(@NonNull Computer computer, long neededSpace, + long maxCachePeriod) throws IOException { final StorageManager storage = mInjector.getSystemService(StorageManager.class); final File volume = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL); @@ -332,38 +333,36 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable // Important: We skip shared libs used for some user since // in such a case we need to keep the APK on the device. The check for // a lib being used for any user is performed by the uninstall call. - mPm.executeWithConsistentComputer(computer -> { - final WatchedArrayMap> - sharedLibraries = computer.getSharedLibraries(); - final int libCount = sharedLibraries.size(); - for (int i = 0; i < libCount; i++) { - final WatchedLongSparseArray versionedLib = - sharedLibraries.valueAt(i); - if (versionedLib == null) { + final WatchedArrayMap> + sharedLibraries = computer.getSharedLibraries(); + final int libCount = sharedLibraries.size(); + for (int i = 0; i < libCount; i++) { + final WatchedLongSparseArray versionedLib = + sharedLibraries.valueAt(i); + if (versionedLib == null) { + continue; + } + final int versionCount = versionedLib.size(); + for (int j = 0; j < versionCount; j++) { + SharedLibraryInfo libInfo = versionedLib.valueAt(j); + final PackageStateInternal ps = getLibraryPackage(computer, libInfo); + if (ps == null) { continue; } - final int versionCount = versionedLib.size(); - for (int j = 0; j < versionCount; j++) { - SharedLibraryInfo libInfo = versionedLib.valueAt(j); - final PackageStateInternal ps = getLibraryPackage(computer, libInfo); - if (ps == null) { - continue; - } - // Skip unused libs cached less than the min period to prevent pruning a lib - // needed by a subsequently installed package. - if (now - ps.getLastUpdateTime() < maxCachePeriod) { - continue; - } - - if (ps.getPkg().isSystem()) { - continue; - } - - packagesToDelete.add(new VersionedPackage(ps.getPkg().getPackageName(), - libInfo.getDeclaringPackage().getLongVersionCode())); + // Skip unused libs cached less than the min period to prevent pruning a lib + // needed by a subsequently installed package. + if (now - ps.getLastUpdateTime() < maxCachePeriod) { + continue; } + + if (ps.getPkg().isSystem()) { + continue; + } + + packagesToDelete.add(new VersionedPackage(ps.getPkg().getPackageName(), + libInfo.getDeclaringPackage().getLongVersionCode())); } - }); + } final int packageCount = packagesToDelete.size(); for (int i = 0; i < packageCount; i++) { diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java index bd1c9c702bcb5..3ef5599385cec 100644 --- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java +++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java @@ -27,6 +27,7 @@ import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.IActivityManager; import android.content.Intent; @@ -99,10 +100,10 @@ public final class SuspendPackageHelper { * @return The names of failed packages. */ @Nullable - String[] setPackagesSuspended(@Nullable String[] packageNames, boolean suspended, - @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras, - @Nullable SuspendDialogInfo dialogInfo, @NonNull String callingPackage, - int userId, int callingUid) { + String[] setPackagesSuspended(@NonNull Computer computer, @Nullable String[] packageNames, + boolean suspended, @Nullable PersistableBundle appExtras, + @Nullable PersistableBundle launcherExtras, @Nullable SuspendDialogInfo dialogInfo, + @NonNull String callingPackage, @UserIdInt int userId, int callingUid) { if (ArrayUtils.isEmpty(packageNames)) { return packageNames; } @@ -121,62 +122,60 @@ public final class SuspendPackageHelper { ArraySet modifiedPackages = new ArraySet<>(); - mPm.executeWithConsistentComputer(computer -> { - final boolean[] canSuspend = suspended - ? canSuspendPackageForUser(computer, packageNames, userId, callingUid) : null; - for (int i = 0; i < packageNames.length; i++) { - final String packageName = packageNames[i]; - if (callingPackage.equals(packageName)) { - Slog.w(TAG, "Calling package: " + callingPackage + " trying to " - + (suspended ? "" : "un") + "suspend itself. Ignoring"); - unmodifiablePackages.add(packageName); - continue; - } - final PackageStateInternal packageState = - computer.getPackageStateInternal(packageName); - if (packageState == null - || computer.shouldFilterApplication(packageState, callingUid, userId)) { - Slog.w(TAG, "Could not find package setting for package: " + packageName - + ". Skipping suspending/un-suspending."); - unmodifiablePackages.add(packageName); - continue; - } - if (canSuspend != null && !canSuspend[i]) { - unmodifiablePackages.add(packageName); - continue; - } + final boolean[] canSuspend = suspended + ? canSuspendPackageForUser(computer, packageNames, userId, callingUid) : null; + for (int i = 0; i < packageNames.length; i++) { + final String packageName = packageNames[i]; + if (callingPackage.equals(packageName)) { + Slog.w(TAG, "Calling package: " + callingPackage + " trying to " + + (suspended ? "" : "un") + "suspend itself. Ignoring"); + unmodifiablePackages.add(packageName); + continue; + } + final PackageStateInternal packageState = + computer.getPackageStateInternal(packageName); + if (packageState == null + || computer.shouldFilterApplication(packageState, callingUid, userId)) { + Slog.w(TAG, "Could not find package setting for package: " + packageName + + ". Skipping suspending/un-suspending."); + unmodifiablePackages.add(packageName); + continue; + } + if (canSuspend != null && !canSuspend[i]) { + unmodifiablePackages.add(packageName); + continue; + } - final WatchedArrayMap suspendParamsMap = - packageState.getUserStateOrDefault(userId).getSuspendParams(); - if (suspended) { - if (suspendParamsMap != null && suspendParamsMap.containsKey(packageName)) { - final SuspendParams suspendParams = suspendParamsMap.get(packageName); - // Skip if there's no changes - if (suspendParams != null - && Objects.equals(suspendParams.getDialogInfo(), dialogInfo) - && Objects.equals(suspendParams.getAppExtras(), appExtras) - && Objects.equals(suspendParams.getLauncherExtras(), - launcherExtras)) { - // Carried over API behavior, must notify change even if no change - changedPackagesList.add(packageName); - changedUids.add(UserHandle.getUid(userId, packageState.getAppId())); - continue; - } + final WatchedArrayMap suspendParamsMap = + packageState.getUserStateOrDefault(userId).getSuspendParams(); + if (suspended) { + if (suspendParamsMap != null && suspendParamsMap.containsKey(packageName)) { + final SuspendParams suspendParams = suspendParamsMap.get(packageName); + // Skip if there's no changes + if (suspendParams != null + && Objects.equals(suspendParams.getDialogInfo(), dialogInfo) + && Objects.equals(suspendParams.getAppExtras(), appExtras) + && Objects.equals(suspendParams.getLauncherExtras(), + launcherExtras)) { + // Carried over API behavior, must notify change even if no change + changedPackagesList.add(packageName); + changedUids.add(UserHandle.getUid(userId, packageState.getAppId())); + continue; } } - - // If size one, the package will be unsuspended from this call - boolean packageUnsuspended = - !suspended && CollectionUtils.size(suspendParamsMap) <= 1; - if (suspended || packageUnsuspended) { - changedPackagesList.add(packageName); - changedUids.add(UserHandle.getUid(userId, packageState.getAppId())); - } - - modifiedPackages.add(packageName); - modifiedUids.add(UserHandle.getUid(userId, packageState.getAppId())); } - }); + + // If size one, the package will be unsuspended from this call + boolean packageUnsuspended = + !suspended && CollectionUtils.size(suspendParamsMap) <= 1; + if (suspended || packageUnsuspended) { + changedPackagesList.add(packageName); + changedUids.add(UserHandle.getUid(userId, packageState.getAppId())); + } + + modifiedPackages.add(packageName); + modifiedUids.add(UserHandle.getUid(userId, packageState.getAppId())); + } mPm.commitPackageStateMutation(null, mutator -> { final int size = modifiedPackages.size(); @@ -218,29 +217,27 @@ public final class SuspendPackageHelper { * @return The names of packages which are Unsuspendable. */ @NonNull - String[] getUnsuspendablePackagesForUser(@NonNull String[] packageNames, int userId, - int callingUid) { + String[] getUnsuspendablePackagesForUser(@NonNull Computer computer, + @NonNull String[] packageNames, @UserIdInt int userId, int callingUid) { if (!isSuspendAllowedForUser(userId, callingUid)) { Slog.w(TAG, "Cannot suspend due to restrictions on user " + userId); return packageNames; } final ArraySet unactionablePackages = new ArraySet<>(); - mPm.executeWithConsistentComputer(computer -> { - final boolean[] canSuspend = canSuspendPackageForUser(computer, packageNames, userId, - callingUid); - for (int i = 0; i < packageNames.length; i++) { - if (!canSuspend[i]) { - unactionablePackages.add(packageNames[i]); - continue; - } - final PackageStateInternal packageState = - computer.getPackageStateFiltered(packageNames[i], callingUid, userId); - if (packageState == null) { - Slog.w(TAG, "Could not find package setting for package: " + packageNames[i]); - unactionablePackages.add(packageNames[i]); - } + final boolean[] canSuspend = canSuspendPackageForUser(computer, packageNames, userId, + callingUid); + for (int i = 0; i < packageNames.length; i++) { + if (!canSuspend[i]) { + unactionablePackages.add(packageNames[i]); + continue; } - }); + final PackageStateInternal packageState = + computer.getPackageStateFiltered(packageNames[i], callingUid, userId); + if (packageState == null) { + Slog.w(TAG, "Could not find package setting for package: " + packageNames[i]); + unactionablePackages.add(packageNames[i]); + } + } return unactionablePackages.toArray(new String[unactionablePackages.size()]); } @@ -282,45 +279,44 @@ public final class SuspendPackageHelper { * suspensions will be removed. * @param userId The user for which the changes are taking place. */ - void removeSuspensionsBySuspendingPackage(@NonNull String[] packagesToChange, + void removeSuspensionsBySuspendingPackage(@NonNull Computer computer, + @NonNull String[] packagesToChange, @NonNull Predicate suspendingPackagePredicate, int userId) { final List unsuspendedPackages = new ArrayList<>(); final IntArray unsuspendedUids = new IntArray(); final ArrayMap> pkgToSuspendingPkgsToCommit = new ArrayMap<>(); - mPm.executeWithConsistentComputer(computer -> { - for (String packageName : packagesToChange) { - final PackageStateInternal packageState = - computer.getPackageStateInternal(packageName); - final PackageUserStateInternal packageUserState = packageState == null - ? null : packageState.getUserStateOrDefault(userId); - if (packageUserState == null || !packageUserState.isSuspended()) { - continue; - } + for (String packageName : packagesToChange) { + final PackageStateInternal packageState = + computer.getPackageStateInternal(packageName); + final PackageUserStateInternal packageUserState = packageState == null + ? null : packageState.getUserStateOrDefault(userId); + if (packageUserState == null || !packageUserState.isSuspended()) { + continue; + } - WatchedArrayMap suspendParamsMap = - packageUserState.getSuspendParams(); - int countRemoved = 0; - for (int index = 0; index < suspendParamsMap.size(); index++) { - String suspendingPackage = suspendParamsMap.keyAt(index); - if (suspendingPackagePredicate.test(suspendingPackage)) { - ArraySet suspendingPkgsToCommit = - pkgToSuspendingPkgsToCommit.get(packageName); - if (suspendingPkgsToCommit == null) { - suspendingPkgsToCommit = new ArraySet<>(); - pkgToSuspendingPkgsToCommit.put(packageName, suspendingPkgsToCommit); - } - suspendingPkgsToCommit.add(suspendingPackage); - countRemoved++; + WatchedArrayMap suspendParamsMap = + packageUserState.getSuspendParams(); + int countRemoved = 0; + for (int index = 0; index < suspendParamsMap.size(); index++) { + String suspendingPackage = suspendParamsMap.keyAt(index); + if (suspendingPackagePredicate.test(suspendingPackage)) { + ArraySet suspendingPkgsToCommit = + pkgToSuspendingPkgsToCommit.get(packageName); + if (suspendingPkgsToCommit == null) { + suspendingPkgsToCommit = new ArraySet<>(); + pkgToSuspendingPkgsToCommit.put(packageName, suspendingPkgsToCommit); } - } - - // Everything would be removed and package unsuspended - if (countRemoved == suspendParamsMap.size()) { - unsuspendedPackages.add(packageState.getPackageName()); - unsuspendedUids.add(UserHandle.getUid(userId, packageState.getAppId())); + suspendingPkgsToCommit.add(suspendingPackage); + countRemoved++; } } - }); + + // Everything would be removed and package unsuspended + if (countRemoved == suspendParamsMap.size()) { + unsuspendedPackages.add(packageState.getPackageName()); + unsuspendedUids.add(UserHandle.getUid(userId, packageState.getAppId())); + } + } mPm.commitPackageStateMutation(null, mutator -> { for (int mapIndex = 0; mapIndex < pkgToSuspendingPkgsToCommit.size(); mapIndex++) { diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java index b730ab27c70f5..e06b6081fd1bb 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java @@ -30,6 +30,7 @@ import android.util.PackageUtils; import android.util.SparseArray; import com.android.internal.util.CollectionUtils; +import com.android.server.pm.Computer; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState; @@ -38,7 +39,6 @@ import com.android.server.pm.verify.domain.models.DomainVerificationStateMap; import java.util.Arrays; import java.util.List; -import java.util.function.Function; @SuppressWarnings("PointlessBooleanExpression") public class DomainVerificationDebug { @@ -62,8 +62,7 @@ public class DomainVerificationDebug { } public void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName, - @Nullable @UserIdInt Integer userId, - @NonNull Function pkgSettingFunction, + @Nullable @UserIdInt Integer userId, @NonNull Computer snapshot, @NonNull DomainVerificationStateMap stateMap) throws NameNotFoundException { ArrayMap reusedMap = new ArrayMap<>(); @@ -74,7 +73,7 @@ public class DomainVerificationDebug { for (int index = 0; index < size; index++) { DomainVerificationPkgState pkgState = stateMap.valueAt(index); String pkgName = pkgState.getPackageName(); - PackageStateInternal pkgSetting = pkgSettingFunction.apply(pkgName); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName); if (pkgSetting == null || pkgSetting.getPkg() == null) { continue; } @@ -90,7 +89,7 @@ public class DomainVerificationDebug { throw DomainVerificationUtils.throwPackageUnavailable(packageName); } - PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); if (pkgSetting == null || pkgSetting.getPkg() == null) { throw DomainVerificationUtils.throwPackageUnavailable(packageName); } diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java index 25147d092066f..17140865a9d51 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java @@ -25,7 +25,6 @@ import android.content.Intent; import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageSettingsSnapshotProvider; import android.content.pm.ResolveInfo; import android.content.pm.verify.domain.DomainVerificationInfo; import android.content.pm.verify.domain.DomainVerificationManager; @@ -37,7 +36,7 @@ import android.util.Pair; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; -import com.android.server.pm.PackageManagerService; +import com.android.server.pm.Computer; import com.android.server.pm.PackageSetting; import com.android.server.pm.Settings; import com.android.server.pm.pkg.PackageStateInternal; @@ -227,14 +226,14 @@ public interface DomainVerificationManagerInternal { * assumed nothing has changed since the device rebooted. *

* If this is a new install, state will be restored from a previous call to {@link - * #restoreSettings(TypedXmlPullParser)}, or a new one will be generated. In either case, a + * #restoreSettings(Computer, TypedXmlPullParser)}, or a new one will be generated. In either case, a * broadcast will be sent to the domain verification agent so it may re-run any verification * logic for the newly associated domains. *

* This will mutate internal {@link DomainVerificationPkgState} and so will hold the internal * lock. This should never be called from within the domain verification classes themselves. *

- * This will NOT call {@link #writeSettings(TypedXmlSerializer, boolean, int)}. That must be + * This will NOT call {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. That must be * handled by the caller. */ void addPackage(@NonNull PackageStateInternal newPkgSetting); @@ -249,7 +248,7 @@ public interface DomainVerificationManagerInternal { * This will mutate internal {@link DomainVerificationPkgState} and so will hold the internal * lock. This should never be called from within the domain verification classes themselves. *

- * This will NOT call {@link #writeSettings(TypedXmlSerializer, boolean, int)}. That must be + * This will NOT call {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. That must be * handled by the caller. */ void migrateState(@NonNull PackageStateInternal oldPkgSetting, @@ -259,24 +258,24 @@ public interface DomainVerificationManagerInternal { * Serializes the entire internal state. This is equivalent to a full backup of the existing * verification state. This write includes legacy state, as a sibling tag the modern state. * + * @param snapshot * @param includeSignatures Whether to include the package signatures in the output, mainly * used for backing up the user settings and ensuring they're * re-attached to the same package. * @param userId The user to write out. Supports {@link UserHandle#USER_ALL} if all users - * should be written. */ - void writeSettings(@NonNull TypedXmlSerializer serializer, boolean includeSignatures, - @UserIdInt int userId) throws IOException; + void writeSettings(@NonNull Computer snapshot, @NonNull TypedXmlSerializer serializer, + boolean includeSignatures, @UserIdInt int userId) throws IOException; /** * Read back a list of {@link DomainVerificationPkgState}s previously written by {@link - * #writeSettings(TypedXmlSerializer, boolean, int)}. Assumes that the + * #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. Assumes that the * {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} tag has already been entered. *

* This is expected to only be used to re-attach states for packages already known to be on the - * device. If restoring from a backup, use {@link #restoreSettings(TypedXmlPullParser)}. + * device. If restoring from a backup, use {@link #restoreSettings(Computer, TypedXmlPullParser)}. */ - void readSettings(@NonNull TypedXmlPullParser parser) + void readSettings(@NonNull Computer snapshot, @NonNull TypedXmlPullParser parser) throws IOException, XmlPullParserException; /** @@ -306,7 +305,7 @@ public interface DomainVerificationManagerInternal { /** * Restore a list of {@link DomainVerificationPkgState}s previously written by {@link - * #writeSettings(TypedXmlSerializer, boolean, int)}. Assumes that the + * #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. Assumes that the * {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} * tag has already been entered. *

@@ -321,7 +320,7 @@ public interface DomainVerificationManagerInternal { * TODO(b/170746586): Figure out how to verify that package signatures match at snapshot time * and restore time. */ - void restoreSettings(@NonNull TypedXmlPullParser parser) + void restoreSettings(@NonNull Computer snapshot, @NonNull TypedXmlPullParser parser) throws IOException, XmlPullParserException; /** @@ -349,17 +348,14 @@ public interface DomainVerificationManagerInternal { /** * Print the verification state and user selection state of a package. * + * @param snapshot * @param packageName the package whose state to change, or all packages if none is * specified * @param userId the specific user to print, or null to skip printing user selection - * states, supports {@link android.os.UserHandle#USER_ALL} - * @param pkgSettingFunction the method by which to retrieve package data; if this is called - * from {@link PackageManagerService}, it is expected to pass in the - * snapshot of {@link PackageStateInternal} objects + * states, supports {@link UserHandle#USER_ALL} */ - void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName, - @Nullable @UserIdInt Integer userId, - @NonNull Function pkgSettingFunction) + void printState(@NonNull Computer snapshot, @NonNull IndentingPrintWriter writer, + @Nullable String packageName, @Nullable @UserIdInt Integer userId) throws NameNotFoundException; @NonNull @@ -406,12 +402,11 @@ public interface DomainVerificationManagerInternal { @NonNull Set domains, int state) throws NameNotFoundException; - interface Connection extends DomainVerificationEnforcer.Callback, - PackageSettingsSnapshotProvider { + interface Connection extends DomainVerificationEnforcer.Callback { /** * Notify that a settings change has been made and that eventually - * {@link #writeSettings(TypedXmlSerializer, boolean, int)} should be invoked by the parent. + * {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)} should be invoked by the parent. */ void scheduleWriteSettings(); @@ -433,5 +428,8 @@ public interface DomainVerificationManagerInternal { @UserIdInt int[] getAllUserIds(); + + @NonNull + Computer snapshot(); } } diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java index d6c89f7209e63..13218eaf2ded4 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java @@ -37,7 +37,6 @@ import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationState; import android.content.pm.verify.domain.DomainVerificationUserState; import android.content.pm.verify.domain.IDomainVerificationManager; -import android.os.Build; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; @@ -52,11 +51,10 @@ import android.util.TypedXmlSerializer; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.CollectionUtils; -import com.android.internal.util.FunctionalUtils; import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.compat.PlatformCompat; -import com.android.server.pm.Settings; +import com.android.server.pm.Computer; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageStateUtils; @@ -80,7 +78,6 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; -import java.util.function.Consumer; import java.util.function.Function; @SuppressLint("MissingPermission") @@ -109,9 +106,9 @@ public class DomainVerificationService extends SystemService * immediately attached once its available. *

* Generally this should be not accessed directly. Prefer calling {@link - * #getAndValidateAttachedLocked(UUID, Set, boolean, int, Integer, Function)}. + * #getAndValidateAttachedLocked(UUID, Set, boolean, int, Integer, Computer)}. * - * @see #getAndValidateAttachedLocked(UUID, Set, boolean, int, Integer, Function) + * @see #getAndValidateAttachedLocked(UUID, Set, boolean, int, Integer, Computer) **/ @GuardedBy("mLock") @NonNull @@ -178,12 +175,7 @@ public class DomainVerificationService extends SystemService @Override public void setConnection(@NonNull Connection connection) { - if (Build.IS_USERDEBUG || Build.IS_ENG) { - mConnection = new LockSafeConnection(connection); - } else { - mConnection = connection; - } - + mConnection = connection; mEnforcer.setCallback(mConnection); } @@ -264,44 +256,43 @@ public class DomainVerificationService extends SystemService public DomainVerificationInfo getDomainVerificationInfo(@NonNull String packageName) throws NameNotFoundException { mEnforcer.assertApprovedQuerent(mConnection.getCallingUid(), mProxy); - return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> { - synchronized (mLock) { - PackageStateInternal pkgSetting = pkgSettings.apply(packageName); - AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg(); - if (pkg == null) { - throw DomainVerificationUtils.throwPackageUnavailable(packageName); - } - - DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); - if (pkgState == null) { - return null; - } - - ArrayMap hostToStateMap = new ArrayMap<>(pkgState.getStateMap()); - - // TODO(b/159952358): Should the domain list be cached? - ArraySet domains = mCollector.collectValidAutoVerifyDomains(pkg); - if (domains.isEmpty()) { - return null; - } - - int size = domains.size(); - for (int index = 0; index < size; index++) { - hostToStateMap.putIfAbsent(domains.valueAt(index), - DomainVerificationState.STATE_NO_RESPONSE); - } - - final int mapSize = hostToStateMap.size(); - for (int index = 0; index < mapSize; index++) { - int internalValue = hostToStateMap.valueAt(index); - int publicValue = DomainVerificationState.convertToInfoState(internalValue); - hostToStateMap.setValueAt(index, publicValue); - } - - // TODO(b/159952358): Do not return if no values are editable (all ignored states)? - return new DomainVerificationInfo(pkgState.getId(), packageName, hostToStateMap); + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); + AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg(); + if (pkg == null) { + throw DomainVerificationUtils.throwPackageUnavailable(packageName); } - }); + + DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); + if (pkgState == null) { + return null; + } + + ArrayMap hostToStateMap = new ArrayMap<>(pkgState.getStateMap()); + + // TODO(b/159952358): Should the domain list be cached? + ArraySet domains = mCollector.collectValidAutoVerifyDomains(pkg); + if (domains.isEmpty()) { + return null; + } + + int size = domains.size(); + for (int index = 0; index < size; index++) { + hostToStateMap.putIfAbsent(domains.valueAt(index), + DomainVerificationState.STATE_NO_RESPONSE); + } + + final int mapSize = hostToStateMap.size(); + for (int index = 0; index < mapSize; index++) { + int internalValue = hostToStateMap.valueAt(index); + int publicValue = DomainVerificationState.convertToInfoState(internalValue); + hostToStateMap.setValueAt(index, publicValue); + } + + // TODO(b/159952358): Do not return if no values are editable (all ignored states)? + return new DomainVerificationInfo(pkgState.getId(), packageName, hostToStateMap); + } } @DomainVerificationManager.Error @@ -324,42 +315,40 @@ public class DomainVerificationService extends SystemService @NonNull Set domains, int state) throws NameNotFoundException { mEnforcer.assertApprovedVerifier(callingUid, mProxy); - return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> { - synchronized (mLock) { - List verifiedDomains = new ArrayList<>(); + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + List verifiedDomains = new ArrayList<>(); - GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains, - true /* forAutoVerify */, callingUid, null /* userId */, - pkgSettings); - if (result.isError()) { - return result.getErrorCode(); - } - - DomainVerificationPkgState pkgState = result.getPkgState(); - ArrayMap stateMap = pkgState.getStateMap(); - for (String domain : domains) { - Integer previousState = stateMap.get(domain); - if (previousState != null - && !DomainVerificationState.isModifiable(previousState)) { - continue; - } - - if (DomainVerificationState.isVerified(state)) { - verifiedDomains.add(domain); - } - - stateMap.put(domain, state); - } - - int size = verifiedDomains.size(); - for (int index = 0; index < size; index++) { - removeUserStatesForDomain(verifiedDomains.get(index)); - } + GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains, + true /* forAutoVerify */, callingUid, null /* userId */, snapshot); + if (result.isError()) { + return result.getErrorCode(); } - mConnection.scheduleWriteSettings(); - return DomainVerificationManager.STATUS_OK; - }); + DomainVerificationPkgState pkgState = result.getPkgState(); + ArrayMap stateMap = pkgState.getStateMap(); + for (String domain : domains) { + Integer previousState = stateMap.get(domain); + if (previousState != null + && !DomainVerificationState.isModifiable(previousState)) { + continue; + } + + if (DomainVerificationState.isVerified(state)) { + verifiedDomains.add(domain); + } + + stateMap.put(domain, state); + } + + int size = verifiedDomains.size(); + for (int index = 0; index < size; index++) { + removeUserStatesForDomain(verifiedDomains.get(index)); + } + } + + mConnection.scheduleWriteSettings(); + return DomainVerificationManager.STATUS_OK; } @Override @@ -380,60 +369,30 @@ public class DomainVerificationService extends SystemService ArraySet verifiedDomains = new ArraySet<>(); if (packageName == null) { - mConnection.withPackageSettingsSnapshot(pkgSettings -> { - synchronized (mLock) { - ArraySet validDomains = new ArraySet<>(); + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + ArraySet validDomains = new ArraySet<>(); - int size = mAttachedPkgStates.size(); - for (int index = 0; index < size; index++) { - DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index); - String pkgName = pkgState.getPackageName(); - PackageStateInternal pkgSetting = pkgSettings.apply(pkgName); - if (pkgSetting == null || pkgSetting.getPkg() == null) { - continue; - } - - AndroidPackage pkg = pkgSetting.getPkg(); - - validDomains.clear(); - - ArraySet autoVerifyDomains = - mCollector.collectValidAutoVerifyDomains(pkg); - if (domains == null) { - validDomains.addAll(autoVerifyDomains); - } else { - validDomains.addAll(domains); - validDomains.retainAll(autoVerifyDomains); - } - - if (DomainVerificationState.isVerified(state)) { - verifiedDomains.addAll(validDomains); - } - - setDomainVerificationStatusInternal(pkgState, state, validDomains); - } - } - }); - } else { - mConnection.withPackageSettingsSnapshotThrowing(pkgSettings -> { - synchronized (mLock) { - DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); - if (pkgState == null) { - throw DomainVerificationUtils.throwPackageUnavailable(packageName); - } - - PackageStateInternal pkgSetting = pkgSettings.apply(packageName); + int size = mAttachedPkgStates.size(); + for (int index = 0; index < size; index++) { + DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index); + String pkgName = pkgState.getPackageName(); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName); if (pkgSetting == null || pkgSetting.getPkg() == null) { - throw DomainVerificationUtils.throwPackageUnavailable(packageName); + continue; } AndroidPackage pkg = pkgSetting.getPkg(); - final ArraySet validDomains; + + validDomains.clear(); + + ArraySet autoVerifyDomains = + mCollector.collectValidAutoVerifyDomains(pkg); if (domains == null) { - validDomains = mCollector.collectValidAutoVerifyDomains(pkg); + validDomains.addAll(autoVerifyDomains); } else { - validDomains = domains; - validDomains.retainAll(mCollector.collectValidAutoVerifyDomains(pkg)); + validDomains.addAll(domains); + validDomains.retainAll(autoVerifyDomains); } if (DomainVerificationState.isVerified(state)) { @@ -442,7 +401,35 @@ public class DomainVerificationService extends SystemService setDomainVerificationStatusInternal(pkgState, state, validDomains); } - }); + } + } else { + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); + if (pkgState == null) { + throw DomainVerificationUtils.throwPackageUnavailable(packageName); + } + + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); + if (pkgSetting == null || pkgSetting.getPkg() == null) { + throw DomainVerificationUtils.throwPackageUnavailable(packageName); + } + + AndroidPackage pkg = pkgSetting.getPkg(); + final ArraySet validDomains; + if (domains == null) { + validDomains = mCollector.collectValidAutoVerifyDomains(pkg); + } else { + validDomains = domains; + validDomains.retainAll(mCollector.collectValidAutoVerifyDomains(pkg)); + } + + if (DomainVerificationState.isVerified(state)) { + verifiedDomains.addAll(validDomains); + } + + setDomainVerificationStatusInternal(pkgState, state, validDomains); + } } // Mirror SystemApi behavior of revoking user selection for approved domains. @@ -552,39 +539,38 @@ public class DomainVerificationService extends SystemService return DomainVerificationManager.ERROR_DOMAIN_SET_ID_INVALID; } - return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> { - synchronized (mLock) { - GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains, - false /* forAutoVerify */, callingUid, userId, pkgSettings); - if (result.isError()) { - return result.getErrorCode(); - } + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains, + false /* forAutoVerify */, callingUid, userId, snapshot); + if (result.isError()) { + return result.getErrorCode(); + } - DomainVerificationPkgState pkgState = result.getPkgState(); - DomainVerificationInternalUserState userState = pkgState.getOrCreateUserState( - userId); + DomainVerificationPkgState pkgState = result.getPkgState(); + DomainVerificationInternalUserState userState = pkgState.getOrCreateUserState( + userId); - // Disable other packages if approving this one. Note that this check is only done - // for enabling. This allows an escape hatch in case multiple packages somehow get - // selected. They can be disabled without blocking in a circular dependency. - if (enabled) { - int statusCode = revokeOtherUserSelectionsLocked(userState, userId, domains, - pkgSettings); - if (statusCode != DomainVerificationManager.STATUS_OK) { - return statusCode; - } - } - - if (enabled) { - userState.addHosts(domains); - } else { - userState.removeHosts(domains); + // Disable other packages if approving this one. Note that this check is only done + // for enabling. This allows an escape hatch in case multiple packages somehow get + // selected. They can be disabled without blocking in a circular dependency. + if (enabled) { + int statusCode = revokeOtherUserSelectionsLocked(userState, userId, domains, + snapshot); + if (statusCode != DomainVerificationManager.STATUS_OK) { + return statusCode; } } - mConnection.scheduleWriteSettings(); - return DomainVerificationManager.STATUS_OK; - }); + if (enabled) { + userState.addHosts(domains); + } else { + userState.removeHosts(domains); + } + } + + mConnection.scheduleWriteSettings(); + return DomainVerificationManager.STATUS_OK; } @Override @@ -592,48 +578,47 @@ public class DomainVerificationService extends SystemService @NonNull String packageName, boolean enabled, @Nullable ArraySet domains) throws NameNotFoundException { mEnforcer.assertInternal(mConnection.getCallingUid()); - mConnection.withPackageSettingsSnapshotThrowing(pkgSettings -> { - synchronized (mLock) { - DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); - if (pkgState == null) { - throw DomainVerificationUtils.throwPackageUnavailable(packageName); - } + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); + if (pkgState == null) { + throw DomainVerificationUtils.throwPackageUnavailable(packageName); + } - PackageStateInternal pkgSetting = pkgSettings.apply(packageName); - AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg(); - if (pkg == null) { - throw DomainVerificationUtils.throwPackageUnavailable(packageName); - } + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); + AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg(); + if (pkg == null) { + throw DomainVerificationUtils.throwPackageUnavailable(packageName); + } - Set validDomains = - domains == null ? mCollector.collectAllWebDomains(pkg) : domains; + Set validDomains = + domains == null ? mCollector.collectAllWebDomains(pkg) : domains; - validDomains.retainAll(mCollector.collectAllWebDomains(pkg)); + validDomains.retainAll(mCollector.collectAllWebDomains(pkg)); - if (userId == UserHandle.USER_ALL) { - for (int aUserId : mConnection.getAllUserIds()) { - DomainVerificationInternalUserState userState = - pkgState.getOrCreateUserState(aUserId); - revokeOtherUserSelectionsLocked(userState, aUserId, validDomains, - pkgSettings); - if (enabled) { - userState.addHosts(validDomains); - } else { - userState.removeHosts(validDomains); - } - } - } else { + if (userId == UserHandle.USER_ALL) { + for (int aUserId : mConnection.getAllUserIds()) { DomainVerificationInternalUserState userState = - pkgState.getOrCreateUserState(userId); - revokeOtherUserSelectionsLocked(userState, userId, validDomains, pkgSettings); + pkgState.getOrCreateUserState(aUserId); + revokeOtherUserSelectionsLocked(userState, aUserId, validDomains, + snapshot); if (enabled) { userState.addHosts(validDomains); } else { userState.removeHosts(validDomains); } } + } else { + DomainVerificationInternalUserState userState = + pkgState.getOrCreateUserState(userId); + revokeOtherUserSelectionsLocked(userState, userId, validDomains, snapshot); + if (enabled) { + userState.addHosts(validDomains); + } else { + userState.removeHosts(validDomains); + } } - }); + } mConnection.scheduleWriteSettings(); } @@ -641,8 +626,7 @@ public class DomainVerificationService extends SystemService @GuardedBy("mLock") private int revokeOtherUserSelectionsLocked( @NonNull DomainVerificationInternalUserState userState, @UserIdInt int userId, - @NonNull Set domains, - @NonNull Function pkgSettingFunction) { + @NonNull Set domains, @NonNull Computer snapshot) { // Cache the approved packages from the 1st pass because the search is expensive ArrayMap> domainToApprovedPackages = new ArrayMap<>(); @@ -652,7 +636,7 @@ public class DomainVerificationService extends SystemService } Pair, Integer> packagesToLevel = getApprovedPackagesLocked(domain, - userId, APPROVAL_LEVEL_NONE + 1, pkgSettingFunction); + userId, APPROVAL_LEVEL_NONE + 1, snapshot); int highestApproval = packagesToLevel.second; if (highestApproval > APPROVAL_LEVEL_SELECTION) { return DomainVerificationManager.ERROR_UNABLE_TO_APPROVE; @@ -698,51 +682,50 @@ public class DomainVerificationService extends SystemService throw DomainVerificationUtils.throwPackageUnavailable(packageName); } - return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> { - synchronized (mLock) { - PackageStateInternal pkgSetting = pkgSettings.apply(packageName); - AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg(); - if (pkg == null) { - throw DomainVerificationUtils.throwPackageUnavailable(packageName); - } - - DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); - if (pkgState == null) { - return null; - } - - ArraySet webDomains = mCollector.collectAllWebDomains(pkg); - int webDomainsSize = webDomains.size(); - - Map domains = new ArrayMap<>(webDomainsSize); - ArrayMap stateMap = pkgState.getStateMap(); - DomainVerificationInternalUserState userState = pkgState.getUserState(userId); - Set enabledHosts = - userState == null ? emptySet() : userState.getEnabledHosts(); - - for (int index = 0; index < webDomainsSize; index++) { - String host = webDomains.valueAt(index); - Integer state = stateMap.get(host); - - int domainState; - if (state != null && DomainVerificationState.isVerified(state)) { - domainState = DomainVerificationUserState.DOMAIN_STATE_VERIFIED; - } else if (enabledHosts.contains(host)) { - domainState = DomainVerificationUserState.DOMAIN_STATE_SELECTED; - } else { - domainState = DomainVerificationUserState.DOMAIN_STATE_NONE; - } - - domains.put(host, domainState); - } - - boolean linkHandlingAllowed = - userState == null || userState.isLinkHandlingAllowed(); - - return new DomainVerificationUserState(pkgState.getId(), packageName, - UserHandle.of(userId), linkHandlingAllowed, domains); + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); + AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg(); + if (pkg == null) { + throw DomainVerificationUtils.throwPackageUnavailable(packageName); } - }); + + DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); + if (pkgState == null) { + return null; + } + + ArraySet webDomains = mCollector.collectAllWebDomains(pkg); + int webDomainsSize = webDomains.size(); + + Map domains = new ArrayMap<>(webDomainsSize); + ArrayMap stateMap = pkgState.getStateMap(); + DomainVerificationInternalUserState userState = pkgState.getUserState(userId); + Set enabledHosts = + userState == null ? emptySet() : userState.getEnabledHosts(); + + for (int index = 0; index < webDomainsSize; index++) { + String host = webDomains.valueAt(index); + Integer state = stateMap.get(host); + + int domainState; + if (state != null && DomainVerificationState.isVerified(state)) { + domainState = DomainVerificationUserState.DOMAIN_STATE_VERIFIED; + } else if (enabledHosts.contains(host)) { + domainState = DomainVerificationUserState.DOMAIN_STATE_SELECTED; + } else { + domainState = DomainVerificationUserState.DOMAIN_STATE_NONE; + } + + domains.put(host, domainState); + } + + boolean linkHandlingAllowed = + userState == null || userState.isLinkHandlingAllowed(); + + return new DomainVerificationUserState(pkgState.getId(), packageName, + UserHandle.of(userId), linkHandlingAllowed, domains); + } } @NonNull @@ -751,27 +734,26 @@ public class DomainVerificationService extends SystemService mEnforcer.assertOwnerQuerent(mConnection.getCallingUid(), mConnection.getCallingUserId(), userId); - return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> { - SparseArray> levelToPackages = getOwnersForDomainInternal(domain, false, - userId, pkgSettings); - if (levelToPackages.size() == 0) { - return emptyList(); - } + final Computer snapshot = mConnection.snapshot(); + SparseArray> levelToPackages = getOwnersForDomainInternal(domain, false, + userId, snapshot); + if (levelToPackages.size() == 0) { + return emptyList(); + } - List owners = new ArrayList<>(); - int size = levelToPackages.size(); - for (int index = 0; index < size; index++) { - int level = levelToPackages.keyAt(index); - boolean overrideable = level <= APPROVAL_LEVEL_SELECTION; - List packages = levelToPackages.valueAt(index); - int packagesSize = packages.size(); - for (int packageIndex = 0; packageIndex < packagesSize; packageIndex++) { - owners.add(new DomainOwner(packages.get(packageIndex), overrideable)); - } + List owners = new ArrayList<>(); + int size = levelToPackages.size(); + for (int index = 0; index < size; index++) { + int level = levelToPackages.keyAt(index); + boolean overrideable = level <= APPROVAL_LEVEL_SELECTION; + List packages = levelToPackages.valueAt(index); + int packagesSize = packages.size(); + for (int packageIndex = 0; packageIndex < packagesSize; packageIndex++) { + owners.add(new DomainOwner(packages.get(packageIndex), overrideable)); } + } - return owners; - }); + return owners; } /** @@ -782,8 +764,7 @@ public class DomainVerificationService extends SystemService */ @NonNull private SparseArray> getOwnersForDomainInternal(@NonNull String domain, - boolean includeNegative, @UserIdInt int userId, - @NonNull Function pkgSettingFunction) { + boolean includeNegative, @UserIdInt int userId, @NonNull Computer snapshot) { SparseArray> levelToPackages = new SparseArray<>(); // First, collect the raw approval level values synchronized (mLock) { @@ -791,7 +772,7 @@ public class DomainVerificationService extends SystemService for (int index = 0; index < size; index++) { DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index); String packageName = pkgState.getPackageName(); - PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); if (pkgSetting == null) { continue; } @@ -818,8 +799,8 @@ public class DomainVerificationService extends SystemService // Then sort them ascending by first installed time, with package name as tie breaker for (int index = 0; index < size; index++) { levelToPackages.valueAt(index).sort((first, second) -> { - PackageStateInternal firstPkgSetting = pkgSettingFunction.apply(first); - PackageStateInternal secondPkgSetting = pkgSettingFunction.apply(second); + PackageStateInternal firstPkgSetting = snapshot.getPackageStateInternal(first); + PackageStateInternal secondPkgSetting = snapshot.getPackageStateInternal(second); long firstInstallTime = firstPkgSetting == null ? -1L : firstPkgSetting.getUserStateOrDefault(userId).getFirstInstallTime(); @@ -1060,44 +1041,38 @@ public class DomainVerificationService extends SystemService } @Override - public void writeSettings(@NonNull TypedXmlSerializer serializer, boolean includeSignatures, - @UserIdInt int userId) - throws IOException { - mConnection.withPackageSettingsSnapshotThrowing(pkgSettings -> { - synchronized (mLock) { - Function pkgNameToSignature = null; - if (includeSignatures) { - pkgNameToSignature = pkgName -> { - PackageStateInternal pkgSetting = pkgSettings.apply(pkgName); - if (pkgSetting == null) { - // If querying for a user restored package that isn't installed on the - // device yet, there will be no signature to write out. In that case, - // it's expected that this returns null and it falls back to the - // restored state's stored signature if it exists. - return null; - } + public void writeSettings(Computer snapshot, @NonNull TypedXmlSerializer serializer, + boolean includeSignatures, @UserIdInt int userId) throws IOException { + synchronized (mLock) { + Function pkgNameToSignature = null; + if (includeSignatures) { + pkgNameToSignature = pkgName -> { + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName); + if (pkgSetting == null) { + // If querying for a user restored package that isn't installed on the + // device yet, there will be no signature to write out. In that case, + // it's expected that this returns null and it falls back to the + // restored state's stored signature if it exists. + return null; + } - return PackageUtils.computeSignaturesSha256Digest( - pkgSetting.getSigningDetails().getSignatures()); - }; - } - - mSettings.writeSettings(serializer, mAttachedPkgStates, userId, pkgNameToSignature); + return PackageUtils.computeSignaturesSha256Digest( + pkgSetting.getSigningDetails().getSignatures()); + }; } - }); + + mSettings.writeSettings(serializer, mAttachedPkgStates, userId, pkgNameToSignature); + } mLegacySettings.writeSettings(serializer); } @Override - public void readSettings(@NonNull TypedXmlPullParser parser) throws IOException, - XmlPullParserException { - mConnection.withPackageSettingsSnapshotThrowing2( - pkgSettings -> { - synchronized (mLock) { - mSettings.readSettings(parser, mAttachedPkgStates, pkgSettings); - } - }); + public void readSettings(@NonNull Computer snapshot, @NonNull TypedXmlPullParser parser) + throws IOException, XmlPullParserException { + synchronized (mLock) { + mSettings.readSettings(parser, mAttachedPkgStates, snapshot); + } } @Override @@ -1107,14 +1082,11 @@ public class DomainVerificationService extends SystemService } @Override - public void restoreSettings(@NonNull TypedXmlPullParser parser) + public void restoreSettings(Computer snapshot, @NonNull TypedXmlPullParser parser) throws IOException, XmlPullParserException { - mConnection.withPackageSettingsSnapshotThrowing2( - pkgSettings -> { - synchronized (mLock) { - mSettings.restoreSettings(parser, mAttachedPkgStates, pkgSettings); - } - }); + synchronized (mLock) { + mSettings.restoreSettings(parser, mAttachedPkgStates, snapshot); + } } @Override @@ -1190,18 +1162,16 @@ public class DomainVerificationService extends SystemService @Override public void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName, @Nullable Integer userId) throws NameNotFoundException { - mConnection.withPackageSettingsSnapshotThrowing( - pkgSettings -> printState(writer, packageName, userId, pkgSettings)); + printState(mConnection.snapshot(), writer, packageName, userId); } @Override - public void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName, - @Nullable @UserIdInt Integer userId, - @NonNull Function pkgSettingFunction) + public void printState(@NonNull Computer snapshot, @NonNull IndentingPrintWriter writer, + @Nullable String packageName, @Nullable @UserIdInt Integer userId) throws NameNotFoundException { mEnforcer.assertApprovedQuerent(mConnection.getCallingUid(), mProxy); synchronized (mLock) { - mDebug.printState(writer, packageName, userId, pkgSettingFunction, mAttachedPkgStates); + mDebug.printState(writer, packageName, userId, snapshot, mAttachedPkgStates); } } @@ -1209,31 +1179,30 @@ public class DomainVerificationService extends SystemService public void printOwnersForPackage(@NonNull IndentingPrintWriter writer, @Nullable String packageName, @Nullable @UserIdInt Integer userId) throws NameNotFoundException { - mConnection.withPackageSettingsSnapshotThrowing(pkgSettings -> { - synchronized (mLock) { - if (packageName == null) { - int size = mAttachedPkgStates.size(); - for (int index = 0; index < size; index++) { - try { - printOwnersForPackage(writer, - mAttachedPkgStates.valueAt(index).getPackageName(), userId, - pkgSettings); - } catch (NameNotFoundException ignored) { - // When iterating packages, if one doesn't exist somehow, ignore - } + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + if (packageName == null) { + int size = mAttachedPkgStates.size(); + for (int index = 0; index < size; index++) { + try { + printOwnersForPackage(writer, + mAttachedPkgStates.valueAt(index).getPackageName(), userId, + snapshot); + } catch (NameNotFoundException ignored) { + // When iterating packages, if one doesn't exist somehow, ignore } - } else { - printOwnersForPackage(writer, packageName, userId, pkgSettings); } + } else { + printOwnersForPackage(writer, packageName, userId, snapshot); } - }); + } } private void printOwnersForPackage(@NonNull IndentingPrintWriter writer, @NonNull String packageName, @Nullable @UserIdInt Integer userId, - @NonNull Function pkgSettingFunction) + @NonNull Computer snapshot) throws NameNotFoundException { - PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg(); if (pkg == null) { throw DomainVerificationUtils.throwPackageUnavailable(packageName); @@ -1249,7 +1218,7 @@ public class DomainVerificationService extends SystemService writer.increaseIndent(); for (int index = 0; index < size; index++) { - printOwnersForDomain(writer, domains.valueAt(index), userId, pkgSettingFunction); + printOwnersForDomain(writer, domains.valueAt(index), userId, snapshot); } writer.decreaseIndent(); @@ -1258,30 +1227,28 @@ public class DomainVerificationService extends SystemService @Override public void printOwnersForDomains(@NonNull IndentingPrintWriter writer, @NonNull List domains, @Nullable @UserIdInt Integer userId) { - mConnection.withPackageSettingsSnapshot(pkgSettings -> { - synchronized (mLock) { - int size = domains.size(); - for (int index = 0; index < size; index++) { - printOwnersForDomain(writer, domains.get(index), userId, pkgSettings); - } + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + int size = domains.size(); + for (int index = 0; index < size; index++) { + printOwnersForDomain(writer, domains.get(index), userId, snapshot); } - }); + } } private void printOwnersForDomain(@NonNull IndentingPrintWriter writer, @NonNull String domain, - @Nullable @UserIdInt Integer userId, - @NonNull Function pkgSettingFunction) { + @Nullable @UserIdInt Integer userId, @NonNull Computer snapshot) { SparseArray>> userIdToApprovalLevelToOwners = new SparseArray<>(); if (userId == null || userId == UserHandle.USER_ALL) { for (int aUserId : mConnection.getAllUserIds()) { userIdToApprovalLevelToOwners.put(aUserId, - getOwnersForDomainInternal(domain, true, aUserId, pkgSettingFunction)); + getOwnersForDomainInternal(domain, true, aUserId, snapshot)); } } else { userIdToApprovalLevelToOwners.put(userId, - getOwnersForDomainInternal(domain, true, userId, pkgSettingFunction)); + getOwnersForDomainInternal(domain, true, userId, snapshot)); } mDebug.printOwners(writer, domain, userIdToApprovalLevelToOwners); @@ -1330,8 +1297,7 @@ public class DomainVerificationService extends SystemService @GuardedBy("mLock") private GetAttachedResult getAndValidateAttachedLocked(@NonNull UUID domainSetId, @NonNull Set domains, boolean forAutoVerify, int callingUid, - @Nullable Integer userIdForFilter, - @NonNull Function pkgSettingFunction) + @Nullable Integer userIdForFilter, @NonNull Computer snapshot) throws NameNotFoundException { if (domainSetId == null) { throw new IllegalArgumentException("domainSetId cannot be null"); @@ -1349,7 +1315,7 @@ public class DomainVerificationService extends SystemService return GetAttachedResult.error(DomainVerificationManager.ERROR_DOMAIN_SET_ID_INVALID); } - PackageStateInternal pkgSetting = pkgSettingFunction.apply(pkgName); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName); if (pkgSetting == null || pkgSetting.getPkg() == null) { throw DomainVerificationUtils.throwPackageUnavailable(pkgName); } @@ -1437,33 +1403,32 @@ public class DomainVerificationService extends SystemService @Override public void clearDomainVerificationState(@Nullable List packageNames) { mEnforcer.assertInternal(mConnection.getCallingUid()); - mConnection.withPackageSettingsSnapshot(pkgSettings -> { - synchronized (mLock) { - if (packageNames == null) { - int size = mAttachedPkgStates.size(); - for (int index = 0; index < size; index++) { - DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index); - String pkgName = pkgState.getPackageName(); - PackageStateInternal pkgSetting = pkgSettings.apply(pkgName); - if (pkgSetting == null || pkgSetting.getPkg() == null) { - continue; - } - resetDomainState(pkgState.getStateMap(), pkgSetting); + synchronized (mLock) { + final Computer snapshot = mConnection.snapshot(); + if (packageNames == null) { + int size = mAttachedPkgStates.size(); + for (int index = 0; index < size; index++) { + DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index); + String pkgName = pkgState.getPackageName(); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName); + if (pkgSetting == null || pkgSetting.getPkg() == null) { + continue; } - } else { - int size = packageNames.size(); - for (int index = 0; index < size; index++) { - String pkgName = packageNames.get(index); - DomainVerificationPkgState pkgState = mAttachedPkgStates.get(pkgName); - PackageStateInternal pkgSetting = pkgSettings.apply(pkgName); - if (pkgSetting == null || pkgSetting.getPkg() == null) { - continue; - } - resetDomainState(pkgState.getStateMap(), pkgSetting); + resetDomainState(pkgState.getStateMap(), pkgSetting); + } + } else { + int size = packageNames.size(); + for (int index = 0; index < size; index++) { + String pkgName = packageNames.get(index); + DomainVerificationPkgState pkgState = mAttachedPkgStates.get(pkgName); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName); + if (pkgSetting == null || pkgSetting.getPkg() == null) { + continue; } + resetDomainState(pkgState.getStateMap(), pkgSetting); } } - }); + } mConnection.scheduleWriteSettings(); } @@ -1935,35 +1900,32 @@ public class DomainVerificationService extends SystemService @GuardedBy("mLock") @NonNull private Pair, Integer> getApprovedPackagesLocked(@NonNull String domain, - @UserIdInt int userId, int minimumApproval, - @NonNull Function pkgSettingFunction) { + @UserIdInt int userId, int minimumApproval, @NonNull Computer snapshot) { boolean includeNegative = minimumApproval < APPROVAL_LEVEL_NONE; int highestApproval = minimumApproval; List approvedPackages = emptyList(); - synchronized (mLock) { - final int size = mAttachedPkgStates.size(); - for (int index = 0; index < size; index++) { - DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index); - String packageName = pkgState.getPackageName(); - PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName); - if (pkgSetting == null) { - continue; - } + final int size = mAttachedPkgStates.size(); + for (int index = 0; index < size; index++) { + DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index); + String packageName = pkgState.getPackageName(); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); + if (pkgSetting == null) { + continue; + } - int level = approvalLevelForDomain(pkgSetting, domain, includeNegative, userId, - domain); - if (level < minimumApproval) { - continue; - } + int level = approvalLevelForDomain(pkgSetting, domain, includeNegative, userId, + domain); + if (level < minimumApproval) { + continue; + } - if (level > highestApproval) { - approvedPackages.clear(); - approvedPackages = CollectionUtils.add(approvedPackages, packageName); - highestApproval = level; - } else if (level == highestApproval) { - approvedPackages = CollectionUtils.add(approvedPackages, packageName); - } + if (level > highestApproval) { + approvedPackages.clear(); + approvedPackages = CollectionUtils.add(approvedPackages, packageName); + highestApproval = level; + } else if (level == highestApproval) { + approvedPackages = CollectionUtils.add(approvedPackages, packageName); } } @@ -1976,7 +1938,7 @@ public class DomainVerificationService extends SystemService final int approvedSize = approvedPackages.size(); for (int index = 0; index < approvedSize; index++) { String packageName = approvedPackages.get(index); - PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName); + PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName); if (pkgSetting == null) { continue; } @@ -2035,108 +1997,4 @@ public class DomainVerificationService extends SystemService return mErrorCode; } } - - /** - * Wraps a {@link Connection} to verify that the {@link PackageStateInternal} calls do not hold - * {@link #mLock}, as that can cause deadlock when {@link Settings} tries to serialize state to - * disk. Only enabled if {@link Build#IS_USERDEBUG} or {@link Build#IS_ENG} is true. - */ - private class LockSafeConnection implements Connection { - - @NonNull - private final Connection mConnection; - - private LockSafeConnection(@NonNull Connection connection) { - mConnection = connection; - } - - private void enforceLocking() { - if (Thread.holdsLock(mLock)) { - Slog.wtf(TAG, "Method should not hold DVS lock when accessing package data"); - } - } - - @Override - public void withPackageSettingsSnapshot( - @NonNull Consumer> block) { - enforceLocking(); - mConnection.withPackageSettingsSnapshot(block); - } - - @Override - public Output withPackageSettingsSnapshotReturning( - @NonNull FunctionalUtils.ThrowingFunction, - Output> block) { - enforceLocking(); - return mConnection.withPackageSettingsSnapshotReturning(block); - } - - @Override - public void withPackageSettingsSnapshotThrowing( - @NonNull FunctionalUtils.ThrowingCheckedConsumer< - Function, ExceptionType> block) - throws ExceptionType { - enforceLocking(); - mConnection.withPackageSettingsSnapshotThrowing(block); - } - - @Override - public void - withPackageSettingsSnapshotThrowing2( - @NonNull FunctionalUtils.ThrowingChecked2Consumer< - Function, ExceptionOne, - ExceptionTwo> block) - throws ExceptionOne, ExceptionTwo { - enforceLocking(); - mConnection.withPackageSettingsSnapshotThrowing2(block); - } - - @Override - public Output - withPackageSettingsSnapshotReturningThrowing( - @NonNull FunctionalUtils.ThrowingCheckedFunction< - Function, Output, - ExceptionType> block) - throws ExceptionType { - enforceLocking(); - return mConnection.withPackageSettingsSnapshotReturningThrowing(block); - } - - @Override - public void scheduleWriteSettings() { - mConnection.scheduleWriteSettings(); - } - - @Override - public int getCallingUid() { - return mConnection.getCallingUid(); - } - - @Override - @UserIdInt - public int getCallingUserId() { - return mConnection.getCallingUserId(); - } - - @Override - public void schedule(int code, @Nullable Object object) { - mConnection.schedule(code, object); - } - - @Override - @UserIdInt - public int[] getAllUserIds() { - return mConnection.getAllUserIds(); - } - - @Override - public boolean filterAppAccess(@NonNull String packageName, int callingUid, int userId) { - return mConnection.filterAppAccess(packageName, callingUid, userId); - } - - @Override - public boolean doesUserExist(int userId) { - return mConnection.doesUserExist(userId); - } - } } diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java index 015d4e9e9f167..8d1ae0bc20b06 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java @@ -28,6 +28,7 @@ import android.util.TypedXmlSerializer; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.pm.Computer; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState; @@ -101,8 +102,7 @@ class DomainVerificationSettings { */ public void readSettings(@NonNull TypedXmlPullParser parser, @NonNull DomainVerificationStateMap liveState, - @NonNull Function pkgSettingFunction) - throws IOException, XmlPullParserException { + @NonNull Computer snapshot) throws IOException, XmlPullParserException { DomainVerificationPersistence.ReadResult result = DomainVerificationPersistence.readFromXml(parser); ArrayMap active = result.active; @@ -118,7 +118,7 @@ class DomainVerificationSettings { // This branch should never be possible. Settings should be read from disk // before any states are attached. But just in case, handle it. if (!existingState.getId().equals(pkgState.getId())) { - mergePkgState(existingState, pkgState, pkgSettingFunction); + mergePkgState(existingState, pkgState, snapshot); } } else { mPendingPkgStates.put(pkgName, pkgState); @@ -139,8 +139,7 @@ class DomainVerificationSettings { */ public void restoreSettings(@NonNull TypedXmlPullParser parser, @NonNull DomainVerificationStateMap liveState, - @NonNull Function pkgSettingFunction) - throws IOException, XmlPullParserException { + @NonNull Computer snapshot) throws IOException, XmlPullParserException { // TODO(b/170746586): Restoration assumes user IDs match, which is probably not the case on // a new device. @@ -166,7 +165,7 @@ class DomainVerificationSettings { } if (existingState != null) { - mergePkgState(existingState, newState, pkgSettingFunction); + mergePkgState(existingState, newState, snapshot); } else { // If there's no existing state, that means the new state has to be transformed // in preparation for attaching to brand new package that may eventually be @@ -216,9 +215,9 @@ class DomainVerificationSettings { */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public void mergePkgState(@NonNull DomainVerificationPkgState oldState, - @NonNull DomainVerificationPkgState newState, - @NonNull Function pkgSettingFunction) { - PackageStateInternal pkgSetting = pkgSettingFunction.apply(oldState.getPackageName()); + @NonNull DomainVerificationPkgState newState, @NonNull Computer snapshot) { + PackageStateInternal pkgSetting = + snapshot.getPackageStateInternal(oldState.getPackageName()); AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg(); Set validDomains = pkg == null ? Collections.emptySet() : mCollector.collectValidAutoVerifyDomains(pkg); diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java index da2d162d46f9e..4b0a8e2778c01 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java @@ -32,6 +32,7 @@ import android.util.ArraySet; import android.util.IndentingPrintWriter; import com.android.modules.utils.BasicShellCommandHandler; +import com.android.server.pm.Computer; import java.io.PrintWriter; import java.util.ArrayList; @@ -39,7 +40,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; -import java.util.function.Function; public class DomainVerificationShell { @@ -599,8 +599,8 @@ public class DomainVerificationShell { void verifyPackages(@Nullable List packageNames, boolean reVerify); /** - * @see DomainVerificationManagerInternal#printState(IndentingPrintWriter, String, Integer, - * Function) + * @see DomainVerificationManagerInternal#printState(Computer, IndentingPrintWriter, String, + * Integer) */ void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName, @Nullable @UserIdInt Integer userId) throws NameNotFoundException; diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt index 43b2e1e4b21e2..dcc461be00151 100644 --- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt +++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt @@ -265,12 +265,14 @@ class PackageManagerComponentLabelIconOverrideTest { assertServiceInitialized() ?: return when (params.result) { is Result.Changed, Result.ChangedWithoutNotify -> { - assertThat(mockPendingBroadcasts.get(userId, params.pkgName) ?: emptyList()) + assertThat(mockPendingBroadcasts.copiedMap()?.get(userId)?.get(params.pkgName) + ?: emptyList()) .containsExactly(params.componentName!!.className) .inOrder() } is Result.NotChanged, is Result.Exception -> { - assertThat(mockPendingBroadcasts.get(userId, params.pkgName)).isNull() + assertThat(mockPendingBroadcasts.copiedMap()?.get(userId)?.get(params.pkgName)) + .isNull() } }.run { /*exhaust*/ } } diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt index 92cdb348e60df..c9601de6ff265 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt @@ -20,8 +20,6 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.content.pm.SigningDetails -import com.android.server.pm.pkg.component.ParsedActivityImpl -import com.android.server.pm.pkg.component.ParsedIntentInfoImpl import android.content.pm.verify.domain.DomainVerificationManager import android.content.pm.verify.domain.DomainVerificationState import android.os.Build @@ -30,10 +28,12 @@ import android.util.ArraySet import android.util.IndentingPrintWriter import android.util.SparseArray import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.pm.Computer import com.android.server.pm.parsing.pkg.AndroidPackage import com.android.server.pm.pkg.PackageStateInternal import com.android.server.pm.pkg.PackageUserStateInternal -import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates +import com.android.server.pm.pkg.component.ParsedActivityImpl +import com.android.server.pm.pkg.component.ParsedIntentInfoImpl import com.android.server.pm.verify.domain.DomainVerificationEnforcer import com.android.server.pm.verify.domain.DomainVerificationManagerInternal import com.android.server.pm.verify.domain.DomainVerificationService @@ -100,11 +100,15 @@ class DomainVerificationEnforcerTest { mockThrowOnUnmocked { whenever(callingUid) { callingUidInt.get() } whenever(callingUserId) { callingUserIdInt.get() } - mockPackageStates { - when (it) { - VISIBLE_PKG -> visiblePkgState - INVISIBLE_PKG -> invisiblePkgState - else -> null + whenever(snapshot()) { + mockThrowOnUnmocked { + whenever(getPackageStateInternal(anyString())) { + when (getArgument(0)) { + VISIBLE_PKG -> visiblePkgState + INVISIBLE_PKG -> invisiblePkgState + else -> null + } + } } } whenever(schedule(anyInt(), any())) @@ -211,9 +215,8 @@ class DomainVerificationEnforcerTest { printState(mock(IndentingPrintWriter::class.java), null, null) }, service(Type.QUERENT, "printStateInternal") { - printState(mock(IndentingPrintWriter::class.java), null, null) { - mockPkgState(it, UUID.randomUUID()) - } + printState(mock(Computer::class.java), mock(IndentingPrintWriter::class.java), + null, null) }, service(Type.VERIFIER, "setStatus") { setDomainVerificationStatus( diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt index 878bee0126358..7273b0b54e1e0 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt @@ -19,9 +19,6 @@ package com.android.server.pm.test.verify.domain import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import com.android.server.pm.pkg.component.ParsedActivityImpl -import com.android.server.pm.pkg.component.ParsedIntentInfoImpl -import com.android.server.pm.pkg.PackageUserStateInternal import android.content.pm.verify.domain.DomainOwner import android.content.pm.verify.domain.DomainVerificationInfo import android.content.pm.verify.domain.DomainVerificationManager @@ -34,7 +31,9 @@ import android.util.ArraySet import android.util.SparseArray import com.android.server.pm.parsing.pkg.AndroidPackage import com.android.server.pm.pkg.PackageStateInternal -import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates +import com.android.server.pm.pkg.PackageUserStateInternal +import com.android.server.pm.pkg.component.ParsedActivityImpl +import com.android.server.pm.pkg.component.ParsedIntentInfoImpl import com.android.server.pm.verify.domain.DomainVerificationManagerStub import com.android.server.pm.verify.domain.DomainVerificationService import com.android.server.testutils.mockThrowOnUnmocked @@ -502,8 +501,12 @@ class DomainVerificationManagerApiTest { whenever(callingUid) { Process.ROOT_UID } whenever(callingUserId) { 0 } - mockPackageStates { - pkgStateFunction(it) + whenever(snapshot()) { + mockThrowOnUnmocked { + whenever(getPackageStateInternal(anyString())) { + pkgStateFunction(getArgument(0)) + } + } } }) } diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt index 0369bab61f0f6..40f37a7ee1f7c 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt @@ -20,9 +20,6 @@ import android.content.Intent import android.content.pm.PackageManager import android.content.pm.Signature import android.content.pm.SigningDetails -import com.android.server.pm.pkg.component.ParsedActivityImpl -import com.android.server.pm.pkg.component.ParsedIntentInfoImpl -import com.android.server.pm.pkg.PackageUserStateInternal import android.content.pm.verify.domain.DomainOwner import android.content.pm.verify.domain.DomainVerificationInfo.STATE_MODIFIABLE_VERIFIED import android.content.pm.verify.domain.DomainVerificationInfo.STATE_NO_RESPONSE @@ -39,9 +36,12 @@ import android.os.Process import android.util.ArraySet import android.util.SparseArray import android.util.Xml +import com.android.server.pm.Computer import com.android.server.pm.parsing.pkg.AndroidPackage import com.android.server.pm.pkg.PackageStateInternal -import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates +import com.android.server.pm.pkg.PackageUserStateInternal +import com.android.server.pm.pkg.component.ParsedActivityImpl +import com.android.server.pm.pkg.component.ParsedIntentInfoImpl import com.android.server.pm.verify.domain.DomainVerificationService import com.android.server.testutils.mock import com.android.server.testutils.mockThrowOnUnmocked @@ -194,7 +194,8 @@ class DomainVerificationPackageTest { """ val service = makeService(pkg1, pkg2) - service.restoreSettings(Xml.resolvePullParser(xml.byteInputStream())) + val computer = mockComputer(pkg1, pkg2) + service.restoreSettings(computer, Xml.resolvePullParser(xml.byteInputStream())) service.addPackage(pkg1) val info = service.getInfo(pkg1.packageName) assertThat(info.packageName).isEqualTo(pkg1.packageName) @@ -243,7 +244,8 @@ class DomainVerificationPackageTest { """ val service = makeService(pkg1, pkg2) - service.restoreSettings(Xml.resolvePullParser(xml.byteInputStream())) + val computer = mockComputer(pkg1, pkg2) + service.restoreSettings(computer, Xml.resolvePullParser(xml.byteInputStream())) service.addPackage(pkg1) val info = service.getInfo(pkg1.packageName) assertThat(info.packageName).isEqualTo(pkg1.packageName) @@ -298,8 +300,9 @@ class DomainVerificationPackageTest { """.trimIndent() val service = makeService(pkg1, pkg2) + val computer = mockComputer(pkg1, pkg2) xml.byteInputStream().use { - service.readSettings(Xml.resolvePullParser(it)) + service.readSettings(computer, Xml.resolvePullParser(it)) } service.addPackage(pkg1) @@ -311,8 +314,9 @@ class DomainVerificationPackageTest { fun addPackagePendingStripInvalidDomains() { val xml = addPackagePendingOrRestoredWithInvalidDomains() val service = makeService(pkg1, pkg2) + val computer = mockComputer(pkg1, pkg2) xml.byteInputStream().use { - service.readSettings(Xml.resolvePullParser(it)) + service.readSettings(computer, Xml.resolvePullParser(it)) } service.addPackage(pkg1) @@ -334,8 +338,9 @@ class DomainVerificationPackageTest { fun addPackageRestoredStripInvalidDomains() { val xml = addPackagePendingOrRestoredWithInvalidDomains() val service = makeService(pkg1, pkg2) + val computer = mockComputer(pkg1, pkg2) xml.byteInputStream().use { - service.restoreSettings(Xml.resolvePullParser(it)) + service.restoreSettings(computer, Xml.resolvePullParser(it)) } service.addPackage(pkg1) @@ -686,6 +691,7 @@ class DomainVerificationPackageTest { val pkg2 = mockPkgState(PKG_TWO, UUID_TWO, SIGNATURE_TWO, listOf(DOMAIN_1, DOMAIN_2, DOMAIN_3)) val serviceBefore = makeService(pkg1, pkg2) + val computerBefore = mockComputer(pkg1, pkg2) serviceBefore.addPackage(pkg1) serviceBefore.addPackage(pkg2) @@ -729,16 +735,17 @@ class DomainVerificationPackageTest { assertExpectedState(serviceBefore) val backupUser0 = ByteArrayOutputStream().use { - serviceBefore.writeSettings(Xml.resolveSerializer(it), true, 0) + serviceBefore.writeSettings(computerBefore, Xml.resolveSerializer(it), true, 0) it.toByteArray() } val backupUser1 = ByteArrayOutputStream().use { - serviceBefore.writeSettings(Xml.resolveSerializer(it), true, 10) + serviceBefore.writeSettings(computerBefore, Xml.resolveSerializer(it), true, 10) it.toByteArray() } val serviceAfter = makeService(pkg1, pkg2) + val computerAfter = mockComputer(pkg1, pkg2) serviceAfter.addPackage(pkg1) serviceAfter.addPackage(pkg2) @@ -763,7 +770,7 @@ class DomainVerificationPackageTest { } ByteArrayInputStream(backupUser1).use { - serviceAfter.restoreSettings(Xml.resolvePullParser(it)) + serviceAfter.restoreSettings(computerAfter, Xml.resolvePullParser(it)) } // Assert user 1 was restored @@ -800,7 +807,7 @@ class DomainVerificationPackageTest { ) ByteArrayInputStream(backupUser0).use { - serviceAfter.restoreSettings(Xml.resolvePullParser(it)) + serviceAfter.restoreSettings(computerAfter, Xml.resolvePullParser(it)) } assertExpectedState(serviceAfter) @@ -848,12 +855,20 @@ class DomainVerificationPackageTest { whenever(callingUid) { Process.ROOT_UID } whenever(callingUserId) { 0 } - mockPackageStates { - pkgStateFunction(it) - } + whenever(snapshot()) { mockComputer(pkgStateFunction) } }) } + private fun mockComputer(vararg pkgStates: PackageStateInternal) = + mockComputer { pkgName -> pkgStates.find { pkgName == it.packageName } } + + private fun mockComputer(pkgStateFunction: (String) -> PackageStateInternal? = { null }) = + mockThrowOnUnmocked { + whenever(getPackageStateInternal(anyString())) { + pkgStateFunction(getArgument(0)) + } + } + private fun mockPkgState( pkgName: String, domainSetId: UUID, diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt index 3a602a8b3c466..fc20c2657b979 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt @@ -29,7 +29,6 @@ import android.util.ArraySet import android.util.SparseArray import com.android.server.pm.parsing.pkg.AndroidPackage import com.android.server.pm.pkg.PackageStateInternal -import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates 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 @@ -245,10 +244,14 @@ class DomainVerificationSettingsMutationTest { mockThrowOnUnmocked { whenever(callingUid) { TEST_UID } whenever(callingUserId) { TEST_USER_ID } - mockPackageStates { - when (it) { - TEST_PKG -> mockPkgState() - else -> null + whenever(snapshot()) { + mockThrowOnUnmocked { + whenever(getPackageStateInternal(anyString())) { + when (getArgument(0)) { + TEST_PKG -> mockPkgState() + else -> null + } + } } } whenever(schedule(anyInt(), any())) diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationTestUtils.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationTestUtils.kt deleted file mode 100644 index c5f0eb1843863..0000000000000 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationTestUtils.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.test.verify.domain - -import com.android.internal.util.FunctionalUtils -import com.android.server.pm.pkg.PackageStateInternal -import com.android.server.pm.verify.domain.DomainVerificationManagerInternal -import com.android.server.testutils.whenever -import org.mockito.ArgumentMatchers.any -import java.util.function.Consumer -import java.util.function.Function - -internal object DomainVerificationTestUtils { - - @Suppress("UNCHECKED_CAST") - fun DomainVerificationManagerInternal.Connection.mockPackageStates( - block: (String) -> PackageStateInternal? - ) { - whenever(withPackageSettingsSnapshot(any())) { - (arguments[0] as Consumer>).accept { block(it) } - } - whenever(withPackageSettingsSnapshotReturning(any())) { - (arguments[0] as FunctionalUtils.ThrowingFunction< - Function, *>) - .apply { block(it) } - } - whenever(withPackageSettingsSnapshotThrowing(any())) { - (arguments[0] as FunctionalUtils.ThrowingCheckedConsumer< - Function, *>) - .accept { block(it) } - } - whenever(withPackageSettingsSnapshotThrowing2(any())) { - (arguments[0] as FunctionalUtils.ThrowingChecked2Consumer< - Function, *, *>) - .accept { block(it) } - } - whenever(withPackageSettingsSnapshotReturningThrowing(any())) { - (arguments[0] as FunctionalUtils.ThrowingCheckedFunction< - Function, *, *>) - .apply { block(it) } - } - } -} diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt index ffc2877360665..589633ccb9002 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt @@ -31,7 +31,6 @@ import android.util.SparseArray import com.android.server.pm.parsing.pkg.AndroidPackage import com.android.server.pm.pkg.PackageStateInternal import com.android.server.pm.pkg.PackageUserStateInternal -import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates import com.android.server.pm.verify.domain.DomainVerificationService import com.android.server.testutils.mockThrowOnUnmocked import com.android.server.testutils.whenever @@ -85,11 +84,15 @@ class DomainVerificationUserStateOverrideTest { // Need to provide an internal UID so some permission checks are ignored whenever(callingUid) { Process.ROOT_UID } whenever(callingUserId) { 0 } - mockPackageStates { - when (it) { - PKG_ONE -> pkg1 - PKG_TWO -> pkg2 - else -> null + whenever(snapshot()) { + mockThrowOnUnmocked { + whenever(getPackageStateInternal(anyString())) { + when (getArgument(0)) { + PKG_ONE -> pkg1 + PKG_TWO -> pkg2 + else -> null + } + } } } }) diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt index ca5bf2085d713..6510cd19e5fb4 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt @@ -167,7 +167,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { } whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap) whenever(mocks.settings.getPackageLPr(anyString())) { mSettingsMap[getArgument(0)] } - whenever(mocks.settings.readLPw(nullable())) { + whenever(mocks.settings.readLPw(any(), nullable())) { mSettingsMap.putAll(mPreExistingSettings) !mPreExistingSettings.isEmpty() } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt index f35986b178d8a..b063d22de2bb5 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt @@ -120,17 +120,16 @@ class SharedLibrariesImplTest { whenever(mStorageManager.findPathForUuid(nullable())).thenReturn(mFile) doAnswer { it.arguments[0] }.`when`(mPms).resolveInternalPackageName(any(), any()) doAnswer { - it.getArgument>(0).acceptOrThrow( - mockThrowOnUnmocked { - whenever(sharedLibraries) { mSharedLibrariesImpl.sharedLibraries } - whenever(resolveInternalPackageName(anyString(), anyLong())) { - mPms.resolveInternalPackageName(getArgument(0), getArgument(1)) - } - whenever(getPackageStateInternal(anyString())) { - mPms.getPackageStateInternal(getArgument(0)) - } - }) - }.`when`(mPms).executeWithConsistentComputer(any()) + mockThrowOnUnmocked { + whenever(sharedLibraries) { mSharedLibrariesImpl.sharedLibraries } + whenever(resolveInternalPackageName(anyString(), anyLong())) { + mPms.resolveInternalPackageName(getArgument(0), getArgument(1)) + } + whenever(getPackageStateInternal(anyString())) { + mPms.getPackageStateInternal(getArgument(0)) + } + } + }.`when`(mPms).snapshotComputer() whenever(mDeletePackageHelper.deletePackageX(any(), any(), any(), any(), any())) .thenReturn(PackageManager.DELETE_SUCCEEDED) whenever(mRule.mocks().injector.compatibility).thenReturn(mPlatformCompat) @@ -206,7 +205,8 @@ class SharedLibrariesImplTest { @Test fun pruneUnusedStaticSharedLibraries() { - mSharedLibrariesImpl.pruneUnusedStaticSharedLibraries(Long.MAX_VALUE, 0) + mSharedLibrariesImpl.pruneUnusedStaticSharedLibraries(mPms.snapshotComputer(), + Long.MAX_VALUE, 0) verify(mDeletePackageHelper) .deletePackageX(eq(STATIC_LIB_PACKAGE_NAME), any(), any(), any(), any()) diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt index ac406b588d385..5230ea7304c80 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt @@ -123,8 +123,8 @@ class SuspendPackageHelperTest { @Test fun setPackagesSuspended() { val targetPackages = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2) - val failedNames = suspendPackageHelper.setPackagesSuspended(targetPackages, - true /* suspended */, null /* appExtras */, null /* launcherExtras */, + val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + targetPackages, true /* suspended */, null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) testHandler.flush() @@ -144,14 +144,15 @@ class SuspendPackageHelperTest { @Test fun setPackagesSuspended_emptyPackageName() { - var failedNames = suspendPackageHelper.setPackagesSuspended(null /* packageNames */, - true /* suspended */, null /* appExtras */, null /* launcherExtras */, - null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + null /* packageNames */, true /* suspended */, null /* appExtras */, + null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, + deviceOwnerUid) assertThat(failedNames).isNull() - failedNames = suspendPackageHelper.setPackagesSuspended(arrayOfNulls(0), - true /* suspended */, null /* appExtras */, null /* launcherExtras */, + failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOfNulls(0), true /* suspended */, null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) assertThat(failedNames).isEmpty() @@ -159,9 +160,10 @@ class SuspendPackageHelperTest { @Test fun setPackagesSuspended_callerIsNotAllowed() { - val failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_2), - true /* suspended */, null /* appExtras */, null /* launcherExtras */, - null /* dialogInfo */, TEST_PACKAGE_1, TEST_USER_ID, Binder.getCallingUid()) + val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, + null /* launcherExtras */, null /* dialogInfo */, TEST_PACKAGE_1, TEST_USER_ID, + Binder.getCallingUid()) assertThat(failedNames).asList().hasSize(1) assertThat(failedNames).asList().contains(TEST_PACKAGE_2) @@ -169,9 +171,10 @@ class SuspendPackageHelperTest { @Test fun setPackagesSuspended_callerSuspendItself() { - val failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(DEVICE_OWNER_PACKAGE), - true /* suspended */, null /* appExtras */, null /* launcherExtras */, - null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) + val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOf(DEVICE_OWNER_PACKAGE), true /* suspended */, null /* appExtras */, + null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, + deviceOwnerUid) assertThat(failedNames).asList().hasSize(1) assertThat(failedNames).asList().contains(DEVICE_OWNER_PACKAGE) @@ -179,9 +182,10 @@ class SuspendPackageHelperTest { @Test fun setPackagesSuspended_nonexistentPackage() { - val failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(NONEXISTENT_PACKAGE), - true /* suspended */, null /* appExtras */, null /* launcherExtras */, - null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) + val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOf(NONEXISTENT_PACKAGE), true /* suspended */, null /* appExtras */, + null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, + deviceOwnerUid) assertThat(failedNames).asList().hasSize(1) assertThat(failedNames).asList().contains(NONEXISTENT_PACKAGE) @@ -191,8 +195,8 @@ class SuspendPackageHelperTest { fun setPackagesSuspended_knownPackages() { val knownPackages = arrayOf(DEVICE_ADMIN_PACKAGE, DEFAULT_HOME_PACKAGE, DIALER_PACKAGE, INSTALLER_PACKAGE, UNINSTALLER_PACKAGE, VERIFIER_PACKAGE, PERMISSION_CONTROLLER_PACKAGE) - val failedNames = suspendPackageHelper.setPackagesSuspended(knownPackages, - true /* suspended */, null /* appExtras */, null /* launcherExtras */, + val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + knownPackages, true /* suspended */, null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)!! assertThat(failedNames.size).isEqualTo(knownPackages.size) @@ -204,13 +208,13 @@ class SuspendPackageHelperTest { @Test fun setPackagesUnsuspended() { val targetPackages = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2) - var failedNames = suspendPackageHelper.setPackagesSuspended(targetPackages, - true /* suspended */, null /* appExtras */, null /* launcherExtras */, + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + targetPackages, true /* suspended */, null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) testHandler.flush() assertThat(failedNames).isEmpty() - failedNames = suspendPackageHelper.setPackagesSuspended(targetPackages, - false /* suspended */, null /* appExtras */, null /* launcherExtras */, + failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + targetPackages, false /* suspended */, null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) testHandler.flush() @@ -235,7 +239,7 @@ class SuspendPackageHelperTest { val suspendables = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2) val unsuspendables = arrayOf(DEVICE_ADMIN_PACKAGE, DEFAULT_HOME_PACKAGE, DIALER_PACKAGE, INSTALLER_PACKAGE, UNINSTALLER_PACKAGE, VERIFIER_PACKAGE, PERMISSION_CONTROLLER_PACKAGE) - val results = suspendPackageHelper.getUnsuspendablePackagesForUser( + val results = suspendPackageHelper.getUnsuspendablePackagesForUser(pms.snapshotComputer(), suspendables + unsuspendables, TEST_USER_ID, deviceOwnerUid) assertThat(results.size).isEqualTo(unsuspendables.size) @@ -247,7 +251,7 @@ class SuspendPackageHelperTest { @Test fun getUnsuspendablePackagesForUser_callerIsNotAllowed() { val suspendables = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2) - val results = suspendPackageHelper.getUnsuspendablePackagesForUser( + val results = suspendPackageHelper.getUnsuspendablePackagesForUser(pms.snapshotComputer(), suspendables, TEST_USER_ID, Binder.getCallingUid()) assertThat(results.size).isEqualTo(suspendables.size) @@ -260,8 +264,8 @@ class SuspendPackageHelperTest { fun getSuspendedPackageAppExtras() { val appExtras = PersistableBundle() appExtras.putString(TEST_PACKAGE_1, TEST_PACKAGE_1) - var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_1), - true /* suspended */, appExtras, null /* launcherExtras */, + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOf(TEST_PACKAGE_1), true /* suspended */, appExtras, null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) testHandler.flush() assertThat(failedNames).isEmpty() @@ -277,8 +281,8 @@ class SuspendPackageHelperTest { val appExtras = PersistableBundle() appExtras.putString(TEST_PACKAGE_1, TEST_PACKAGE_2) val targetPackages = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2) - var failedNames = suspendPackageHelper.setPackagesSuspended(targetPackages, - true /* suspended */, appExtras, null /* launcherExtras */, + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + targetPackages, true /* suspended */, appExtras, null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) testHandler.flush() assertThat(failedNames).isEmpty() @@ -291,8 +295,9 @@ class SuspendPackageHelperTest { assertThat(suspendPackageHelper.getSuspendedPackageAppExtras( TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNotNull() - suspendPackageHelper.removeSuspensionsBySuspendingPackage(targetPackages, - { suspendingPackage -> suspendingPackage == DEVICE_OWNER_PACKAGE }, TEST_USER_ID) + suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(), + targetPackages, { suspendingPackage -> suspendingPackage == DEVICE_OWNER_PACKAGE }, + TEST_USER_ID) testHandler.flush() verify(pms, times(2)).scheduleWritePackageRestrictions(eq(TEST_USER_ID)) @@ -320,8 +325,8 @@ class SuspendPackageHelperTest { fun getSuspendedPackageLauncherExtras() { val launcherExtras = PersistableBundle() launcherExtras.putString(TEST_PACKAGE_2, TEST_PACKAGE_2) - var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_2), - true /* suspended */, null /* appExtras */, launcherExtras, + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, launcherExtras, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) testHandler.flush() assertThat(failedNames).isEmpty() @@ -334,9 +339,10 @@ class SuspendPackageHelperTest { @Test fun isPackageSuspended() { - var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_1), - true /* suspended */, null /* appExtras */, null /* launcherExtras */, - null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOf(TEST_PACKAGE_1), true /* suspended */, null /* appExtras */, + null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, + deviceOwnerUid) testHandler.flush() assertThat(failedNames).isEmpty() @@ -348,8 +354,8 @@ class SuspendPackageHelperTest { fun getSuspendingPackage() { val launcherExtras = PersistableBundle() launcherExtras.putString(TEST_PACKAGE_2, TEST_PACKAGE_2) - var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_2), - true /* suspended */, null /* appExtras */, launcherExtras, + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, launcherExtras, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) testHandler.flush() assertThat(failedNames).isEmpty() @@ -362,9 +368,10 @@ class SuspendPackageHelperTest { fun getSuspendedDialogInfo() { val dialogInfo = SuspendDialogInfo.Builder() .setTitle(TEST_PACKAGE_1).build() - var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_1), - true /* suspended */, null /* appExtras */, null /* launcherExtras */, - dialogInfo, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid) + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + arrayOf(TEST_PACKAGE_1), true /* suspended */, null /* appExtras */, + null /* launcherExtras */, dialogInfo, DEVICE_OWNER_PACKAGE, TEST_USER_ID, + deviceOwnerUid) testHandler.flush() assertThat(failedNames).isEmpty() 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 6789af4a13d8b..2b34bc2ef28db 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -35,6 +35,7 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.annotation.NonNull; @@ -109,6 +110,8 @@ public class PackageManagerSettingsTests { LegacyPermissionDataProvider mPermissionDataProvider; @Mock DomainVerificationManagerInternal mDomainVerificationManager; + @Mock + Computer computer; final ArrayMap mOrigFirstInstallTimes = new ArrayMap<>(); @@ -132,7 +135,7 @@ public class PackageManagerSettingsTests { /* write out files and read */ writeOldFiles(); Settings settings = makeSettings(); - assertThat(settings.readLPw(createFakeUsers()), is(true)); + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); verifyKeySetMetaData(settings); } @@ -143,11 +146,11 @@ public class PackageManagerSettingsTests { // write out files and read writeOldFiles(); Settings settings = makeSettings(); - assertThat(settings.readLPw(createFakeUsers()), is(true)); + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); // write out, read back in and verify the same - settings.writeLPr(); - assertThat(settings.readLPw(createFakeUsers()), is(true)); + settings.writeLPr(computer); + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); verifyKeySetMetaData(settings); } @@ -156,7 +159,7 @@ public class PackageManagerSettingsTests { // Write delegateshellthe package files and make sure they're parsed properly the first time writeOldFiles(); Settings settings = makeSettings(); - assertThat(settings.readLPw(createFakeUsers()), is(true)); + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); assertThat(settings.getPackageLPr(PACKAGE_NAME_3), is(notNullValue())); assertThat(settings.getPackageLPr(PACKAGE_NAME_1), is(notNullValue())); @@ -175,12 +178,12 @@ public class PackageManagerSettingsTests { // Write the package files and make sure they're parsed properly the first time writeOldFiles(); Settings settings = makeSettings(); - assertThat(settings.readLPw(createFakeUsers()), is(true)); - settings.writeLPr(); + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); + settings.writeLPr(computer); // Create Settings again to make it read from the new files settings = makeSettings(); - assertThat(settings.readLPw(createFakeUsers()), is(true)); + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_2); assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER)); @@ -469,12 +472,12 @@ public class PackageManagerSettingsTests { ps2.setUsesStaticLibrariesVersions(new long[] { 34 }); settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2); - settingsUnderTest.writeLPr(); + settingsUnderTest.writeLPr(computer); settingsUnderTest.mPackages.clear(); settingsUnderTest.mDisabledSysPackages.clear(); - assertThat(settingsUnderTest.readLPw(createFakeUsers()), is(true)); + assertThat(settingsUnderTest.readLPw(computer, createFakeUsers()), is(true)); PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1); PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2); @@ -534,12 +537,12 @@ public class PackageManagerSettingsTests { ps2.setUsesSdkLibrariesVersionsMajor(new long[] { 34 }); settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2); - settingsUnderTest.writeLPr(); + settingsUnderTest.writeLPr(computer); settingsUnderTest.mPackages.clear(); settingsUnderTest.mDisabledSysPackages.clear(); - assertThat(settingsUnderTest.readLPw(createFakeUsers()), is(true)); + assertThat(settingsUnderTest.readLPw(computer, createFakeUsers()), is(true)); PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1); PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2); @@ -587,7 +590,7 @@ public class PackageManagerSettingsTests { Settings settings = makeSettings(); final WatchableTester watcher = new WatchableTester(settings, "testEnableDisable"); watcher.register(); - assertThat(settings.readLPw(createFakeUsers()), is(true)); + assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); watcher.verifyChangeReported("readLPw"); // Enable/Disable a package