1 /* 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 17 package android.webkit; 18 19 import static android.webkit.Flags.updateServiceV2; 20 21 import android.annotation.NonNull; 22 import android.annotation.SystemApi; 23 import android.annotation.UptimeMillisLong; 24 import android.app.ActivityManager; 25 import android.app.AppGlobals; 26 import android.app.Application; 27 import android.compat.annotation.UnsupportedAppUsage; 28 import android.content.Context; 29 import android.content.pm.ApplicationInfo; 30 import android.content.pm.PackageInfo; 31 import android.content.pm.PackageManager; 32 import android.content.pm.Signature; 33 import android.content.res.Resources; 34 import android.os.Build; 35 import android.os.RemoteException; 36 import android.os.ServiceManager; 37 import android.os.SystemClock; 38 import android.os.Trace; 39 import android.text.TextUtils; 40 import android.util.AndroidRuntimeException; 41 import android.util.ArraySet; 42 import android.util.Log; 43 import android.util.Slog; 44 45 import java.io.File; 46 import java.lang.reflect.Method; 47 48 /** 49 * Top level factory, used creating all the main WebView implementation classes. 50 * 51 * @hide 52 */ 53 @SystemApi 54 public final class WebViewFactory { 55 56 // visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote. 57 /** @hide */ 58 private static final String CHROMIUM_WEBVIEW_FACTORY = 59 "com.android.webview.chromium.WebViewChromiumFactoryProviderForT"; 60 61 private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create"; 62 63 private static final String LOGTAG = "WebViewFactory"; 64 65 private static final boolean DEBUG = false; 66 67 // Cache the factory both for efficiency, and ensure any one process gets all webviews from the 68 // same provider. 69 @UnsupportedAppUsage 70 private static WebViewFactoryProvider sProviderInstance; 71 private static final Object sProviderLock = new Object(); 72 @UnsupportedAppUsage 73 private static PackageInfo sPackageInfo; 74 private static Boolean sWebViewSupported; 75 private static boolean sWebViewDisabled; 76 private static String sDataDirectorySuffix; // stored here so it can be set without loading WV 77 78 // Error codes for loadWebViewNativeLibraryFromPackage 79 public static final int LIBLOAD_SUCCESS = 0; 80 public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1; 81 public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; 82 83 // error codes for waiting for WebView preparation 84 public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3; 85 public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; 86 87 // native relro loading error codes 88 public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5; 89 public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6; 90 public static final int LIBLOAD_FAILED_JNI_CALL = 7; 91 92 // more error codes for waiting for WebView preparation 93 public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 8; 94 95 // error for namespace lookup 96 public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10; 97 98 // generic error for future use 99 static final int LIBLOAD_FAILED_OTHER = 11; 100 101 /** 102 * Stores the timestamps at which various WebView startup events occurred in this process. 103 */ 104 public static class StartupTimestamps { 105 long mWebViewLoadStart; 106 long mCreateContextStart; 107 long mCreateContextEnd; 108 long mAddAssetsStart; 109 long mAddAssetsEnd; 110 long mGetClassLoaderStart; 111 long mGetClassLoaderEnd; 112 long mNativeLoadStart; 113 long mNativeLoadEnd; 114 long mProviderClassForNameStart; 115 long mProviderClassForNameEnd; 116 StartupTimestamps()117 StartupTimestamps() {} 118 119 /** When the overall WebView provider load began. */ 120 @UptimeMillisLong getWebViewLoadStart()121 public long getWebViewLoadStart() { 122 return mWebViewLoadStart; 123 } 124 125 /** Before creating the WebView APK Context. */ 126 @UptimeMillisLong getCreateContextStart()127 public long getCreateContextStart() { 128 return mCreateContextStart; 129 } 130 131 /** After creating the WebView APK Context. */ 132 @UptimeMillisLong getCreateContextEnd()133 public long getCreateContextEnd() { 134 return mCreateContextEnd; 135 } 136 137 /** Before adding WebView assets to AssetManager. */ 138 @UptimeMillisLong getAddAssetsStart()139 public long getAddAssetsStart() { 140 return mAddAssetsStart; 141 } 142 143 /** After adding WebView assets to AssetManager. */ 144 @UptimeMillisLong getAddAssetsEnd()145 public long getAddAssetsEnd() { 146 return mAddAssetsEnd; 147 } 148 149 /** Before creating the WebView ClassLoader. */ 150 @UptimeMillisLong getGetClassLoaderStart()151 public long getGetClassLoaderStart() { 152 return mGetClassLoaderStart; 153 } 154 155 /** After creating the WebView ClassLoader. */ 156 @UptimeMillisLong getGetClassLoaderEnd()157 public long getGetClassLoaderEnd() { 158 return mGetClassLoaderEnd; 159 } 160 161 /** Before preloading the WebView native library. */ 162 @UptimeMillisLong getNativeLoadStart()163 public long getNativeLoadStart() { 164 return mNativeLoadStart; 165 } 166 167 /** After preloading the WebView native library. */ 168 @UptimeMillisLong getNativeLoadEnd()169 public long getNativeLoadEnd() { 170 return mNativeLoadEnd; 171 } 172 173 /** Before looking up the WebView provider class. */ 174 @UptimeMillisLong getProviderClassForNameStart()175 public long getProviderClassForNameStart() { 176 return mProviderClassForNameStart; 177 } 178 179 /** After looking up the WebView provider class. */ 180 @UptimeMillisLong getProviderClassForNameEnd()181 public long getProviderClassForNameEnd() { 182 return mProviderClassForNameEnd; 183 } 184 } 185 186 static final StartupTimestamps sTimestamps = new StartupTimestamps(); 187 188 @NonNull getStartupTimestamps()189 static StartupTimestamps getStartupTimestamps() { 190 return sTimestamps; 191 } 192 getWebViewPreparationErrorReason(int error)193 private static String getWebViewPreparationErrorReason(int error) { 194 switch (error) { 195 case LIBLOAD_FAILED_WAITING_FOR_RELRO: 196 return "Time out waiting for Relro files being created"; 197 case LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES: 198 return "No WebView installed"; 199 case LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN: 200 return "Crashed for unknown reason"; 201 } 202 return "Unknown"; 203 } 204 205 static class MissingWebViewPackageException extends Exception { MissingWebViewPackageException(String message)206 public MissingWebViewPackageException(String message) { super(message); } MissingWebViewPackageException(Exception e)207 public MissingWebViewPackageException(Exception e) { super(e); } 208 } 209 isWebViewSupported()210 private static boolean isWebViewSupported() { 211 // No lock; this is a benign race as Boolean's state is final and the PackageManager call 212 // will always return the same value. 213 if (sWebViewSupported == null) { 214 sWebViewSupported = AppGlobals.getInitialApplication().getPackageManager() 215 .hasSystemFeature(PackageManager.FEATURE_WEBVIEW); 216 } 217 return sWebViewSupported; 218 } 219 220 /** 221 * @hide 222 */ disableWebView()223 static void disableWebView() { 224 synchronized (sProviderLock) { 225 if (sProviderInstance != null) { 226 throw new IllegalStateException( 227 "Can't disable WebView: WebView already initialized"); 228 } 229 sWebViewDisabled = true; 230 } 231 } 232 233 /** 234 * @hide 235 */ setDataDirectorySuffix(String suffix)236 static void setDataDirectorySuffix(String suffix) { 237 synchronized (sProviderLock) { 238 if (sProviderInstance != null) { 239 throw new IllegalStateException( 240 "Can't set data directory suffix: WebView already initialized"); 241 } 242 if (suffix.indexOf(File.separatorChar) >= 0) { 243 throw new IllegalArgumentException("Suffix " + suffix 244 + " contains a path separator"); 245 } 246 sDataDirectorySuffix = suffix; 247 } 248 } 249 250 /** 251 * @hide 252 */ getDataDirectorySuffix()253 static String getDataDirectorySuffix() { 254 synchronized (sProviderLock) { 255 return sDataDirectorySuffix; 256 } 257 } 258 259 /** 260 * @hide 261 */ getWebViewLibrary(ApplicationInfo ai)262 public static String getWebViewLibrary(ApplicationInfo ai) { 263 if (ai.metaData != null) 264 return ai.metaData.getString("com.android.webview.WebViewLibrary"); 265 return null; 266 } 267 getLoadedPackageInfo()268 public static PackageInfo getLoadedPackageInfo() { 269 synchronized (sProviderLock) { 270 return sPackageInfo; 271 } 272 } 273 274 /** 275 * @hide 276 */ getWebViewProviderClass(ClassLoader clazzLoader)277 public static Class<WebViewFactoryProvider> getWebViewProviderClass(ClassLoader clazzLoader) 278 throws ClassNotFoundException { 279 return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, 280 true, clazzLoader); 281 } 282 283 /** 284 * Load the native library for the given package name if that package 285 * name is the same as the one providing the webview. 286 */ loadWebViewNativeLibraryFromPackage(String packageName, ClassLoader clazzLoader)287 public static int loadWebViewNativeLibraryFromPackage(String packageName, 288 ClassLoader clazzLoader) { 289 if (!isWebViewSupported()) { 290 return LIBLOAD_WRONG_PACKAGE_NAME; 291 } 292 293 Application initialApplication = AppGlobals.getInitialApplication(); 294 WebViewProviderResponse response = null; 295 try { 296 if (Flags.updateServiceIpcWrapper()) { 297 response = initialApplication.getSystemService(WebViewUpdateManager.class) 298 .waitForAndGetProvider(); 299 } else { 300 response = getUpdateService().waitForAndGetProvider(); 301 } 302 } catch (Exception e) { 303 Log.e(LOGTAG, "error waiting for relro creation", e); 304 return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN; 305 } 306 307 308 if (response.status != LIBLOAD_SUCCESS 309 && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) { 310 return response.status; 311 } 312 if (!response.packageInfo.packageName.equals(packageName)) { 313 return LIBLOAD_WRONG_PACKAGE_NAME; 314 } 315 316 PackageManager packageManager = initialApplication.getPackageManager(); 317 String libraryFileName; 318 try { 319 PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 320 PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING); 321 libraryFileName = getWebViewLibrary(packageInfo.applicationInfo); 322 } catch (PackageManager.NameNotFoundException e) { 323 Log.e(LOGTAG, "Couldn't find package " + packageName); 324 return LIBLOAD_WRONG_PACKAGE_NAME; 325 } 326 327 int loadNativeRet = WebViewLibraryLoader.loadNativeLibrary(clazzLoader, libraryFileName); 328 // If we failed waiting for relro we want to return that fact even if we successfully 329 // load the relro file. 330 if (loadNativeRet == LIBLOAD_SUCCESS) return response.status; 331 return loadNativeRet; 332 } 333 334 @UnsupportedAppUsage getProvider()335 static WebViewFactoryProvider getProvider() { 336 synchronized (sProviderLock) { 337 // For now the main purpose of this function (and the factory abstraction) is to keep 338 // us honest and minimize usage of WebView internals when binding the proxy. 339 if (sProviderInstance != null) return sProviderInstance; 340 341 sTimestamps.mWebViewLoadStart = SystemClock.uptimeMillis(); 342 final int uid = android.os.Process.myUid(); 343 if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID 344 || uid == android.os.Process.PHONE_UID || uid == android.os.Process.NFC_UID 345 || uid == android.os.Process.BLUETOOTH_UID) { 346 throw new UnsupportedOperationException( 347 "For security reasons, WebView is not allowed in privileged processes"); 348 } 349 350 if (!isWebViewSupported()) { 351 // Device doesn't support WebView; don't try to load it, just throw. 352 throw new UnsupportedOperationException(); 353 } 354 355 if (sWebViewDisabled) { 356 throw new IllegalStateException( 357 "WebView.disableWebView() was called: WebView is disabled"); 358 } 359 360 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()"); 361 try { 362 Class<WebViewFactoryProvider> providerClass = getProviderClass(); 363 Method staticFactory = providerClass.getMethod( 364 CHROMIUM_WEBVIEW_FACTORY_METHOD, WebViewDelegate.class); 365 366 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactoryProvider invocation"); 367 try { 368 sProviderInstance = (WebViewFactoryProvider) 369 staticFactory.invoke(null, new WebViewDelegate()); 370 if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance); 371 return sProviderInstance; 372 } finally { 373 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 374 } 375 } catch (Exception e) { 376 Log.e(LOGTAG, "error instantiating provider", e); 377 throw new AndroidRuntimeException(e); 378 } finally { 379 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 380 } 381 } 382 } 383 384 /** 385 * Returns {@code true} if the signatures match, {@code false} otherwise 386 */ signaturesEquals(Signature[] s1, Signature[] s2)387 private static boolean signaturesEquals(Signature[] s1, Signature[] s2) { 388 if (s1 == null) { 389 return s2 == null; 390 } 391 if (s2 == null) return false; 392 393 ArraySet<Signature> set1 = new ArraySet<>(); 394 for(Signature signature : s1) { 395 set1.add(signature); 396 } 397 ArraySet<Signature> set2 = new ArraySet<>(); 398 for(Signature signature : s2) { 399 set2.add(signature); 400 } 401 return set1.equals(set2); 402 } 403 404 // Throws MissingWebViewPackageException on failure verifyPackageInfo(PackageInfo chosen, PackageInfo toUse)405 private static void verifyPackageInfo(PackageInfo chosen, PackageInfo toUse) 406 throws MissingWebViewPackageException { 407 if (!chosen.packageName.equals(toUse.packageName)) { 408 throw new MissingWebViewPackageException("Failed to verify WebView provider, " 409 + "packageName mismatch, expected: " 410 + chosen.packageName + " actual: " + toUse.packageName); 411 } 412 if (chosen.getLongVersionCode() > toUse.getLongVersionCode()) { 413 throw new MissingWebViewPackageException("Failed to verify WebView provider, " 414 + "version code is lower than expected: " + chosen.getLongVersionCode() 415 + " actual: " + toUse.getLongVersionCode()); 416 } 417 if (getWebViewLibrary(toUse.applicationInfo) == null) { 418 throw new MissingWebViewPackageException("Tried to load an invalid WebView provider: " 419 + toUse.packageName); 420 } 421 if (!signaturesEquals(chosen.signatures, toUse.signatures)) { 422 throw new MissingWebViewPackageException("Failed to verify WebView provider, " 423 + "signature mismatch"); 424 } 425 } 426 427 // Returns whether the given package is enabled. 428 // This state can be changed by the user from Settings->Apps isEnabledPackage(PackageInfo packageInfo)429 private static boolean isEnabledPackage(PackageInfo packageInfo) { 430 if (packageInfo == null) return false; 431 return packageInfo.applicationInfo.enabled; 432 } 433 434 // Return {@code true} if the package is installed and not hidden isInstalledPackage(PackageInfo packageInfo)435 private static boolean isInstalledPackage(PackageInfo packageInfo) { 436 if (packageInfo == null) return false; 437 return (((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0) 438 && ((packageInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HIDDEN) 439 == 0)); 440 } 441 442 @UnsupportedAppUsage getWebViewContextAndSetProvider()443 private static Context getWebViewContextAndSetProvider() throws MissingWebViewPackageException { 444 Application initialApplication = AppGlobals.getInitialApplication(); 445 try { 446 WebViewProviderResponse response = null; 447 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, 448 "WebViewUpdateService.waitForAndGetProvider()"); 449 try { 450 if (Flags.updateServiceIpcWrapper()) { 451 response = initialApplication.getSystemService(WebViewUpdateManager.class) 452 .waitForAndGetProvider(); 453 } else { 454 response = getUpdateService().waitForAndGetProvider(); 455 } 456 } finally { 457 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 458 } 459 if (response.status != LIBLOAD_SUCCESS 460 && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) { 461 throw new MissingWebViewPackageException("Failed to load WebView provider: " 462 + getWebViewPreparationErrorReason(response.status)); 463 } 464 // Register to be killed before fetching package info - so that we will be 465 // killed if the package info goes out-of-date. 466 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "ActivityManager.addPackageDependency()"); 467 try { 468 ActivityManager.getService().addPackageDependency( 469 response.packageInfo.packageName); 470 } finally { 471 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 472 } 473 // Fetch package info and verify it against the chosen package 474 PackageInfo newPackageInfo = null; 475 PackageManager pm = initialApplication.getPackageManager(); 476 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "PackageManager.getPackageInfo()"); 477 try { 478 newPackageInfo = pm.getPackageInfo( 479 response.packageInfo.packageName, 480 PackageManager.GET_SHARED_LIBRARY_FILES 481 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING 482 // Make sure that we fetch the current provider even if its not 483 // installed for the current user 484 | PackageManager.MATCH_UNINSTALLED_PACKAGES 485 // Fetch signatures for verification 486 | PackageManager.GET_SIGNATURES 487 // Get meta-data for meta data flag verification 488 | PackageManager.GET_META_DATA); 489 } finally { 490 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 491 } 492 493 if (updateServiceV2() && !isInstalledPackage(newPackageInfo)) { 494 throw new MissingWebViewPackageException( 495 TextUtils.formatSimple( 496 "Current WebView Package (%s) is not installed for the current " 497 + "user", 498 newPackageInfo.packageName)); 499 } 500 501 if (updateServiceV2() && !isEnabledPackage(newPackageInfo)) { 502 throw new MissingWebViewPackageException( 503 TextUtils.formatSimple( 504 "Current WebView Package (%s) is not enabled for the current user", 505 newPackageInfo.packageName)); 506 } 507 508 // Validate the newly fetched package info, throws MissingWebViewPackageException on 509 // failure 510 verifyPackageInfo(response.packageInfo, newPackageInfo); 511 512 ApplicationInfo ai = newPackageInfo.applicationInfo; 513 514 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, 515 "initialApplication.createApplicationContext"); 516 sTimestamps.mCreateContextStart = SystemClock.uptimeMillis(); 517 try { 518 // Construct an app context to load the Java code into the current app. 519 Context webViewContext = initialApplication.createApplicationContext( 520 ai, 521 Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); 522 sPackageInfo = newPackageInfo; 523 return webViewContext; 524 } finally { 525 sTimestamps.mCreateContextEnd = SystemClock.uptimeMillis(); 526 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 527 } 528 } catch (RemoteException | PackageManager.NameNotFoundException e) { 529 throw new MissingWebViewPackageException("Failed to load WebView provider: " + e); 530 } 531 } 532 533 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getProviderClass()534 private static Class<WebViewFactoryProvider> getProviderClass() { 535 Context webViewContext = null; 536 Application initialApplication = AppGlobals.getInitialApplication(); 537 538 try { 539 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, 540 "WebViewFactory.getWebViewContextAndSetProvider()"); 541 try { 542 webViewContext = getWebViewContextAndSetProvider(); 543 } finally { 544 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 545 } 546 Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " + 547 sPackageInfo.versionName + " (code " + sPackageInfo.getLongVersionCode() + ")"); 548 549 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()"); 550 try { 551 sTimestamps.mAddAssetsStart = SystemClock.uptimeMillis(); 552 if (android.content.res.Flags.registerResourcePaths()) { 553 Resources.registerResourcePaths(webViewContext.getPackageName(), 554 webViewContext.getApplicationInfo()); 555 } else { 556 for (String newAssetPath : webViewContext.getApplicationInfo() 557 .getAllApkPaths()) { 558 initialApplication.getAssets().addAssetPathAsSharedLibrary(newAssetPath); 559 } 560 } 561 sTimestamps.mAddAssetsEnd = sTimestamps.mGetClassLoaderStart = 562 SystemClock.uptimeMillis(); 563 ClassLoader clazzLoader = webViewContext.getClassLoader(); 564 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()"); 565 sTimestamps.mGetClassLoaderEnd = sTimestamps.mNativeLoadStart = 566 SystemClock.uptimeMillis(); 567 WebViewLibraryLoader.loadNativeLibrary(clazzLoader, 568 getWebViewLibrary(sPackageInfo.applicationInfo)); 569 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 570 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()"); 571 sTimestamps.mNativeLoadEnd = sTimestamps.mProviderClassForNameStart = 572 SystemClock.uptimeMillis(); 573 try { 574 return getWebViewProviderClass(clazzLoader); 575 } finally { 576 sTimestamps.mProviderClassForNameEnd = SystemClock.uptimeMillis(); 577 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 578 } 579 } catch (ClassNotFoundException e) { 580 Log.e(LOGTAG, "error loading provider", e); 581 throw new AndroidRuntimeException(e); 582 } finally { 583 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 584 } 585 } catch (MissingWebViewPackageException e) { 586 Log.e(LOGTAG, "Chromium WebView package does not exist", e); 587 throw new AndroidRuntimeException(e); 588 } 589 } 590 591 /** 592 * Perform any WebView loading preparations that must happen in the zygote. 593 * Currently, this means allocating address space to load the real JNI library later. 594 */ prepareWebViewInZygote()595 public static void prepareWebViewInZygote() { 596 try { 597 WebViewLibraryLoader.reserveAddressSpaceInZygote(); 598 } catch (Throwable t) { 599 // Log and discard errors at this stage as we must not crash the zygote. 600 Log.e(LOGTAG, "error preparing native loader", t); 601 } 602 } 603 604 /** 605 * @hide 606 */ onWebViewProviderChanged(PackageInfo packageInfo)607 public static int onWebViewProviderChanged(PackageInfo packageInfo) { 608 int startedRelroProcesses = 0; 609 try { 610 startedRelroProcesses = WebViewLibraryLoader.prepareNativeLibraries(packageInfo); 611 } catch (Throwable t) { 612 // Log and discard errors at this stage as we must not crash the system server. 613 Slog.wtf(LOGTAG, "error preparing webview native library", t); 614 } 615 616 WebViewZygote.onWebViewProviderChanged(packageInfo); 617 618 return startedRelroProcesses; 619 } 620 621 private static String WEBVIEW_UPDATE_SERVICE_NAME = "webviewupdate"; 622 623 /** @hide */ 624 @UnsupportedAppUsage getUpdateService()625 public static IWebViewUpdateService getUpdateService() { 626 if (isWebViewSupported()) { 627 return getUpdateServiceUnchecked(); 628 } else { 629 return null; 630 } 631 } 632 633 /** @hide */ getUpdateServiceUnchecked()634 static IWebViewUpdateService getUpdateServiceUnchecked() { 635 return IWebViewUpdateService.Stub.asInterface( 636 ServiceManager.getService(WEBVIEW_UPDATE_SERVICE_NAME)); 637 } 638 } 639