Simplify WebView RELRO creation and handle more cases.

Instead of having the system server search for the absolute path to the
WebView's native .so file, simply pass the package name and library
filename to the RELRO creation process. The RELRO creation process can
then request a classloader that corresponds to that package, and use
that classloader to let the system search for the library itself using
the standard platform library search path logic.

This significantly simplifies the WebView code, but more importantly
enables the library to be found even if it's not actually present in the
main WebView APK and is instead stored in a shared library APK: our
previous code was never updated to handle this new case when the
platform introduced it.

As a side effect of no longer searching for the library, we also no
longer discover the size of the library, and thus cannot use the size to
calculate the amount of address space to reserve. This has been replaced
with a fixed size: 100MB for 32-bit processes (the previous default size
for when the size had not yet been calculated), and 1GB for 64-bit
processes. We do not anticipate WebView ever needing more than 100MB of
virtual address space for its native library on 32-bit platforms; it
currently uses about 44MB.

The unit tests covering the complex library searching logic have been
removed, as the functionality they are testing no longer exists.

Bug: 110790153
Test: WebView-related CTS and GTS tests
Change-Id: Icc7bcd0a2b33f4dbf26d0d663e098c9e207281a5
diff --git a/api/system-current.txt b/api/system-current.txt
index 6a00815..161d5cf 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6708,7 +6708,6 @@
     method public static android.content.pm.PackageInfo getLoadedPackageInfo();
     method public static int loadWebViewNativeLibraryFromPackage(java.lang.String, java.lang.ClassLoader);
     method public static void prepareWebViewInZygote();
-    field public static final java.lang.String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = "persist.sys.webview.vmsize";
     field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2
     field public static final int LIBLOAD_FAILED_JNI_CALL = 7; // 0x7
     field public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; // 0x4
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index e0ccda9..cc0cf02 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -50,9 +50,6 @@
 
     private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create";
 
-    public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY =
-            "persist.sys.webview.vmsize";
-
     private static final String LOGTAG = "WebViewFactory";
 
     private static final boolean DEBUG = false;
