Loading core/java/android/content/pm/PackagePartitions.java +56 −8 Original line number Diff line number Diff line Loading @@ -19,8 +19,11 @@ package android.content.pm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Build; import android.os.Build.Partition; import android.os.Environment; import android.os.FileUtils; import android.os.SystemProperties; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -64,19 +67,33 @@ public class PackagePartitions { */ private static final ArrayList<SystemPartition> SYSTEM_PARTITIONS = new ArrayList<>(Arrays.asList( new SystemPartition(Environment.getRootDirectory(), PARTITION_SYSTEM, new SystemPartition(Environment.getRootDirectory(), PARTITION_SYSTEM, Partition.PARTITION_NAME_SYSTEM, true /* containsPrivApp */, false /* containsOverlay */), new SystemPartition(Environment.getVendorDirectory(), PARTITION_VENDOR, new SystemPartition(Environment.getVendorDirectory(), PARTITION_VENDOR, Partition.PARTITION_NAME_VENDOR, true /* containsPrivApp */, true /* containsOverlay */), new SystemPartition(Environment.getOdmDirectory(), PARTITION_ODM, new SystemPartition(Environment.getOdmDirectory(), PARTITION_ODM, Partition.PARTITION_NAME_ODM, true /* containsPrivApp */, true /* containsOverlay */), new SystemPartition(Environment.getOemDirectory(), PARTITION_OEM, new SystemPartition(Environment.getOemDirectory(), PARTITION_OEM, Partition.PARTITION_NAME_OEM, false /* containsPrivApp */, true /* containsOverlay */), new SystemPartition(Environment.getProductDirectory(), PARTITION_PRODUCT, new SystemPartition(Environment.getProductDirectory(), PARTITION_PRODUCT, Partition.PARTITION_NAME_PRODUCT, true /* containsPrivApp */, true /* containsOverlay */), new SystemPartition(Environment.getSystemExtDirectory(), PARTITION_SYSTEM_EXT, new SystemPartition(Environment.getSystemExtDirectory(), PARTITION_SYSTEM_EXT, Partition.PARTITION_NAME_SYSTEM_EXT, true /* containsPrivApp */, true /* containsOverlay */))); /** * A string to represent the fingerprint of this build and all package partitions. Using it to * determine whether the system update has occurred. Different from {@link Build#FINGERPRINT}, * this string is digested from the fingerprints of the build and all package partitions to * help detect the partition update. */ public static final String FINGERPRINT = getFingerprint(); /** * Returns a list in which the elements are products of the specified function applied to the * list of {@link #SYSTEM_PARTITIONS} in increasing specificity order. Loading @@ -101,12 +118,32 @@ public class PackagePartitions { } } /** * Returns a fingerprint string for this build and all package partitions. The string is * digested from the fingerprints of the build and all package partitions. * * @return A string to represent the fingerprint of this build and all package partitions. */ @NonNull private static String getFingerprint() { final String[] digestProperties = new String[SYSTEM_PARTITIONS.size() + 1]; for (int i = 0; i < SYSTEM_PARTITIONS.size(); i++) { final String partitionName = SYSTEM_PARTITIONS.get(i).getName(); digestProperties[i] = "ro." + partitionName + ".build.fingerprint"; } digestProperties[SYSTEM_PARTITIONS.size()] = "ro.build.fingerprint"; // build fingerprint return SystemProperties.digestOf(digestProperties); } /** Represents a partition that contains application packages. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public static class SystemPartition { @PartitionType public final int type; @NonNull private final String mName; @NonNull private final DeferredCanonicalFile mFolder; Loading @@ -122,9 +159,10 @@ public class PackagePartitions { @NonNull private final File mNonConicalFolder; private SystemPartition(@NonNull File folder, @PartitionType int type, private SystemPartition(@NonNull File folder, @PartitionType int type, String name, boolean containsPrivApp, boolean containsOverlay) { this.type = type; this.mName = name; this.mFolder = new DeferredCanonicalFile(folder); this.mAppFolder = new DeferredCanonicalFile(folder, "app"); this.mPrivAppFolder = containsPrivApp ? new DeferredCanonicalFile(folder, "priv-app") Loading @@ -136,6 +174,7 @@ public class PackagePartitions { public SystemPartition(@NonNull SystemPartition original) { this.type = original.type; this.mName = original.mName; this.mFolder = new DeferredCanonicalFile(original.mFolder.getFile()); this.mAppFolder = original.mAppFolder; this.mPrivAppFolder = original.mPrivAppFolder; Loading @@ -148,10 +187,19 @@ public class PackagePartitions { * different root folder. */ public SystemPartition(@NonNull File rootFolder, @NonNull SystemPartition partition) { this(rootFolder, partition.type, partition.mPrivAppFolder != null, this(rootFolder, partition.type, partition.mName, partition.mPrivAppFolder != null, partition.mOverlayFolder != null); } /** * Returns the name identifying the partition. * @see Partition */ @NonNull public String getName() { return mName; } /** Returns the canonical folder of the partition. */ @NonNull public File getFolder() { Loading core/java/android/os/Build.java +18 −2 Original line number Diff line number Diff line Loading @@ -1294,6 +1294,18 @@ public class Build { public static class Partition { /** The name identifying the system partition. */ public static final String PARTITION_NAME_SYSTEM = "system"; /** @hide */ public static final String PARTITION_NAME_BOOTIMAGE = "bootimage"; /** @hide */ public static final String PARTITION_NAME_ODM = "odm"; /** @hide */ public static final String PARTITION_NAME_OEM = "oem"; /** @hide */ public static final String PARTITION_NAME_PRODUCT = "product"; /** @hide */ public static final String PARTITION_NAME_SYSTEM_EXT = "system_ext"; /** @hide */ public static final String PARTITION_NAME_VENDOR = "vendor"; private final String mName; private final String mFingerprint; Loading Loading @@ -1350,8 +1362,12 @@ public class Build { ArrayList<Partition> partitions = new ArrayList(); String[] names = new String[] { "bootimage", "odm", "product", "system_ext", Partition.PARTITION_NAME_SYSTEM, "vendor" Partition.PARTITION_NAME_BOOTIMAGE, Partition.PARTITION_NAME_ODM, Partition.PARTITION_NAME_PRODUCT, Partition.PARTITION_NAME_SYSTEM_EXT, Partition.PARTITION_NAME_SYSTEM, Partition.PARTITION_NAME_VENDOR }; for (String name : names) { String fingerprint = SystemProperties.get("ro." + name + ".build.fingerprint"); Loading core/tests/coretests/src/android/content/pm/PackagePartitionsTest.java 0 → 100644 +49 −0 Original line number Diff line number Diff line /* * 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 static com.google.common.truth.Truth.assertThat; import static java.util.function.Function.identity; import android.content.pm.PackagePartitions.SystemPartition; import android.os.SystemProperties; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; @RunWith(AndroidJUnit4.class) public class PackagePartitionsTest { @Test public void testPackagePartitionsFingerprint() { final ArrayList<SystemPartition> partitions = PackagePartitions.getOrderedPartitions( identity()); final String[] properties = new String[partitions.size() + 1]; for (int i = 0; i < partitions.size(); i++) { final String name = partitions.get(i).getName(); properties[i] = "ro." + name + ".build.fingerprint"; } properties[partitions.size()] = "ro.build.fingerprint"; assertThat(SystemProperties.digestOf(properties)).isEqualTo(PackagePartitions.FINGERPRINT); } } services/core/java/com/android/server/am/UserController.java +2 −2 Original line number Diff line number Diff line Loading @@ -67,10 +67,10 @@ import android.content.Intent; import android.content.PermissionChecker; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackagePartitions; import android.content.pm.UserInfo; import android.os.BatteryStats; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.Handler; Loading Loading @@ -719,7 +719,7 @@ class UserController implements Handler.Callback { // purposefully block sending BOOT_COMPLETED until after all // PRE_BOOT receivers are finished to avoid ANR'ing apps final UserInfo info = getUserInfo(userId); if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT) if (!Objects.equals(info.lastLoggedInFingerprint, PackagePartitions.FINGERPRINT) || SystemProperties.getBoolean("persist.pm.mock-upgrade", false)) { // Suppress double notifications for managed profiles that // were unlocked automatically as part of their parent user Loading services/core/java/com/android/server/pm/PackageManagerService.java +7 −6 Original line number Diff line number Diff line Loading @@ -1493,8 +1493,8 @@ public class PackageManagerService extends IPackageManager.Stub } PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest, Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL, SNAPSHOT_ENABLED); PackagePartitions.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL, SNAPSHOT_ENABLED); t.traceEnd(); // "create package manager" final CompatChange.ChangeListener selinuxChangeListener = packageName -> { Loading Loading @@ -1907,8 +1907,8 @@ public class PackageManagerService extends IPackageManager.Stub mIsUpgrade = !buildFingerprint.equals(ver.fingerprint); if (mIsUpgrade) { PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT); PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from " + ver.fingerprint + " to " + PackagePartitions.FINGERPRINT); } // when upgrading from pre-M, promote system app permissions from install to runtime Loading Loading @@ -2006,7 +2006,8 @@ public class PackageManagerService extends IPackageManager.Stub // this situation. if (mIsUpgrade) { Slog.i(TAG, "Build fingerprint changed from " + ver.fingerprint + " to " + Build.FINGERPRINT + "; regranting permissions for internal storage"); + PackagePartitions.FINGERPRINT + "; regranting permissions for internal storage"); } mPermissionManager.onStorageVolumeMounted( StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade); Loading Loading @@ -2040,7 +2041,7 @@ public class PackageManagerService extends IPackageManager.Stub | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES); } } ver.fingerprint = Build.FINGERPRINT; ver.fingerprint = PackagePartitions.FINGERPRINT; } // Legacy existing (installed before Q) non-system apps to hide Loading Loading
core/java/android/content/pm/PackagePartitions.java +56 −8 Original line number Diff line number Diff line Loading @@ -19,8 +19,11 @@ package android.content.pm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Build; import android.os.Build.Partition; import android.os.Environment; import android.os.FileUtils; import android.os.SystemProperties; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -64,19 +67,33 @@ public class PackagePartitions { */ private static final ArrayList<SystemPartition> SYSTEM_PARTITIONS = new ArrayList<>(Arrays.asList( new SystemPartition(Environment.getRootDirectory(), PARTITION_SYSTEM, new SystemPartition(Environment.getRootDirectory(), PARTITION_SYSTEM, Partition.PARTITION_NAME_SYSTEM, true /* containsPrivApp */, false /* containsOverlay */), new SystemPartition(Environment.getVendorDirectory(), PARTITION_VENDOR, new SystemPartition(Environment.getVendorDirectory(), PARTITION_VENDOR, Partition.PARTITION_NAME_VENDOR, true /* containsPrivApp */, true /* containsOverlay */), new SystemPartition(Environment.getOdmDirectory(), PARTITION_ODM, new SystemPartition(Environment.getOdmDirectory(), PARTITION_ODM, Partition.PARTITION_NAME_ODM, true /* containsPrivApp */, true /* containsOverlay */), new SystemPartition(Environment.getOemDirectory(), PARTITION_OEM, new SystemPartition(Environment.getOemDirectory(), PARTITION_OEM, Partition.PARTITION_NAME_OEM, false /* containsPrivApp */, true /* containsOverlay */), new SystemPartition(Environment.getProductDirectory(), PARTITION_PRODUCT, new SystemPartition(Environment.getProductDirectory(), PARTITION_PRODUCT, Partition.PARTITION_NAME_PRODUCT, true /* containsPrivApp */, true /* containsOverlay */), new SystemPartition(Environment.getSystemExtDirectory(), PARTITION_SYSTEM_EXT, new SystemPartition(Environment.getSystemExtDirectory(), PARTITION_SYSTEM_EXT, Partition.PARTITION_NAME_SYSTEM_EXT, true /* containsPrivApp */, true /* containsOverlay */))); /** * A string to represent the fingerprint of this build and all package partitions. Using it to * determine whether the system update has occurred. Different from {@link Build#FINGERPRINT}, * this string is digested from the fingerprints of the build and all package partitions to * help detect the partition update. */ public static final String FINGERPRINT = getFingerprint(); /** * Returns a list in which the elements are products of the specified function applied to the * list of {@link #SYSTEM_PARTITIONS} in increasing specificity order. Loading @@ -101,12 +118,32 @@ public class PackagePartitions { } } /** * Returns a fingerprint string for this build and all package partitions. The string is * digested from the fingerprints of the build and all package partitions. * * @return A string to represent the fingerprint of this build and all package partitions. */ @NonNull private static String getFingerprint() { final String[] digestProperties = new String[SYSTEM_PARTITIONS.size() + 1]; for (int i = 0; i < SYSTEM_PARTITIONS.size(); i++) { final String partitionName = SYSTEM_PARTITIONS.get(i).getName(); digestProperties[i] = "ro." + partitionName + ".build.fingerprint"; } digestProperties[SYSTEM_PARTITIONS.size()] = "ro.build.fingerprint"; // build fingerprint return SystemProperties.digestOf(digestProperties); } /** Represents a partition that contains application packages. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public static class SystemPartition { @PartitionType public final int type; @NonNull private final String mName; @NonNull private final DeferredCanonicalFile mFolder; Loading @@ -122,9 +159,10 @@ public class PackagePartitions { @NonNull private final File mNonConicalFolder; private SystemPartition(@NonNull File folder, @PartitionType int type, private SystemPartition(@NonNull File folder, @PartitionType int type, String name, boolean containsPrivApp, boolean containsOverlay) { this.type = type; this.mName = name; this.mFolder = new DeferredCanonicalFile(folder); this.mAppFolder = new DeferredCanonicalFile(folder, "app"); this.mPrivAppFolder = containsPrivApp ? new DeferredCanonicalFile(folder, "priv-app") Loading @@ -136,6 +174,7 @@ public class PackagePartitions { public SystemPartition(@NonNull SystemPartition original) { this.type = original.type; this.mName = original.mName; this.mFolder = new DeferredCanonicalFile(original.mFolder.getFile()); this.mAppFolder = original.mAppFolder; this.mPrivAppFolder = original.mPrivAppFolder; Loading @@ -148,10 +187,19 @@ public class PackagePartitions { * different root folder. */ public SystemPartition(@NonNull File rootFolder, @NonNull SystemPartition partition) { this(rootFolder, partition.type, partition.mPrivAppFolder != null, this(rootFolder, partition.type, partition.mName, partition.mPrivAppFolder != null, partition.mOverlayFolder != null); } /** * Returns the name identifying the partition. * @see Partition */ @NonNull public String getName() { return mName; } /** Returns the canonical folder of the partition. */ @NonNull public File getFolder() { Loading
core/java/android/os/Build.java +18 −2 Original line number Diff line number Diff line Loading @@ -1294,6 +1294,18 @@ public class Build { public static class Partition { /** The name identifying the system partition. */ public static final String PARTITION_NAME_SYSTEM = "system"; /** @hide */ public static final String PARTITION_NAME_BOOTIMAGE = "bootimage"; /** @hide */ public static final String PARTITION_NAME_ODM = "odm"; /** @hide */ public static final String PARTITION_NAME_OEM = "oem"; /** @hide */ public static final String PARTITION_NAME_PRODUCT = "product"; /** @hide */ public static final String PARTITION_NAME_SYSTEM_EXT = "system_ext"; /** @hide */ public static final String PARTITION_NAME_VENDOR = "vendor"; private final String mName; private final String mFingerprint; Loading Loading @@ -1350,8 +1362,12 @@ public class Build { ArrayList<Partition> partitions = new ArrayList(); String[] names = new String[] { "bootimage", "odm", "product", "system_ext", Partition.PARTITION_NAME_SYSTEM, "vendor" Partition.PARTITION_NAME_BOOTIMAGE, Partition.PARTITION_NAME_ODM, Partition.PARTITION_NAME_PRODUCT, Partition.PARTITION_NAME_SYSTEM_EXT, Partition.PARTITION_NAME_SYSTEM, Partition.PARTITION_NAME_VENDOR }; for (String name : names) { String fingerprint = SystemProperties.get("ro." + name + ".build.fingerprint"); Loading
core/tests/coretests/src/android/content/pm/PackagePartitionsTest.java 0 → 100644 +49 −0 Original line number Diff line number Diff line /* * 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 static com.google.common.truth.Truth.assertThat; import static java.util.function.Function.identity; import android.content.pm.PackagePartitions.SystemPartition; import android.os.SystemProperties; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; @RunWith(AndroidJUnit4.class) public class PackagePartitionsTest { @Test public void testPackagePartitionsFingerprint() { final ArrayList<SystemPartition> partitions = PackagePartitions.getOrderedPartitions( identity()); final String[] properties = new String[partitions.size() + 1]; for (int i = 0; i < partitions.size(); i++) { final String name = partitions.get(i).getName(); properties[i] = "ro." + name + ".build.fingerprint"; } properties[partitions.size()] = "ro.build.fingerprint"; assertThat(SystemProperties.digestOf(properties)).isEqualTo(PackagePartitions.FINGERPRINT); } }
services/core/java/com/android/server/am/UserController.java +2 −2 Original line number Diff line number Diff line Loading @@ -67,10 +67,10 @@ import android.content.Intent; import android.content.PermissionChecker; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackagePartitions; import android.content.pm.UserInfo; import android.os.BatteryStats; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.Handler; Loading Loading @@ -719,7 +719,7 @@ class UserController implements Handler.Callback { // purposefully block sending BOOT_COMPLETED until after all // PRE_BOOT receivers are finished to avoid ANR'ing apps final UserInfo info = getUserInfo(userId); if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT) if (!Objects.equals(info.lastLoggedInFingerprint, PackagePartitions.FINGERPRINT) || SystemProperties.getBoolean("persist.pm.mock-upgrade", false)) { // Suppress double notifications for managed profiles that // were unlocked automatically as part of their parent user Loading
services/core/java/com/android/server/pm/PackageManagerService.java +7 −6 Original line number Diff line number Diff line Loading @@ -1493,8 +1493,8 @@ public class PackageManagerService extends IPackageManager.Stub } PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest, Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL, SNAPSHOT_ENABLED); PackagePartitions.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL, SNAPSHOT_ENABLED); t.traceEnd(); // "create package manager" final CompatChange.ChangeListener selinuxChangeListener = packageName -> { Loading Loading @@ -1907,8 +1907,8 @@ public class PackageManagerService extends IPackageManager.Stub mIsUpgrade = !buildFingerprint.equals(ver.fingerprint); if (mIsUpgrade) { PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT); PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from " + ver.fingerprint + " to " + PackagePartitions.FINGERPRINT); } // when upgrading from pre-M, promote system app permissions from install to runtime Loading Loading @@ -2006,7 +2006,8 @@ public class PackageManagerService extends IPackageManager.Stub // this situation. if (mIsUpgrade) { Slog.i(TAG, "Build fingerprint changed from " + ver.fingerprint + " to " + Build.FINGERPRINT + "; regranting permissions for internal storage"); + PackagePartitions.FINGERPRINT + "; regranting permissions for internal storage"); } mPermissionManager.onStorageVolumeMounted( StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade); Loading Loading @@ -2040,7 +2041,7 @@ public class PackageManagerService extends IPackageManager.Stub | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES); } } ver.fingerprint = Build.FINGERPRINT; ver.fingerprint = PackagePartitions.FINGERPRINT; } // Legacy existing (installed before Q) non-system apps to hide Loading