1 /* 2 * Copyright (C) 2014 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 android.net; 18 19 import android.content.Context; 20 import android.os.Handler; 21 import android.os.Looper; 22 import android.os.Message; 23 import android.os.Messenger; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.util.Log; 27 28 import com.android.internal.util.AsyncChannel; 29 import com.android.internal.util.Protocol; 30 31 import java.util.ArrayList; 32 import java.util.concurrent.atomic.AtomicBoolean; 33 34 /** 35 * A Utility class for handling for communicating between bearer-specific 36 * code and ConnectivityService. 37 * 38 * A bearer may have more than one NetworkAgent if it can simultaneously 39 * support separate networks (IMS / Internet / MMS Apns on cellular, or 40 * perhaps connections with different SSID or P2P for Wi-Fi). 41 * 42 * @hide 43 */ 44 public abstract class NetworkAgent extends Handler { 45 private volatile AsyncChannel mAsyncChannel; 46 private final String LOG_TAG; 47 private static final boolean DBG = true; 48 private static final boolean VDBG = false; 49 private final Context mContext; 50 private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>(); 51 52 private static final int BASE = Protocol.BASE_NETWORK_AGENT; 53 54 /** 55 * Sent by ConnectivityService to the NetworkAgent to inform it of 56 * suspected connectivity problems on its network. The NetworkAgent 57 * should take steps to verify and correct connectivity. 58 */ 59 public static final int CMD_SUSPECT_BAD = BASE; 60 61 /** 62 * Sent by the NetworkAgent (note the EVENT vs CMD prefix) to 63 * ConnectivityService to pass the current NetworkInfo (connection state). 64 * Sent when the NetworkInfo changes, mainly due to change of state. 65 * obj = NetworkInfo 66 */ 67 public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1; 68 69 /** 70 * Sent by the NetworkAgent to ConnectivityService to pass the current 71 * NetworkCapabilties. 72 * obj = NetworkCapabilities 73 */ 74 public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2; 75 76 /** 77 * Sent by the NetworkAgent to ConnectivityService to pass the current 78 * NetworkProperties. 79 * obj = NetworkProperties 80 */ 81 public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; 82 83 /* centralize place where base network score, and network score scaling, will be 84 * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE 85 */ 86 public static final int WIFI_BASE_SCORE = 60; 87 88 /** 89 * Sent by the NetworkAgent to ConnectivityService to pass the current 90 * network score. 91 * obj = network score Integer 92 */ 93 public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; 94 95 /** 96 * Sent by the NetworkAgent to ConnectivityService to add new UID ranges 97 * to be forced into this Network. For VPNs only. 98 * obj = UidRange[] to forward 99 */ 100 public static final int EVENT_UID_RANGES_ADDED = BASE + 5; 101 102 /** 103 * Sent by the NetworkAgent to ConnectivityService to remove UID ranges 104 * from being forced into this Network. For VPNs only. 105 * obj = UidRange[] to stop forwarding 106 */ 107 public static final int EVENT_UID_RANGES_REMOVED = BASE + 6; 108 109 /** 110 * Sent by ConnectivitySerice to the NetworkAgent to inform the agent of the 111 * networks status - whether we could use the network or could not, due to 112 * either a bad network configuration (no internet link) or captive portal. 113 * 114 * arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK} 115 */ 116 public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7; 117 118 public static final int VALID_NETWORK = 1; 119 public static final int INVALID_NETWORK = 2; 120 121 /** 122 * Sent by the NetworkAgent to ConnectivityService to indicate this network was 123 * explicitly selected. This should be sent before the NetworkInfo is marked 124 * CONNECTED so it can be given special treatment at that time. 125 */ 126 public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 8; 127 128 public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, 129 NetworkCapabilities nc, LinkProperties lp, int score) { 130 this(looper, context, logTag, ni, nc, lp, score, null); 131 } 132 133 public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, 134 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 135 super(looper); 136 LOG_TAG = logTag; 137 mContext = context; 138 if (ni == null || nc == null || lp == null) { 139 throw new IllegalArgumentException(); 140 } 141 142 if (VDBG) log("Registering NetworkAgent"); 143 ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( 144 Context.CONNECTIVITY_SERVICE); 145 cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), 146 new LinkProperties(lp), new NetworkCapabilities(nc), score, misc); 147 } 148 149 @Override 150 public void handleMessage(Message msg) { 151 switch (msg.what) { 152 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { 153 if (mAsyncChannel != null) { 154 log("Received new connection while already connected!"); 155 } else { 156 if (VDBG) log("NetworkAgent fully connected"); 157 AsyncChannel ac = new AsyncChannel(); 158 ac.connected(null, this, msg.replyTo); 159 ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, 160 AsyncChannel.STATUS_SUCCESSFUL); 161 synchronized (mPreConnectedQueue) { 162 mAsyncChannel = ac; 163 for (Message m : mPreConnectedQueue) { 164 ac.sendMessage(m); 165 } 166 mPreConnectedQueue.clear(); 167 } 168 } 169 break; 170 } 171 case AsyncChannel.CMD_CHANNEL_DISCONNECT: { 172 if (VDBG) log("CMD_CHANNEL_DISCONNECT"); 173 if (mAsyncChannel != null) mAsyncChannel.disconnect(); 174 break; 175 } 176 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 177 if (DBG) log("NetworkAgent channel lost"); 178 // let the client know CS is done with us. 179 unwanted(); 180 synchronized (mPreConnectedQueue) { 181 mAsyncChannel = null; 182 } 183 break; 184 } 185 case CMD_SUSPECT_BAD: { 186 log("Unhandled Message " + msg); 187 break; 188 } 189 case CMD_REPORT_NETWORK_STATUS: { 190 if (VDBG) { 191 log("CMD_REPORT_NETWORK_STATUS(" + 192 (msg.arg1 == VALID_NETWORK ? "VALID)" : "INVALID)")); 193 } 194 networkStatus(msg.arg1); 195 break; 196 } 197 } 198 } 199 200 private void queueOrSendMessage(int what, Object obj) { 201 synchronized (mPreConnectedQueue) { 202 if (mAsyncChannel != null) { 203 mAsyncChannel.sendMessage(what, obj); 204 } else { 205 Message msg = Message.obtain(); 206 msg.what = what; 207 msg.obj = obj; 208 mPreConnectedQueue.add(msg); 209 } 210 } 211 } 212 213 /** 214 * Called by the bearer code when it has new LinkProperties data. 215 */ 216 public void sendLinkProperties(LinkProperties linkProperties) { 217 queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties)); 218 } 219 220 /** 221 * Called by the bearer code when it has new NetworkInfo data. 222 */ 223 public void sendNetworkInfo(NetworkInfo networkInfo) { 224 queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo)); 225 } 226 227 /** 228 * Called by the bearer code when it has new NetworkCapabilities data. 229 */ 230 public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) { 231 queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, 232 new NetworkCapabilities(networkCapabilities)); 233 } 234 235 /** 236 * Called by the bearer code when it has a new score for this network. 237 */ 238 public void sendNetworkScore(int score) { 239 if (score < 0) { 240 throw new IllegalArgumentException("Score must be >= 0"); 241 } 242 queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score)); 243 } 244 245 /** 246 * Called by the VPN code when it wants to add ranges of UIDs to be routed 247 * through the VPN network. 248 */ 249 public void addUidRanges(UidRange[] ranges) { 250 queueOrSendMessage(EVENT_UID_RANGES_ADDED, ranges); 251 } 252 253 /** 254 * Called by the VPN code when it wants to remove ranges of UIDs from being routed 255 * through the VPN network. 256 */ 257 public void removeUidRanges(UidRange[] ranges) { 258 queueOrSendMessage(EVENT_UID_RANGES_REMOVED, ranges); 259 } 260 261 /** 262 * Called by the bearer to indicate this network was manually selected by the user. 263 * This should be called before the NetworkInfo is marked CONNECTED so that this 264 * Network can be given special treatment at that time. 265 */ 266 public void explicitlySelected() { 267 queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, 0); 268 } 269 270 /** 271 * Called when ConnectivityService has indicated they no longer want this network. 272 * The parent factory should (previously) have received indication of the change 273 * as well, either canceling NetworkRequests or altering their score such that this 274 * network won't be immediately requested again. 275 */ 276 abstract protected void unwanted(); 277 278 /** 279 * Called when the system determines the usefulness of this network. 280 * 281 * Networks claiming internet connectivity will have their internet 282 * connectivity verified. 283 * 284 * Currently there are two possible values: 285 * {@code VALID_NETWORK} if the system is happy with the connection, 286 * {@code INVALID_NETWORK} if the system is not happy. 287 * TODO - add indications of captive portal-ness and related success/failure, 288 * ie, CAPTIVE_SUCCESS_NETWORK, CAPTIVE_NETWORK for successful login and detection 289 * 290 * This may be called multiple times as the network status changes and may 291 * generate false negatives if we lose ip connectivity before the link is torn down. 292 */ 293 protected void networkStatus(int status) { 294 } 295 296 protected void log(String s) { 297 Log.d(LOG_TAG, "NetworkAgent: " + s); 298 } 299 } 300