Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57652524 authored by Ben Murdoch's avatar Ben Murdoch Committed by Android Git Automerger
Browse files

am f3fc680c: Merge changes I2f40be36,I4af9fd7e,Ib0b4245f,I55acad96,Id276b71e, ... into lmp-dev

* commit 'f3fc680ca61e0c31c924e95afe1e2ac0368994ae':
  Cherry pick Cleanup debug messages in WebViewFactory and WebViewUpdateService DO NOT MERGE
  Cherry pick Move startIsolatedProcess implementation in ActivityManagerService DO NOT MERGE
  CHerry pick Find WebView package name from a config resource. DO NOT MERGE
  Cherry pick Remove dependency on WebView native library path. DO NOT MERGE
  Cherry pick Make WebViewUpdateService a SystemService. DO NOT MERGE
  Cherry pick Refactor ActivityManagerService and make WebViewFactory more pedantic. DO NOT MERGE
  Cherry pick Refactor native library path logic in WebViewFactory DO NOT MERGE
  Cherry pick Append WebView assets to AssetManager when loading the WebView. DO NOT MERGE
  Cherry pick Introduce startIsolatedProcess private API in ActivityManager DO NOT MERGE
  Cherry pick Load the WebView Java code from an APK. DO NOT MERGE
parents ab03bfcf 798e7f5c
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -25,4 +25,6 @@ public abstract class ActivityManagerInternal {
    // Called by the power manager.
    // Called by the power manager.
    public abstract void goingToSleep();
    public abstract void goingToSleep();
    public abstract void wakingUp();
    public abstract void wakingUp();
    public abstract int startIsolatedProcess(String entryPoint, String[] mainArgs,
            String processName, String abiOverride, int uid, Runnable crashHandler);
}
}
+205 −66
Original line number Original line Diff line number Diff line
@@ -16,16 +16,26 @@


package android.webkit;
package android.webkit;


import android.app.ActivityManagerInternal;
import android.app.Application;
import android.app.AppGlobals;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Build;
import android.os.Process;
import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.StrictMode;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.AndroidRuntimeException;
import android.util.Log;
import android.util.Log;
import com.android.server.LocalServices;
import dalvik.system.VMRuntime;
import dalvik.system.VMRuntime;


import java.io.File;
import java.io.File;
import java.util.Arrays;


import com.android.internal.os.Zygote;
import com.android.internal.os.Zygote;


@@ -42,17 +52,15 @@ public final class WebViewFactory {
    private static final String NULL_WEBVIEW_FACTORY =
    private static final String NULL_WEBVIEW_FACTORY =
            "com.android.webview.nullwebview.NullWebViewFactoryProvider";
            "com.android.webview.nullwebview.NullWebViewFactoryProvider";


    // TODO(torne): we need to use a system property instead of hardcoding the library paths to
    // enable it to be changed when a webview update apk is installed.
    private static final String CHROMIUM_WEBVIEW_NATIVE_LIB_32 =
            "/system/lib/libwebviewchromium.so";
    private static final String CHROMIUM_WEBVIEW_NATIVE_LIB_64 =
            "/system/lib64/libwebviewchromium.so";
    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 =
    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 =
            "/data/misc/shared_relro/libwebviewchromium32.relro";
            "/data/misc/shared_relro/libwebviewchromium32.relro";
    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
            "/data/misc/shared_relro/libwebviewchromium64.relro";
            "/data/misc/shared_relro/libwebviewchromium64.relro";


    public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY =
            "persist.sys.webview.vmsize";
    private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024;

    private static final String LOGTAG = "WebViewFactory";
    private static final String LOGTAG = "WebViewFactory";


    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;
@@ -64,8 +72,8 @@ public final class WebViewFactory {
    private static boolean sAddressSpaceReserved = false;
    private static boolean sAddressSpaceReserved = false;


    public static String getWebViewPackageName() {
    public static String getWebViewPackageName() {
        // TODO: Make this dynamic based on resource configuration.
        return AppGlobals.getInitialApplication().getString(
        return "com.android.webview";
                com.android.internal.R.string.config_webViewPackageName);
    }
    }


    static WebViewFactoryProvider getProvider() {
    static WebViewFactoryProvider getProvider() {
@@ -99,10 +107,18 @@ public final class WebViewFactory {
    }
    }


    private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
    private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
        Application initialApplication = AppGlobals.getInitialApplication();
        try {
        try {
            return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY);
            Context webViewContext = initialApplication.createPackageContext(
        } catch (ClassNotFoundException e) {
                    getWebViewPackageName(),
            Log.e(LOGTAG, "Chromium WebView does not exist");
                    Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
            initialApplication.getAssets().addAssetPath(
                    webViewContext.getApplicationInfo().sourceDir);
            ClassLoader clazzLoader = webViewContext.getClassLoader();
            return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true,
                                                                 clazzLoader);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(LOGTAG, "Chromium WebView package does not exist");
            return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
            return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
        }
        }
    }
    }
