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