diff options
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageAbiHelperImpl.java | 90 |
2 files changed, 89 insertions, 12 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 49c8a7cad57a..2a673530578a 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2554,6 +2554,15 @@ public abstract class PackageManager { public static final int INSTALL_FAILED_SHARED_LIBRARY_BAD_CERTIFICATE_DIGEST = -130; /** + * Installation failed return code: if the system failed to install the package that + * {@link android.R.attr#multiArch} is true in its manifest because its packaged + * native code did not match all of the natively ABIs supported by the system. + * + * @hide + */ + public static final int INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS = -131; + + /** * App minimum aspect ratio set by the user which will override app-defined aspect ratio. * * @hide @@ -10452,6 +10461,8 @@ public abstract class PackageManager { case INSTALL_FAILED_SESSION_INVALID: return "INSTALL_FAILED_SESSION_INVALID"; case INSTALL_FAILED_SHARED_LIBRARY_BAD_CERTIFICATE_DIGEST: return "INSTALL_FAILED_SHARED_LIBRARY_BAD_CERTIFICATE_DIGEST"; + case INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS: + return "INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS"; default: return Integer.toString(status); } } diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java index 85d2df320fc9..bbce26c85549 100644 --- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java +++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java @@ -27,11 +27,14 @@ import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME; import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.Flags; import android.content.pm.PackageManager; import android.os.Build; import android.os.Environment; import android.os.FileUtils; +import android.os.SystemProperties; import android.os.Trace; import android.text.TextUtils; import android.util.ArraySet; @@ -50,9 +53,15 @@ import libcore.io.IoUtils; import java.io.File; import java.io.IOException; +import java.util.Set; final class PackageAbiHelperImpl implements PackageAbiHelper { + @Nullable + private static String[] sNativelySupported32BitAbis = null; + @Nullable + private static String[] sNativelySupported64BitAbis = null; + private static String calculateBundledApkRoot(final String codePathString) { final File codePath = new File(codePathString); final File codeRoot; @@ -122,13 +131,20 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { } } - private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet) throws - PackageManagerException { + private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet, + boolean forceMatch) throws PackageManagerException { if (copyRet < 0) { if (copyRet != PackageManager.NO_NATIVE_LIBRARIES && copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { throw new PackageManagerException(copyRet, message); } + + if (forceMatch && copyRet == PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_MULTI_ARCH_NOT_MATCH_ALL_NATIVE_ABIS, + "The multiArch app's native libs don't support all the natively" + + " supported ABIs of the device."); + } } } @@ -296,7 +312,40 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { return new Abis(primaryCpuAbi, secondaryCpuAbi); } + @NonNull + private static String[] getNativelySupportedAbis(@NonNull String[] supportedAbis) { + Set<String> nativelySupportedAbis = new ArraySet<>(); + for (int i = 0; i < supportedAbis.length; i++) { + final String currentAbi = supportedAbis[i]; + // In presence of a native bridge this means the Abi is emulated. + final String currentIsa = VMRuntime.getInstructionSet(currentAbi); + if (TextUtils.isEmpty(SystemProperties.get("ro.dalvik.vm.isa." + currentIsa))) { + nativelySupportedAbis.add(currentAbi); + } + } + return nativelySupportedAbis.toArray(new String[0]); + } + + private static String[] getNativelySupported32BitAbis() { + if (sNativelySupported32BitAbis != null) { + return sNativelySupported32BitAbis; + } + + sNativelySupported32BitAbis = getNativelySupportedAbis(Build.SUPPORTED_32_BIT_ABIS); + return sNativelySupported32BitAbis; + } + + private static String[] getNativelySupported64BitAbis() { + if (sNativelySupported64BitAbis != null) { + return sNativelySupported64BitAbis; + } + + sNativelySupported64BitAbis = getNativelySupportedAbis(Build.SUPPORTED_64_BIT_ABIS); + return sNativelySupported64BitAbis; + } + @Override + @SuppressWarnings("AndroidFrameworkCompatChange") // the check is before the apk is installed public Pair<Abis, NativeLibraryPaths> derivePackageAbi(AndroidPackage pkg, boolean isSystemApp, boolean isUpdatedSystemApp, String cpuAbiOverride, File appLib32InstallDir) throws PackageManagerException { @@ -334,18 +383,33 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { primaryCpuAbi = null; secondaryCpuAbi = null; if (pkg.isMultiArch()) { + // Force the match for these cases + // 1. pkg.getTargetSdkVersion >= Build.VERSION_CODES.VANILLA_ICE_CREAM + // 2. cpuAbiOverride is null. If it is non-null, it is set via shell for testing + final boolean forceMatch = Flags.forceMultiArchNativeLibsMatch() + && pkg.getTargetSdkVersion() >= Build.VERSION_CODES.VANILLA_ICE_CREAM + && cpuAbiOverride == null; + + String[] supported32BitAbis = forceMatch ? getNativelySupported32BitAbis() + : Build.SUPPORTED_32_BIT_ABIS; + String[] supported64BitAbis = forceMatch ? getNativelySupported64BitAbis() + : Build.SUPPORTED_64_BIT_ABIS; + + final boolean systemSupports32BitAbi = supported32BitAbis.length > 0; + final boolean systemSupports64BitAbi = supported64BitAbis.length > 0; + int abi32 = PackageManager.NO_NATIVE_LIBRARIES; int abi64 = PackageManager.NO_NATIVE_LIBRARIES; - if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { + if (systemSupports32BitAbi) { if (extractLibs) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries"); abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, - nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, + nativeLibraryRoot, supported32BitAbis, useIsaSpecificSubdirs, onIncremental); } else { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi"); abi32 = NativeLibraryHelper.findSupportedAbi( - handle, Build.SUPPORTED_32_BIT_ABIS); + handle, supported32BitAbis); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } @@ -357,24 +421,26 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { } maybeThrowExceptionForMultiArchCopy( - "Error unpackaging 32 bit native libs for multiarch app.", abi32); + "Error unpackaging 32 bit native libs for multiarch app.", abi32, + forceMatch && systemSupports32BitAbi); - if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { + if (systemSupports64BitAbi) { if (extractLibs) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries"); abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, - nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, + nativeLibraryRoot, supported64BitAbis, useIsaSpecificSubdirs, onIncremental); } else { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi"); abi64 = NativeLibraryHelper.findSupportedAbi( - handle, Build.SUPPORTED_64_BIT_ABIS); + handle, supported64BitAbis); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } maybeThrowExceptionForMultiArchCopy( - "Error unpackaging 64 bit native libs for multiarch app.", abi64); + "Error unpackaging 64 bit native libs for multiarch app.", abi64, + forceMatch && systemSupports64BitAbi); if (abi64 >= 0) { // Shared library native libs should be in the APK zip aligned @@ -382,11 +448,11 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Shared library native lib extraction not supported"); } - primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64]; + primaryCpuAbi = supported64BitAbis[abi64]; } if (abi32 >= 0) { - final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32]; + final String abi = supported32BitAbis[abi32]; if (abi64 >= 0) { if (pkg.is32BitAbiPreferred()) { secondaryCpuAbi = primaryCpuAbi; |