summaryrefslogtreecommitdiff
path: root/core/java/android/webkit/WebViewLibraryLoader.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/webkit/WebViewLibraryLoader.java')
-rw-r--r--core/java/android/webkit/WebViewLibraryLoader.java218
1 files changed, 43 insertions, 175 deletions
diff --git a/core/java/android/webkit/WebViewLibraryLoader.java b/core/java/android/webkit/WebViewLibraryLoader.java
index cabba06bdff5..5a6aebaaad51 100644
--- a/core/java/android/webkit/WebViewLibraryLoader.java
+++ b/core/java/android/webkit/WebViewLibraryLoader.java
@@ -17,15 +17,14 @@
package android.webkit;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
-import android.content.pm.ApplicationInfo;
+import android.app.ActivityThread;
+import android.app.LoadedApk;
+import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -33,11 +32,7 @@ import com.android.server.LocalServices;
import dalvik.system.VMRuntime;
-import java.io.File;
-import java.io.IOException;
import java.util.Arrays;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
/**
* @hide
@@ -50,7 +45,6 @@ public class WebViewLibraryLoader {
"/data/misc/shared_relro/libwebviewchromium32.relro";
private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
"/data/misc/shared_relro/libwebviewchromium64.relro";
- private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024;
private static final boolean DEBUG = false;
@@ -69,18 +63,26 @@ public class WebViewLibraryLoader {
boolean result = false;
boolean is64Bit = VMRuntime.getRuntime().is64Bit();
try {
- if (args.length != 1 || args[0] == null) {
+ if (args.length != 2 || args[0] == null || args[1] == null) {
Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args));
return;
}
- Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), lib: " + args[0]);
+ String packageName = args[0];
+ String libraryFileName = args[1];
+ Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), package: "
+ + packageName + " library: " + libraryFileName);
if (!sAddressSpaceReserved) {
Log.e(LOGTAG, "can't create relro file; address space not reserved");
return;
}
- result = nativeCreateRelroFile(args[0] /* path */,
+ LoadedApk apk = ActivityThread.currentActivityThread().getPackageInfo(
+ packageName,
+ null,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ result = nativeCreateRelroFile(libraryFileName,
is64Bit ? CHROMIUM_WEBVIEW_NATIVE_RELRO_64 :
- CHROMIUM_WEBVIEW_NATIVE_RELRO_32);
+ CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
+ apk.getClassLoader());
if (result && DEBUG) Log.v(LOGTAG, "created relro file");
} finally {
// We must do our best to always notify the update service, even if something fails.
@@ -101,7 +103,8 @@ public class WebViewLibraryLoader {
/**
* Create a single relro file by invoking an isolated process that to do the actual work.
*/
- static void createRelroFile(final boolean is64Bit, @NonNull WebViewNativeLibrary nativeLib) {
+ static void createRelroFile(final boolean is64Bit, @NonNull String packageName,
+ @NonNull String libraryFileName) {
final String abi =
is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
@@ -119,13 +122,10 @@ public class WebViewLibraryLoader {
};
try {
- if (nativeLib == null || nativeLib.path == null) {
- throw new IllegalArgumentException(
- "Native library paths to the WebView RelRo process must not be null!");
- }
boolean success = LocalServices.getService(ActivityManagerInternal.class)
.startIsolatedProcess(
- RelroFileCreator.class.getName(), new String[] { nativeLib.path },
+ RelroFileCreator.class.getName(),
+ new String[] { packageName, libraryFileName },
"WebViewLoader-" + abi, abi, Process.SHARED_RELRO_UID, crashHandler);
if (!success) throw new Exception("Failed to start the relro file creator process");
} catch (Throwable t) {
@@ -140,83 +140,50 @@ public class WebViewLibraryLoader {
* be called whenever we change WebView provider.
* @return the number of relro processes started.
*/
- static int prepareNativeLibraries(PackageInfo webviewPackageInfo)
- throws WebViewFactory.MissingWebViewPackageException {
- WebViewNativeLibrary nativeLib32bit =
- getWebViewNativeLibrary(webviewPackageInfo, false /* is64bit */);
- WebViewNativeLibrary nativeLib64bit =
- getWebViewNativeLibrary(webviewPackageInfo, true /* is64bit */);
- updateWebViewZygoteVmSize(nativeLib32bit, nativeLib64bit);
-
- return createRelros(nativeLib32bit, nativeLib64bit);
+ static int prepareNativeLibraries(@NonNull PackageInfo webViewPackageInfo) {
+ // TODO(torne): new way of calculating VM size
+ // updateWebViewZygoteVmSize(nativeLib32bit, nativeLib64bit);
+ String libraryFileName = WebViewFactory.getWebViewLibrary(
+ webViewPackageInfo.applicationInfo);
+ if (libraryFileName == null) {
+ // Can't do anything with no filename, don't spawn any processes.
+ return 0;
+ }
+ return createRelros(webViewPackageInfo.packageName, libraryFileName);
}
/**
* @return the number of relro processes started.
*/
- private static int createRelros(@Nullable WebViewNativeLibrary nativeLib32bit,
- @Nullable WebViewNativeLibrary nativeLib64bit) {
+ private static int createRelros(@NonNull String packageName, @NonNull String libraryFileName) {
if (DEBUG) Log.v(LOGTAG, "creating relro files");
int numRelros = 0;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
- if (nativeLib32bit == null) {
- Log.e(LOGTAG, "No 32-bit WebView library path, skipping relro creation.");
- } else {
- if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
- createRelroFile(false /* is64Bit */, nativeLib32bit);
- numRelros++;
- }
+ if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
+ createRelroFile(false /* is64Bit */, packageName, libraryFileName);
+ numRelros++;
}
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
- if (nativeLib64bit == null) {
- Log.e(LOGTAG, "No 64-bit WebView library path, skipping relro creation.");
- } else {
- if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
- createRelroFile(true /* is64Bit */, nativeLib64bit);
- numRelros++;
- }
+ if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
+ createRelroFile(true /* is64Bit */, packageName, libraryFileName);
+ numRelros++;
}
return numRelros;
}
/**
- *
- * @return the native WebView libraries in the new WebView APK.
- */
- private static void updateWebViewZygoteVmSize(
- @Nullable WebViewNativeLibrary nativeLib32bit,
- @Nullable WebViewNativeLibrary nativeLib64bit)
- throws WebViewFactory.MissingWebViewPackageException {
- // Find the native libraries of the new WebView package, to change the size of the
- // memory region in the Zygote reserved for the library.
- long newVmSize = 0L;
-
- if (nativeLib32bit != null) newVmSize = Math.max(newVmSize, nativeLib32bit.size);
- if (nativeLib64bit != null) newVmSize = Math.max(newVmSize, nativeLib64bit.size);
-
- if (DEBUG) {
- Log.v(LOGTAG, "Based on library size, need " + newVmSize
- + " bytes of address space.");
- }
- // The required memory can be larger than the file on disk (due to .bss), and an
- // upgraded version of the library will likely be larger, so always attempt to
- // reserve twice as much as we think to allow for the library to grow during this
- // boot cycle.
- newVmSize = Math.max(2 * newVmSize, CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
- Log.d(LOGTAG, "Setting new address space to " + newVmSize);
- setWebViewZygoteVmSize(newVmSize);
- }
-
- /**
* Reserve space for the native library to be loaded into.
*/
static void reserveAddressSpaceInZygote() {
System.loadLibrary("webviewchromium_loader");
- long addressSpaceToReserve =
- SystemProperties.getLong(WebViewFactory.CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
- CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
+ boolean is64Bit = VMRuntime.getRuntime().is64Bit();
+ // On 64-bit address space is really cheap and we can reserve 1GB which is plenty.
+ // On 32-bit it's fairly scarce and we should keep it to a realistic number that
+ // permits some future growth but doesn't hog space: we use 100MB which is more than 2x
+ // the current requirement.
+ long addressSpaceToReserve = is64Bit ? 1 * 1024 * 1024 * 1024 : 100 * 1024 * 1024;
sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
if (sAddressSpaceReserved) {
@@ -253,106 +220,7 @@ public class WebViewLibraryLoader {
return result;
}
- /**
- * Fetch WebView's native library paths from {@param packageInfo}.
- * @hide
- */
- @Nullable
- @VisibleForTesting
- public static WebViewNativeLibrary getWebViewNativeLibrary(PackageInfo packageInfo,
- boolean is64bit) throws WebViewFactory.MissingWebViewPackageException {
- ApplicationInfo ai = packageInfo.applicationInfo;
- final String nativeLibFileName = WebViewFactory.getWebViewLibrary(ai);
-
- String dir = getWebViewNativeLibraryDirectory(ai, is64bit /* 64bit */);
-
- WebViewNativeLibrary lib = findNativeLibrary(ai, nativeLibFileName,
- is64bit ? Build.SUPPORTED_64_BIT_ABIS : Build.SUPPORTED_32_BIT_ABIS, dir);
-
- if (DEBUG) {
- Log.v(LOGTAG, String.format("Native %d-bit lib: %s", is64bit ? 64 : 32, lib.path));
- }
- return lib;
- }
-
- /**
- * @return the directory of the native WebView library with bitness {@param is64bit}.
- * @hide
- */
- @VisibleForTesting
- public static String getWebViewNativeLibraryDirectory(ApplicationInfo ai, boolean is64bit) {
- // Primary arch has the same bitness as the library we are looking for.
- if (is64bit == VMRuntime.is64BitAbi(ai.primaryCpuAbi)) return ai.nativeLibraryDir;
-
- // Secondary arch has the same bitness as the library we are looking for.
- if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) {
- return ai.secondaryNativeLibraryDir;
- }
-
- return "";
- }
-
- /**
- * @return an object describing a native WebView library given the directory path of that
- * library, or null if the library couldn't be found.
- */
- @Nullable
- private static WebViewNativeLibrary findNativeLibrary(ApplicationInfo ai,
- String nativeLibFileName, String[] abiList, String libDirectory)
- throws WebViewFactory.MissingWebViewPackageException {
- if (TextUtils.isEmpty(libDirectory)) return null;
- String libPath = libDirectory + "/" + nativeLibFileName;
- File f = new File(libPath);
- if (f.exists()) {
- return new WebViewNativeLibrary(libPath, f.length());
- } else {
- return getLoadFromApkPath(ai.sourceDir, abiList, nativeLibFileName);
- }
- }
-
- /**
- * @hide
- */
- @VisibleForTesting
- public static class WebViewNativeLibrary {
- public final String path;
- public final long size;
-
- WebViewNativeLibrary(String path, long size) {
- this.path = path;
- this.size = size;
- }
- }
-
- private static WebViewNativeLibrary getLoadFromApkPath(String apkPath,
- String[] abiList,
- String nativeLibFileName)
- throws WebViewFactory.MissingWebViewPackageException {
- // Search the APK for a native library conforming to a listed ABI.
- try (ZipFile z = new ZipFile(apkPath)) {
- for (String abi : abiList) {
- final String entry = "lib/" + abi + "/" + nativeLibFileName;
- ZipEntry e = z.getEntry(entry);
- if (e != null && e.getMethod() == ZipEntry.STORED) {
- // Return a path formatted for dlopen() load from APK.
- return new WebViewNativeLibrary(apkPath + "!/" + entry, e.getSize());
- }
- }
- } catch (IOException e) {
- throw new WebViewFactory.MissingWebViewPackageException(e);
- }
- return null;
- }
-
- /**
- * Sets the size of the memory area in which to store the relro section.
- */
- private static void setWebViewZygoteVmSize(long vmSize) {
- SystemProperties.set(WebViewFactory.CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
- Long.toString(vmSize));
- }
-
static native boolean nativeReserveAddressSpace(long addressSpaceToReserve);
- static native boolean nativeCreateRelroFile(String lib, String relro);
+ static native boolean nativeCreateRelroFile(String lib, String relro, ClassLoader clazzLoader);
static native int nativeLoadWithRelroFile(String lib, String relro, ClassLoader clazzLoader);
}