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