NativeLibraryHelper.java revision 831baa2e2566bf1d243c06918672abd5ff786105
185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootpackage com.android.internal.content; 285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.content.pm.PackageManager; 485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.os.Build; 585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.os.FileUtils; 685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.os.SystemProperties; 785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.util.Config; 885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.util.Log; 985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.util.Pair; 1085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.util.Slog; 1185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 1285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.io.File; 1385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.io.IOException; 1485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.io.InputStream; 1585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.util.Enumeration; 1685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.util.LinkedList; 1785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.util.List; 1885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.util.zip.ZipEntry; 1985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.util.zip.ZipException; 2085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.util.zip.ZipFile; 2185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 2285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root/** 2385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Native libraries helper. 2485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 2585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * @hide 2685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 2785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootpublic class NativeLibraryHelper { 2885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final String TAG = "NativeHelper"; 2985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 3085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final boolean DEBUG_NATIVE = false; 3185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 3285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 3385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * The following constants are returned by listPackageSharedLibsForAbiLI 3485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * to indicate if native shared libraries were found in the package. 3585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Values are: 3685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed 3785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package 3885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found 3985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * in package (and not installed) 4085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 4185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 4285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0; 4385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1; 4485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2; 4585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 4685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // Directory in the APK that holds all the native shared libraries. 4785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final String APK_LIB = "lib/"; 4885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final int APK_LIB_LENGTH = APK_LIB.length(); 4985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 5085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // Prefix that native shared libraries must have. 5185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final String LIB_PREFIX = "lib"; 5285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final int LIB_PREFIX_LENGTH = LIB_PREFIX.length(); 5385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 5485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // Suffix that the native shared libraries must have. 5585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final String LIB_SUFFIX = ".so"; 5685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final int LIB_SUFFIX_LENGTH = LIB_SUFFIX.length(); 5785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 5885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // Name of the GDB binary. 5985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final String GDBSERVER = "gdbserver"; 6085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 6185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // the minimum length of a valid native shared library of the form 6285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // lib/<something>/lib<name>.so. 6385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static final int MIN_ENTRY_LENGTH = APK_LIB_LENGTH + 2 + LIB_PREFIX_LENGTH + 1 6485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root + LIB_SUFFIX_LENGTH; 6585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 6685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 6785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk 6885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * and add them to a list to be installed later. 6985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 7085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * NOTE: this method may throw an IOException if the library cannot 7185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * be copied to its final destination, e.g. if there isn't enough 7285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * room left on the data partition, or a ZipException if the package 7385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * file is malformed. 7485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 7585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static int listPackageSharedLibsForAbiLI(ZipFile zipFile, 7685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root String cpuAbi, List<Pair<ZipEntry, String>> libEntries) throws IOException, 7785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root ZipException { 7885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root final int cpuAbiLen = cpuAbi.length(); 7985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root boolean hasNativeLibraries = false; 8085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root boolean installedNativeLibraries = false; 8185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 8285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (DEBUG_NATIVE) { 8385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root Slog.d(TAG, "Checking " + zipFile.getName() + " for shared libraries of CPU ABI type " 8485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root + cpuAbi); 8585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 8685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 8785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root Enumeration<? extends ZipEntry> entries = zipFile.entries(); 8885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 8985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root while (entries.hasMoreElements()) { 9085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root ZipEntry entry = entries.nextElement(); 9185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 9285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // skip directories 9385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (entry.isDirectory()) { 9485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root continue; 9585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 9685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root String entryName = entry.getName(); 9785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 9885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 9985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Check that the entry looks like lib/<something>/lib<name>.so 10085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * here, but don't check the ABI just yet. 10185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 10285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * - must be sufficiently long 10385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * - must end with LIB_SUFFIX, i.e. ".so" 10485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * - must start with APK_LIB, i.e. "lib/" 10585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 10685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (entryName.length() < MIN_ENTRY_LENGTH || !entryName.endsWith(LIB_SUFFIX) 10785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root || !entryName.startsWith(APK_LIB)) { 10885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root continue; 10985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 11085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 11185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // file name must start with LIB_PREFIX, i.e. "lib" 11285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root int lastSlash = entryName.lastIndexOf('/'); 11385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 11485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (lastSlash < 0 11585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root || !entryName.regionMatches(lastSlash + 1, LIB_PREFIX, 0, LIB_PREFIX_LENGTH)) { 11685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root continue; 11785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 11885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 11985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root hasNativeLibraries = true; 12085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 12185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // check the cpuAbi now, between lib/ and /lib<name>.so 12285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (lastSlash != APK_LIB_LENGTH + cpuAbiLen 12385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root || !entryName.regionMatches(APK_LIB_LENGTH, cpuAbi, 0, cpuAbiLen)) 12485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root continue; 12585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 12685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 12785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Extract the library file name, ensure it doesn't contain 12885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * weird characters. we're guaranteed here that it doesn't contain 12985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * a directory separator though. 13085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 13185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root String libFileName = entryName.substring(lastSlash+1); 13285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (!FileUtils.isFilenameSafe(new File(libFileName))) { 13385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root continue; 13485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 13585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 13685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root installedNativeLibraries = true; 13785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 13885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (DEBUG_NATIVE) { 13985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root Log.d(TAG, "Caching shared lib " + entry.getName()); 14085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 14185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 14285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root libEntries.add(Pair.create(entry, libFileName)); 14385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 14485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (!hasNativeLibraries) 14585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES; 14685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 14785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (!installedNativeLibraries) 14885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH; 14985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 15085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES; 15185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 15285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 15385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 15485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Find the gdbserver executable program in a package at 15585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * lib/<cpuAbi>/gdbserver and add it to the list of binaries 15685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * to be copied out later. 15785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 15885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success, 15985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise. 16085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 16185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static int listPackageGdbServerLI(ZipFile zipFile, String cpuAbi, 16285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root List<Pair<ZipEntry, String>> nativeFiles) throws IOException, ZipException { 16385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER; 16485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 16585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root Enumeration<? extends ZipEntry> entries = zipFile.entries(); 16685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 16785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root while (entries.hasMoreElements()) { 16885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root ZipEntry entry = entries.nextElement(); 16985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // skip directories 17085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (entry.isDirectory()) { 17185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root continue; 17285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 17385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root String entryName = entry.getName(); 17485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 17585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (!entryName.equals(apkGdbServerPath)) { 17685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root continue; 17785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 17885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 17985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (Config.LOGD) { 18085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root Log.d(TAG, "Found gdbserver: " + entry.getName()); 18185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 18285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 183e6da118ebfa2574da7a635158178b768f3a226e1Kenny Root final String installGdbServerPath = GDBSERVER; 18485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root nativeFiles.add(Pair.create(entry, installGdbServerPath)); 18585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 18685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES; 18785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 18885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES; 18985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 19085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 19185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 19285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Examine shared libraries stored in the APK as 19385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * lib/<cpuAbi>/lib<name>.so and add them to a list to be copied 19485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * later. 19585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 19685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * This function will first try the main CPU ABI defined by Build.CPU_ABI 19785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * (which corresponds to ro.product.cpu.abi), and also try an alternate 19885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * one if ro.product.cpu.abi2 is defined. 19985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 20085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root public static int listPackageNativeBinariesLI(ZipFile zipFile, 20185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root List<Pair<ZipEntry, String>> nativeFiles) throws ZipException, IOException { 20285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root String cpuAbi = Build.CPU_ABI; 20385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 20485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root int result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi, nativeFiles); 20585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 20685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 20785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Some architectures are capable of supporting several CPU ABIs 20885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * for example, 'armeabi-v7a' also supports 'armeabi' native code 20985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * this is indicated by the definition of the ro.product.cpu.abi2 21085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * system property. 21185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * 21285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * only scan the package twice in case of ABI mismatch 21385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 21485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) { 21585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2", null); 21685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (cpuAbi2 != null) { 21785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi2, nativeFiles); 21885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 21985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 22085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) { 22185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root Slog.w(TAG, "Native ABI mismatch from package file"); 22285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PackageManager.INSTALL_FAILED_INVALID_APK; 22385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 22485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 22585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) { 22685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root cpuAbi = cpuAbi2; 22785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 22885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 22985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 23085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 23185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Debuggable packages may have gdbserver embedded, so add it to 23285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * the list to the list of items to be extracted (as lib/gdbserver) 23385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * into the application's native library directory later. 23485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 23585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) { 23685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root listPackageGdbServerLI(zipFile, cpuAbi, nativeFiles); 23785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 23885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PackageManager.INSTALL_SUCCEEDED; 23985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 24085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 24185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root public static int copyNativeBinariesLI(File scanFile, File sharedLibraryDir) { 24285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root /* 24385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Check all the native files that need to be copied and add 24485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * that to the container size. 24585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */ 24685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root ZipFile zipFile; 24785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root try { 24885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root zipFile = new ZipFile(scanFile); 24985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 25085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root List<Pair<ZipEntry, String>> nativeFiles = new LinkedList<Pair<ZipEntry, String>>(); 25185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 25285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles); 25385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 25485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root final int N = nativeFiles.size(); 25585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 25685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root for (int i = 0; i < N; i++) { 25785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root final Pair<ZipEntry, String> entry = nativeFiles.get(i); 25885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 25985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root File destFile = new File(sharedLibraryDir, entry.second); 26085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root copyNativeBinaryLI(zipFile, entry.first, sharedLibraryDir, destFile); 26185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 26285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } catch (ZipException e) { 26385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root Slog.w(TAG, "Failed to extract data from package file", e); 26485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PackageManager.INSTALL_FAILED_INVALID_APK; 26585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } catch (IOException e) { 26685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root Slog.w(TAG, "Failed to cache package shared libs", e); 26785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 26885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 26985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 27085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root return PackageManager.INSTALL_SUCCEEDED; 27185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 27285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root 27385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root private static void copyNativeBinaryLI(ZipFile zipFile, ZipEntry entry, 27485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root File binaryDir, File binaryFile) throws IOException { 27585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root InputStream inputStream = zipFile.getInputStream(entry); 27685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root try { 27785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root File tempFile = File.createTempFile("tmp", "tmp", binaryDir); 27885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root String tempFilePath = tempFile.getPath(); 27985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // XXX package manager can't change owner, so the executable files for 28085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // now need to be left as world readable and owned by the system. 28185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root if (!FileUtils.copyToFile(inputStream, tempFile) 28285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root || !tempFile.setLastModified(entry.getTime()) 28385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root || FileUtils.setPermissions(tempFilePath, FileUtils.S_IRUSR | FileUtils.S_IWUSR 28485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root | FileUtils.S_IRGRP | FileUtils.S_IXUSR | FileUtils.S_IXGRP 28585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root | FileUtils.S_IXOTH | FileUtils.S_IROTH, -1, -1) != 0 28685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root || !tempFile.renameTo(binaryFile)) { 28785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root // Failed to properly write file. 28885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root tempFile.delete(); 28985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root throw new IOException("Couldn't create cached binary " + binaryFile + " in " 29085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root + binaryDir); 29185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 29285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } finally { 29385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root inputStream.close(); 29485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 29585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root } 2968f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root 297831baa2e2566bf1d243c06918672abd5ff786105Kenny Root // Convenience method to call removeNativeBinariesFromDirLI(File) 298831baa2e2566bf1d243c06918672abd5ff786105Kenny Root public static boolean removeNativeBinariesLI(String nativeLibraryPath) { 299831baa2e2566bf1d243c06918672abd5ff786105Kenny Root return removeNativeBinariesFromDirLI(new File(nativeLibraryPath)); 300831baa2e2566bf1d243c06918672abd5ff786105Kenny Root } 301831baa2e2566bf1d243c06918672abd5ff786105Kenny Root 3028f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root // Remove the native binaries of a given package. This simply 3038f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root // gets rid of the files in the 'lib' sub-directory. 304831baa2e2566bf1d243c06918672abd5ff786105Kenny Root public static boolean removeNativeBinariesFromDirLI(File nativeLibraryDir) { 3058f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root if (DEBUG_NATIVE) { 306831baa2e2566bf1d243c06918672abd5ff786105Kenny Root Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryDir.getPath()); 3078f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 3088f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root 309831baa2e2566bf1d243c06918672abd5ff786105Kenny Root boolean deletedFiles = false; 310831baa2e2566bf1d243c06918672abd5ff786105Kenny Root 3118f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root /* 3128f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * Just remove any file in the directory. Since the directory is owned 3138f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * by the 'system' UID, the application is not supposed to have written 3148f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root * anything there. 3158f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root */ 316831baa2e2566bf1d243c06918672abd5ff786105Kenny Root if (nativeLibraryDir.exists()) { 317831baa2e2566bf1d243c06918672abd5ff786105Kenny Root final File[] binaries = nativeLibraryDir.listFiles(); 3188f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root if (binaries != null) { 3198f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root for (int nn = 0; nn < binaries.length; nn++) { 3208f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root if (DEBUG_NATIVE) { 3218f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root Slog.d(TAG, " Deleting " + binaries[nn].getName()); 3228f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 323831baa2e2566bf1d243c06918672abd5ff786105Kenny Root 3248f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root if (!binaries[nn].delete()) { 3258f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root Slog.w(TAG, "Could not delete native binary: " + binaries[nn].getPath()); 326831baa2e2566bf1d243c06918672abd5ff786105Kenny Root } else { 327831baa2e2566bf1d243c06918672abd5ff786105Kenny Root deletedFiles = true; 3288f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 3298f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 3308f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 3318f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root // Do not delete 'lib' directory itself, or this will prevent 3328f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root // installation of future updates. 3338f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 334831baa2e2566bf1d243c06918672abd5ff786105Kenny Root 335831baa2e2566bf1d243c06918672abd5ff786105Kenny Root return deletedFiles; 3368f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root } 33785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root} 338