Loading services/core/java/com/android/server/pm/InstallPackageHelper.java +39 −9 Original line number Diff line number Diff line Loading @@ -2629,18 +2629,28 @@ final class InstallPackageHelper { String packageName = pkgLite.packageName; synchronized (mPm.mLock) { // Package which currently owns the data that the new package will own if installed. // If an app is uninstalled while keeping data (e.g. adb uninstall -k), installedPkg // will be null whereas dataOwnerPkg will contain information about the package // which was uninstalled while keeping its data. AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName); PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName); if (dataOwnerPkg == null) { if (dataOwnerPs != null) { dataOwnerPkg = dataOwnerPs.getPkg(); if (dataOwnerPs == null) { if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) { String errorMsg = "Required installed version code was " + requiredInstalledVersionCode + " but package is not installed"; Slog.w(TAG, errorMsg); return Pair.create( PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg); } // The package doesn't exist in the system, don't need to check the version // replacing. return Pair.create(PackageManager.INSTALL_SUCCEEDED, null); } // Package which currently owns the data that the new package will own if installed. // If an app is uninstalled while keeping data (e.g. adb uninstall -k), dataOwnerPkg // will be null whereas dataOwnerPs will contain information about the package // which was uninstalled while keeping its data. The AndroidPackage object that the // PackageSetting refers to is the same object that is stored in mPackages. AndroidPackage dataOwnerPkg = dataOwnerPs.getPkg(); if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) { if (dataOwnerPkg == null) { String errorMsg = "Required installed version code was " Loading @@ -2662,7 +2672,27 @@ final class InstallPackageHelper { } } if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) { // If dataOwnerPkg is null but dataOwnerPs is not null, there is always data on // some users. Wwe should do the downgrade check. E.g. DELETE_KEEP_DATA and // archived apps if (dataOwnerPkg == null) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, dataOwnerPs.isDebuggable())) { // The data exists on some users and downgrade is not permitted; a lower // version of the app will not be allowed. try { PackageManagerServiceUtils.checkDowngrade(dataOwnerPs, pkgLite); } catch (PackageManagerException e) { String errorMsg = "Downgrade detected on app uninstalled with" + " DELETE_KEEP_DATA: " + e.getMessage(); Slog.w(TAG, errorMsg); return Pair.create( PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg); } } // dataOwnerPs.getPkg() is not null on system apps case. Don't need to consider // system apps case like below. } else if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, dataOwnerPkg.isDebuggable())) { // Downgrade is not permitted; a lower version of the app will not be allowed Loading services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +16 −3 Original line number Diff line number Diff line Loading @@ -1419,10 +1419,23 @@ public class PackageManagerServiceUtils { /** * Check and throw if the given before/after packages would be considered a * downgrade. * downgrade with {@link PackageSetting}. */ public static void checkDowngrade(AndroidPackage before, PackageInfoLite after) throws PackageManagerException { public static void checkDowngrade(@NonNull PackageSetting before, @NonNull PackageInfoLite after) throws PackageManagerException { if (after.getLongVersionCode() < before.getVersionCode()) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Update version code " + after.versionCode + " is older than current " + before.getVersionCode()); } } /** * Check and throw if the given before/after packages would be considered a * downgrade with {@link AndroidPackage}. */ public static void checkDowngrade(@NonNull AndroidPackage before, @NonNull PackageInfoLite after) throws PackageManagerException { if (after.getLongVersionCode() < before.getLongVersionCode()) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Update version code " + after.versionCode + " is older than current " Loading services/core/java/com/android/server/pm/PackageSetting.java +16 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal FORCE_QUERYABLE_OVERRIDE, SCANNED_AS_STOPPED_SYSTEM_APP, PENDING_RESTORE, DEBUGGABLE, }) public @interface Flags { } Loading @@ -105,6 +106,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal private static final int FORCE_QUERYABLE_OVERRIDE = 1 << 2; private static final int SCANNED_AS_STOPPED_SYSTEM_APP = 1 << 3; private static final int PENDING_RESTORE = 1 << 4; private static final int DEBUGGABLE = 1 << 5; } private int mBooleans; Loading Loading @@ -562,6 +564,20 @@ public class PackageSetting extends SettingBase implements PackageStateInternal return getBoolean(Booleans.PENDING_RESTORE); } /** * @see PackageState#isDebuggable */ public PackageSetting setDebuggable(boolean value) { setBoolean(Booleans.DEBUGGABLE, value); onChanged(); return this; } @Override public boolean isDebuggable() { return getBoolean(Booleans.DEBUGGABLE); } @Override public String toString() { return "PackageSetting{" Loading services/core/java/com/android/server/pm/ScanPackageUtils.java +3 −0 Original line number Diff line number Diff line Loading @@ -437,6 +437,9 @@ final class ScanPackageUtils { pkgSetting.setIsOrphaned(true); } // update debuggable to packageSetting pkgSetting.setDebuggable(parsedPackage.isDebuggable()); // Take care of first install / last update times. final long scanFileTime = getLastModifiedTime(parsedPackage); final long existingFirstInstallTime = userId == UserHandle.USER_ALL Loading services/core/java/com/android/server/pm/Settings.java +6 −1 Original line number Diff line number Diff line Loading @@ -3255,6 +3255,9 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile if (pkg.isPendingRestore()) { serializer.attributeBoolean(null, "pendingRestore", true); } if (pkg.isDebuggable()) { serializer.attributeBoolean(null, "debuggable", true); } if (pkg.isLoading()) { serializer.attributeBoolean(null, "isLoading", true); } Loading @@ -3269,7 +3272,6 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile serializer.attributeInt(null, "appMetadataSource", pkg.getAppMetadataSource()); writeUsesSdkLibLPw(serializer, pkg.getUsesSdkLibraries(), pkg.getUsesSdkLibrariesVersionsMajor(), pkg.getUsesSdkLibrariesOptional()); Loading Loading @@ -4059,6 +4061,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile long versionCode = 0; boolean installedForceQueryable = false; boolean isPendingRestore = false; boolean isDebuggable = false; float loadingProgress = 0; long loadingCompletedTime = 0; UUID domainSetId; Loading @@ -4085,6 +4088,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile updateAvailable = parser.getAttributeBoolean(null, "updateAvailable", false); installedForceQueryable = parser.getAttributeBoolean(null, "forceQueryable", false); isPendingRestore = parser.getAttributeBoolean(null, "pendingRestore", false); isDebuggable = parser.getAttributeBoolean(null, "debuggable", false); loadingProgress = parser.getAttributeFloat(null, "loadingProgress", 0); loadingCompletedTime = parser.getAttributeLongHex(null, "loadingCompletedTime", 0); Loading Loading @@ -4259,6 +4263,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile .setUpdateAvailable(updateAvailable) .setForceQueryableOverride(installedForceQueryable) .setPendingRestore(isPendingRestore) .setDebuggable(isDebuggable) .setLoadingProgress(loadingProgress) .setLoadingCompletedTime(loadingCompletedTime) .setAppMetadataFilePath(appMetadataFilePath) Loading Loading
services/core/java/com/android/server/pm/InstallPackageHelper.java +39 −9 Original line number Diff line number Diff line Loading @@ -2629,18 +2629,28 @@ final class InstallPackageHelper { String packageName = pkgLite.packageName; synchronized (mPm.mLock) { // Package which currently owns the data that the new package will own if installed. // If an app is uninstalled while keeping data (e.g. adb uninstall -k), installedPkg // will be null whereas dataOwnerPkg will contain information about the package // which was uninstalled while keeping its data. AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName); PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName); if (dataOwnerPkg == null) { if (dataOwnerPs != null) { dataOwnerPkg = dataOwnerPs.getPkg(); if (dataOwnerPs == null) { if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) { String errorMsg = "Required installed version code was " + requiredInstalledVersionCode + " but package is not installed"; Slog.w(TAG, errorMsg); return Pair.create( PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg); } // The package doesn't exist in the system, don't need to check the version // replacing. return Pair.create(PackageManager.INSTALL_SUCCEEDED, null); } // Package which currently owns the data that the new package will own if installed. // If an app is uninstalled while keeping data (e.g. adb uninstall -k), dataOwnerPkg // will be null whereas dataOwnerPs will contain information about the package // which was uninstalled while keeping its data. The AndroidPackage object that the // PackageSetting refers to is the same object that is stored in mPackages. AndroidPackage dataOwnerPkg = dataOwnerPs.getPkg(); if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) { if (dataOwnerPkg == null) { String errorMsg = "Required installed version code was " Loading @@ -2662,7 +2672,27 @@ final class InstallPackageHelper { } } if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) { // If dataOwnerPkg is null but dataOwnerPs is not null, there is always data on // some users. Wwe should do the downgrade check. E.g. DELETE_KEEP_DATA and // archived apps if (dataOwnerPkg == null) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, dataOwnerPs.isDebuggable())) { // The data exists on some users and downgrade is not permitted; a lower // version of the app will not be allowed. try { PackageManagerServiceUtils.checkDowngrade(dataOwnerPs, pkgLite); } catch (PackageManagerException e) { String errorMsg = "Downgrade detected on app uninstalled with" + " DELETE_KEEP_DATA: " + e.getMessage(); Slog.w(TAG, errorMsg); return Pair.create( PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg); } } // dataOwnerPs.getPkg() is not null on system apps case. Don't need to consider // system apps case like below. } else if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, dataOwnerPkg.isDebuggable())) { // Downgrade is not permitted; a lower version of the app will not be allowed Loading
services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +16 −3 Original line number Diff line number Diff line Loading @@ -1419,10 +1419,23 @@ public class PackageManagerServiceUtils { /** * Check and throw if the given before/after packages would be considered a * downgrade. * downgrade with {@link PackageSetting}. */ public static void checkDowngrade(AndroidPackage before, PackageInfoLite after) throws PackageManagerException { public static void checkDowngrade(@NonNull PackageSetting before, @NonNull PackageInfoLite after) throws PackageManagerException { if (after.getLongVersionCode() < before.getVersionCode()) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Update version code " + after.versionCode + " is older than current " + before.getVersionCode()); } } /** * Check and throw if the given before/after packages would be considered a * downgrade with {@link AndroidPackage}. */ public static void checkDowngrade(@NonNull AndroidPackage before, @NonNull PackageInfoLite after) throws PackageManagerException { if (after.getLongVersionCode() < before.getLongVersionCode()) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Update version code " + after.versionCode + " is older than current " Loading
services/core/java/com/android/server/pm/PackageSetting.java +16 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal FORCE_QUERYABLE_OVERRIDE, SCANNED_AS_STOPPED_SYSTEM_APP, PENDING_RESTORE, DEBUGGABLE, }) public @interface Flags { } Loading @@ -105,6 +106,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal private static final int FORCE_QUERYABLE_OVERRIDE = 1 << 2; private static final int SCANNED_AS_STOPPED_SYSTEM_APP = 1 << 3; private static final int PENDING_RESTORE = 1 << 4; private static final int DEBUGGABLE = 1 << 5; } private int mBooleans; Loading Loading @@ -562,6 +564,20 @@ public class PackageSetting extends SettingBase implements PackageStateInternal return getBoolean(Booleans.PENDING_RESTORE); } /** * @see PackageState#isDebuggable */ public PackageSetting setDebuggable(boolean value) { setBoolean(Booleans.DEBUGGABLE, value); onChanged(); return this; } @Override public boolean isDebuggable() { return getBoolean(Booleans.DEBUGGABLE); } @Override public String toString() { return "PackageSetting{" Loading
services/core/java/com/android/server/pm/ScanPackageUtils.java +3 −0 Original line number Diff line number Diff line Loading @@ -437,6 +437,9 @@ final class ScanPackageUtils { pkgSetting.setIsOrphaned(true); } // update debuggable to packageSetting pkgSetting.setDebuggable(parsedPackage.isDebuggable()); // Take care of first install / last update times. final long scanFileTime = getLastModifiedTime(parsedPackage); final long existingFirstInstallTime = userId == UserHandle.USER_ALL Loading
services/core/java/com/android/server/pm/Settings.java +6 −1 Original line number Diff line number Diff line Loading @@ -3255,6 +3255,9 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile if (pkg.isPendingRestore()) { serializer.attributeBoolean(null, "pendingRestore", true); } if (pkg.isDebuggable()) { serializer.attributeBoolean(null, "debuggable", true); } if (pkg.isLoading()) { serializer.attributeBoolean(null, "isLoading", true); } Loading @@ -3269,7 +3272,6 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile serializer.attributeInt(null, "appMetadataSource", pkg.getAppMetadataSource()); writeUsesSdkLibLPw(serializer, pkg.getUsesSdkLibraries(), pkg.getUsesSdkLibrariesVersionsMajor(), pkg.getUsesSdkLibrariesOptional()); Loading Loading @@ -4059,6 +4061,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile long versionCode = 0; boolean installedForceQueryable = false; boolean isPendingRestore = false; boolean isDebuggable = false; float loadingProgress = 0; long loadingCompletedTime = 0; UUID domainSetId; Loading @@ -4085,6 +4088,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile updateAvailable = parser.getAttributeBoolean(null, "updateAvailable", false); installedForceQueryable = parser.getAttributeBoolean(null, "forceQueryable", false); isPendingRestore = parser.getAttributeBoolean(null, "pendingRestore", false); isDebuggable = parser.getAttributeBoolean(null, "debuggable", false); loadingProgress = parser.getAttributeFloat(null, "loadingProgress", 0); loadingCompletedTime = parser.getAttributeLongHex(null, "loadingCompletedTime", 0); Loading Loading @@ -4259,6 +4263,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile .setUpdateAvailable(updateAvailable) .setForceQueryableOverride(installedForceQueryable) .setPendingRestore(isPendingRestore) .setDebuggable(isDebuggable) .setLoadingProgress(loadingProgress) .setLoadingCompletedTime(loadingCompletedTime) .setAppMetadataFilePath(appMetadataFilePath) Loading