| Index: net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
|
| diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
|
| index 19a3e33512af38609d7f94b396a4edbd9c58afc2..5808341dc1cc24fa70c4eddd219c91a5f307bbdc 100644
|
| --- a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
|
| +++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
|
| @@ -26,10 +26,15 @@ import android.net.NetworkRequest;
|
| import android.net.wifi.WifiInfo;
|
| import android.net.wifi.WifiManager;
|
| import android.os.Build;
|
| +import android.os.Handler;
|
| +import android.os.HandlerThread;
|
| +import android.os.Looper;
|
| +import android.os.Process;
|
| import android.telephony.TelephonyManager;
|
|
|
| import org.chromium.base.ApplicationState;
|
| import org.chromium.base.ApplicationStatus;
|
| +import org.chromium.base.BuildConfig;
|
| import org.chromium.base.ThreadUtils;
|
| import org.chromium.base.VisibleForTesting;
|
| import org.chromium.base.metrics.RecordHistogram;
|
| @@ -365,7 +370,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| }
|
|
|
| String getWifiSsid() {
|
| - // Synchronized because this method can be called on multiple threads (e.g. UI thread
|
| + // Synchronized because this method can be called on multiple threads (e.g. mLooper
|
| // from a private caller, and another thread calling a public API like
|
| // getCurrentNetworkState) and is otherwise racy.
|
| synchronized (mLock) {
|
| @@ -407,7 +412,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| // This class gets called back by ConnectivityManager whenever networks come
|
| // and go. It gets called back on a special handler thread
|
| // ConnectivityManager creates for making the callbacks. The callbacks in
|
| - // turn post to the UI thread where mObserver lives.
|
| + // turn post to mLooper where mObserver lives.
|
| @TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
| private class MyNetworkCallback extends NetworkCallback {
|
| // If non-null, this indicates a VPN is in place for the current user, and no other
|
| @@ -482,7 +487,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| final long netId = networkToNetId(network);
|
| @ConnectionTypeEnum
|
| final int connectionType = mConnectivityManagerDelegate.getConnectionType(network);
|
| - ThreadUtils.postOnUiThread(new Runnable() {
|
| + runOnThread(new Runnable() {
|
| @Override
|
| public void run() {
|
| mObserver.onNetworkConnect(netId, connectionType);
|
| @@ -506,7 +511,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| // so forward the new ConnectionType along to observer.
|
| final long netId = networkToNetId(network);
|
| final int connectionType = mConnectivityManagerDelegate.getConnectionType(network);
|
| - ThreadUtils.postOnUiThread(new Runnable() {
|
| + runOnThread(new Runnable() {
|
| @Override
|
| public void run() {
|
| mObserver.onNetworkConnect(netId, connectionType);
|
| @@ -520,7 +525,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| return;
|
| }
|
| final long netId = networkToNetId(network);
|
| - ThreadUtils.postOnUiThread(new Runnable() {
|
| + runOnThread(new Runnable() {
|
| @Override
|
| public void run() {
|
| mObserver.onNetworkSoonToDisconnect(netId);
|
| @@ -533,7 +538,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| if (ignoreNetworkDueToVpn(network)) {
|
| return;
|
| }
|
| - ThreadUtils.postOnUiThread(new Runnable() {
|
| + runOnThread(new Runnable() {
|
| @Override
|
| public void run() {
|
| mObserver.onNetworkDisconnect(networkToNetId(network));
|
| @@ -551,7 +556,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| }
|
| @ConnectionTypeEnum
|
| final int newConnectionType = convertToConnectionType(getCurrentNetworkState());
|
| - ThreadUtils.postOnUiThread(new Runnable() {
|
| + runOnThread(new Runnable() {
|
| @Override
|
| public void run() {
|
| mObserver.onConnectionTypeChanged(newConnectionType);
|
| @@ -595,9 +600,12 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| protected abstract void destroy();
|
| }
|
|
|
| - private static final String TAG = "NetworkChangeNotifierAutoDetect";
|
| + private static final String TAG = NetworkChangeNotifierAutoDetect.class.getSimpleName();
|
| private static final int UNKNOWN_LINK_SPEED = -1;
|
|
|
| + private final Looper mLooper;
|
| + private final Handler mHandler;
|
| +
|
| private final NetworkConnectivityIntentFilter mIntentFilter;
|
| private final Observer mObserver;
|
| private final Context mContext;
|
| @@ -674,7 +682,8 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| }
|
|
|
| /**
|
| - * Constructs a NetworkChangeNotifierAutoDetect. Should only be called on UI thread.
|
| + * Constructs a NetworkChangeNotifierAutoDetect. If called on UI thread, then this instance
|
| + * lives on UI thread, otherwise lives on a new internal thread.
|
| * @param policy The RegistrationPolicy which determines when this class should watch
|
| * for network changes (e.g. see (@link RegistrationPolicyAlwaysRegister} and
|
| * {@link RegistrationPolicyApplicationStatus}).
|
| @@ -682,9 +691,14 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| @TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
| public NetworkChangeNotifierAutoDetect(
|
| Observer observer, Context context, RegistrationPolicy policy) {
|
| - // Since BroadcastReceiver is always called back on UI thread, ensure
|
| - // running on UI thread so notification logic can be single-threaded.
|
| - ThreadUtils.assertOnUiThread();
|
| + if (ThreadUtils.runningOnUiThread()) {
|
| + mLooper = ThreadUtils.getUiThreadLooper();
|
| + } else {
|
| + HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
|
| + thread.start();
|
| + mLooper = thread.getLooper();
|
| + }
|
| + mHandler = new Handler(mLooper);
|
| mObserver = observer;
|
| mContext = context.getApplicationContext();
|
| mConnectivityManagerDelegate = new ConnectivityManagerDelegate(context);
|
| @@ -713,6 +727,25 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| mShouldSignalObserver = true;
|
| }
|
|
|
| + private boolean onThread() {
|
| + return mLooper == Looper.myLooper();
|
| + }
|
| +
|
| + private void assertOnLooper() {
|
| + if (BuildConfig.DCHECK_IS_ON && !onThread()) {
|
| + throw new IllegalStateException(
|
| + "Must be called on NetworkChangeNotifierAutoDetect thread.");
|
| + }
|
| + }
|
| +
|
| + private void runOnThread(Runnable r) {
|
| + if (onThread()) {
|
| + r.run();
|
| + } else {
|
| + mHandler.post(r);
|
| + }
|
| + }
|
| +
|
| /**
|
| * Allows overriding the ConnectivityManagerDelegate for tests.
|
| */
|
| @@ -741,6 +774,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| }
|
|
|
| public void destroy() {
|
| + assertOnLooper();
|
| mRegistrationPolicy.destroy();
|
| unregister();
|
| }
|
| @@ -749,7 +783,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| * Registers a BroadcastReceiver in the given context.
|
| */
|
| public void register() {
|
| - ThreadUtils.assertOnUiThread();
|
| + assertOnLooper();
|
| if (mRegistered) return;
|
|
|
| if (mShouldSignalObserver) {
|
| @@ -789,6 +823,7 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| * Unregisters a BroadcastReceiver in the given context.
|
| */
|
| public void unregister() {
|
| + assertOnLooper();
|
| if (!mRegistered) return;
|
| mContext.unregisterReceiver(this);
|
| mRegistered = false;
|
| @@ -996,15 +1031,18 @@ public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver {
|
| // BroadcastReceiver
|
| @Override
|
| public void onReceive(Context context, Intent intent) {
|
| - if (mIgnoreNextBroadcast) {
|
| - mIgnoreNextBroadcast = false;
|
| - return;
|
| - }
|
| - final NetworkState networkState = getCurrentNetworkState();
|
| - if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
|
| - connectionTypeChanged(networkState);
|
| - maxBandwidthChanged(networkState);
|
| - }
|
| + runOnThread(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + if (mIgnoreNextBroadcast) {
|
| + mIgnoreNextBroadcast = false;
|
| + return;
|
| + }
|
| + final NetworkState networkState = getCurrentNetworkState();
|
| + connectionTypeChanged(networkState);
|
| + maxBandwidthChanged(networkState);
|
| + }
|
| + });
|
| }
|
|
|
| private void connectionTypeChanged(NetworkState networkState) {
|
|
|