summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/res/res/values/config.xml23
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--data/etc/Android.bp6
-rw-r--r--data/etc/initial-package-stopped-states.xml38
-rw-r--r--services/core/java/com/android/server/SystemConfig.java22
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java13
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java11
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java4
-rw-r--r--services/core/java/com/android/server/pm/ScanPackageUtils.java4
-rw-r--r--services/core/java/com/android/server/pm/Settings.java23
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java46
11 files changed, 188 insertions, 4 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index afcc2fc095bd..263d4315fdc3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -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>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d82e898a64f4..fbed371d8662 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -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>
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index d0c3e5f6a91e..f233c6eca13b 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -36,6 +36,12 @@ prebuilt_etc {
}
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,
sub_dir: "sysconfig",
diff --git a/data/etc/initial-package-stopped-states.xml b/data/etc/initial-package-stopped-states.xml
new file mode 100644
index 000000000000..6bda2c0dbc26
--- /dev/null
+++ b/data/etc/initial-package-stopped-states.xml
@@ -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>
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 4854c37933e3..4b7612791fe7 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -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());
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index bd6bd75e60f3..0d5392be30ba 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;
@@ -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);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a02a4197bdea..c6a157968134 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -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,
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index e5cfa671a930..0ed90e478e30 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<String> 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 830b096c696d..253887107a04 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 165e476b1de7..4f0a1159a492 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<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.
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 75484d162282..a39e0216f4e5 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
@@ -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");