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; 36bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport android.system.ErrnoException; 37bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport android.system.Os; 3885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.util.Slog; 3985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 4073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport dalvik.system.CloseGuard; 41bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport dalvik.system.VMRuntime; 4273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey 43cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamathimport java.io.Closeable; 4485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.io.File; 45d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathimport java.io.IOException; 4673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport java.util.List; 4785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 4885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root/** 4985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Native libraries helper. 5085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 5185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * @hide 5285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 5385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootpublic class NativeLibraryHelper { 5485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final String TAG = "NativeHelper"; 5585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final boolean DEBUG_NATIVE = false; 5685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 57941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static final String LIB_DIR_NAME = "lib"; 58941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static final String LIB64_DIR_NAME = "lib64"; 59941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey 60bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate 61bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // that the cpuAbiOverride must be clear. 62bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey public static final String CLEAR_ABI_OVERRIDE = "-"; 63bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 641378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi /** 6573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey * A handle to an opened package, consisting of one or more APKs. Used as 6673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey * input to the various NativeLibraryHelper methods. Allows us to scan and 6773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey * parse the APKs exactly once instead of doing it multiple times. 681378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * 691378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * @hide 701378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi */ 7173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey public static class Handle implements Closeable { 7273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey private final CloseGuard mGuard = CloseGuard.get(); 7373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey private volatile boolean mClosed; 7473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey 7573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final long[] apkHandles; 76941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey final boolean multiArch; 7773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey 7873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey public static Handle create(File packageFile) throws IOException { 7973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey try { 80be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey final PackageLite lite = PackageParser.parsePackageLite(packageFile, 0); 81be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey return create(lite); 8273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } catch (PackageParserException e) { 8373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey throw new IOException("Failed to parse package: " + packageFile, e); 84cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath } 85be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey } 86cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath 878d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey public static Handle create(Package pkg) throws IOException { 88941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey return create(pkg.getAllCodePaths(), 89941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0); 908d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey } 918d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey 92be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey public static Handle create(PackageLite lite) throws IOException { 93941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey return create(lite.getAllCodePaths(), lite.multiArch); 948d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey } 958d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey 96941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey private static Handle create(List<String> codePaths, boolean multiArch) throws IOException { 9773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final int size = codePaths.size(); 9873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final long[] apkHandles = new long[size]; 9973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (int i = 0; i < size; i++) { 10073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final String path = codePaths.get(i); 10173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey apkHandles[i] = nativeOpenApk(path); 10273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (apkHandles[i] == 0) { 10373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // Unwind everything we've opened so far 10473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (int j = 0; j < i; j++) { 10573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey nativeClose(apkHandles[j]); 10673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 10773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey throw new IOException("Unable to open APK: " + path); 10873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 10973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 110cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath 111941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey return new Handle(apkHandles, multiArch); 1121378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 1131378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 114941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey Handle(long[] apkHandles, boolean multiArch) { 11573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey this.apkHandles = apkHandles; 116941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey this.multiArch = multiArch; 11773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey mGuard.open("close"); 1181378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 1191378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 120cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath @Override 1211378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi public void close() { 12273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : apkHandles) { 12373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey nativeClose(apkHandle); 12473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 12573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey mGuard.close(); 12673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey mClosed = true; 1271378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 1281378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 12973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey @Override 13073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey protected void finalize() throws Throwable { 13173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (mGuard != null) { 13273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey mGuard.warnIfOpen(); 13373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 13473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey try { 13573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (!mClosed) { 13673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey close(); 13773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 13873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } finally { 13973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey super.finalize(); 14073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 14173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 14273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 1431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 1441378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi private static native long nativeOpenApk(String path); 1451378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi private static native void nativeClose(long handle); 1461378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 1471378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi private static native long nativeSumNativeBinaries(long handle, String cpuAbi); 14885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 149bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private native static int nativeCopyNativeBinaries(long handle, 150bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String sharedLibraryPath, String abiToCopy); 151bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 152bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private static long sumNativeBinaries(Handle handle, String abi) { 15373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey long sum = 0; 15473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : handle.apkHandles) { 155bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey sum += nativeSumNativeBinaries(apkHandle, abi); 15673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 15773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return sum; 15885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 15985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 1601ebd74acf9977daa42133507e970dab88e08f0efKenny Root /** 1611ebd74acf9977daa42133507e970dab88e08f0efKenny Root * Copies native binaries to a shared library directory. 1621ebd74acf9977daa42133507e970dab88e08f0efKenny Root * 1631378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * @param handle APK file to scan for native libraries 1641ebd74acf9977daa42133507e970dab88e08f0efKenny Root * @param sharedLibraryDir directory for libraries to be copied to 1651ebd74acf9977daa42133507e970dab88e08f0efKenny Root * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another 1661ebd74acf9977daa42133507e970dab88e08f0efKenny Root * error code from that class if not 1671ebd74acf9977daa42133507e970dab88e08f0efKenny Root */ 168941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) { 16973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : handle.apkHandles) { 17073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi); 17173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (res != INSTALL_SUCCEEDED) { 17273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return res; 17373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 17473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 17573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return INSTALL_SUCCEEDED; 17685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 1778f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root 1781378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi /** 1791378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * Checks if a given APK contains native code for any of the provided 1801378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching 1811378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the 1821378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * APK doesn't contain any native code, and 1831378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match. 1841378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi */ 18573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey public static int findSupportedAbi(Handle handle, String[] supportedAbis) { 18673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey int finalRes = NO_NATIVE_LIBRARIES; 18773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : handle.apkHandles) { 18873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final int res = nativeFindSupportedAbi(apkHandle, supportedAbis); 18973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (res == NO_NATIVE_LIBRARIES) { 19073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // No native code, keep looking through all APKs. 19173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) { 19273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // Found some native code, but no ABI match; update our final 19373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // result if we haven't found other valid code. 19473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (finalRes < 0) { 19573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey finalRes = INSTALL_FAILED_NO_MATCHING_ABIS; 19673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 19773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } else if (res >= 0) { 19873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // Found valid native code, track the best ABI match 19973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (finalRes < 0 || res < finalRes) { 20073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey finalRes = res; 20173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 20273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } else { 20373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey // Unexpected error; bail 20473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return res; 20573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 20673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 20773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return finalRes; 2081378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 2091378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 2101378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis); 2111378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 212831baa2e2566bf1d243c06918672abd5ff786105Kenny Root // Convenience method to call removeNativeBinariesFromDirLI(File) 213ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath public static void removeNativeBinariesLI(String nativeLibraryPath) { 214ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (nativeLibraryPath == null) return; 215ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath removeNativeBinariesFromDirLI(new File(nativeLibraryPath), false /* delete root dir */); 216831baa2e2566bf1d243c06918672abd5ff786105Kenny Root } 217831baa2e2566bf1d243c06918672abd5ff786105Kenny Root 218ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath /** 219ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath * Remove the native binaries of a given package. This deletes the files 220ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath */ 221ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot, boolean deleteRootDir) { 2228f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root if (DEBUG_NATIVE) { 223ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath()); 2248f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 2258f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root 2268f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root /* 2278f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * Just remove any file in the directory. Since the directory is owned 2288f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * by the 'system' UID, the application is not supposed to have written 2298f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * anything there. 2308f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root */ 231ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (nativeLibraryRoot.exists()) { 232ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath final File[] files = nativeLibraryRoot.listFiles(); 233ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (files != null) { 234ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath for (int nn = 0; nn < files.length; nn++) { 2358f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root if (DEBUG_NATIVE) { 236ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath Slog.d(TAG, " Deleting " + files[nn].getName()); 2378f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 238831baa2e2566bf1d243c06918672abd5ff786105Kenny Root 239ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (files[nn].isDirectory()) { 240ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath removeNativeBinariesFromDirLI(files[nn], true /* delete root dir */); 241ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath } else if (!files[nn].delete()) { 242ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath Slog.w(TAG, "Could not delete native binary: " + files[nn].getPath()); 2438f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 2448f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 2458f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 246ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath // Do not delete 'lib' directory itself, unless we're specifically 247ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath // asked to or this will prevent installation of future updates. 248ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (deleteRootDir) { 249ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath if (!nativeLibraryRoot.delete()) { 250ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath Slog.w(TAG, "Could not delete native binary directory: " + nativeLibraryRoot.getPath()); 251ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath } 252ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath } 2538f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 2548f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 255d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 256bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private static void createNativeLibrarySubdir(File path) throws IOException { 257bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (!path.isDirectory()) { 258bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey path.delete(); 259bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 260bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (!path.mkdir()) { 261bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throw new IOException("Cannot create " + path.getPath()); 262bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 263bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 264bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey try { 265bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 266bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } catch (ErrnoException e) { 267bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throw new IOException("Cannot chmod native library directory " 268bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey + path.getPath(), e); 269bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 270bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else if (!SELinux.restorecon(path)) { 271bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throw new IOException("Cannot set SELinux context for " + path.getPath()); 272bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 273bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 274bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 275941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey private static long sumNativeBinariesForSupportedAbi(Handle handle, String[] abiList) { 276bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey int abi = findSupportedAbi(handle, abiList); 277bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (abi >= 0) { 278bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return sumNativeBinaries(handle, abiList[abi]); 279bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else { 280bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return 0; 281bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 282bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 283bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 284941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot, 285bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String[] abiList, boolean useIsaSubdir) throws IOException { 286bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey createNativeLibrarySubdir(libraryRoot); 287bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 288bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey /* 289bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey * If this is an internal application or our nativeLibraryPath points to 290bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey * the app-lib directory, unpack the libraries if necessary. 291bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey */ 292bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey int abi = findSupportedAbi(handle, abiList); 293bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (abi >= 0) { 294bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey /* 295bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey * If we have a matching instruction set, construct a subdir under the native 296bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey * library root that corresponds to this instruction set. 297bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey */ 298bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]); 299bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey final File subDir; 300bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (useIsaSubdir) { 301bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey final File isaSubdir = new File(libraryRoot, instructionSet); 302bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey createNativeLibrarySubdir(isaSubdir); 303bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey subDir = isaSubdir; 304bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else { 305bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey subDir = libraryRoot; 306bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 307bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 308941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]); 309bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (copyRet != PackageManager.INSTALL_SUCCEEDED) { 310bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return copyRet; 311bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 312bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 313bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 314bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return abi; 315bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 316bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 317941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static int copyNativeBinariesWithOverride(Handle handle, File libraryRoot, 318941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey String abiOverride) { 319bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey try { 320941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey if (handle.multiArch) { 321bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // Warn if we've set an abiOverride for multi-lib packages.. 322bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // By definition, we need to copy both 32 and 64 bit libraries for 323bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // such packages. 324bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) { 325bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Ignoring abiOverride for multi arch application."); 326bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 327bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 328bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey int copyRet = PackageManager.NO_NATIVE_LIBRARIES; 329bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { 330941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, 331bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */); 332bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES && 333bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { 334bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Failure copying 32 bit native libraries; copyRet=" +copyRet); 335bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return copyRet; 336bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 337bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 338bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 339bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { 340941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, 341bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */); 342bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES && 343bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { 344bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Failure copying 64 bit native libraries; copyRet=" +copyRet); 345bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return copyRet; 346bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 347bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 348bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else { 349bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String cpuAbiOverride = null; 350bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) { 351bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey cpuAbiOverride = null; 352bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else if (abiOverride != null) { 353bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey cpuAbiOverride = abiOverride; 354bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 355bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 356bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String[] abiList = (cpuAbiOverride != null) ? 357bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS; 358bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null && 359bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey hasRenderscriptBitcode(handle)) { 360bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey abiList = Build.SUPPORTED_32_BIT_ABIS; 361bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 362bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 363941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey int copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, abiList, 364bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey true /* use isa specific subdirs */); 365bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) { 366bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]"); 367bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return copyRet; 368bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 369bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 370bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 371bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return PackageManager.INSTALL_SUCCEEDED; 372bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } catch (IOException e) { 373bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.e(TAG, "Copying native libraries failed", e); 374bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; 375bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 376bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 377bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 378941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey public static long sumNativeBinariesWithOverride(Handle handle, String abiOverride) 379bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throws IOException { 380bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey long sum = 0; 381941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey if (handle.multiArch) { 382bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // Warn if we've set an abiOverride for multi-lib packages.. 383bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // By definition, we need to copy both 32 and 64 bit libraries for 384bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey // such packages. 385bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) { 386bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey Slog.w(TAG, "Ignoring abiOverride for multi arch application."); 387bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 388bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 389bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { 390941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS); 391bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 392bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 393bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { 394941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS); 395bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 396bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else { 397bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String cpuAbiOverride = null; 398bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) { 399bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey cpuAbiOverride = null; 400bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } else if (abiOverride != null) { 401bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey cpuAbiOverride = abiOverride; 402bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 403bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 404bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey String[] abiList = (cpuAbiOverride != null) ? 405bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS; 406bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null && 407bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey hasRenderscriptBitcode(handle)) { 408bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey abiList = Build.SUPPORTED_32_BIT_ABIS; 409bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 410bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 411941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey sum += sumNativeBinariesForSupportedAbi(handle, abiList); 412bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 413bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey return sum; 414bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey } 415bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 416d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath // We don't care about the other return values for now. 417d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath private static final int BITCODE_PRESENT = 1; 418d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 419bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private static native int hasRenderscriptBitcode(long apkHandle); 420bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey 42173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey public static boolean hasRenderscriptBitcode(Handle handle) throws IOException { 42273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey for (long apkHandle : handle.apkHandles) { 42373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey final int res = hasRenderscriptBitcode(apkHandle); 42473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey if (res < 0) { 42573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey throw new IOException("Error scanning APK, code: " + res); 42673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } else if (res == BITCODE_PRESENT) { 42773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return true; 42873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey } 429d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 43073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey return false; 431d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 43285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root} 433