OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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; | 5 package org.chromium.net; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.os.Build; | 8 import android.os.Build; |
9 import android.os.ConditionVariable; | 9 import android.os.ConditionVariable; |
10 import android.os.Handler; | 10 import android.os.Handler; |
11 import android.os.Looper; | 11 import android.os.Looper; |
12 import android.os.Process; | 12 import android.os.Process; |
13 import android.util.Log; | 13 import android.util.Log; |
14 | 14 |
| 15 import org.chromium.base.ObserverList; |
15 import org.chromium.base.VisibleForTesting; | 16 import org.chromium.base.VisibleForTesting; |
16 import org.chromium.base.annotations.CalledByNative; | 17 import org.chromium.base.annotations.CalledByNative; |
17 import org.chromium.base.annotations.JNINamespace; | 18 import org.chromium.base.annotations.JNINamespace; |
18 import org.chromium.base.annotations.NativeClassQualifiedName; | 19 import org.chromium.base.annotations.NativeClassQualifiedName; |
19 import org.chromium.base.annotations.UsedByReflection; | 20 import org.chromium.base.annotations.UsedByReflection; |
20 | 21 |
21 import java.util.concurrent.Executor; | 22 import java.util.concurrent.Executor; |
| 23 import java.util.concurrent.RejectedExecutionException; |
22 import java.util.concurrent.atomic.AtomicInteger; | 24 import java.util.concurrent.atomic.AtomicInteger; |
23 | 25 |
| 26 import javax.annotation.concurrent.GuardedBy; |
| 27 |
24 /** | 28 /** |
25 * UrlRequestContext using Chromium HTTP stack implementation. | 29 * UrlRequestContext using Chromium HTTP stack implementation. |
26 */ | 30 */ |
27 @JNINamespace("cronet") | 31 @JNINamespace("cronet") |
28 @UsedByReflection("UrlRequestContext.java") | 32 @UsedByReflection("UrlRequestContext.java") |
29 class CronetUrlRequestContext extends UrlRequestContext { | 33 class CronetUrlRequestContext extends UrlRequestContext { |
30 private static final int LOG_NONE = 3; // LOG(FATAL), no VLOG. | 34 private static final int LOG_NONE = 3; // LOG(FATAL), no VLOG. |
31 private static final int LOG_DEBUG = -1; // LOG(FATAL...INFO), VLOG(1) | 35 private static final int LOG_DEBUG = -1; // LOG(FATAL...INFO), VLOG(1) |
32 private static final int LOG_VERBOSE = -2; // LOG(FATAL...INFO), VLOG(2) | 36 private static final int LOG_VERBOSE = -2; // LOG(FATAL...INFO), VLOG(2) |
33 static final String LOG_TAG = "ChromiumNetwork"; | 37 static final String LOG_TAG = "ChromiumNetwork"; |
34 | 38 |
35 /** | 39 /** |
36 * Synchronize access to mUrlRequestContextAdapter and shutdown routine. | 40 * Synchronize access to mUrlRequestContextAdapter and shutdown routine. |
37 */ | 41 */ |
38 private final Object mLock = new Object(); | 42 private final Object mLock = new Object(); |
39 private final ConditionVariable mInitCompleted = new ConditionVariable(false
); | 43 private final ConditionVariable mInitCompleted = new ConditionVariable(false
); |
40 private final AtomicInteger mActiveRequestCount = new AtomicInteger(0); | 44 private final AtomicInteger mActiveRequestCount = new AtomicInteger(0); |
41 | 45 |
42 private long mUrlRequestContextAdapter = 0; | 46 private long mUrlRequestContextAdapter = 0; |
43 private Thread mNetworkThread; | 47 private Thread mNetworkThread; |
44 | 48 |
| 49 private Executor mNetworkQualityExecutor; |
| 50 |
| 51 /** Locks operations on network quality listeners, because listener |
| 52 * addition and removal may occur on a different thread from notification. |
| 53 */ |
| 54 private final Object mNetworkQualityLock = new Object(); |
| 55 |
| 56 @GuardedBy("mNetworkQualityLock") |
| 57 private final ObserverList<NetworkQualityRttListener> mRttListenerList = |
| 58 new ObserverList<NetworkQualityRttListener>(); |
| 59 |
| 60 @GuardedBy("mNetworkQualityLock") |
| 61 private final ObserverList<NetworkQualityThroughputListener> mThroughputList
enerList = |
| 62 new ObserverList<NetworkQualityThroughputListener>(); |
| 63 |
45 @UsedByReflection("UrlRequestContext.java") | 64 @UsedByReflection("UrlRequestContext.java") |
46 public CronetUrlRequestContext(Context context, | 65 public CronetUrlRequestContext(Context context, |
47 UrlRequestContextConfig config) { | 66 UrlRequestContextConfig config) { |
48 CronetLibraryLoader.ensureInitialized(context, config); | 67 CronetLibraryLoader.ensureInitialized(context, config); |
49 nativeSetMinLogLevel(getLoggingLevel()); | 68 nativeSetMinLogLevel(getLoggingLevel()); |
50 mUrlRequestContextAdapter = nativeCreateRequestContextAdapter(config.toS
tring()); | 69 mUrlRequestContextAdapter = nativeCreateRequestContextAdapter(config.toS
tring()); |
51 if (mUrlRequestContextAdapter == 0) { | 70 if (mUrlRequestContextAdapter == 0) { |
52 throw new NullPointerException("Context Adapter creation failed."); | 71 throw new NullPointerException("Context Adapter creation failed."); |
53 } | 72 } |
54 | 73 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 } | 160 } |
142 | 161 |
143 @Override | 162 @Override |
144 public void stopNetLog() { | 163 public void stopNetLog() { |
145 synchronized (mLock) { | 164 synchronized (mLock) { |
146 checkHaveAdapter(); | 165 checkHaveAdapter(); |
147 nativeStopNetLog(mUrlRequestContextAdapter); | 166 nativeStopNetLog(mUrlRequestContextAdapter); |
148 } | 167 } |
149 } | 168 } |
150 | 169 |
| 170 @Override |
| 171 public void enableNetworkQualityEstimator(Executor executor) { |
| 172 enableNetworkQualityEstimator(false, false, executor); |
| 173 } |
| 174 |
| 175 @VisibleForTesting |
| 176 @Override |
| 177 void enableNetworkQualityEstimator( |
| 178 boolean useLocalHostRequests, boolean useSmallerResponses, Executor
executor) { |
| 179 if (executor == null) { |
| 180 throw new NullPointerException("Network quality estimator requires a
n executor"); |
| 181 } |
| 182 mNetworkQualityExecutor = executor; |
| 183 synchronized (mLock) { |
| 184 checkHaveAdapter(); |
| 185 nativeEnableNetworkQualityEstimator( |
| 186 mUrlRequestContextAdapter, useLocalHostRequests, useSmallerR
esponses); |
| 187 } |
| 188 } |
| 189 |
| 190 @Override |
| 191 public void addRttListener(NetworkQualityRttListener listener) { |
| 192 synchronized (mNetworkQualityLock) { |
| 193 if (mRttListenerList.isEmpty()) { |
| 194 synchronized (mLock) { |
| 195 checkHaveAdapter(); |
| 196 nativeProvideRTTObservations(mUrlRequestContextAdapter, true
); |
| 197 } |
| 198 } |
| 199 mRttListenerList.addObserver(listener); |
| 200 } |
| 201 } |
| 202 |
| 203 @Override |
| 204 public void removeRttListener(NetworkQualityRttListener listener) { |
| 205 synchronized (mNetworkQualityLock) { |
| 206 mRttListenerList.removeObserver(listener); |
| 207 if (mRttListenerList.isEmpty()) { |
| 208 synchronized (mLock) { |
| 209 checkHaveAdapter(); |
| 210 nativeProvideRTTObservations(mUrlRequestContextAdapter, fals
e); |
| 211 } |
| 212 } |
| 213 } |
| 214 } |
| 215 |
| 216 @Override |
| 217 public void addThroughputListener(NetworkQualityThroughputListener listener)
{ |
| 218 synchronized (mNetworkQualityLock) { |
| 219 if (mThroughputListenerList.isEmpty()) { |
| 220 synchronized (mLock) { |
| 221 checkHaveAdapter(); |
| 222 nativeProvideThroughputObservations(mUrlRequestContextAdapte
r, true); |
| 223 } |
| 224 } |
| 225 mThroughputListenerList.addObserver(listener); |
| 226 } |
| 227 } |
| 228 |
| 229 @Override |
| 230 public void removeThroughputListener(NetworkQualityThroughputListener listen
er) { |
| 231 synchronized (mNetworkQualityLock) { |
| 232 mThroughputListenerList.removeObserver(listener); |
| 233 if (mThroughputListenerList.isEmpty()) { |
| 234 synchronized (mLock) { |
| 235 checkHaveAdapter(); |
| 236 nativeProvideThroughputObservations(mUrlRequestContextAdapte
r, false); |
| 237 } |
| 238 } |
| 239 } |
| 240 } |
| 241 |
151 /** | 242 /** |
152 * Mark request as started to prevent shutdown when there are active | 243 * Mark request as started to prevent shutdown when there are active |
153 * requests. | 244 * requests. |
154 */ | 245 */ |
155 void onRequestStarted(UrlRequest urlRequest) { | 246 void onRequestStarted(UrlRequest urlRequest) { |
156 mActiveRequestCount.incrementAndGet(); | 247 mActiveRequestCount.incrementAndGet(); |
157 } | 248 } |
158 | 249 |
159 /** | 250 /** |
160 * Mark request as completed to allow shutdown when there are no active | 251 * Mark request as completed to allow shutdown when there are no active |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 @CalledByNative | 293 @CalledByNative |
203 private void initNetworkThread() { | 294 private void initNetworkThread() { |
204 synchronized (mLock) { | 295 synchronized (mLock) { |
205 mNetworkThread = Thread.currentThread(); | 296 mNetworkThread = Thread.currentThread(); |
206 mInitCompleted.open(); | 297 mInitCompleted.open(); |
207 } | 298 } |
208 Thread.currentThread().setName("ChromiumNet"); | 299 Thread.currentThread().setName("ChromiumNet"); |
209 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); | 300 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); |
210 } | 301 } |
211 | 302 |
| 303 @SuppressWarnings("unused") |
| 304 @CalledByNative |
| 305 private void onRttObservation(final int rttMs, final long whenMs, final int
source) { |
| 306 Runnable task = new Runnable() { |
| 307 @Override |
| 308 public void run() { |
| 309 synchronized (mNetworkQualityLock) { |
| 310 for (NetworkQualityRttListener listener : mRttListenerList)
{ |
| 311 listener.onRttObservation(rttMs, whenMs, source); |
| 312 } |
| 313 } |
| 314 } |
| 315 }; |
| 316 postObservationTaskToExecutor(task); |
| 317 } |
| 318 |
| 319 @SuppressWarnings("unused") |
| 320 @CalledByNative |
| 321 private void onThroughputObservation( |
| 322 final int throughputKbps, final long whenMs, final int source) { |
| 323 Runnable task = new Runnable() { |
| 324 @Override |
| 325 public void run() { |
| 326 synchronized (mNetworkQualityLock) { |
| 327 for (NetworkQualityThroughputListener listener : mThroughput
ListenerList) { |
| 328 listener.onThroughputObservation(throughputKbps, whenMs,
source); |
| 329 } |
| 330 } |
| 331 } |
| 332 }; |
| 333 postObservationTaskToExecutor(task); |
| 334 } |
| 335 |
| 336 void postObservationTaskToExecutor(Runnable task) { |
| 337 try { |
| 338 mNetworkQualityExecutor.execute(task); |
| 339 } catch (RejectedExecutionException failException) { |
| 340 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex
ecutor", |
| 341 failException); |
| 342 } |
| 343 } |
| 344 |
212 // Native methods are implemented in cronet_url_request_context.cc. | 345 // Native methods are implemented in cronet_url_request_context.cc. |
213 private static native long nativeCreateRequestContextAdapter(String config); | 346 private static native long nativeCreateRequestContextAdapter(String config); |
214 | 347 |
215 private static native int nativeSetMinLogLevel(int loggingLevel); | 348 private static native int nativeSetMinLogLevel(int loggingLevel); |
216 | 349 |
217 @NativeClassQualifiedName("CronetURLRequestContextAdapter") | 350 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
218 private native void nativeDestroy(long nativePtr); | 351 private native void nativeDestroy(long nativePtr); |
219 | 352 |
220 @NativeClassQualifiedName("CronetURLRequestContextAdapter") | 353 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
221 private native void nativeStartNetLogToFile(long nativePtr, | 354 private native void nativeStartNetLogToFile(long nativePtr, |
222 String fileName, boolean logAll); | 355 String fileName, boolean logAll); |
223 | 356 |
224 @NativeClassQualifiedName("CronetURLRequestContextAdapter") | 357 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
225 private native void nativeStopNetLog(long nativePtr); | 358 private native void nativeStopNetLog(long nativePtr); |
226 | 359 |
227 @NativeClassQualifiedName("CronetURLRequestContextAdapter") | 360 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
228 private native void nativeInitRequestContextOnMainThread(long nativePtr); | 361 private native void nativeInitRequestContextOnMainThread(long nativePtr); |
| 362 |
| 363 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
| 364 private native void nativeEnableNetworkQualityEstimator( |
| 365 long nativePtr, boolean useLocalHostRequests, boolean useSmallerResp
onses); |
| 366 |
| 367 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
| 368 private native void nativeProvideRTTObservations(long nativePtr, boolean sho
uld); |
| 369 |
| 370 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
| 371 private native void nativeProvideThroughputObservations(long nativePtr, bool
ean should); |
229 } | 372 } |
OLD | NEW |