From f9a03e8104b6fb45dbbd93e07134f7d248ca384f Mon Sep 17 00:00:00 2001 From: Sumedh Sen Date: Tue, 24 Jan 2023 10:49:58 -0800 Subject: [PATCH] Set system packages as stopped Apps preloaded on the system partition will be scanned with an initial state of "stopped=true". Packages can be added to an allowlist to skip setting them initially as stopped. Bug: 249514169 Test: atest PackageManagerServiceServerTests:PackageManagerSettingsTest CtsContentTestCases:SystemPackageDefaultStoppedStateTest Change-Id: I4d89dab65c01a21c4a74e61a1bfe35141b2fe954 --- .../server/pm/InstallPackageHelper.java | 13 ++++++ .../server/pm/PackageManagerService.java | 11 +++++ .../pm/PackageManagerServiceTestParams.java | 4 ++ .../android/server/pm/ScanPackageUtils.java | 4 +- .../java/com/android/server/pm/Settings.java | 14 ++++-- .../pm/PackageManagerSettingsTests.java | 46 +++++++++++++++++++ 6 files changed, 88 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index a4c9baa2f2c14..70e97588934a0 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -70,6 +70,7 @@ import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM; import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM; import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED; import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT; +import static com.android.server.pm.PackageManagerService.SCAN_AS_STOPPED_SYSTEM_APP; import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM; import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT; import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR; @@ -4215,6 +4216,18 @@ final class InstallPackageHelper { } } + // A new application appeared on /system, and we are seeing it for the first time. + // Its also not updated as we don't have a copy of it on /data. So, scan it in a + // STOPPED state. Ignore if it's an APEX package since stopped state does not affect them. + final boolean isApexPkg = (scanFlags & SCAN_AS_APEX) != 0; + if (mPm.mShouldStopSystemPackagesByDefault && scanSystemPartition + && !pkgAlreadyExists && !isApexPkg) { + String packageName = parsedPackage.getPackageName(); + if (!mPm.mInitialNonStoppedSystemPackages.contains(packageName)) { + scanFlags |= SCAN_AS_STOPPED_SYSTEM_APP; + } + } + final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, 0 /* currentTime */, user, null); return new Pair<>(scanResult, shouldHideSystemApp); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 94e96b01a5d75..bcc1d3b764b4c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -386,6 +386,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService static final int SCAN_DROP_CACHE = 1 << 24; static final int SCAN_AS_FACTORY = 1 << 25; static final int SCAN_AS_APEX = 1 << 26; + static final int SCAN_AS_STOPPED_SYSTEM_APP = 1 << 27; @IntDef(flag = true, prefix = { "SCAN_" }, value = { SCAN_NO_DEX, @@ -402,6 +403,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService SCAN_AS_INSTANT_APP, SCAN_AS_FULL_APP, SCAN_AS_VIRTUAL_PRELOAD, + SCAN_AS_STOPPED_SYSTEM_APP, }) @Retention(RetentionPolicy.SOURCE) public @interface ScanFlags {} @@ -963,6 +965,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService final @Nullable String mRecentsPackage; final @Nullable String mAmbientContextDetectionPackage; final @Nullable String mWearableSensingPackage; + final @NonNull Set mInitialNonStoppedSystemPackages; + final boolean mShouldStopSystemPackagesByDefault; private final @NonNull String mRequiredSdkSandboxPackage; @GuardedBy("mLock") @@ -1770,6 +1774,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService mOverlayConfigSignaturePackage = testParams.overlayConfigSignaturePackage; mResolveComponentName = testParams.resolveComponentName; mRequiredSdkSandboxPackage = testParams.requiredSdkSandboxPackage; + mInitialNonStoppedSystemPackages = testParams.initialNonStoppedSystemPackages; + mShouldStopSystemPackagesByDefault = testParams.shouldStopSystemPackagesByDefault; mLiveComputer = createLiveComputer(); mSnapshotStatistics = null; @@ -2096,6 +2102,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService mCacheDir = PackageManagerServiceUtils.preparePackageParserCache( mIsEngBuild, mIsUserDebugBuild, mIncrementalVersion); + mInitialNonStoppedSystemPackages = mInjector.getSystemConfig() + .getInitialNonStoppedSystemPackages(); + mShouldStopSystemPackagesByDefault = mContext.getResources() + .getBoolean(R.bool.config_stopSystemPackagesByDefault); + final int[] userIds = mUserManager.getUserIds(); PackageParser2 packageParser = mInjector.getScanningCachingPackageParser(); mOverlayConfig = mInitAppsHelper.initSystemApps(packageParser, packageSettings, userIds, diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java index e5cfa671a930d..0ed90e478e306 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java @@ -26,6 +26,7 @@ import android.os.Build; import android.os.Handler; import android.os.incremental.IncrementalManager; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.DisplayMetrics; import com.android.internal.annotations.VisibleForTesting; @@ -40,6 +41,7 @@ import com.android.server.pm.pkg.AndroidPackage; import java.io.File; import java.util.List; +import java.util.Set; @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public final class PackageManagerServiceTestParams { @@ -119,4 +121,6 @@ public final class PackageManagerServiceTestParams { public SuspendPackageHelper suspendPackageHelper; public DistractingPackageHelper distractingPackageHelper; public StorageEventHelper storageEventHelper; + public Set initialNonStoppedSystemPackages = new ArraySet<>(); + public boolean shouldStopSystemPackagesByDefault; } diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java index 830b096c696d0..253887107a04d 100644 --- a/services/core/java/com/android/server/pm/ScanPackageUtils.java +++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java @@ -31,6 +31,7 @@ import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM; import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM; import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED; import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT; +import static com.android.server.pm.PackageManagerService.SCAN_AS_STOPPED_SYSTEM_APP; import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM; import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT; import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR; @@ -198,6 +199,7 @@ final class ScanPackageUtils { if (createNewPackage) { final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0; + final boolean isStoppedSystemApp = (scanFlags & SCAN_AS_STOPPED_SYSTEM_APP) != 0; // Flags contain system values stored in the server variant of AndroidPackage, // and so the server-side PackageInfoUtils is still called, even without a @@ -212,7 +214,7 @@ final class ScanPackageUtils { AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage), AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage), parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user, - true /*allowInstall*/, instantApp, virtualPreload, + true /*allowInstall*/, instantApp, virtualPreload, isStoppedSystemApp, UserManagerService.getInstance(), usesSdkLibraries, parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(), diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 165e476b1de7c..0ef94e85102a2 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -1041,7 +1041,7 @@ public final class Settings implements Watchable, Snappable { File codePath, String legacyNativeLibraryPath, String primaryCpuAbi, String secondaryCpuAbi, long versionCode, int pkgFlags, int pkgPrivateFlags, UserHandle installUser, boolean allowInstall, boolean instantApp, - boolean virtualPreload, UserManagerService userManager, + boolean virtualPreload, boolean isStoppedSystemApp, UserManagerService userManager, String[] usesSdkLibraries, long[] usesSdkLibrariesVersions, String[] usesStaticLibraries, long[] usesStaticLibrariesVersions, Set mimeGroupNames, @NonNull UUID domainSetId) { @@ -1068,6 +1068,9 @@ public final class Settings implements Watchable, Snappable { pkgSetting.setFlags(pkgFlags) .setPrivateFlags(pkgPrivateFlags); } else { + int installUserId = installUser != null ? installUser.getIdentifier() + : UserHandle.USER_SYSTEM; + pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi, null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags, @@ -1086,8 +1089,6 @@ public final class Settings implements Watchable, Snappable { Slog.i(PackageManagerService.TAG, "Stopping package " + pkgName, e); } List users = getAllUsers(userManager); - int installUserId = installUser != null ? installUser.getIdentifier() - : UserHandle.USER_SYSTEM; if (users != null && allowInstall) { for (UserInfo user : users) { // By default we consider this app to be installed @@ -1126,6 +1127,13 @@ public final class Settings implements Watchable, Snappable { ); } } + } else if (isStoppedSystemApp) { + if (DEBUG_STOPPED) { + RuntimeException e = new RuntimeException("here"); + e.fillInStackTrace(); + Slog.i(PackageManagerService.TAG, "Stopping system package " + pkgName, e); + } + pkgSetting.setStopped(true, installUserId); } if (sharedUser != null) { pkgSetting.setAppId(sharedUser.mAppId); diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java index 6a1ccc50df584..dfced865febe5 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -1112,6 +1112,7 @@ public class PackageManagerSettingsTests { false /*allowInstall*/, false /*instantApp*/, false /*virtualPreload*/, + false /* stopped */, UserManagerService.getInstance(), null /*usesSdkLibraries*/, null /*usesSdkLibrariesVersions*/, @@ -1156,6 +1157,7 @@ public class PackageManagerSettingsTests { true /*allowInstall*/, false /*instantApp*/, false /*virtualPreload*/, + false /* stopped */, UserManagerService.getInstance(), null /*usesSdkLibraries*/, null /*usesSdkLibrariesVersions*/, @@ -1200,6 +1202,7 @@ public class PackageManagerSettingsTests { false /*allowInstall*/, false /*instantApp*/, false /*virtualPreload*/, + false /* stopped */, UserManagerService.getInstance(), null /*usesSdkLibraries*/, null /*usesSdkLibrariesVersions*/, @@ -1245,6 +1248,7 @@ public class PackageManagerSettingsTests { false /*allowInstall*/, false /*instantApp*/, false /*virtualPreload*/, + false /* stopped */, UserManagerService.getInstance(), null /*usesSdkLibraries*/, null /*usesSdkLibrariesVersions*/, @@ -1267,6 +1271,48 @@ public class PackageManagerSettingsTests { verifyUserState(userState, false /*notLaunched*/, false /*stopped*/, true /*installed*/); } + /** Create a new stopped system PackageSetting */ + @Test + public void testCreateNewSetting05() { + final PackageSetting testPkgSetting01 = Settings.createNewSetting( + PACKAGE_NAME, + null /*originalPkg*/, + null /*disabledPkg*/, + null /*realPkgName*/, + null /*sharedUser*/, + UPDATED_CODE_PATH /*codePath*/, + null /*legacyNativeLibraryPath*/, + "arm64-v8a" /*primaryCpuAbi*/, + "armeabi" /*secondaryCpuAbi*/, + UPDATED_VERSION_CODE /*versionCode*/, + ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/, + 0 /*pkgPrivateFlags*/, + UserHandle.SYSTEM /*installUser*/, + false /*allowInstall*/, + false /*instantApp*/, + false /*virtualPreload*/, + true /* stopped */, + UserManagerService.getInstance(), + null /*usesSdkLibraries*/, + null /*usesSdkLibrariesVersions*/, + null /*usesStaticLibraries*/, + null /*usesStaticLibrariesVersions*/, + null /*mimeGroups*/, + UUID.randomUUID()); + assertThat(testPkgSetting01.getAppId(), is(0)); + assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH)); + assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME)); + assertThat(testPkgSetting01.getFlags(), is(ApplicationInfo.FLAG_SYSTEM)); + assertThat(testPkgSetting01.getPrivateFlags(), is(0)); + assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a")); + assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a")); + assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("armeabi")); + assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("armeabi")); + assertThat(testPkgSetting01.getVersionCode(), is(UPDATED_VERSION_CODE)); + final PackageUserState userState = testPkgSetting01.readUserState(0); + verifyUserState(userState, false /*notLaunched*/, true /*stopped*/, true /*installed*/); + } + @Test public void testSetPkgStateLibraryFiles_addNewFiles() { final PackageSetting packageSetting = createPackageSetting("com.foo");