1 /* 2 * Copyright 2016, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.managedprovisioning.task.wifi; 18 19 import static com.android.internal.util.Preconditions.checkNotNull; 20 21 import android.content.Context; 22 import android.net.ConnectivityManager; 23 import android.net.ConnectivityManager.NetworkCallback; 24 import android.net.Network; 25 import android.net.NetworkCapabilities; 26 27 import com.android.managedprovisioning.common.ProvisionLogger; 28 29 /** 30 * Monitor the state of the data network. Invoke a callback when the network is connected. 31 * 32 * The callback may be called multiple times for the same network as its status changes. 33 */ 34 public class NetworkMonitor { 35 36 /** State notification callback. Expect some duplicate notifications. */ 37 public interface NetworkConnectedCallback { onNetworkConnected()38 void onNetworkConnected(); 39 } 40 41 private final Context mContext; 42 private final boolean mWaitForValidated; 43 44 private NetworkConnectedCallback mCallback = null; 45 46 /** 47 * Start watching the network. Immediately invokes the callback method to report the 48 * current default network if any, and then invokes callback methods over time as the default 49 * network changes. 50 * 51 * @param context to use for intent observers and such 52 */ NetworkMonitor(Context context, boolean waitForValidated)53 public NetworkMonitor(Context context, boolean waitForValidated) { 54 mContext = checkNotNull(context); 55 mWaitForValidated = waitForValidated; 56 } 57 58 /** 59 * Start listening for connectivity changes. 60 * @param callback Callback to inform about those changes. 61 */ startListening(NetworkConnectedCallback callback)62 public synchronized void startListening(NetworkConnectedCallback callback) { 63 mCallback = checkNotNull(callback); 64 // TODO: this code has always kept track of the default network, but it should probably 65 // instead use registerNetworkCallback or even requestNetwork with a specific 66 // NetworkRequest.Builder#addTransportType transport depending on the caller. For example, 67 // ConnectMobileNetworkTask should file a request for TRANSPORT_CELLULAR instead of waiting 68 // for any network to be available. When requestNetwork is not used, cellular data is also 69 // not guaranteed to connect after being enabled if another network is already available. 70 mContext.getSystemService(ConnectivityManager.class) 71 .registerDefaultNetworkCallback(mConnectivityCallback); 72 } 73 74 /** 75 * Stop listening for connectivity changes. 76 */ stopListening()77 public synchronized void stopListening() { 78 if (mCallback == null) { 79 return; 80 } 81 82 mCallback = null; 83 mContext.getSystemService(ConnectivityManager.class) 84 .unregisterNetworkCallback(mConnectivityCallback); 85 } 86 87 private final NetworkCallback mConnectivityCallback = new NetworkCallback() { 88 private boolean mBlocked; 89 private boolean mValidated; 90 91 @Override 92 public void onAvailable(Network network) { 93 // Default network switched to a new network. Set internal state to values that will 94 // not cause a callback to be sent. onBlockedStatusChanged and onCapabilitiesChanged 95 // will be called immediately after (then later on changes). 96 mBlocked = true; 97 mValidated = false; 98 } 99 100 @Override 101 public void onBlockedStatusChanged(Network network, boolean blocked) { 102 if (mBlocked == blocked) { 103 return; 104 } 105 ProvisionLogger.logd("NetworkMonitor.onBlockedStatusChanged: " + network 106 + " blocked=" + blocked); 107 mBlocked = blocked; 108 maybeSendCallback(); 109 } 110 111 @Override 112 public void onCapabilitiesChanged(Network network, NetworkCapabilities caps) { 113 final boolean validated = caps.hasCapability( 114 NetworkCapabilities.NET_CAPABILITY_VALIDATED); 115 if (!mWaitForValidated || mValidated == validated) { 116 return; 117 } 118 ProvisionLogger.logd("NetworkMonitor.onCapabilitiesChanged: " + network 119 + " validated=" + validated); 120 mValidated = validated; 121 maybeSendCallback(); 122 } 123 124 private void maybeSendCallback() { 125 // Receiving blocked=false is the equivalent to legacy behavior that would verify 126 // getActiveNetworkInfo().isConnected() 127 if (mBlocked || (mWaitForValidated && !mValidated)) { 128 return; 129 } 130 synchronized (NetworkMonitor.this) { 131 if (mCallback != null) { 132 mCallback.onNetworkConnected(); 133 } 134 } 135 } 136 }; 137 } 138