Merge "Improve ABI handling for shared user ids."
This commit is contained in:
@@ -5132,6 +5132,20 @@ public class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
pkg.mScanPath = path;
|
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 ((scanMode&SCAN_NO_DEX) == 0) {
|
||||||
if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
|
if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
|
||||||
== DEX_OPT_FAILED) {
|
== DEX_OPT_FAILED) {
|
||||||
@@ -5251,16 +5265,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
|||||||
|
|
||||||
// writer
|
// writer
|
||||||
synchronized (mPackages) {
|
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,
|
// We don't expect installation to fail beyond this point,
|
||||||
if ((scanMode&SCAN_MONITOR) != 0) {
|
if ((scanMode&SCAN_MONITOR) != 0) {
|
||||||
mAppDirs.put(pkg.mPath, pkg);
|
mAppDirs.put(pkg.mPath, pkg);
|
||||||
@@ -5604,19 +5608,43 @@ public class PackageManagerService extends IPackageManager.Stub {
|
|||||||
return pkg;
|
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,
|
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;
|
PackageSetting requirer = null;
|
||||||
for (PackageSetting ps : packagesForUser) {
|
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);
|
final String instructionSet = VMRuntime.getInstructionSet(ps.cpuAbiString);
|
||||||
if (requiredInstructionSet != null) {
|
if (requiredInstructionSet != null) {
|
||||||
if (!instructionSet.equals(requiredInstructionSet)) {
|
if (!instructionSet.equals(requiredInstructionSet)) {
|
||||||
// We have a mismatch between instruction sets (say arm vs arm64).
|
// We have a mismatch between instruction sets (say arm vs arm64).
|
||||||
// bail out.
|
// bail out.
|
||||||
String errorMessage = "Instruction set mismatch, "
|
String errorMessage = "Instruction set mismatch, "
|
||||||
+ ((requirer == null) ? "[caller]" : requirer.pkg)
|
+ ((requirer == null) ? "[caller]" : requirer)
|
||||||
+ " requires " + requiredInstructionSet + " whereas " + ps.pkg
|
+ " requires " + requiredInstructionSet + " whereas " + ps
|
||||||
+ " requires " + instructionSet;
|
+ " requires " + instructionSet;
|
||||||
Slog.e(TAG, errorMessage);
|
Slog.e(TAG, errorMessage);
|
||||||
|
|
||||||
@@ -5632,12 +5660,30 @@ public class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (requiredInstructionSet != null) {
|
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) {
|
for (PackageSetting ps : packagesForUser) {
|
||||||
if (ps.cpuAbiString == null) {
|
if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) {
|
||||||
ps.cpuAbiString = requirer.cpuAbiString;
|
if (ps.cpuAbiString != null) {
|
||||||
if (ps.pkg != null) {
|
continue;
|
||||||
ps.pkg.applicationInfo.cpuAbi = requirer.cpuAbiString;
|
}
|
||||||
Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.cpuAbiString);
|
|
||||||
|
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) {
|
if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) {
|
||||||
ps.cpuAbiString = null;
|
ps.cpuAbiString = null;
|
||||||
@@ -5649,7 +5695,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user