Loading services/core/java/com/android/server/pm/PackageManagerService.java +65 −49 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ import com.android.server.SystemConfig; import com.android.server.Watchdog; import com.android.server.pm.PermissionsState.PermissionState; import com.android.server.pm.Settings.DatabaseVersion; import com.android.server.pm.Settings.VersionInfo; import com.android.server.storage.DeviceStorageMonitorInternal; import org.xmlpull.v1.XmlPullParser; Loading Loading @@ -1654,6 +1655,11 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public void onVolumeForgotten(String fsUuid) { if (TextUtils.isEmpty(fsUuid)) { Slog.w(TAG, "Forgetting internal storage is probably a mistake; ignoring"); return; } // Remove any apps installed on the forgotten volume synchronized (mPackages) { final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(fsUuid); Loading @@ -1663,6 +1669,7 @@ public class PackageManagerService extends IPackageManager.Stub { UserHandle.USER_OWNER, PackageManager.DELETE_ALL_USERS); } mSettings.onVolumeForgotten(fsUuid); mSettings.writeLPr(); } } Loading Loading @@ -2239,17 +2246,16 @@ public class PackageManagerService extends IPackageManager.Stub { // cases get permissions that the user didn't initially explicitly // allow... it would be nice to have some better way to handle // this situation. final boolean regrantPermissions = mSettings.mInternalSdkPlatform != mSdkVersion; if (regrantPermissions) Slog.i(TAG, "Platform changed from " + mSettings.mInternalSdkPlatform + " to " + mSdkVersion + "; regranting permissions for internal storage"); mSettings.mInternalSdkPlatform = mSdkVersion; updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL | (regrantPermissions ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL) : 0)); final VersionInfo ver = mSettings.getInternalVersion(); int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to " + mSdkVersion + "; regranting permissions for internal storage"); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } updatePermissionsLPw(null, null, updateFlags); ver.sdkVersion = mSdkVersion; // If this is the first boot, and it is a normal boot, then // we need to initialize the default preferred apps. Loading @@ -2261,20 +2267,22 @@ public class PackageManagerService extends IPackageManager.Stub { // If this is first boot after an OTA, and a normal boot, then // we need to clear code cache directories. mIsUpgrade = !Build.FINGERPRINT.equals(mSettings.mFingerprint); mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint); if (mIsUpgrade && !onlyCore) { Slog.i(TAG, "Build fingerprint changed; clearing code caches"); for (int i = 0; i < mSettings.mPackages.size(); i++) { final PackageSetting ps = mSettings.mPackages.valueAt(i); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) { deleteCodeCacheDirsLI(ps.volumeUuid, ps.name); } mSettings.mFingerprint = Build.FINGERPRINT; } ver.fingerprint = Build.FINGERPRINT; } checkDefaultBrowser(); // All the changes are done during package scanning. mSettings.updateInternalDatabaseVersion(); ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION; // can downgrade to reader mSettings.writeLPr(); Loading Loading @@ -3919,10 +3927,8 @@ public class PackageManagerService extends IPackageManager.Stub { * were updated, return true. */ private boolean isCompatSignatureUpdateNeeded(PackageParser.Package scannedPkg) { return (isExternal(scannedPkg) && mSettings.isExternalDatabaseVersionOlderThan( DatabaseVersion.SIGNATURE_END_ENTITY)) || (!isExternal(scannedPkg) && mSettings.isInternalDatabaseVersionOlderThan( DatabaseVersion.SIGNATURE_END_ENTITY)); final VersionInfo ver = getSettingsVersionForPackage(scannedPkg); return ver.databaseVersion < DatabaseVersion.SIGNATURE_END_ENTITY; } /** Loading Loading @@ -3969,13 +3975,8 @@ public class PackageManagerService extends IPackageManager.Stub { } private boolean isRecoverSignatureUpdateNeeded(PackageParser.Package scannedPkg) { if (isExternal(scannedPkg)) { return mSettings.isExternalDatabaseVersionOlderThan( DatabaseVersion.SIGNATURE_MALFORMED_RECOVER); } else { return mSettings.isInternalDatabaseVersionOlderThan( DatabaseVersion.SIGNATURE_MALFORMED_RECOVER); } final VersionInfo ver = getSettingsVersionForPackage(scannedPkg); return ver.databaseVersion < DatabaseVersion.SIGNATURE_MALFORMED_RECOVER; } private int compareSignaturesRecover(PackageSignatures existingSigs, Loading Loading @@ -12491,6 +12492,18 @@ public class PackageManagerService extends IPackageManager.Stub { return installFlags; } private VersionInfo getSettingsVersionForPackage(PackageParser.Package pkg) { if (isExternal(pkg)) { if (TextUtils.isEmpty(pkg.volumeUuid)) { return mSettings.getExternalVersion(); } else { return mSettings.findOrCreateVersion(pkg.volumeUuid); } } else { return mSettings.getInternalVersion(); } } private void deleteTempPackageFiles() { final FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { Loading Loading @@ -14756,16 +14769,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (dumpState.onTitlePrinted()) pw.println(); pw.println("Database versions:"); pw.print(" SDK Version:"); pw.print(" internal="); pw.print(mSettings.mInternalSdkPlatform); pw.print(" external="); pw.println(mSettings.mExternalSdkPlatform); pw.print(" DB Version:"); pw.print(" internal="); pw.print(mSettings.mInternalDatabaseVersion); pw.print(" external="); pw.println(mSettings.mExternalDatabaseVersion); mSettings.dumpVersionLPr(new IndentingPrintWriter(pw, " ")); } } Loading Loading @@ -15412,20 +15416,18 @@ public class PackageManagerService extends IPackageManager.Stub { // cases get permissions that the user didn't initially explicitly // allow... it would be nice to have some better way to handle // this situation. final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion; if (regrantPermissions) Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to " + mSdkVersion + "; regranting permissions for external storage"); mSettings.mExternalSdkPlatform = mSdkVersion; final VersionInfo ver = mSettings.getExternalVersion(); // Make sure group IDs have been assigned, and any permission // changes in other apps are accounted for updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL | (regrantPermissions ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL) : 0)); int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to " + mSdkVersion + "; regranting permissions for external"); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } updatePermissionsLPw(null, null, updateFlags); mSettings.updateExternalDatabaseVersion(); // Yay, everything is now upgraded ver.forceCurrent(); // can downgrade to reader // Persist settings Loading Loading @@ -15517,6 +15519,7 @@ public class PackageManagerService extends IPackageManager.Stub { final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE; synchronized (mInstallLock) { synchronized (mPackages) { final VersionInfo ver = mSettings.findOrCreateVersion(vol.fsUuid); final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid); for (PackageSetting ps : packages) { final PackageParser.Package pkg; Loading @@ -15526,9 +15529,22 @@ public class PackageManagerService extends IPackageManager.Stub { } catch (PackageManagerException e) { Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage()); } if (!Build.FINGERPRINT.equals(ver.fingerprint)) { deleteCodeCacheDirsLI(ps.volumeUuid, ps.name); } } int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to " + mSdkVersion + "; regranting permissions for " + vol.fsUuid); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } updatePermissionsLPw(null, null, updateFlags); // TODO: regrant any permissions that changed based since original install // Yay, everything is now upgraded ver.forceCurrent(); mSettings.writeLPr(); } services/core/java/com/android/server/pm/Settings.java +140 −101 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.JournaledFile; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; Loading Loading @@ -129,7 +130,7 @@ final class Settings { * Note that care should be taken to make sure all database upgrades are * idempotent. */ private static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_MALFORMED_RECOVER; public static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_MALFORMED_RECOVER; /** * This class contains constants that can be referred to from upgrade code. Loading Loading @@ -177,11 +178,12 @@ final class Settings { "persistent-preferred-activities"; static final String TAG_CROSS_PROFILE_INTENT_FILTERS = "crossProfile-intent-filters"; public static final String TAG_DOMAIN_VERIFICATION = "domain-verification"; public static final String TAG_DEFAULT_APPS= "default-apps"; public static final String TAG_ALL_INTENT_FILTER_VERIFICATION = private static final String TAG_DOMAIN_VERIFICATION = "domain-verification"; private static final String TAG_DEFAULT_APPS = "default-apps"; private static final String TAG_ALL_INTENT_FILTER_VERIFICATION = "all-intent-filter-verifications"; public static final String TAG_DEFAULT_BROWSER= "default-browser"; private static final String TAG_DEFAULT_BROWSER = "default-browser"; private static final String TAG_VERSION = "version"; private static final String ATTR_NAME = "name"; private static final String ATTR_USER = "user"; Loading @@ -202,6 +204,9 @@ final class Settings { private static final String ATTR_PACKAGE_NAME = "packageName"; private static final String ATTR_FINGERPRINT = "fingerprint"; private static final String ATTR_APP_LINK_GENERATION = "app-link-generation"; private static final String ATTR_VOLUME_UUID = "volumeUuid"; private static final String ATTR_SDK_VERSION = "sdkVersion"; private static final String ATTR_DATABASE_VERSION = "databaseVersion"; private final Object mLock; Loading @@ -226,27 +231,43 @@ final class Settings { private static int mFirstAvailableUid = 0; // TODO: store SDK versions and fingerprint for each volume UUID /** Map from volume UUID to {@link VersionInfo} */ private ArrayMap<String, VersionInfo> mVersion = new ArrayMap<>(); // These are the last platform API version we were using for // the apps installed on internal and external storage. It is // used to grant newer permissions one time during a system upgrade. int mInternalSdkPlatform; int mExternalSdkPlatform; /** * Version details for a storage volume that may hold apps. */ public static class VersionInfo { /** * These are the last platform API version we were using for the apps * installed on internal and external storage. It is used to grant newer * permissions one time during a system upgrade. */ int sdkVersion; /** * The current database version for apps on internal storage. This is * used to upgrade the format of the packages.xml database not necessarily * tied to an SDK version. * used to upgrade the format of the packages.xml database not * necessarily tied to an SDK version. */ int mInternalDatabaseVersion; int mExternalDatabaseVersion; int databaseVersion; /** * Last known value of {@link Build#FINGERPRINT}. Used to determine when an * system update has occurred, meaning we need to clear code caches. * Last known value of {@link Build#FINGERPRINT}. Used to determine when * an system update has occurred, meaning we need to clear code caches. */ String mFingerprint; String fingerprint; /** * Force all version information to match current system values, * typically after resolving any required upgrade steps. */ public void forceCurrent() { sdkVersion = Build.VERSION.SDK_INT; databaseVersion = CURRENT_DATABASE_VERSION; fingerprint = Build.FINGERPRINT; } } Boolean mReadExternalStorageEnforced; Loading Loading @@ -1188,38 +1209,26 @@ final class Settings { .onDefaultRuntimePermissionsGrantedLPr(userId); } /** * Returns whether the current database has is older than {@code version} * for apps on internal storage. */ public boolean isInternalDatabaseVersionOlderThan(int version) { return mInternalDatabaseVersion < version; public VersionInfo findOrCreateVersion(String volumeUuid) { VersionInfo ver = mVersion.get(volumeUuid); if (ver == null) { ver = new VersionInfo(); ver.forceCurrent(); mVersion.put(volumeUuid, ver); } return ver; } /** * Returns whether the current database has is older than {@code version} * for apps on external storage. */ public boolean isExternalDatabaseVersionOlderThan(int version) { return mExternalDatabaseVersion < version; public VersionInfo getInternalVersion() { return mVersion.get(StorageManager.UUID_PRIVATE_INTERNAL); } /** * Updates the database version for apps on internal storage. Called after * call the updates to the database format are done for apps on internal * storage after the initial start-up scan. */ public void updateInternalDatabaseVersion() { mInternalDatabaseVersion = CURRENT_DATABASE_VERSION; public VersionInfo getExternalVersion() { return mVersion.get(StorageManager.UUID_PRIMARY_PHYSICAL); } /** * Updates the database version for apps on internal storage. Called after * call the updates to the database format are done for apps on internal * storage after the initial start-up scan. */ public void updateExternalDatabaseVersion() { mExternalDatabaseVersion = CURRENT_DATABASE_VERSION; public void onVolumeForgotten(String fsUuid) { mVersion.remove(fsUuid); } /** Loading Loading @@ -2060,16 +2069,17 @@ final class Settings { serializer.startTag(null, "packages"); serializer.startTag(null, "last-platform-version"); serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform)); serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform)); serializer.attribute(null, "fingerprint", mFingerprint); serializer.endTag(null, "last-platform-version"); for (int i = 0; i < mVersion.size(); i++) { final String volumeUuid = mVersion.keyAt(i); final VersionInfo ver = mVersion.valueAt(i); serializer.startTag(null, "database-version"); serializer.attribute(null, "internal", Integer.toString(mInternalDatabaseVersion)); serializer.attribute(null, "external", Integer.toString(mExternalDatabaseVersion)); serializer.endTag(null, "database-version"); serializer.startTag(null, TAG_VERSION); XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid); XmlUtils.writeIntAttribute(serializer, ATTR_SDK_VERSION, ver.sdkVersion); XmlUtils.writeIntAttribute(serializer, ATTR_DATABASE_VERSION, ver.databaseVersion); XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint); serializer.endTag(null, TAG_VERSION); } if (mVerifierDeviceIdentity != null) { serializer.startTag(null, "verifier"); Loading Loading @@ -2499,8 +2509,10 @@ final class Settings { mReadMessages.append("No settings file found\n"); PackageManagerService.reportSettingsProblem(Log.INFO, "No settings file; creating initial state"); mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion; mFingerprint = Build.FINGERPRINT; // It's enough to just touch version details to create them // with default values findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL); findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL); return false; } str = new FileInputStream(mSettingsFilename); Loading Loading @@ -2584,48 +2596,27 @@ final class Settings { } else if (tagName.equals("restored-ivi")) { readRestoredIntentFilterVerifications(parser); } else if (tagName.equals("last-platform-version")) { mInternalSdkPlatform = mExternalSdkPlatform = 0; try { String internal = parser.getAttributeValue(null, "internal"); if (internal != null) { mInternalSdkPlatform = Integer.parseInt(internal); } String external = parser.getAttributeValue(null, "external"); if (external != null) { mExternalSdkPlatform = Integer.parseInt(external); } } catch (NumberFormatException e) { } mFingerprint = parser.getAttributeValue(null, "fingerprint"); // Upgrade from older XML schema final VersionInfo internal = findOrCreateVersion( StorageManager.UUID_PRIVATE_INTERNAL); final VersionInfo external = findOrCreateVersion( StorageManager.UUID_PRIMARY_PHYSICAL); internal.sdkVersion = XmlUtils.readIntAttribute(parser, "internal", 0); external.sdkVersion = XmlUtils.readIntAttribute(parser, "external", 0); internal.fingerprint = external.fingerprint = XmlUtils.readStringAttribute(parser, "fingerprint"); // If the build is setup to drop runtime permissions // on update drop the files before loading them. if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) { if (!Build.FINGERPRINT.equals(mFingerprint)) { if (users == null) { mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( UserHandle.USER_OWNER); } else { for (UserInfo user : users) { mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( user.id); } } } } } else if (tagName.equals("database-version")) { mInternalDatabaseVersion = mExternalDatabaseVersion = 0; try { String internalDbVersionString = parser.getAttributeValue(null, "internal"); if (internalDbVersionString != null) { mInternalDatabaseVersion = Integer.parseInt(internalDbVersionString); } String externalDbVersionString = parser.getAttributeValue(null, "external"); if (externalDbVersionString != null) { mExternalDatabaseVersion = Integer.parseInt(externalDbVersionString); } } catch (NumberFormatException ignored) { } // Upgrade from older XML schema final VersionInfo internal = findOrCreateVersion( StorageManager.UUID_PRIVATE_INTERNAL); final VersionInfo external = findOrCreateVersion( StorageManager.UUID_PRIMARY_PHYSICAL); internal.databaseVersion = XmlUtils.readIntAttribute(parser, "internal", 0); external.databaseVersion = XmlUtils.readIntAttribute(parser, "external", 0); } else if (tagName.equals("verifier")) { final String deviceIdentity = parser.getAttributeValue(null, "device"); try { Loading @@ -2639,6 +2630,14 @@ final class Settings { mReadExternalStorageEnforced = "1".equals(enforcement); } else if (tagName.equals("keyset-settings")) { mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs); } else if (TAG_VERSION.equals(tagName)) { final String volumeUuid = XmlUtils.readStringAttribute(parser, ATTR_VOLUME_UUID); final VersionInfo ver = findOrCreateVersion(volumeUuid); ver.sdkVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION); ver.databaseVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION); ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT); } else { Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: " + parser.getName()); Loading @@ -2659,6 +2658,23 @@ final class Settings { Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e); } // If the build is setup to drop runtime permissions // on update drop the files before loading them. if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) { final VersionInfo internal = getInternalVersion(); if (!Build.FINGERPRINT.equals(internal.fingerprint)) { if (users == null) { mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( UserHandle.USER_OWNER); } else { for (UserInfo user : users) { mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( user.id); } } } } final int N = mPendingPackages.size(); for (int i = 0; i < N; i++) { Loading Loading @@ -3902,6 +3918,29 @@ final class Settings { ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE", }; void dumpVersionLPr(IndentingPrintWriter pw) { pw.increaseIndent(); for (int i= 0; i < mVersion.size(); i++) { final String volumeUuid = mVersion.keyAt(i); final VersionInfo ver = mVersion.valueAt(i); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) { pw.println("Internal:"); } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { pw.println("External:"); } else { pw.println("UUID " + volumeUuid + ":"); } pw.increaseIndent(); pw.printPair("sdkVersion", ver.sdkVersion); pw.printPair("databaseVersion", ver.databaseVersion); pw.println(); pw.printPair("fingerprint", ver.fingerprint); pw.println(); pw.decreaseIndent(); } pw.decreaseIndent(); } void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, ArraySet<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf, Date date, List<UserInfo> users) { Loading Loading
services/core/java/com/android/server/pm/PackageManagerService.java +65 −49 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ import com.android.server.SystemConfig; import com.android.server.Watchdog; import com.android.server.pm.PermissionsState.PermissionState; import com.android.server.pm.Settings.DatabaseVersion; import com.android.server.pm.Settings.VersionInfo; import com.android.server.storage.DeviceStorageMonitorInternal; import org.xmlpull.v1.XmlPullParser; Loading Loading @@ -1654,6 +1655,11 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public void onVolumeForgotten(String fsUuid) { if (TextUtils.isEmpty(fsUuid)) { Slog.w(TAG, "Forgetting internal storage is probably a mistake; ignoring"); return; } // Remove any apps installed on the forgotten volume synchronized (mPackages) { final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(fsUuid); Loading @@ -1663,6 +1669,7 @@ public class PackageManagerService extends IPackageManager.Stub { UserHandle.USER_OWNER, PackageManager.DELETE_ALL_USERS); } mSettings.onVolumeForgotten(fsUuid); mSettings.writeLPr(); } } Loading Loading @@ -2239,17 +2246,16 @@ public class PackageManagerService extends IPackageManager.Stub { // cases get permissions that the user didn't initially explicitly // allow... it would be nice to have some better way to handle // this situation. final boolean regrantPermissions = mSettings.mInternalSdkPlatform != mSdkVersion; if (regrantPermissions) Slog.i(TAG, "Platform changed from " + mSettings.mInternalSdkPlatform + " to " + mSdkVersion + "; regranting permissions for internal storage"); mSettings.mInternalSdkPlatform = mSdkVersion; updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL | (regrantPermissions ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL) : 0)); final VersionInfo ver = mSettings.getInternalVersion(); int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to " + mSdkVersion + "; regranting permissions for internal storage"); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } updatePermissionsLPw(null, null, updateFlags); ver.sdkVersion = mSdkVersion; // If this is the first boot, and it is a normal boot, then // we need to initialize the default preferred apps. Loading @@ -2261,20 +2267,22 @@ public class PackageManagerService extends IPackageManager.Stub { // If this is first boot after an OTA, and a normal boot, then // we need to clear code cache directories. mIsUpgrade = !Build.FINGERPRINT.equals(mSettings.mFingerprint); mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint); if (mIsUpgrade && !onlyCore) { Slog.i(TAG, "Build fingerprint changed; clearing code caches"); for (int i = 0; i < mSettings.mPackages.size(); i++) { final PackageSetting ps = mSettings.mPackages.valueAt(i); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) { deleteCodeCacheDirsLI(ps.volumeUuid, ps.name); } mSettings.mFingerprint = Build.FINGERPRINT; } ver.fingerprint = Build.FINGERPRINT; } checkDefaultBrowser(); // All the changes are done during package scanning. mSettings.updateInternalDatabaseVersion(); ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION; // can downgrade to reader mSettings.writeLPr(); Loading Loading @@ -3919,10 +3927,8 @@ public class PackageManagerService extends IPackageManager.Stub { * were updated, return true. */ private boolean isCompatSignatureUpdateNeeded(PackageParser.Package scannedPkg) { return (isExternal(scannedPkg) && mSettings.isExternalDatabaseVersionOlderThan( DatabaseVersion.SIGNATURE_END_ENTITY)) || (!isExternal(scannedPkg) && mSettings.isInternalDatabaseVersionOlderThan( DatabaseVersion.SIGNATURE_END_ENTITY)); final VersionInfo ver = getSettingsVersionForPackage(scannedPkg); return ver.databaseVersion < DatabaseVersion.SIGNATURE_END_ENTITY; } /** Loading Loading @@ -3969,13 +3975,8 @@ public class PackageManagerService extends IPackageManager.Stub { } private boolean isRecoverSignatureUpdateNeeded(PackageParser.Package scannedPkg) { if (isExternal(scannedPkg)) { return mSettings.isExternalDatabaseVersionOlderThan( DatabaseVersion.SIGNATURE_MALFORMED_RECOVER); } else { return mSettings.isInternalDatabaseVersionOlderThan( DatabaseVersion.SIGNATURE_MALFORMED_RECOVER); } final VersionInfo ver = getSettingsVersionForPackage(scannedPkg); return ver.databaseVersion < DatabaseVersion.SIGNATURE_MALFORMED_RECOVER; } private int compareSignaturesRecover(PackageSignatures existingSigs, Loading Loading @@ -12491,6 +12492,18 @@ public class PackageManagerService extends IPackageManager.Stub { return installFlags; } private VersionInfo getSettingsVersionForPackage(PackageParser.Package pkg) { if (isExternal(pkg)) { if (TextUtils.isEmpty(pkg.volumeUuid)) { return mSettings.getExternalVersion(); } else { return mSettings.findOrCreateVersion(pkg.volumeUuid); } } else { return mSettings.getInternalVersion(); } } private void deleteTempPackageFiles() { final FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { Loading Loading @@ -14756,16 +14769,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (dumpState.onTitlePrinted()) pw.println(); pw.println("Database versions:"); pw.print(" SDK Version:"); pw.print(" internal="); pw.print(mSettings.mInternalSdkPlatform); pw.print(" external="); pw.println(mSettings.mExternalSdkPlatform); pw.print(" DB Version:"); pw.print(" internal="); pw.print(mSettings.mInternalDatabaseVersion); pw.print(" external="); pw.println(mSettings.mExternalDatabaseVersion); mSettings.dumpVersionLPr(new IndentingPrintWriter(pw, " ")); } } Loading Loading @@ -15412,20 +15416,18 @@ public class PackageManagerService extends IPackageManager.Stub { // cases get permissions that the user didn't initially explicitly // allow... it would be nice to have some better way to handle // this situation. final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion; if (regrantPermissions) Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to " + mSdkVersion + "; regranting permissions for external storage"); mSettings.mExternalSdkPlatform = mSdkVersion; final VersionInfo ver = mSettings.getExternalVersion(); // Make sure group IDs have been assigned, and any permission // changes in other apps are accounted for updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL | (regrantPermissions ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL) : 0)); int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to " + mSdkVersion + "; regranting permissions for external"); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } updatePermissionsLPw(null, null, updateFlags); mSettings.updateExternalDatabaseVersion(); // Yay, everything is now upgraded ver.forceCurrent(); // can downgrade to reader // Persist settings Loading Loading @@ -15517,6 +15519,7 @@ public class PackageManagerService extends IPackageManager.Stub { final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE; synchronized (mInstallLock) { synchronized (mPackages) { final VersionInfo ver = mSettings.findOrCreateVersion(vol.fsUuid); final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid); for (PackageSetting ps : packages) { final PackageParser.Package pkg; Loading @@ -15526,9 +15529,22 @@ public class PackageManagerService extends IPackageManager.Stub { } catch (PackageManagerException e) { Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage()); } if (!Build.FINGERPRINT.equals(ver.fingerprint)) { deleteCodeCacheDirsLI(ps.volumeUuid, ps.name); } } int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to " + mSdkVersion + "; regranting permissions for " + vol.fsUuid); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } updatePermissionsLPw(null, null, updateFlags); // TODO: regrant any permissions that changed based since original install // Yay, everything is now upgraded ver.forceCurrent(); mSettings.writeLPr(); }
services/core/java/com/android/server/pm/Settings.java +140 −101 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.JournaledFile; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; Loading Loading @@ -129,7 +130,7 @@ final class Settings { * Note that care should be taken to make sure all database upgrades are * idempotent. */ private static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_MALFORMED_RECOVER; public static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_MALFORMED_RECOVER; /** * This class contains constants that can be referred to from upgrade code. Loading Loading @@ -177,11 +178,12 @@ final class Settings { "persistent-preferred-activities"; static final String TAG_CROSS_PROFILE_INTENT_FILTERS = "crossProfile-intent-filters"; public static final String TAG_DOMAIN_VERIFICATION = "domain-verification"; public static final String TAG_DEFAULT_APPS= "default-apps"; public static final String TAG_ALL_INTENT_FILTER_VERIFICATION = private static final String TAG_DOMAIN_VERIFICATION = "domain-verification"; private static final String TAG_DEFAULT_APPS = "default-apps"; private static final String TAG_ALL_INTENT_FILTER_VERIFICATION = "all-intent-filter-verifications"; public static final String TAG_DEFAULT_BROWSER= "default-browser"; private static final String TAG_DEFAULT_BROWSER = "default-browser"; private static final String TAG_VERSION = "version"; private static final String ATTR_NAME = "name"; private static final String ATTR_USER = "user"; Loading @@ -202,6 +204,9 @@ final class Settings { private static final String ATTR_PACKAGE_NAME = "packageName"; private static final String ATTR_FINGERPRINT = "fingerprint"; private static final String ATTR_APP_LINK_GENERATION = "app-link-generation"; private static final String ATTR_VOLUME_UUID = "volumeUuid"; private static final String ATTR_SDK_VERSION = "sdkVersion"; private static final String ATTR_DATABASE_VERSION = "databaseVersion"; private final Object mLock; Loading @@ -226,27 +231,43 @@ final class Settings { private static int mFirstAvailableUid = 0; // TODO: store SDK versions and fingerprint for each volume UUID /** Map from volume UUID to {@link VersionInfo} */ private ArrayMap<String, VersionInfo> mVersion = new ArrayMap<>(); // These are the last platform API version we were using for // the apps installed on internal and external storage. It is // used to grant newer permissions one time during a system upgrade. int mInternalSdkPlatform; int mExternalSdkPlatform; /** * Version details for a storage volume that may hold apps. */ public static class VersionInfo { /** * These are the last platform API version we were using for the apps * installed on internal and external storage. It is used to grant newer * permissions one time during a system upgrade. */ int sdkVersion; /** * The current database version for apps on internal storage. This is * used to upgrade the format of the packages.xml database not necessarily * tied to an SDK version. * used to upgrade the format of the packages.xml database not * necessarily tied to an SDK version. */ int mInternalDatabaseVersion; int mExternalDatabaseVersion; int databaseVersion; /** * Last known value of {@link Build#FINGERPRINT}. Used to determine when an * system update has occurred, meaning we need to clear code caches. * Last known value of {@link Build#FINGERPRINT}. Used to determine when * an system update has occurred, meaning we need to clear code caches. */ String mFingerprint; String fingerprint; /** * Force all version information to match current system values, * typically after resolving any required upgrade steps. */ public void forceCurrent() { sdkVersion = Build.VERSION.SDK_INT; databaseVersion = CURRENT_DATABASE_VERSION; fingerprint = Build.FINGERPRINT; } } Boolean mReadExternalStorageEnforced; Loading Loading @@ -1188,38 +1209,26 @@ final class Settings { .onDefaultRuntimePermissionsGrantedLPr(userId); } /** * Returns whether the current database has is older than {@code version} * for apps on internal storage. */ public boolean isInternalDatabaseVersionOlderThan(int version) { return mInternalDatabaseVersion < version; public VersionInfo findOrCreateVersion(String volumeUuid) { VersionInfo ver = mVersion.get(volumeUuid); if (ver == null) { ver = new VersionInfo(); ver.forceCurrent(); mVersion.put(volumeUuid, ver); } return ver; } /** * Returns whether the current database has is older than {@code version} * for apps on external storage. */ public boolean isExternalDatabaseVersionOlderThan(int version) { return mExternalDatabaseVersion < version; public VersionInfo getInternalVersion() { return mVersion.get(StorageManager.UUID_PRIVATE_INTERNAL); } /** * Updates the database version for apps on internal storage. Called after * call the updates to the database format are done for apps on internal * storage after the initial start-up scan. */ public void updateInternalDatabaseVersion() { mInternalDatabaseVersion = CURRENT_DATABASE_VERSION; public VersionInfo getExternalVersion() { return mVersion.get(StorageManager.UUID_PRIMARY_PHYSICAL); } /** * Updates the database version for apps on internal storage. Called after * call the updates to the database format are done for apps on internal * storage after the initial start-up scan. */ public void updateExternalDatabaseVersion() { mExternalDatabaseVersion = CURRENT_DATABASE_VERSION; public void onVolumeForgotten(String fsUuid) { mVersion.remove(fsUuid); } /** Loading Loading @@ -2060,16 +2069,17 @@ final class Settings { serializer.startTag(null, "packages"); serializer.startTag(null, "last-platform-version"); serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform)); serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform)); serializer.attribute(null, "fingerprint", mFingerprint); serializer.endTag(null, "last-platform-version"); for (int i = 0; i < mVersion.size(); i++) { final String volumeUuid = mVersion.keyAt(i); final VersionInfo ver = mVersion.valueAt(i); serializer.startTag(null, "database-version"); serializer.attribute(null, "internal", Integer.toString(mInternalDatabaseVersion)); serializer.attribute(null, "external", Integer.toString(mExternalDatabaseVersion)); serializer.endTag(null, "database-version"); serializer.startTag(null, TAG_VERSION); XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid); XmlUtils.writeIntAttribute(serializer, ATTR_SDK_VERSION, ver.sdkVersion); XmlUtils.writeIntAttribute(serializer, ATTR_DATABASE_VERSION, ver.databaseVersion); XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint); serializer.endTag(null, TAG_VERSION); } if (mVerifierDeviceIdentity != null) { serializer.startTag(null, "verifier"); Loading Loading @@ -2499,8 +2509,10 @@ final class Settings { mReadMessages.append("No settings file found\n"); PackageManagerService.reportSettingsProblem(Log.INFO, "No settings file; creating initial state"); mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion; mFingerprint = Build.FINGERPRINT; // It's enough to just touch version details to create them // with default values findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL); findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL); return false; } str = new FileInputStream(mSettingsFilename); Loading Loading @@ -2584,48 +2596,27 @@ final class Settings { } else if (tagName.equals("restored-ivi")) { readRestoredIntentFilterVerifications(parser); } else if (tagName.equals("last-platform-version")) { mInternalSdkPlatform = mExternalSdkPlatform = 0; try { String internal = parser.getAttributeValue(null, "internal"); if (internal != null) { mInternalSdkPlatform = Integer.parseInt(internal); } String external = parser.getAttributeValue(null, "external"); if (external != null) { mExternalSdkPlatform = Integer.parseInt(external); } } catch (NumberFormatException e) { } mFingerprint = parser.getAttributeValue(null, "fingerprint"); // Upgrade from older XML schema final VersionInfo internal = findOrCreateVersion( StorageManager.UUID_PRIVATE_INTERNAL); final VersionInfo external = findOrCreateVersion( StorageManager.UUID_PRIMARY_PHYSICAL); internal.sdkVersion = XmlUtils.readIntAttribute(parser, "internal", 0); external.sdkVersion = XmlUtils.readIntAttribute(parser, "external", 0); internal.fingerprint = external.fingerprint = XmlUtils.readStringAttribute(parser, "fingerprint"); // If the build is setup to drop runtime permissions // on update drop the files before loading them. if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) { if (!Build.FINGERPRINT.equals(mFingerprint)) { if (users == null) { mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( UserHandle.USER_OWNER); } else { for (UserInfo user : users) { mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( user.id); } } } } } else if (tagName.equals("database-version")) { mInternalDatabaseVersion = mExternalDatabaseVersion = 0; try { String internalDbVersionString = parser.getAttributeValue(null, "internal"); if (internalDbVersionString != null) { mInternalDatabaseVersion = Integer.parseInt(internalDbVersionString); } String externalDbVersionString = parser.getAttributeValue(null, "external"); if (externalDbVersionString != null) { mExternalDatabaseVersion = Integer.parseInt(externalDbVersionString); } } catch (NumberFormatException ignored) { } // Upgrade from older XML schema final VersionInfo internal = findOrCreateVersion( StorageManager.UUID_PRIVATE_INTERNAL); final VersionInfo external = findOrCreateVersion( StorageManager.UUID_PRIMARY_PHYSICAL); internal.databaseVersion = XmlUtils.readIntAttribute(parser, "internal", 0); external.databaseVersion = XmlUtils.readIntAttribute(parser, "external", 0); } else if (tagName.equals("verifier")) { final String deviceIdentity = parser.getAttributeValue(null, "device"); try { Loading @@ -2639,6 +2630,14 @@ final class Settings { mReadExternalStorageEnforced = "1".equals(enforcement); } else if (tagName.equals("keyset-settings")) { mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs); } else if (TAG_VERSION.equals(tagName)) { final String volumeUuid = XmlUtils.readStringAttribute(parser, ATTR_VOLUME_UUID); final VersionInfo ver = findOrCreateVersion(volumeUuid); ver.sdkVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION); ver.databaseVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION); ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT); } else { Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: " + parser.getName()); Loading @@ -2659,6 +2658,23 @@ final class Settings { Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e); } // If the build is setup to drop runtime permissions // on update drop the files before loading them. if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) { final VersionInfo internal = getInternalVersion(); if (!Build.FINGERPRINT.equals(internal.fingerprint)) { if (users == null) { mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( UserHandle.USER_OWNER); } else { for (UserInfo user : users) { mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( user.id); } } } } final int N = mPendingPackages.size(); for (int i = 0; i < N; i++) { Loading Loading @@ -3902,6 +3918,29 @@ final class Settings { ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE", }; void dumpVersionLPr(IndentingPrintWriter pw) { pw.increaseIndent(); for (int i= 0; i < mVersion.size(); i++) { final String volumeUuid = mVersion.keyAt(i); final VersionInfo ver = mVersion.valueAt(i); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) { pw.println("Internal:"); } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { pw.println("External:"); } else { pw.println("UUID " + volumeUuid + ":"); } pw.increaseIndent(); pw.printPair("sdkVersion", ver.sdkVersion); pw.printPair("databaseVersion", ver.databaseVersion); pw.println(); pw.printPair("fingerprint", ver.fingerprint); pw.println(); pw.decreaseIndent(); } pw.decreaseIndent(); } void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, ArraySet<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf, Date date, List<UserInfo> users) { Loading