blob: f479f4feca3539ce4868d65e41079a3e2ec0f03b [file] [log] [blame]
Kenny Root1ebd74a2011-08-03 15:09:44 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Kenny Root85387d72010-08-26 10:13:11 -070017package com.android.internal.content;
18
Jeff Sharkey73767b92014-07-04 20:18:13 -070019import static android.content.pm.PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS;
20import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
21import static android.content.pm.PackageManager.NO_NATIVE_LIBRARIES;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -070022import static android.system.OsConstants.S_IRGRP;
23import static android.system.OsConstants.S_IROTH;
24import static android.system.OsConstants.S_IRWXU;
25import static android.system.OsConstants.S_IXGRP;
26import static android.system.OsConstants.S_IXOTH;
Jeff Sharkey73767b92014-07-04 20:18:13 -070027
Jeff Sharkey941a8ba2014-08-20 16:26:32 -070028import android.content.pm.ApplicationInfo;
Ramin Zaghi1378aba2014-02-28 15:03:19 +000029import android.content.pm.PackageManager;
Jeff Sharkey73767b92014-07-04 20:18:13 -070030import android.content.pm.PackageParser;
Jeff Sharkey8d479b02014-07-08 14:57:34 -070031import android.content.pm.PackageParser.Package;
Jeff Sharkey73767b92014-07-04 20:18:13 -070032import android.content.pm.PackageParser.PackageLite;
33import android.content.pm.PackageParser.PackageParserException;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -070034import android.os.Build;
35import android.os.SELinux;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -070036import android.os.SystemProperties;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -070037import android.system.ErrnoException;
38import android.system.Os;
Kenny Root85387d72010-08-26 10:13:11 -070039import android.util.Slog;
40
Jeff Sharkey73767b92014-07-04 20:18:13 -070041import dalvik.system.CloseGuard;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -070042import dalvik.system.VMRuntime;
Jeff Sharkey73767b92014-07-04 20:18:13 -070043
Narayan Kamathcef0b392014-06-12 17:19:43 +010044import java.io.Closeable;
Kenny Root85387d72010-08-26 10:13:11 -070045import java.io.File;
Narayan Kamathd47e38b2014-05-16 16:45:56 +010046import java.io.IOException;
Jeff Sharkey73767b92014-07-04 20:18:13 -070047import java.util.List;
Kenny Root85387d72010-08-26 10:13:11 -070048
49/**
50 * Native libraries helper.
51 *
52 * @hide
53 */
54public class NativeLibraryHelper {
55 private static final String TAG = "NativeHelper";
Kenny Root85387d72010-08-26 10:13:11 -070056 private static final boolean DEBUG_NATIVE = false;
57
Jeff Sharkey941a8ba2014-08-20 16:26:32 -070058 public static final String LIB_DIR_NAME = "lib";
59 public static final String LIB64_DIR_NAME = "lib64";
60
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -070061 // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
62 // that the cpuAbiOverride must be clear.
63 public static final String CLEAR_ABI_OVERRIDE = "-";
64
Kenny Root1ebd74a2011-08-03 15:09:44 -070065 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -070066 * A handle to an opened package, consisting of one or more APKs. Used as
67 * input to the various NativeLibraryHelper methods. Allows us to scan and
68 * parse the APKs exactly once instead of doing it multiple times.
Kenny Root1ebd74a2011-08-03 15:09:44 -070069 *
Ramin Zaghi1378aba2014-02-28 15:03:19 +000070 * @hide
Kenny Root1ebd74a2011-08-03 15:09:44 -070071 */
Jeff Sharkey73767b92014-07-04 20:18:13 -070072 public static class Handle implements Closeable {
73 private final CloseGuard mGuard = CloseGuard.get();
74 private volatile boolean mClosed;
Ramin Zaghi1378aba2014-02-28 15:03:19 +000075
Jeff Sharkey73767b92014-07-04 20:18:13 -070076 final long[] apkHandles;
Jeff Sharkey941a8ba2014-08-20 16:26:32 -070077 final boolean multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -070078 final boolean extractNativeLibs;
Jeff Sharkey73767b92014-07-04 20:18:13 -070079
80 public static Handle create(File packageFile) throws IOException {
Jeff Sharkey73767b92014-07-04 20:18:13 -070081 try {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -070082 final PackageLite lite = PackageParser.parsePackageLite(packageFile, 0);
83 return create(lite);
Jeff Sharkey73767b92014-07-04 20:18:13 -070084 } catch (PackageParserException e) {
85 throw new IOException("Failed to parse package: " + packageFile, e);
Narayan Kamathcef0b392014-06-12 17:19:43 +010086 }
Jeff Sharkeybe520fb2014-07-04 18:23:17 -070087 }
Narayan Kamathcef0b392014-06-12 17:19:43 +010088
Jeff Sharkey8d479b02014-07-08 14:57:34 -070089 public static Handle create(Package pkg) throws IOException {
Jeff Sharkey941a8ba2014-08-20 16:26:32 -070090 return create(pkg.getAllCodePaths(),
Dmitriy Ivanovff193d62014-09-30 15:10:48 -070091 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0,
92 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0);
Jeff Sharkey8d479b02014-07-08 14:57:34 -070093 }
94
Jeff Sharkeybe520fb2014-07-04 18:23:17 -070095 public static Handle create(PackageLite lite) throws IOException {
Dmitriy Ivanovff193d62014-09-30 15:10:48 -070096 return create(lite.getAllCodePaths(), lite.multiArch, lite.extractNativeLibs);
Jeff Sharkey8d479b02014-07-08 14:57:34 -070097 }
98
Dmitriy Ivanovff193d62014-09-30 15:10:48 -070099 private static Handle create(List<String> codePaths, boolean multiArch,
100 boolean extractNativeLibs) throws IOException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700101 final int size = codePaths.size();
102 final long[] apkHandles = new long[size];
103 for (int i = 0; i < size; i++) {
104 final String path = codePaths.get(i);
105 apkHandles[i] = nativeOpenApk(path);
106 if (apkHandles[i] == 0) {
107 // Unwind everything we've opened so far
108 for (int j = 0; j < i; j++) {
109 nativeClose(apkHandles[j]);
110 }
111 throw new IOException("Unable to open APK: " + path);
112 }
113 }
114
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700115 return new Handle(apkHandles, multiArch, extractNativeLibs);
Ramin Zaghi1378aba2014-02-28 15:03:19 +0000116 }
117
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700118 Handle(long[] apkHandles, boolean multiArch, boolean extractNativeLibs) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700119 this.apkHandles = apkHandles;
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700120 this.multiArch = multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700121 this.extractNativeLibs = extractNativeLibs;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700122 mGuard.open("close");
Narayan Kamathcef0b392014-06-12 17:19:43 +0100123 }
124
125 @Override
Ramin Zaghi1378aba2014-02-28 15:03:19 +0000126 public void close() {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700127 for (long apkHandle : apkHandles) {
128 nativeClose(apkHandle);
129 }
130 mGuard.close();
131 mClosed = true;
132 }
133
134 @Override
135 protected void finalize() throws Throwable {
136 if (mGuard != null) {
137 mGuard.warnIfOpen();
138 }
139 try {
140 if (!mClosed) {
141 close();
142 }
143 } finally {
144 super.finalize();
145 }
Ramin Zaghi1378aba2014-02-28 15:03:19 +0000146 }
Kenny Root85387d72010-08-26 10:13:11 -0700147 }
148
Ramin Zaghi1378aba2014-02-28 15:03:19 +0000149 private static native long nativeOpenApk(String path);
150 private static native void nativeClose(long handle);
151
152 private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
153
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700154 private native static int nativeCopyNativeBinaries(long handle, String sharedLibraryPath,
155 String abiToCopy, boolean extractNativeLibs, boolean hasNativeBridge);
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700156
157 private static long sumNativeBinaries(Handle handle, String abi) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700158 long sum = 0;
159 for (long apkHandle : handle.apkHandles) {
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700160 sum += nativeSumNativeBinaries(apkHandle, abi);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700161 }
162 return sum;
Ramin Zaghi1378aba2014-02-28 15:03:19 +0000163 }
164
Kenny Root1ebd74a2011-08-03 15:09:44 -0700165 /**
166 * Copies native binaries to a shared library directory.
167 *
Ramin Zaghi1378aba2014-02-28 15:03:19 +0000168 * @param handle APK file to scan for native libraries
Kenny Root1ebd74a2011-08-03 15:09:44 -0700169 * @param sharedLibraryDir directory for libraries to be copied to
170 * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
171 * error code from that class if not
172 */
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700173 public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700174 for (long apkHandle : handle.apkHandles) {
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700175 int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi,
176 handle.extractNativeLibs, HAS_NATIVE_BRIDGE);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700177 if (res != INSTALL_SUCCEEDED) {
178 return res;
179 }
180 }
181 return INSTALL_SUCCEEDED;
Kenny Root85387d72010-08-26 10:13:11 -0700182 }
Kenny Root8f7cc022010-09-12 09:04:56 -0700183
Ramin Zaghi1378aba2014-02-28 15:03:19 +0000184 /**
185 * Checks if a given APK contains native code for any of the provided
186 * {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching
187 * ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the
188 * APK doesn't contain any native code, and
189 * {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match.
190 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700191 public static int findSupportedAbi(Handle handle, String[] supportedAbis) {
192 int finalRes = NO_NATIVE_LIBRARIES;
193 for (long apkHandle : handle.apkHandles) {
194 final int res = nativeFindSupportedAbi(apkHandle, supportedAbis);
195 if (res == NO_NATIVE_LIBRARIES) {
196 // No native code, keep looking through all APKs.
197 } else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) {
198 // Found some native code, but no ABI match; update our final
199 // result if we haven't found other valid code.
200 if (finalRes < 0) {
201 finalRes = INSTALL_FAILED_NO_MATCHING_ABIS;
202 }
203 } else if (res >= 0) {
204 // Found valid native code, track the best ABI match
205 if (finalRes < 0 || res < finalRes) {
206 finalRes = res;
207 }
208 } else {
209 // Unexpected error; bail
210 return res;
211 }
212 }
213 return finalRes;
Ramin Zaghi1378aba2014-02-28 15:03:19 +0000214 }
215
216 private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis);
217
Kenny Root831baa22010-10-05 12:29:25 -0700218 // Convenience method to call removeNativeBinariesFromDirLI(File)
Narayan Kamathff110bd2014-07-04 18:30:45 +0100219 public static void removeNativeBinariesLI(String nativeLibraryPath) {
220 if (nativeLibraryPath == null) return;
221 removeNativeBinariesFromDirLI(new File(nativeLibraryPath), false /* delete root dir */);
Kenny Root831baa22010-10-05 12:29:25 -0700222 }
223
Narayan Kamathff110bd2014-07-04 18:30:45 +0100224 /**
225 * Remove the native binaries of a given package. This deletes the files
226 */
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700227 public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot,
228 boolean deleteRootDir) {
Kenny Root8f7cc022010-09-12 09:04:56 -0700229 if (DEBUG_NATIVE) {
Narayan Kamathff110bd2014-07-04 18:30:45 +0100230 Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath());
Kenny Root8f7cc022010-09-12 09:04:56 -0700231 }
232
233 /*
234 * Just remove any file in the directory. Since the directory is owned
235 * by the 'system' UID, the application is not supposed to have written
236 * anything there.
237 */
Narayan Kamathff110bd2014-07-04 18:30:45 +0100238 if (nativeLibraryRoot.exists()) {
239 final File[] files = nativeLibraryRoot.listFiles();
240 if (files != null) {
241 for (int nn = 0; nn < files.length; nn++) {
Kenny Root8f7cc022010-09-12 09:04:56 -0700242 if (DEBUG_NATIVE) {
Narayan Kamathff110bd2014-07-04 18:30:45 +0100243 Slog.d(TAG, " Deleting " + files[nn].getName());
Kenny Root8f7cc022010-09-12 09:04:56 -0700244 }
Kenny Root831baa22010-10-05 12:29:25 -0700245
Narayan Kamathff110bd2014-07-04 18:30:45 +0100246 if (files[nn].isDirectory()) {
247 removeNativeBinariesFromDirLI(files[nn], true /* delete root dir */);
248 } else if (!files[nn].delete()) {
249 Slog.w(TAG, "Could not delete native binary: " + files[nn].getPath());
Kenny Root8f7cc022010-09-12 09:04:56 -0700250 }
251 }
252 }
Narayan Kamathff110bd2014-07-04 18:30:45 +0100253 // Do not delete 'lib' directory itself, unless we're specifically
254 // asked to or this will prevent installation of future updates.
255 if (deleteRootDir) {
256 if (!nativeLibraryRoot.delete()) {
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700257 Slog.w(TAG, "Could not delete native binary directory: " +
258 nativeLibraryRoot.getPath());
Narayan Kamathff110bd2014-07-04 18:30:45 +0100259 }
260 }
Kenny Root8f7cc022010-09-12 09:04:56 -0700261 }
262 }
Narayan Kamathd47e38b2014-05-16 16:45:56 +0100263
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700264 private static void createNativeLibrarySubdir(File path) throws IOException {
265 if (!path.isDirectory()) {
266 path.delete();
267
268 if (!path.mkdir()) {
269 throw new IOException("Cannot create " + path.getPath());
270 }
271
272 try {
273 Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
274 } catch (ErrnoException e) {
275 throw new IOException("Cannot chmod native library directory "
276 + path.getPath(), e);
277 }
278 } else if (!SELinux.restorecon(path)) {
279 throw new IOException("Cannot set SELinux context for " + path.getPath());
280 }
281 }
282
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700283 private static long sumNativeBinariesForSupportedAbi(Handle handle, String[] abiList) {
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700284 int abi = findSupportedAbi(handle, abiList);
285 if (abi >= 0) {
286 return sumNativeBinaries(handle, abiList[abi]);
287 } else {
288 return 0;
289 }
290 }
291
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700292 public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot,
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700293 String[] abiList, boolean useIsaSubdir) throws IOException {
294 createNativeLibrarySubdir(libraryRoot);
295
296 /*
297 * If this is an internal application or our nativeLibraryPath points to
298 * the app-lib directory, unpack the libraries if necessary.
299 */
300 int abi = findSupportedAbi(handle, abiList);
301 if (abi >= 0) {
302 /*
303 * If we have a matching instruction set, construct a subdir under the native
304 * library root that corresponds to this instruction set.
305 */
306 final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
307 final File subDir;
308 if (useIsaSubdir) {
309 final File isaSubdir = new File(libraryRoot, instructionSet);
310 createNativeLibrarySubdir(isaSubdir);
311 subDir = isaSubdir;
312 } else {
313 subDir = libraryRoot;
314 }
315
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700316 int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]);
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700317 if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
318 return copyRet;
319 }
320 }
321
322 return abi;
323 }
324
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700325 public static int copyNativeBinariesWithOverride(Handle handle, File libraryRoot,
326 String abiOverride) {
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700327 try {
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700328 if (handle.multiArch) {
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700329 // Warn if we've set an abiOverride for multi-lib packages..
330 // By definition, we need to copy both 32 and 64 bit libraries for
331 // such packages.
332 if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
333 Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
334 }
335
336 int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
337 if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700338 copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot,
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700339 Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
340 if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
341 copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
342 Slog.w(TAG, "Failure copying 32 bit native libraries; copyRet=" +copyRet);
343 return copyRet;
344 }
345 }
346
347 if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700348 copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot,
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700349 Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
350 if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
351 copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
352 Slog.w(TAG, "Failure copying 64 bit native libraries; copyRet=" +copyRet);
353 return copyRet;
354 }
355 }
356 } else {
357 String cpuAbiOverride = null;
358 if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
359 cpuAbiOverride = null;
360 } else if (abiOverride != null) {
361 cpuAbiOverride = abiOverride;
362 }
363
364 String[] abiList = (cpuAbiOverride != null) ?
365 new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
366 if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
367 hasRenderscriptBitcode(handle)) {
368 abiList = Build.SUPPORTED_32_BIT_ABIS;
369 }
370
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700371 int copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, abiList,
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700372 true /* use isa specific subdirs */);
373 if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
374 Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
375 return copyRet;
376 }
377 }
378
379 return PackageManager.INSTALL_SUCCEEDED;
380 } catch (IOException e) {
381 Slog.e(TAG, "Copying native libraries failed", e);
382 return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
383 }
384 }
385
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700386 public static long sumNativeBinariesWithOverride(Handle handle, String abiOverride)
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700387 throws IOException {
388 long sum = 0;
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700389 if (handle.multiArch) {
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700390 // Warn if we've set an abiOverride for multi-lib packages..
391 // By definition, we need to copy both 32 and 64 bit libraries for
392 // such packages.
393 if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
394 Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
395 }
396
397 if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700398 sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700399 }
400
401 if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700402 sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700403 }
404 } else {
405 String cpuAbiOverride = null;
406 if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
407 cpuAbiOverride = null;
408 } else if (abiOverride != null) {
409 cpuAbiOverride = abiOverride;
410 }
411
412 String[] abiList = (cpuAbiOverride != null) ?
413 new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
414 if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
415 hasRenderscriptBitcode(handle)) {
416 abiList = Build.SUPPORTED_32_BIT_ABIS;
417 }
418
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700419 sum += sumNativeBinariesForSupportedAbi(handle, abiList);
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700420 }
421 return sum;
422 }
423
Narayan Kamathd47e38b2014-05-16 16:45:56 +0100424 // We don't care about the other return values for now.
425 private static final int BITCODE_PRESENT = 1;
426
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700427 private static final boolean HAS_NATIVE_BRIDGE =
428 !"0".equals(SystemProperties.get("ro.dalvik.vm.native.bridge", "0"));
429
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700430 private static native int hasRenderscriptBitcode(long apkHandle);
431
Jeff Sharkey73767b92014-07-04 20:18:13 -0700432 public static boolean hasRenderscriptBitcode(Handle handle) throws IOException {
433 for (long apkHandle : handle.apkHandles) {
434 final int res = hasRenderscriptBitcode(apkHandle);
435 if (res < 0) {
436 throw new IOException("Error scanning APK, code: " + res);
437 } else if (res == BITCODE_PRESENT) {
438 return true;
439 }
Narayan Kamathd47e38b2014-05-16 16:45:56 +0100440 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700441 return false;
Narayan Kamathd47e38b2014-05-16 16:45:56 +0100442 }
Kenny Root85387d72010-08-26 10:13:11 -0700443}