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