Merge "Make DataConnection asynchronous." into honeycomb-LTE

This commit is contained in:
Wink Saville
2011-05-02 23:41:29 -07:00
committed by Android (Google) Code Review
9 changed files with 779 additions and 411 deletions

View File

@ -39,6 +39,7 @@ public class Protocol {
public static final int BASE_WIFI = 0x00020000; public static final int BASE_WIFI = 0x00020000;
public static final int BASE_DHCP = 0x00030000; public static final int BASE_DHCP = 0x00030000;
public static final int BASE_DATA_CONNECTION = 0x00040000; public static final int BASE_DATA_CONNECTION = 0x00040000;
public static final int BASE_DATA_CONNECTION_AC = 0x00041000;
public static final int BASE_DATA_CONNECTION_TRACKER = 0x00050000; public static final int BASE_DATA_CONNECTION_TRACKER = 0x00050000;
//TODO: define all used protocols //TODO: define all used protocols

View File

@ -51,6 +51,8 @@ public class ApnContext {
DataConnection mDataConnection; DataConnection mDataConnection;
DataConnectionAc mDataConnectionAc;
String mReason; String mReason;
PendingIntent mReconnectIntent; PendingIntent mReconnectIntent;
@ -96,6 +98,17 @@ public class ApnContext {
mDataConnection = dataConnection; mDataConnection = dataConnection;
} }
public synchronized DataConnectionAc getDataConnectionAc() {
log("getDataConnectionAc dcac=" + mDataConnectionAc);
return mDataConnectionAc;
}
public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
log("setDataConnectionAc dcac=" + dcac);
mDataConnectionAc = dcac;
}
public synchronized ApnSetting getApnSetting() { public synchronized ApnSetting getApnSetting() {
return mApnSetting; return mApnSetting;
} }
@ -206,6 +219,11 @@ public class ApnContext {
return mDependencyMet.get(); return mDependencyMet.get();
} }
@Override
public String toString() {
return "state=" + getState() + " apnType=" + mApnType;
}
protected void log(String s) { protected void log(String s) {
Log.d(LOG_TAG, "[ApnContext] " + s); Log.d(LOG_TAG, "[ApnContext] " + s);
} }

View File

@ -17,22 +17,24 @@
package com.android.internal.telephony; package com.android.internal.telephony;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import com.android.internal.util.State; import com.android.internal.util.State;
import com.android.internal.util.StateMachine; import com.android.internal.util.StateMachine;
import android.net.LinkAddress;
import android.net.LinkCapabilities; import android.net.LinkCapabilities;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.NetworkUtils; import android.net.ProxyProperties;
import android.os.AsyncResult; import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Message; import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.text.TextUtils; import android.text.TextUtils;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* {@hide} * {@hide}
@ -60,6 +62,8 @@ public abstract class DataConnection extends StateMachine {
protected static Object mCountLock = new Object(); protected static Object mCountLock = new Object();
protected static int mCount; protected static int mCount;
protected AsyncChannel mAc;
/** /**
* Used internally for saving connecting parameters. * Used internally for saving connecting parameters.
@ -75,13 +79,6 @@ public abstract class DataConnection extends StateMachine {
public Message onCompletedMsg; public Message onCompletedMsg;
} }
/**
* An instance used for notification of blockingReset.
* TODO: Remove when blockingReset is removed.
*/
class ResetSynchronouslyLock {
}
/** /**
* Used internally for saving disconnecting parameters. * Used internally for saving disconnecting parameters.
*/ */
@ -90,15 +87,9 @@ public abstract class DataConnection extends StateMachine {
this.reason = reason; this.reason = reason;
this.onCompletedMsg = onCompletedMsg; this.onCompletedMsg = onCompletedMsg;
} }
public DisconnectParams(ResetSynchronouslyLock lockObj) {
this.reason = null;
this.lockObj = lockObj;
}
public int tag; public int tag;
public String reason; public String reason;
public Message onCompletedMsg; public Message onCompletedMsg;
public ResetSynchronouslyLock lockObj;
} }
/** /**
@ -188,13 +179,13 @@ public abstract class DataConnection extends StateMachine {
} }
// ***** Event codes for driving the state machine // ***** Event codes for driving the state machine
protected static final int EVENT_RESET = 1; protected static final int BASE = Protocol.BASE_DATA_CONNECTION;
protected static final int EVENT_CONNECT = 2; protected static final int EVENT_CONNECT = BASE + 0;
protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 3; protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1;
protected static final int EVENT_GET_LAST_FAIL_DONE = 4; protected static final int EVENT_GET_LAST_FAIL_DONE = BASE + 2;
protected static final int EVENT_DEACTIVATE_DONE = 5; protected static final int EVENT_DEACTIVATE_DONE = BASE + 3;
protected static final int EVENT_DISCONNECT = 6; protected static final int EVENT_DISCONNECT = BASE + 4;
protected static final int EVENT_RIL_CONNECTED = 7; protected static final int EVENT_RIL_CONNECTED = BASE + 5;
//***** Tag IDs for EventLog //***** Tag IDs for EventLog
protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100; protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
@ -313,13 +304,8 @@ public abstract class DataConnection extends StateMachine {
AsyncResult.forMessage(msg); AsyncResult.forMessage(msg);
msg.sendToTarget(); msg.sendToTarget();
} }
if (dp.lockObj != null) {
synchronized(dp.lockObj) {
dp.lockObj.notify();
}
}
clearSettings(); clearSettings();
if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
} }
protected int getRadioTechnology(int defaultRadioTechnology) { protected int getRadioTechnology(int defaultRadioTechnology) {
@ -408,6 +394,49 @@ public abstract class DataConnection extends StateMachine {
return mRetryMgr.isRetryForever(); return mRetryMgr.isRetryForever();
} }
private AtomicInteger mRefCount = new AtomicInteger(0);
/**
* Set refCount.
*
* @param val is new refCount
*/
public void setRefCount(int val) {
mRefCount.set(val);
}
/**
* Get refCount
*
* @return refCount
*/
public int getRefCount() {
return mRefCount.get();
}
/**
* @return decrement and return refCount
*
* TODO: Consider using the refCount for defining the
* life time of a connection. When this goes zero the
* DataConnection could tear itself down.
*/
public int decAndGetRefCount() {
int v = mRefCount.decrementAndGet();
if (v < 0) {
log("BUG: decAndGetRefCount caused refCount to be < 0");
mRefCount.set(0);
}
return v;
}
/**
* @return increment and return refCount
*/
public int incAndGetRefCount() {
return mRefCount.incrementAndGet();
}
/* /*
* ************************************************************************** * **************************************************************************
* End members owned by DataConnectionTracker * End members owned by DataConnectionTracker
@ -498,12 +527,74 @@ public abstract class DataConnection extends StateMachine {
AsyncResult ar; AsyncResult ar;
switch (msg.what) { switch (msg.what) {
case EVENT_RESET: case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
if (DBG) log("DcDefaultState: msg.what=EVENT_RESET"); if (mAc != null) {
clearSettings(); log("Disconnecting to previous connection mAc=" + mAc);
if (msg.obj != null) { mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
notifyDisconnectCompleted((DisconnectParams) msg.obj); AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
} else {
mAc = new AsyncChannel();
mAc.connected(null, getHandler(), msg.replyTo);
log("DcDefaultState: FULL_CONNECTION reply connected");
mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
AsyncChannel.STATUS_SUCCESSFUL, mId, "hi");
} }
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
log("CMD_CHANNEL_DISCONNECT");
mAc.disconnect();
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
log("CMD_CHANNEL_DISCONNECTED");
mAc = null;
break;
}
case DataConnectionAc.REQ_IS_INACTIVE: {
boolean val = getCurrentState() == mInactiveState;
log("REQ_IS_INACTIVE isInactive=" + val);
mAc.replyToMessage(msg, DataConnectionAc.RSP_IS_INACTIVE, val ? 1 : 0);
break;
}
case DataConnectionAc.REQ_GET_CID: {
log("REQ_GET_CID cid=" + cid);
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_CID, cid);
break;
}
case DataConnectionAc.REQ_GET_APNSETTING: {
log("REQ_GET_APNSETTING apnSetting=" + mApn);
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNSETTING, mApn);
break;
}
case DataConnectionAc.REQ_GET_LINK_PROPERTIES: {
LinkProperties lp = new LinkProperties(mLinkProperties);
log("REQ_GET_LINK_PROPERTIES linkProperties" + lp);
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_PROPERTIES, lp);
break;
}
case DataConnectionAc.REQ_SET_LINK_PROPERTIES_HTTP_PROXY: {
ProxyProperties proxy = (ProxyProperties) msg.obj;
log("REQ_SET_LINK_PROPERTIES_HTTP_PROXY proxy=" + proxy);
mLinkProperties.setHttpProxy(proxy);
mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_LINK_PROPERTIES_HTTP_PROXY);
break;
}
case DataConnectionAc.REQ_GET_LINK_CAPABILITIES: {
LinkCapabilities lc = new LinkCapabilities(mCapabilities);
log("REQ_GET_LINK_CAPABILITIES linkCapabilities" + lc);
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_CAPABILITIES, lc);
break;
}
case DataConnectionAc.REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE: {
Bundle data = msg.getData();
mLinkProperties = (LinkProperties) data.get("linkProperties");
break;
}
case DataConnectionAc.REQ_RESET:
if (DBG) log("DcDefaultState: msg.what=REQ_RESET");
clearSettings();
mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
transitionTo(mInactiveState); transitionTo(mInactiveState);
break; break;
@ -539,7 +630,7 @@ public abstract class DataConnection extends StateMachine {
break; break;
} }
return true; return HANDLED;
} }
} }
private DcDefaultState mDefaultState = new DcDefaultState(); private DcDefaultState mDefaultState = new DcDefaultState();
@ -597,14 +688,12 @@ public abstract class DataConnection extends StateMachine {
boolean retVal; boolean retVal;
switch (msg.what) { switch (msg.what) {
case EVENT_RESET: case DataConnectionAc.REQ_RESET:
if (DBG) { if (DBG) {
log("DcInactiveState: msg.what=EVENT_RESET, ignore we're already reset"); log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset");
} }
if (msg.obj != null) { mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
notifyDisconnectCompleted((DisconnectParams) msg.obj); retVal = HANDLED;
}
retVal = true;
break; break;
case EVENT_CONNECT: case EVENT_CONNECT:
@ -613,12 +702,12 @@ public abstract class DataConnection extends StateMachine {
cp.tag = mTag; cp.tag = mTag;
onConnect(cp); onConnect(cp);
transitionTo(mActivatingState); transitionTo(mActivatingState);
retVal = true; retVal = HANDLED;
break; break;
default: default:
if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what); if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what);
retVal = false; retVal = NOT_HANDLED;
break; break;
} }
return retVal; return retVal;
@ -640,7 +729,7 @@ public abstract class DataConnection extends StateMachine {
case EVENT_DISCONNECT: case EVENT_DISCONNECT:
if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT"); if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT");
deferMessage(msg); deferMessage(msg);
retVal = true; retVal = HANDLED;
break; break;
case EVENT_SETUP_DATA_CONNECTION_DONE: case EVENT_SETUP_DATA_CONNECTION_DONE:
@ -685,7 +774,7 @@ public abstract class DataConnection extends StateMachine {
default: default:
throw new RuntimeException("Unknown SetupResult, should not happen"); throw new RuntimeException("Unknown SetupResult, should not happen");
} }
retVal = true; retVal = HANDLED;
break; break;
case EVENT_GET_LAST_FAIL_DONE: case EVENT_GET_LAST_FAIL_DONE:
@ -710,12 +799,12 @@ public abstract class DataConnection extends StateMachine {
} }
} }
retVal = true; retVal = HANDLED;
break; break;
default: default:
if (DBG) log("DcActivatingState not handled msg.what=" + msg.what); if (DBG) log("DcActivatingState not handled msg.what=" + msg.what);
retVal = false; retVal = NOT_HANDLED;
break; break;
} }
return retVal; return retVal;
@ -768,12 +857,12 @@ public abstract class DataConnection extends StateMachine {
dp.tag = mTag; dp.tag = mTag;
tearDownData(dp); tearDownData(dp);
transitionTo(mDisconnectingState); transitionTo(mDisconnectingState);
retVal = true; retVal = HANDLED;
break; break;
default: default:
if (DBG) log("DcActiveState nothandled msg.what=" + msg.what); if (DBG) log("DcActiveState nothandled msg.what=" + msg.what);
retVal = false; retVal = NOT_HANDLED;
break; break;
} }
return retVal; return retVal;
@ -803,12 +892,12 @@ public abstract class DataConnection extends StateMachine {
if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag=" if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag="
+ dp.tag + " mTag=" + mTag); + dp.tag + " mTag=" + mTag);
} }
retVal = true; retVal = HANDLED;
break; break;
default: default:
if (DBG) log("DcDisconnectingState not handled msg.what=" + msg.what); if (DBG) log("DcDisconnectingState not handled msg.what=" + msg.what);
retVal = false; retVal = NOT_HANDLED;
break; break;
} }
return retVal; return retVal;
@ -845,7 +934,7 @@ public abstract class DataConnection extends StateMachine {
" stale dp.tag=" + cp.tag + ", mTag=" + mTag); " stale dp.tag=" + cp.tag + ", mTag=" + mTag);
} }
} }
retVal = true; retVal = HANDLED;
break; break;
default: default:
@ -853,7 +942,7 @@ public abstract class DataConnection extends StateMachine {
log("DcDisconnectionErrorCreatingConnection not handled msg.what=" log("DcDisconnectionErrorCreatingConnection not handled msg.what="
+ msg.what); + msg.what);
} }
retVal = false; retVal = NOT_HANDLED;
break; break;
} }
return retVal; return retVal;
@ -865,147 +954,26 @@ public abstract class DataConnection extends StateMachine {
// ******* public interface // ******* public interface
/** /**
* Disconnect from the network. * Bring up a connection 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.
*/
public void reset(Message onCompletedMsg) {
sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(null, onCompletedMsg)));
}
/**
* Reset the connection and wait for it to complete.
* TODO: Remove when all callers only need the asynchronous
* reset defined above.
*/
public void resetSynchronously() {
ResetSynchronouslyLock lockObj = new ResetSynchronouslyLock();
synchronized(lockObj) {
sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(lockObj)));
try {
lockObj.wait();
} catch (InterruptedException e) {
log("blockingReset: unexpected interrupted of wait()");
}
}
}
/**
* Connect to the apn and return an AsyncResult in onCompletedMsg.
* Used for cellular networks that use Acesss Point Names (APN) such * Used for cellular networks that use Acesss Point Names (APN) such
* as GSM networks. * as GSM networks.
* *
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj, * With AsyncResult.userObj set to the original msg.obj,
* AsyncResult.result = FailCause and AsyncResult.exception = Exception(). * AsyncResult.result = FailCause and AsyncResult.exception = Exception().
* @param apn is the Access Point Name to connect to * @param apn is the Access Point Name to bring up a connection to
*/ */
public void connect(Message onCompletedMsg, ApnSetting apn) { public void bringUp(Message onCompletedMsg, ApnSetting apn) {
sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg))); sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg)));
} }
/** /**
* Connect to the apn and return an AsyncResult in onCompletedMsg. * Tear down the connection through the apn on the network.
*
* @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)));
}
/**
* Disconnect from the network.
* *
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj. * With AsyncResult.userObj set to the original msg.obj.
*/ */
public void disconnect(String reason, Message onCompletedMsg) { public void tearDown(String reason, Message onCompletedMsg) {
sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(reason, onCompletedMsg))); sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(reason, onCompletedMsg)));
} }
// ****** The following are used for debugging.
/**
* TODO: This should be an asynchronous call and we wouldn't
* have to use handle the notification in the DcInactiveState.enter.
*
* @return true if the state machine is in the inactive state.
*/
public boolean isInactive() {
boolean retVal = getCurrentState() == mInactiveState;
return retVal;
}
/**
* TODO: This should be an asynchronous call and we wouldn't
* have to use handle the notification in the DcActiveState.enter.
*
* @return true if the state machine is in the active state.
*/
public boolean isActive() {
boolean retVal = getCurrentState() == mActiveState;
return retVal;
}
/**
* Return the LinkProperties for the connection.
*
* @return a copy of the LinkProperties, is never null.
*/
public LinkProperties getLinkProperties() {
return new LinkProperties(mLinkProperties);
}
/**
* A capability is an Integer/String pair, the capabilities
* are defined in the class LinkSocket#Key.
*
* @return a copy of this connections capabilities, may be empty but never null.
*/
public LinkCapabilities getLinkCapabilities() {
return new LinkCapabilities(mCapabilities);
}
/**
* @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() {
return createTime;
}
/**
* @return the time of the last failure.
*/
public long getLastFailTime() {
return lastFailTime;
}
/**
* @return the last cause of failure.
*/
public FailCause getLastFailCause() {
return lastFailCause;
}
/**
* @return the current ApnSetting
*/
public ApnSetting getApn() {
return mApn;
}
public int getCid() {
return cid;
}
} }