@@ -114,81 +130,199 @@ public final class WebViewFactory {
    public static void prepareWebViewInZygote() {
    public static void prepareWebViewInZygote() {
        try {
        try {
            System.loadLibrary("webviewchromium_loader");
            System.loadLibrary("webviewchromium_loader");
            sAddressSpaceReserved = nativeReserveAddressSpace(CHROMIUM_WEBVIEW_NATIVE_LIB_32,
            long addressSpaceToReserve =
                                                              CHROMIUM_WEBVIEW_NATIVE_LIB_64);
                    SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
                    CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
            sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);

            if (sAddressSpaceReserved) {
            if (sAddressSpaceReserved) {
                if (DEBUG) Log.v(LOGTAG, "address space reserved");
                if (DEBUG) {
                    Log.v(LOGTAG, "address space reserved: " + addressSpaceToReserve + " bytes");
                }
            } else {
            } else {
                Log.e(LOGTAG, "reserving address space failed");
                Log.e(LOGTAG, "reserving " + addressSpaceToReserve +
                        " bytes of address space failed");
            }
            }
        } catch (Throwable e) {
        } catch (Throwable t) {
            // Log and discard errors at this stage as we must not crash the zygote.
            // Log and discard errors at this stage as we must not crash the zygote.
            Log.e(LOGTAG, "error preparing native loader", e);
            Log.e(LOGTAG, "error preparing native loader", t);
        }
        }
    }
    }


    /**
    /**
     * Perform any WebView loading preparations that must happen at boot from the system server,
     * Perform any WebView loading preparations that must happen at boot from the system server,
     * after the package manager has started.
     * after the package manager has started or after an update to the webview is installed.
     * This must be called in the system server.
     * This must be called in the system server.
     * Currently, this means spawning the child processes which will create the relro files.
     * Currently, this means spawning the child processes which will create the relro files.
     */
     */
    public static void prepareWebViewInSystemServer() {
    public static void prepareWebViewInSystemServer() {
        String[] nativePaths = null;
        try {
            nativePaths = getWebViewNativeLibraryPaths();
        } catch (PackageManager.NameNotFoundException e) {
        }
        prepareWebViewInSystemServer(nativePaths);
    }

    private static void prepareWebViewInSystemServer(String[] nativeLibraryPaths) {
        if (DEBUG) Log.v(LOGTAG, "creating relro files");
        if (DEBUG) Log.v(LOGTAG, "creating relro files");
        if (new File(CHROMIUM_WEBVIEW_NATIVE_LIB_64).exists()) {

            createRelroFile(Build.SUPPORTED_64_BIT_ABIS[0]);
        // We must always trigger createRelRo regardless of the value of nativeLibraryPaths. Any
        // unexpected values will be handled there to ensure that we trigger notifying any process
        // waiting on relreo creation.
        if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
            if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
            createRelroFile(false /* is64Bit */, nativeLibraryPaths);
        }

        if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
            if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
            createRelroFile(true /* is64Bit */, nativeLibraryPaths);
        }
    }

    public static void onWebViewUpdateInstalled() {
        String[] nativeLibs = null;
        try {
            nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths();
        } catch (PackageManager.NameNotFoundException e) {
        }

        if (nativeLibs != null) {
            long newVmSize = 0L;

            for (String path : nativeLibs) {
                if (DEBUG) Log.d(LOGTAG, "Checking file size of " + path);
                if (path == null) continue;
                File f = new File(path);
                if (f.exists()) {
                    long length = f.length();
                    if (length > newVmSize) {
                        newVmSize = length;
                    }
                }
            }

            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);
            SystemProperties.set(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
                    Long.toString(newVmSize));
        }
        prepareWebViewInSystemServer(nativeLibs);
    }
    }
        if (new File(CHROMIUM_WEBVIEW_NATIVE_LIB_32).exists()) {

            createRelroFile(Build.SUPPORTED_32_BIT_ABIS[0]);
    private static String[] getWebViewNativeLibraryPaths()
            throws PackageManager.NameNotFoundException {
        final String NATIVE_LIB_FILE_NAME = "libwebviewchromium.so";

        PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
        ApplicationInfo ai = pm.getApplicationInfo(getWebViewPackageName(), 0);

        String path32;
        String path64;
        boolean primaryArchIs64bit = VMRuntime.is64BitAbi(ai.primaryCpuAbi);
        if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) {
            // Multi-arch case.
            if (primaryArchIs64bit) {
                // Primary arch: 64-bit, secondary: 32-bit.
                path64 = ai.nativeLibraryDir;
                path32 = ai.secondaryNativeLibraryDir;
            } else {
                // Primary arch: 32-bit, secondary: 64-bit.
                path64 = ai.secondaryNativeLibraryDir;
                path32 = ai.nativeLibraryDir;
            }
        } else if (primaryArchIs64bit) {
            // Single-arch 64-bit.
            path64 = ai.nativeLibraryDir;
            path32 = "";
        } else {
            // Single-arch 32-bit.
            path32 = ai.nativeLibraryDir;
            path64 = "";
        }
        if (!TextUtils.isEmpty(path32)) path32 += "/" + NATIVE_LIB_FILE_NAME;
        if (!TextUtils.isEmpty(path64)) path64 += "/" + NATIVE_LIB_FILE_NAME;
        return new String[] { path32, path64 };
    }

    private static void createRelroFile(final boolean is64Bit, String[] nativeLibraryPaths) {
        final String abi =
                is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];

        // crashHandler is invoked by the ActivityManagerService when the isolated process crashes.
        Runnable crashHandler = new Runnable() {
            @Override
            public void run() {
                try {
                    Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without");
                    getUpdateService().notifyRelroCreationCompleted(is64Bit, false);
                } catch (RemoteException e) {
                    Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage());
                }
                }
            }
            }
        };


    private static void createRelroFile(String abi) {
        try {
        try {
            Process.start("android.webkit.WebViewFactory$RelroFileCreator",
            if (nativeLibraryPaths == null
                          "WebViewLoader-" + abi,
                    || nativeLibraryPaths[0] == null || nativeLibraryPaths[1] == null) {
                          Process.SHARED_RELRO_UID,
                throw new IllegalArgumentException(
                          Process.SHARED_RELRO_UID,
                        "Native library paths to the WebView RelRo process must not be null!");
                          null,
            }
                          0,                 // TODO(torne): do we need to set debug flags?
            int pid = LocalServices.getService(ActivityManagerInternal.class).startIsolatedProcess(
                          Zygote.MOUNT_EXTERNAL_NONE,
                    RelroFileCreator.class.getName(), nativeLibraryPaths, "WebViewLoader-" + abi, abi,
                          Build.VERSION.SDK_INT,
                    Process.SHARED_RELRO_UID, crashHandler);
                          null,
            if (pid <= 0) throw new Exception("Failed to start the relro file creator process");
                          abi,
        } catch (Throwable t) {
                          null);
        } catch (Throwable e) {
            // Log and discard errors as we must not crash the system server.
            // Log and discard errors as we must not crash the system server.
            Log.e(LOGTAG, "error starting relro file creator for abi " + abi, e);
            Log.e(LOGTAG, "error starting relro file creator for abi " + abi, t);
            crashHandler.run();
        }
        }
    }
    }


    private static class RelroFileCreator {
    private static class RelroFileCreator {
        // Called in an unprivileged child process to create the relro file.
        // Called in an unprivileged child process to create the relro file.
        public static void main(String[] args) {
        public static void main(String[] args) {
            boolean result = false;
            boolean is64Bit = VMRuntime.getRuntime().is64Bit();
            try{
                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 + "), " +
                        " 32-bit lib: " + args[0] + ", 64-bit lib: " + args[1]);
                if (!sAddressSpaceReserved) {
                if (!sAddressSpaceReserved) {
                    Log.e(LOGTAG, "can't create relro file; address space not reserved");
                    Log.e(LOGTAG, "can't create relro file; address space not reserved");
                    return;
                    return;
                }
                }
            boolean result = nativeCreateRelroFile(CHROMIUM_WEBVIEW_NATIVE_LIB_32,
                result = nativeCreateRelroFile(args[0] /* path32 */,
                                                   CHROMIUM_WEBVIEW_NATIVE_LIB_64,
                                               args[1] /* path64 */,
                                               CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
                                               CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
                                               CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
                                               CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
            if (!result) {
                if (result && DEBUG) Log.v(LOGTAG, "created relro file");
                Log.e(LOGTAG, "failed to create relro file");
            } finally {
            } else if (DEBUG) {
                // We must do our best to always notify the update service, even if something fails.
                Log.v(LOGTAG, "created relro file");
            }
                try {
                try {
                getUpdateService().notifyRelroCreationCompleted(VMRuntime.getRuntime().is64Bit(),
                    getUpdateService().notifyRelroCreationCompleted(is64Bit, result);
                                                                result);
                } catch (RemoteException e) {
                } catch (RemoteException e) {
                    Log.e(LOGTAG, "error notifying update service", e);
                    Log.e(LOGTAG, "error notifying update service", e);
                }
                }


                if (!result) Log.e(LOGTAG, "failed to create relro file");

                // Must explicitly exit or else this process will just sit around after we return.
                // Must explicitly exit or else this process will just sit around after we return.
                System.exit(0);
                System.exit(0);
            }
            }
        }
        }
    }


    private static void loadNativeLibrary() {
    private static void loadNativeLibrary() {
        if (!sAddressSpaceReserved) {
        if (!sAddressSpaceReserved) {
@@ -203,8 +337,10 @@ public final class WebViewFactory {
            return;
            return;
        }
        }


        boolean result = nativeLoadWithRelroFile(CHROMIUM_WEBVIEW_NATIVE_LIB_32,
        try {
                                                 CHROMIUM_WEBVIEW_NATIVE_LIB_64,
            String[] args = getWebViewNativeLibraryPaths();
            boolean result = nativeLoadWithRelroFile(args[0] /* path32 */,
                                                     args[1] /* path64 */,
                                                     CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
                                                     CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
                                                     CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
                                                     CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
            if (!result) {
            if (!result) {
@@ -212,13 +348,16 @@ public final class WebViewFactory {
            } else if (DEBUG) {
            } else if (DEBUG) {
                Log.v(LOGTAG, "loaded with relro file");
                Log.v(LOGTAG, "loaded with relro file");
            }
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(LOGTAG, "Failed to list WebView package libraries for loadNativeLibrary", e);
        }
    }
    }


    private static IWebViewUpdateService getUpdateService() {
    private static IWebViewUpdateService getUpdateService() {
        return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
        return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
    }
    }


    private static native boolean nativeReserveAddressSpace(String lib32, String lib64);
    private static native boolean nativeReserveAddressSpace(long addressSpaceToReserve);
    private static native boolean nativeCreateRelroFile(String lib32, String lib64,
    private static native boolean nativeCreateRelroFile(String lib32, String lib64,
                                                        String relro32, String relro64);
                                                        String relro32, String relro64);
    private static native boolean nativeLoadWithRelroFile(String lib32, String lib64,
    private static native boolean nativeLoadWithRelroFile(String lib32, String lib64,
+4 −0
Original line number Original line Diff line number Diff line
@@ -1661,4 +1661,8 @@
    <!--Support decoding the user data payload as pack GSM 8-bit (a GSM alphabet
    <!--Support decoding the user data payload as pack GSM 8-bit (a GSM alphabet
        string that's stored in 8-bit unpacked format) characters.-->
        string that's stored in 8-bit unpacked format) characters.-->
    <bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool>
    <bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool>

    <!-- Package name providing WebView implementation. -->
    <string name="config_webViewPackageName" translatable="false">com.android.webview</string>

</resources>
</resources>
+1 −0
Original line number Original line Diff line number Diff line
@@ -1839,6 +1839,7 @@
  <java-symbol type="attr" name="actionModeWebSearchDrawable" />
  <java-symbol type="attr" name="actionModeWebSearchDrawable" />
  <java-symbol type="string" name="websearch" />
  <java-symbol type="string" name="websearch" />
  <java-symbol type="drawable" name="ic_media_video_poster" />
  <java-symbol type="drawable" name="ic_media_video_poster" />
  <java-symbol type="string" name="config_webViewPackageName" />


  <!-- From SubtitleView -->
  <!-- From SubtitleView -->
  <java-symbol type="dimen" name="subtitle_corner_radius" />
  <java-symbol type="dimen" name="subtitle_corner_radius" />
+100 −34

File changed.

Preview size limit exceeded, changes collapsed.

Loading