diff --git a/core/java/android/webkit/WebViewLibraryLoader.java b/core/java/android/webkit/WebViewLibraryLoader.java
index cabba06..5a6aeba 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 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 @@
             "/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 @@
             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 @@
     /**
      * 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 @@
         };
 
         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 @@
      * 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 @@
         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);
 }
diff --git a/core/tests/webkit/Android.mk b/core/tests/webkit/Android.mk
deleted file mode 100644
index 45f6957..0000000
--- a/core/tests/webkit/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-
-# Include all test java files.
-LOCAL_SRC_FILES := \
-	$(call all-java-files-under, unit_tests_src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-	android-support-test
-
-LOCAL_PACKAGE_NAME := WebViewLoadingTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_REQUIRED_MODULES := \
-	WebViewLoadingOnDiskTestApk \
-	WebViewLoadingFromApkTestApk
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/webkit/AndroidManifest.xml b/core/tests/webkit/AndroidManifest.xml
deleted file mode 100644
index 42accdf..0000000
--- a/core/tests/webkit/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.webkit.tests"
-          android:sharedUserId="android.uid.system">
-
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation
-            android:name="android.support.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.webkit.tests"
-            android:label="Frameworks WebView Loader Tests" />
-
-</manifest>
diff --git a/core/tests/webkit/AndroidTest.xml b/core/tests/webkit/AndroidTest.xml
deleted file mode 100644
index 4c50b7d..0000000
--- a/core/tests/webkit/AndroidTest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs Frameworks WebView Loading Tests.">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-instrumentation" />
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="test-file-name" value="WebViewLoadingTests.apk" />
-        <option name="test-file-name" value="WebViewLoadingOnDiskTestApk.apk" />
-        <option name="test-file-name" value="WebViewLoadingFromApkTestApk.apk" />
-        <option name="cleanup-apks" value="true" />
-        <option name="alt-dir" value="out" />
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.webkit.tests" />
-    </test>
-</configuration>
diff --git a/core/tests/webkit/OWNERS b/core/tests/webkit/OWNERS
deleted file mode 100644
index 00e540a..0000000
--- a/core/tests/webkit/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-changwan@google.com
-tobiasjs@google.com
-torne@google.com
diff --git a/core/tests/webkit/apk_with_native_libs/Android.mk b/core/tests/webkit/apk_with_native_libs/Android.mk
deleted file mode 100644
index e18a7e0..0000000
--- a/core/tests/webkit/apk_with_native_libs/Android.mk
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-MY_PATH := $(LOCAL_PATH)
-
-# Set shared variables
-MY_MODULE_TAGS := optional
-MY_JNI_SHARED_LIBRARIES := libwebviewtest_jni
-MY_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-MY_SRC_FILES := $(call all-java-files-under, src)
-MY_CFLAGS := -Wall -Werror
-MY_SDK_VERSION := system_current
-MY_PROGUARD_ENABLED := disabled
-MY_MULTILIB := both
-
-# Recurse down the file tree.
-include $(call all-subdir-makefiles)
-
-
-
-# Builds an apk containing native libraries that will be unzipped on the device.
-include $(CLEAR_VARS)
-
-LOCAL_PATH := $(MY_PATH)
-LOCAL_PACKAGE_NAME := WebViewLoadingOnDiskTestApk
-LOCAL_MANIFEST_FILE := ondisk/AndroidManifest.xml
-
-LOCAL_MODULE_TAGS := $(MY_MODULE_TAGS)
-LOCAL_JNI_SHARED_LIBRARIES := $(MY_JNI_SHARED_LIBRARIES)
-LOCAL_MODULE_PATH := $(MY_MODULE_PATH)
-LOCAL_SRC_FILES := $(MY_SRC_FILES)
-LOCAL_CFLAGS := $(MY_CFLAGS)
-LOCAL_SDK_VERSION := $(MY_SDK_VERSION)
-LOCAL_PROGUARD_ENABLED := $(MY_PROGUARD_ENABLED)
-LOCAL_MULTILIB := $(MY_MULTILIB)
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
-
-# Builds an apk containing uncompressed native libraries that have to be
-# accessed through the APK itself on the device.
-include $(CLEAR_VARS)
-
-LOCAL_PATH := $(MY_PATH)
-LOCAL_PACKAGE_NAME := WebViewLoadingFromApkTestApk
-LOCAL_MANIFEST_FILE := inapk/AndroidManifest.xml
-
-LOCAL_MODULE_TAGS := $(MY_MODULE_TAGS)
-LOCAL_JNI_SHARED_LIBRARIES := $(MY_JNI_SHARED_LIBRARIES)
-LOCAL_MODULE_PATH := $(MY_MODULE_PATH)
-LOCAL_SRC_FILES := $(MY_SRC_FILES)
-LOCAL_CFLAGS := $(MY_CFLAGS)
-LOCAL_SDK_VERSION := $(MY_SDK_VERSION)
-LOCAL_PROGUARD_ENABLED := $(MY_PROGUARD_ENABLED)
-LOCAL_MULTILIB := $(MY_MULTILIB)
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml b/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml
deleted file mode 100644
index 868b238..0000000
--- a/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.webviewloading_test_from_apk"
-    android:versionCode="1"
-    android:versionName="0.0.0.1">
-
-    <application android:label="WebView Loading Test APK"
-      android:multiArch="true"
-      android:extractNativeLibs="false">
-        <meta-data android:name="com.android.webview.WebViewLibrary"
-            android:value="libwebviewtest_jni.so" />
-    </application>
-</manifest>
diff --git a/core/tests/webkit/apk_with_native_libs/jni/Android.mk b/core/tests/webkit/apk_with_native_libs/jni/Android.mk
deleted file mode 100644
index fd5b5eb..0000000
--- a/core/tests/webkit/apk_with_native_libs/jni/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libwebviewtest_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := WebViewTestJniOnLoad.cpp
-
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_MULTILIB := both
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp b/core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp
deleted file mode 100644
index 0ced4ee..0000000
--- a/core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <jni.h>
-
-jint JNI_OnLoad(JavaVM * /*vm*/, void * /*reserved*/) {
-    return JNI_VERSION_1_4;
-}
diff --git a/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml b/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml
deleted file mode 100644
index ffffeb8..0000000
--- a/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.webviewloading_test_on_disk"
-    android:versionCode="1"
-    android:versionName="0.0.0.1">
-
-    <application android:label="WebView Loading Test APK"
-      android:multiArch="true">
-        <meta-data android:name="com.android.webview.WebViewLibrary"
-            android:value="libwebviewtest_jni.so" />
-    </application>
-</manifest>
diff --git a/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java b/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java
deleted file mode 100644
index 0efa4b4..0000000
--- a/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package com.android.webview.chromium;
-
-/**
- * An empty class for testing purposes.
- */
-public class WebViewLoadingTestClass {
-}
diff --git a/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java b/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java
deleted file mode 100644
index e2f2d37..0000000
--- a/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.Log;
-
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.InstrumentationRegistry;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Unit tests for {@link WebViewLibraryLoader}.
- * Use the following command to run these tests:
- * make WebViewLoadingTests \
- * && adb install -r -d \
- * ${ANDROID_PRODUCT_OUT}/data/app/WebViewLoadingTests/WebViewLoadingTests.apk \
- * && adb shell am instrument -e class 'android.webkit.WebViewLibraryLoaderTest' -w \
- * 'com.android.webkit.tests/android.support.test.runner.AndroidJUnitRunner'
- */
-@RunWith(AndroidJUnit4.class)
-public final class WebViewLibraryLoaderTest {
-    private static final String WEBVIEW_LIBS_ON_DISK_TEST_APK =
-            "com.android.webviewloading_test_on_disk";
-    private static final String WEBVIEW_LIBS_IN_APK_TEST_APK =
-            "com.android.webviewloading_test_from_apk";
-    private static final String WEBVIEW_LOADING_TEST_NATIVE_LIB = "libwebviewtest_jni.so";
-
-    private PackageInfo webviewOnDiskPackageInfo;
-    private PackageInfo webviewFromApkPackageInfo;
-
-    @Before public void setUp() throws PackageManager.NameNotFoundException {
-        PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
-        webviewOnDiskPackageInfo =
-                pm.getPackageInfo(WEBVIEW_LIBS_ON_DISK_TEST_APK, PackageManager.GET_META_DATA);
-        webviewFromApkPackageInfo =
-                pm.getPackageInfo(WEBVIEW_LIBS_IN_APK_TEST_APK, PackageManager.GET_META_DATA);
-    }
-
-    private static boolean is64BitDevice() {
-        return Build.SUPPORTED_64_BIT_ABIS.length > 0;
-    }
-
-    // We test the getWebViewNativeLibraryDirectory method here because it handled several different
-    // cases/combinations and it seems unnecessary to create one test-apk for each such combination
-    // and arch.
-
-    /**
-     * Ensure we fetch the correct native library directories in the multi-arch case where
-     * the primary ABI is 64-bit.
-     */
-    @SmallTest
-    @Test public void testGetWebViewLibDirMultiArchPrimary64bit() {
-        final String nativeLib = "nativeLib";
-        final String secondaryNativeLib = "secondaryNativeLib";
-        PackageInfo packageInfo = new PackageInfo();
-        ApplicationInfo ai = new ApplicationInfoBuilder().
-                // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP
-                setPrimaryCpuAbi("arm64-v8a").
-                setNativeLibraryDir(nativeLib).
-                setSecondaryCpuAbi("armeabi").
-                setSecondaryNativeLibraryDir(secondaryNativeLib).
-                create();
-        packageInfo.applicationInfo = ai;
-        String actual32Lib =
-                WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, false /* is64bit */);
-        String actual64Lib =
-                WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, true /* is64bit */);
-        assertEquals(nativeLib, actual64Lib);
-        assertEquals(secondaryNativeLib, actual32Lib);
-    }
-
-    /**
-     * Ensure we fetch the correct native library directory in the 64-bit single-arch case.
-     */
-    @SmallTest
-    @Test public void testGetWebViewLibDirSingleArch64bit() {
-        final String nativeLib = "nativeLib";
-        PackageInfo packageInfo = new PackageInfo();
-        ApplicationInfo ai = new ApplicationInfoBuilder().
-                // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP
-                setPrimaryCpuAbi("arm64-v8a").
-                setNativeLibraryDir(nativeLib).
-                create();
-        packageInfo.applicationInfo = ai;
-        String actual64Lib =
-                WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, true /* is64bit */);
-        assertEquals(nativeLib, actual64Lib);
-    }
-
-    /**
-     * Ensure we fetch the correct native library directory in the 32-bit single-arch case.
-     */
-    @SmallTest
-    @Test public void testGetWebViewLibDirSingleArch32bit() {
-        final String nativeLib = "nativeLib";
-        PackageInfo packageInfo = new PackageInfo();
-        ApplicationInfo ai = new ApplicationInfoBuilder().
-                // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP
-                setPrimaryCpuAbi("armeabi-v7a").
-                setNativeLibraryDir(nativeLib).
-                create();
-        packageInfo.applicationInfo = ai;
-        String actual32Lib =
-                WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, false /* is64bit */);
-        assertEquals(nativeLib, actual32Lib);
-    }
-
-    /**
-     * Ensure we fetch the correct 32-bit library path from an APK with 32-bit and 64-bit
-     * libraries unzipped onto disk.
-     */
-    @MediumTest
-    @Test public void testGetWebViewLibraryPathOnDisk32Bit()
-            throws WebViewFactory.MissingWebViewPackageException {
-        WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewOnDiskPackageInfo, false /* is64bit */);
-        String expectedLibaryDirectory = is64BitDevice() ?
-                webviewOnDiskPackageInfo.applicationInfo.secondaryNativeLibraryDir :
-                webviewOnDiskPackageInfo.applicationInfo.nativeLibraryDir;
-        String lib32Path = expectedLibaryDirectory + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB;
-        assertEquals("Fetched incorrect 32-bit path from WebView library.",
-                lib32Path, actualNativeLib.path);
-    }
-
-    /**
-     * Ensure we fetch the correct 64-bit library path from an APK with 32-bit and 64-bit
-     * libraries unzipped onto disk.
-     */
-    @MediumTest
-    @Test public void testGetWebViewLibraryPathOnDisk64Bit()
-            throws WebViewFactory.MissingWebViewPackageException {
-        // A 32-bit device will not unpack 64-bit libraries.
-        if (!is64BitDevice()) return;
-
-        WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewOnDiskPackageInfo, true /* is64bit */);
-        String lib64Path = webviewOnDiskPackageInfo.applicationInfo.nativeLibraryDir
-                + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB;
-        assertEquals("Fetched incorrect 64-bit path from WebView library.",
-                lib64Path, actualNativeLib.path);
-    }
-
-    /**
-     * Check the size of the 32-bit library fetched from an APK with both 32-bit and 64-bit
-     * libraries unzipped onto disk.
-     */
-    @MediumTest
-    @Test public void testGetWebView32BitLibrarySizeOnDiskIsNonZero()
-            throws WebViewFactory.MissingWebViewPackageException {
-        WebViewLibraryLoader.WebViewNativeLibrary actual32BitNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewOnDiskPackageInfo, false /* is64bit */);
-        assertTrue(actual32BitNativeLib.size > 0);
-    }
-
-    /**
-     * Check the size of the 64-bit library fetched from an APK with both 32-bit and 64-bit
-     * libraries unzipped onto disk.
-     */
-    @MediumTest
-    @Test public void testGetWebView64BitLibrarySizeOnDiskIsNonZero()
-            throws WebViewFactory.MissingWebViewPackageException {
-        // A 32-bit device will not unpack 64-bit libraries.
-        if (!is64BitDevice()) return;
-        WebViewLibraryLoader.WebViewNativeLibrary actual64BitNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewOnDiskPackageInfo, true /* is64bit */);
-        assertTrue(actual64BitNativeLib.size > 0);
-    }
-
-    /**
-     * Ensure we fetch the correct 32-bit library path from an APK with both 32-bit and 64-bit
-     * libraries stored uncompressed in the APK.
-     */
-    @MediumTest
-    @Test public void testGetWebView32BitLibraryPathFromApk()
-            throws WebViewFactory.MissingWebViewPackageException, IOException {
-        WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewFromApkPackageInfo, false /* is64bit */);
-        // The device might have ignored the app's request to not extract native libs, so first
-        // check whether the library paths match those of extracted libraries.
-        String expectedLibaryDirectory = is64BitDevice() ?
-                webviewFromApkPackageInfo.applicationInfo.secondaryNativeLibraryDir :
-                webviewFromApkPackageInfo.applicationInfo.nativeLibraryDir;
-        String lib32Path = expectedLibaryDirectory + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB;
-        if (lib32Path.equals(actualNativeLib.path)) {
-            // If the libraries were extracted to disk, ensure that they're actually there.
-            assertTrue("The given WebView library doesn't exist.",
-                    new File(actualNativeLib.path).exists());
-        } else { // The libraries were not extracted to disk.
-            assertIsValidZipEntryPath(actualNativeLib.path,
-                    webviewFromApkPackageInfo.applicationInfo.sourceDir);
-        }
-    }
-
-    /**
-     * Ensure we fetch the correct 32-bit library path from an APK with both 32-bit and 64-bit
-     * libraries stored uncompressed in the APK.
-     */
-    @MediumTest
-    @Test public void testGetWebView64BitLibraryPathFromApk()
-            throws WebViewFactory.MissingWebViewPackageException, IOException {
-        // A 32-bit device will not unpack 64-bit libraries.
-        if (!is64BitDevice()) return;
-
-        WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewFromApkPackageInfo, true /* is64bit */);
-        assertIsValidZipEntryPath(actualNativeLib.path,
-                webviewFromApkPackageInfo.applicationInfo.sourceDir);
-    }
-
-    private static void assertIsValidZipEntryPath(String path, String zipFilePath)
-            throws IOException {
-        assertTrue("The path to a zip entry must start with the path to the zip file itself."
-            + "Expected zip path: " + zipFilePath + ", actual zip entry: " + path,
-            path.startsWith(zipFilePath + "!/"));
-        String[] pathSplit = path.split("!/");
-        assertEquals("A zip file path should have two parts, the zip path, and the zip entry path.",
-                2, pathSplit.length);
-        ZipFile zipFile = new ZipFile(pathSplit[0]);
-        assertNotNull("Path doesn't point to a valid zip entry: " + path,
-                zipFile.getEntry(pathSplit[1]));
-    }
-
-
-    /**
-     * Check the size of the 32-bit library fetched from an APK with both 32-bit and 64-bit
-     * libraries stored uncompressed in the APK.
-     */
-    @MediumTest
-    @Test public void testGetWebView32BitLibrarySizeFromApkIsNonZero()
-            throws WebViewFactory.MissingWebViewPackageException {
-        WebViewLibraryLoader.WebViewNativeLibrary actual32BitNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewFromApkPackageInfo, false /* is64bit */);
-        assertTrue(actual32BitNativeLib.size > 0);
-    }
-
-    /**
-     * Check the size of the 64-bit library fetched from an APK with both 32-bit and 64-bit
-     * libraries stored uncompressed in the APK.
-     */
-    @MediumTest
-    @Test public void testGetWebView64BitLibrarySizeFromApkIsNonZero()
-            throws WebViewFactory.MissingWebViewPackageException {
-        // A 32-bit device will not unpack 64-bit libraries.
-        if (!is64BitDevice()) return;
-
-        WebViewLibraryLoader.WebViewNativeLibrary actual64BitNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewFromApkPackageInfo, true /* is64bit */);
-        assertTrue(actual64BitNativeLib.size > 0);
-    }
-
-    private static class ApplicationInfoBuilder {
-        ApplicationInfo ai;
-
-        public ApplicationInfoBuilder setPrimaryCpuAbi(String primaryCpuAbi) {
-            ai.primaryCpuAbi = primaryCpuAbi;
-            return this;
-        }
-
-        public ApplicationInfoBuilder setSecondaryCpuAbi(String secondaryCpuAbi) {
-            ai.secondaryCpuAbi = secondaryCpuAbi;
-            return this;
-        }
-
-        public ApplicationInfoBuilder setNativeLibraryDir(String nativeLibraryDir) {
-            ai.nativeLibraryDir = nativeLibraryDir;
-            return this;
-        }
-
-        public ApplicationInfoBuilder setSecondaryNativeLibraryDir(
-                String secondaryNativeLibraryDir) {
-            ai.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
-            return this;
-        }
-
-        public ApplicationInfoBuilder setMetaData(Bundle metaData) {
-            ai.metaData = metaData;
-            return this;
-        }
-
-        public ApplicationInfoBuilder() {
-            ai = new android.content.pm.ApplicationInfo();
-        }
-
-        public ApplicationInfo create() {
-            return ai;
-        }
-    }
-}
diff --git a/native/webview/loader/loader.cpp b/native/webview/loader/loader.cpp
index adb371d..fee2a25 100644
--- a/native/webview/loader/loader.cpp
+++ b/native/webview/loader/loader.cpp
@@ -64,7 +64,8 @@
   return JNI_TRUE;
 }
 
