/* * 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 "); } /** * 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); } } } }