NativeLibraryHelper.java revision 1378aba7aeeb7f6dd6cc2503968ba7b0e58d9333
1/*
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
17package com.android.internal.content;
18
19import android.content.pm.PackageManager;
20import android.util.Slog;
21
22import java.io.File;
23
24/**
25 * Native libraries helper.
26 *
27 * @hide
28 */
29public class NativeLibraryHelper {
30    private static final String TAG = "NativeHelper";
31
32    private static final boolean DEBUG_NATIVE = false;
33
34    /**
35     * A handle to an opened APK. Used as input to the various NativeLibraryHelper
36     * methods. Allows us to scan and parse the APK exactly once instead of doing
37     * it multiple times.
38     *
39     * @hide
40     */
41    public static class ApkHandle {
42        final String apkPath;
43        final long apkHandle;
44
45        public ApkHandle(String path) {
46            apkPath = path;
47            apkHandle = nativeOpenApk(apkPath);
48        }
49
50        public ApkHandle(File apkFile) {
51            apkPath = apkFile.getPath();
52            apkHandle = nativeOpenApk(apkPath);
53        }
54
55        public void close() {
56            nativeClose(apkHandle);
57        }
58    }
59
60
61    private static native long nativeOpenApk(String path);
62    private static native void nativeClose(long handle);
63
64    private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
65
66    /**
67     * Sums the size of native binaries in an APK for a given ABI.
68     *
69     * @return size of all native binary files in bytes
70     */
71    public static long sumNativeBinariesLI(ApkHandle handle, String abi) {
72        return nativeSumNativeBinaries(handle.apkHandle, abi);
73    }
74
75    private native static int nativeCopyNativeBinaries(long handle,
76            String sharedLibraryPath, String abiToCopy);
77
78    /**
79     * Copies native binaries to a shared library directory.
80     *
81     * @param handle APK file to scan for native libraries
82     * @param sharedLibraryDir directory for libraries to be copied to
83     * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
84     *         error code from that class if not
85     */
86    public static int copyNativeBinariesIfNeededLI(ApkHandle handle, File sharedLibraryDir,
87            String abi) {
88        return nativeCopyNativeBinaries(handle.apkHandle, sharedLibraryDir.getPath(), abi);
89    }
90
91    /**
92     * Checks if a given APK contains native code for any of the provided
93     * {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching
94     * ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the
95     * APK doesn't contain any native code, and
96     * {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match.
97     */
98    public static int findSupportedAbi(ApkHandle handle, String[] supportedAbis) {
99        return nativeFindSupportedAbi(handle.apkHandle, supportedAbis);
100    }
101
102    private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis);
103
104    // Convenience method to call removeNativeBinariesFromDirLI(File)
105    public static boolean removeNativeBinariesLI(String nativeLibraryPath) {
106        return removeNativeBinariesFromDirLI(new File(nativeLibraryPath));
107    }
108
109    // Remove the native binaries of a given package. This simply
110    // gets rid of the files in the 'lib' sub-directory.
111    public static boolean removeNativeBinariesFromDirLI(File nativeLibraryDir) {
112        if (DEBUG_NATIVE) {
113            Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryDir.getPath());
114        }
115
116        boolean deletedFiles = false;
117
118        /*
119         * Just remove any file in the directory. Since the directory is owned
120         * by the 'system' UID, the application is not supposed to have written
121         * anything there.
122         */
123        if (nativeLibraryDir.exists()) {
124            final File[] binaries = nativeLibraryDir.listFiles();
125            if (binaries != null) {
126                for (int nn = 0; nn < binaries.length; nn++) {
127                    if (DEBUG_NATIVE) {
128                        Slog.d(TAG, "    Deleting " + binaries[nn].getName());
129                    }
130
131                    if (!binaries[nn].delete()) {
132                        Slog.w(TAG, "Could not delete native binary: " + binaries[nn].getPath());
133                    } else {
134                        deletedFiles = true;
135                    }
136                }
137            }
138            // Do not delete 'lib' directory itself, or this will prevent
139            // installation of future updates.
140        }
141
142        return deletedFiles;
143    }
144}
145