-jboolean DoCreateRelroFile(const char* lib, const char* relro) {
+jboolean DoCreateRelroFile(JNIEnv* env, const char* lib, const char* relro,
+                           jobject clazzLoader) {
   // Try to unlink the old file, since if this is being called, the old one is
   // obsolete.
   if (unlink(relro) != 0 && errno != ENOENT) {
@@ -82,11 +83,19 @@
     ALOGE("Failed to create temporary file %s: %s", relro_tmp, strerror(errno));
     return JNI_FALSE;
   }
+  android_namespace_t* ns =
+      android::FindNamespaceByClassLoader(env, clazzLoader);
+  if (ns == NULL) {
+    ALOGE("Failed to find classloader namespace");
+    return JNI_FALSE;
+  }
   android_dlextinfo extinfo;
-  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO;
+  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO |
+                  ANDROID_DLEXT_USE_NAMESPACE;
   extinfo.reserved_addr = gReservedAddress;
   extinfo.reserved_size = gReservedSize;
   extinfo.relro_fd = tmp_fd;
+  extinfo.library_namespace = ns;
   void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo);
   int close_result = close(tmp_fd);
   if (handle == NULL) {
@@ -143,13 +152,14 @@
   return DoReserveAddressSpace(size);
 }
 
-jboolean CreateRelroFile(JNIEnv* env, jclass, jstring lib, jstring relro) {
+jboolean CreateRelroFile(JNIEnv* env, jclass, jstring lib, jstring relro,
+                         jobject clazzLoader) {
   jboolean ret = JNI_FALSE;
   const char* lib_utf8 = env->GetStringUTFChars(lib, NULL);
   if (lib_utf8 != NULL) {
     const char* relro_utf8 = env->GetStringUTFChars(relro, NULL);
     if (relro_utf8 != NULL) {
-      ret = DoCreateRelroFile(lib_utf8, relro_utf8);
+      ret = DoCreateRelroFile(env, lib_utf8, relro_utf8, clazzLoader);
       env->ReleaseStringUTFChars(relro, relro_utf8);
     }
     env->ReleaseStringUTFChars(lib, lib_utf8);
@@ -179,7 +189,7 @@
   { "nativeReserveAddressSpace", "(J)Z",
       reinterpret_cast<void*>(ReserveAddressSpace) },
   { "nativeCreateRelroFile",
-      "(Ljava/lang/String;Ljava/lang/String;)Z",
+      "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)Z",
       reinterpret_cast<void*>(CreateRelroFile) },
   { "nativeLoadWithRelroFile",
       "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)I",