Merge changes from topic "stopped-sys-apps"

* changes:
  Set system packages as stopped on user creation
  Set system packages as stopped
  Allowlist for exempting packages from being marked as stopped by default
  Feature flag for toggling stop system packages default behavior
This commit is contained in:
Sumedh Sen
2023-01-31 23:20:46 +00:00
committed by Android (Google) Code Review
11 changed files with 188 additions and 4 deletions

View File

@@ -6230,4 +6230,27 @@
trusted certificate using the SHA-256 digest algorithm. -->
<string-array name="config_healthConnectMigrationKnownSigners">
</string-array>
<!-- The Universal Stylus Initiative (USI) protocol version supported by each display.
(@see https://universalstylus.org/).
The i-th value in this array corresponds to the supported USI version of the i-th display
listed in config_displayUniqueIdArray. On a single-display device, the
config_displayUniqueIdArray may be empty, in which case the only value in this array should
be the USI version for the main built-in display.
If the display does not support USI, the version value should be an empty string. If the
display supports USI, the version must be in the following format:
"<major-version>.<minor-version>"
For example, "", "1.0", and "2.0" are valid values. -->
<string-array name="config_displayUsiVersionArray" translatable="false">
<item>""</item>
</string-array>
<!-- Whether system apps should be scanned in the stopped state during initial boot.
Packages can be added by OEMs in an allowlist, to prevent them from being scanned as
"stopped" during initial boot of a device, or after an OTA update. Stopped state of
an app is not changed during subsequent reboots. -->
<bool name="config_stopSystemPackagesByDefault">false</bool>
</resources>

View File

@@ -4909,4 +4909,6 @@
<java-symbol type="string" name="config_mainDisplayShape"/>
<java-symbol type="string" name="config_secondaryDisplayShape"/>
<java-symbol type="array" name="config_displayShapeArray" />
<java-symbol type="bool" name="config_stopSystemPackagesByDefault"/>
</resources>

View File

@@ -35,6 +35,12 @@ prebuilt_etc {
src: "preinstalled-packages-platform.xml",
}
prebuilt_etc {
name: "initial-package-stopped-states.xml",
sub_dir: "sysconfig",
src: "initial-package-stopped-states.xml",
}
prebuilt_etc {
name: "preinstalled-packages-platform-overlays.xml",
product_specific: true,

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2023 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.
-->
<!--
This XML defines an allowlist for packages that should not be scanned in a "stopped" state.
When this feature is turned on (indicated by the config config_stopSystemPackagesByDefault in
core/res/res/values/config.xml) packages on the system partition that are encountered by
the PackageManagerService for the first time are scanned in the "stopped" state. This allowlist
is also considered while creating new users on the device. Stopped state is not set during
subsequent reboots.
Example usage
1. <initial-package-state package="com.example.app" stopped="false"/>
Indicates that a system package - com.example.app's initial stopped state should not be set
by the Package Manager. By default, system apps are marked as stopped.
2. <initial-package-state package="com.example.app" stopped="true"/>
Indicates that a system package - com.example.app's initial state should be set by the
Package Manager to "stopped=true". It will have the same effect on the
package's stopped state even if this package was not included in the allow list.
3. <initial-package-state package="com.example.app"/>
Invalid usage.
-->
<config></config>

View File

@@ -333,6 +333,11 @@ public class SystemConfig {
// Update ownership for system applications and the installers eligible to update them.
private final ArrayMap<String, String> mUpdateOwnersForSystemApps = new ArrayMap<>();
// Set of package names that should not be marked as "stopped" during initial device boot
// or when adding a new user. A new package not contained in this set will be
// marked as stopped by the system
@NonNull private final Set<String> mInitialNonStoppedSystemPackages = new ArraySet<>();
/**
* Map of system pre-defined, uniquely named actors; keys are namespace,
* value maps actor name to package name.
@@ -527,6 +532,10 @@ public class SystemConfig {
? null : mOverlayConfigSignaturePackage;
}
public Set<String> getInitialNonStoppedSystemPackages() {
return mInitialNonStoppedSystemPackages;
}
/**
* Only use for testing. Do NOT use in production code.
* @param readPermissions false to create an empty SystemConfig; true to read the permissions.
@@ -1445,6 +1454,19 @@ public class SystemConfig {
}
XmlUtils.skipCurrentTag(parser);
} break;
case "initial-package-state": {
String pkgName = parser.getAttributeValue(null, "package");
String stopped = parser.getAttributeValue(null, "stopped");
if (TextUtils.isEmpty(pkgName)) {
Slog.w(TAG, "<" + name + "> without package in " + permFile
+ " at " + parser.getPositionDescription());
} else if (TextUtils.isEmpty(stopped)) {
Slog.w(TAG, "<" + name + "> without stopped in " + permFile
+ " at " + parser.getPositionDescription());
} else if (!Boolean.parseBoolean(stopped)) {
mInitialNonStoppedSystemPackages.add(pkgName);
}
}
default: {
Slog.w(TAG, "Tag " + name + " is unknown in "
+ permFile + " at " + parser.getPositionDescription());

View File

@@ -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;
@@ -4237,6 +4238,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);

View File

@@ -387,6 +387,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,
@@ -403,6 +404,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 {}
@@ -964,6 +966,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
final @Nullable String mRecentsPackage;
final @Nullable String mAmbientContextDetectionPackage;
final @Nullable String mWearableSensingPackage;
final @NonNull Set<String> mInitialNonStoppedSystemPackages;
final boolean mShouldStopSystemPackagesByDefault;
private final @NonNull String mRequiredSdkSandboxPackage;
@GuardedBy("mLock")
@@ -1771,6 +1775,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;
@@ -2097,6 +2103,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,

View File

@@ -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<String> initialNonStoppedSystemPackages = new ArraySet<>();
public boolean shouldStopSystemPackagesByDefault;
}

View File

@@ -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(),

View File

@@ -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<String> 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<UserInfo> 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);
@@ -4422,6 +4430,15 @@ public final class Settings implements Watchable, Snappable {
ps.getPackageName()));
// Only system apps are initially installed.
ps.setInstalled(shouldReallyInstall, userHandle);
// Non-Apex system apps, that are not included in the allowlist in
// initialNonStoppedSystemPackages, should be marked as stopped by default.
final boolean shouldBeStopped = service.mShouldStopSystemPackagesByDefault
&& ps.isSystem()
&& !ps.isApex()
&& !service.mInitialNonStoppedSystemPackages.contains(ps.getPackageName());
ps.setStopped(shouldBeStopped, userHandle);
// If userTypeInstallablePackages is the *only* reason why we're not installing,
// then uninstallReason is USER_TYPE. If there's a different reason, or if we
// actually are installing, put UNKNOWN.

View File

@@ -1129,6 +1129,7 @@ public class PackageManagerSettingsTests {
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
false /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
@@ -1173,6 +1174,7 @@ public class PackageManagerSettingsTests {
true /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
false /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
@@ -1217,6 +1219,7 @@ public class PackageManagerSettingsTests {
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
false /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
@@ -1262,6 +1265,7 @@ public class PackageManagerSettingsTests {
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
false /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
@@ -1284,6 +1288,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");