diff options
Diffstat (limited to 'telephony/java')
13 files changed, 893 insertions, 923 deletions
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java index 7809fed..99d5520 100644 --- a/telephony/java/com/android/internal/telephony/DataConnection.java +++ b/telephony/java/com/android/internal/telephony/DataConnection.java @@ -16,43 +16,137 @@ package com.android.internal.telephony; +import com.android.internal.telephony.gsm.ApnSetting; + +import com.android.internal.util.HierarchicalState; +import com.android.internal.util.HierarchicalStateMachine; + import android.os.AsyncResult; -import android.os.Handler; import android.os.Message; -import android.util.Log; +import android.os.SystemProperties; +import android.util.EventLog; /** * {@hide} + * + * DataConnection HierarchicalStateMachine. + * + * This is an abstract base class for representing a single data connection. + * Instances of this class such as <code>CdmaDataConnection</code> and + * <code>GsmDataConnection</code>, * represent a connection via the cellular network. + * There may be multiple data connections and all of them are managed by the + * <code>DataConnectionTracker</code>. + * + * Instances are asynchronous state machines and have two primary entry points + * <code>connect()</code> and <code>disconnect</code>. The message a parameter will be returned + * hen the operation completes. The <code>msg.obj</code> will contain an AsyncResult + * object and <code>AsyncResult.userObj</code> is the original <code>msg.obj</code>. if successful + * with the <code>AsyncResult.result == null</code> and <code>AsyncResult.exception == null</code>. + * If an error <code>AsyncResult.result = FailCause</code> and + * <code>AsyncResult.exception = new Exception()</code>. + * + * The other public methods are provided for debugging. + * + * Below is the state machine description for this class. + * + * DataConnection { + * + mDefaultState { + * EVENT_RESET { clearSettings, >mInactiveState }. + * EVENT_CONNECT { notifyConnectCompleted(FailCause.UNKNOWN) }. + * EVENT_DISCONNECT { notifyDisconnectCompleted }. + * + * // Ignored messages + * EVENT_SETUP_DATA_CONNECTION_DONE, + * EVENT_GET_LAST_FAIL_DONE, + * EVENT_DEACTIVATE_DONE. + * } + * ++ # mInactiveState { + * EVENT_RESET. + * EVENT_CONNECT {startConnecting, >mActivatingState }. + * } + * ++ mActivatingState { + * EVENT_DISCONNECT { %EVENT_DISCONNECT }. + * EVENT_SETUP_DATA_CONNECTION_DONE { + * if (SUCCESS) { notifyConnectCompleted(FailCause.NONE), >mActiveState }. + * if (ERR_BadCommand) { + * notifyConnectCompleted(FailCause.UNKNOWN), >mInactiveState }. + * if (ERR_BadDns) { tearDownData($DEACTIVATE_DONE), >mDisconnectingBadDnsState }. + * if (ERR_Other) { getLastDataCallFailCause($EVENT_GET_LAST_FAIL_DONE) }. + * if (ERR_Stale) {}. + * } + * EVENT_GET_LAST_FAIL_DONE { notifyConnectCompleted(result), >mInactive }. + * } + * ++ mActiveState { + * EVENT_DISCONNECT { tearDownData($EVENT_DEACTIVATE_DONE), >mDisconnecting }. + * } + * ++ mDisconnectingState { + * EVENT_DEACTIVATE_DONE { notifyDisconnectCompleted, >mInactiveState }. + * } + * ++ mDisconnectingBadDnsState { + * EVENT_DEACTIVATE_DONE { notifyConnectComplete(FailCause.UNKNOWN), >mInactiveState }. + * } + * } */ -public abstract class DataConnection extends Handler { +public abstract class DataConnection extends HierarchicalStateMachine { + protected static final boolean DBG = true; - // the inherited class + protected static Object mCountLock = new Object(); + protected static int mCount; - public enum State { - ACTIVE, /* has active data connection */ - ACTIVATING, /* during connecting process */ - INACTIVE; /* has empty data connection */ + /** + * Class returned by onSetupConnectionCompleted. + */ + protected enum SetupResult { + ERR_BadCommand, + ERR_BadDns, + ERR_Other, + ERR_Stale, + SUCCESS; + public FailCause mFailCause; + + @Override public String toString() { switch (this) { - case ACTIVE: - return "active"; - case ACTIVATING: - return "setting up"; - default: - return "inactive"; + case ERR_BadCommand: return "Bad Command"; + case ERR_BadDns: return "Bad DNS"; + case ERR_Other: return "Other error"; + case ERR_Stale: return "Stale command"; + case SUCCESS: return "SUCCESS"; + default: return "unknown"; } } + } - public boolean isActive() { - return this == ACTIVE; + /** + * Used internally for saving connecting parameters. + */ + protected static class ConnectionParams { + public ConnectionParams(ApnSetting apn, Message onCompletedMsg) { + this.apn = apn; + this.onCompletedMsg = onCompletedMsg; } - public boolean isInactive() { - return this == INACTIVE; + public int tag; + public ApnSetting apn; + public Message onCompletedMsg; + } + + /** + * Used internally for saving disconnecting parameters. + */ + protected static class DisconnectParams { + public DisconnectParams(Message onCompletedMsg) { + this.onCompletedMsg = onCompletedMsg; } + + public int tag; + public Message onCompletedMsg; } + /** + * Returned as the reason for a connection failure. + */ public enum FailCause { NONE, OPERATOR_BARRED, @@ -71,8 +165,7 @@ public abstract class DataConnection extends Handler { GPRS_REGISTRATION_FAIL, UNKNOWN, - RADIO_NOT_AVAILABLE, - RADIO_ERROR_RETRY; + RADIO_NOT_AVAILABLE; public boolean isPermanentFail() { return (this == OPERATOR_BARRED) || (this == MISSING_UKNOWN_APN) || @@ -128,117 +221,139 @@ public abstract class DataConnection extends Handler { return "Data Network Registration Failure"; case RADIO_NOT_AVAILABLE: return "Radio Not Available"; - case RADIO_ERROR_RETRY: - return "Transient Radio Rrror"; default: return "Unknown Data Error"; } } } - // ***** Event codes - protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 1; - protected static final int EVENT_GET_LAST_FAIL_DONE = 2; - protected static final int EVENT_LINK_STATE_CHANGED = 3; - protected static final int EVENT_DEACTIVATE_DONE = 4; - protected static final int EVENT_FORCE_RETRY = 5; + // ***** Event codes for driving the state machine + protected static final int EVENT_RESET = 1; + protected static final int EVENT_CONNECT = 2; + protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 3; + protected static final int EVENT_GET_LAST_FAIL_DONE = 4; + protected static final int EVENT_DEACTIVATE_DONE = 5; + protected static final int EVENT_DISCONNECT = 6; //***** Tag IDs for EventLog protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100; - //***** Member Variables + protected int mTag; protected PhoneBase phone; - protected Message onConnectCompleted; - protected Message onDisconnect; protected int cid; protected String interfaceName; protected String ipAddress; protected String gatewayAddress; protected String[] dnsServers; - protected State state; protected long createTime; protected long lastFailTime; protected FailCause lastFailCause; protected static final String NULL_IP = "0.0.0.0"; Object userData; - // receivedDisconnectReq is set when disconnect during activation - protected boolean receivedDisconnectReq; - - /* Instance Methods */ - protected abstract void onSetupConnectionCompleted(AsyncResult ar); - - protected abstract void onDeactivated(AsyncResult ar); - - protected abstract void disconnect(Message msg); - - protected abstract void notifyFail(FailCause cause, Message onCompleted); - - protected abstract void notifyDisconnect(Message msg); + //***** Abstract methods + public abstract String toString(); - protected abstract void onLinkStateChanged(DataLink.LinkState linkState); + protected abstract void onConnect(ConnectionParams cp); protected abstract FailCause getFailCauseFromRequest(int rilCause); - public abstract String toString(); + protected abstract boolean isDnsOk(String[] domainNameServers); protected abstract void log(String s); //***** Constructor - protected DataConnection(PhoneBase phone) { - super(); + protected DataConnection(PhoneBase phone, String name) { + super(name); + if (DBG) log("DataConnection constructor E"); this.phone = phone; - onConnectCompleted = null; - onDisconnect = null; this.cid = -1; - receivedDisconnectReq = false; this.dnsServers = new String[2]; clearSettings(); + + setDbg(true); + addState(mDefaultState); + addState(mInactiveState, mDefaultState); + addState(mActivatingState, mDefaultState); + addState(mActiveState, mDefaultState); + addState(mDisconnectingState, mDefaultState); + addState(mDisconnectingBadDnsState, mDefaultState); + setInitialState(mInactiveState); + if (DBG) log("DataConnection constructor X"); } - protected void setHttpProxy(String httpProxy, String httpPort) { - if (httpProxy == null || httpProxy.length() == 0) { - phone.setSystemProperty("net.gprs.http-proxy", null); - return; + /** + * TearDown the data connection. + * + * @param o will be returned in AsyncResult.userObj + * and is either a DisconnectParams or ConnectionParams. + */ + private void tearDownData(Object o) { + if (phone.mCM.getRadioState().isOn()) { + if (DBG) log("tearDownData radio is on, call deactivateDataCall"); + phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, o)); + } else { + if (DBG) log("tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately"); + sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, o)); } + } - if (httpPort == null || httpPort.length() == 0) { - httpPort = "8080"; // Default to port 8080 + /** + * Send the connectionCompletedMsg. + * + * @param cp is the ConnectionParams + * @param cause + */ + private void notifyConnectCompleted(ConnectionParams cp, FailCause cause) { + Message connectionCompletedMsg = cp.onCompletedMsg; + if (connectionCompletedMsg == null) { + return; } - phone.setSystemProperty("net.gprs.http-proxy", - "http://" + httpProxy + ":" + httpPort + "/"); - } + long timeStamp = System.currentTimeMillis(); + connectionCompletedMsg.arg1 = cid; - public String getInterface() { - return interfaceName; - } + if (cause == FailCause.NONE) { + createTime = timeStamp; + AsyncResult.forMessage(connectionCompletedMsg); + } else { + lastFailCause = cause; + lastFailTime = timeStamp; + AsyncResult.forMessage(connectionCompletedMsg, cause, new Exception()); + } + if (DBG) log("notifyConnection at " + timeStamp + " cause=" + cause); - public String getIpAddress() { - return ipAddress; + connectionCompletedMsg.sendToTarget(); } - public String getGatewayAddress() { - return gatewayAddress; - } + /** + * Send ar.userObj if its a message, which is should be back to originator. + * + * @param dp is the DisconnectParams. + */ + private void notifyDisconnectCompleted(DisconnectParams dp) { + if (DBG) log("NotifyDisconnectCompleted"); - public String[] getDnsServers() { - return dnsServers; + Message msg = dp.onCompletedMsg; + AsyncResult.forMessage(msg); + msg.sendToTarget(); + + clearSettings(); } - public void clearSettings() { - log("DataConnection.clearSettings()"); + /** + * Clear all settings called when entering mInactiveState. + */ + protected void clearSettings() { + if (DBG) log("clearSettings"); - this.state = State.INACTIVE; this.createTime = -1; this.lastFailTime = -1; this.lastFailCause = FailCause.NONE; - receivedDisconnectReq = false; - onConnectCompleted = null; interfaceName = null; ipAddress = null; gatewayAddress = null; @@ -246,80 +361,433 @@ public abstract class DataConnection extends Handler { dnsServers[1] = null; } - protected void onGetLastFailCompleted(AsyncResult ar) { - 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); + /** + * Process setup completion. + * + * @param ar is the result + * @return SetupResult. + */ + private SetupResult onSetupConnectionCompleted(AsyncResult ar) { + SetupResult result; + String[] response = ((String[]) ar.result); + ConnectionParams cp = (ConnectionParams) ar.userObj; + + if (ar.exception != null) { + if (DBG) log("DataConnection Init failed " + ar.exception); + + if (ar.exception instanceof CommandException + && ((CommandException) (ar.exception)).getCommandError() + == CommandException.Error.RADIO_NOT_AVAILABLE) { + result = SetupResult.ERR_BadCommand; + result.mFailCause = FailCause.RADIO_NOT_AVAILABLE; + } else { + result = SetupResult.ERR_Other; + } + } else if (cp.tag != mTag) { + if (DBG) { + log("BUG: onSetupConnectionCompleted is stale cp.tag=" + cp.tag + ", mtag=" + mTag); + } + result = SetupResult.ERR_Stale; } else { - FailCause cause = FailCause.UNKNOWN; - - if (ar.exception == null) { - int rilFailCause = ((int[]) (ar.result))[0]; - cause = getFailCauseFromRequest(rilFailCause); + 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 (isDnsOk(dnsServers)) { + result = SetupResult.SUCCESS; + } else { + result = SetupResult.ERR_BadDns; + } + } else { + result = SetupResult.ERR_Other; } - notifyFail(cause, onConnectCompleted); } + + if (DBG) log("DataConnection setup result=" + result + " on cid = " + cid); + return result; } - protected void onForceRetry() { - if (receivedDisconnectReq) { - notifyDisconnect(onDisconnect); - } else { - notifyFail(FailCause.RADIO_ERROR_RETRY, onConnectCompleted); + /** + * The parent state for all other states. + */ + private class DcDefaultState extends HierarchicalState { + @Override + protected boolean processMessage(Message msg) { + AsyncResult ar; + + switch (msg.what) { + case EVENT_RESET: + if (DBG) log("DcDefaultState: msg.what=EVENT_RESET"); + clearSettings(); + transitionTo(mInactiveState); + break; + + case EVENT_CONNECT: + if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected"); + ConnectionParams cp = (ConnectionParams) msg.obj; + notifyConnectCompleted(cp, FailCause.UNKNOWN); + break; + + case EVENT_DISCONNECT: + if (DBG) log("DcDefaultState: msg.what=EVENT_DISCONNECT"); + notifyDisconnectCompleted((DisconnectParams) msg.obj); + break; + + default: + if (DBG) { + log("DcDefaultState: shouldn't happen but ignore msg.what=" + msg.what); + } + break; + } + + return true; + } + } + private DcDefaultState mDefaultState = new DcDefaultState(); + + /** + * The state machine is inactive and expects a EVENT_CONNECT. + */ + private class DcInactiveState extends HierarchicalState { + @Override protected void enter() { + mTag += 1; + } + @Override protected boolean processMessage(Message msg) { + boolean retVal; + + switch (msg.what) { + case EVENT_RESET: + if (DBG) { + log("DcInactiveState: msg.what=EVENT_RESET, ignore we're already reset"); + } + retVal = true; + break; + + case EVENT_CONNECT: + if (DBG) log("DcInactiveState msg.what=EVENT_CONNECT"); + ConnectionParams cp = (ConnectionParams) msg.obj; + cp.tag = mTag; + onConnect(cp); + transitionTo(mActivatingState); + retVal = true; + break; + + default: + if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what); + retVal = false; + break; + } + return retVal; + } + } + private DcInactiveState mInactiveState = new DcInactiveState(); + + /** + * The state machine is activating a connection. + */ + private class DcActivatingState extends HierarchicalState { + @Override protected boolean processMessage(Message msg) { + boolean retVal; + AsyncResult ar; + ConnectionParams cp; + + switch (msg.what) { + case EVENT_DISCONNECT: + if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT"); + deferMessage(msg); + retVal = true; + break; + + case EVENT_SETUP_DATA_CONNECTION_DONE: + if (DBG) log("DcActivatingState msg.what=EVENT_SETUP_DATA_CONNECTION_DONE"); + + ar = (AsyncResult) msg.obj; + cp = (ConnectionParams) ar.userObj; + + SetupResult result = onSetupConnectionCompleted(ar); + switch (result) { + case SUCCESS: + // All is well + notifyConnectCompleted(cp, FailCause.NONE); + transitionTo(mActiveState); + break; + case ERR_BadCommand: + // Vendor ril rejected the command and didn't connect. + notifyConnectCompleted(cp, result.mFailCause); + transitionTo(mInactiveState); + break; + case ERR_BadDns: + // Connection succeeded but DNS info is bad so disconnect + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS, + dnsServers[0]); + tearDownData(cp); + transitionTo(mDisconnectingBadDnsState); + break; + case ERR_Other: + // Request the failure cause and process in this state + phone.mCM.getLastDataCallFailCause( + obtainMessage(EVENT_GET_LAST_FAIL_DONE, cp)); + break; + case ERR_Stale: + // Request is stale, ignore. + break; + default: + throw new RuntimeException("Unkown SetupResult, should not happen"); + } + retVal = true; + break; + + case EVENT_GET_LAST_FAIL_DONE: + ar = (AsyncResult) msg.obj; + cp = (ConnectionParams) ar.userObj; + FailCause cause = FailCause.UNKNOWN; + + if (cp.tag == mTag) { + if (DBG) log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE"); + if (ar.exception == null) { + int rilFailCause = ((int[]) (ar.result))[0]; + cause = getFailCauseFromRequest(rilFailCause); + } + notifyConnectCompleted(cp, cause); + transitionTo(mInactiveState); + } else { + if (DBG) { + log("DcActivatingState EVENT_GET_LAST_FAIL_DONE is stale cp.tag=" + + cp.tag + ", mTag=" + mTag); + } + } + + retVal = true; + break; + + default: + if (DBG) log("DcActivatingState not handled msg.what=" + msg.what); + retVal = false; + break; + } + return retVal; + } + } + private DcActivatingState mActivatingState = new DcActivatingState(); + + /** + * The state machine is connected, expecting an EVENT_DISCONNECT. + */ + private class DcActiveState extends HierarchicalState { + @Override protected boolean processMessage(Message msg) { + boolean retVal; + + switch (msg.what) { + case EVENT_DISCONNECT: + if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT"); + DisconnectParams dp = (DisconnectParams) msg.obj; + dp.tag = mTag; + tearDownData(dp); + transitionTo(mDisconnectingState); + retVal = true; + break; + + default: + if (DBG) log("DcActiveState nothandled msg.what=" + msg.what); + retVal = false; + break; + } + return retVal; + } + } + private DcActiveState mActiveState = new DcActiveState(); + + /** + * The state machine is disconnecting. + */ + private class DcDisconnectingState extends HierarchicalState { + @Override protected boolean processMessage(Message msg) { + boolean retVal; + + switch (msg.what) { + case EVENT_DEACTIVATE_DONE: + if (DBG) log("DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE"); + AsyncResult ar = (AsyncResult) msg.obj; + DisconnectParams dp = (DisconnectParams) ar.userObj; + if (dp.tag == mTag) { + notifyDisconnectCompleted((DisconnectParams) ar.userObj); + transitionTo(mInactiveState); + } else { + if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag=" + + dp.tag + " mTag=" + mTag); + } + retVal = true; + break; + + default: + if (DBG) log("DcDisconnectingState not handled msg.what=" + msg.what); + retVal = false; + break; + } + return retVal; + } + } + private DcDisconnectingState mDisconnectingState = new DcDisconnectingState(); + + /** + * The state machine is disconnecting after a bad dns setup + * was found in mInactivatingState. + */ + private class DcDisconnectingBadDnsState extends HierarchicalState { + @Override protected boolean processMessage(Message msg) { + boolean retVal; + + switch (msg.what) { + case EVENT_DEACTIVATE_DONE: + AsyncResult ar = (AsyncResult) msg.obj; + ConnectionParams cp = (ConnectionParams) ar.userObj; + if (cp.tag == mTag) { + if (DBG) log("DcDisconnectingBadDnsState msg.what=EVENT_DEACTIVATE_DONE"); + notifyConnectCompleted(cp, FailCause.UNKNOWN); + transitionTo(mInactiveState); + } else { + if (DBG) log("DcDisconnectingBadDnsState EVENT_DEACTIVE_DONE stale dp.tag=" + + cp.tag + ", mTag=" + mTag); + } + retVal = true; + break; + + default: + if (DBG) log("DcDisconnectingBadDnsState not handled msg.what=" + msg.what); + retVal = false; + break; + } + return retVal; } } + private DcDisconnectingBadDnsState mDisconnectingBadDnsState = new DcDisconnectingBadDnsState(); - @Override - public void handleMessage(Message msg) { - AsyncResult ar; + // ******* public interface - log("DataConnection.handleMessage()"); + /** + * Disconnect from the network. + */ + public void reset() { + sendMessage(obtainMessage(EVENT_RESET)); + } - switch (msg.what) { + /** + * Connect to the apn and return an AsyncResult in onCompletedMsg. + * Used for cellular networks that use Acess Point Names (APN) such + * as GSM networks. + * + * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. + * With AsyncResult.userObj set to the original msg.obj, + * AsyncResult.result = FailCause and AsyncResult.exception = Exception(). + * @param apn is the Acces Point Name to connect to + */ + public void connect(Message onCompletedMsg, ApnSetting apn) { + sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg))); + } - case EVENT_SETUP_DATA_CONNECTION_DONE: - onSetupConnectionCompleted((AsyncResult) msg.obj); - break; + /** + * Connect to the apn and return an AsyncResult in onCompletedMsg. + * + * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. + * With AsyncResult.userObj set to the original msg.obj, + * AsyncResult.result = FailCause and AsyncResult.exception = Exception(). + */ + public void connect(Message onCompletedMsg) { + sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(null, onCompletedMsg))); + } - case EVENT_FORCE_RETRY: - onForceRetry(); - break; + /** + * Disconnect from the network. + * + * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. + * With AsyncResult.userObj set to the original msg.obj. + */ + public void disconnect(Message onCompletedMsg) { + sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(onCompletedMsg))); + } - case EVENT_GET_LAST_FAIL_DONE: - onGetLastFailCompleted((AsyncResult) msg.obj); - break; + // ****** The following are used for debugging. - case EVENT_LINK_STATE_CHANGED: - ar = (AsyncResult) msg.obj; - DataLink.LinkState ls = (DataLink.LinkState) ar.result; - onLinkStateChanged(ls); - break; + /** + * @return true if the state machine is in the inactive state. + */ + public boolean isInactive() { + boolean retVal = getCurrentState() == mInactiveState; + return retVal; + } - case EVENT_DEACTIVATE_DONE: - onDeactivated((AsyncResult) msg.obj); - break; - } + /** + * @return true if the state machine is in the inactive state. + */ + public boolean isActive() { + boolean retVal = getCurrentState() == mActiveState; + return retVal; + } + + /** + * @return the interface name as a string. + */ + public String getInterface() { + return interfaceName; + } + + /** + * @return the ip address as a string. + */ + public String getIpAddress() { + return ipAddress; + } + + /** + * @return the gateway address as a string. + */ + public String getGatewayAddress() { + return gatewayAddress; + } + + /** + * @return an array of associated DNS addresses. + */ + public String[] getDnsServers() { + return dnsServers; } - public State getState() { - log("DataConnection.getState()"); - return state; + /** + * @return the current state as a string. + */ + public String getStateAsString() { + String retVal = getCurrentState().getName(); + return retVal; } + /** + * @return the time of when this connection was created. + */ public long getConnectionTime() { - log("DataConnection.getConnectionTime()"); return createTime; } + /** + * @return the time of the last failure. + */ public long getLastFailTime() { - log("DataConnection.getLastFailTime()"); return lastFailTime; } + /** + * @return the last cause of failure. + */ public FailCause getLastFailCause() { - log("DataConnection.getLastFailCause()"); return lastFailCause; } } diff --git a/telephony/java/com/android/internal/telephony/DataLink.java b/telephony/java/com/android/internal/telephony/DataLink.java deleted file mode 100644 index 8132d91..0000000 --- a/telephony/java/com/android/internal/telephony/DataLink.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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; - -import android.os.Handler; -import android.os.Registrant; - -/** - * Base class representing the data link layer (eg, PPP). - * - * {@hide} - */ -public abstract class DataLink extends Handler implements DataLinkInterface { - - /** Registrant for link status change notifications. */ - protected Registrant mLinkChangeRegistrant; - protected DataConnectionTracker dataConnection; - - protected DataLink(DataConnectionTracker dc) { - dataConnection = dc; - } - - public void setOnLinkChange(Handler h, int what, Object obj) { - mLinkChangeRegistrant = new Registrant(h, what, obj); - } -} diff --git a/telephony/java/com/android/internal/telephony/DataLinkInterface.java b/telephony/java/com/android/internal/telephony/DataLinkInterface.java deleted file mode 100644 index e8148a8..0000000 --- a/telephony/java/com/android/internal/telephony/DataLinkInterface.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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; - -import android.database.Cursor; -import android.os.Handler; - -/** - * Data link interface. - * - * {@hide} - */ -public interface DataLinkInterface { - /** - * Link state enumeration. - * - */ - enum LinkState { - LINK_UNKNOWN, - LINK_UP, - LINK_DOWN, - LINK_EXITED - } - - /** Normal exit */ - final static int EXIT_OK = 0; - /** Open failed */ - final static int EXIT_OPEN_FAILED = 7; - - /** - * Sets the handler for link state change events. - * - * @param h Handler - * @param what User-defined message code - * @param obj User object - */ - void setOnLinkChange(Handler h, int what, Object obj); - - /** - * Sets up the data link. - */ - void connect(); - - /** - * Tears down the data link. - */ - void disconnect(); - - /** - * Returns the exit code for a data link failure. - * - * @return exit code - */ - int getLastLinkExitCode(); - - /** - * Sets password information that may be required by the data link - * (eg, PAP secrets). - * - * @param cursor cursor to carriers table - */ - void setPasswordInfo(Cursor cursor); -} diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index c113581..a8ad80e 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -28,7 +28,7 @@ import android.telephony.SignalStrength; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.gsm.NetworkInfo; -import com.android.internal.telephony.gsm.PdpConnection; +import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -1176,21 +1176,7 @@ public interface Phone { void invokeOemRilRequestStrings(String[] strings, Message response); /** - * Get the current active PDP context list - * - * @deprecated - * @param response <strong>On success</strong>, "response" bytes is - * made available as: - * (String[])(((AsyncResult)response.obj).result). - * <strong>On failure</strong>, - * (((AsyncResult)response.obj).result) == null and - * (((AsyncResult)response.obj).exception) being an instance of - * com.android.internal.telephony.gsm.CommandException - */ - void getPdpContextList(Message response); - - /** - * Get the current active Data Call list, substitutes getPdpContextList + * Get the current active Data Call list * * @param response <strong>On success</strong>, "response" bytes is * made available as: @@ -1203,19 +1189,11 @@ public interface Phone { void getDataCallList(Message response); /** - * Get current mutiple PDP link status - * - * @deprecated - * @return list of pdp link connections - */ - List<PdpConnection> getCurrentPdpList (); - - /** * Get current mutiple data connection status * * @return list of data connections */ - List<DataConnection> getCurrentDataConnectionList (); + List<DataConnection> getCurrentDataConnectionList(); /** * Update the ServiceState CellLocation for current network registration. diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index 50dd76a..bad9ab3 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -35,7 +35,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.R; -import com.android.internal.telephony.gsm.PdpConnection; +import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -692,16 +692,6 @@ public abstract class PhoneBase extends Handler implements Phone { Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); } - /** - * This should only be called in GSM mode. - * Only here for some backward compatibility - * issues concerning the GSMPhone class. - * @deprecated Always returns null. - */ - public List<PdpConnection> getCurrentPdpList() { - return null; - } - public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) { // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java index 3eadd81..d56d99f 100644 --- a/telephony/java/com/android/internal/telephony/PhoneProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java @@ -34,7 +34,7 @@ import android.util.Log; import com.android.internal.telephony.cdma.CDMAPhone; import com.android.internal.telephony.gsm.GSMPhone; import com.android.internal.telephony.gsm.NetworkInfo; -import com.android.internal.telephony.gsm.PdpConnection; +import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -564,24 +564,10 @@ public class PhoneProxy extends Handler implements Phone { mActivePhone.invokeOemRilRequestStrings(strings, response); } - /** - * @deprecated - */ - public void getPdpContextList(Message response) { - mActivePhone.getPdpContextList(response); - } - public void getDataCallList(Message response) { mActivePhone.getDataCallList(response); } - /** - * @deprecated - */ - public List<PdpConnection> getCurrentPdpList() { - return mActivePhone.getCurrentPdpList(); - } - public List<DataConnection> getCurrentDataConnectionList() { return mActivePhone.getCurrentDataConnectionList(); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 75e8b65..d4b1652 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -657,13 +657,6 @@ public class CDMAPhone extends PhoneBase { mSST.disableLocationUpdates(); } - /** - * @deprecated - */ - public void getPdpContextList(Message response) { - getDataCallList(response); - } - public void getDataCallList(Message response) { mCM.getDataCallList(response); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java index 4588f36..6c20204 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java @@ -16,221 +16,77 @@ package com.android.internal.telephony.cdma; -import android.os.*; -import android.util.EventLog; +import android.os.Message; 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); + private CdmaDataConnection(CDMAPhone phone, String name) { + super(phone, name); + } - if (DBG) log("CdmaDataConnection <constructor>"); + /** + * Create the connection object + * + * @param phone + * @return CdmaDataConnection that was created. + */ + static CdmaDataConnection makeDataConnection(CDMAPhone phone) { + synchronized (mCountLock) { + mCount += 1; + } + CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, "CdmaDataConnection-" + mCount); + cdmaDc.start(); + if (DBG) cdmaDc.log("Made " + cdmaDc.getName()); + return cdmaDc; } /** - * Setup a data connection + * Begin setting up a data connection, calls setupDataCall + * and the ConnectionParams will be returned with the + * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj. * - * @param onCompleted - * notify success or not after down + * @param cp is the connection parameters */ - void connect(Message onCompleted) { + @Override + protected void onConnect(ConnectionParams cp) { if (DBG) log("CdmaDataConnection Connecting..."); - state = State.ACTIVATING; - onConnectCompleted = onCompleted; createTime = -1; lastFailTime = -1; lastFailCause = FailCause.NONE; - receivedDisconnectReq = false; + + // msg.obj will be returned in AsyncResult.userObj; + Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp); + msg.obj = cp; phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA), Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), null, null, - null, Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP), - obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE)); + null, Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP), msg); } - 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); - } - } - - + @Override 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; - } + return "State=" + getCurrentState().getName() + " create=" + createTime + " lastFail=" + + lastFailTime + " lastFasilCause=" + lastFailCause; } + @Override protected FailCause getFailCauseFromRequest(int rilCause) { FailCause cause; @@ -253,73 +109,19 @@ public class CdmaDataConnection extends DataConnection { 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"); + protected boolean isDnsOk(String[] domainNameServers) { + if ((NULL_IP.equals(domainNameServers[0]) + && NULL_IP.equals(domainNameServers[1]) + && !((CDMAPhone) phone).isDnsCheckDisabled())) { + return false; + } else { + return true; + } } @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); - } - } + protected void log(String s) { + Log.d(LOG_TAG, "[" + getName() + "] " + s); } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index b63b0c4..ecd3380 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -386,7 +386,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason); conn.disconnect(msg); } else { - conn.clearSettings(); + conn.reset(); } } } @@ -403,7 +403,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private CdmaDataConnection findFreeDataConnection() { for (DataConnection connBase : dataConnectionList) { CdmaDataConnection conn = (CdmaDataConnection) connBase; - if (conn.getState() == DataConnection.State.INACTIVE) { + if (conn.isInactive()) { return conn; } } @@ -801,7 +801,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { CdmaDataConnection dataConn; for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) { - dataConn = new CdmaDataConnection(mCdmaPhone); + dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone); dataConnectionList.add(dataConn); } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java index 33d150a..2bb7968 100755 --- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java @@ -1050,33 +1050,10 @@ public class GSMPhone extends PhoneBase { return mCT.getMute(); } - /** - * @deprecated Do not use. - */ - @Deprecated - public void getPdpContextList(Message response) { - getDataCallList(response); - } - public void getDataCallList(Message response) { mCM.getDataCallList(response); } - /** - * @deprecated Do not use. - */ - @Deprecated - public List<PdpConnection> getCurrentPdpList() { - ArrayList<DataConnection> connections = new ArrayList<DataConnection>(); - ArrayList<PdpConnection> pdp_list = new ArrayList<PdpConnection>(); - - for(int n = 0; n < connections.size(); n++) { - pdp_list.add((PdpConnection) connections.get(n)); - } - - return pdp_list; - } - public List<DataConnection> getCurrentDataConnectionList () { return mDataConnection.getAllDataConnections(); } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java new file mode 100644 index 0000000..905d5e3 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java @@ -0,0 +1,226 @@ +/* + * 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.gsm; + +import android.os.Message; +import android.util.Log; + +import com.android.common.Patterns; +import com.android.internal.telephony.DataConnection; +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.RILConstants; + +/** + * {@hide} + */ +public class GsmDataConnection extends DataConnection { + + private static final String LOG_TAG = "GSM"; + + /** Fail cause of last PDP activate, from RIL_LastPDPActivateFailCause */ + private static final int PDP_FAIL_OPERATOR_BARRED = 0x08; + private static final int PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A; + private static final int PDP_FAIL_MISSING_UKNOWN_APN = 0x1B; + private static final int PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C; + private static final int PDP_FAIL_USER_AUTHENTICATION = 0x1D; + private static final int PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E; + private static final int PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F; + private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20; + private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21; + private static final int PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22; + private static final int PDP_FAIL_NSAPI_IN_USE = 0x23; + private static final int PDP_FAIL_PROTOCOL_ERRORS = 0x6F; + private static final int PDP_FAIL_ERROR_UNSPECIFIED = 0xffff; + + private static final int PDP_FAIL_REGISTRATION_FAIL = -1; + private static final int PDP_FAIL_GPRS_REGISTRATION_FAIL = -2; + + //***** Instance Variables + private ApnSetting apn; + + //***** Constructor + private GsmDataConnection(GSMPhone phone, String name) { + super(phone, name); + } + + /** + * Create the connection object + * + * @param phone + * @return GsmDataConnection that was created. + */ + static GsmDataConnection makeDataConnection(GSMPhone phone) { + synchronized (mCountLock) { + mCount += 1; + } + GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount); + gsmDc.start(); + if (DBG) gsmDc.log("Made " + gsmDc.getName()); + return gsmDc; + } + + /** + * Begin setting up a data connection, calls setupDataCall + * and the ConnectionParams will be returned with the + * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj. + * + * @param cp is the connection parameters + */ + @Override + protected + void onConnect(ConnectionParams cp) { + apn = cp.apn; + + if (DBG) log("Connecting to carrier: '" + apn.carrier + + "' APN: '" + apn.apn + + "' proxy: '" + apn.proxy + "' port: '" + apn.port); + + setHttpProxy (apn.proxy, apn.port); + + createTime = -1; + lastFailTime = -1; + lastFailCause = FailCause.NONE; + + // msg.obj will be returned in AsyncResult.userObj; + Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp); + msg.obj = cp; + + int authType = apn.authType; + if (authType == -1) { + authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP : + RILConstants.SETUP_DATA_AUTH_NONE; + } + phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_GSM), + Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), apn.apn, apn.user, + apn.password, Integer.toString(authType), msg); + } + + @Override + protected void clearSettings() { + super.clearSettings(); + apn = null; + } + + @Override + public String toString() { + return "State=" + getCurrentState().getName() + " Apn=" + apn + + " create=" + createTime + " lastFail=" + lastFailTime + + " lastFailCause=" + lastFailCause; + } + + @Override + protected FailCause getFailCauseFromRequest(int rilCause) { + FailCause cause; + + switch (rilCause) { + case PDP_FAIL_OPERATOR_BARRED: + cause = FailCause.OPERATOR_BARRED; + break; + case PDP_FAIL_INSUFFICIENT_RESOURCES: + cause = FailCause.INSUFFICIENT_RESOURCES; + break; + case PDP_FAIL_MISSING_UKNOWN_APN: + cause = FailCause.MISSING_UKNOWN_APN; + break; + case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE: + cause = FailCause.UNKNOWN_PDP_ADDRESS; + break; + case PDP_FAIL_USER_AUTHENTICATION: + cause = FailCause.USER_AUTHENTICATION; + break; + case PDP_FAIL_ACTIVATION_REJECT_GGSN: + cause = FailCause.ACTIVATION_REJECT_GGSN; + break; + case PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED: + cause = FailCause.ACTIVATION_REJECT_UNSPECIFIED; + break; + case PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER: + cause = FailCause.SERVICE_OPTION_OUT_OF_ORDER; + break; + case PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED: + cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED; + break; + case PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED: + cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED; + break; + case PDP_FAIL_NSAPI_IN_USE: + cause = FailCause.NSAPI_IN_USE; + break; + case PDP_FAIL_PROTOCOL_ERRORS: + cause = FailCause.PROTOCOL_ERRORS; + break; + case PDP_FAIL_ERROR_UNSPECIFIED: + cause = FailCause.UNKNOWN; + break; + case PDP_FAIL_REGISTRATION_FAIL: + cause = FailCause.REGISTRATION_FAIL; + break; + case PDP_FAIL_GPRS_REGISTRATION_FAIL: + cause = FailCause.GPRS_REGISTRATION_FAIL; + break; + default: + cause = FailCause.UNKNOWN; + } + return cause; + } + + @Override + protected boolean isDnsOk(String[] domainNameServers) { + if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1]) + && !((GSMPhone) phone).isDnsCheckDisabled()) { + // Work around a race condition where QMI does not fill in DNS: + // Deactivate PDP and let DataConnectionTracker retry. + // Do not apply the race condition workaround for MMS APN + // if Proxy is an IP-address. + // Otherwise, the default APN will not be restored anymore. + if (!apn.types[0].equals(Phone.APN_TYPE_MMS) + || !isIpAddress(apn.mmsProxy)) { + return false; + } + } + return true; + } + + @Override + protected void log(String s) { + Log.d(LOG_TAG, "[" + getName() + "] " + s); + } + + public ApnSetting getApn() { + return this.apn; + } + + private void setHttpProxy(String httpProxy, String httpPort) { + if (httpProxy == null || httpProxy.length() == 0) { + phone.setSystemProperty("net.gprs.http-proxy", null); + return; + } + + if (httpPort == null || httpPort.length() == 0) { + httpPort = "8080"; // Default to port 8080 + } + + phone.setSystemProperty("net.gprs.http-proxy", + "http://" + httpProxy + ":" + httpPort + "/"); + } + + private boolean isIpAddress(String address) { + if (address == null) return false; + + return Patterns.IP_ADDRESS.matcher(apn.mmsProxy).matches(); + } +} diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index fb7aa3d..5c97925 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -126,8 +126,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { */ private ArrayList<DataConnection> pdpList; - /** Currently active PdpConnection */ - private PdpConnection mActivePdp; + /** Currently active DataConnection */ + private GsmDataConnection mActivePdp; /** Is packet service restricted by network */ private boolean mIsPsRestricted = false; @@ -137,7 +137,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // TODO: Increase this to match the max number of simultaneous // PDP contexts we plan to support. /** - * Pool size of PdpConnection objects. + * Pool size of DataConnection objects. */ private static final int PDP_CONNECTION_POOL_SIZE = 1; @@ -382,7 +382,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } /** - * Formerly this method was ArrayList<PdpConnection> getAllPdps() + * Formerly this method was ArrayList<GsmDataConnection> getAllPdps() */ public ArrayList<DataConnection> getAllDataConnections() { ArrayList<DataConnection> pdps = (ArrayList<DataConnection>)pdpList.clone(); @@ -452,7 +452,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { waitingApns = buildWaitingApns(); if (waitingApns.isEmpty()) { if (DBG) log("No APN found"); - notifyNoData(PdpConnection.FailCause.MISSING_UKNOWN_APN); + notifyNoData(GsmDataConnection.FailCause.MISSING_UKNOWN_APN); return false; } else { log ("Create from allApns : " + apnListToString(allApns)); @@ -487,7 +487,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * there is no mechanism for abandoning an INITING/CONNECTING session, * but would likely involve cancelling pending async requests or * setting a flag or new state to ignore them when they came in - * @param tearDown true if the underlying PdpConnection should be + * @param tearDown true if the underlying GsmDataConnection should be * disconnected. * @param reason reason for the clean up. */ @@ -505,12 +505,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { setState(State.DISCONNECTING); for (DataConnection conn : pdpList) { - PdpConnection pdp = (PdpConnection) conn; if (tearDown) { Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason); - pdp.disconnect(msg); + conn.disconnect(msg); } else { - pdp.clearSettings(); + conn.reset(); } } stopNetStatPoll(); @@ -564,10 +563,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return result; } - private PdpConnection findFreePdp() { + private GsmDataConnection findFreePdp() { for (DataConnection conn : pdpList) { - PdpConnection pdp = (PdpConnection) conn; - if (pdp.getState() == DataConnection.State.INACTIVE) { + GsmDataConnection pdp = (GsmDataConnection) conn; + if (pdp.isInactive()) { return pdp; } } @@ -576,13 +575,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private boolean setupData(String reason) { ApnSetting apn; - PdpConnection pdp; + GsmDataConnection pdp; apn = getNextApn(); if (apn == null) return false; pdp = findFreePdp(); if (pdp == null) { - if (DBG) log("setupData: No free PdpConnection found!"); + if (DBG) log("setupData: No free GsmDataConnection found!"); return false; } mActiveApn = apn; @@ -591,7 +590,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { Message msg = obtainMessage(); msg.what = EVENT_DATA_SETUP_COMPLETE; msg.obj = reason; - pdp.connect(apn, msg); + pdp.connect(msg, apn); setState(State.INITING); phone.notifyDataConnection(reason); @@ -974,13 +973,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * seems like it deserves an error notification. * Transient errors are ignored */ - private boolean shouldPostNotification(PdpConnection.FailCause cause) { - boolean shouldPost = true; - // TODO CHECK - // if (dataLink != null) { - // shouldPost = dataLink.getLastLinkExitCode() != DataLink.EXIT_OPEN_FAILED; - //} - return (shouldPost && cause != PdpConnection.FailCause.UNKNOWN); + private boolean shouldPostNotification(GsmDataConnection.FailCause cause) { + return (cause != GsmDataConnection.FailCause.UNKNOWN); } /** @@ -1046,7 +1040,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } - private void notifyNoData(PdpConnection.FailCause lastFailCauseCode) { + private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode) { setState(State.FAILED); } @@ -1069,7 +1063,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { mRetryMgr.resetRetryCount(); // TODO: To support simultaneous PDP contexts, this should really only call - // cleanUpConnection if it needs to free up a PdpConnection. + // cleanUpConnection if it needs to free up a GsmDataConnection. cleanUpConnection(true, Phone.REASON_APN_SWITCHED); } @@ -1149,8 +1143,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // that the existing connection may service that type, in which // case we should try the next type, etc. } else { - PdpConnection.FailCause cause; - cause = (PdpConnection.FailCause) (ar.result); + GsmDataConnection.FailCause cause; + cause = (GsmDataConnection.FailCause) (ar.result); if(DBG) log("PDP setup failed " + cause); // Log this failure to the Event Logs. if (cause.isEventLoggable()) { @@ -1259,9 +1253,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (cursor.getCount() > 0) { allApns = createApnList(cursor); // TODO: Figure out where this fits in. This basically just - // writes the pap-secrets file. No longer tied to PdpConnection + // writes the pap-secrets file. No longer tied to GsmDataConnection // object. Not used on current platform (no ppp). - //PdpConnection pdp = pdpList.get(pdp_name); + //GsmDataConnection pdp = pdpList.get(pdp_name); //if (pdp != null && pdp.dataLink != null) { // pdp.dataLink.setPasswordInfo(cursor); //} @@ -1273,7 +1267,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (allApns.isEmpty()) { if (DBG) log("No APN found for carrier: " + operator); preferredApn = null; - notifyNoData(PdpConnection.FailCause.MISSING_UKNOWN_APN); + notifyNoData(GsmDataConnection.FailCause.MISSING_UKNOWN_APN); } else { preferredApn = getPreferredApn(); Log.d(LOG_TAG, "Get PreferredAPN"); @@ -1289,14 +1283,14 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { DataConnection pdp; for (int i = 0; i < PDP_CONNECTION_POOL_SIZE; i++) { - pdp = new PdpConnection(mGsmPhone); + pdp = GsmDataConnection.makeDataConnection(mGsmPhone); pdpList.add(pdp); } } private void destroyAllPdpList() { if(pdpList != null) { - PdpConnection pdp; + GsmDataConnection pdp; pdpList.removeAll(pdpList); } } @@ -1361,7 +1355,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return result.toString(); } - private void startDelayedRetry(PdpConnection.FailCause cause, String reason) { + private void startDelayedRetry(GsmDataConnection.FailCause cause, String reason) { notifyNoData(cause); reconnectAfterFail(cause, reason); } diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java deleted file mode 100644 index 02b061c..0000000 --- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * 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.gsm; - -import android.os.*; -import android.util.EventLog; -import android.util.Log; - -import com.android.common.Patterns; -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.Phone; -import com.android.internal.telephony.RILConstants; -import com.android.internal.telephony.TelephonyEventLog; - -/** - * {@hide} - */ -public class PdpConnection extends DataConnection { - - private static final String LOG_TAG = "GSM"; - private static final boolean DBG = true; - - /** Fail cause of last PDP activate, from RIL_LastPDPActivateFailCause */ - private static final int PDP_FAIL_OPERATOR_BARRED = 0x08; - private static final int PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A; - private static final int PDP_FAIL_MISSING_UKNOWN_APN = 0x1B; - private static final int PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C; - private static final int PDP_FAIL_USER_AUTHENTICATION = 0x1D; - private static final int PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E; - private static final int PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F; - private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20; - private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21; - private static final int PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22; - private static final int PDP_FAIL_NSAPI_IN_USE = 0x23; - private static final int PDP_FAIL_PROTOCOL_ERRORS = 0x6F; - private static final int PDP_FAIL_ERROR_UNSPECIFIED = 0xffff; - - private static final int PDP_FAIL_REGISTRATION_FAIL = -1; - private static final int PDP_FAIL_GPRS_REGISTRATION_FAIL = -2; - - //***** Instance Variables - private String pdp_name; - private ApnSetting apn; - - //***** Constructor - PdpConnection(GSMPhone phone) { - super(phone); - } - - /** - * Setup PDP connection for provided apn - * @param apn for this connection - * @param onCompleted notify success or not after down - */ - void connect(ApnSetting apn, Message onCompleted) { - if (DBG) log("Connecting to carrier: '" + apn.carrier - + "' APN: '" + apn.apn - + "' proxy: '" + apn.proxy + "' port: '" + apn.port); - - setHttpProxy (apn.proxy, apn.port); - - state = State.ACTIVATING; - this.apn = apn; - onConnectCompleted = onCompleted; - createTime = -1; - lastFailTime = -1; - lastFailCause = FailCause.NONE; - receivedDisconnectReq = false; - - int authType = apn.authType; - if (authType == -1) { - authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP : - RILConstants.SETUP_DATA_AUTH_NONE; - } - phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_GSM), - Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), apn.apn, apn.user, - apn.password, Integer.toString(authType), - 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 void clearSettings() { - super.clearSettings(); - apn = null; - } - - public String toString() { - return "State=" + state + " Apn=" + apn + - " 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 PDP 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 PDP success at " + createTime); - - AsyncResult.forMessage(onCompleted); - onCompleted.sendToTarget(); - } - - protected void notifyDisconnect(Message msg) { - if (DBG) log("Notify PDP 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.getLastPdpFailCause( - obtainMessage (EVENT_GET_LAST_FAIL_DONE)); - break; - } - } - - protected FailCause getFailCauseFromRequest(int rilCause) { - FailCause cause; - - switch (rilCause) { - case PDP_FAIL_OPERATOR_BARRED: - cause = FailCause.OPERATOR_BARRED; - break; - case PDP_FAIL_INSUFFICIENT_RESOURCES: - cause = FailCause.INSUFFICIENT_RESOURCES; - break; - case PDP_FAIL_MISSING_UKNOWN_APN: - cause = FailCause.MISSING_UKNOWN_APN; - break; - case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE: - cause = FailCause.UNKNOWN_PDP_ADDRESS; - break; - case PDP_FAIL_USER_AUTHENTICATION: - cause = FailCause.USER_AUTHENTICATION; - break; - case PDP_FAIL_ACTIVATION_REJECT_GGSN: - cause = FailCause.ACTIVATION_REJECT_GGSN; - break; - case PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED: - cause = FailCause.ACTIVATION_REJECT_UNSPECIFIED; - break; - case PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER: - cause = FailCause.SERVICE_OPTION_OUT_OF_ORDER; - break; - case PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED: - cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED; - break; - case PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED: - cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED; - break; - case PDP_FAIL_NSAPI_IN_USE: - cause = FailCause.NSAPI_IN_USE; - break; - case PDP_FAIL_PROTOCOL_ERRORS: - cause = FailCause.PROTOCOL_ERRORS; - break; - case PDP_FAIL_ERROR_UNSPECIFIED: - cause = FailCause.UNKNOWN; - break; - case PDP_FAIL_REGISTRATION_FAIL: - cause = FailCause.REGISTRATION_FAIL; - break; - case PDP_FAIL_GPRS_REGISTRATION_FAIL: - cause = FailCause.GPRS_REGISTRATION_FAIL; - break; - default: - cause = FailCause.UNKNOWN; - } - return cause; - } - - protected void log(String s) { - Log.d(LOG_TAG, "[PdpConnection] " + s); - } - - @Override - protected void onDeactivated(AsyncResult ar) { - notifyDisconnect((Message) ar.userObj); - if (DBG) log("PDP Connection Deactivated"); - } - - @Override - protected void onSetupConnectionCompleted(AsyncResult ar) { - if (ar.exception != null) { - Log.e(LOG_TAG, "PDP Context 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.getLastPdpFailCause( - 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]) - && !((GSMPhone) phone).isDnsCheckDisabled()) { - // Work around a race condition where QMI does not fill in DNS: - // Deactivate PDP and let DataConnectionTracker retry. - // Do not apply the race condition workaround for MMS APN - // if Proxy is an IP-address. - // Otherwise, the default APN will not be restored anymore. - if (!apn.types[0].equals(Phone.APN_TYPE_MMS) - || !isIpAddress(apn.mmsProxy)) { - 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("PDP setup on cid = " + cid); - } - } - } - - private boolean isIpAddress(String address) { - if (address == null) return false; - - return Patterns.IP_ADDRESS.matcher(apn.mmsProxy).matches(); - } - - public ApnSetting getApn() { - return this.apn; - } -} |