Analyse des problèmes de chargement d'Android WebView

I. Analyse des logs

Lors du chargement normal d'une WebView, les logs suivants apparaissent, indiquant le démarrage du processus WebView :

2025-08-23 01:56:25.849  1142-1316  ActivityManager         pid-1142                             I  Start proc 4098:com.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0/u0ai9000 for  {com.dunn.demo/org.chromium.content.app.SandboxedProcessService0:0}
2025-08-23 01:56:26.214  1142-1316  ActivityManager         pid-1142                             I  Start proc 4130:com.android.webview:webview_service/u0a125 for service {com.android.webview/org.chromium.android_webview.services.ComponentsProviderService}
2025-08-23 02:07:56.187  1142-1360  ActivityManager         pid-1142                             D  sync unfroze 4130 com.android.webview:webview_service for 6

Lorsqu'une application est installée, ou que la commande am force-stop est utilisée, les logs suivanst apparaissent, indiquant que le processus WebView a été tué et libéré :

2025-08-22 22:08:55.018  1117-1174  ActivityManager         system_server                        I  Killing 4805:com.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0/99003 (adj 0): isolated not needed
2025-08-23 01:58:03.376  1142-1295  ActivityManager         pid-1142                             I  Killing 4098:com.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0/99000 (adj 0): isolated not needed
2025-08-23 02:04:46.839  1142-1381  ActivityManager         pid-1142                             D  freezing 4130 com.android.webview:webview_service

Lorsque la commande pm clear est utilisée, les logs suivants apparaissnet, indiquant que le processus WebView a été tué et libéré :

2025-08-23 02:01:00.891  1142-1360  ActivityManager         pid-1142                             I  Killing 4946:com.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0/99001 (adj 0): isolated not needed
2025-08-23 02:01:10.967  1142-1381  ActivityManager         pid-1142                             D  freezing 4130 com.android.webview:webview_service

Le processus xxx/org.chromium.content.app.SandboxedProcessService est intercepté par le système et ne peut pas être relancé, ce qui empêche le chargement de la WebView :

2025-08-22 21:28:37.133  1081-12814 ActivityManager         system_server                        W  Unable to launch app com.coocaa.study.jxw/1000 for service Intent { cmp=com.coocaa.study.jxw/org.chromium.content.app.SandboxedProcessService0:0 }: process is bad
2025-08-22 21:28:37.135 15281-15637 cr_ChildProcessConn     com.coocaa.study.jxw                 W  Fallback to ComponentInfo{com.android.webview/org.chromium.content.app.SandboxedProcessService1}
2025-08-22 21:28:37.139  1081-1332  ActivityManager         system_server                        W  Unable to launch app com.coocaa.study.jxw/1000 for service Intent { cmp=com.coocaa.study.jxw/org.chromium.content.app.SandboxedProcessService1:0 }: process is bad
2025-08-22 21:28:37.230 15281-15281 ContextImpl             com.coocaa.study.jxw                 W  Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1988 android.content.ContextWrapper.bindService:861 android.content.ContextWrapper.bindService:861 org.chromium.components.component_updater.b.a:15 org.chromium.android_webview.AwBrowserProcess.h:34 
2025-08-22 21:28:37.240 15281-15281 ContextImpl             com.coocaa.study.jxw                 W  Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1988 android.content.ContextWrapper.bindService:861 android.content.ContextWrapper.bindService:861 sf0.a:3 org.chromium.android_webview.AwBrowserProcess.g:47 
2025-08-22 21:28:37.510 15281-15658 chromium                com.coocaa.study.jxw                 W  [WARNING:display_webview.cc(32)] WebView overlays are enabled!

2025-08-23 02:05:47.087  1142-1753  ActivityManager         pid-1142                             D  bringUpServiceLocked, suppress to start service!
2025-08-23 02:05:47.088  1142-1753  ActivityManager         pid-1142                             W  Unable to launch app com.dunn.demo/1000 for service Intent { cmp=com.dunn.demo/org.chromium.content.app.SandboxedProcessService0:0 }: process is bad
2025-08-23 02:05:47.160  1142-1862  ActivityManager         pid-1142                             D  sync unfroze 4130 com.android.webview:webview_service for 6

II. Analyse du code source

Fichier : frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

