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 NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score)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 NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc)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 handleMessage(Message msg)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 queueOrSendMessage(int what, Object obj)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 */ sendLinkProperties(LinkProperties linkProperties)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 */ sendNetworkInfo(NetworkInfo networkInfo)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 */ sendNetworkCapabilities(NetworkCapabilities networkCapabilities)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 */ sendNetworkScore(int score)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 */ addUidRanges(UidRange[] ranges)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 */ removeUidRanges(UidRange[] ranges)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 */ explicitlySelected()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 */ unwanted()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 */ networkStatus(int status)293 protected void networkStatus(int status) { 294 } 295 log(String s)296 protected void log(String s) { 297 Log.d(LOG_TAG, "NetworkAgent: " + s); 298 } 299 } 300