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

Unified Diff: components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java

Issue 1273173002: Added Network Quality Estimator Real-time interface to Cronet (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nit Created 5 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
index 7bae2883221d5340a4ddbb23c19c9bf4865d978a..cd4b710f7c710b296620ba6ed0e150261833bf48 100644
--- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
+++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
@@ -12,6 +12,7 @@ import android.os.Looper;
import android.os.Process;
import android.util.Log;
+import org.chromium.base.ObserverList;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
@@ -19,8 +20,11 @@ import org.chromium.base.annotations.NativeClassQualifiedName;
import org.chromium.base.annotations.UsedByReflection;
import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
+import javax.annotation.concurrent.GuardedBy;
+
/**
* UrlRequestContext using Chromium HTTP stack implementation.
*/
@@ -42,6 +46,22 @@ class CronetUrlRequestContext extends UrlRequestContext {
private long mUrlRequestContextAdapter = 0;
private Thread mNetworkThread;
+ private Executor mNetworkQualityExecutor;
+ private boolean mNetworkQualityEstimatorEnabled;
+
+ /** Locks operations on network quality listeners, because listener
+ * addition and removal may occur on a different thread from notification.
+ */
+ private final Object mNetworkQualityLock = new Object();
+
+ @GuardedBy("mNetworkQualityLock")
+ private final ObserverList<NetworkQualityRttListener> mRttListenerList =
+ new ObserverList<NetworkQualityRttListener>();
+
+ @GuardedBy("mNetworkQualityLock")
+ private final ObserverList<NetworkQualityThroughputListener> mThroughputListenerList =
+ new ObserverList<NetworkQualityThroughputListener>();
+
@UsedByReflection("UrlRequestContext.java")
public CronetUrlRequestContext(Context context,
UrlRequestContextConfig config) {
@@ -148,6 +168,94 @@ class CronetUrlRequestContext extends UrlRequestContext {
}
}
+ @Override
+ public void enableNetworkQualityEstimator(Executor executor) {
+ enableNetworkQualityEstimatorForTesting(false, false, executor);
+ }
+
+ @VisibleForTesting
+ @Override
+ void enableNetworkQualityEstimatorForTesting(
+ boolean useLocalHostRequests, boolean useSmallerResponses, Executor executor) {
+ if (mNetworkQualityEstimatorEnabled) {
+ throw new IllegalStateException("Network quality estimator already enabled");
+ }
+ mNetworkQualityEstimatorEnabled = true;
+ if (executor == null) {
+ throw new NullPointerException("Network quality estimator requires an executor");
+ }
+ mNetworkQualityExecutor = executor;
+ synchronized (mLock) {
+ checkHaveAdapter();
+ nativeEnableNetworkQualityEstimator(
+ mUrlRequestContextAdapter, useLocalHostRequests, useSmallerResponses);
+ }
+ }
+
+ @Override
+ public void addRttListener(NetworkQualityRttListener listener) {
+ if (!mNetworkQualityEstimatorEnabled) {
+ throw new IllegalStateException("Network quality estimator must be enabled");
+ }
+ synchronized (mNetworkQualityLock) {
+ if (mRttListenerList.isEmpty()) {
+ synchronized (mLock) {
+ checkHaveAdapter();
+ nativeProvideRTTObservations(mUrlRequestContextAdapter, true);
+ }
+ }
+ mRttListenerList.addObserver(listener);
+ }
+ }
+
+ @Override
+ public void removeRttListener(NetworkQualityRttListener listener) {
+ if (!mNetworkQualityEstimatorEnabled) {
+ throw new IllegalStateException("Network quality estimator must be enabled");
+ }
+ synchronized (mNetworkQualityLock) {
+ mRttListenerList.removeObserver(listener);
+ if (mRttListenerList.isEmpty()) {
+ synchronized (mLock) {
+ checkHaveAdapter();
+ nativeProvideRTTObservations(mUrlRequestContextAdapter, false);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void addThroughputListener(NetworkQualityThroughputListener listener) {
+ if (!mNetworkQualityEstimatorEnabled) {
+ throw new IllegalStateException("Network quality estimator must be enabled");
+ }
+ synchronized (mNetworkQualityLock) {
+ if (mThroughputListenerList.isEmpty()) {
+ synchronized (mLock) {
+ checkHaveAdapter();
+ nativeProvideThroughputObservations(mUrlRequestContextAdapter, true);
+ }
+ }
+ mThroughputListenerList.addObserver(listener);
+ }
+ }
+
+ @Override
+ public void removeThroughputListener(NetworkQualityThroughputListener listener) {
+ if (!mNetworkQualityEstimatorEnabled) {
+ throw new IllegalStateException("Network quality estimator must be enabled");
+ }
+ synchronized (mNetworkQualityLock) {
+ mThroughputListenerList.removeObserver(listener);
+ if (mThroughputListenerList.isEmpty()) {
+ synchronized (mLock) {
+ checkHaveAdapter();
+ nativeProvideThroughputObservations(mUrlRequestContextAdapter, false);
+ }
+ }
+ }
+ }
+
/**
* Mark request as started to prevent shutdown when there are active
* requests.
@@ -209,6 +317,48 @@ class CronetUrlRequestContext extends UrlRequestContext {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private void onRttObservation(final int rttMs, final long whenMs, final int source) {
+ Runnable task = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mNetworkQualityLock) {
+ for (NetworkQualityRttListener listener : mRttListenerList) {
+ listener.onRttObservation(rttMs, whenMs, source);
+ }
+ }
+ }
+ };
+ postObservationTaskToNetworkQualityExecutor(task);
+ }
+
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private void onThroughputObservation(
+ final int throughputKbps, final long whenMs, final int source) {
+ Runnable task = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mNetworkQualityLock) {
+ for (NetworkQualityThroughputListener listener : mThroughputListenerList) {
+ listener.onThroughputObservation(throughputKbps, whenMs, source);
+ }
+ }
+ }
+ };
+ postObservationTaskToNetworkQualityExecutor(task);
+ }
+
+ void postObservationTaskToNetworkQualityExecutor(Runnable task) {
+ try {
+ mNetworkQualityExecutor.execute(task);
+ } catch (RejectedExecutionException failException) {
+ Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to executor",
+ failException);
+ }
+ }
+
// Native methods are implemented in cronet_url_request_context.cc.
private static native long nativeCreateRequestContextAdapter(String config);
@@ -226,4 +376,14 @@ class CronetUrlRequestContext extends UrlRequestContext {
@NativeClassQualifiedName("CronetURLRequestContextAdapter")
private native void nativeInitRequestContextOnMainThread(long nativePtr);
+
+ @NativeClassQualifiedName("CronetURLRequestContextAdapter")
+ private native void nativeEnableNetworkQualityEstimator(
+ long nativePtr, boolean useLocalHostRequests, boolean useSmallerResponses);
+
+ @NativeClassQualifiedName("CronetURLRequestContextAdapter")
+ private native void nativeProvideRTTObservations(long nativePtr, boolean should);
+
+ @NativeClassQualifiedName("CronetURLRequestContextAdapter")
+ private native void nativeProvideThroughputObservations(long nativePtr, boolean should);
}

Powered by Google App Engine
This is Rietveld 408576698