WebViewFactory.java revision 6c778cebc73e7eb76510f6e2183d804b8c07082b
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
196c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.app.AppGlobals;
206c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.content.Context;
216c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.content.pm.PackageManager;
2208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Build;
2308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Process;
2408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.RemoteException;
2508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.ServiceManager;
26e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdochimport android.os.StrictMode;
2703ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)import android.util.AndroidRuntimeException;
28d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixonimport android.util.Log;
2908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import dalvik.system.VMRuntime;
3008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
3108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import java.io.File;
3208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
3308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import com.android.internal.os.Zygote;
34d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
35d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon/**
36d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Top level factory, used creating all the main WebView implementation classes.
37b0e35846b818bdf0db9cafe881a8a535116d596eJared Duke *
38b0e35846b818bdf0db9cafe881a8a535116d596eJared Duke * @hide
39d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon */
40b0e35846b818bdf0db9cafe881a8a535116d596eJared Dukepublic final class WebViewFactory {
41a7eaa8ee222611c28f050158db4b68c4d893a8a9Jonathan Dixon
42e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch    private static final String CHROMIUM_WEBVIEW_FACTORY =
43a9bbd9439c3043bd76a7474e6dca3c8131b1b258Torne (Richard Coles)            "com.android.webview.chromium.WebViewChromiumFactoryProvider";
44d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
450e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch    private static final String NULL_WEBVIEW_FACTORY =
460e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch            "com.android.webview.nullwebview.NullWebViewFactoryProvider";
470e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch
4808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    // TODO(torne): we need to use a system property instead of hardcoding the library paths to
4908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    // enable it to be changed when a webview update apk is installed.
5008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static final String CHROMIUM_WEBVIEW_NATIVE_LIB_32 =
5108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            "/system/lib/libwebviewchromium.so";
5208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static final String CHROMIUM_WEBVIEW_NATIVE_LIB_64 =
5308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            "/system/lib64/libwebviewchromium.so";
5408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 =
5508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            "/data/misc/shared_relro/libwebviewchromium32.relro";
5608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
5708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            "/data/misc/shared_relro/libwebviewchromium64.relro";
5808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
59d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    private static final String LOGTAG = "WebViewFactory";
60d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
61d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    private static final boolean DEBUG = false;
62d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
63d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
64d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    // same provider.
65d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    private static WebViewFactoryProvider sProviderInstance;
669f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck    private static final Object sProviderLock = new Object();
6708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static boolean sAddressSpaceReserved = false;
68d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
69dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch    public static String getWebViewPackageName() {
70dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch        // TODO: Make this dynamic based on resource configuration.
71dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch        return "com.android.webview";
72dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch    }
73dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch
749f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck    static WebViewFactoryProvider getProvider() {
759f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck        synchronized (sProviderLock) {
769f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck            // For now the main purpose of this function (and the factory abstraction) is to keep
77d892afc88d3c67a7fe1c9550bfa7a452051d031dTorne (Richard Coles)            // us honest and minimize usage of WebView internals when binding the proxy.
789f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck            if (sProviderInstance != null) return sProviderInstance;
79d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
8008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            loadNativeLibrary();
8108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
8203ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            Class<WebViewFactoryProvider> providerClass;
8303ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            try {
8403ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                providerClass = getFactoryClass();
8503ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            } catch (ClassNotFoundException e) {
8603ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                Log.e(LOGTAG, "error loading provider", e);
8703ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                throw new AndroidRuntimeException(e);
88e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch            }
89e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch
9003ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
9103ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            try {
9203ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                sProviderInstance = providerClass.newInstance();
9303ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
9403ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                return sProviderInstance;
9503ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            } catch (Exception e) {
9603ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                Log.e(LOGTAG, "error instantiating provider", e);
9703ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                throw new AndroidRuntimeException(e);
9803ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)            } finally {
9903ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)                StrictMode.setThreadPolicy(oldPolicy);
100e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch            }
101d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon        }
102d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    }
103d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon
10403ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)    private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
1050e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch        try {
1066c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)            Context webViewContext = AppGlobals.getInitialApplication().createPackageContext(
1076c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)                    getWebViewPackageName(),
1086c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)                    Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
1096c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)            ClassLoader clazzLoader = webViewContext.getClassLoader();
1106c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)            return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true,
1116c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)                                                                 clazzLoader);
1126c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)        } catch (PackageManager.NameNotFoundException e) {
1136c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)            Log.e(LOGTAG, "Chromium WebView package does not exist");
1140e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch            return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
1150e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch        }
116d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon    }
11708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
11808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    /**
11908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * Perform any WebView loading preparations that must happen in the zygote.
12008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * Currently, this means allocating address space to load the real JNI library later.
12108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     */
12208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    public static void prepareWebViewInZygote() {
12308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        try {
12408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            System.loadLibrary("webviewchromium_loader");
12508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            sAddressSpaceReserved = nativeReserveAddressSpace(CHROMIUM_WEBVIEW_NATIVE_LIB_32,
12608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                              CHROMIUM_WEBVIEW_NATIVE_LIB_64);
12708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            if (sAddressSpaceReserved) {
12808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                if (DEBUG) Log.v(LOGTAG, "address space reserved");
12908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            } else {
13008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                Log.e(LOGTAG, "reserving address space failed");
13108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            }
13208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        } catch (Throwable e) {
13308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            // Log and discard errors at this stage as we must not crash the zygote.
13408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Log.e(LOGTAG, "error preparing native loader", e);
13508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
13608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
13708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
13808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    /**
13908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * Perform any WebView loading preparations that must happen at boot from the system server,
14008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * after the package manager has started.
14108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * This must be called in the system server.
14208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     * Currently, this means spawning the child processes which will create the relro files.
14308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)     */
14408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    public static void prepareWebViewInSystemServer() {
14508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        if (DEBUG) Log.v(LOGTAG, "creating relro files");
14608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        if (new File(CHROMIUM_WEBVIEW_NATIVE_LIB_64).exists()) {
14708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            createRelroFile(Build.SUPPORTED_64_BIT_ABIS[0]);
14808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
14908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        if (new File(CHROMIUM_WEBVIEW_NATIVE_LIB_32).exists()) {
15008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            createRelroFile(Build.SUPPORTED_32_BIT_ABIS[0]);
15108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
15208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
15308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
15408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static void createRelroFile(String abi) {
15508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        try {
15608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Process.start("android.webkit.WebViewFactory$RelroFileCreator",
15708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          "WebViewLoader-" + abi,
15808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          Process.SHARED_RELRO_UID,
15908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          Process.SHARED_RELRO_UID,
16008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          null,
16108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          0,                 // TODO(torne): do we need to set debug flags?
16208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          Zygote.MOUNT_EXTERNAL_NONE,
16308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          Build.VERSION.SDK_INT,
16408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          null,
16508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          abi,
16608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                          null);
16708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        } catch (Throwable e) {
16808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            // Log and discard errors as we must not crash the system server.
16908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Log.e(LOGTAG, "error starting relro file creator for abi " + abi, e);
17008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
17108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
17208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
17308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static class RelroFileCreator {
17408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        // Called in an unprivileged child process to create the relro file.
17508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        public static void main(String[] args) {
17608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            if (!sAddressSpaceReserved) {
17708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                Log.e(LOGTAG, "can't create relro file; address space not reserved");
17808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                return;
17908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            }
18008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            boolean result = nativeCreateRelroFile(CHROMIUM_WEBVIEW_NATIVE_LIB_32,
18108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                   CHROMIUM_WEBVIEW_NATIVE_LIB_64,
18208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                   CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
18308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                   CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
18408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            if (!result) {
18508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                Log.e(LOGTAG, "failed to create relro file");
18608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            } else if (DEBUG) {
18708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                Log.v(LOGTAG, "created relro file");
18808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            }
18908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            try {
19008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                getUpdateService().notifyRelroCreationCompleted(VMRuntime.getRuntime().is64Bit(),
19108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                                result);
19208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            } catch (RemoteException e) {
19308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                Log.e(LOGTAG, "error notifying update service", e);
19408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            }
19508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
19608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            // Must explicitly exit or else this process will just sit around after we return.
19708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            System.exit(0);
19808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
19908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
20008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
20108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static void loadNativeLibrary() {
20208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        if (!sAddressSpaceReserved) {
20308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Log.e(LOGTAG, "can't load with relro file; address space not reserved");
20408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            return;
20508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
20608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
20708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        try {
20808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            getUpdateService().waitForRelroCreationCompleted(VMRuntime.getRuntime().is64Bit());
20908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        } catch (RemoteException e) {
21008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Log.e(LOGTAG, "error waiting for relro creation, proceeding without", e);
21108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            return;
21208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
21308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
21408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        boolean result = nativeLoadWithRelroFile(CHROMIUM_WEBVIEW_NATIVE_LIB_32,
21508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                 CHROMIUM_WEBVIEW_NATIVE_LIB_64,
21608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                 CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
21708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                 CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
21808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        if (!result) {
21908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Log.w(LOGTAG, "failed to load with relro file, proceeding without");
22008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        } else if (DEBUG) {
22108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            Log.v(LOGTAG, "loaded with relro file");
22208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
22308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
22408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
22508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static IWebViewUpdateService getUpdateService() {
22608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
22708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
22808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
22908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static native boolean nativeReserveAddressSpace(String lib32, String lib64);
23008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static native boolean nativeCreateRelroFile(String lib32, String lib64,
23108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                        String relro32, String relro64);
23208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static native boolean nativeLoadWithRelroFile(String lib32, String lib64,
23308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                                                          String relro32, String relro64);
234d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon}
235