NativeLibraryHelper.java revision 85387d7ba36e56b291cbde87acb5a5b2200fe01c
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
18385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root            final String installGdbServerPath = APK_LIB + 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    }
29685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root}
297