| Index: components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java
|
| diff --git a/components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java b/components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java
|
| index c7a7cb46b52ed2ece1448634f14f36b89cea496d..ecd1ef1c0567eac0434930022d4dddfa47be8ed3 100644
|
| --- a/components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java
|
| +++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java
|
| @@ -6,6 +6,7 @@ package org.chromium.net.impl;
|
|
|
| import android.content.Context;
|
| import android.os.Handler;
|
| +import android.os.HandlerThread;
|
| import android.os.Looper;
|
|
|
| import org.chromium.base.ContextUtils;
|
| @@ -15,7 +16,7 @@ import org.chromium.base.annotations.JNINamespace;
|
| import org.chromium.net.NetworkChangeNotifier;
|
|
|
| /**
|
| - * CronetLibraryLoader loads and initializes native library on main thread.
|
| + * CronetLibraryLoader loads and initializes native library on init thread.
|
| */
|
| @JNINamespace("cronet")
|
| @VisibleForTesting
|
| @@ -24,14 +25,18 @@ public class CronetLibraryLoader {
|
| private static final Object sLoadLock = new Object();
|
| private static final String LIBRARY_NAME = "cronet." + ImplVersion.getCronetVersion();
|
| private static final String TAG = CronetLibraryLoader.class.getSimpleName();
|
| + // Thread used for initialization work and processing callbacks for
|
| + // long-lived global singletons. This thread lives forever as things like
|
| + // the global singleton NetworkChangeNotifier live on it and are never killed.
|
| + private static final HandlerThread sInitThread = new HandlerThread("CronetInit");
|
| // Has library loading commenced? Setting guarded by sLoadLock.
|
| private static volatile boolean sLibraryLoaded = false;
|
| - // Has ensureMainThreadInitialized() completed? Only accessed on main thread.
|
| - private static volatile boolean sMainThreadInitDone = false;
|
| + // Has ensureInitThreadInitialized() completed?
|
| + private static volatile boolean sInitThreadInitDone = false;
|
|
|
| /**
|
| * Ensure that native library is loaded and initialized. Can be called from
|
| - * any thread, the load and initialization is performed on main thread.
|
| + * any thread, the load and initialization is performed on init thread.
|
| */
|
| public static void ensureInitialized(
|
| final Context applicationContext, final CronetEngineBuilderImpl builder) {
|
| @@ -55,35 +60,36 @@ public class CronetLibraryLoader {
|
| sLibraryLoaded = true;
|
| }
|
|
|
| - if (!sMainThreadInitDone) {
|
| - // Init native Chromium CronetEngine on Main UI thread.
|
| - Runnable task = new Runnable() {
|
| + if (!sInitThreadInitDone) {
|
| + if (!sInitThread.isAlive()) {
|
| + sInitThread.start();
|
| + }
|
| + postToInitThread(new Runnable() {
|
| @Override
|
| public void run() {
|
| - ensureInitializedOnMainThread(applicationContext);
|
| + ensureInitializedOnInitThread(applicationContext);
|
| }
|
| - };
|
| - // Run task immediately or post it to the UI thread.
|
| - if (Looper.getMainLooper() == Looper.myLooper()) {
|
| - task.run();
|
| - } else {
|
| - // The initOnMainThread will complete on the main thread prior
|
| - // to other tasks posted to the main thread.
|
| - new Handler(Looper.getMainLooper()).post(task);
|
| - }
|
| + });
|
| }
|
| }
|
| }
|
|
|
| /**
|
| - * Ensure that the main thread initialization has completed. Can only be called from
|
| - * the main thread. Ensures that the NetworkChangeNotifier is initialzied and the
|
| - * main thread native MessageLoop is initialized.
|
| + * Returns {@code true} if running on the initialization thread.
|
| + */
|
| + private static boolean onInitThread() {
|
| + return sInitThread.getLooper() == Looper.myLooper();
|
| + }
|
| +
|
| + /**
|
| + * Ensure that the init thread initialization has completed. Can only be called from
|
| + * the init thread. Ensures that the NetworkChangeNotifier is initialzied and the
|
| + * init thread native MessageLoop is initialized.
|
| */
|
| - static void ensureInitializedOnMainThread(Context context) {
|
| + static void ensureInitializedOnInitThread(Context context) {
|
| assert sLibraryLoaded;
|
| - assert Looper.getMainLooper() == Looper.myLooper();
|
| - if (sMainThreadInitDone) {
|
| + assert onInitThread();
|
| + if (sInitThreadInitDone) {
|
| return;
|
| }
|
| NetworkChangeNotifier.init(context);
|
| @@ -97,11 +103,22 @@ public class CronetLibraryLoader {
|
| // NetworkChangeNotifierAndroid is created, so as to avoid receiving
|
| // the undesired initial network change observer notification, which
|
| // will cause active requests to fail with ERR_NETWORK_CHANGED.
|
| - nativeCronetInitOnMainThread();
|
| - sMainThreadInitDone = true;
|
| + nativeCronetInitOnInitThread();
|
| + sInitThreadInitDone = true;
|
| + }
|
| +
|
| + /**
|
| + * Run {@code r} on the initialization thread.
|
| + */
|
| + static void postToInitThread(Runnable r) {
|
| + if (onInitThread()) {
|
| + r.run();
|
| + } else {
|
| + new Handler(sInitThread.getLooper()).post(r);
|
| + }
|
| }
|
|
|
| // Native methods are implemented in cronet_library_loader.cc.
|
| - private static native void nativeCronetInitOnMainThread();
|
| + private static native void nativeCronetInitOnInitThread();
|
| private static native String nativeGetCronetVersion();
|
| }
|
|
|