diff options
author | Narayan Kamath <narayan@google.com> | 2014-05-20 13:55:09 +0100 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2014-05-20 22:10:24 -0700 |
commit | 96db91e0ff30c872dacc7f9a5d5a67e950e4ba26 (patch) | |
tree | e49413436b34b51be857fd49eb5735df691ca6c3 /services | |
parent | cd956e0fe21dc1ba8f814950f109648499c8ac5f (diff) | |
download | frameworks_base-96db91e0ff30c872dacc7f9a5d5a67e950e4ba26.zip frameworks_base-96db91e0ff30c872dacc7f9a5d5a67e950e4ba26.tar.gz frameworks_base-96db91e0ff30c872dacc7f9a5d5a67e950e4ba26.tar.bz2 |
Improve ABI handling for shared user ids.
The key improvement is that we need to keep track of
the package that's currently being scanned (this includes
new installs and upgrades of existing packages) and treat
it specially. If we didn't do that, In the case of upgrades
we would perform the shared UID calculation based on the ABI
of the old package, and not the current package.
This change also allows us to perform the CPU ABI calculation
before dexopt, which saves us from having to do it twice and
fixes a bug where we were using the wrong package path to
dexopt a package.
This also has the side effect of fixing 15081286.
bug: 15081286
(cherry-picked from commit b851c89d2252cf3d1dc504558ce1553527885316)
Change-Id: I20f8ad36941fc3df29007f0e83ce82f38f3585c8
Diffstat (limited to 'services')
-rwxr-xr-x | services/core/java/com/android/server/pm/PackageManagerService.java | 97 |
1 files changed, 71 insertions, 26 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 46c5482..dd5e9de 100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -5486,6 +5486,20 @@ public class PackageManagerService extends IPackageManager.Stub { } pkg.mScanPath = path; + if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) { + // We don't do this here during boot because we can do it all + // at once after scanning all existing packages. + // + // We also do this *before* we perform dexopt on this package, so that + // we can avoid redundant dexopts, and also to make sure we've got the + // code and package path correct. + if (!adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, + pkg, forceDex, (scanMode & SCAN_DEFER_DEX) != 0)) { + mLastScanError = PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE; + return null; + } + } + if ((scanMode&SCAN_NO_DEX) == 0) { if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) { @@ -5613,16 +5627,6 @@ public class PackageManagerService extends IPackageManager.Stub { // writer synchronized (mPackages) { - if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) { - // We don't do this here during boot because we can do it all - // at once after scanning all existing packages. - if (!adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, - pkg.applicationInfo.cpuAbi, - forceDex, (scanMode & SCAN_DEFER_DEX) != 0)) { - mLastScanError = PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE; - return null; - } - } // We don't expect installation to fail beyond this point, if ((scanMode&SCAN_MONITOR) != 0) { mAppDirs.put(pkg.mPath, pkg); @@ -5967,19 +5971,43 @@ public class PackageManagerService extends IPackageManager.Stub { return pkg; } + /** + * Adjusts ABIs for a set of packages belonging to a shared user so that they all match. + * i.e, so that all packages can be run inside a single process if required. + * + * Optionally, callers can pass in a parsed package via {@code newPackage} in which case + * this function will either try and make the ABI for all packages in {@code packagesForUser} + * match {@code scannedPackage} or will update the ABI of {@code scannedPackage} to match + * the ABI selected for {@code packagesForUser}. This variant is used when installing or + * updating a package that belongs to a shared user. + */ private boolean adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser, - String requiredInstructionSet, boolean forceDexOpt, boolean deferDexOpt) { + PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt) { + String requiredInstructionSet = null; + if (scannedPackage != null && scannedPackage.applicationInfo.cpuAbi != null) { + requiredInstructionSet = VMRuntime.getInstructionSet( + scannedPackage.applicationInfo.cpuAbi); + } + PackageSetting requirer = null; for (PackageSetting ps : packagesForUser) { - if (ps.cpuAbiString != null) { + // If packagesForUser contains scannedPackage, we skip it. This will happen + // when scannedPackage is an update of an existing package. Without this check, + // we will never be able to change the ABI of any package belonging to a shared + // user, even if it's compatible with other packages. + if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) { + if (ps.cpuAbiString == null) { + continue; + } + final String instructionSet = VMRuntime.getInstructionSet(ps.cpuAbiString); if (requiredInstructionSet != null) { if (!instructionSet.equals(requiredInstructionSet)) { // We have a mismatch between instruction sets (say arm vs arm64). // bail out. String errorMessage = "Instruction set mismatch, " - + ((requirer == null) ? "[caller]" : requirer.pkg) - + " requires " + requiredInstructionSet + " whereas " + ps.pkg + + ((requirer == null) ? "[caller]" : requirer) + + " requires " + requiredInstructionSet + " whereas " + ps + " requires " + instructionSet; Slog.e(TAG, errorMessage); @@ -5995,20 +6023,37 @@ public class PackageManagerService extends IPackageManager.Stub { } if (requiredInstructionSet != null) { + String adjustedAbi; + if (requirer != null) { + // requirer != null implies that either scannedPackage was null or that scannedPackage + // did not require an ABI, in which case we have to adjust scannedPackage to match + // the ABI of the set (which is the same as requirer's ABI) + adjustedAbi = requirer.cpuAbiString; + if (scannedPackage != null) { + scannedPackage.applicationInfo.cpuAbi = adjustedAbi; + } + } else { + // requirer == null implies that we're updating all ABIs in the set to + // match scannedPackage. + adjustedAbi = scannedPackage.applicationInfo.cpuAbi; + } + for (PackageSetting ps : packagesForUser) { - if (ps.cpuAbiString == null) { - ps.cpuAbiString = requirer.cpuAbiString; - if (ps.pkg != null) { - ps.pkg.applicationInfo.cpuAbi = requirer.cpuAbiString; - Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.cpuAbiString); + if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) { + if (ps.cpuAbiString != null) { + continue; + } - if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) { - ps.cpuAbiString = null; - ps.pkg.applicationInfo.cpuAbi = null; - return false; - } else { - mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet()); - } + ps.cpuAbiString = adjustedAbi; + ps.pkg.applicationInfo.cpuAbi = adjustedAbi; + Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi); + + if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) { + ps.cpuAbiString = null; + ps.pkg.applicationInfo.cpuAbi = null; + return false; + } else { + mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet()); } } } |