1 /* 2 * Copyright (C) 2011 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.internal.telephony.dataconnection; 18 19 import android.net.LinkProperties; 20 import android.net.NetworkCapabilities; 21 import android.net.ProxyInfo; 22 import android.os.Message; 23 24 import com.android.internal.telephony.dataconnection.DataConnection.ConnectionParams; 25 import com.android.internal.telephony.dataconnection.DataConnection.DisconnectParams; 26 import com.android.internal.util.AsyncChannel; 27 import com.android.internal.util.Protocol; 28 29 /** 30 * AsyncChannel to a DataConnection 31 */ 32 public class DcAsyncChannel extends AsyncChannel { 33 private static final boolean DBG = false; 34 private String mLogTag; 35 36 private DataConnection mDc; 37 private long mDcThreadId; 38 39 public static final int BASE = Protocol.BASE_DATA_CONNECTION_AC; 40 41 public static final int REQ_IS_INACTIVE = BASE + 0; 42 public static final int RSP_IS_INACTIVE = BASE + 1; 43 44 public static final int REQ_GET_CID = BASE + 2; 45 public static final int RSP_GET_CID = BASE + 3; 46 47 public static final int REQ_GET_APNSETTING = BASE + 4; 48 public static final int RSP_GET_APNSETTING = BASE + 5; 49 50 public static final int REQ_GET_LINK_PROPERTIES = BASE + 6; 51 public static final int RSP_GET_LINK_PROPERTIES = BASE + 7; 52 53 public static final int REQ_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 8; 54 public static final int RSP_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 9; 55 56 public static final int REQ_GET_NETWORK_CAPABILITIES = BASE + 10; 57 public static final int RSP_GET_NETWORK_CAPABILITIES = BASE + 11; 58 59 public static final int REQ_RESET = BASE + 12; 60 public static final int RSP_RESET = BASE + 13; 61 62 private static final int CMD_TO_STRING_COUNT = RSP_RESET - BASE + 1; 63 private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; 64 static { 65 sCmdToString[REQ_IS_INACTIVE - BASE] = "REQ_IS_INACTIVE"; 66 sCmdToString[RSP_IS_INACTIVE - BASE] = "RSP_IS_INACTIVE"; 67 sCmdToString[REQ_GET_CID - BASE] = "REQ_GET_CID"; 68 sCmdToString[RSP_GET_CID - BASE] = "RSP_GET_CID"; 69 sCmdToString[REQ_GET_APNSETTING - BASE] = "REQ_GET_APNSETTING"; 70 sCmdToString[RSP_GET_APNSETTING - BASE] = "RSP_GET_APNSETTING"; 71 sCmdToString[REQ_GET_LINK_PROPERTIES - BASE] = "REQ_GET_LINK_PROPERTIES"; 72 sCmdToString[RSP_GET_LINK_PROPERTIES - BASE] = "RSP_GET_LINK_PROPERTIES"; 73 sCmdToString[REQ_SET_LINK_PROPERTIES_HTTP_PROXY - BASE] = 74 "REQ_SET_LINK_PROPERTIES_HTTP_PROXY"; 75 sCmdToString[RSP_SET_LINK_PROPERTIES_HTTP_PROXY - BASE] = 76 "RSP_SET_LINK_PROPERTIES_HTTP_PROXY"; 77 sCmdToString[REQ_GET_NETWORK_CAPABILITIES - BASE] = "REQ_GET_NETWORK_CAPABILITIES"; 78 sCmdToString[RSP_GET_NETWORK_CAPABILITIES - BASE] = "RSP_GET_NETWORK_CAPABILITIES"; 79 sCmdToString[REQ_RESET - BASE] = "REQ_RESET"; 80 sCmdToString[RSP_RESET - BASE] = "RSP_RESET"; 81 } 82 83 ConnectionParams mLastConnectionParams; 84 85 // Convert cmd to string or null if unknown 86 protected static String cmdToString(int cmd) { 87 cmd -= BASE; 88 if ((cmd >= 0) && (cmd < sCmdToString.length)) { 89 return sCmdToString[cmd]; 90 } else { 91 return AsyncChannel.cmdToString(cmd + BASE); 92 } 93 } 94 95 /** 96 * enum used to notify action taken or necessary to be 97 * taken after the link property is changed. 98 */ 99 public enum LinkPropertyChangeAction { 100 NONE, CHANGED, RESET; 101 102 public static LinkPropertyChangeAction fromInt(int value) { 103 if (value == NONE.ordinal()) { 104 return NONE; 105 } else if (value == CHANGED.ordinal()) { 106 return CHANGED; 107 } else if (value == RESET.ordinal()) { 108 return RESET; 109 } else { 110 throw new RuntimeException("LinkPropertyChangeAction.fromInt: bad value=" + value); 111 } 112 } 113 } 114 115 public DcAsyncChannel(DataConnection dc, String logTag) { 116 mDc = dc; 117 mDcThreadId = mDc.getHandler().getLooper().getThread().getId(); 118 mLogTag = logTag; 119 } 120 121 /** 122 * Request if the state machine is in the inactive state. 123 * Response {@link #rspIsInactive} 124 */ 125 public void reqIsInactive() { 126 sendMessage(REQ_IS_INACTIVE); 127 if (DBG) log("reqIsInactive"); 128 } 129 130 /** 131 * Evaluate RSP_IS_INACTIVE. 132 * 133 * @return true if the state machine is in the inactive state. 134 */ 135 public boolean rspIsInactive(Message response) { 136 boolean retVal = response.arg1 == 1; 137 if (DBG) log("rspIsInactive=" + retVal); 138 return retVal; 139 } 140 141 /** 142 * @return true if the state machine is in the inactive state 143 * and can be used for a new connection. 144 */ 145 public boolean isInactiveSync() { 146 boolean value; 147 if (isCallerOnDifferentThread()) { 148 Message response = sendMessageSynchronously(REQ_IS_INACTIVE); 149 if ((response != null) && (response.what == RSP_IS_INACTIVE)) { 150 value = rspIsInactive(response); 151 } else { 152 log("rspIsInactive error response=" + response); 153 value = false; 154 } 155 } else { 156 value = mDc.isInactive(); 157 } 158 return value; 159 } 160 161 /** 162 * Request the Connection ID. 163 * Response {@link #rspCid} 164 */ 165 public void reqCid() { 166 sendMessage(REQ_GET_CID); 167 if (DBG) log("reqCid"); 168 } 169 170 /** 171 * Evaluate a RSP_GET_CID message and return the cid. 172 * 173 * @param response Message 174 * @return connection id or -1 if an error 175 */ 176 public int rspCid(Message response) { 177 int retVal = response.arg1; 178 if (DBG) log("rspCid=" + retVal); 179 return retVal; 180 } 181 182 /** 183 * @return connection id or -1 if an error 184 */ 185 public int getCidSync() { 186 int value; 187 if (isCallerOnDifferentThread()) { 188 Message response = sendMessageSynchronously(REQ_GET_CID); 189 if ((response != null) && (response.what == RSP_GET_CID)) { 190 value = rspCid(response); 191 } else { 192 log("rspCid error response=" + response); 193 value = -1; 194 } 195 } else { 196 value = mDc.getCid(); 197 } 198 return value; 199 } 200 201 /** 202 * Request the connections ApnSetting. 203 * Response {@link #rspApnSetting} 204 */ 205 public void reqApnSetting() { 206 sendMessage(REQ_GET_APNSETTING); 207 if (DBG) log("reqApnSetting"); 208 } 209 210 /** 211 * Evaluate a RSP_APN_SETTING message and return the ApnSetting. 212 * 213 * @param response Message 214 * @return ApnSetting, maybe null 215 */ 216 public ApnSetting rspApnSetting(Message response) { 217 ApnSetting retVal = (ApnSetting) response.obj; 218 if (DBG) log("rspApnSetting=" + retVal); 219 return retVal; 220 } 221 222 /** 223 * Get the connections ApnSetting. 224 * 225 * @return ApnSetting or null if an error 226 */ 227 public ApnSetting getApnSettingSync() { 228 ApnSetting value; 229 if (isCallerOnDifferentThread()) { 230 Message response = sendMessageSynchronously(REQ_GET_APNSETTING); 231 if ((response != null) && (response.what == RSP_GET_APNSETTING)) { 232 value = rspApnSetting(response); 233 } else { 234 log("getApnSetting error response=" + response); 235 value = null; 236 } 237 } else { 238 value = mDc.getApnSetting(); 239 } 240 return value; 241 } 242 243 /** 244 * Request the connections LinkProperties. 245 * Response {@link #rspLinkProperties} 246 */ 247 public void reqLinkProperties() { 248 sendMessage(REQ_GET_LINK_PROPERTIES); 249 if (DBG) log("reqLinkProperties"); 250 } 251 252 /** 253 * Evaluate RSP_GET_LINK_PROPERTIES 254 * 255 * @param response 256 * @return LinkProperties, maybe null. 257 */ 258 public LinkProperties rspLinkProperties(Message response) { 259 LinkProperties retVal = (LinkProperties) response.obj; 260 if (DBG) log("rspLinkProperties=" + retVal); 261 return retVal; 262 } 263 264 /** 265 * Get the connections LinkProperties. 266 * 267 * @return LinkProperties or null if an error 268 */ 269 public LinkProperties getLinkPropertiesSync() { 270 LinkProperties value; 271 if (isCallerOnDifferentThread()) { 272 Message response = sendMessageSynchronously(REQ_GET_LINK_PROPERTIES); 273 if ((response != null) && (response.what == RSP_GET_LINK_PROPERTIES)) { 274 value = rspLinkProperties(response); 275 } else { 276 log("getLinkProperties error response=" + response); 277 value = null; 278 } 279 } else { 280 value = mDc.getCopyLinkProperties(); 281 } 282 return value; 283 } 284 285 /** 286 * Request setting the connections LinkProperties.HttpProxy. 287 * Response RSP_SET_LINK_PROPERTIES when complete. 288 */ 289 public void reqSetLinkPropertiesHttpProxy(ProxyInfo proxy) { 290 sendMessage(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy); 291 if (DBG) log("reqSetLinkPropertiesHttpProxy proxy=" + proxy); 292 } 293 294 /** 295 * Set the connections LinkProperties.HttpProxy 296 */ 297 public void setLinkPropertiesHttpProxySync(ProxyInfo proxy) { 298 if (isCallerOnDifferentThread()) { 299 Message response = 300 sendMessageSynchronously(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy); 301 if ((response != null) && (response.what == RSP_SET_LINK_PROPERTIES_HTTP_PROXY)) { 302 if (DBG) log("setLinkPropertiesHttpPoxy ok"); 303 } else { 304 log("setLinkPropertiesHttpPoxy error response=" + response); 305 } 306 } else { 307 mDc.setLinkPropertiesHttpProxy(proxy); 308 } 309 } 310 311 /** 312 * Request the connections NetworkCapabilities. 313 * Response {@link #rspNetworkCapabilities} 314 */ 315 public void reqNetworkCapabilities() { 316 sendMessage(REQ_GET_NETWORK_CAPABILITIES); 317 if (DBG) log("reqNetworkCapabilities"); 318 } 319 320 /** 321 * Evaluate RSP_GET_NETWORK_CAPABILITIES 322 * 323 * @param response 324 * @return NetworkCapabilities, maybe null. 325 */ 326 public NetworkCapabilities rspNetworkCapabilities(Message response) { 327 NetworkCapabilities retVal = (NetworkCapabilities) response.obj; 328 if (DBG) log("rspNetworkCapabilities=" + retVal); 329 return retVal; 330 } 331 332 /** 333 * Get the connections NetworkCapabilities. 334 * 335 * @return NetworkCapabilities or null if an error 336 */ 337 public NetworkCapabilities getNetworkCapabilitiesSync() { 338 NetworkCapabilities value; 339 if (isCallerOnDifferentThread()) { 340 Message response = sendMessageSynchronously(REQ_GET_NETWORK_CAPABILITIES); 341 if ((response != null) && (response.what == RSP_GET_NETWORK_CAPABILITIES)) { 342 value = rspNetworkCapabilities(response); 343 } else { 344 value = null; 345 } 346 } else { 347 value = mDc.getNetworkCapabilities(); 348 } 349 return value; 350 } 351 352 /** 353 * Response RSP_RESET when complete 354 */ 355 public void reqReset() { 356 sendMessage(REQ_RESET); 357 if (DBG) log("reqReset"); 358 } 359 360 /** 361 * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg. 362 * Used for cellular networks that use Access Point Names (APN) such 363 * as GSM networks. 364 * 365 * @param apnContext is the Access Point Name to bring up a connection to 366 * @param profileId for the connection 367 * @param rilRadioTechnology Radio technology for the data connection 368 * @param unmeteredUseOnly Indicates the data connection can only used for unmetered purposes 369 * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. 370 * With AsyncResult.userObj set to the original msg.obj, 371 * AsyncResult.result = FailCause and AsyncResult.exception = Exception(). 372 * @param connectionGeneration used to track a single connection request so disconnects can get 373 * ignored if obsolete. 374 */ 375 public void bringUp(ApnContext apnContext, int profileId, int rilRadioTechnology, 376 boolean unmeteredUseOnly, Message onCompletedMsg, 377 int connectionGeneration) { 378 if (DBG) { 379 log("bringUp: apnContext=" + apnContext + "unmeteredUseOnly=" + unmeteredUseOnly 380 + " onCompletedMsg=" + onCompletedMsg); 381 } 382 mLastConnectionParams = new ConnectionParams(apnContext, profileId, rilRadioTechnology, 383 unmeteredUseOnly, onCompletedMsg, connectionGeneration); 384 sendMessage(DataConnection.EVENT_CONNECT, mLastConnectionParams); 385 } 386 387 /** 388 * Tear down the connection through the apn on the network. 389 * 390 * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. 391 * With AsyncResult.userObj set to the original msg.obj. 392 */ 393 public void tearDown(ApnContext apnContext, String reason, Message onCompletedMsg) { 394 if (DBG) { 395 log("tearDown: apnContext=" + apnContext 396 + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg); 397 } 398 sendMessage(DataConnection.EVENT_DISCONNECT, 399 new DisconnectParams(apnContext, reason, onCompletedMsg)); 400 } 401 402 /** 403 * Tear down the connection through the apn on the network. Ignores refcount and 404 * and always tears down. 405 * 406 * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. 407 * With AsyncResult.userObj set to the original msg.obj. 408 */ 409 public void tearDownAll(String reason, Message onCompletedMsg) { 410 if (DBG) log("tearDownAll: reason=" + reason + " onCompletedMsg=" + onCompletedMsg); 411 sendMessage(DataConnection.EVENT_DISCONNECT_ALL, 412 new DisconnectParams(null, reason, onCompletedMsg)); 413 } 414 415 /** 416 * @return connection id 417 */ 418 public int getDataConnectionIdSync() { 419 // Safe because this is owned by the caller. 420 return mDc.getDataConnectionId(); 421 } 422 423 @Override 424 public String toString() { 425 return mDc.getName(); 426 } 427 428 private boolean isCallerOnDifferentThread() { 429 long curThreadId = Thread.currentThread().getId(); 430 boolean value = mDcThreadId != curThreadId; 431 if (DBG) log("isCallerOnDifferentThread: " + value); 432 return value; 433 } 434 435 private void log(String s) { 436 android.telephony.Rlog.d(mLogTag, "DataConnectionAc " + s); 437 } 438 439 public String[] getPcscfAddr() { 440 return mDc.mPcscfAddr; 441 } 442 } 443