1ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek/*
2ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * Copyright (C) 2016 The Android Open Source Project
3ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek *
4ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * Licensed under the Apache License, Version 2.0 (the "License");
5ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * you may not use this file except in compliance with the License.
6ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * You may obtain a copy of the License at
7ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek *
8ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek *      http://www.apache.org/licenses/LICENSE-2.0
9ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek *
10ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * Unless required by applicable law or agreed to in writing, software
11ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * distributed under the License is distributed on an "AS IS" BASIS,
12ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * See the License for the specific language governing permissions and
14ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * limitations under the License.
15ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek */
16ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
17ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekpackage android.webkit;
18ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
193b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import android.app.LoadedApk;
20ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.content.pm.PackageInfo;
21ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.os.Build;
22ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.os.SystemService;
23ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.os.ZygoteProcess;
243b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import android.text.TextUtils;
25f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Senntonimport android.util.AndroidRuntimeException;
26ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.util.Log;
27ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
2889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesekimport com.android.internal.annotations.GuardedBy;
2989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek
303b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import java.io.File;
31ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport java.io.IOException;
323b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import java.util.ArrayList;
33ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport java.util.Arrays;
343b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import java.util.List;
35ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport java.util.concurrent.TimeoutException;
36ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
37ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek/** @hide */
38ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekpublic class WebViewZygote {
39ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    private static final String LOGTAG = "WebViewZygote";
40ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
41ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    private static final String WEBVIEW_ZYGOTE_SERVICE_32 = "webview_zygote32";
42ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    private static final String WEBVIEW_ZYGOTE_SERVICE_64 = "webview_zygote64";
43833813cecc357a9d9bda28917a931a9a9539cd37Gustav Sennton    private static final String WEBVIEW_ZYGOTE_SOCKET = "webview_zygote";
44ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
4589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    /**
4689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     * Lock object that protects all other static members.
4789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     */
4889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    private static final Object sLock = new Object();
4989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek
5089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    /**
5189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     * Instance that maintains the socket connection to the zygote. This is null if the zygote
5289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     * is not running or is not connected.
5389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     */
5489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    @GuardedBy("sLock")
55ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    private static ZygoteProcess sZygote;
56ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
5789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    /**
58f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton     * Variable that allows us to determine whether the WebView zygote Service has already been
59f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton     * started.
60f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton     */
61f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton    @GuardedBy("sLock")
62f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton    private static boolean sStartedService = false;
63f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton
64f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton    /**
6589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     * Information about the selected WebView package. This is set from #onWebViewProviderChanged().
6689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     */
6789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    @GuardedBy("sLock")
68ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    private static PackageInfo sPackage;
69ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
7089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    /**
710452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)     * Cache key for the selected WebView package's classloader. This is set from
720452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)     * #onWebViewProviderChanged().
730452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)     */
740452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)    @GuardedBy("sLock")
750452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)    private static String sPackageCacheKey;
760452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)
770452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)    /**
7889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     * Flag for whether multi-process WebView is enabled. If this is false, the zygote
7989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     * will not be started.
8089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek     */
8189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    @GuardedBy("sLock")
82ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    private static boolean sMultiprocessEnabled = false;
83ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
84ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    public static ZygoteProcess getProcess() {
8589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        synchronized (sLock) {
86f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            if (sZygote != null) return sZygote;
87f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton
88f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            waitForServiceStartAndConnect();
8989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            return sZygote;
9089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        }
91ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    }
92ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
93ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    public static String getPackageName() {
9489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        synchronized (sLock) {
9589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            return sPackage.packageName;
9689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        }
97ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    }
98ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
99c5f86647b19d5cac4d9874ef84954fcf7a6d5fa9Robert Sesek    public static boolean isMultiprocessEnabled() {
10089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        synchronized (sLock) {
10189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            return sMultiprocessEnabled && sPackage != null;
10289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        }
103c5f86647b19d5cac4d9874ef84954fcf7a6d5fa9Robert Sesek    }
104c5f86647b19d5cac4d9874ef84954fcf7a6d5fa9Robert Sesek
105ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    public static void setMultiprocessEnabled(boolean enabled) {
10689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        synchronized (sLock) {
10789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            sMultiprocessEnabled = enabled;
10889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek
10989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            // When toggling between multi-process being on/off, start or stop the
11089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            // service. If it is enabled and the zygote is not yet started, bring up the service.
11189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            // Otherwise, bring down the service. The name may be null if the package
11289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            // information has not yet been resolved.
11389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            final String serviceName = getServiceNameLocked();
11489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            if (serviceName == null) return;
11589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek
116f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            if (enabled) {
117f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton                if (!sStartedService) {
118f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton                    SystemService.start(serviceName);
119f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton                    sStartedService = true;
120f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton                }
12189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            } else {
12289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek                SystemService.stop(serviceName);
123f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton                sStartedService = false;
12489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek                sZygote = null;
12589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            }
126ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        }
127ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    }
128ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
1290452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)    public static void onWebViewProviderChanged(PackageInfo packageInfo, String cacheKey) {
13089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        synchronized (sLock) {
13189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            sPackage = packageInfo;
1320452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)            sPackageCacheKey = cacheKey;
133ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
13489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            // If multi-process is not enabled, then do not start the zygote service.
13589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            if (!sMultiprocessEnabled) {
13689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek                return;
13789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            }
138ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
139f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            final String serviceName = getServiceNameLocked();
14089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            sZygote = null;
141ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
14289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            // The service may enter the RUNNING state before it opens the socket,
14389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            // so connectToZygoteIfNeededLocked() may still fail.
14489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            if (SystemService.isStopped(serviceName)) {
14589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek                SystemService.start(serviceName);
14689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            } else {
14789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek                SystemService.restart(serviceName);
14889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            }
149f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            sStartedService = true;
150f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        }
151f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton    }
15289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek
153f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton    private static void waitForServiceStartAndConnect() {
154f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        if (!sStartedService) {
155f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            throw new AndroidRuntimeException("Tried waiting for the WebView Zygote Service to " +
156f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton                    "start running without first starting the service.");
157f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        }
158f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton
159f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        String serviceName;
160f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        synchronized (sLock) {
161f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            serviceName = getServiceNameLocked();
162f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        }
163f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        try {
164f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
165f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        } catch (TimeoutException e) {
166f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            Log.e(LOGTAG, "Timed out waiting for " + serviceName);
167f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton            return;
168f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        }
16989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek
170f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        synchronized (sLock) {
17189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek            connectToZygoteIfNeededLocked();
172ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        }
173ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    }
174ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
17589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    @GuardedBy("sLock")
17689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    private static String getServiceNameLocked() {
177ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        if (sPackage == null)
178ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            return null;
179ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
180ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        if (Arrays.asList(Build.SUPPORTED_64_BIT_ABIS).contains(
181ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek                    sPackage.applicationInfo.primaryCpuAbi)) {
182ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            return WEBVIEW_ZYGOTE_SERVICE_64;
183ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        }
184ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
185ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        return WEBVIEW_ZYGOTE_SERVICE_32;
186ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    }
187ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
18889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    @GuardedBy("sLock")
18989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek    private static void connectToZygoteIfNeededLocked() {
190f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        if (sZygote != null) {
191ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            return;
192f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton        }
193ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
194ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        if (sPackage == null) {
195ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            Log.e(LOGTAG, "Cannot connect to zygote, no package specified");
196ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            return;
197ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        }
198ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
19989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek        final String serviceName = getServiceNameLocked();
200ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        if (!SystemService.isRunning(serviceName)) {
201ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            Log.e(LOGTAG, serviceName + " is not running");
202ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            return;
203ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        }
204ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
205ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        try {
206833813cecc357a9d9bda28917a931a9a9539cd37Gustav Sennton            sZygote = new ZygoteProcess(WEBVIEW_ZYGOTE_SOCKET, null);
207ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek
2083b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            // All the work below is usually done by LoadedApk, but the zygote can't talk to
2093b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so
2103b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            // doesn't have an ActivityThread and can't use Binder.
2113b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            // Instead, figure out the paths here, in the system server where we have access to
2123b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            // the package manager. Reuse the logic from LoadedApk to determine the correct
2133b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            // paths and pass them to the zygote as strings.
2143b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            final List<String> zipPaths = new ArrayList<>(10);
2153b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            final List<String> libPaths = new ArrayList<>(10);
216638d81009918eae44eec3261e235b78eae44331dDimitry Ivanov            LoadedApk.makePaths(null, false, sPackage.applicationInfo, zipPaths, libPaths);
2173b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
2183b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
2193b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)                    TextUtils.join(File.pathSeparator, zipPaths);
2203b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)
221f0c52b5e9c498c31a963232a008ca43836ebc32aGustav Sennton            ZygoteProcess.waitForConnectionToZygote(WEBVIEW_ZYGOTE_SOCKET);
222833813cecc357a9d9bda28917a931a9a9539cd37Gustav Sennton
2233b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)            Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath);
2240452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)            sZygote.preloadPackageForAbi(zip, librarySearchPath, sPackageCacheKey,
2250452670374ebb2a22d2dc44c030f7b43173800c0Torne (Richard Coles)                                         Build.SUPPORTED_ABIS[0]);
226ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        } catch (Exception e) {
227ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            Log.e(LOGTAG, "Error connecting to " + serviceName, e);
228ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek            sZygote = null;
229ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek        }
230ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek    }
231ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek}
232