blob: 1b6b3923d1308147ca559f0329b932efe6963e8c [file] [log] [blame]
Jonathan Dixond3101b12012-04-12 20:51:51 +01001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
Ignacio Solla451e3382014-11-10 10:35:54 +000019import android.annotation.SystemApi;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080020import android.app.ActivityManager;
Primiano Tucci810c0522014-07-25 18:03:16 +010021import android.app.ActivityManagerInternal;
Torne (Richard Coles)6c778ce2014-07-17 14:14:48 -070022import android.app.AppGlobals;
Jeff Sharkey85844912014-11-13 16:20:38 -080023import android.app.Application;
Torne (Richard Coles)6c778ce2014-07-17 14:14:48 -070024import android.content.Context;
Primiano Tucci1b7977b2014-07-25 19:19:32 +010025import android.content.pm.ApplicationInfo;
Torne (Richard Coles)0606cd52014-08-05 16:12:09 +010026import android.content.pm.PackageInfo;
Torne (Richard Coles)6c778ce2014-07-17 14:14:48 -070027import android.content.pm.PackageManager;
Gustav Senntoncd8f2732016-04-14 09:58:36 +010028import android.content.pm.Signature;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010029import android.os.Build;
30import android.os.Process;
31import android.os.RemoteException;
32import android.os.ServiceManager;
Ben Murdoche09e9762012-07-19 14:48:13 +010033import android.os.StrictMode;
Ben Murdoch5ced5022014-07-28 15:57:00 +010034import android.os.SystemProperties;
Torne (Richard Coles)38228822014-08-13 17:11:45 +010035import android.os.Trace;
Primiano Tucci1b7977b2014-07-25 19:19:32 +010036import android.text.TextUtils;
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +010037import android.util.AndroidRuntimeException;
Gustav Senntoncd8f2732016-04-14 09:58:36 +010038import android.util.ArraySet;
Jonathan Dixond3101b12012-04-12 20:51:51 +010039import android.util.Log;
Jeff Sharkey85844912014-11-13 16:20:38 -080040
Primiano Tucci810c0522014-07-25 18:03:16 +010041import com.android.server.LocalServices;
Jeff Sharkey85844912014-11-13 16:20:38 -080042
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010043import dalvik.system.VMRuntime;
44
Bo Liu48273852016-08-16 19:03:44 -070045import java.lang.reflect.Method;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010046import java.io.File;
Simon Baldwinb98082dc2015-05-15 12:56:50 +010047import java.io.IOException;
Primiano Tucci1b7977b2014-07-25 19:19:32 +010048import java.util.Arrays;
Simon Baldwinb98082dc2015-05-15 12:56:50 +010049import java.util.zip.ZipEntry;
50import java.util.zip.ZipFile;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010051
Jonathan Dixond3101b12012-04-12 20:51:51 +010052/**
53 * Top level factory, used creating all the main WebView implementation classes.
Jared Dukeb0e35842013-03-19 16:25:39 -070054 *
55 * @hide
Jonathan Dixond3101b12012-04-12 20:51:51 +010056 */
Ignacio Solla451e3382014-11-10 10:35:54 +000057@SystemApi
Jared Dukeb0e35842013-03-19 16:25:39 -070058public final class WebViewFactory {
Jonathan Dixona7eaa8e2013-07-25 19:52:47 -070059
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +010060 // visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote.
61 /** @hide */
Tao Bai755eded2017-01-09 18:35:44 -080062 private static final String CHROMIUM_WEBVIEW_FACTORY =
63 "com.android.webview.chromium.WebViewChromiumFactoryProviderForO";
Jonathan Dixond3101b12012-04-12 20:51:51 +010064
Bo Liu48273852016-08-16 19:03:44 -070065 private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create";
66
Ben Murdoch0e04bcf2014-05-16 13:41:12 +010067 private static final String NULL_WEBVIEW_FACTORY =
68 "com.android.webview.nullwebview.NullWebViewFactoryProvider";
69
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010070 private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 =
71 "/data/misc/shared_relro/libwebviewchromium32.relro";
72 private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
73 "/data/misc/shared_relro/libwebviewchromium64.relro";
74
Ben Murdoch5ced5022014-07-28 15:57:00 +010075 public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY =
76 "persist.sys.webview.vmsize";
77 private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024;
Primiano Tucci1b7977b2014-07-25 19:19:32 +010078
Jonathan Dixond3101b12012-04-12 20:51:51 +010079 private static final String LOGTAG = "WebViewFactory";
80
81 private static final boolean DEBUG = false;
82
83 // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
84 // same provider.
85 private static WebViewFactoryProvider sProviderInstance;
John Reck9f9d3452012-09-20 13:18:59 -070086 private static final Object sProviderLock = new Object();
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010087 private static boolean sAddressSpaceReserved = false;
Torne (Richard Coles)84392d72014-08-14 16:43:18 +010088 private static PackageInfo sPackageInfo;
Jonathan Dixond3101b12012-04-12 20:51:51 +010089
Gustav Sennton85edb6c2015-04-15 11:54:20 +010090 // Error codes for loadWebViewNativeLibraryFromPackage
91 public static final int LIBLOAD_SUCCESS = 0;
92 public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1;
93 public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000094
95 // error codes for waiting for WebView preparation
Gustav Sennton85edb6c2015-04-15 11:54:20 +010096 public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3;
97 public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4;
98
99 // native relro loading error codes
100 public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5;
101 public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6;
102 public static final int LIBLOAD_FAILED_JNI_CALL = 7;
103
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000104 // more error codes for waiting for WebView preparation
Gustav Sennton26c82ff2016-03-11 13:06:40 +0000105 public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 8;
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000106
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000107 // error for namespace lookup
108 public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10;
109
Gustav Senntonb715d402017-05-12 14:22:58 +0100110
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000111 private static String getWebViewPreparationErrorReason(int error) {
112 switch (error) {
113 case LIBLOAD_FAILED_WAITING_FOR_RELRO:
114 return "Time out waiting for Relro files being created";
115 case LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES:
116 return "No WebView installed";
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000117 case LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN:
118 return "Crashed for unknown reason";
119 }
120 return "Unknown";
121 }
122
Gustav Senntonb715d402017-05-12 14:22:58 +0100123 private static class MissingWebViewPackageException extends Exception {
Gustav Senntona8366e72015-04-17 11:24:07 +0100124 public MissingWebViewPackageException(String message) { super(message); }
125 public MissingWebViewPackageException(Exception e) { super(e); }
126 }
127
Gustav Sennton6ce92c92015-10-23 11:10:39 +0100128 /**
Gustav Sennton6ce92c92015-10-23 11:10:39 +0100129 * @hide
130 */
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000131 public static String getWebViewLibrary(ApplicationInfo ai) {
Gustav Sennton2ed6fee2015-03-03 15:12:34 +0000132 if (ai.metaData != null)
133 return ai.metaData.getString("com.android.webview.WebViewLibrary");
134 return null;
Ben Murdochdc00a842014-07-17 14:55:00 +0100135 }
136
Torne (Richard Coles)84392d72014-08-14 16:43:18 +0100137 public static PackageInfo getLoadedPackageInfo() {
Gustav Senntonbf683e02016-09-15 14:42:50 +0100138 synchronized (sProviderLock) {
139 return sPackageInfo;
140 }
Torne (Richard Coles)84392d72014-08-14 16:43:18 +0100141 }
142
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100143 /**
Tao Bai755eded2017-01-09 18:35:44 -0800144 * @hide
145 */
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000146 public static Class<WebViewFactoryProvider> getWebViewProviderClass(ClassLoader clazzLoader)
147 throws ClassNotFoundException {
148 return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
149 true, clazzLoader);
Tao Bai755eded2017-01-09 18:35:44 -0800150 }
151
152 /**
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100153 * Load the native library for the given package name iff that package
Gustav Senntond97301822015-06-18 16:56:26 +0100154 * name is the same as the one providing the webview.
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100155 */
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000156 public static int loadWebViewNativeLibraryFromPackage(String packageName,
157 ClassLoader clazzLoader) {
Gustav Senntonb088cb32016-06-17 14:02:52 +0100158 WebViewProviderResponse response = null;
159 try {
160 response = getUpdateService().waitForAndGetProvider();
161 } catch (RemoteException e) {
162 Log.e(LOGTAG, "error waiting for relro creation", e);
163 return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN;
Gustav Sennton6ce92c92015-10-23 11:10:39 +0100164 }
Gustav Senntonb088cb32016-06-17 14:02:52 +0100165
166
167 if (response.status != LIBLOAD_SUCCESS
168 && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) {
169 return response.status;
170 }
171 if (!response.packageInfo.packageName.equals(packageName)) {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000172 return LIBLOAD_WRONG_PACKAGE_NAME;
Gustav Senntonb088cb32016-06-17 14:02:52 +0100173 }
174
175 PackageManager packageManager = AppGlobals.getInitialApplication().getPackageManager();
176 PackageInfo packageInfo;
177 try {
178 packageInfo = packageManager.getPackageInfo(packageName,
179 PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
180 } catch (PackageManager.NameNotFoundException e) {
181 Log.e(LOGTAG, "Couldn't find package " + packageName);
182 return LIBLOAD_WRONG_PACKAGE_NAME;
183 }
Gustav Sennton6ce92c92015-10-23 11:10:39 +0100184
Gustav Senntonb715d402017-05-12 14:22:58 +0100185 try {
186 int loadNativeRet = loadNativeLibrary(clazzLoader, packageInfo);
187 // If we failed waiting for relro we want to return that fact even if we successfully
188 // load the relro file.
189 if (loadNativeRet == LIBLOAD_SUCCESS) return response.status;
190 return loadNativeRet;
191 } catch (MissingWebViewPackageException e) {
192 Log.e(LOGTAG, "Couldn't load native library: " + e);
193 return LIBLOAD_FAILED_TO_LOAD_LIBRARY;
194 }
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100195 }
196
John Reck9f9d3452012-09-20 13:18:59 -0700197 static WebViewFactoryProvider getProvider() {
198 synchronized (sProviderLock) {
199 // For now the main purpose of this function (and the factory abstraction) is to keep
Torne (Richard Coles)d892afc2013-10-14 17:14:04 +0100200 // us honest and minimize usage of WebView internals when binding the proxy.
John Reck9f9d3452012-09-20 13:18:59 -0700201 if (sProviderInstance != null) return sProviderInstance;
Jonathan Dixond3101b12012-04-12 20:51:51 +0100202
Jeff Sharkey85844912014-11-13 16:20:38 -0800203 final int uid = android.os.Process.myUid();
Robert Sesek450b55b2017-03-16 18:17:11 -0400204 if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID
205 || uid == android.os.Process.PHONE_UID || uid == android.os.Process.NFC_UID
206 || uid == android.os.Process.BLUETOOTH_UID) {
Jeff Sharkey85844912014-11-13 16:20:38 -0800207 throw new UnsupportedOperationException(
208 "For security reasons, WebView is not allowed in privileged processes");
209 }
210
Gustav Sennton5df5e222016-02-25 18:20:12 +0000211 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100212 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +0100213 try {
Gustav Senntona8366e72015-04-17 11:24:07 +0100214 Class<WebViewFactoryProvider> providerClass = getProviderClass();
Bo Liu48273852016-08-16 19:03:44 -0700215 Method staticFactory = null;
216 try {
217 staticFactory = providerClass.getMethod(
218 CHROMIUM_WEBVIEW_FACTORY_METHOD, WebViewDelegate.class);
219 } catch (Exception e) {
220 if (DEBUG) {
221 Log.w(LOGTAG, "error instantiating provider with static factory method", e);
222 }
223 }
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100224
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000225 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactoryProvider invocation");
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100226 try {
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000227 sProviderInstance = (WebViewFactoryProvider)
228 staticFactory.invoke(null, new WebViewDelegate());
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100229 if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
230 return sProviderInstance;
231 } catch (Exception e) {
232 Log.e(LOGTAG, "error instantiating provider", e);
233 throw new AndroidRuntimeException(e);
234 } finally {
235 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100236 }
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +0100237 } finally {
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100238 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
Gustav Sennton5df5e222016-02-25 18:20:12 +0000239 StrictMode.setThreadPolicy(oldPolicy);
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +0100240 }
Jonathan Dixond3101b12012-04-12 20:51:51 +0100241 }
Jonathan Dixond3101b12012-04-12 20:51:51 +0100242 }
243
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100244 /**
245 * Returns true if the signatures match, false otherwise
246 */
247 private static boolean signaturesEquals(Signature[] s1, Signature[] s2) {
248 if (s1 == null) {
249 return s2 == null;
250 }
251 if (s2 == null) return false;
252
253 ArraySet<Signature> set1 = new ArraySet<>();
254 for(Signature signature : s1) {
255 set1.add(signature);
256 }
257 ArraySet<Signature> set2 = new ArraySet<>();
258 for(Signature signature : s2) {
259 set2.add(signature);
260 }
261 return set1.equals(set2);
262 }
263
264 // Throws MissingWebViewPackageException on failure
Gustav Senntonb715d402017-05-12 14:22:58 +0100265 private static void verifyPackageInfo(PackageInfo chosen, PackageInfo toUse)
266 throws MissingWebViewPackageException {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100267 if (!chosen.packageName.equals(toUse.packageName)) {
268 throw new MissingWebViewPackageException("Failed to verify WebView provider, "
269 + "packageName mismatch, expected: "
270 + chosen.packageName + " actual: " + toUse.packageName);
271 }
272 if (chosen.versionCode > toUse.versionCode) {
273 throw new MissingWebViewPackageException("Failed to verify WebView provider, "
Hui Shub5f554a2016-04-20 17:17:44 -0700274 + "version code is lower than expected: " + chosen.versionCode
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100275 + " actual: " + toUse.versionCode);
276 }
277 if (getWebViewLibrary(toUse.applicationInfo) == null) {
278 throw new MissingWebViewPackageException("Tried to load an invalid WebView provider: "
279 + toUse.packageName);
280 }
281 if (!signaturesEquals(chosen.signatures, toUse.signatures)) {
282 throw new MissingWebViewPackageException("Failed to verify WebView provider, "
283 + "signature mismatch");
284 }
285 }
286
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000287 /**
288 * If the ApplicationInfo provided is for a stub WebView, fix up the object to include the
289 * required values from the donor package. If the ApplicationInfo is for a full WebView,
290 * leave it alone. Throws MissingWebViewPackageException if the donor is missing.
291 */
Gustav Senntonb715d402017-05-12 14:22:58 +0100292 private static void fixupStubApplicationInfo(ApplicationInfo ai, PackageManager pm)
293 throws MissingWebViewPackageException {
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000294 String donorPackageName = null;
295 if (ai.metaData != null) {
296 donorPackageName = ai.metaData.getString("com.android.webview.WebViewDonorPackage");
297 }
298 if (donorPackageName != null) {
299 PackageInfo donorPackage;
300 try {
301 donorPackage = pm.getPackageInfo(
302 donorPackageName,
303 PackageManager.GET_SHARED_LIBRARY_FILES
304 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
305 | PackageManager.MATCH_UNINSTALLED_PACKAGES
306 | PackageManager.MATCH_FACTORY_ONLY);
307 } catch (PackageManager.NameNotFoundException e) {
308 throw new MissingWebViewPackageException("Failed to find donor package: " +
309 donorPackageName);
310 }
311 ApplicationInfo donorInfo = donorPackage.applicationInfo;
312
313 // Replace the stub's code locations with the donor's.
314 ai.sourceDir = donorInfo.sourceDir;
315 ai.splitSourceDirs = donorInfo.splitSourceDirs;
316 ai.nativeLibraryDir = donorInfo.nativeLibraryDir;
317 ai.secondaryNativeLibraryDir = donorInfo.secondaryNativeLibraryDir;
318
319 // Copy the donor's primary and secondary ABIs, since the stub doesn't have native code
320 // and so they are unset.
321 ai.primaryCpuAbi = donorInfo.primaryCpuAbi;
322 ai.secondaryCpuAbi = donorInfo.secondaryCpuAbi;
323 }
324 }
325
Gustav Senntonb715d402017-05-12 14:22:58 +0100326 private static Context getWebViewContextAndSetProvider() throws MissingWebViewPackageException {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100327 Application initialApplication = AppGlobals.getInitialApplication();
328 try {
329 WebViewProviderResponse response = null;
330 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
331 "WebViewUpdateService.waitForAndGetProvider()");
332 try {
333 response = getUpdateService().waitForAndGetProvider();
334 } finally {
335 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
336 }
Gustav Senntonfd07efa2016-05-23 13:09:03 +0100337 if (response.status != LIBLOAD_SUCCESS
338 && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100339 throw new MissingWebViewPackageException("Failed to load WebView provider: "
340 + getWebViewPreparationErrorReason(response.status));
341 }
342 // Register to be killed before fetching package info - so that we will be
343 // killed if the package info goes out-of-date.
344 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "ActivityManager.addPackageDependency()");
345 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800346 ActivityManager.getService().addPackageDependency(
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100347 response.packageInfo.packageName);
348 } finally {
349 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
350 }
351 // Fetch package info and verify it against the chosen package
352 PackageInfo newPackageInfo = null;
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000353 PackageManager pm = initialApplication.getPackageManager();
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100354 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "PackageManager.getPackageInfo()");
355 try {
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000356 newPackageInfo = pm.getPackageInfo(
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100357 response.packageInfo.packageName,
358 PackageManager.GET_SHARED_LIBRARY_FILES
359 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
360 // Make sure that we fetch the current provider even if its not
361 // installed for the current user
362 | PackageManager.MATCH_UNINSTALLED_PACKAGES
363 // Fetch signatures for verification
364 | PackageManager.GET_SIGNATURES
365 // Get meta-data for meta data flag verification
366 | PackageManager.GET_META_DATA);
367 } finally {
368 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
369 }
370
371 // Validate the newly fetched package info, throws MissingWebViewPackageException on
372 // failure
373 verifyPackageInfo(response.packageInfo, newPackageInfo);
374
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000375 ApplicationInfo ai = newPackageInfo.applicationInfo;
376 fixupStubApplicationInfo(ai, pm);
377
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100378 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
379 "initialApplication.createApplicationContext");
380 try {
381 // Construct an app context to load the Java code into the current app.
382 Context webViewContext = initialApplication.createApplicationContext(
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000383 ai,
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100384 Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
Gustav Senntonb088cb32016-06-17 14:02:52 +0100385 sPackageInfo = newPackageInfo;
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100386 return webViewContext;
387 } finally {
388 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
389 }
390 } catch (RemoteException | PackageManager.NameNotFoundException e) {
391 throw new MissingWebViewPackageException("Failed to load WebView provider: " + e);
392 }
393 }
394
Gustav Senntona8366e72015-04-17 11:24:07 +0100395 private static Class<WebViewFactoryProvider> getProviderClass() {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100396 Context webViewContext = null;
397 Application initialApplication = AppGlobals.getInitialApplication();
398
Gustav Senntona8366e72015-04-17 11:24:07 +0100399 try {
Gustav Senntonfc424472016-01-06 17:11:09 +0000400 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100401 "WebViewFactory.getWebViewContextAndSetProvider()");
Gustav Senntonfc424472016-01-06 17:11:09 +0000402 try {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100403 webViewContext = getWebViewContextAndSetProvider();
Gustav Senntonfc424472016-01-06 17:11:09 +0000404 } finally {
405 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000406 }
Gustav Senntona8366e72015-04-17 11:24:07 +0100407 Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100408 sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000409
Gustav Senntona8366e72015-04-17 11:24:07 +0100410 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
411 try {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000412 initialApplication.getAssets().addAssetPathAsSharedLibrary(
413 webViewContext.getApplicationInfo().sourceDir);
414 ClassLoader clazzLoader = webViewContext.getClassLoader();
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000415
416 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
Gustav Senntonbf683e02016-09-15 14:42:50 +0100417 loadNativeLibrary(clazzLoader, sPackageInfo);
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000418 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
419
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000420 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
421 try {
Tao Bai755eded2017-01-09 18:35:44 -0800422 return getWebViewProviderClass(clazzLoader);
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000423 } finally {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000424 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
425 }
Gustav Senntona8366e72015-04-17 11:24:07 +0100426 } catch (ClassNotFoundException e) {
427 Log.e(LOGTAG, "error loading provider", e);
428 throw new AndroidRuntimeException(e);
429 } finally {
430 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
431 }
432 } catch (MissingWebViewPackageException e) {
433 // If the package doesn't exist, then try loading the null WebView instead.
434 // If that succeeds, then this is a device without WebView support; if it fails then
435 // swallow the failure, complain that the real WebView is missing and rethrow the
436 // original exception.
437 try {
438 return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
439 } catch (ClassNotFoundException e2) {
440 // Ignore.
441 }
442 Log.e(LOGTAG, "Chromium WebView package does not exist", e);
443 throw new AndroidRuntimeException(e);
444 }
445 }
446
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100447 /**
448 * Perform any WebView loading preparations that must happen in the zygote.
449 * Currently, this means allocating address space to load the real JNI library later.
450 */
451 public static void prepareWebViewInZygote() {
452 try {
453 System.loadLibrary("webviewchromium_loader");
Ben Murdoch5ced5022014-07-28 15:57:00 +0100454 long addressSpaceToReserve =
455 SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
456 CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
457 sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
458
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100459 if (sAddressSpaceReserved) {
Ben Murdoch5ced5022014-07-28 15:57:00 +0100460 if (DEBUG) {
461 Log.v(LOGTAG, "address space reserved: " + addressSpaceToReserve + " bytes");
462 }
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100463 } else {
Ben Murdoch5ced5022014-07-28 15:57:00 +0100464 Log.e(LOGTAG, "reserving " + addressSpaceToReserve +
465 " bytes of address space failed");
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100466 }
Primiano Tucci810c0522014-07-25 18:03:16 +0100467 } catch (Throwable t) {
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100468 // Log and discard errors at this stage as we must not crash the zygote.
Primiano Tucci810c0522014-07-25 18:03:16 +0100469 Log.e(LOGTAG, "error preparing native loader", t);
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100470 }
471 }
472
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000473 private static int prepareWebViewInSystemServer(String[] nativeLibraryPaths) {
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100474 if (DEBUG) Log.v(LOGTAG, "creating relro files");
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000475 int numRelros = 0;
Ben Murdoch5ced5022014-07-28 15:57:00 +0100476
477 // We must always trigger createRelRo regardless of the value of nativeLibraryPaths. Any
478 // unexpected values will be handled there to ensure that we trigger notifying any process
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000479 // waiting on relro creation.
Ben Murdoch5ced5022014-07-28 15:57:00 +0100480 if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
481 if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
482 createRelroFile(false /* is64Bit */, nativeLibraryPaths);
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000483 numRelros++;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100484 }
Ben Murdoch5ced5022014-07-28 15:57:00 +0100485
486 if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
487 if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
488 createRelroFile(true /* is64Bit */, nativeLibraryPaths);
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000489 numRelros++;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100490 }
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000491 return numRelros;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100492 }
493
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000494 /**
495 * @hide
496 */
497 public static int onWebViewProviderChanged(PackageInfo packageInfo) {
Ben Murdoch5ced5022014-07-28 15:57:00 +0100498 String[] nativeLibs = null;
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000499 String originalSourceDir = packageInfo.applicationInfo.sourceDir;
Ben Murdoch5ced5022014-07-28 15:57:00 +0100500 try {
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000501 fixupStubApplicationInfo(packageInfo.applicationInfo,
502 AppGlobals.getInitialApplication().getPackageManager());
503
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000504 nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths(packageInfo);
Torne (Richard Coles)27cb0d22014-08-08 18:24:12 +0100505 if (nativeLibs != null) {
506 long newVmSize = 0L;
Ben Murdoch5ced5022014-07-28 15:57:00 +0100507
Torne (Richard Coles)27cb0d22014-08-08 18:24:12 +0100508 for (String path : nativeLibs) {
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100509 if (path == null || TextUtils.isEmpty(path)) continue;
Torne (Richard Coles)27cb0d22014-08-08 18:24:12 +0100510 if (DEBUG) Log.d(LOGTAG, "Checking file size of " + path);
Torne (Richard Coles)27cb0d22014-08-08 18:24:12 +0100511 File f = new File(path);
512 if (f.exists()) {
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100513 newVmSize = Math.max(newVmSize, f.length());
514 continue;
515 }
Simon Baldwin519919b2015-06-11 17:09:49 +0100516 if (path.contains("!/")) {
517 String[] split = TextUtils.split(path, "!/");
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100518 if (split.length == 2) {
Torne (Richard Coles)c5283922015-08-10 16:40:50 +0100519 try (ZipFile z = new ZipFile(split[0])) {
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100520 ZipEntry e = z.getEntry(split[1]);
521 if (e != null && e.getMethod() == ZipEntry.STORED) {
522 newVmSize = Math.max(newVmSize, e.getSize());
523 continue;
524 }
525 }
526 catch (IOException e) {
527 Log.e(LOGTAG, "error reading APK file " + split[0] + ", ", e);
528 }
Torne (Richard Coles)27cb0d22014-08-08 18:24:12 +0100529 }
Ben Murdoch5ced5022014-07-28 15:57:00 +0100530 }
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100531 Log.e(LOGTAG, "error sizing load for " + path);
Ben Murdoch5ced5022014-07-28 15:57:00 +0100532 }
Ben Murdoch5ced5022014-07-28 15:57:00 +0100533
Torne (Richard Coles)27cb0d22014-08-08 18:24:12 +0100534 if (DEBUG) {
535 Log.v(LOGTAG, "Based on library size, need " + newVmSize +
536 " bytes of address space.");
537 }
538 // The required memory can be larger than the file on disk (due to .bss), and an
539 // upgraded version of the library will likely be larger, so always attempt to
540 // reserve twice as much as we think to allow for the library to grow during this
541 // boot cycle.
542 newVmSize = Math.max(2 * newVmSize, CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
543 Log.d(LOGTAG, "Setting new address space to " + newVmSize);
544 SystemProperties.set(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
545 Long.toString(newVmSize));
Ben Murdoch5ced5022014-07-28 15:57:00 +0100546 }
Torne (Richard Coles)27cb0d22014-08-08 18:24:12 +0100547 } catch (Throwable t) {
548 // Log and discard errors at this stage as we must not crash the system server.
549 Log.e(LOGTAG, "error preparing webview native library", t);
Ben Murdoch5ced5022014-07-28 15:57:00 +0100550 }
Robert Sesekded20982016-08-15 13:59:13 -0400551
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000552 WebViewZygote.onWebViewProviderChanged(packageInfo, originalSourceDir);
Robert Sesekded20982016-08-15 13:59:13 -0400553
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000554 return prepareWebViewInSystemServer(nativeLibs);
Ben Murdoch5ced5022014-07-28 15:57:00 +0100555 }
556
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100557 private static String getLoadFromApkPath(String apkPath,
558 String[] abiList,
Gustav Senntonb715d402017-05-12 14:22:58 +0100559 String nativeLibFileName)
560 throws MissingWebViewPackageException {
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100561 // Search the APK for a native library conforming to a listed ABI.
Torne (Richard Coles)c5283922015-08-10 16:40:50 +0100562 try (ZipFile z = new ZipFile(apkPath)) {
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100563 for (String abi : abiList) {
564 final String entry = "lib/" + abi + "/" + nativeLibFileName;
565 ZipEntry e = z.getEntry(entry);
566 if (e != null && e.getMethod() == ZipEntry.STORED) {
567 // Return a path formatted for dlopen() load from APK.
Simon Baldwin519919b2015-06-11 17:09:49 +0100568 return apkPath + "!/" + entry;
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100569 }
570 }
571 } catch (IOException e) {
572 throw new MissingWebViewPackageException(e);
573 }
574 return "";
575 }
576
Gustav Senntonb715d402017-05-12 14:22:58 +0100577 private static String[] getWebViewNativeLibraryPaths(PackageInfo packageInfo)
578 throws MissingWebViewPackageException {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000579 ApplicationInfo ai = packageInfo.applicationInfo;
Gustav Sennton2ed6fee2015-03-03 15:12:34 +0000580 final String NATIVE_LIB_FILE_NAME = getWebViewLibrary(ai);
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100581
582 String path32;
583 String path64;
584 boolean primaryArchIs64bit = VMRuntime.is64BitAbi(ai.primaryCpuAbi);
585 if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) {
586 // Multi-arch case.
587 if (primaryArchIs64bit) {
588 // Primary arch: 64-bit, secondary: 32-bit.
589 path64 = ai.nativeLibraryDir;
590 path32 = ai.secondaryNativeLibraryDir;
591 } else {
592 // Primary arch: 32-bit, secondary: 64-bit.
593 path64 = ai.secondaryNativeLibraryDir;
594 path32 = ai.nativeLibraryDir;
595 }
596 } else if (primaryArchIs64bit) {
597 // Single-arch 64-bit.
598 path64 = ai.nativeLibraryDir;
599 path32 = "";
600 } else {
601 // Single-arch 32-bit.
602 path32 = ai.nativeLibraryDir;
603 path64 = "";
604 }
Simon Baldwinb98082dc2015-05-15 12:56:50 +0100605
606 // Form the full paths to the extracted native libraries.
607 // If libraries were not extracted, try load from APK paths instead.
608 if (!TextUtils.isEmpty(path32)) {
609 path32 += "/" + NATIVE_LIB_FILE_NAME;
610 File f = new File(path32);
611 if (!f.exists()) {
612 path32 = getLoadFromApkPath(ai.sourceDir,
613 Build.SUPPORTED_32_BIT_ABIS,
614 NATIVE_LIB_FILE_NAME);
615 }
616 }
617 if (!TextUtils.isEmpty(path64)) {
618 path64 += "/" + NATIVE_LIB_FILE_NAME;
619 File f = new File(path64);
620 if (!f.exists()) {
621 path64 = getLoadFromApkPath(ai.sourceDir,
622 Build.SUPPORTED_64_BIT_ABIS,
623 NATIVE_LIB_FILE_NAME);
624 }
625 }
626
627 if (DEBUG) Log.v(LOGTAG, "Native 32-bit lib: " + path32 + ", 64-bit lib: " + path64);
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100628 return new String[] { path32, path64 };
629 }
630
Ben Murdoch5ced5022014-07-28 15:57:00 +0100631 private static void createRelroFile(final boolean is64Bit, String[] nativeLibraryPaths) {
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100632 final String abi =
633 is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
Primiano Tucci810c0522014-07-25 18:03:16 +0100634
635 // crashHandler is invoked by the ActivityManagerService when the isolated process crashes.
636 Runnable crashHandler = new Runnable() {
637 @Override
638 public void run() {
639 try {
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100640 Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without");
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000641 getUpdateService().notifyRelroCreationCompleted();
Primiano Tucci810c0522014-07-25 18:03:16 +0100642 } catch (RemoteException e) {
643 Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage());
644 }
645 }
646 };
647
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100648 try {
Ben Murdoch5ced5022014-07-28 15:57:00 +0100649 if (nativeLibraryPaths == null
650 || nativeLibraryPaths[0] == null || nativeLibraryPaths[1] == null) {
651 throw new IllegalArgumentException(
652 "Native library paths to the WebView RelRo process must not be null!");
653 }
Primiano Tucci161536b2014-07-28 18:51:45 +0100654 int pid = LocalServices.getService(ActivityManagerInternal.class).startIsolatedProcess(
Ben Murdoch5ced5022014-07-28 15:57:00 +0100655 RelroFileCreator.class.getName(), nativeLibraryPaths, "WebViewLoader-" + abi, abi,
Primiano Tucci810c0522014-07-25 18:03:16 +0100656 Process.SHARED_RELRO_UID, crashHandler);
Primiano Tuccie76e81a2014-07-29 16:38:33 +0100657 if (pid <= 0) throw new Exception("Failed to start the relro file creator process");
Primiano Tucci810c0522014-07-25 18:03:16 +0100658 } catch (Throwable t) {
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100659 // Log and discard errors as we must not crash the system server.
Primiano Tucci810c0522014-07-25 18:03:16 +0100660 Log.e(LOGTAG, "error starting relro file creator for abi " + abi, t);
661 crashHandler.run();
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100662 }
663 }
664
665 private static class RelroFileCreator {
666 // Called in an unprivileged child process to create the relro file.
667 public static void main(String[] args) {
Primiano Tucci161536b2014-07-28 18:51:45 +0100668 boolean result = false;
669 boolean is64Bit = VMRuntime.getRuntime().is64Bit();
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100670 try{
671 if (args.length != 2 || args[0] == null || args[1] == null) {
672 Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args));
673 return;
674 }
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100675 Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), " +
676 " 32-bit lib: " + args[0] + ", 64-bit lib: " + args[1]);
677 if (!sAddressSpaceReserved) {
678 Log.e(LOGTAG, "can't create relro file; address space not reserved");
679 return;
680 }
Primiano Tucci161536b2014-07-28 18:51:45 +0100681 result = nativeCreateRelroFile(args[0] /* path32 */,
682 args[1] /* path64 */,
683 CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
684 CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
Primiano Tuccie76e81a2014-07-29 16:38:33 +0100685 if (result && DEBUG) Log.v(LOGTAG, "created relro file");
Primiano Tucci161536b2014-07-28 18:51:45 +0100686 } finally {
687 // We must do our best to always notify the update service, even if something fails.
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100688 try {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000689 getUpdateService().notifyRelroCreationCompleted();
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100690 } catch (RemoteException e) {
691 Log.e(LOGTAG, "error notifying update service", e);
692 }
Primiano Tucci161536b2014-07-28 18:51:45 +0100693
694 if (!result) Log.e(LOGTAG, "failed to create relro file");
695
Primiano Tucci1b7977b2014-07-25 19:19:32 +0100696 // Must explicitly exit or else this process will just sit around after we return.
697 System.exit(0);
698 }
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100699 }
700 }
701
Gustav Senntonbf683e02016-09-15 14:42:50 +0100702 // Assumes that we have waited for relro creation
Gustav Senntonb715d402017-05-12 14:22:58 +0100703 private static int loadNativeLibrary(ClassLoader clazzLoader, PackageInfo packageInfo)
704 throws MissingWebViewPackageException {
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100705 if (!sAddressSpaceReserved) {
706 Log.e(LOGTAG, "can't load with relro file; address space not reserved");
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100707 return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100708 }
709
Gustav Senntonbf683e02016-09-15 14:42:50 +0100710 String[] args = getWebViewNativeLibraryPaths(packageInfo);
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000711 int result = nativeLoadWithRelroFile(args[0] /* path32 */,
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000712 args[1] /* path64 */,
713 CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
714 CHROMIUM_WEBVIEW_NATIVE_RELRO_64,
715 clazzLoader);
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000716 if (result != LIBLOAD_SUCCESS) {
717 Log.w(LOGTAG, "failed to load with relro file, proceeding without");
718 } else if (DEBUG) {
719 Log.v(LOGTAG, "loaded with relro file");
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100720 }
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000721 return result;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100722 }
723
Gustav Sennton1c177d82016-03-29 20:43:11 +0100724 private static String WEBVIEW_UPDATE_SERVICE_NAME = "webviewupdate";
725
726 /** @hide */
727 public static IWebViewUpdateService getUpdateService() {
728 return IWebViewUpdateService.Stub.asInterface(
729 ServiceManager.getService(WEBVIEW_UPDATE_SERVICE_NAME));
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100730 }
731
Ben Murdoch5ced5022014-07-28 15:57:00 +0100732 private static native boolean nativeReserveAddressSpace(long addressSpaceToReserve);
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100733 private static native boolean nativeCreateRelroFile(String lib32, String lib64,
734 String relro32, String relro64);
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100735 private static native int nativeLoadWithRelroFile(String lib32, String lib64,
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000736 String relro32, String relro64,
737 ClassLoader clazzLoader);
Jonathan Dixond3101b12012-04-12 20:51:51 +0100738}