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(); |
} |