Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java

Issue 2812963002: [Cronet] Move initialization to a new thread rather than the UI thread. (Closed)
Patch Set: mostly renaming Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.net.impl; 5 package org.chromium.net.impl;
6 6
7 import android.content.Context; 7 import android.content.Context;
8 import android.os.Handler; 8 import android.os.Handler;
9 import android.os.HandlerThread;
9 import android.os.Looper; 10 import android.os.Looper;
10 11
11 import org.chromium.base.ContextUtils; 12 import org.chromium.base.ContextUtils;
12 import org.chromium.base.Log; 13 import org.chromium.base.Log;
13 import org.chromium.base.VisibleForTesting; 14 import org.chromium.base.VisibleForTesting;
14 import org.chromium.base.annotations.JNINamespace; 15 import org.chromium.base.annotations.JNINamespace;
15 import org.chromium.net.NetworkChangeNotifier; 16 import org.chromium.net.NetworkChangeNotifier;
16 17
17 /** 18 /**
18 * CronetLibraryLoader loads and initializes native library on main thread. 19 * CronetLibraryLoader loads and initializes native library on init thread.
19 */ 20 */
20 @JNINamespace("cronet") 21 @JNINamespace("cronet")
21 @VisibleForTesting 22 @VisibleForTesting
22 public class CronetLibraryLoader { 23 public class CronetLibraryLoader {
23 // Synchronize initialization. 24 // Synchronize initialization.
24 private static final Object sLoadLock = new Object(); 25 private static final Object sLoadLock = new Object();
25 private static final String LIBRARY_NAME = "cronet." + ImplVersion.getCronet Version(); 26 private static final String LIBRARY_NAME = "cronet." + ImplVersion.getCronet Version();
26 private static final String TAG = CronetLibraryLoader.class.getSimpleName(); 27 private static final String TAG = CronetLibraryLoader.class.getSimpleName();
28 // Thread used for initialization. This thread lives forever as things like the
29 // global singleton NetworkChangeNotifier live on it and are never killed.
30 private static final HandlerThread sInitThread = new HandlerThread("CronetIn it");
xunjieli 2017/04/13 18:44:54 I am fine with the word "init thread." However, si
pauljensen 2017/05/01 15:35:53 True, I've updated the comment appropriately. I c
27 // Has library loading commenced? Setting guarded by sLoadLock. 31 // Has library loading commenced? Setting guarded by sLoadLock.
28 private static volatile boolean sLibraryLoaded = false; 32 private static volatile boolean sLibraryLoaded = false;
29 // Has ensureMainThreadInitialized() completed? Only accessed on main threa d. 33 // Has ensureInitThreadInitialized() completed? Only accessed on init threa d.
30 private static volatile boolean sMainThreadInitDone = false; 34 private static volatile boolean sInitThreadInitDone = false;
31 35
32 /** 36 /**
33 * Ensure that native library is loaded and initialized. Can be called from 37 * Ensure that native library is loaded and initialized. Can be called from
34 * any thread, the load and initialization is performed on main thread. 38 * any thread, the load and initialization is performed on init thread.
35 */ 39 */
36 public static void ensureInitialized( 40 public static void ensureInitialized(
37 final Context applicationContext, final CronetEngineBuilderImpl buil der) { 41 final Context applicationContext, final CronetEngineBuilderImpl buil der) {
38 synchronized (sLoadLock) { 42 synchronized (sLoadLock) {
39 if (!sLibraryLoaded) { 43 if (!sLibraryLoaded) {
40 ContextUtils.initApplicationContext(applicationContext); 44 ContextUtils.initApplicationContext(applicationContext);
41 if (builder.libraryLoader() != null) { 45 if (builder.libraryLoader() != null) {
42 builder.libraryLoader().loadLibrary(LIBRARY_NAME); 46 builder.libraryLoader().loadLibrary(LIBRARY_NAME);
43 } else { 47 } else {
44 System.loadLibrary(LIBRARY_NAME); 48 System.loadLibrary(LIBRARY_NAME);
45 } 49 }
46 ContextUtils.initApplicationContextForNative(); 50 ContextUtils.initApplicationContextForNative();
47 String implVersion = ImplVersion.getCronetVersion(); 51 String implVersion = ImplVersion.getCronetVersion();
48 if (!implVersion.equals(nativeGetCronetVersion())) { 52 if (!implVersion.equals(nativeGetCronetVersion())) {
49 throw new RuntimeException(String.format("Expected Cronet ve rsion number %s, " 53 throw new RuntimeException(String.format("Expected Cronet ve rsion number %s, "
50 + "actual version number %s.", 54 + "actual version number %s.",
51 implVersion, nativeGetCronetVersion())); 55 implVersion, nativeGetCronetVersion()));
52 } 56 }
53 Log.i(TAG, "Cronet version: %s, arch: %s", implVersion, 57 Log.i(TAG, "Cronet version: %s, arch: %s", implVersion,
54 System.getProperty("os.arch")); 58 System.getProperty("os.arch"));
55 sLibraryLoaded = true; 59 sLibraryLoaded = true;
56 } 60 }
57 61
58 if (!sMainThreadInitDone) { 62 if (!sInitThreadInitDone) {
59 // Init native Chromium CronetEngine on Main UI thread. 63 if (!sInitThread.isAlive()) {
xunjieli 2017/04/13 18:44:54 We could also lazily create sInitThread here to av
pauljensen 2017/05/01 15:35:53 We could but this would require making sInitThread
60 Runnable task = new Runnable() { 64 sInitThread.start();
65 }
66 postToInitThread(new Runnable() {
61 @Override 67 @Override
62 public void run() { 68 public void run() {
63 ensureInitializedOnMainThread(applicationContext); 69 ensureInitializedOnInitThread(applicationContext);
64 } 70 }
65 }; 71 });
66 // Run task immediately or post it to the UI thread.
67 if (Looper.getMainLooper() == Looper.myLooper()) {
68 task.run();
69 } else {
70 // The initOnMainThread will complete on the main thread pri or
71 // to other tasks posted to the main thread.
72 new Handler(Looper.getMainLooper()).post(task);
73 }
74 } 72 }
75 } 73 }
76 } 74 }
77 75
78 /** 76 /**
79 * Ensure that the main thread initialization has completed. Can only be cal led from 77 * Ensure that the init thread initialization has completed. Can only be cal led from
80 * the main thread. Ensures that the NetworkChangeNotifier is initialzied an d the 78 * the init thread. Ensures that the NetworkChangeNotifier is initialzied an d the
81 * main thread native MessageLoop is initialized. 79 * init thread native MessageLoop is initialized.
82 */ 80 */
83 static void ensureInitializedOnMainThread(Context context) { 81 static void ensureInitializedOnInitThread(Context context) {
84 assert sLibraryLoaded; 82 assert sLibraryLoaded;
85 assert Looper.getMainLooper() == Looper.myLooper(); 83 assert sInitThread.getLooper() == Looper.myLooper();
86 if (sMainThreadInitDone) { 84 if (sInitThreadInitDone) {
87 return; 85 return;
88 } 86 }
89 NetworkChangeNotifier.init(context); 87 NetworkChangeNotifier.init(context);
90 // Registers to always receive network notifications. Note 88 // Registers to always receive network notifications. Note
91 // that this call is fine for Cronet because Cronet 89 // that this call is fine for Cronet because Cronet
92 // embedders do not have API access to create network change 90 // embedders do not have API access to create network change
93 // observers. Existing observers in the net stack do not 91 // observers. Existing observers in the net stack do not
94 // perform expensive work. 92 // perform expensive work.
95 NetworkChangeNotifier.registerToReceiveNotificationsAlways(); 93 NetworkChangeNotifier.registerToReceiveNotificationsAlways();
96 // registerToReceiveNotificationsAlways() is called before the native 94 // registerToReceiveNotificationsAlways() is called before the native
97 // NetworkChangeNotifierAndroid is created, so as to avoid receiving 95 // NetworkChangeNotifierAndroid is created, so as to avoid receiving
98 // the undesired initial network change observer notification, which 96 // the undesired initial network change observer notification, which
99 // will cause active requests to fail with ERR_NETWORK_CHANGED. 97 // will cause active requests to fail with ERR_NETWORK_CHANGED.
100 nativeCronetInitOnMainThread(); 98 nativeCronetInitOnInitThread();
101 sMainThreadInitDone = true; 99 sInitThreadInitDone = true;
100 }
101
102 /**
103 * Run {@code r} on the initialization thread.
104 */
105 static void postToInitThread(Runnable r) {
106 new Handler(sInitThread.getLooper()).post(r);
xunjieli 2017/04/13 18:44:54 Do we need to test to see if we aren't already on
pauljensen 2017/05/01 15:35:53 Done.
102 } 107 }
103 108
104 // Native methods are implemented in cronet_library_loader.cc. 109 // Native methods are implemented in cronet_library_loader.cc.
105 private static native void nativeCronetInitOnMainThread(); 110 private static native void nativeCronetInitOnInitThread();
106 private static native String nativeGetCronetVersion(); 111 private static native String nativeGetCronetVersion();
107 } 112 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698