private String bringUpServiceInnerLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
        boolean enqueueOomAdj)
        throws TransactionTooLargeException {

    ......

    // Not running -- get it started, and enqueue this service record
    // to be executed when the app comes up.
    if (app == null && !permissionsReviewRequired && !packageFrozen) {
        // TODO (chriswailes): Change the Zygote policy flags based on if the launch-for-service
        //  was initiated from a notification tap or not.
        /// M: DuraSpeed @{
        String suppressAction = "allowed";
        Boolean isWebClassName = false;
        try{
            String webClassName = r.intent.getIntent().getComponent().getClassName();
            if(webClassName.contains("org.chromium.content.app.SandboxedProcessService")){
                isWebClassName = true;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        // We add a condition here : if it's a WebView component that starts the process,
        // suppressAction must not be set to "skipped", we need to go through the process creation.
        if ("1".equals(SystemProperties.get("persist.vendor.duraspeed.support")) && !isWebClassName) {
            String action = null;
            if (r.intent.getIntent() != null) {
                action =  r.intent.getIntent().getAction();
            }
            // After killing the process with force-stop, our WebView process will set suppressAction
            // to "skipped" here. So we must prevent WebView from reaching this point by adding
            // a condition in the previous check.
            suppressAction = mAm.mAmsExt.onReadyToStartComponent(r.appInfo.packageName,
                    r.appInfo.uid, "service", action);
        }
        try {
            Slog.w("study-debug", "bringUpServiceInnerLocked: suppressAction=" + suppressAction + ", r.packageName=" + r.packageName +
                    ", r.userId=" + r.userId + ", r.intent.getIntent=" + r.intent.getIntent() +
                    ", r.intent.getIntent.action=" + r.intent.getIntent().getAction() +
                    ", r.intent.getIntent.getComponent=" + r.intent.getIntent().getComponent() +
                    ", r.intent.getIntent.getClass=" + r.intent.getIntent().getClass() +
                    ", getComponent.packagename" + r.intent.getIntent().getComponent().getPackageName() + ", getComponent.classname=" + r.intent.getIntent().getComponent().getClassName());
        }catch (Exception e){
            Slog.e("study-debug", "bringUpServiceInnerLocked: e="+e);
        }
        if ((suppressAction != null) && suppressAction.equals("skipped")) {
            // If we reach here, the process is not created. From the logs, the WebView process
            // fails to start precisely because it reaches this point.
            Slog.d(TAG, "bringUpServiceLocked, suppress to start service!");
            try {
                AppGlobals.getPackageManager().setPackageStoppedState(
                        r.packageName, true, r.userId);
            } catch (Exception e) {
                Slog.w(TAG, "Exception: " + e);
            }
        } else {
            // If we reach here, we need to create the process.
            // was initiated from a notification tap or not.
            if (r.isSdkSandbox) {
                final int uid = Process.toSdkSandboxUid(r.sdkSandboxClientAppUid);
                app = mAm.startSdkSandboxProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, uid, r.sdkSandboxClientAppPackage);
                r.isolationHostProc = app;
            } else {
                app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated);
            }
        }
        /// @}
        if (app == null) {
            // Here we finally see the "process is bad" log.
            String msg = "Unable to launch app "
                    + r.appInfo.packageName + "/"
                    + r.appInfo.uid + " for service "
                    + r.intent.getIntent() + ": process is bad";
            Slog.w(TAG, msg);
            bringDownServiceLocked(r, enqueueOomAdj);
            return msg;
        }
        if (isolated) {
            r.isolationHostProc = app;
        }
    }

    ......

    return null;
}

III. Analyse du principe

Lorsque force-stop tue une application, il tue également le processus WebView associé (com.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0). Ce processus WebView est alors marqué comme bad. Au redémarrage de l'application, le système empêche le lancement du processus WebView, ce qui rend la WebView inutilisable et empêche son chargement.

Notre stratégie consiste donc à empêcher le système d'intercepter le démarrage du processus WebView.

Les processus liés à la WebView sont :

webview_zygote 1604  709    1745608  79972 0                   0 S webview_zygote
u0_i9000      4155  1604    1429976 133504 0                   0 S com.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0
u0_a122       4200   709    1372860  94060 0                   0 S com.android.webview:webview_service
u0_i9006      5321  1604    1507020 171728 0                   0 S com.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0

Le package com.android.webview se trouve généralement dans /product/app/webview/webview.apk, selon la plateforme.

Étiquettes: Android WebView ActivityManager Chromium Analyse de logs

Publié le 30 juin à 21h15