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

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: update tests to account for mRegistered change Created 3 years, 7 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 work and processing callbacks for
29 // long-lived global singletons. This thread lives forever as things like
30 // the global singleton NetworkChangeNotifier live on it and are never kille d.
31 private static final HandlerThread sInitThread = new HandlerThread("CronetIn it");
27 // Has library loading commenced? Setting guarded by sLoadLock. 32 // Has library loading commenced? Setting guarded by sLoadLock.
28 private static volatile boolean sLibraryLoaded = false; 33 private static volatile boolean sLibraryLoaded = false;
29 // Has ensureMainThreadInitialized() completed? Only accessed on main threa d. 34 // Has ensureInitThreadInitialized() completed?
30 private static volatile boolean sMainThreadInitDone = false; 35 private static volatile boolean sInitThreadInitDone = false;
31 36
32 /** 37 /**
33 * Ensure that native library is loaded and initialized. Can be called from 38 * Ensure that native library is loaded and initialized. Can be called from
34 * any thread, the load and initialization is performed on main thread. 39 * any thread, the load and initialization is performed on init thread.
35 */ 40 */
36 public static void ensureInitialized( 41 public static void ensureInitialized(
37 final Context applicationContext, final CronetEngineBuilderImpl buil der) { 42 final Context applicationContext, final CronetEngineBuilderImpl buil der) {
38 synchronized (sLoadLock) { 43 synchronized (sLoadLock) {
39 if (!sLibraryLoaded) { 44 if (!sLibraryLoaded) {
40 ContextUtils.initApplicationContext(applicationContext); 45 ContextUtils.initApplicationContext(applicationContext);
41 if (builder.libraryLoader() != null) { 46 if (builder.libraryLoader() != null) {
42 builder.libraryLoader().loadLibrary(LIBRARY_NAME); 47 builder.libraryLoader().loadLibrary(LIBRARY_NAME);
43 } else { 48 } else {
44 System.loadLibrary(LIBRARY_NAME); 49 System.loadLibrary(LIBRARY_NAME);
45 } 50 }
46 ContextUtils.initApplicationContextForNative(); 51 ContextUtils.initApplicationContextForNative();
47 String implVersion = ImplVersion.getCronetVersion(); 52 String implVersion = ImplVersion.getCronetVersion();
48 if (!implVersion.equals(nativeGetCronetVersion())) { 53 if (!implVersion.equals(nativeGetCronetVersion())) {
49 throw new RuntimeException(String.format("Expected Cronet ve rsion number %s, " 54 throw new RuntimeException(String.format("Expected Cronet ve rsion number %s, "
50 + "actual version number %s.", 55 + "actual version number %s.",
51 implVersion, nativeGetCronetVersion())); 56 implVersion, nativeGetCronetVersion()));
52 } 57 }
53 Log.i(TAG, "Cronet version: %s, arch: %s", implVersion, 58 Log.i(TAG, "Cronet version: %s, arch: %s", implVersion,
54 System.getProperty("os.arch")); 59 System.getProperty("os.arch"));
55 sLibraryLoaded = true; 60 sLibraryLoaded = true;
56 } 61 }
57 62
58 if (!sMainThreadInitDone) { 63 if (!sInitThreadInitDone) {
59 // Init native Chromium CronetEngine on Main UI thread. 64 if (!sInitThread.isAlive()) {
60 Runnable task = new Runnable() { 65 sInitThread.start();
66 }
67 postToInitThread(new Runnable() {
61 @Override 68 @Override
62 public void run() { 69 public void run() {
63 ensureInitializedOnMainThread(applicationContext); 70 ensureInitializedOnInitThread(applicationContext);
64 } 71 }
65 }; 72 });
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 } 73 }
75 } 74 }
76 } 75 }
77 76
78 /** 77 /**
79 * Ensure that the main thread initialization has completed. Can only be cal led from 78 * Returns {@code true} if running on the initialization thread.
80 * the main thread. Ensures that the NetworkChangeNotifier is initialzied an d the
81 * main thread native MessageLoop is initialized.
82 */ 79 */
83 static void ensureInitializedOnMainThread(Context context) { 80 private static boolean onInitThread() {
81 return sInitThread.getLooper() == Looper.myLooper();
82 }
83
84 /**
85 * Ensure that the init thread initialization has completed. Can only be cal led from
86 * the init thread. Ensures that the NetworkChangeNotifier is initialzied an d the
87 * init thread native MessageLoop is initialized.
88 */
89 static void ensureInitializedOnInitThread(Context context) {
84 assert sLibraryLoaded; 90 assert sLibraryLoaded;
85 assert Looper.getMainLooper() == Looper.myLooper(); 91 assert onInitThread();
86 if (sMainThreadInitDone) { 92 if (sInitThreadInitDone) {
87 return; 93 return;
88 } 94 }
89 NetworkChangeNotifier.init(context); 95 NetworkChangeNotifier.init(context);
90 // Registers to always receive network notifications. Note 96 // Registers to always receive network notifications. Note
91 // that this call is fine for Cronet because Cronet 97 // that this call is fine for Cronet because Cronet
92 // embedders do not have API access to create network change 98 // embedders do not have API access to create network change
93 // observers. Existing observers in the net stack do not 99 // observers. Existing observers in the net stack do not
94 // perform expensive work. 100 // perform expensive work.
95 NetworkChangeNotifier.registerToReceiveNotificationsAlways(); 101 NetworkChangeNotifier.registerToReceiveNotificationsAlways();
96 // registerToReceiveNotificationsAlways() is called before the native 102 // registerToReceiveNotificationsAlways() is called before the native
97 // NetworkChangeNotifierAndroid is created, so as to avoid receiving 103 // NetworkChangeNotifierAndroid is created, so as to avoid receiving
98 // the undesired initial network change observer notification, which 104 // the undesired initial network change observer notification, which
99 // will cause active requests to fail with ERR_NETWORK_CHANGED. 105 // will cause active requests to fail with ERR_NETWORK_CHANGED.
100 nativeCronetInitOnMainThread(); 106 nativeCronetInitOnInitThread();
101 sMainThreadInitDone = true; 107 sInitThreadInitDone = true;
108 }
109
110 /**
111 * Run {@code r} on the initialization thread.
112 */
113 static void postToInitThread(Runnable r) {
114 if (onInitThread()) {
115 r.run();
116 } else {
117 new Handler(sInitThread.getLooper()).post(r);
118 }
102 } 119 }
103 120
104 // Native methods are implemented in cronet_library_loader.cc. 121 // Native methods are implemented in cronet_library_loader.cc.
105 private static native void nativeCronetInitOnMainThread(); 122 private static native void nativeCronetInitOnInitThread();
106 private static native String nativeGetCronetVersion(); 123 private static native String nativeGetCronetVersion();
107 } 124 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698