diff options
| -rw-r--r-- | core/java/android/webkit/WebViewZygote.java | 56 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/WebViewZygoteInit.java | 47 |
2 files changed, 69 insertions, 34 deletions
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index 3a1c4576ab3e..de1f3df61462 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -150,6 +150,7 @@ public class WebViewZygote { } try { + String abi = sPackage.applicationInfo.primaryCpuAbi; sZygote = Process.ZYGOTE_PROCESS.startChildZygote( "com.android.internal.os.WebViewZygoteInit", "webview_zygote", @@ -158,39 +159,40 @@ public class WebViewZygote { null, // gids 0, // runtimeFlags "webview_zygote", // seInfo - sPackage.applicationInfo.primaryCpuAbi, // abi + abi, // abi TextUtils.join(",", Build.SUPPORTED_ABIS), null, // instructionSet Process.FIRST_ISOLATED_UID, Process.LAST_ISOLATED_UID); - - // All the work below is usually done by LoadedApk, but the zygote can't talk to - // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so - // doesn't have an ActivityThread and can't use Binder. - // Instead, figure out the paths here, in the system server where we have access to - // the package manager. Reuse the logic from LoadedApk to determine the correct - // paths and pass them to the zygote as strings. - final List<String> zipPaths = new ArrayList<>(10); - final List<String> libPaths = new ArrayList<>(10); - LoadedApk.makePaths(null, false, sPackage.applicationInfo, zipPaths, libPaths); - final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); - final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : - TextUtils.join(File.pathSeparator, zipPaths); - - String libFileName = WebViewFactory.getWebViewLibrary(sPackage.applicationInfo); - - // In the case where the ApplicationInfo has been modified by the stub WebView, - // we need to use the original ApplicationInfo to determine what the original classpath - // would have been to use as a cache key. - LoadedApk.makePaths(null, false, sPackageOriginalAppInfo, zipPaths, null); - final String cacheKey = (zipPaths.size() == 1) ? zipPaths.get(0) : - TextUtils.join(File.pathSeparator, zipPaths); - ZygoteProcess.waitForConnectionToZygote(sZygote.getPrimarySocketAddress()); - Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath); - sZygote.preloadPackageForAbi(zip, librarySearchPath, libFileName, cacheKey, - Build.SUPPORTED_ABIS[0]); + if (sPackageOriginalAppInfo.sourceDir.equals(sPackage.applicationInfo.sourceDir)) { + // No stub WebView is involved here, so we can preload the package the "clean" way + // using the ApplicationInfo. + sZygote.preloadApp(sPackage.applicationInfo, abi); + } else { + // Legacy path to support the stub WebView. + // Reuse the logic from LoadedApk to determine the correct paths and pass them to + // the zygote as strings. + final List<String> zipPaths = new ArrayList<>(10); + final List<String> libPaths = new ArrayList<>(10); + LoadedApk.makePaths(null, false, sPackage.applicationInfo, zipPaths, libPaths); + final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); + final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : + TextUtils.join(File.pathSeparator, zipPaths); + + String libFileName = WebViewFactory.getWebViewLibrary(sPackage.applicationInfo); + + // Use the original ApplicationInfo to determine what the original classpath would + // have been to use as a cache key. + LoadedApk.makePaths(null, false, sPackageOriginalAppInfo, zipPaths, null); + final String cacheKey = (zipPaths.size() == 1) ? zipPaths.get(0) : + TextUtils.join(File.pathSeparator, zipPaths); + + Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath); + sZygote.preloadPackageForAbi(zip, librarySearchPath, libFileName, cacheKey, + Build.SUPPORTED_ABIS[0]); + } } catch (Exception e) { Log.e(LOGTAG, "Error connecting to webview zygote", e); stopZygoteLocked(); diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java index 0b329d70f7af..c8d30b27d4dc 100644 --- a/core/java/com/android/internal/os/WebViewZygoteInit.java +++ b/core/java/com/android/internal/os/WebViewZygoteInit.java @@ -17,8 +17,9 @@ package com.android.internal.os; import android.app.ApplicationLoaders; +import android.app.LoadedApk; +import android.content.pm.ApplicationInfo; import android.net.LocalSocket; -import android.os.Build; import android.text.TextUtils; import android.util.Log; import android.webkit.WebViewFactory; @@ -66,6 +67,34 @@ class WebViewZygoteInit { } @Override + protected boolean canPreloadApp() { + return true; + } + + @Override + protected void handlePreloadApp(ApplicationInfo appInfo) { + Log.i(TAG, "Beginning application preload for " + appInfo.packageName); + LoadedApk loadedApk = new LoadedApk(null, appInfo, null, null, false, true, false); + ClassLoader loader = loadedApk.getClassLoader(); + doPreload(loader, WebViewFactory.getWebViewLibrary(appInfo)); + + // Add the APK to the Zygote's list of allowed files for children. + Zygote.nativeAllowFileAcrossFork(appInfo.sourceDir); + if (appInfo.splitSourceDirs != null) { + for (String path : appInfo.splitSourceDirs) { + Zygote.nativeAllowFileAcrossFork(path); + } + } + if (appInfo.sharedLibraryFiles != null) { + for (String path : appInfo.sharedLibraryFiles) { + Zygote.nativeAllowFileAcrossFork(path); + } + } + + Log.i(TAG, "Application preload done"); + } + + @Override protected void handlePreloadPackage(String packagePath, String libsPath, String libFileName, String cacheKey) { Log.i(TAG, "Beginning package preload"); @@ -76,16 +105,22 @@ class WebViewZygoteInit { ClassLoader loader = ApplicationLoaders.getDefault().createAndCacheWebViewClassLoader( packagePath, libsPath, cacheKey); - // Load the native library using WebViewLibraryLoader to share the RELRO data with other - // processes. - WebViewLibraryLoader.loadNativeLibrary(loader, libFileName); - // Add the APK to the Zygote's list of allowed files for children. String[] packageList = TextUtils.split(packagePath, File.pathSeparator); for (String packageEntry : packageList) { Zygote.nativeAllowFileAcrossFork(packageEntry); } + doPreload(loader, libFileName); + + Log.i(TAG, "Package preload done"); + } + + private void doPreload(ClassLoader loader, String libFileName) { + // Load the native library using WebViewLibraryLoader to share the RELRO data with other + // processes. + WebViewLibraryLoader.loadNativeLibrary(loader, libFileName); + // Once we have the classloader, look up the WebViewFactoryProvider implementation and // call preloadInZygote() on it to give it the opportunity to preload the native library // and perform any other initialisation work that should be shared among the children. @@ -114,8 +149,6 @@ class WebViewZygoteInit { } catch (IOException ioe) { throw new IllegalStateException("Error writing to command socket", ioe); } - - Log.i(TAG, "Package preload done"); } } |