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;
36ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanovimport android.os.SystemProperties;
37bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport android.system.ErrnoException;
38bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport android.system.Os;
3985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport android.util.Slog;
4085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root
4173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport dalvik.system.CloseGuard;
42bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkeyimport dalvik.system.VMRuntime;
4373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey
44cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamathimport java.io.Closeable;
4585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootimport java.io.File;
461704e3cf0c445512f0a9644485dd3449e874556bDianne Hackbornimport java.io.FileDescriptor;
47d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathimport java.io.IOException;
4873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkeyimport java.util.List;
4985387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root
5085387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root/**
5185387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * Native libraries helper.
5285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root *
5385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root * @hide
5485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root */
5585387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Rootpublic class NativeLibraryHelper {
5685387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root    private static final String TAG = "NativeHelper";
5785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root    private static final boolean DEBUG_NATIVE = false;
5885387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root
59941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey    public static final String LIB_DIR_NAME = "lib";
60941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey    public static final String LIB64_DIR_NAME = "lib64";
61941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey
62bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
63bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    // that the cpuAbiOverride must be clear.
64bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    public static final String CLEAR_ABI_OVERRIDE = "-";
65bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
661378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi    /**
6773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey     * A handle to an opened package, consisting of one or more APKs. Used as
6873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey     * input to the various NativeLibraryHelper methods. Allows us to scan and
6973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey     * parse the APKs exactly once instead of doing it multiple times.
701378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     *
711378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     * @hide
721378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     */
7373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey    public static class Handle implements Closeable {
7473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        private final CloseGuard mGuard = CloseGuard.get();
7573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        private volatile boolean mClosed;
7673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey
7773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        final long[] apkHandles;
78941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey        final boolean multiArch;
79ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov        final boolean extractNativeLibs;
80d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer        final boolean debuggable;
8173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey
8273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        public static Handle create(File packageFile) throws IOException {
8373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            try {
84be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey                final PackageLite lite = PackageParser.parsePackageLite(packageFile, 0);
85be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey                return create(lite);
8673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            } catch (PackageParserException e) {
8773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                throw new IOException("Failed to parse package: " + packageFile, e);
88cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath            }
89be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey        }
90cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath
918d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey        public static Handle create(Package pkg) throws IOException {
92941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey            return create(pkg.getAllCodePaths(),
93ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov                    (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0,
94d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer                    (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0,
95d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer                    (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
968d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey        }
978d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey
98be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey        public static Handle create(PackageLite lite) throws IOException {
99d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            return create(lite.getAllCodePaths(), lite.multiArch, lite.extractNativeLibs,
100d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer                    lite.debuggable);
1018d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey        }
1028d479b0c2ddb150182bcf510876a240cb869661bJeff Sharkey
103ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov        private static Handle create(List<String> codePaths, boolean multiArch,
104d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer                boolean extractNativeLibs, boolean debuggable) throws IOException {
10573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            final int size = codePaths.size();
10673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            final long[] apkHandles = new long[size];
10773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            for (int i = 0; i < size; i++) {
10873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                final String path = codePaths.get(i);
10973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                apkHandles[i] = nativeOpenApk(path);
11073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                if (apkHandles[i] == 0) {
11173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                    // Unwind everything we've opened so far
11273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                    for (int j = 0; j < i; j++) {
11373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                        nativeClose(apkHandles[j]);
11473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                    }
11573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                    throw new IOException("Unable to open APK: " + path);
11673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                }
11773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            }
118cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath
119d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            return new Handle(apkHandles, multiArch, extractNativeLibs, debuggable);
1201378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi        }
1211378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi
1221704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn        public static Handle createFd(PackageLite lite, FileDescriptor fd) throws IOException {
1231704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            final long[] apkHandles = new long[1];
1241704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            final String path = lite.baseCodePath;
1251704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            apkHandles[0] = nativeOpenApkFd(fd, path);
1261704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            if (apkHandles[0] == 0) {
1271704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn                throw new IOException("Unable to open APK " + path + " from fd " + fd);
1281704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            }
1291704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn
1301704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn            return new Handle(apkHandles, lite.multiArch, lite.extractNativeLibs, lite.debuggable);
1311704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn        }
1321704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn
133d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer        Handle(long[] apkHandles, boolean multiArch, boolean extractNativeLibs,
134d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer                boolean debuggable) {
13573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            this.apkHandles = apkHandles;
136941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey            this.multiArch = multiArch;
137ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov            this.extractNativeLibs = extractNativeLibs;
138d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            this.debuggable = debuggable;
13973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            mGuard.open("close");
1401378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi        }
1411378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi
142cef0b39b9211882f59b6bfe1148e2cd247056693Narayan Kamath        @Override
1431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi        public void close() {
14473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            for (long apkHandle : apkHandles) {
14573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                nativeClose(apkHandle);
14673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            }
14773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            mGuard.close();
14873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            mClosed = true;
1491378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi        }
1501378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi
15173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        @Override
15273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        protected void finalize() throws Throwable {
15373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            if (mGuard != null) {
15473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                mGuard.warnIfOpen();
15573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            }
15673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            try {
15773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                if (!mClosed) {
15873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                    close();
15973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                }
16073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            } finally {
16173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                super.finalize();
16273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            }
16373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        }
16473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey    }
1651378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi
1661378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi    private static native long nativeOpenApk(String path);
1671704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn    private static native long nativeOpenApkFd(FileDescriptor fd, String debugPath);
1681378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi    private static native void nativeClose(long handle);
1691378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi
170d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer    private static native long nativeSumNativeBinaries(long handle, String cpuAbi,
171d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            boolean debuggable);
17285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root
173ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov    private native static int nativeCopyNativeBinaries(long handle, String sharedLibraryPath,
174d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            String abiToCopy, boolean extractNativeLibs, boolean hasNativeBridge,
175d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            boolean debuggable);
176bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
177bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    private static long sumNativeBinaries(Handle handle, String abi) {
17873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        long sum = 0;
17973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        for (long apkHandle : handle.apkHandles) {
180d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            sum += nativeSumNativeBinaries(apkHandle, abi, handle.debuggable);
18173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        }
18273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        return sum;
18385387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root    }
18485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root
1851ebd74acf9977daa42133507e970dab88e08f0efKenny Root    /**
1861ebd74acf9977daa42133507e970dab88e08f0efKenny Root     * Copies native binaries to a shared library directory.
1871ebd74acf9977daa42133507e970dab88e08f0efKenny Root     *
1881378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     * @param handle APK file to scan for native libraries
1891ebd74acf9977daa42133507e970dab88e08f0efKenny Root     * @param sharedLibraryDir directory for libraries to be copied to
1901ebd74acf9977daa42133507e970dab88e08f0efKenny Root     * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
1911ebd74acf9977daa42133507e970dab88e08f0efKenny Root     *         error code from that class if not
1921ebd74acf9977daa42133507e970dab88e08f0efKenny Root     */
193941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey    public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) {
19473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        for (long apkHandle : handle.apkHandles) {
195ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov            int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi,
196d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer                    handle.extractNativeLibs, HAS_NATIVE_BRIDGE, handle.debuggable);
19773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            if (res != INSTALL_SUCCEEDED) {
19873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                return res;
19973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            }
20073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        }
20173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        return INSTALL_SUCCEEDED;
20285387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root    }
2038f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root
2041378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi    /**
2051378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     * Checks if a given APK contains native code for any of the provided
2061378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     * {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching
2071378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     * ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the
2081378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     * APK doesn't contain any native code, and
2091378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     * {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match.
2101378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi     */
21173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey    public static int findSupportedAbi(Handle handle, String[] supportedAbis) {
21273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        int finalRes = NO_NATIVE_LIBRARIES;
21373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        for (long apkHandle : handle.apkHandles) {
214d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            final int res = nativeFindSupportedAbi(apkHandle, supportedAbis, handle.debuggable);
21573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            if (res == NO_NATIVE_LIBRARIES) {
21673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                // No native code, keep looking through all APKs.
21773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            } else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) {
21873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                // Found some native code, but no ABI match; update our final
21973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                // result if we haven't found other valid code.
22073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                if (finalRes < 0) {
22173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                    finalRes = INSTALL_FAILED_NO_MATCHING_ABIS;
22273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                }
22373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            } else if (res >= 0) {
22473767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                // Found valid native code, track the best ABI match
22573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                if (finalRes < 0 || res < finalRes) {
22673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                    finalRes = res;
22773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                }
22873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            } else {
22973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                // Unexpected error; bail
23073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                return res;
23173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            }
23273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        }
23373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        return finalRes;
2341378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi    }
2351378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi
236d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer    private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis,
237d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer            boolean debuggable);
2381378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi
239831baa2e2566bf1d243c06918672abd5ff786105Kenny Root    // Convenience method to call removeNativeBinariesFromDirLI(File)
240ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath    public static void removeNativeBinariesLI(String nativeLibraryPath) {
241ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath        if (nativeLibraryPath == null) return;
242ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath        removeNativeBinariesFromDirLI(new File(nativeLibraryPath), false /* delete root dir */);
243831baa2e2566bf1d243c06918672abd5ff786105Kenny Root    }
244831baa2e2566bf1d243c06918672abd5ff786105Kenny Root
245ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath    /**
246ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath     * Remove the native binaries of a given package. This deletes the files
247ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath     */
248ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov    public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot,
249ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov            boolean deleteRootDir) {
2508f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root        if (DEBUG_NATIVE) {
251ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath            Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath());
2528f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root        }
2538f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root
2548f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root        /*
2558f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root         * Just remove any file in the directory. Since the directory is owned
2568f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root         * by the 'system' UID, the application is not supposed to have written
2578f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root         * anything there.
2588f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root         */
259ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath        if (nativeLibraryRoot.exists()) {
260ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath            final File[] files = nativeLibraryRoot.listFiles();
261ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath            if (files != null) {
262ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath                for (int nn = 0; nn < files.length; nn++) {
2638f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root                    if (DEBUG_NATIVE) {
264ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath                        Slog.d(TAG, "    Deleting " + files[nn].getName());
2658f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root                    }
266831baa2e2566bf1d243c06918672abd5ff786105Kenny Root
267ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath                    if (files[nn].isDirectory()) {
268ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath                        removeNativeBinariesFromDirLI(files[nn], true /* delete root dir */);
269ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath                    } else if (!files[nn].delete()) {
270ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath                        Slog.w(TAG, "Could not delete native binary: " + files[nn].getPath());
2718f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root                    }
2728f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root                }
2738f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root            }
274ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath            // Do not delete 'lib' directory itself, unless we're specifically
275ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath            // asked to or this will prevent installation of future updates.
276ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath            if (deleteRootDir) {
277ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath                if (!nativeLibraryRoot.delete()) {
278ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov                    Slog.w(TAG, "Could not delete native binary directory: " +
279ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov                            nativeLibraryRoot.getPath());
280ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath                }
281ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath            }
2828f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root        }
2838f7cc02c7c4bd542376648dbd54be3ceb8521f73Kenny Root    }
284d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath
2851bea237aa296a35c263f0c4965ba0f5a140cd848Patrick Baumann    /**
2861bea237aa296a35c263f0c4965ba0f5a140cd848Patrick Baumann     * @hide
2871bea237aa296a35c263f0c4965ba0f5a140cd848Patrick Baumann     */
2881bea237aa296a35c263f0c4965ba0f5a140cd848Patrick Baumann    public static void createNativeLibrarySubdir(File path) throws IOException {
289bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        if (!path.isDirectory()) {
290bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            path.delete();
291bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
292bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            if (!path.mkdir()) {
293bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                throw new IOException("Cannot create " + path.getPath());
294bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
295bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
296bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            try {
297bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
298bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            } catch (ErrnoException e) {
299bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                throw new IOException("Cannot chmod native library directory "
300bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                        + path.getPath(), e);
301bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
302bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        } else if (!SELinux.restorecon(path)) {
303bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            throw new IOException("Cannot set SELinux context for " + path.getPath());
304bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        }
305bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    }
306bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
307941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey    private static long sumNativeBinariesForSupportedAbi(Handle handle, String[] abiList) {
308bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        int abi = findSupportedAbi(handle, abiList);
309bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        if (abi >= 0) {
310bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            return sumNativeBinaries(handle, abiList[abi]);
311bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        } else {
312bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            return 0;
313bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        }
314bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    }
315bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
316941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey    public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot,
317bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            String[] abiList, boolean useIsaSubdir) throws IOException {
318bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        createNativeLibrarySubdir(libraryRoot);
319bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
320bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        /*
321bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey         * If this is an internal application or our nativeLibraryPath points to
322bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey         * the app-lib directory, unpack the libraries if necessary.
323bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey         */
324bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        int abi = findSupportedAbi(handle, abiList);
325bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        if (abi >= 0) {
326bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            /*
327bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey             * If we have a matching instruction set, construct a subdir under the native
328bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey             * library root that corresponds to this instruction set.
329bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey             */
330bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
331bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            final File subDir;
332bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            if (useIsaSubdir) {
333bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                final File isaSubdir = new File(libraryRoot, instructionSet);
334bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                createNativeLibrarySubdir(isaSubdir);
335bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                subDir = isaSubdir;
336bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            } else {
337bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                subDir = libraryRoot;
338bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
339bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
340941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey            int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]);
341bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
342bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                return copyRet;
343bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
344bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        }
345bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
346bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        return abi;
347bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    }
348bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
349941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey    public static int copyNativeBinariesWithOverride(Handle handle, File libraryRoot,
350941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey            String abiOverride) {
351bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        try {
352941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey            if (handle.multiArch) {
353bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                // Warn if we've set an abiOverride for multi-lib packages..
354bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                // By definition, we need to copy both 32 and 64 bit libraries for
355bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                // such packages.
356bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
357bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
358bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                }
359bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
360bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
361bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
362941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey                    copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot,
363bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                            Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
364bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
365bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                            copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
366bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                        Slog.w(TAG, "Failure copying 32 bit native libraries; copyRet=" +copyRet);
367bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                        return copyRet;
368bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    }
369bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                }
370bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
371bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
372941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey                    copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot,
373bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                            Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
374bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
375bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                            copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
376bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                        Slog.w(TAG, "Failure copying 64 bit native libraries; copyRet=" +copyRet);
377bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                        return copyRet;
378bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    }
379bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                }
380bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            } else {
381bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                String cpuAbiOverride = null;
382bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
383bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    cpuAbiOverride = null;
384bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                } else if (abiOverride != null) {
385bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    cpuAbiOverride = abiOverride;
386bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                }
387bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
388bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                String[] abiList = (cpuAbiOverride != null) ?
389bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                        new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
390bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
391bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                        hasRenderscriptBitcode(handle)) {
392bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    abiList = Build.SUPPORTED_32_BIT_ABIS;
393bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                }
394bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
395941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey                int copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, abiList,
396bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                        true /* use isa specific subdirs */);
397bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
398bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
399bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    return copyRet;
400bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                }
401bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
402bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
403bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            return PackageManager.INSTALL_SUCCEEDED;
404bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        } catch (IOException e) {
405bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            Slog.e(TAG, "Copying native libraries failed", e);
406bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
407bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        }
408bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    }
409bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
410941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey    public static long sumNativeBinariesWithOverride(Handle handle, String abiOverride)
411bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            throws IOException {
412bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        long sum = 0;
413941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey        if (handle.multiArch) {
414bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            // Warn if we've set an abiOverride for multi-lib packages..
415bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            // By definition, we need to copy both 32 and 64 bit libraries for
416bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            // such packages.
417bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
418bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
419bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
420bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
421bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
422941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey                sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
423bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
424bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
425bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
426941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey                sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
427bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
428bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        } else {
429bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            String cpuAbiOverride = null;
430bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
431bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                cpuAbiOverride = null;
432bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            } else if (abiOverride != null) {
433bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                cpuAbiOverride = abiOverride;
434bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
435bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
436bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            String[] abiList = (cpuAbiOverride != null) ?
437bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
438bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
439bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                    hasRenderscriptBitcode(handle)) {
440bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey                abiList = Build.SUPPORTED_32_BIT_ABIS;
441bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey            }
442bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
443941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey            sum += sumNativeBinariesForSupportedAbi(handle, abiList);
444bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        }
445bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey        return sum;
446bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    }
447bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
448d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath    // We don't care about the other return values for now.
449d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath    private static final int BITCODE_PRESENT = 1;
450d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath
451ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov    private static final boolean HAS_NATIVE_BRIDGE =
452ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov            !"0".equals(SystemProperties.get("ro.dalvik.vm.native.bridge", "0"));
453ff193d642eea7128faad837d19e347cd25212c27Dmitriy Ivanov
454bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey    private static native int hasRenderscriptBitcode(long apkHandle);
455bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey
45673767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey    public static boolean hasRenderscriptBitcode(Handle handle) throws IOException {
45773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        for (long apkHandle : handle.apkHandles) {
45873767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            final int res = hasRenderscriptBitcode(apkHandle);
45973767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            if (res < 0) {
46073767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                throw new IOException("Error scanning APK, code: " + res);
46173767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            } else if (res == BITCODE_PRESENT) {
46273767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey                return true;
46373767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey            }
464d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath        }
46573767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey        return false;
466d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath    }
46785387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root}
468