| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.internal.telephony.cdma; |
| |
| import android.os.*; |
| import android.util.EventLog; |
| import android.util.Log; |
| |
| import com.android.internal.telephony.CommandException; |
| import com.android.internal.telephony.CommandsInterface; |
| import com.android.internal.telephony.DataConnection; |
| import com.android.internal.telephony.DataLink; |
| import com.android.internal.telephony.RILConstants; |
| import com.android.internal.telephony.TelephonyEventLog; |
| |
| /** |
| * {@hide} |
| * |
| */ |
| public class CdmaDataConnection extends DataConnection { |
| |
| private static final String LOG_TAG = "CDMA"; |
| private static final boolean DBG = true; |
| |
| /** Fail cause of last Data Call activate from RIL_LastDataCallActivateFailCause */ |
| private final static int PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING = 8; |
| private final static int PS_NET_DOWN_REASON_UNKNOWN_APN = 27; |
| private final static int PS_NET_DOWN_REASON_AUTH_FAILED = 29; |
| private final static int PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED = 32; |
| private final static int PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED = 33; |
| |
| /** It is likely that the number of error codes listed below will be removed |
| * in the foreseeable future. They have been added, but not agreed upon. |
| * |
| */ |
| private final static int PS_NET_DOWN_REASON_NOT_SPECIFIED = 0; |
| private final static int PS_NET_DOWN_REASON_CLOSE_IN_PROGRESS = 1; |
| private final static int PS_NET_DOWN_REASON_NW_INITIATED_TERMINATION = 2; |
| private final static int PS_NET_DOWN_REASON_APP_PREEMPTED = 3; |
| private final static int PS_NET_DOWN_REASON_LLC_SNDCP_FAILURE = 25; |
| private final static int PS_NET_DOWN_REASON_INSUFFICIENT_RESOURCES = 26; |
| private final static int PS_NET_DOWN_REASON_UNKNOWN_PDP = 28; |
| private final static int PS_NET_DOWN_REASON_GGSN_REJECT = 30; |
| private final static int PS_NET_DOWN_REASON_ACTIVATION_REJECT = 31; |
| private final static int PS_NET_DOWN_REASON_OPTION_TEMP_OOO = 34; |
| private final static int PS_NET_DOWN_REASON_NSAPI_ALREADY_USED = 35; |
| private final static int PS_NET_DOWN_REASON_REGULAR_DEACTIVATION = 36; |
| private final static int PS_NET_DOWN_REASON_QOS_NOT_ACCEPTED = 37; |
| private final static int PS_NET_DOWN_REASON_NETWORK_FAILURE = 38; |
| private final static int PS_NET_DOWN_REASON_UMTS_REATTACH_REQ = 39; |
| private final static int PS_NET_DOWN_REASON_TFT_SEMANTIC_ERROR = 41; |
| private final static int PS_NET_DOWN_REASON_TFT_SYNTAX_ERROR = 42; |
| private final static int PS_NET_DOWN_REASON_UNKNOWN_PDP_CONTEXT = 43; |
| private final static int PS_NET_DOWN_REASON_FILTER_SEMANTIC_ERROR = 44; |
| private final static int PS_NET_DOWN_REASON_FILTER_SYNTAX_ERROR = 45; |
| private final static int PS_NET_DOWN_REASON_PDP_WITHOUT_ACTIVE_TFT = 46; |
| private final static int PS_NET_DOWN_REASON_INVALID_TRANSACTION_ID = 81; |
| private final static int PS_NET_DOWN_REASON_MESSAGE_INCORRECT_SEMANTIC = 95; |
| private final static int PS_NET_DOWN_REASON_INVALID_MANDATORY_INFO = 96; |
| private final static int PS_NET_DOWN_REASON_MESSAGE_TYPE_UNSUPPORTED = 97; |
| private final static int PS_NET_DOWN_REASON_MSG_TYPE_NONCOMPATIBLE_STATE = 98; |
| private final static int PS_NET_DOWN_REASON_UNKNOWN_INFO_ELEMENT = 99; |
| private final static int PS_NET_DOWN_REASON_CONDITIONAL_IE_ERROR = 100; |
| private final static int PS_NET_DOWN_REASON_MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101; |
| private final static int PS_NET_DOWN_REASON_PROTOCOL_ERROR = 111; |
| private final static int PS_NET_DOWN_REASON_APN_TYPE_CONFLICT = 112; |
| private final static int PS_NET_DOWN_REASON_UNKNOWN_CAUSE_CODE = 113; |
| private final static int PS_NET_DOWN_REASON_INTERNAL_MIN = 200; |
| private final static int PS_NET_DOWN_REASON_INTERNAL_ERROR = 201; |
| private final static int PS_NET_DOWN_REASON_INTERNAL_CALL_ENDED = 202; |
| private final static int PS_NET_DOWN_REASON_INTERNAL_UNKNOWN_CAUSE_CODE = 203; |
| private final static int PS_NET_DOWN_REASON_INTERNAL_MAX = 204; |
| private final static int PS_NET_DOWN_REASON_CDMA_LOCK = 500; |
| private final static int PS_NET_DOWN_REASON_INTERCEPT = 501; |
| private final static int PS_NET_DOWN_REASON_REORDER = 502; |
| private final static int PS_NET_DOWN_REASON_REL_SO_REJ = 503; |
| private final static int PS_NET_DOWN_REASON_INCOM_CALL = 504; |
| private final static int PS_NET_DOWN_REASON_ALERT_STOP = 505; |
| private final static int PS_NET_DOWN_REASON_ACTIVATION = 506; |
| private final static int PS_NET_DOWN_REASON_MAX_ACCESS_PROBE = 507; |
| private final static int PS_NET_DOWN_REASON_CCS_NOT_SUPPORTED_BY_BS = 508; |
| private final static int PS_NET_DOWN_REASON_NO_RESPONSE_FROM_BS = 509; |
| private final static int PS_NET_DOWN_REASON_REJECTED_BY_BS = 510; |
| private final static int PS_NET_DOWN_REASON_INCOMPATIBLE = 511; |
| private final static int PS_NET_DOWN_REASON_ALREADY_IN_TC = 512; |
| private final static int PS_NET_DOWN_REASON_USER_CALL_ORIG_DURING_GPS = 513; |
| private final static int PS_NET_DOWN_REASON_USER_CALL_ORIG_DURING_SMS = 514; |
| private final static int PS_NET_DOWN_REASON_NO_CDMA_SRV = 515; |
| private final static int PS_NET_DOWN_REASON_CONF_FAILED = 1000; |
| private final static int PS_NET_DOWN_REASON_INCOM_REJ = 1001; |
| private final static int PS_NET_DOWN_REASON_NO_GW_SRV = 1002; |
| private final static int PS_NET_DOWN_REASON_CD_GEN_OR_BUSY = 1500; |
| private final static int PS_NET_DOWN_REASON_CD_BILL_OR_AUTH = 1501; |
| private final static int PS_NET_DOWN_REASON_CHG_HDR = 1502; |
| private final static int PS_NET_DOWN_REASON_EXIT_HDR = 1503; |
| private final static int PS_NET_DOWN_REASON_HDR_NO_SESSION = 1504; |
| private final static int PS_NET_DOWN_REASON_HDR_ORIG_DURING_GPS_FIX = 1505; |
| private final static int PS_NET_DOWN_REASON_HDR_CS_TIMEOUT = 1506; |
| private final static int PS_NET_DOWN_REASON_HDR_RELEASED_BY_CM = 1507; |
| private final static int PS_NET_DOWN_REASON_CLIENT_END = 2000; |
| private final static int PS_NET_DOWN_REASON_NO_SRV = 2001; |
| private final static int PS_NET_DOWN_REASON_FADE = 2002; |
| private final static int PS_NET_DOWN_REASON_REL_NORMAL = 2003; |
| private final static int PS_NET_DOWN_REASON_ACC_IN_PROG = 2004; |
| private final static int PS_NET_DOWN_REASON_ACC_FAIL = 2005; |
| private final static int PS_NET_DOWN_REASON_REDIR_OR_HANDOFF = 2006; |
| |
| // ***** Instance Variables |
| |
| // ***** Constructor |
| CdmaDataConnection(CDMAPhone phone) { |
| super(phone); |
| |
| if (DBG) log("CdmaDataConnection <constructor>"); |
| } |
| |
| /** |
| * Setup a data connection |
| * |
| * @param onCompleted |
| * notify success or not after down |
| */ |
| void connect(Message onCompleted) { |
| if (DBG) log("CdmaDataConnection Connecting..."); |
| |
| state = State.ACTIVATING; |
| onConnectCompleted = onCompleted; |
| createTime = -1; |
| lastFailTime = -1; |
| lastFailCause = FailCause.NONE; |
| receivedDisconnectReq = false; |
| phone.mCM.setupDataCall(Integer.toString(RILConstants.CDMA_PHONE), |
| Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), null, null, |
| null, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE)); |
| } |
| |
| private void tearDownData(Message msg) { |
| if (phone.mCM.getRadioState().isOn()) { |
| phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg)); |
| } |
| } |
| |
| protected void disconnect(Message msg) { |
| onDisconnect = msg; |
| if (state == State.ACTIVE) { |
| tearDownData(msg); |
| } else if (state == State.ACTIVATING) { |
| receivedDisconnectReq = true; |
| } else { |
| // state == INACTIVE. Nothing to do, so notify immediately. |
| notifyDisconnect(msg); |
| } |
| } |
| |
| |
| public String toString() { |
| return "State=" + state + " create=" + createTime + " lastFail=" |
| + lastFailTime + " lastFailCause=" + lastFailCause; |
| } |
| |
| |
| protected void notifyFail(FailCause cause, Message onCompleted) { |
| if (onCompleted == null) { |
| return; |
| } |
| state = State.INACTIVE; |
| lastFailCause = cause; |
| lastFailTime = System.currentTimeMillis(); |
| onConnectCompleted = null; |
| |
| if(DBG) { |
| log("Notify data connection fail at " + lastFailTime + |
| " due to " + lastFailCause); |
| } |
| |
| AsyncResult.forMessage(onCompleted, cause, new Exception()); |
| onCompleted.sendToTarget(); |
| } |
| |
| protected void notifySuccess(Message onCompleted) { |
| if (onCompleted == null) { |
| return; |
| } |
| |
| state = State.ACTIVE; |
| createTime = System.currentTimeMillis(); |
| onConnectCompleted = null; |
| onCompleted.arg1 = cid; |
| |
| if (DBG) log("Notify data connection success at " + createTime); |
| |
| AsyncResult.forMessage(onCompleted); |
| onCompleted.sendToTarget(); |
| } |
| |
| protected void notifyDisconnect(Message msg) { |
| if (DBG) log("Notify data connection disconnect"); |
| |
| if (msg != null) { |
| AsyncResult.forMessage(msg); |
| msg.sendToTarget(); |
| } |
| clearSettings(); |
| } |
| |
| protected void onLinkStateChanged(DataLink.LinkState linkState) { |
| switch (linkState) { |
| case LINK_UP: |
| notifySuccess(onConnectCompleted); |
| break; |
| |
| case LINK_DOWN: |
| case LINK_EXITED: |
| phone.mCM.getLastDataCallFailCause(obtainMessage(EVENT_GET_LAST_FAIL_DONE)); |
| break; |
| } |
| } |
| |
| protected FailCause getFailCauseFromRequest(int rilCause) { |
| FailCause cause; |
| |
| switch (rilCause) { |
| case PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING: |
| cause = FailCause.OPERATOR_BARRED; |
| break; |
| case PS_NET_DOWN_REASON_AUTH_FAILED: |
| cause = FailCause.USER_AUTHENTICATION; |
| break; |
| case PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED: |
| cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED; |
| break; |
| case PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED: |
| cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED; |
| break; |
| default: |
| cause = FailCause.UNKNOWN; |
| } |
| return cause; |
| } |
| |
| protected void log(String s) { |
| Log.d(LOG_TAG, "[CdmaDataConnection] " + s); |
| } |
| |
| @Override |
| protected void onDeactivated(AsyncResult ar) { |
| notifyDisconnect((Message) ar.userObj); |
| if (DBG) log("CDMA Connection Deactivated"); |
| } |
| |
| @Override |
| protected void onSetupConnectionCompleted(AsyncResult ar) { |
| if (ar.exception != null) { |
| Log.e(LOG_TAG, "CdmaDataConnection Init failed " + ar.exception); |
| |
| if (receivedDisconnectReq) { |
| // Don't bother reporting the error if there's already a |
| // pending disconnect request, since DataConnectionTracker |
| // has already updated its state. |
| notifyDisconnect(onDisconnect); |
| } else { |
| if (ar.exception instanceof CommandException |
| && ((CommandException) (ar.exception)).getCommandError() |
| == CommandException.Error.RADIO_NOT_AVAILABLE) { |
| notifyFail(FailCause.RADIO_NOT_AVAILABLE, onConnectCompleted); |
| } else { |
| phone.mCM.getLastDataCallFailCause(obtainMessage(EVENT_GET_LAST_FAIL_DONE)); |
| } |
| } |
| } else { |
| if (receivedDisconnectReq) { |
| // Don't bother reporting success if there's already a |
| // pending disconnect request, since DataConnectionTracker |
| // has already updated its state. |
| tearDownData(onDisconnect); |
| } else { |
| String[] response = ((String[]) ar.result); |
| cid = Integer.parseInt(response[0]); |
| |
| if (response.length > 2) { |
| interfaceName = response[1]; |
| ipAddress = response[2]; |
| String prefix = "net." + interfaceName + "."; |
| gatewayAddress = SystemProperties.get(prefix + "gw"); |
| dnsServers[0] = SystemProperties.get(prefix + "dns1"); |
| dnsServers[1] = SystemProperties.get(prefix + "dns2"); |
| if (DBG) { |
| log("interface=" + interfaceName + " ipAddress=" + ipAddress |
| + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0] |
| + " DNS2=" + dnsServers[1]); |
| } |
| |
| if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1]) |
| && !((CDMAPhone) phone).isDnsCheckDisabled()) { |
| // Work around a race condition where QMI does not fill in DNS: |
| // Deactivate PDP and let DataConnectionTracker retry. |
| EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS, |
| dnsServers[0]); |
| phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_FORCE_RETRY)); |
| return; |
| } |
| } |
| |
| onLinkStateChanged(DataLink.LinkState.LINK_UP); |
| |
| if (DBG) log("CdmaDataConnection setup on cid = " + cid); |
| } |
| } |
| } |
| } |