11ebd74acf9977daa42133507e970dab88e08f0efKenny Root/* 21ebd74acf9977daa42133507e970dab88e08f0efKenny Root * Copyright (C) 2010 The Android Open Source Project 31ebd74acf9977daa42133507e970dab88e08f0efKenny Root * 41ebd74acf9977daa42133507e970dab88e08f0efKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 51ebd74acf9977daa42133507e970dab88e08f0efKenny Root * you may not use this file except in compliance with the License. 61ebd74acf9977daa42133507e970dab88e08f0efKenny Root * You may obtain a copy of the License at 71ebd74acf9977daa42133507e970dab88e08f0efKenny Root * 81ebd74acf9977daa42133507e970dab88e08f0efKenny Root * http://www.apache.org/licenses/LICENSE-2.0 91ebd74acf9977daa42133507e970dab88e08f0efKenny Root * 101ebd74acf9977daa42133507e970dab88e08f0efKenny Root * Unless required by applicable law or agreed to in writing, software 111ebd74acf9977daa42133507e970dab88e08f0efKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 121ebd74acf9977daa42133507e970dab88e08f0efKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ebd74acf9977daa42133507e970dab88e08f0efKenny Root * See the License for the specific language governing permissions and 141ebd74acf9977daa42133507e970dab88e08f0efKenny Root * limitations under the License. 151ebd74acf9977daa42133507e970dab88e08f0efKenny Root */ 161ebd74acf9977daa42133507e970dab88e08f0efKenny Root 1785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootpackage com.android.internal.content; 1885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 1973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport static android.content.pm.PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS; 2073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport static android.content.pm.PackageManager.INSTALL_SUCCEEDED; 2173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport static android.content.pm.PackageManager.NO_NATIVE_LIBRARIES; 22bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport static android.system.OsConstants.S_IRGRP; 23bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport static android.system.OsConstants.S_IROTH; 24bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport static android.system.OsConstants.S_IRWXU; 25bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport static android.system.OsConstants.S_IXGRP; 26bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport static android.system.OsConstants.S_IXOTH; 2773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey 28941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkeyimport android.content.pm.ApplicationInfo; 291378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghiimport android.content.pm.PackageManager; 3073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport android.content.pm.PackageParser; 318d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkeyimport android.content.pm.PackageParser.Package; 3273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport android.content.pm.PackageParser.PackageLite; 3373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport android.content.pm.PackageParser.PackageParserException; 34bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport android.os.Build; 35bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport android.os.SELinux; 36ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanovimport android.os.SystemProperties; 37bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport android.system.ErrnoException; 38bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport android.system.Os; 3985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.util.Slog; 4085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 4173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport dalvik.system.CloseGuard; 42bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport dalvik.system.VMRuntime; 4373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey 44cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamathimport java.io.Closeable; 4585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.io.File; 461704e3cf0c445512f0a9644485dd3449e874556bDianne Hackbornimport java.io.FileDescriptor; 47d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathimport java.io.IOException; 4873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport java.util.List; 4985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 5085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root/** 5185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Native libraries helper. 5285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 5385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * @hide 5485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 5585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootpublic class NativeLibraryHelper { 5685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final String TAG = "NativeHelper"; 5785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final boolean DEBUG_NATIVE = false; 5885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 59941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static final String LIB_DIR_NAME = "lib"; 60941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static final String LIB64_DIR_NAME = "lib64"; 61941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey 62bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate 63bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // that the cpuAbiOverride must be clear. 64bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey public static final String CLEAR_ABI_OVERRIDE = "-"; 65bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 661378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi /** 6773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey * A handle to an opened package, consisting of one or more APKs. Used as 6873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey * input to the various NativeLibraryHelper methods. Allows us to scan and 6973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey * parse the APKs exactly once instead of doing it multiple times. 701378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * 711378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * @hide 721378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi */ 7373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey public static class Handle implements Closeable { 7473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey private final CloseGuard mGuard = CloseGuard.get(); 7573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey private volatile boolean mClosed; 7673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey 7773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final long[] apkHandles; 78941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey final boolean multiArch; 79ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov final boolean extractNativeLibs; 80d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer final boolean debuggable; 8173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey 8273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey public static Handle create(File packageFile) throws IOException { 8373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey try { 84be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey final PackageLite lite = PackageParser.parsePackageLite(packageFile, 0); 85be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey return create(lite); 8673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } catch (PackageParserException e) { 8773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey throw new IOException("Failed to parse package: " + packageFile, e); 88cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath } 89be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey } 90cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath 918d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey public static Handle create(Package pkg) throws IOException { 92941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey return create(pkg.getAllCodePaths(), 93ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0, 94d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0, 95d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0); 968d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey } 978d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey 98be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey public static Handle create(PackageLite lite) throws IOException { 99d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer return create(lite.getAllCodePaths(), lite.multiArch, lite.extractNativeLibs, 100d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer lite.debuggable); 1018d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey } 1028d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey 103ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov private static Handle create(List<String> codePaths, boolean multiArch, 104d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer boolean extractNativeLibs, boolean debuggable) throws IOException { 10573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final int size = codePaths.size(); 10673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final long[] apkHandles = new long[size]; 10773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (int i = 0; i < size; i++) { 10873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final String path = codePaths.get(i); 10973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey apkHandles[i] = nativeOpenApk(path); 11073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (apkHandles[i] == 0) { 11173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // Unwind everything we've opened so far 11273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (int j = 0; j < i; j++) { 11373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey nativeClose(apkHandles[j]); 11473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 11573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey throw new IOException("Unable to open APK: " + path); 11673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 11773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 118cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath 119d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer return new Handle(apkHandles, multiArch, extractNativeLibs, debuggable); 1201378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 1211378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 1221704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn public static Handle createFd(PackageLite lite, FileDescriptor fd) throws IOException { 1231704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn final long[] apkHandles = new long[1]; 1241704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn final String path = lite.baseCodePath; 1251704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn apkHandles[0] = nativeOpenApkFd(fd, path); 1261704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn if (apkHandles[0] == 0) { 1271704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn throw new IOException("Unable to open APK " + path + " from fd " + fd); 1281704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn } 1291704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn 1301704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn return new Handle(apkHandles, lite.multiArch, lite.extractNativeLibs, lite.debuggable); 1311704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn } 1321704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn 133d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer Handle(long[] apkHandles, boolean multiArch, boolean extractNativeLibs, 134d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer boolean debuggable) { 13573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey this.apkHandles = apkHandles; 136941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey this.multiArch = multiArch; 137ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov this.extractNativeLibs = extractNativeLibs; 138d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer this.debuggable = debuggable; 13973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey mGuard.open("close"); 1401378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 1411378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 142cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath @Override 1431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi public void close() { 14473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : apkHandles) { 14573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey nativeClose(apkHandle); 14673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 14773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey mGuard.close(); 14873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey mClosed = true; 1491378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 1501378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 15173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey @Override 15273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey protected void finalize() throws Throwable { 15373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (mGuard != null) { 15473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey mGuard.warnIfOpen(); 15573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 15673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey try { 15773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (!mClosed) { 15873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey close(); 15973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 16073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } finally { 16173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey super.finalize(); 16273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 16373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 16473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 1651378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 1661378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi private static native long nativeOpenApk(String path); 1671704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn private static native long nativeOpenApkFd(FileDescriptor fd, String debugPath); 1681378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi private static native void nativeClose(long handle); 1691378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 170d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer private static native long nativeSumNativeBinaries(long handle, String cpuAbi, 171d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer boolean debuggable); 17285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 173ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov private native static int nativeCopyNativeBinaries(long handle, String sharedLibraryPath, 174d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer String abiToCopy, boolean extractNativeLibs, boolean hasNativeBridge, 175d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer boolean debuggable); 176bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 177bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private static long sumNativeBinaries(Handle handle, String abi) { 17873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey long sum = 0; 17973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : handle.apkHandles) { 180d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer sum += nativeSumNativeBinaries(apkHandle, abi, handle.debuggable); 18173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 18273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return sum; 18385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 18485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 1851ebd74acf9977daa42133507e970dab88e08f0efKenny Root /** 1861ebd74acf9977daa42133507e970dab88e08f0efKenny Root * Copies native binaries to a shared library directory. 1871ebd74acf9977daa42133507e970dab88e08f0efKenny Root * 1881378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * @param handle APK file to scan for native libraries 1891ebd74acf9977daa42133507e970dab88e08f0efKenny Root * @param sharedLibraryDir directory for libraries to be copied to 1901ebd74acf9977daa42133507e970dab88e08f0efKenny Root * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another 1911ebd74acf9977daa42133507e970dab88e08f0efKenny Root * error code from that class if not 1921ebd74acf9977daa42133507e970dab88e08f0efKenny Root */ 193941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) { 19473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : handle.apkHandles) { 195ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi, 196d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer handle.extractNativeLibs, HAS_NATIVE_BRIDGE, handle.debuggable); 19773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (res != INSTALL_SUCCEEDED) { 19873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return res; 19973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 20073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 20173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return INSTALL_SUCCEEDED; 20285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 2038f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root 2041378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi /** 2051378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * Checks if a given APK contains native code for any of the provided 2061378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching 2071378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the 2081378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * APK doesn't contain any native code, and 2091378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match. 2101378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi */ 21173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey public static int findSupportedAbi(Handle handle, String[] supportedAbis) { 21273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey int finalRes = NO_NATIVE_LIBRARIES; 21373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : handle.apkHandles) { 214d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer final int res = nativeFindSupportedAbi(apkHandle, supportedAbis, handle.debuggable); 21573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (res == NO_NATIVE_LIBRARIES) { 21673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // No native code, keep looking through all APKs. 21773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) { 21873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // Found some native code, but no ABI match; update our final 21973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // result if we haven't found other valid code. 22073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (finalRes < 0) { 22173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey finalRes = INSTALL_FAILED_NO_MATCHING_ABIS; 22273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 22373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } else if (res >= 0) { 22473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // Found valid native code, track the best ABI match 22573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (finalRes < 0 || res < finalRes) { 22673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey finalRes = res; 22773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 22873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } else { 22973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // Unexpected error; bail 23073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return res; 23173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 23273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 23373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return finalRes; 2341378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 2351378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 236d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis, 237d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer boolean debuggable); 2381378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 239831baa2e2566bf1d243c06918672abd5ff786105Kenny Root // Convenience method to call removeNativeBinariesFromDirLI(File) 240ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath public static void removeNativeBinariesLI(String nativeLibraryPath) { 241ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (nativeLibraryPath == null) return; 242ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath removeNativeBinariesFromDirLI(new File(nativeLibraryPath), false /* delete root dir */); 243831baa2e2566bf1d243c06918672abd5ff786105Kenny Root } 244831baa2e2566bf1d243c06918672abd5ff786105Kenny Root 245ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath /** 246ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath * Remove the native binaries of a given package. This deletes the files 247ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath */ 248ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot, 249ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov boolean deleteRootDir) { 2508f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root if (DEBUG_NATIVE) { 251ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath()); 2528f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 2538f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root 2548f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root /* 2558f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * Just remove any file in the directory. Since the directory is owned 2568f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * by the 'system' UID, the application is not supposed to have written 2578f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * anything there. 2588f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root */ 259ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (nativeLibraryRoot.exists()) { 260ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath final File[] files = nativeLibraryRoot.listFiles(); 261ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (files != null) { 262ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath for (int nn = 0; nn < files.length; nn++) { 2638f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root if (DEBUG_NATIVE) { 264ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath Slog.d(TAG, " Deleting " + files[nn].getName()); 2658f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 266831baa2e2566bf1d243c06918672abd5ff786105Kenny Root 267ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (files[nn].isDirectory()) { 268ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath removeNativeBinariesFromDirLI(files[nn], true /* delete root dir */); 269ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath } else if (!files[nn].delete()) { 270ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath Slog.w(TAG, "Could not delete native binary: " + files[nn].getPath()); 2718f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 2728f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 2738f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 274ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath // Do not delete 'lib' directory itself, unless we're specifically 275ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath // asked to or this will prevent installation of future updates. 276ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (deleteRootDir) { 277ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (!nativeLibraryRoot.delete()) { 278ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov Slog.w(TAG, "Could not delete native binary directory: " + 279ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov nativeLibraryRoot.getPath()); 280ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath } 281ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath } 2828f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 2838f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 284d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 2851bea237aa296a35c263f0c4965ba0f5a140cd848Patrick Baumann /** 2861bea237aa296a35c263f0c4965ba0f5a140cd848Patrick Baumann * @hide 2871bea237aa296a35c263f0c4965ba0f5a140cd848Patrick Baumann */ 2881bea237aa296a35c263f0c4965ba0f5a140cd848Patrick Baumann public static void createNativeLibrarySubdir(File path) throws IOException { 289bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (!path.isDirectory()) { 290bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey path.delete(); 291bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 292bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (!path.mkdir()) { 293bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throw new IOException("Cannot create " + path.getPath()); 294bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 295bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 296bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey try { 297bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 298bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } catch (ErrnoException e) { 299bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throw new IOException("Cannot chmod native library directory " 300bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey + path.getPath(), e); 301bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 302bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else if (!SELinux.restorecon(path)) { 303bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throw new IOException("Cannot set SELinux context for " + path.getPath()); 304bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 305bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 306bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 307941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey private static long sumNativeBinariesForSupportedAbi(Handle handle, String[] abiList) { 308bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey int abi = findSupportedAbi(handle, abiList); 309bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (abi >= 0) { 310bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return sumNativeBinaries(handle, abiList[abi]); 311bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else { 312bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return 0; 313bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 314bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 315bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 316941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot, 317bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String[] abiList, boolean useIsaSubdir) throws IOException { 318bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey createNativeLibrarySubdir(libraryRoot); 319bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 320bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey /* 321bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey * If this is an internal application or our nativeLibraryPath points to 322bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey * the app-lib directory, unpack the libraries if necessary. 323bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey */ 324bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey int abi = findSupportedAbi(handle, abiList); 325bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (abi >= 0) { 326bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey /* 327bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey * If we have a matching instruction set, construct a subdir under the native 328bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey * library root that corresponds to this instruction set. 329bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey */ 330bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]); 331bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey final File subDir; 332bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (useIsaSubdir) { 333bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey final File isaSubdir = new File(libraryRoot, instructionSet); 334bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey createNativeLibrarySubdir(isaSubdir); 335bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey subDir = isaSubdir; 336bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else { 337bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey subDir = libraryRoot; 338bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 339bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 340941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]); 341bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (copyRet != PackageManager.INSTALL_SUCCEEDED) { 342bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return copyRet; 343bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 344bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 345bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 346bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return abi; 347bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 348bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 349941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static int copyNativeBinariesWithOverride(Handle handle, File libraryRoot, 350941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey String abiOverride) { 351bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey try { 352941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey if (handle.multiArch) { 353bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // Warn if we've set an abiOverride for multi-lib packages.. 354bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // By definition, we need to copy both 32 and 64 bit libraries for 355bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // such packages. 356bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) { 357bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Ignoring abiOverride for multi arch application."); 358bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 359bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 360bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey int copyRet = PackageManager.NO_NATIVE_LIBRARIES; 361bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { 362941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, 363bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */); 364bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES && 365bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { 366bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Failure copying 32 bit native libraries; copyRet=" +copyRet); 367bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return copyRet; 368bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 369bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 370bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 371bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { 372941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, 373bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */); 374bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES && 375bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { 376bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Failure copying 64 bit native libraries; copyRet=" +copyRet); 377bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return copyRet; 378bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 379bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 380bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else { 381bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String cpuAbiOverride = null; 382bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) { 383bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey cpuAbiOverride = null; 384bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else if (abiOverride != null) { 385bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey cpuAbiOverride = abiOverride; 386bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 387bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 388bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String[] abiList = (cpuAbiOverride != null) ? 389bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS; 390bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null && 391bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey hasRenderscriptBitcode(handle)) { 392bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey abiList = Build.SUPPORTED_32_BIT_ABIS; 393bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 394bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 395941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey int copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, abiList, 396bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey true /* use isa specific subdirs */); 397bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) { 398bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]"); 399bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return copyRet; 400bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 401bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 402bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 403bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return PackageManager.INSTALL_SUCCEEDED; 404bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } catch (IOException e) { 405bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.e(TAG, "Copying native libraries failed", e); 406bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; 407bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 408bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 409bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 410941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static long sumNativeBinariesWithOverride(Handle handle, String abiOverride) 411bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throws IOException { 412bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey long sum = 0; 413941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey if (handle.multiArch) { 414bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // Warn if we've set an abiOverride for multi-lib packages.. 415bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // By definition, we need to copy both 32 and 64 bit libraries for 416bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // such packages. 417bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) { 418bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Ignoring abiOverride for multi arch application."); 419bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 420bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 421bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { 422941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS); 423bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 424bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 425bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { 426941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS); 427bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 428bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else { 429bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String cpuAbiOverride = null; 430bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) { 431bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey cpuAbiOverride = null; 432bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else if (abiOverride != null) { 433bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey cpuAbiOverride = abiOverride; 434bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 435bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 436bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String[] abiList = (cpuAbiOverride != null) ? 437bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS; 438bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null && 439bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey hasRenderscriptBitcode(handle)) { 440bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey abiList = Build.SUPPORTED_32_BIT_ABIS; 441bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 442bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 443941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey sum += sumNativeBinariesForSupportedAbi(handle, abiList); 444bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 445bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return sum; 446bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 447bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 448d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath // We don't care about the other return values for now. 449d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath private static final int BITCODE_PRESENT = 1; 450d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 451ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov private static final boolean HAS_NATIVE_BRIDGE = 452ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov !"0".equals(SystemProperties.get("ro.dalvik.vm.native.bridge", "0")); 453ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov 454bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private static native int hasRenderscriptBitcode(long apkHandle); 455bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 45673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey public static boolean hasRenderscriptBitcode(Handle handle) throws IOException { 45773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : handle.apkHandles) { 45873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final int res = hasRenderscriptBitcode(apkHandle); 45973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (res < 0) { 46073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey throw new IOException("Error scanning APK, code: " + res); 46173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } else if (res == BITCODE_PRESENT) { 46273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return true; 46373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 464d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 46573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return false; 466d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 46785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root} 468