WebViewFactory.java revision 3822882b32d9b1b803aaff9b657a91d680f1d0f9
1d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon/*
2d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Copyright (C) 2012 The Android Open Source Project
3d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon *
4d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Licensed under the Apache License, Version 2.0 (the "License");
5d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * you may not use this file except in compliance with the License.
6d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * You may obtain a copy of the License at
7d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon *
8d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon *      http://www.apache.org/licenses/LICENSE-2.0
9d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon *
10d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Unless required by applicable law or agreed to in writing, software
11d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * distributed under the License is distributed on an "AS IS" BASIS,
12d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * See the License for the specific language governing permissions and
14d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * limitations under the License.
15d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon */
16d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
17d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixonpackage android.webkit;
18d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
19810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucciimport android.app.ActivityManagerInternal;
2063d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosibaimport android.app.Application;
216c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.app.AppGlobals;
226c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.content.Context;
231b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport android.content.pm.ApplicationInfo;
240606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)import android.content.pm.PackageInfo;
256c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.content.pm.PackageManager;
2608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Build;
2708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Process;
2808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.RemoteException;
2908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.ServiceManager;
30e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdochimport android.os.StrictMode;
315ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdochimport android.os.SystemProperties;
323822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)import android.os.Trace;
331b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport android.text.TextUtils;
3403ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)import android.util.AndroidRuntimeException;
35d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixonimport android.util.Log;
36810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucciimport com.android.server.LocalServices;
3708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import dalvik.system.VMRuntime;
3808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
3908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import java.io.File;
401b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport java.util.Arrays;
4108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
4208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import com.android.internal.os.Zygote;
43d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
44d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon/**
45d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Top level factory, used creating all the main WebView implementation classes.
46b0e35846b818bdf0db9cafe881a8a535116d596eJared Duke *
47b0e35846b818bdf0db9cafe881a8a535116d596eJared Duke * @hide
48d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon */
49b0e35846b818bdf0db9cafe881a8a535116d596eJared Dukepublic final class WebViewFactory {
50a7eaa8ee222611c28f050158db4b68c4d893a8a9Jonathan Dixon
51e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch    private static final String CHROMIUM_WEBVIEW_FACTORY =
52a9bbd9439c3043bd76a7474e6dca3c8131b1b258Torne (Richard Coles)            "com.android.webview.chromium.WebViewChromiumFactoryProvider";
53d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
540e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch    private static final String NULL_WEBVIEW_FACTORY =
550e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch            "com.android.webview.nullwebview.NullWebViewFactoryProvider";
560e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch
5708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 =
5808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            "/data/misc/shared_relro/libwebviewchromium32.relro";
5908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
6008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            "/data/misc/shared_relro/libwebviewchromium64.relro";
6108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
625ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch    public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY =
635ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            "persist.sys.webview.vmsize";
645ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch    private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024;
651b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci
66d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    private static final String LOGTAG = "WebViewFactory";
67d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
68d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    private static final boolean DEBUG = false;
69d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
70d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
71d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    // same provider.
72d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    private static WebViewFactoryProvider sProviderInstance;
739f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck    private static final Object sProviderLock = new Object();
7408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static boolean sAddressSpaceReserved = false;
75d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
76dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch    public static String getWebViewPackageName() {
775651fc2feeed3af1bd0991e32788a8936d698811Torne (Richard Coles)        return AppGlobals.getInitialApplication().getString(
785651fc2feeed3af1bd0991e32788a8936d698811Torne (Richard Coles)                com.android.internal.R.string.config_webViewPackageName);
79dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch    }
80dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch
819f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck    static WebViewFactoryProvider getProvider() {
829f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck        synchronized (sProviderLock) {
839f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck            // For now the main purpose of this function (and the factory abstraction) is to keep
84d892afc88d3c67a7fe1c9550bfa7a452051d031dTorne (Richard Coles)            // us honest and minimize usage of WebView internals when binding the proxy.
859f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck            if (sProviderInstance != null) return sProviderInstance;
86d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
873822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
8803ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            try {
893822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
903822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                loadNativeLibrary();
913822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
923822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)
933822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                Class<WebViewFactoryProvider> providerClass;
943822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getFactoryClass()");
953822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                try {
963822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    providerClass = getFactoryClass();
973822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                } catch (ClassNotFoundException e) {
983822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    Log.e(LOGTAG, "error loading provider", e);
993822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    throw new AndroidRuntimeException(e);
1003822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                } finally {
1013822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
1023822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                }
1033822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)
1043822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
1053822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
1063822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                try {
1073822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    sProviderInstance = providerClass.newInstance();
1083822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
1093822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    return sProviderInstance;
1103822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                } catch (Exception e) {
1113822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    Log.e(LOGTAG, "error instantiating provider", e);
1123822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    throw new AndroidRuntimeException(e);
1133822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                } finally {
1143822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
1153822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                    StrictMode.setThreadPolicy(oldPolicy);
1163822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                }
11703ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            } finally {
1183822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
119e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch            }
120d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon        }
121d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    }
122d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
12303ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)    private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
12463d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba        Application initialApplication = AppGlobals.getInitialApplication();
1250e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch        try {
1260606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)            // First fetch the package info so we can log the webview package version.
1270606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)            String packageName = getWebViewPackageName();
1280606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)            PackageInfo pi = initialApplication.getPackageManager().getPackageInfo(packageName, 0);
1290606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)            Log.i(LOGTAG, "Loading " + packageName + " version " + pi.versionName +
1300606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)                          " (code " + pi.versionCode + ")");
1310606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)
1320606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)            // Construct a package context to load the Java code into the current app.
1330606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)            Context webViewContext = initialApplication.createPackageContext(packageName,
1346c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)                    Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
13563d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba            initialApplication.getAssets().addAssetPath(
13663d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba                    webViewContext.getApplicationInfo().sourceDir);
1376c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)            ClassLoader clazzLoader = webViewContext.getClassLoader();
1383822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
1393822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)            try {
1403822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true,
1413822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                                                                     clazzLoader);
1423822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)            } finally {
1433822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
1443822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)            }
1456c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)        } catch (PackageManager.NameNotFoundException e) {
1465f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            // If the package doesn't exist, then try loading the null WebView instead.
1475f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            // If that succeeds, then this is a device without WebView support; if it fails then
1485f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            // swallow the failure, complain that the real WebView is missing and rethrow the
1495f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            // original exception.
1505f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            try {
1515f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)                return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
1525f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            } catch (ClassNotFoundException e2) {
1535f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)                // Ignore.
1545f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            }
1555f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            Log.e(LOGTAG, "Chromium WebView package does not exist", e);
1565f3278ba1e7572d4a5624d18fd08ba9038abc575Torne (Richard Coles)            throw new AndroidRuntimeException(e);
1570e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch        }
158d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    }
15908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
16008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    /**
16108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * Perform any WebView loading preparations that must happen in the zygote.
16208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * Currently, this means allocating address space to load the real JNI library later.
16308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     */
16408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    public static void prepareWebViewInZygote() {
16508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        try {
16608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            System.loadLibrary("webviewchromium_loader");
1675ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            long addressSpaceToReserve =
1685ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                    SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
1695ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                    CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
1705ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
1715ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch
17208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            if (sAddressSpaceReserved) {
1735ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                if (DEBUG) {
1745ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                    Log.v(LOGTAG, "address space reserved: " + addressSpaceToReserve + " bytes");
1755ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                }
17608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            } else {
1775ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                Log.e(LOGTAG, "reserving " + addressSpaceToReserve +
1785ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                        " bytes of address space failed");
17908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            }
180810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci        } catch (Throwable t) {
18108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            // Log and discard errors at this stage as we must not crash the zygote.
182810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci            Log.e(LOGTAG, "error preparing native loader", t);
18308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
18408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
18508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
18608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    /**
18708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * Perform any WebView loading preparations that must happen at boot from the system server,
1885ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch     * after the package manager has started or after an update to the webview is installed.
18908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * This must be called in the system server.
19008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * Currently, this means spawning the child processes which will create the relro files.
19108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     */
19208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    public static void prepareWebViewInSystemServer() {
1935ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        String[] nativePaths = null;
1945ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        try {
1955ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            nativePaths = getWebViewNativeLibraryPaths();
19627cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)        } catch (Throwable t) {
19727cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)            // Log and discard errors at this stage as we must not crash the system server.
19827cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)            Log.e(LOGTAG, "error preparing webview native library", t);
1995ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        }
2005ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        prepareWebViewInSystemServer(nativePaths);
2015ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch    }
2025ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch
2035ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch    private static void prepareWebViewInSystemServer(String[] nativeLibraryPaths) {
20408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        if (DEBUG) Log.v(LOGTAG, "creating relro files");
2055ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch
2065ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        // We must always trigger createRelRo regardless of the value of nativeLibraryPaths. Any
2075ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        // unexpected values will be handled there to ensure that we trigger notifying any process
2085ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        // waiting on relreo creation.
2095ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
2105ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
2115ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            createRelroFile(false /* is64Bit */, nativeLibraryPaths);
2125ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        }
2135ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch
2145ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
2155ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
2165ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            createRelroFile(true /* is64Bit */, nativeLibraryPaths);
2175ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        }
2185ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch    }
2195ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch
2205ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch    public static void onWebViewUpdateInstalled() {
2215ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        String[] nativeLibs = null;
2225ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        try {
2235ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths();
22427cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)            if (nativeLibs != null) {
22527cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                long newVmSize = 0L;
22627cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)
22727cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                for (String path : nativeLibs) {
22827cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                    if (DEBUG) Log.d(LOGTAG, "Checking file size of " + path);
22927cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                    if (path == null) continue;
23027cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                    File f = new File(path);
23127cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                    if (f.exists()) {
23227cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                        long length = f.length();
23327cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                        if (length > newVmSize) {
23427cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                            newVmSize = length;
23527cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                        }
2365ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                    }
2375ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                }
2385ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch
23927cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                if (DEBUG) {
24027cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                    Log.v(LOGTAG, "Based on library size, need " + newVmSize +
24127cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                            " bytes of address space.");
24227cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                }
24327cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                // The required memory can be larger than the file on disk (due to .bss), and an
24427cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                // upgraded version of the library will likely be larger, so always attempt to
24527cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                // reserve twice as much as we think to allow for the library to grow during this
24627cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                // boot cycle.
24727cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                newVmSize = Math.max(2 * newVmSize, CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
24827cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                Log.d(LOGTAG, "Setting new address space to " + newVmSize);
24927cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                SystemProperties.set(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
25027cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)                        Long.toString(newVmSize));
2515ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            }
25227cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)        } catch (Throwable t) {
25327cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)            // Log and discard errors at this stage as we must not crash the system server.
25427cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles)            Log.e(LOGTAG, "error preparing webview native library", t);
25508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
2565ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        prepareWebViewInSystemServer(nativeLibs);
25708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
25808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
2591b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci    private static String[] getWebViewNativeLibraryPaths()
2601b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            throws PackageManager.NameNotFoundException {
2611b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        final String NATIVE_LIB_FILE_NAME = "libwebviewchromium.so";
2621b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci
2631b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
2641b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        ApplicationInfo ai = pm.getApplicationInfo(getWebViewPackageName(), 0);
2651b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci
2661b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        String path32;
2671b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        String path64;
2681b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        boolean primaryArchIs64bit = VMRuntime.is64BitAbi(ai.primaryCpuAbi);
2691b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) {
2701b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            // Multi-arch case.
2711b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            if (primaryArchIs64bit) {
2721b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                // Primary arch: 64-bit, secondary: 32-bit.
2731b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                path64 = ai.nativeLibraryDir;
2741b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                path32 = ai.secondaryNativeLibraryDir;
2751b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            } else {
2761b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                // Primary arch: 32-bit, secondary: 64-bit.
2771b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                path64 = ai.secondaryNativeLibraryDir;
2781b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                path32 = ai.nativeLibraryDir;
2791b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            }
2801b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        } else if (primaryArchIs64bit) {
2811b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            // Single-arch 64-bit.
2821b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            path64 = ai.nativeLibraryDir;
2831b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            path32 = "";
2841b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        } else {
2851b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            // Single-arch 32-bit.
2861b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            path32 = ai.nativeLibraryDir;
2871b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            path64 = "";
2881b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        }
2891b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        if (!TextUtils.isEmpty(path32)) path32 += "/" + NATIVE_LIB_FILE_NAME;
2901b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        if (!TextUtils.isEmpty(path64)) path64 += "/" + NATIVE_LIB_FILE_NAME;
2911b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        return new String[] { path32, path64 };
2921b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci    }
2931b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci
2945ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch    private static void createRelroFile(final boolean is64Bit, String[] nativeLibraryPaths) {
2951b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        final String abi =
2961b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
297810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci
298810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci        // crashHandler is invoked by the ActivityManagerService when the isolated process crashes.
299810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci        Runnable crashHandler = new Runnable() {
300810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci            @Override
301810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci            public void run() {
302810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci                try {
3031b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                    Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without");
304810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci                    getUpdateService().notifyRelroCreationCompleted(is64Bit, false);
305810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci                } catch (RemoteException e) {
306810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci                    Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage());
307810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci                }
308810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci            }
309810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci        };
310810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci
31108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        try {
3125ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            if (nativeLibraryPaths == null
3135ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                    || nativeLibraryPaths[0] == null || nativeLibraryPaths[1] == null) {
3145ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                throw new IllegalArgumentException(
3155ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                        "Native library paths to the WebView RelRo process must not be null!");
3165ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch            }
317161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci            int pid = LocalServices.getService(ActivityManagerInternal.class).startIsolatedProcess(
3185ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch                    RelroFileCreator.class.getName(), nativeLibraryPaths, "WebViewLoader-" + abi, abi,
319810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci                    Process.SHARED_RELRO_UID, crashHandler);
320e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            if (pid <= 0) throw new Exception("Failed to start the relro file creator process");
321810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci        } catch (Throwable t) {
32208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            // Log and discard errors as we must not crash the system server.
323810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci            Log.e(LOGTAG, "error starting relro file creator for abi " + abi, t);
324810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci            crashHandler.run();
32508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
32608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
32708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
32808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static class RelroFileCreator {
32908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        // Called in an unprivileged child process to create the relro file.
33008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        public static void main(String[] args) {
331161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci            boolean result = false;
332161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci            boolean is64Bit = VMRuntime.getRuntime().is64Bit();
3331b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            try{
3341b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                if (args.length != 2 || args[0] == null || args[1] == null) {
3351b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                    Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args));
3361b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                    return;
3371b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                }
3381b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), " +
3391b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                        " 32-bit lib: " + args[0] + ", 64-bit lib: " + args[1]);
3401b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                if (!sAddressSpaceReserved) {
3411b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                    Log.e(LOGTAG, "can't create relro file; address space not reserved");
3421b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                    return;
3431b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                }
344161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci                result = nativeCreateRelroFile(args[0] /* path32 */,
345161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci                                               args[1] /* path64 */,
346161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci                                               CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
347161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci                                               CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
348e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                if (result && DEBUG) Log.v(LOGTAG, "created relro file");
349161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci            } finally {
350161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci                // We must do our best to always notify the update service, even if something fails.
3511b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                try {
3521b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                    getUpdateService().notifyRelroCreationCompleted(is64Bit, result);
3531b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                } catch (RemoteException e) {
3541b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                    Log.e(LOGTAG, "error notifying update service", e);
3551b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                }
356161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci
357161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci                if (!result) Log.e(LOGTAG, "failed to create relro file");
358161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci
3591b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                // Must explicitly exit or else this process will just sit around after we return.
3601b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                System.exit(0);
3611b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            }
36208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
36308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
36408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
36508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static void loadNativeLibrary() {
36608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        if (!sAddressSpaceReserved) {
36708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Log.e(LOGTAG, "can't load with relro file; address space not reserved");
36808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            return;
36908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
37008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
37108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        try {
37208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            getUpdateService().waitForRelroCreationCompleted(VMRuntime.getRuntime().is64Bit());
37308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        } catch (RemoteException e) {
37408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Log.e(LOGTAG, "error waiting for relro creation, proceeding without", e);
37508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            return;
37608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
37708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
3781b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        try {
3791b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            String[] args = getWebViewNativeLibraryPaths();
3801b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            boolean result = nativeLoadWithRelroFile(args[0] /* path32 */,
3811b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                                                     args[1] /* path64 */,
3821b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                                                     CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
3831b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                                                     CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
3841b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            if (!result) {
3851b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                Log.w(LOGTAG, "failed to load with relro file, proceeding without");
3861b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            } else if (DEBUG) {
3871b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci                Log.v(LOGTAG, "loaded with relro file");
3881b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            }
3891b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci        } catch (PackageManager.NameNotFoundException e) {
3901b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci            Log.e(LOGTAG, "Failed to list WebView package libraries for loadNativeLibrary", e);
39108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
39208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
39308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
39408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static IWebViewUpdateService getUpdateService() {
39508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
39608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
39708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
3985ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch    private static native boolean nativeReserveAddressSpace(long addressSpaceToReserve);
39908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static native boolean nativeCreateRelroFile(String lib32, String lib64,
40008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                        String relro32, String relro64);
40108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static native boolean nativeLoadWithRelroFile(String lib32, String lib64,
40208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                          String relro32, String relro64);
403d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon}
404