| 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.impl; | 5 package org.chromium.net.impl; |
| 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.ObserverList; |
| 16 import org.chromium.base.VisibleForTesting; | 16 import org.chromium.base.VisibleForTesting; |
| 17 import org.chromium.base.annotations.CalledByNative; | 17 import org.chromium.base.annotations.CalledByNative; |
| 18 import org.chromium.base.annotations.JNINamespace; | 18 import org.chromium.base.annotations.JNINamespace; |
| 19 import org.chromium.base.annotations.NativeClassQualifiedName; | 19 import org.chromium.base.annotations.NativeClassQualifiedName; |
| 20 import org.chromium.base.annotations.UsedByReflection; | 20 import org.chromium.base.annotations.UsedByReflection; |
| 21 import org.chromium.net.BidirectionalStream; | 21 import org.chromium.net.BidirectionalStream; |
| 22 import org.chromium.net.CronetEngine; | 22 import org.chromium.net.CronetEngine; |
| 23 import org.chromium.net.NetworkQualityRttListener; | 23 import org.chromium.net.NetworkQualityRttListener; |
| 24 import org.chromium.net.NetworkQualityThroughputListener; | 24 import org.chromium.net.NetworkQualityThroughputListener; |
| 25 import org.chromium.net.RequestFinishedListener; |
| 25 import org.chromium.net.UrlRequest; | 26 import org.chromium.net.UrlRequest; |
| 26 import org.chromium.net.urlconnection.CronetHttpURLConnection; | 27 import org.chromium.net.urlconnection.CronetHttpURLConnection; |
| 27 import org.chromium.net.urlconnection.CronetURLStreamHandlerFactory; | 28 import org.chromium.net.urlconnection.CronetURLStreamHandlerFactory; |
| 28 | 29 |
| 29 import java.net.Proxy; | 30 import java.net.Proxy; |
| 30 import java.net.URL; | 31 import java.net.URL; |
| 31 import java.net.URLConnection; | 32 import java.net.URLConnection; |
| 32 import java.net.URLStreamHandlerFactory; | 33 import java.net.URLStreamHandlerFactory; |
| 34 import java.util.ArrayList; |
| 33 import java.util.Collection; | 35 import java.util.Collection; |
| 34 import java.util.List; | 36 import java.util.List; |
| 35 import java.util.Map; | 37 import java.util.Map; |
| 36 import java.util.concurrent.Executor; | 38 import java.util.concurrent.Executor; |
| 37 import java.util.concurrent.RejectedExecutionException; | 39 import java.util.concurrent.RejectedExecutionException; |
| 38 import java.util.concurrent.atomic.AtomicInteger; | 40 import java.util.concurrent.atomic.AtomicInteger; |
| 39 | 41 |
| 40 import javax.annotation.concurrent.GuardedBy; | 42 import javax.annotation.concurrent.GuardedBy; |
| 41 | 43 |
| 42 /** | 44 /** |
| (...skipping 14 matching lines...) Expand all Loading... |
| 57 private final Object mLock = new Object(); | 59 private final Object mLock = new Object(); |
| 58 private final ConditionVariable mInitCompleted = new ConditionVariable(false
); | 60 private final ConditionVariable mInitCompleted = new ConditionVariable(false
); |
| 59 private final AtomicInteger mActiveRequestCount = new AtomicInteger(0); | 61 private final AtomicInteger mActiveRequestCount = new AtomicInteger(0); |
| 60 | 62 |
| 61 private long mUrlRequestContextAdapter = 0; | 63 private long mUrlRequestContextAdapter = 0; |
| 62 private Thread mNetworkThread; | 64 private Thread mNetworkThread; |
| 63 | 65 |
| 64 private Executor mNetworkQualityExecutor; | 66 private Executor mNetworkQualityExecutor; |
| 65 private boolean mNetworkQualityEstimatorEnabled; | 67 private boolean mNetworkQualityEstimatorEnabled; |
| 66 | 68 |
| 67 /** Locks operations on network quality listeners, because listener | 69 /** |
| 70 * Locks operations on network quality listeners, because listener |
| 68 * addition and removal may occur on a different thread from notification. | 71 * addition and removal may occur on a different thread from notification. |
| 69 */ | 72 */ |
| 70 private final Object mNetworkQualityLock = new Object(); | 73 private final Object mNetworkQualityLock = new Object(); |
| 71 | 74 |
| 75 /** |
| 76 * Locks operations on the list of RequestFinishedListeners, because operati
ons can happen on |
| 77 * any thread. |
| 78 */ |
| 79 private final Object mFinishedListenerLock = new Object(); |
| 80 |
| 72 @GuardedBy("mNetworkQualityLock") | 81 @GuardedBy("mNetworkQualityLock") |
| 73 private final ObserverList<NetworkQualityRttListener> mRttListenerList = | 82 private final ObserverList<NetworkQualityRttListener> mRttListenerList = |
| 74 new ObserverList<NetworkQualityRttListener>(); | 83 new ObserverList<NetworkQualityRttListener>(); |
| 75 | 84 |
| 76 @GuardedBy("mNetworkQualityLock") | 85 @GuardedBy("mNetworkQualityLock") |
| 77 private final ObserverList<NetworkQualityThroughputListener> mThroughputList
enerList = | 86 private final ObserverList<NetworkQualityThroughputListener> mThroughputList
enerList = |
| 78 new ObserverList<NetworkQualityThroughputListener>(); | 87 new ObserverList<NetworkQualityThroughputListener>(); |
| 79 | 88 |
| 80 @GuardedBy("mNetworkQualityLock") | 89 @GuardedBy("mFinishedListenerLock") |
| 81 private final ObserverList<RequestFinishedListener> mFinishedListenerList = | 90 private final List<RequestFinishedListener> mFinishedListenerList = |
| 82 new ObserverList<RequestFinishedListener>(); | 91 new ArrayList<RequestFinishedListener>(); |
| 83 | 92 |
| 84 /** | 93 /** |
| 85 * Synchronize access to mCertVerifierData. | 94 * Synchronize access to mCertVerifierData. |
| 86 */ | 95 */ |
| 87 private ConditionVariable mWaitGetCertVerifierDataComplete = new ConditionVa
riable(); | 96 private ConditionVariable mWaitGetCertVerifierDataComplete = new ConditionVa
riable(); |
| 88 | 97 |
| 89 /** Holds CertVerifier data. */ | 98 /** Holds CertVerifier data. */ |
| 90 private String mCertVerifierData; | 99 private String mCertVerifierData; |
| 91 | 100 |
| 92 @UsedByReflection("CronetEngine.java") | 101 @UsedByReflection("CronetEngine.java") |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 } | 155 } |
| 147 return urlRequestContextConfig; | 156 return urlRequestContextConfig; |
| 148 } | 157 } |
| 149 | 158 |
| 150 @Override | 159 @Override |
| 151 public UrlRequest createRequest(String url, UrlRequest.Callback callback, Ex
ecutor executor, | 160 public UrlRequest createRequest(String url, UrlRequest.Callback callback, Ex
ecutor executor, |
| 152 int priority, Collection<Object> requestAnnotations, boolean disable
Cache, | 161 int priority, Collection<Object> requestAnnotations, boolean disable
Cache, |
| 153 boolean disableConnectionMigration) { | 162 boolean disableConnectionMigration) { |
| 154 synchronized (mLock) { | 163 synchronized (mLock) { |
| 155 checkHaveAdapter(); | 164 checkHaveAdapter(); |
| 156 boolean metricsCollectionEnabled = mNetworkQualityEstimatorEnabled; | 165 boolean metricsCollectionEnabled = false; |
| 157 if (metricsCollectionEnabled) { // Collect metrics only if someone i
s listening. | 166 synchronized (mFinishedListenerLock) { |
| 158 synchronized (mNetworkQualityLock) { | 167 metricsCollectionEnabled = !mFinishedListenerList.isEmpty(); |
| 159 metricsCollectionEnabled = !mFinishedListenerList.isEmpty(); | |
| 160 } | |
| 161 } | 168 } |
| 162 return new CronetUrlRequest(this, url, priority, callback, executor,
requestAnnotations, | 169 return new CronetUrlRequest(this, url, priority, callback, executor,
requestAnnotations, |
| 163 metricsCollectionEnabled, disableCache, disableConnectionMig
ration); | 170 metricsCollectionEnabled, disableCache, disableConnectionMig
ration); |
| 164 } | 171 } |
| 165 } | 172 } |
| 166 | 173 |
| 167 @Override | 174 @Override |
| 168 public BidirectionalStream createBidirectionalStream(String url, | 175 public BidirectionalStream createBidirectionalStream(String url, |
| 169 BidirectionalStream.Callback callback, Executor executor, String htt
pMethod, | 176 BidirectionalStream.Callback callback, Executor executor, String htt
pMethod, |
| 170 List<Map.Entry<String, String>> requestHeaders, | 177 List<Map.Entry<String, String>> requestHeaders, |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 } | 379 } |
| 373 } | 380 } |
| 374 | 381 |
| 375 /** | 382 /** |
| 376 * TODO(tbansal): http://crbug.com/618034 Remove this API once all | 383 * TODO(tbansal): http://crbug.com/618034 Remove this API once all |
| 377 * embedders have switched to using a request finished listener that | 384 * embedders have switched to using a request finished listener that |
| 378 * provides its own executor. | 385 * provides its own executor. |
| 379 */ | 386 */ |
| 380 @Override | 387 @Override |
| 381 public void addRequestFinishedListener(RequestFinishedListener listener) { | 388 public void addRequestFinishedListener(RequestFinishedListener listener) { |
| 382 if (!mNetworkQualityEstimatorEnabled) { | 389 synchronized (mFinishedListenerLock) { |
| 383 throw new IllegalStateException("Network quality estimator must be e
nabled"); | 390 mFinishedListenerList.add(listener); |
| 384 } | |
| 385 // RequestFinishedListener does not provide its own executor. | |
| 386 if (mNetworkQualityExecutor == null) { | |
| 387 throw new IllegalStateException("Executor must not be null"); | |
| 388 } | |
| 389 synchronized (mNetworkQualityLock) { | |
| 390 mFinishedListenerList.addObserver(listener); | |
| 391 } | 391 } |
| 392 } | 392 } |
| 393 | 393 |
| 394 /** | 394 /** |
| 395 * TODO(tbansal): http://crbug.com/618034 Remove this API. | 395 * TODO(tbansal): http://crbug.com/618034 Remove this API. |
| 396 */ | 396 */ |
| 397 @Override | 397 @Override |
| 398 public void removeRequestFinishedListener(RequestFinishedListener listener)
{ | 398 public void removeRequestFinishedListener(RequestFinishedListener listener)
{ |
| 399 if (!mNetworkQualityEstimatorEnabled) { | 399 synchronized (mFinishedListenerLock) { |
| 400 throw new IllegalStateException("Network quality estimator must be e
nabled"); | 400 mFinishedListenerList.remove(listener); |
| 401 } | |
| 402 synchronized (mNetworkQualityLock) { | |
| 403 mFinishedListenerList.removeObserver(listener); | |
| 404 } | 401 } |
| 405 } | 402 } |
| 406 | 403 |
| 407 @Override | 404 @Override |
| 408 public URLConnection openConnection(URL url) { | 405 public URLConnection openConnection(URL url) { |
| 409 return openConnection(url, Proxy.NO_PROXY); | 406 return openConnection(url, Proxy.NO_PROXY); |
| 410 } | 407 } |
| 411 | 408 |
| 412 @Override | 409 @Override |
| 413 public URLConnection openConnection(URL url, Proxy proxy) { | 410 public URLConnection openConnection(URL url, Proxy proxy) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 } | 518 } |
| 522 | 519 |
| 523 @SuppressWarnings("unused") | 520 @SuppressWarnings("unused") |
| 524 @CalledByNative | 521 @CalledByNative |
| 525 private void onGetCertVerifierData(String certVerifierData) { | 522 private void onGetCertVerifierData(String certVerifierData) { |
| 526 mCertVerifierData = certVerifierData; | 523 mCertVerifierData = certVerifierData; |
| 527 mWaitGetCertVerifierDataComplete.open(); | 524 mWaitGetCertVerifierDataComplete.open(); |
| 528 } | 525 } |
| 529 | 526 |
| 530 void reportFinished(final CronetUrlRequest request) { | 527 void reportFinished(final CronetUrlRequest request) { |
| 531 if (!mNetworkQualityEstimatorEnabled) { | 528 final UrlRequestInfo requestInfo = request.getRequestInfo(); |
| 532 return; | 529 ArrayList<RequestFinishedListener> currentListeners; |
| 530 synchronized (mFinishedListenerLock) { |
| 531 currentListeners = new ArrayList<RequestFinishedListener>(mFinishedL
istenerList); |
| 533 } | 532 } |
| 534 // If no request finished listener has been added, then mNetworkQualityE
xecutor may be | 533 for (final RequestFinishedListener listener : currentListeners) { |
| 535 // null. Exit early to avoid posting to a null executor. | 534 Runnable task = new Runnable() { |
| 536 synchronized (mNetworkQualityLock) { | 535 @Override |
| 537 if (mFinishedListenerList.isEmpty()) { | 536 public void run() { |
| 538 return; | 537 listener.onRequestFinished(requestInfo); |
| 539 } | 538 } |
| 539 }; |
| 540 postObservationTaskToExecutor(listener.getExecutor(), task); |
| 540 } | 541 } |
| 541 Runnable task = new Runnable() { | |
| 542 @Override | |
| 543 public void run() { | |
| 544 synchronized (mNetworkQualityLock) { | |
| 545 UrlRequestInfo requestInfo = request.getRequestInfo(); | |
| 546 for (RequestFinishedListener listener : mFinishedListenerLis
t) { | |
| 547 listener.onRequestFinished(requestInfo); | |
| 548 } | |
| 549 } | |
| 550 } | |
| 551 }; | |
| 552 // Use {@link mNetworkQualityExecutor} since | |
| 553 // RequestFInishedListeners do not provide an executor. | |
| 554 postObservationTaskToExecutor(mNetworkQualityExecutor, task); | |
| 555 } | 542 } |
| 556 | 543 |
| 557 private static void postObservationTaskToExecutor(Executor executor, Runnabl
e task) { | 544 private static void postObservationTaskToExecutor(Executor executor, Runnabl
e task) { |
| 558 try { | 545 try { |
| 559 executor.execute(task); | 546 executor.execute(task); |
| 560 } catch (RejectedExecutionException failException) { | 547 } catch (RejectedExecutionException failException) { |
| 561 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex
ecutor", | 548 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex
ecutor", |
| 562 failException); | 549 failException); |
| 563 } | 550 } |
| 564 } | 551 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 | 593 |
| 607 @NativeClassQualifiedName("CronetURLRequestContextAdapter") | 594 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
| 608 private native void nativeEnableNetworkQualityEstimator(long nativePtr); | 595 private native void nativeEnableNetworkQualityEstimator(long nativePtr); |
| 609 | 596 |
| 610 @NativeClassQualifiedName("CronetURLRequestContextAdapter") | 597 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
| 611 private native void nativeProvideRTTObservations(long nativePtr, boolean sho
uld); | 598 private native void nativeProvideRTTObservations(long nativePtr, boolean sho
uld); |
| 612 | 599 |
| 613 @NativeClassQualifiedName("CronetURLRequestContextAdapter") | 600 @NativeClassQualifiedName("CronetURLRequestContextAdapter") |
| 614 private native void nativeProvideThroughputObservations(long nativePtr, bool
ean should); | 601 private native void nativeProvideThroughputObservations(long nativePtr, bool
ean should); |
| 615 } | 602 } |
| OLD | NEW |