blob: fef6d3c633a7a2bf65c2814a63aeca500d2279d2 [file] [log] [blame]
/*
* 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);
}
}
}
}