View File

@ -0,0 +1,288 @@
/*
* Copyright (C) 2011 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 com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.ProxyProperties;
import android.os.Message;
/**
* AsyncChannel to a DataConnection
*/
public class DataConnectionAc extends AsyncChannel {
private static final boolean DBG = true;
private String mLogTag;
public DataConnection dataConnection;
public static final int BASE = Protocol.BASE_DATA_CONNECTION_AC;
public static final int REQ_IS_INACTIVE = BASE + 0;
public static final int RSP_IS_INACTIVE = BASE + 1;
public static final int REQ_GET_CID = BASE + 2;
public static final int RSP_GET_CID = BASE + 3;
public static final int REQ_GET_APNSETTING = BASE + 4;
public static final int RSP_GET_APNSETTING = BASE + 5;
public static final int REQ_GET_LINK_PROPERTIES = BASE + 6;
public static final int RSP_GET_LINK_PROPERTIES = BASE + 7;
public static final int REQ_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 8;
public static final int RSP_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 9;
public static final int REQ_GET_LINK_CAPABILITIES = BASE + 10;
public static final int RSP_GET_LINK_CAPABILITIES = BASE + 11;
public static final int REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE = BASE + 12;
public static final int RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE = BASE + 13;
public static final int REQ_RESET = BASE + 14;
public static final int RSP_RESET = BASE + 15;
public DataConnectionAc(DataConnection dc, String logTag) {
dataConnection = dc;
mLogTag = logTag;
}
/**
* Request if the state machine is in the inactive state.
* Response {@link #rspIsInactive}
*/
public void reqIsInactive() {
sendMessage(REQ_IS_INACTIVE);
if (DBG) log("reqIsInactive");
}
/**
* Evaluate RSP_IS_INACTIVE.
*
* @return true if the state machine is in the inactive state.
*/
public boolean rspIsInactive(Message response) {
boolean retVal = response.arg1 == 1;
if (DBG) log("rspIsInactive=" + retVal);
return retVal;
}
/**
* @return true if the state machine is in the inactive state.
*/
public boolean isInactiveSync() {
Message response = sendMessageSynchronously(REQ_IS_INACTIVE);
if ((response != null) && (response.what == RSP_IS_INACTIVE)) {
return rspIsInactive(response);
} else {
log("rspIsInactive error response=" + response);
return false;
}
}
/**
* Request the Connection ID.
* Response {@link #rspCid}
*/
public void reqCid() {
sendMessage(REQ_GET_CID);
if (DBG) log("reqCid");
}
/**
* Evaluate a RSP_GET_CID message and return the cid.
*
* @param response Message
* @return connection id or -1 if an error
*/
public int rspCid(Message response) {
int retVal = response.arg1;
if (DBG) log("rspCid=" + retVal);
return retVal;
}
/**
* @return connection id or -1 if an error
*/
public int getCidSync() {
Message response = sendMessageSynchronously(REQ_GET_CID);
if ((response != null) && (response.what == RSP_GET_CID)) {
return rspCid(response);
} else {
log("rspCid error response=" + response);
return -1;
}
}
/**
* Request the connections ApnSetting.
* Response {@link #rspApnSetting}
*/
public void reqApnSetting() {
sendMessage(REQ_GET_APNSETTING);
if (DBG) log("reqApnSetting");
}
/**
* Evaluate a RSP_APN_SETTING message and return the ApnSetting.
*
* @param response Message
* @return ApnSetting, maybe null
*/
public ApnSetting rspApnSetting(Message response) {
ApnSetting retVal = (ApnSetting) response.obj;
if (DBG) log("rspApnSetting=" + retVal);
return retVal;
}
/**
* Get the connections ApnSetting.
*
* @return ApnSetting or null if an error
*/
public ApnSetting getApnSettingSync() {
Message response = sendMessageSynchronously(REQ_GET_APNSETTING);
if ((response != null) && (response.what == RSP_GET_APNSETTING)) {
return rspApnSetting(response);
} else {
log("getApnSetting error response=" + response);
return null;
}
}
/**
* Request the connections LinkProperties.
* Response {@link #rspLinkProperties}
*/
public void reqLinkProperties() {
sendMessage(REQ_GET_LINK_PROPERTIES);
if (DBG) log("reqLinkProperties");
}
/**
* Evaluate RSP_GET_LINK_PROPERTIES
*
* @param response
* @return LinkProperties, maybe null.
*/
public LinkProperties rspLinkProperties(Message response) {
LinkProperties retVal = (LinkProperties) response.obj;
if (DBG) log("rspLinkProperties=" + retVal);
return retVal;
}
/**
* Get the connections LinkProperties.
*
* @return LinkProperties or null if an error
*/
public LinkProperties getLinkPropertiesSync() {
Message response = sendMessageSynchronously(REQ_GET_LINK_PROPERTIES);
if ((response != null) && (response.what == RSP_GET_LINK_PROPERTIES)) {
return rspLinkProperties(response);
} else {
log("getLinkProperties error response=" + response);
return null;
}
}
/**
* Request setting the connections LinkProperties.HttpProxy.
* Response RSP_SET_LINK_PROPERTIES when complete.
*/
public void reqSetLinkPropertiesHttpProxy(ProxyProperties proxy) {
sendMessage(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
if (DBG) log("reqSetLinkPropertiesHttpProxy proxy=" + proxy);
}
/**
* Set the connections LinkProperties.HttpProxy
*/
public void setLinkPropertiesHttpProxySync(ProxyProperties proxy) {
Message response =
sendMessageSynchronously(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
if ((response != null) && (response.what == RSP_SET_LINK_PROPERTIES_HTTP_PROXY)) {
if (DBG) log("setLinkPropertiesHttpPoxy ok");
} else {
log("setLinkPropertiesHttpPoxy error response=" + response);
}
}
/**
* Request the connections LinkCapabilities.
* Response {@link #rspLinkCapabilities}
*/
public void reqLinkCapabilities() {
sendMessage(REQ_GET_LINK_CAPABILITIES);
if (DBG) log("reqLinkCapabilities");
}
/**
* Evaluate RSP_GET_LINK_CAPABILITIES
*
* @param response
* @return LinkCapabilites, maybe null.
*/
public LinkCapabilities rspLinkCapabilities(Message response) {
LinkCapabilities retVal = (LinkCapabilities) response.obj;
if (DBG) log("rspLinkCapabilities=" + retVal);
return retVal;
}
/**
* Get the connections LinkCapabilities.
*
* @return LinkCapabilities or null if an error
*/
public LinkCapabilities getLinkCapabilitiesSync() {
Message response = sendMessageSynchronously(REQ_GET_LINK_CAPABILITIES);
if ((response != null) && (response.what == RSP_GET_LINK_CAPABILITIES)) {
return rspLinkCapabilities(response);
} else {
log("getLinkCapabilities error response=" + response);
return null;
}
}
/**
* Request the connections LinkCapabilities.
* Response RSP_RESET when complete
*/
public void reqReset() {
sendMessage(REQ_RESET);
if (DBG) log("reqReset");
}
/**
* Reset the connection and wait for it to complete.
*/
public void resetSync() {
Message response = sendMessageSynchronously(REQ_RESET);
if ((response != null) && (response.what == RSP_RESET)) {
if (DBG) log("restSync ok");
} else {
if (DBG) log("restSync error response=" + response);
}
}
private void log(String s) {
android.util.Log.d(mLogTag, "DataConnectionAc " + s);
}
}

View File

@ -22,7 +22,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.IConnectivityManager;
import android.net.LinkCapabilities; import android.net.LinkCapabilities;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.NetworkInfo; import android.net.NetworkInfo;
@ -32,7 +31,6 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.Messenger; import android.os.Messenger;
import android.os.ServiceManager;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.provider.Settings; import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException; import android.provider.Settings.SettingNotFoundException;
@ -40,6 +38,8 @@ import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -91,38 +91,39 @@ public abstract class DataConnectionTracker extends Handler {
public static String EXTRA_MESSENGER = "EXTRA_MESSENGER"; public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
/***** Event Codes *****/ /***** Event Codes *****/
protected static final int EVENT_DATA_SETUP_COMPLETE = 1; protected static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER;
protected static final int EVENT_RADIO_AVAILABLE = 3; protected static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0;
protected static final int EVENT_RECORDS_LOADED = 4; protected static final int EVENT_RADIO_AVAILABLE = BASE + 1;
protected static final int EVENT_TRY_SETUP_DATA = 5; protected static final int EVENT_RECORDS_LOADED = BASE + 2;
protected static final int EVENT_DATA_STATE_CHANGED = 6; protected static final int EVENT_TRY_SETUP_DATA = BASE + 3;
protected static final int EVENT_POLL_PDP = 7; protected static final int EVENT_DATA_STATE_CHANGED = BASE + 4;
protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12; protected static final int EVENT_POLL_PDP = BASE + 5;
protected static final int EVENT_VOICE_CALL_STARTED = 14; protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6;
protected static final int EVENT_VOICE_CALL_ENDED = 15; protected static final int EVENT_VOICE_CALL_STARTED = BASE + 7;
protected static final int EVENT_DATA_CONNECTION_DETACHED = 19; protected static final int EVENT_VOICE_CALL_ENDED = BASE + 8;
protected static final int EVENT_LINK_STATE_CHANGED = 20; protected static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9;
protected static final int EVENT_ROAMING_ON = 21; protected static final int EVENT_LINK_STATE_CHANGED = BASE + 10;
protected static final int EVENT_ROAMING_OFF = 22; protected static final int EVENT_ROAMING_ON = BASE + 11;
protected static final int EVENT_ENABLE_NEW_APN = 23; protected static final int EVENT_ROAMING_OFF = BASE + 12;
protected static final int EVENT_RESTORE_DEFAULT_APN = 24; protected static final int EVENT_ENABLE_NEW_APN = BASE + 13;
protected static final int EVENT_DISCONNECT_DONE = 25; protected static final int EVENT_RESTORE_DEFAULT_APN = BASE + 14;
protected static final int EVENT_DATA_CONNECTION_ATTACHED = 26; protected static final int EVENT_DISCONNECT_DONE = BASE + 15;
protected static final int EVENT_START_NETSTAT_POLL = 27; protected static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16;
protected static final int EVENT_START_RECOVERY = 28; protected static final int EVENT_START_NETSTAT_POLL = BASE + 17;
protected static final int EVENT_APN_CHANGED = 29; protected static final int EVENT_START_RECOVERY = BASE + 18;
protected static final int EVENT_CDMA_DATA_DETACHED = 30; protected static final int EVENT_APN_CHANGED = BASE + 19;
protected static final int EVENT_NV_READY = 31; protected static final int EVENT_CDMA_DATA_DETACHED = BASE + 20;
protected static final int EVENT_PS_RESTRICT_ENABLED = 32; protected static final int EVENT_NV_READY = BASE + 21;
protected static final int EVENT_PS_RESTRICT_DISABLED = 33; protected static final int EVENT_PS_RESTRICT_ENABLED = BASE + 22;
public static final int EVENT_CLEAN_UP_CONNECTION = 34; protected static final int EVENT_PS_RESTRICT_DISABLED = BASE + 23;
protected static final int EVENT_CDMA_OTA_PROVISION = 35; public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
protected static final int EVENT_RESTART_RADIO = 36; protected static final int EVENT_CDMA_OTA_PROVISION = BASE + 25;
protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37; protected static final int EVENT_RESTART_RADIO = BASE + 26;
protected static final int EVENT_RESET_DONE = 38; protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = BASE + 27;
public static final int CMD_SET_DATA_ENABLE = 39; protected static final int EVENT_RESET_DONE = BASE + 28;
public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = 40; public static final int CMD_SET_DATA_ENABLE = BASE + 29;
public static final int CMD_SET_DEPENDENCY_MET = 41; public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 30;
public static final int CMD_SET_DEPENDENCY_MET = BASE + 31;
/***** Constants *****/ /***** Constants *****/
@ -227,7 +228,7 @@ public abstract class DataConnectionTracker extends Handler {
/** indication of our availability (preconditions to trysetupData are met) **/ /** indication of our availability (preconditions to trysetupData are met) **/
protected boolean mAvailability = false; protected boolean mAvailability = false;
// When false we will not auto attach and manully attaching is required. // When false we will not auto attach and manually attaching is required.
protected boolean mAutoAttachOnCreation = false; protected boolean mAutoAttachOnCreation = false;
// State of screen // State of screen
@ -235,12 +236,6 @@ public abstract class DataConnectionTracker extends Handler {
// really a lower power mode") // really a lower power mode")
protected boolean mIsScreenOn = true; protected boolean mIsScreenOn = true;
/** The link properties (dns, gateway, ip, etc) */
protected LinkProperties mLinkProperties = new LinkProperties();
/** The link capabilities */
protected LinkCapabilities mLinkCapabilities = new LinkCapabilities();
/** Allows the generation of unique Id's for DataConnection objects */ /** Allows the generation of unique Id's for DataConnection objects */
protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0); protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
@ -248,6 +243,10 @@ public abstract class DataConnectionTracker extends Handler {
protected HashMap<Integer, DataConnection> mDataConnections = protected HashMap<Integer, DataConnection> mDataConnections =
new HashMap<Integer, DataConnection>(); new HashMap<Integer, DataConnection>();
/** The data connection async channels */
protected HashMap<Integer, DataConnectionAc> mDataConnectionAsyncChannels =
new HashMap<Integer, DataConnectionAc>();
/** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */ /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
protected HashMap<String, Integer> mApnToDataConnectionId = protected HashMap<String, Integer> mApnToDataConnectionId =
new HashMap<String, Integer>(); new HashMap<String, Integer>();
@ -267,7 +266,6 @@ public abstract class DataConnectionTracker extends Handler {
/** Is packet service restricted by network */ /** Is packet service restricted by network */
protected boolean mIsPsRestricted = false; protected boolean mIsPsRestricted = false;
/* Once disposed dont handle any messages */ /* Once disposed dont handle any messages */
protected boolean mIsDisposed = false; protected boolean mIsDisposed = false;
@ -351,6 +349,10 @@ public abstract class DataConnectionTracker extends Handler {
} }
public void dispose() { public void dispose() {
for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
dcac.disconnect();
}
mDataConnectionAsyncChannels.clear();
mIsDisposed = true; mIsDisposed = true;
mPhone.getContext().unregisterReceiver(this.mIntentReceiver); mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
} }
@ -463,7 +465,13 @@ public abstract class DataConnectionTracker extends Handler {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
switch (msg.what) { switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
log("DISCONNECTED_CONNECTED: msg=" + msg);
DataConnectionAc dcac = (DataConnectionAc) msg.obj;
mDataConnectionAsyncChannels.remove(dcac.dataConnection.getDataConnectionId());
dcac.disconnected();
break;
}
case EVENT_ENABLE_NEW_APN: case EVENT_ENABLE_NEW_APN:
onEnableApn(msg.arg1, msg.arg2); onEnableApn(msg.arg1, msg.arg2);
break; break;
@ -528,19 +536,20 @@ public abstract class DataConnectionTracker extends Handler {
break; break;
} }
case EVENT_RESET_DONE: { case EVENT_RESET_DONE: {
if (DBG) log("EVENT_RESET_DONE");
onResetDone((AsyncResult) msg.obj); onResetDone((AsyncResult) msg.obj);
break; break;
} }
case CMD_SET_DATA_ENABLE: { case CMD_SET_DATA_ENABLE: {
log("CMD_SET_DATA_ENABLE msg=" + msg);
boolean enabled = (msg.arg1 == ENABLED) ? true : false; boolean enabled = (msg.arg1 == ENABLED) ? true : false;
if (DBG) log("CMD_SET_DATA_ENABLE enabled=" + enabled);
onSetDataEnabled(enabled); onSetDataEnabled(enabled);
break; break;
} }
case CMD_SET_DEPENDENCY_MET: { case CMD_SET_DEPENDENCY_MET: {
log("CMD_SET_DEPENDENCY_MET msg=" + msg);
boolean met = (msg.arg1 == ENABLED) ? true : false; boolean met = (msg.arg1 == ENABLED) ? true : false;
if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met);
Bundle bundle = msg.getData(); Bundle bundle = msg.getData();
if (bundle != null) { if (bundle != null) {
String apnType = (String)bundle.get(APN_TYPE_KEY); String apnType = (String)bundle.get(APN_TYPE_KEY);
@ -552,7 +561,7 @@ public abstract class DataConnectionTracker extends Handler {
} }
default: default:
Log.e("DATA", "Unidentified event = " + msg.what); Log.e("DATA", "Unidentified event msg=" + msg);
break; break;
} }
} }
@ -618,7 +627,8 @@ public abstract class DataConnectionTracker extends Handler {
protected LinkProperties getLinkProperties(String apnType) { protected LinkProperties getLinkProperties(String apnType) {
int id = apnTypeToId(apnType); int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) { if (isApnIdEnabled(id)) {
return new LinkProperties(mLinkProperties); DataConnectionAc dcac = mDataConnectionAsyncChannels.get(id);
return dcac.getLinkPropertiesSync();
} else { } else {
return new LinkProperties(); return new LinkProperties();
} }
@ -627,33 +637,13 @@ public abstract class DataConnectionTracker extends Handler {
protected LinkCapabilities getLinkCapabilities(String apnType) { protected LinkCapabilities getLinkCapabilities(String apnType) {
int id = apnTypeToId(apnType); int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) { if (isApnIdEnabled(id)) {
return new LinkCapabilities(mLinkCapabilities); DataConnectionAc dcac = mDataConnectionAsyncChannels.get(id);
return dcac.getLinkCapabilitiesSync();
} else { } else {
return new LinkCapabilities(); return new LinkCapabilities();
} }
} }
/**
* Return the LinkProperties for the connection.
*
* @param connection
* @return a copy of the LinkProperties, is never null.
*/
protected LinkProperties getLinkProperties(DataConnection connection) {
return connection.getLinkProperties();
}
/**
* A capability is an Integer/String pair, the capabilities
* are defined in the class LinkSocket#Key.
*
* @param connection
* @return a copy of this connections capabilities, may be empty but never null.
*/
protected LinkCapabilities getLinkCapabilities(DataConnection connection) {
return connection.getLinkCapabilities();
}
// tell all active apns of the current condition // tell all active apns of the current condition
protected void notifyDataConnection(String reason) { protected void notifyDataConnection(String reason) {
for (int id = 0; id < APN_NUM_TYPES; id++) { for (int id = 0; id < APN_NUM_TYPES; id++) {

View File

@ -20,7 +20,6 @@ import android.os.Message;
import android.util.Log; import android.util.Log;
import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager; import com.android.internal.telephony.RetryManager;

View File

@ -37,10 +37,12 @@ import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection.FailCause; import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.RetryManager; import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone;
import com.android.internal.util.AsyncChannel;
import java.util.ArrayList; import java.util.ArrayList;
@ -297,14 +299,18 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
boolean notificationDeferred = false; boolean notificationDeferred = false;
for (DataConnection conn : mDataConnections.values()) { for (DataConnection conn : mDataConnections.values()) {
if(conn != null) { if(conn != null) {
DataConnectionAc dcac =
mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
if (tearDown) { if (tearDown) {
if (DBG) log("cleanUpConnection: teardown, call conn.disconnect"); if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
conn.disconnect(reason, obtainMessage(EVENT_DISCONNECT_DONE, conn.tearDown(reason, obtainMessage(EVENT_DISCONNECT_DONE,
conn.getDataConnectionId(), 0, reason)); conn.getDataConnectionId(), 0, reason));
notificationDeferred = true; notificationDeferred = true;
} else { } else {
if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously"); if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
conn.resetSynchronously(); if (dcac != null) {
dcac.resetSync();
}
notificationDeferred = false; notificationDeferred = false;
} }
} }
@ -319,11 +325,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
} }
private CdmaDataConnection findFreeDataConnection() { private CdmaDataConnection findFreeDataConnection() {
for (DataConnection dc : mDataConnections.values()) { for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
if (dc.isInactive()) { if (dcac.isInactiveSync()) {
return (CdmaDataConnection) dc; log("found free GsmDataConnection");
return (CdmaDataConnection) dcac.dataConnection;
} }
} }
log("NO free CdmaDataConnection");
return null; return null;
} }
@ -349,12 +357,12 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
} }
mActiveApn = new ApnSetting(apnId, "", "", "", "", "", "", "", "", "", mActiveApn = new ApnSetting(apnId, "", "", "", "", "", "", "", "", "",
"", 0, types, "IP", "IP"); "", 0, types, "IP", "IP");
if (DBG) log("setupData: mActiveApn=" + mActiveApn); if (DBG) log("call conn.bringUp mActiveApn=" + mActiveApn);
Message msg = obtainMessage(); Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE; msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason; msg.obj = reason;
conn.connect(msg, mActiveApn); conn.bringUp(msg, mActiveApn);
setState(State.INITING); setState(State.INITING);
notifyDataConnection(reason); notifyDataConnection(reason);
@ -653,11 +661,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
} }
if (ar.exception == null) { if (ar.exception == null) {
// TODO: We should clear LinkProperties/Capabilities when torn down or disconnected // Everything is setup
mLinkProperties = getLinkProperties(mPendingDataConnection);
mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
// everything is setup
notifyDefaultData(reason); notifyDefaultData(reason);
} else { } else {
FailCause cause = (FailCause) (ar.result); FailCause cause = (FailCause) (ar.result);
@ -767,6 +771,16 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
int id = mUniqueIdGenerator.getAndIncrement(); int id = mUniqueIdGenerator.getAndIncrement();
dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm); dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm);
mDataConnections.put(id, dataConn); mDataConnections.put(id, dataConn);
DataConnectionAc dcac = new DataConnectionAc(dataConn, LOG_TAG);
int status = dcac.fullyConnectSync(mPhone.getContext(), this, dataConn.getHandler());
if (status == AsyncChannel.STATUS_SUCCESSFUL) {
log("Fully connected");
mDataConnectionAsyncChannels.put(dcac.dataConnection.getDataConnectionId(), dcac);
} else {
log("Could not connect to dcac.dataConnection=" + dcac.dataConnection +
" status=" + status);
}
} }
} }
@ -897,6 +911,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@Override @Override
public void handleMessage (Message msg) { public void handleMessage (Message msg) {
if (DBG) log("CdmaDCT handleMessage msg=" + msg);
if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) { if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
log("Ignore CDMA msgs since CDMA phone is inactive"); log("Ignore CDMA msgs since CDMA phone is inactive");

View File

@ -21,7 +21,6 @@ import android.util.Log;
import android.util.Patterns; import android.util.Patterns;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase; import com.android.internal.telephony.PhoneBase;

View File

@ -53,6 +53,7 @@ import com.android.internal.telephony.ApnContext;
import com.android.internal.telephony.ApnSetting; import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase; import com.android.internal.telephony.PhoneBase;
@ -60,6 +61,7 @@ import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.DataConnection.FailCause; import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.RILConstants;
import com.android.internal.util.AsyncChannel;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
@ -119,7 +121,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override @Override
protected void onActionIntentReconnectAlarm(Intent intent) { protected void onActionIntentReconnectAlarm(Intent intent) {
log("GPRS reconnect alarm. Previous state was " + mState); if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON); String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE); String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
@ -224,7 +226,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
boolean possible = (isDataAllowed() boolean possible = (isDataAllowed()
&& !(getAnyDataEnabled() && (getOverallState() == State.FAILED))); && !(getAnyDataEnabled() && (getOverallState() == State.FAILED)));
if (!possible && DBG && isDataAllowed()) { if (!possible && DBG && isDataAllowed()) {
log("Data not possible. No coverage: dataState = " + getOverallState()); if (DBG) log("Data not possible. No coverage: dataState = " + getOverallState());
} }
return possible; return possible;
} }
@ -319,10 +321,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected LinkProperties getLinkProperties(String apnType) { protected LinkProperties getLinkProperties(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType); ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext != null) { if (apnContext != null) {
DataConnection dataConnection = apnContext.getDataConnection(); DataConnectionAc dcac = apnContext.getDataConnectionAc();
if (dataConnection != null) { if (dcac != null) {
if (DBG) log("get active pdp is not null, return link properites for " + apnType); if (DBG) log("return link properites for " + apnType);
return dataConnection.getLinkProperties(); return dcac.getLinkPropertiesSync();
} }
} }
if (DBG) log("return new LinkProperties"); if (DBG) log("return new LinkProperties");
@ -333,10 +335,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected LinkCapabilities getLinkCapabilities(String apnType) { protected LinkCapabilities getLinkCapabilities(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType); ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext!=null) { if (apnContext!=null) {
DataConnection dataConnection = apnContext.getDataConnection(); DataConnectionAc dataConnectionAc = apnContext.getDataConnectionAc();
if (dataConnection != null) { if (dataConnectionAc != null) {
if (DBG) log("get active pdp is not null, return link Capabilities for " + apnType); if (DBG) log("get active pdp is not null, return link Capabilities for " + apnType);
return dataConnection.getLinkCapabilities(); return dataConnectionAc.getLinkCapabilitiesSync();
} }
} }
if (DBG) log("return new LinkCapabilities"); if (DBG) log("return new LinkCapabilities");
@ -424,6 +426,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
if (!isAnyEnabled) { // Nothing enabled. return IDLE. if (!isAnyEnabled) { // Nothing enabled. return IDLE.
if (DBG) log( "overall state is IDLE");
return State.IDLE; return State.IDLE;
} }
@ -450,34 +453,34 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
*/ */
@Override @Override
public synchronized int enableApnType(String apnType) { public synchronized int enableApnType(String apnType) {
if (DBG) log("calling enableApnType with type:" + apnType);
ApnContext apnContext = mApnContexts.get(apnType); ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext == null || !isApnTypeAvailable(apnType)) { if (apnContext == null || !isApnTypeAvailable(apnType)) {
if (DBG) log("type not available"); if (DBG) log("enableApnType: " + apnType + " is type not available");
return Phone.APN_TYPE_NOT_AVAILABLE; return Phone.APN_TYPE_NOT_AVAILABLE;
} }
// If already active, return // If already active, return
log("enableApnType(" + apnType + ")" + ", mState(" + apnContext.getState() + ")"); if (DBG) log("enableApnType: " + apnType + " mState(" + apnContext.getState() + ")");
if (apnContext.getState() == State.INITING) { if (apnContext.getState() == State.INITING) {
if (DBG) log("return APN_REQUEST_STARTED"); if (DBG) log("enableApnType: return APN_REQUEST_STARTED");
return Phone.APN_REQUEST_STARTED; return Phone.APN_REQUEST_STARTED;
} }
else if (apnContext.getState() == State.CONNECTED) { else if (apnContext.getState() == State.CONNECTED) {
if (DBG) log("return APN_ALREADY_ACTIVE"); if (DBG) log("enableApnType: return APN_ALREADY_ACTIVE");
return Phone.APN_ALREADY_ACTIVE; return Phone.APN_ALREADY_ACTIVE;
} }
else if (apnContext.getState() == State.DISCONNECTING) { else if (apnContext.getState() == State.DISCONNECTING) {
if (DBG) log("requested APN while disconnecting"); if (DBG) log("enableApnType: while disconnecting, return APN_REQUEST_STARTED");
apnContext.setPendingAction(ApnContext.PENDING_ACTION_RECONNECT); apnContext.setPendingAction(ApnContext.PENDING_ACTION_RECONNECT);
return Phone.APN_REQUEST_STARTED; return Phone.APN_REQUEST_STARTED;
} }
if (DBG) log("new apn request for type " + apnType + " is to be handled");
setEnabled(apnTypeToId(apnType), true); setEnabled(apnTypeToId(apnType), true);
if (DBG) log("return APN_REQUEST_STARTED"); if (DBG) {
log("enableApnType: new apn request for type " + apnType +
" return APN_REQUEST_STARTED");
}
return Phone.APN_REQUEST_STARTED; return Phone.APN_REQUEST_STARTED;
} }
@ -502,7 +505,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override @Override
public synchronized int disableApnType(String type) { public synchronized int disableApnType(String type) {
if (DBG) log("calling disableApnType with type:" + type); if (DBG) log("disableApnType:" + type);
ApnContext apnContext = mApnContexts.get(type); ApnContext apnContext = mApnContexts.get(type);
if (apnContext != null) { if (apnContext != null) {
@ -515,18 +518,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.setReason(Phone.REASON_DATA_DISABLED); apnContext.setReason(Phone.REASON_DATA_DISABLED);
msg.obj = apnContext; msg.obj = apnContext;
sendMessage(msg); sendMessage(msg);
if (DBG) log("return APN_REQUEST_STARTED"); if (DBG) log("diableApnType: return APN_REQUEST_STARTED");
return Phone.APN_REQUEST_STARTED; return Phone.APN_REQUEST_STARTED;
} else { } else {
if (DBG) log("return APN_ALREADY_INACTIVE"); if (DBG) log("disableApnType: return APN_ALREADY_INACTIVE");
apnContext.setEnabled(false); apnContext.setEnabled(false);
apnContext.setDataConnection(null); apnContext.setDataConnection(null);
return Phone.APN_ALREADY_INACTIVE; return Phone.APN_ALREADY_INACTIVE;
} }
} else { } else {
if (DBG) if (DBG) {
log("no apn context was found, return APN_REQUEST_FAILED"); log("disableApnType: no apn context was found, return APN_REQUEST_FAILED");
}
return Phone.APN_REQUEST_FAILED; return Phone.APN_REQUEST_FAILED;
} }
} }
@ -583,12 +587,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* We presently believe it is unnecessary to tear down the PDP context * We presently believe it is unnecessary to tear down the PDP context
* when GPRS detaches, but we should stop the network polling. * when GPRS detaches, but we should stop the network polling.
*/ */
if (DBG) log ("onDataConnectionDetached: stop polling and notify detached");
stopNetStatPoll(); stopNetStatPoll();
notifyDataConnection(Phone.REASON_DATA_DETACHED); notifyDataConnection(Phone.REASON_DATA_DETACHED);
} }
private void onDataConnectionAttached() { private void onDataConnectionAttached() {
if (DBG) log("onDataConnectionAttached");
if (getOverallState() == State.CONNECTED) { if (getOverallState() == State.CONNECTED) {
if (DBG) log("onDataConnectionAttached: start polling notify attached");
startNetStatPoll(); startNetStatPoll();
notifyDataConnection(Phone.REASON_DATA_ATTACHED); notifyDataConnection(Phone.REASON_DATA_ATTACHED);
} }
@ -624,11 +631,40 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
if (mIsPsRestricted) reason += " - mIsPsRestricted= true"; if (mIsPsRestricted) reason += " - mIsPsRestricted= true";
if (!desiredPowerState) reason += " - desiredPowerState= false"; if (!desiredPowerState) reason += " - desiredPowerState= false";
log("Data not allowed due to" + reason); if (DBG) log("isDataAllowed: not allowed due to" + reason);
} }
return allowed; return allowed;
} }
/**
* Release the apnContext
*
* @param apnContext
* @param tearDown
* @return refCount
*/
private int releaseApnContext(ApnContext apnContext, boolean tearDown) {
if (apnContext == null) {
if (DBG) loge("releaseApnContext: apnContext null should not happen, ignore");
return -1;
}
DataConnection dc = apnContext.getDataConnection();
if (dc == null) {
if (DBG) loge("releaseApnContext: apnContext dc == null should not happen, ignore");
return -1;
}
int refCount = dc.decAndGetRefCount();
if (DBG) log("releaseApnContext: dec refCount=" + refCount + " tearDown=" + tearDown);
if (tearDown && (refCount == 0)) {
if (DBG) log("releaseApnContext: tearing down");
Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
}
apnContext.setDataConnection(null);
apnContext.setDataConnectionAc(null);
return refCount;
}
private void setupDataOnReadyApns(String reason) { private void setupDataOnReadyApns(String reason) {
// Only check for default APN state // Only check for default APN state
for (ApnContext apnContext : mApnContexts.values()) { for (ApnContext apnContext : mApnContexts.values()) {
@ -651,9 +687,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private boolean trySetupData(String reason, String type) { private boolean trySetupData(String reason, String type) {
if (DBG) { if (DBG) {
log("***trySetupData for type:" + type + log("trySetupData: " + type + " due to " + (reason == null ? "(unspecified)" : reason)
" due to " + (reason == null ? "(unspecified)" : reason) + + " isPsRestricted=" + mIsPsRestricted);
" isPsRestricted=" + mIsPsRestricted);
} }
if (type == null) { if (type == null) {
@ -663,18 +698,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
ApnContext apnContext = mApnContexts.get(type); ApnContext apnContext = mApnContexts.get(type);
if (apnContext == null ){ if (apnContext == null ){
if (DBG) log("new apn context for type:" + type); if (DBG) log("trySetupData new apn context for type:" + type);
apnContext = new ApnContext(type, LOG_TAG); apnContext = new ApnContext(type, LOG_TAG);
mApnContexts.put(type, apnContext); mApnContexts.put(type, apnContext);
} }
apnContext.setReason(reason); apnContext.setReason(reason);
return trySetupData(apnContext); return trySetupData(apnContext);
} }
private boolean trySetupData(ApnContext apnContext) { private boolean trySetupData(ApnContext apnContext) {
if (DBG) { if (DBG) {
log("trySetupData for type:" + apnContext.getApnType() + log("trySetupData for type:" + apnContext.getApnType() +
" due to " + apnContext.getReason()); " due to " + apnContext.getReason());
@ -687,7 +720,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.setState(State.CONNECTED); apnContext.setState(State.CONNECTED);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType()); mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
log("(fix?) We're on the simulator; assuming data is connected"); log("trySetupData: (fix?) We're on the simulator; assuming data is connected");
return true; return true;
} }
@ -699,13 +732,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (apnContext.getState() == State.IDLE) { if (apnContext.getState() == State.IDLE) {
ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType()); ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
if (waitingApns.isEmpty()) { if (waitingApns.isEmpty()) {
if (DBG) log("No APN found"); if (DBG) log("trySetupData: No APN found");
notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext); notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
notifyOffApnsOfAvailability(apnContext.getReason(), false); notifyOffApnsOfAvailability(apnContext.getReason(), false);
return false; return false;
} else { } else {
apnContext.setWaitingApns(waitingApns); apnContext.setWaitingApns(waitingApns);
log ("Create from mAllApns : " + apnListToString(mAllApns)); if (DBG) {
log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns));
}
} }
} }
@ -735,7 +770,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
for (ApnContext apnContext : mApnContexts.values()) { for (ApnContext apnContext : mApnContexts.values()) {
if (!apnContext.isReady()) { if (!apnContext.isReady()) {
if (DBG) log("notify disconnected for type:" + apnContext.getApnType()); if (DBG) log("notifyOffApnOfAvailability type:" + apnContext.getApnType());
mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(), mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
apnContext.getApnType(), apnContext.getApnType(),
Phone.DataState.DISCONNECTED); Phone.DataState.DISCONNECTED);
@ -753,7 +788,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* @param reason reason for the clean up. * @param reason reason for the clean up.
*/ */
protected void cleanUpAllConnections(boolean tearDown, String reason) { protected void cleanUpAllConnections(boolean tearDown, String reason) {
if (DBG) log("Clean up all connections due to " + reason); if (DBG) log("cleanUpAllConnections: tearDown=" + tearDown + " reason=" + reason);
for (ApnContext apnContext : mApnContexts.values()) { for (ApnContext apnContext : mApnContexts.values()) {
apnContext.setReason(reason); apnContext.setReason(reason);
@ -784,11 +819,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void cleanUpConnection(boolean tearDown, ApnContext apnContext) { private void cleanUpConnection(boolean tearDown, ApnContext apnContext) {
if (apnContext == null) { if (apnContext == null) {
if (DBG) log("apn context is null"); if (DBG) log("cleanUpConnection: apn context is null");
return; return;
} }
if (DBG) log("Clean up connection due to " + apnContext.getReason()); if (DBG) {
log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
}
// Clear the reconnect alarm, if set. // Clear the reconnect alarm, if set.
if (apnContext.getReconnectIntent() != null) { if (apnContext.getReconnectIntent() != null) {
@ -799,24 +836,26 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) { if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
if (DBG) log("state is in " + apnContext.getState()); if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
return; return;
} }
if (apnContext.getState() == State.FAILED) { if (apnContext.getState() == State.FAILED) {
if (DBG) log("state is in FAILED"); if (DBG) log("cleanUpConnection: state is in FAILED");
apnContext.setState(State.IDLE); apnContext.setState(State.IDLE);
return; return;
} }
DataConnection conn = apnContext.getDataConnection(); DataConnection conn = apnContext.getDataConnection();
if (conn != null) { if (conn != null) {
DataConnectionAc dcac = mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
apnContext.setState(State.DISCONNECTING); apnContext.setState(State.DISCONNECTING);
if (tearDown) { if (tearDown) {
Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext); releaseApnContext(apnContext, tearDown);
conn.disconnect(apnContext.getReason(), msg);
} else { } else {
conn.resetSynchronously(); if (dcac != null) {
dcac.resetSync();
}
apnContext.setState(State.IDLE); apnContext.setState(State.IDLE);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType()); mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
} }
@ -871,27 +910,31 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
private GsmDataConnection findFreeDataConnection() { private GsmDataConnection findFreeDataConnection() {
for (DataConnection dc : mDataConnections.values()) { for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
if (dc.isInactive()) { if (dcac.isInactiveSync()) {
log("found free GsmDataConnection"); log("findFreeDataConnection: found free GsmDataConnection");
return (GsmDataConnection) dc; return (GsmDataConnection) dcac.dataConnection;
} }
} }
log("NO free GsmDataConnection"); log("findFreeDataConnection: NO free GsmDataConnection");
return null; return null;
} }
protected GsmDataConnection findReadyDataConnection(ApnSetting apn) { protected GsmDataConnection findReadyDataConnection(ApnSetting apn) {
if (DBG) if (DBG)
log("findReadyDataConnection for apn string <" + log("findReadyDataConnection: apn string <" +
(apn!=null?(apn.toString()):"null") +">"); (apn!=null?(apn.toString()):"null") +">");
for (DataConnection conn : mDataConnections.values()) { if (apn == null) {
GsmDataConnection dc = (GsmDataConnection) conn; return null;
if (DBG) log("dc apn string <" + }
(dc.getApn() != null ? (dc.getApn().toString()) : "null") + ">"); for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
if (dc.getApn() != null && apn != null ApnSetting apnSetting = dcac.getApnSettingSync();
&& dc.getApn().toString().equals(apn.toString())) { if (DBG) {
return dc; log("findReadyDataConnection: dc apn string <" +
(apnSetting != null ? (apnSetting.toString()) : "null") + ">");
}
if ((apnSetting != null) && TextUtils.equals(apnSetting.toString(), apn.toString())) {
return (GsmDataConnection) dcac.dataConnection;
} }
} }
return null; return null;
@ -899,7 +942,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private boolean setupData(ApnContext apnContext) { private boolean setupData(ApnContext apnContext) {
if (DBG) log("enter setupData!"); if (DBG) log("setupData: apnContext=" + apnContext);
ApnSetting apn; ApnSetting apn;
GsmDataConnection dc; GsmDataConnection dc;
@ -920,7 +963,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
if (dc == null) { if (dc == null) {
dc = createDataConnection(apnContext); dc = createDataConnection(apnContext.getApnType());
} }
if (dc == null) { if (dc == null) {
@ -928,17 +971,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return false; return false;
} }
apnContext.setApnSetting(apn);
apnContext.setDataConnection(dc);
dc.setProfileId( profileId ); dc.setProfileId( profileId );
dc.setActiveApnType(apnContext.getApnType()); dc.setActiveApnType(apnContext.getApnType());
int refCount = dc.incAndGetRefCount();
if (DBG) log("setupData: init dc and apnContext refCount=" + refCount);
DataConnectionAc dcac = mDataConnectionAsyncChannels.get(dc.getDataConnectionId());
apnContext.setDataConnectionAc(mDataConnectionAsyncChannels.get(dc.getDataConnectionId()));
apnContext.setApnSetting(apn);
apnContext.setDataConnection(dc);
Message msg = obtainMessage(); Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE; msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = apnContext; msg.obj = apnContext;
dc.bringUp(msg, apn);
if (DBG) log("dc connect!");
dc.connect(msg, apn);
apnContext.setState(State.INITING); apnContext.setState(State.INITING);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType()); mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@ -981,7 +1026,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// TODO: It'd be nice to only do this if the changed entrie(s) // TODO: It'd be nice to only do this if the changed entrie(s)
// match the current operator. // match the current operator.
if (DBG) log("onApnChanged createAllApnList and cleanUpAllConnections"); if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections");
createAllApnList(); createAllApnList();
cleanUpAllConnections(isConnected, Phone.REASON_APN_CHANGED); cleanUpAllConnections(isConnected, Phone.REASON_APN_CHANGED);
if (!isConnected) { if (!isConnected) {
@ -998,25 +1043,30 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void onDataStateChanged (AsyncResult ar) { private void onDataStateChanged (AsyncResult ar) {
ArrayList<DataCallState> dataCallStates; ArrayList<DataCallState> dataCallStates;
if (DBG) log("onDataStateChanged(ar) E");
dataCallStates = (ArrayList<DataCallState>)(ar.result); dataCallStates = (ArrayList<DataCallState>)(ar.result);
if (ar.exception != null) { if (ar.exception != null) {
// This is probably "radio not available" or something // This is probably "radio not available" or something
// of that sort. If so, the whole connection is going // of that sort. If so, the whole connection is going
// to come down soon anyway // to come down soon anyway
if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
return; return;
} }
for (ApnContext apnContext : mApnContexts.values()) { for (ApnContext apnContext : mApnContexts.values()) {
onDataStateChanged(dataCallStates, apnContext); onDataStateChanged(dataCallStates, apnContext);
} }
if (DBG) log("onDataStateChanged(ar) X");
} }
private void onDataStateChanged (ArrayList<DataCallState> dataCallStates, private void onDataStateChanged (ArrayList<DataCallState> dataCallStates,
ApnContext apnContext) { ApnContext apnContext) {
if (DBG) log("onDataStateChanged(dataCallState, apnContext): apnContext=" + apnContext);
if (apnContext == null) { if (apnContext == null) {
// Should not happen // Should not happen
if (DBG) log("onDataStateChanged(dataCallState, apnContext): ignore apnContext=null");
return; return;
} }
@ -1027,28 +1077,37 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// context is still listed with active = false, which // context is still listed with active = false, which
// makes it hard to distinguish an activating context from // makes it hard to distinguish an activating context from
// an activated-and-then deactivated one. // an activated-and-then deactivated one.
if (!dataCallStatesHasCID(dataCallStates, apnContext.getDataConnection().getCid())) { DataConnectionAc dcac = apnContext.getDataConnectionAc();
if (dcac == null) {
if (DBG) log("onDataStateChanged(dataCallState, apnContext): dcac==null BAD NEWS");
return;
}
int cid = dcac.getCidSync();
if (!dataCallStatesHasCID(dataCallStates, cid)) {
// It looks like the PDP context has deactivated. // It looks like the PDP context has deactivated.
// Tear everything down and try to reconnect. // Tear everything down and try to reconnect.
Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting"); if (DBG) {
log("onDataStateChanged(dataCallStates,apnContext) " +
"PDP connection has dropped. Reconnecting");
}
// Add an event log when the network drops PDP // Add an event log when the network drops PDP
int cid = getCellLocationId(); int cellLocationId = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid, EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
TelephonyManager.getDefault().getNetworkType()); TelephonyManager.getDefault().getNetworkType());
cleanUpConnection(true, apnContext); cleanUpConnection(true, apnContext);
return;
} else if (!dataCallStatesHasActiveCID(dataCallStates, } else if (!dataCallStatesHasActiveCID(dataCallStates,
apnContext.getDataConnection().getCid())) { apnContext.getDataConnectionAc().getCidSync())) {
Log.i(LOG_TAG, "PDP connection has dropped (active=false case). " if (DBG) {
+ " Reconnecting"); log("onDataStateChanged(dataCallStates,apnContext) " +
"PDP connection has dropped (active=false case). Reconnecting");
}
// Log the network drop on the event log. // Log the network drop on the event log.
int cid = getCellLocationId(); int cellLocationId = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid, EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
TelephonyManager.getDefault().getNetworkType()); TelephonyManager.getDefault().getNetworkType());
cleanUpConnection(true, apnContext); cleanUpConnection(true, apnContext);
@ -1057,9 +1116,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
private void notifyDefaultData(ApnContext apnContext) { private void notifyDefaultData(ApnContext apnContext) {
if (DBG) if (DBG) {
log("notifyDefaultData for type: " + apnContext.getApnType() log("notifyDefaultData: type=" + apnContext.getApnType()
+ ", reason:" + apnContext.getReason()); + ", reason:" + apnContext.getReason());
}
apnContext.setState(State.CONNECTED); apnContext.setState(State.CONNECTED);
// setState(State.CONNECTED); // setState(State.CONNECTED);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType()); mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@ -1091,21 +1151,25 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (mPdpResetCount < maxPdpReset) { if (mPdpResetCount < maxPdpReset) {
mPdpResetCount++; mPdpResetCount++;
EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv); EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
if (DBG) log("doRecovery() cleanup all connections mPdpResetCount < max");
cleanUpAllConnections(true, Phone.REASON_PDP_RESET); cleanUpAllConnections(true, Phone.REASON_PDP_RESET);
} else { } else {
mPdpResetCount = 0; mPdpResetCount = 0;
EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv); EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
if (DBG) log("doRecovery() re-register getting preferred network type");
mPhone.getServiceStateTracker().reRegisterNetwork(null); mPhone.getServiceStateTracker().reRegisterNetwork(null);
} }
// TODO: Add increasingly drastic recovery steps, eg, // TODO: Add increasingly drastic recovery steps, eg,
// reset the radio, reset the device. // reset the radio, reset the device.
} else {
if (DBG) log("doRecovery(): ignore, we're not connected");
} }
} }
@Override @Override
protected void startNetStatPoll() { protected void startNetStatPoll() {
if (getOverallState() == State.CONNECTED && mNetStatPollEnabled == false) { if (getOverallState() == State.CONNECTED && mNetStatPollEnabled == false) {
log("[DataConnection] Start poll NetStat"); if (DBG) log("startNetStatPoll");
resetPollStats(); resetPollStats();
mNetStatPollEnabled = true; mNetStatPollEnabled = true;
mPollNetStat.run(); mPollNetStat.run();
@ -1116,12 +1180,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void stopNetStatPoll() { protected void stopNetStatPoll() {
mNetStatPollEnabled = false; mNetStatPollEnabled = false;
removeCallbacks(mPollNetStat); removeCallbacks(mPollNetStat);
log("[DataConnection] Stop poll NetStat"); if (DBG) log("stopNetStatPoll");
} }
@Override @Override
protected void restartRadio() { protected void restartRadio() {
log("************TURN OFF RADIO**************"); if (DBG) log("restartRadio: ************TURN OFF RADIO**************");
cleanUpAllConnections(true, Phone.REASON_RADIO_TURNED_OFF); cleanUpAllConnections(true, Phone.REASON_RADIO_TURNED_OFF);
mPhone.getServiceStateTracker().powerOffRadioSafely(this); mPhone.getServiceStateTracker().powerOffRadioSafely(this);
/* Note: no need to call setRadioPower(true). Assuming the desired /* Note: no need to call setRadioPower(true). Assuming the desired
@ -1202,7 +1266,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (mNoRecvPollCount < noRecvPollLimit) { if (mNoRecvPollCount < noRecvPollLimit) {
// It's possible the PDP context went down and we weren't notified. // It's possible the PDP context went down and we weren't notified.
// Start polling the context list in an attempt to recover. // Start polling the context list in an attempt to recover.
if (DBG) log("no DATAIN in a while; polling PDP"); if (DBG) log("Polling: no DATAIN in a while; polling PDP");
mPhone.mCM.getDataCallList(obtainMessage(EVENT_DATA_STATE_CHANGED)); mPhone.mCM.getDataCallList(obtainMessage(EVENT_DATA_STATE_CHANGED));
mNoRecvPollCount++; mNoRecvPollCount++;
@ -1212,7 +1276,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS, Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
POLL_NETSTAT_SLOW_MILLIS); POLL_NETSTAT_SLOW_MILLIS);
} else { } else {
if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) + if (DBG) log("Polling: Sent " + String.valueOf(mSentSinceLastRecv) +
" pkts since last received start recovery process"); " pkts since last received start recovery process");
stopNetStatPoll(); stopNetStatPoll();
sendMessage(obtainMessage(EVENT_START_RECOVERY)); sendMessage(obtainMessage(EVENT_START_RECOVERY));
@ -1262,14 +1326,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) { private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) {
if (apnContext == null) { if (apnContext == null) {
Log.d(LOG_TAG, "It is impossible"); loge("reconnectAfterFail: apnContext == null, impossible");
return; return;
} }
if (apnContext.getState() == State.FAILED) { if (apnContext.getState() == State.FAILED) {
if (!apnContext.getDataConnection().isRetryNeeded()) { if (!apnContext.getDataConnection().isRetryNeeded()) {
if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)){ if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)) {
// if no more retries on a secondary APN attempt, tell the world and revert.
apnContext.setDataConnection(null);
notifyDataConnection(Phone.REASON_APN_FAILED); notifyDataConnection(Phone.REASON_APN_FAILED);
return; return;
} }
@ -1278,7 +1340,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.getDataConnection().retryForeverUsingLastTimeout(); apnContext.getDataConnection().retryForeverUsingLastTimeout();
} else { } else {
// Try to Re-register to the network. // Try to Re-register to the network.
log("PDP activate failed, Reregistering to the network"); if (DBG) log("reconnectAfterFail: activate failed, Reregistering to network");
mReregisterOnReconnectFailure = true; mReregisterOnReconnectFailure = true;
mPhone.getServiceStateTracker().reRegisterNetwork(null); mPhone.getServiceStateTracker().reRegisterNetwork(null);
apnContext.getDataConnection().resetRetryCount(); apnContext.getDataConnection().resetRetryCount();
@ -1287,8 +1349,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer(); int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
log("PDP activate failed. Scheduling next attempt for " if (DBG) {
log("reconnectAfterFail: activate failed. Scheduling next attempt for "
+ (nextReconnectDelay / 1000) + "s"); + (nextReconnectDelay / 1000) + "s");
}
AlarmManager am = AlarmManager am =
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
@ -1305,8 +1369,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.getDataConnection().increaseRetryCount(); apnContext.getDataConnection().increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) { if (!shouldPostNotification(lastFailCauseCode)) {
Log.d(LOG_TAG, "NOT Posting GPRS Unavailable notification " if (DBG) {
log("reconnectAfterFail: NOT Posting GPRS Unavailable notification "
+ "-- likely transient error"); + "-- likely transient error");
}
} else { } else {
notifyNoData(lastFailCauseCode, apnContext); notifyNoData(lastFailCauseCode, apnContext);
} }
@ -1315,7 +1381,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode, private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode,
ApnContext apnContext) { ApnContext apnContext) {
if (DBG) log( "notifyNoData for type:" + apnContext.getApnType()); if (DBG) log( "notifyNoData: type=" + apnContext.getApnType());
apnContext.setState(State.FAILED); apnContext.setState(State.FAILED);
if (lastFailCauseCode.isPermanentFail() if (lastFailCauseCode.isPermanentFail()
&& (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT))) { && (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT))) {
@ -1327,7 +1393,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (DBG) log("onRecordsLoaded: createAllApnList"); if (DBG) log("onRecordsLoaded: createAllApnList");
createAllApnList(); createAllApnList();
if (mRadioAvailable) { if (mRadioAvailable) {
if (DBG) log("onRecordsLoaded, notifying data availability"); if (DBG) log("onRecordsLoaded: notifying data availability");
notifyDataAvailability(null); notifyDataAvailability(null);
} }
setupDataOnReadyApns(Phone.REASON_SIM_LOADED); setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
@ -1337,7 +1403,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onSetDependencyMet(String apnType, boolean met) { protected void onSetDependencyMet(String apnType, boolean met) {
ApnContext apnContext = mApnContexts.get(apnType); ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext == null) { if (apnContext == null) {
log("ApnContext not found in onSetDependencyMet(" + apnType + ", " + met + ")"); loge("onSetDependencyMet: ApnContext not found in onSetDependencyMet(" +
apnType + ", " + met + ")");
return; return;
} }
applyNewState(apnContext, apnContext.isEnabled(), met); applyNewState(apnContext, apnContext.isEnabled(), met);
@ -1373,12 +1440,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
trySetup = true; trySetup = true;
} else { } else {
// TODO send notifications int refCount = conn.incAndGetRefCount();
if (DBG) {
log("Found existing connection for " + apnContext.getApnType() +
": " + conn);
}
apnContext.setDataConnection(conn); apnContext.setDataConnection(conn);
apnContext.setDataConnectionAc(
mDataConnectionAsyncChannels.get(conn.getDataConnectionId()));
if (DBG) {
log("applyNewState: Found existing connection for " +
apnContext.getApnType() + " inc refCount=" + refCount +
" conn=" + conn);
}
} }
} }
} }
@ -1395,9 +1465,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
DataConnection conn = c.getDataConnection(); DataConnection conn = c.getDataConnection();
if (conn != null) { if (conn != null) {
ApnSetting apnSetting = c.getApnSetting(); ApnSetting apnSetting = c.getApnSetting();
if (apnSetting != null && apnSetting.canHandleType(apnType)) return conn; if (apnSetting != null && apnSetting.canHandleType(apnType)) {
if (DBG) {
log("checkForConnectionForApnContext: apnContext=" + apnContext +
" found conn=" + conn);
}
return conn;
} }
} }
}
if (DBG) log("checkForConnectionForApnContext: apnContext=" + apnContext + " NO conn");
return null; return null;
} }
@ -1405,43 +1482,47 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onEnableApn(int apnId, int enabled) { protected void onEnableApn(int apnId, int enabled) {
ApnContext apnContext = mApnContexts.get(apnIdToType(apnId)); ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));
if (apnContext == null) { if (apnContext == null) {
log("ApnContext not found in onEnableApn(" + apnId + ", " + enabled + ")"); loge("onEnableApn(" + apnId + ", " + enabled + "): NO ApnContext");
return; return;
} }
// TODO change our retry manager to use the appropriate numbers for the new APN // TODO change our retry manager to use the appropriate numbers for the new APN
log("onEnableApn with ApnContext E"); if (DBG) log("onEnableApn: apnContext=" + apnContext + " call applyNewState");
applyNewState(apnContext, enabled == ENABLED, apnContext.getDependencyMet()); applyNewState(apnContext, enabled == ENABLED, apnContext.getDependencyMet());
} }
@Override @Override
// TODO: We shouldnt need this. // TODO: We shouldnt need this.
protected boolean onTrySetupData(String reason) { protected boolean onTrySetupData(String reason) {
if (DBG) log("onTrySetupData: reason=" + reason);
setupDataOnReadyApns(reason); setupDataOnReadyApns(reason);
return true; return true;
} }
protected boolean onTrySetupData(ApnContext apnContext) { protected boolean onTrySetupData(ApnContext apnContext) {
if (DBG) log("onTrySetupData: apnContext=" + apnContext);
return trySetupData(apnContext); return trySetupData(apnContext);
} }
@Override @Override
protected void onRoamingOff() { protected void onRoamingOff() {
if (DBG) log("onRoamingOff");
setupDataOnReadyApns(Phone.REASON_ROAMING_OFF); setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
} }
@Override @Override
protected void onRoamingOn() { protected void onRoamingOn() {
if (getDataOnRoamingEnabled()) { if (getDataOnRoamingEnabled()) {
if (DBG) log("onRoamingOn: setup data on roaming");
setupDataOnReadyApns(Phone.REASON_ROAMING_ON); setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
} else { } else {
if (DBG) log("Tear down data connection on roaming."); if (DBG) log("onRoamingOn: Tear down data connection on roaming.");
cleanUpAllConnections(true, Phone.REASON_ROAMING_ON); cleanUpAllConnections(true, Phone.REASON_ROAMING_ON);
} }
} }
@Override @Override
protected void onRadioAvailable() { protected void onRadioAvailable() {
if (DBG) log("onRadioAvailable");
mRadioAvailable = true; mRadioAvailable = true;
if (mPhone.getSimulatedRadioControl() != null) { if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator // Assume data is connected on the simulator
@ -1449,7 +1530,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// setState(State.CONNECTED); // setState(State.CONNECTED);
notifyDataConnection(null); notifyDataConnection(null);
log("We're on the simulator; assuming data is connected"); log("onRadioAvailable: We're on the simulator; assuming data is connected");
} }
if (mPhone.mSIMRecords.getRecordsLoaded()) { if (mPhone.mSIMRecords.getRecordsLoaded()) {
@ -1477,7 +1558,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// FIXME this can be improved // FIXME this can be improved
log("We're on the simulator; assuming radio off is meaningless"); log("We're on the simulator; assuming radio off is meaningless");
} else { } else {
if (DBG) log("Radio is off and clean up all connection"); if (DBG) log("onRadioOffOrNotAvailable: is off and clean up all connections");
cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF); cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF);
} }
notifyDataAvailability(null); notifyDataAvailability(null);
@ -1490,27 +1571,29 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if(ar.userObj instanceof ApnContext){ if(ar.userObj instanceof ApnContext){
apnContext = (ApnContext)ar.userObj; apnContext = (ApnContext)ar.userObj;
} else {
throw new RuntimeException("onDataSetupComplete: No apnContext");
} }
DataConnectionAc dcac = apnContext.getDataConnectionAc();
if (dcac == null) {
throw new RuntimeException("onDataSetupCompete: No dcac");
}
DataConnection dc = apnContext.getDataConnection();
if (ar.exception == null) { if (ar.exception == null) {
// Everything is setup
// TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
if (DBG) { if (DBG) {
log(String.format("onDataSetupComplete: success apn=%s", log(String.format("onDataSetupComplete: success apn=%s",
apnContext.getWaitingApns().get(0).apn)); apnContext.getWaitingApns().get(0).apn) + " refCount=" + dc.getRefCount());
} }
mLinkProperties = getLinkProperties(apnContext.getApnType());
mLinkCapabilities = getLinkCapabilities(apnContext.getApnType());
ApnSetting apn = apnContext.getApnSetting(); ApnSetting apn = apnContext.getApnSetting();
if (apn.proxy != null && apn.proxy.length() != 0) { if (apn.proxy != null && apn.proxy.length() != 0) {
try { try {
ProxyProperties proxy = new ProxyProperties(apn.proxy, ProxyProperties proxy = new ProxyProperties(apn.proxy,
Integer.parseInt(apn.port), null); Integer.parseInt(apn.port), null);
mLinkProperties.setHttpProxy(proxy); dcac.setLinkPropertiesHttpProxySync(proxy);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
loge("NumberFormatException making ProxyProperties (" + apn.port + loge("onDataSetupComplete: NumberFormatException making ProxyProperties (" +
"): " + e); apn.port + "): " + e);
} }
} }
@ -1518,7 +1601,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if(TextUtils.equals(apnContext.getApnType(),Phone.APN_TYPE_DEFAULT)) { if(TextUtils.equals(apnContext.getApnType(),Phone.APN_TYPE_DEFAULT)) {
SystemProperties.set("gsm.defaultpdpcontext.active", "true"); SystemProperties.set("gsm.defaultpdpcontext.active", "true");
if (canSetPreferApn && mPreferredApn == null) { if (canSetPreferApn && mPreferredApn == null) {
log("PREFERED APN is null"); if (DBG) log("onDataSetupComplete: PREFERED APN is null");
mPreferredApn = apnContext.getApnSetting(); mPreferredApn = apnContext.getApnSetting();
if (mPreferredApn != null) { if (mPreferredApn != null) {
setPreferredApn(mPreferredApn.id); setPreferredApn(mPreferredApn.id);
@ -1528,15 +1611,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
SystemProperties.set("gsm.defaultpdpcontext.active", "false"); SystemProperties.set("gsm.defaultpdpcontext.active", "false");
} }
notifyDefaultData(apnContext); notifyDefaultData(apnContext);
// TODO: For simultaneous PDP support, we need to build another
// trigger another TRY_SETUP_DATA for the next APN type. (Note
// that the existing connection may service that type, in which
// case we should try the next type, etc.
// I dont believe for simultaneous PDP you need to trigger. Each
// Connection should be independent and they can be setup simultaneously
// So, dont have to wait till one is finished.
} else { } else {
int refCount = releaseApnContext(apnContext, false);
if (DBG) {
log(String.format("onDataSetupComplete: error apn=%s",
apnContext.getWaitingApns().get(0).apn) + " refCount=" + refCount);
}
GsmDataConnection.FailCause cause; GsmDataConnection.FailCause cause;
cause = (GsmDataConnection.FailCause) (ar.result); cause = (GsmDataConnection.FailCause) (ar.result);
if (DBG) { if (DBG) {
@ -1573,7 +1654,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
log("onDataSetupComplete: All APN's had permanent failures, stop retrying"); log("onDataSetupComplete: All APN's had permanent failures, stop retrying");
} }
apnContext.setState(State.FAILED); apnContext.setState(State.FAILED);
apnContext.setDataConnection(null);
notifyDataConnection(Phone.REASON_APN_FAILED); notifyDataConnection(Phone.REASON_APN_FAILED);
} else { } else {
if (DBG) log("onDataSetupComplete: Not all permanent failures, retry"); if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
@ -1597,7 +1677,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onDisconnectDone(int connId, AsyncResult ar) { protected void onDisconnectDone(int connId, AsyncResult ar) {
ApnContext apnContext = null; ApnContext apnContext = null;
if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId); if(DBG) log("onDisconnectDone: EVENT_DISCONNECT_DONE connId=" + connId);
if (ar.userObj instanceof ApnContext) { if (ar.userObj instanceof ApnContext) {
apnContext = (ApnContext) ar.userObj; apnContext = (ApnContext) ar.userObj;
} else { } else {
@ -1610,9 +1690,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// Check if APN disabled. // Check if APN disabled.
if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) { if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
apnContext.setEnabled(false);
apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE); apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE);
apnContext.setDataConnection(null);
} }
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType()); mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@ -1648,7 +1726,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override @Override
protected void onVoiceCallStarted() { protected void onVoiceCallStarted() {
if (DBG) log("onVoiceCallStarted");
if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
if (DBG) log("onVoiceCallStarted stop polling");
stopNetStatPoll(); stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
} }
@ -1656,6 +1736,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override @Override
protected void onVoiceCallEnded() { protected void onVoiceCallEnded() {
if (DBG) log("onVoiceCallEnded");
if (isConnected()) { if (isConnected()) {
if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
startNetStatPoll(); startNetStatPoll();
@ -1688,10 +1769,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override @Override
protected void notifyDataConnection(String reason) { protected void notifyDataConnection(String reason) {
if (DBG) log("notify all enabled connection for:" + reason); if (DBG) log("notifyDataConnection: reason=" + reason);
for (ApnContext apnContext : mApnContexts.values()) { for (ApnContext apnContext : mApnContexts.values()) {
if (apnContext.isReady()) { if (apnContext.isReady()) {
if (DBG) log("notify for type:"+apnContext.getApnType()); if (DBG) log("notifyDataConnection: type:"+apnContext.getApnType());
mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(), mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
apnContext.getApnType()); apnContext.getApnType());
} }
@ -1738,17 +1819,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} }
/** Return the id for a new data connection */ /** Return the id for a new data connection */
private GsmDataConnection createDataConnection(ApnContext apnContext) { private GsmDataConnection createDataConnection(String apnType) {
String apnType = apnContext.getApnType(); if (DBG) log("createDataConnection(" + apnType + ") E");
log("createDataConnection(" + apnType + ") E");
RetryManager rm = new RetryManager(); RetryManager rm = new RetryManager();
if (apnType.equals(Phone.APN_TYPE_DEFAULT)) { if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) { if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) { if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple linear sequence. // Should never happen, log an error and default to a simple linear sequence.
log("Could not configure using DEFAULT_DATA_RETRY_CONFIG=" loge("createDataConnection: Could not configure using " +
+ DEFAULT_DATA_RETRY_CONFIG); "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
rm.configure(20, 2000, 1000); rm.configure(20, 2000, 1000);
} }
} }
@ -1756,8 +1836,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (!rm.configure(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) { if (!rm.configure(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
if (!rm.configure(SECONDARY_DATA_RETRY_CONFIG)) { if (!rm.configure(SECONDARY_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple sequence. // Should never happen, log an error and default to a simple sequence.
log("Could note configure using SECONDARY_DATA_RETRY_CONFIG=" loge("createDataConnection: Could note configure using " +
+ SECONDARY_DATA_RETRY_CONFIG); "SECONDARY_DATA_RETRY_CONFIG=" + SECONDARY_DATA_RETRY_CONFIG);
rm.configure("max_retries=3, 333, 333, 333"); rm.configure("max_retries=3, 333, 333, 333");
} }
} }
@ -1767,18 +1847,25 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
GsmDataConnection conn = GsmDataConnection.makeDataConnection(mPhone, id, rm); GsmDataConnection conn = GsmDataConnection.makeDataConnection(mPhone, id, rm);
conn.resetRetryCount(); conn.resetRetryCount();
mDataConnections.put(id, conn); mDataConnections.put(id, conn);
apnContext.setDataConnection(conn); DataConnectionAc dcac = new DataConnectionAc(conn, LOG_TAG);
int status = dcac.fullyConnectSync(mPhone.getContext(), this, conn.getHandler());
if (status == AsyncChannel.STATUS_SUCCESSFUL) {
mDataConnectionAsyncChannels.put(dcac.dataConnection.getDataConnectionId(), dcac);
} else {
loge("createDataConnection: Could not connect to dcac.mDc=" + dcac.dataConnection +
" status=" + status);
}
log("createDataConnection(" + apnType + ") X id=" + id); if (DBG) log("createDataConnection(" + apnType + ") X id=" + id);
return conn; return conn;
} }
private void destroyDataConnections() { private void destroyDataConnections() {
if(mDataConnections != null) { if(mDataConnections != null) {
log("destroyDataConnectionList clear mDataConnectionList"); if (DBG) log("destroyDataConnections: clear mDataConnectionList");
mDataConnections.clear(); mDataConnections.clear();
} else { } else {
log("destroyDataConnectionList mDataConnecitonList is empty, ignore"); if (DBG) log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
} }
} }
@ -1802,8 +1889,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
String operator = mPhone.mSIMRecords.getSIMOperatorNumeric(); String operator = mPhone.mSIMRecords.getSIMOperatorNumeric();
if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
if (canSetPreferApn && mPreferredApn != null) { if (canSetPreferApn && mPreferredApn != null) {
log("Preferred APN:" + operator + ":" if (DBG) {
log("buildWaitingApns: Preferred APN:" + operator + ":"
+ mPreferredApn.numeric + ":" + mPreferredApn); + mPreferredApn.numeric + ":" + mPreferredApn);
}
if (mPreferredApn.numeric.equals(operator)) { if (mPreferredApn.numeric.equals(operator)) {
apnList.add(mPreferredApn); apnList.add(mPreferredApn);
if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList); if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
@ -1894,10 +1983,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override @Override
public void handleMessage (Message msg) { public void handleMessage (Message msg) {
if (DBG) log("GSMDataConnTrack handleMessage "+msg); if (DBG) log("handleMessage msg=" + msg);
if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) { if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
log("Ignore GSM msgs since GSM phone is inactive"); loge("handleMessage: Ignore GSM msgs since GSM phone is inactive");
return; return;
} }
@ -1941,7 +2030,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* PDP context and notify us with PDP_CONTEXT_CHANGED. * PDP context and notify us with PDP_CONTEXT_CHANGED.
* But we should stop the network polling and prevent reset PDP. * But we should stop the network polling and prevent reset PDP.
*/ */
log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); if (DBG) log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
stopNetStatPoll(); stopNetStatPoll();
mIsPsRestricted = true; mIsPsRestricted = true;
break; break;
@ -1951,7 +2040,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* When PS restrict is removed, we need setup PDP connection if * When PS restrict is removed, we need setup PDP connection if
* PDP connection is down. * PDP connection is down.
*/ */
log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted); if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
mIsPsRestricted = false; mIsPsRestricted = false;
if (isConnected()) { if (isConnected()) {
startNetStatPoll(); startNetStatPoll();
@ -1968,19 +2057,20 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
case EVENT_TRY_SETUP_DATA: case EVENT_TRY_SETUP_DATA:
if (msg.obj instanceof ApnContext) { if (msg.obj instanceof ApnContext) {
onTrySetupData((ApnContext)msg.obj); onTrySetupData((ApnContext)msg.obj);
} else { } else if (msg.obj instanceof String) {
if (msg.obj instanceof String) {
onTrySetupData((String)msg.obj); onTrySetupData((String)msg.obj);
} } else {
loge("EVENT_TRY_SETUP request w/o apnContext or String");
} }
break; break;
case EVENT_CLEAN_UP_CONNECTION: case EVENT_CLEAN_UP_CONNECTION:
boolean tearDown = (msg.arg1 == 0) ? false : true; boolean tearDown = (msg.arg1 == 0) ? false : true;
if (DBG) log("EVENT_CLEAN_UP_CONNECTION tearDown=" + tearDown);
if (msg.obj instanceof ApnContext) { if (msg.obj instanceof ApnContext) {
cleanUpConnection(tearDown, (ApnContext)msg.obj); cleanUpConnection(tearDown, (ApnContext)msg.obj);
} else { } else {
loge("[GsmDataConnectionTracker] connectpion cleanup request w/o apn context"); loge("EVENT_CLEAN_UP_CONNECTION request w/o apn context");
} }
break; break;
default: default: