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_DHCP = 0x00030000;
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;
//TODO: define all used protocols

View File

@ -51,6 +51,8 @@ public class ApnContext {
DataConnection mDataConnection;
DataConnectionAc mDataConnectionAc;
String mReason;
PendingIntent mReconnectIntent;
@ -96,6 +98,17 @@ public class ApnContext {
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() {
return mApnSetting;
}
@ -206,6 +219,11 @@ public class ApnContext {
return mDependencyMet.get();
}
@Override
public String toString() {
return "state=" + getState() + " apnType=" + mApnType;
}
protected void log(String s) {
Log.d(LOG_TAG, "[ApnContext] " + s);
}

View File

@ -17,22 +17,24 @@
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.StateMachine;
import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.ProxyProperties;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemProperties;
import android.text.TextUtils;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* {@hide}
@ -60,6 +62,8 @@ public abstract class DataConnection extends StateMachine {
protected static Object mCountLock = new Object();
protected static int mCount;
protected AsyncChannel mAc;
/**
* Used internally for saving connecting parameters.
@ -75,13 +79,6 @@ public abstract class DataConnection extends StateMachine {
public Message onCompletedMsg;
}
/**
* An instance used for notification of blockingReset.
* TODO: Remove when blockingReset is removed.
*/
class ResetSynchronouslyLock {
}
/**
* Used internally for saving disconnecting parameters.
*/
@ -90,15 +87,9 @@ public abstract class DataConnection extends StateMachine {
this.reason = reason;
this.onCompletedMsg = onCompletedMsg;
}
public DisconnectParams(ResetSynchronouslyLock lockObj) {
this.reason = null;
this.lockObj = lockObj;
}
public int tag;
public String reason;
public Message onCompletedMsg;
public ResetSynchronouslyLock lockObj;
}
/**
@ -188,13 +179,13 @@ public abstract class DataConnection extends StateMachine {
}
// ***** Event codes for driving the state machine
protected static final int EVENT_RESET = 1;
protected static final int EVENT_CONNECT = 2;
protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 3;
protected static final int EVENT_GET_LAST_FAIL_DONE = 4;
protected static final int EVENT_DEACTIVATE_DONE = 5;
protected static final int EVENT_DISCONNECT = 6;
protected static final int EVENT_RIL_CONNECTED = 7;
protected static final int BASE = Protocol.BASE_DATA_CONNECTION;
protected static final int EVENT_CONNECT = BASE + 0;
protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1;
protected static final int EVENT_GET_LAST_FAIL_DONE = BASE + 2;
protected static final int EVENT_DEACTIVATE_DONE = BASE + 3;
protected static final int EVENT_DISCONNECT = BASE + 4;
protected static final int EVENT_RIL_CONNECTED = BASE + 5;
//***** Tag IDs for EventLog
protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
@ -313,13 +304,8 @@ public abstract class DataConnection extends StateMachine {
AsyncResult.forMessage(msg);
msg.sendToTarget();
}
if (dp.lockObj != null) {
synchronized(dp.lockObj) {
dp.lockObj.notify();
}
}
clearSettings();
if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
}
protected int getRadioTechnology(int defaultRadioTechnology) {
@ -408,6 +394,49 @@ public abstract class DataConnection extends StateMachine {
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
@ -498,12 +527,74 @@ public abstract class DataConnection extends StateMachine {
AsyncResult ar;
switch (msg.what) {
case EVENT_RESET:
if (DBG) log("DcDefaultState: msg.what=EVENT_RESET");
clearSettings();
if (msg.obj != null) {
notifyDisconnectCompleted((DisconnectParams) msg.obj);
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
if (mAc != null) {
log("Disconnecting to previous connection mAc=" + mAc);
mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
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);
break;
@ -539,7 +630,7 @@ public abstract class DataConnection extends StateMachine {
break;
}
return true;
return HANDLED;
}
}
private DcDefaultState mDefaultState = new DcDefaultState();
@ -597,14 +688,12 @@ public abstract class DataConnection extends StateMachine {
boolean retVal;
switch (msg.what) {
case EVENT_RESET:
case DataConnectionAc.REQ_RESET:
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) {
notifyDisconnectCompleted((DisconnectParams) msg.obj);
}
retVal = true;
mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
retVal = HANDLED;
break;
case EVENT_CONNECT:
@ -613,12 +702,12 @@ public abstract class DataConnection extends StateMachine {
cp.tag = mTag;
onConnect(cp);
transitionTo(mActivatingState);
retVal = true;
retVal = HANDLED;
break;
default:
if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what);
retVal = false;
retVal = NOT_HANDLED;
break;
}
return retVal;
@ -640,7 +729,7 @@ public abstract class DataConnection extends StateMachine {
case EVENT_DISCONNECT:
if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT");
deferMessage(msg);
retVal = true;
retVal = HANDLED;
break;
case EVENT_SETUP_DATA_CONNECTION_DONE:
@ -685,7 +774,7 @@ public abstract class DataConnection extends StateMachine {
default:
throw new RuntimeException("Unknown SetupResult, should not happen");
}
retVal = true;
retVal = HANDLED;
break;
case EVENT_GET_LAST_FAIL_DONE:
@ -710,12 +799,12 @@ public abstract class DataConnection extends StateMachine {
}
}
retVal = true;
retVal = HANDLED;
break;
default:
if (DBG) log("DcActivatingState not handled msg.what=" + msg.what);
retVal = false;
retVal = NOT_HANDLED;
break;
}
return retVal;
@ -768,12 +857,12 @@ public abstract class DataConnection extends StateMachine {
dp.tag = mTag;
tearDownData(dp);
transitionTo(mDisconnectingState);
retVal = true;
retVal = HANDLED;
break;
default:
if (DBG) log("DcActiveState nothandled msg.what=" + msg.what);
retVal = false;
retVal = NOT_HANDLED;
break;
}
return retVal;
@ -803,12 +892,12 @@ public abstract class DataConnection extends StateMachine {
if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag="
+ dp.tag + " mTag=" + mTag);
}
retVal = true;
retVal = HANDLED;
break;
default:
if (DBG) log("DcDisconnectingState not handled msg.what=" + msg.what);
retVal = false;
retVal = NOT_HANDLED;
break;
}
return retVal;
@ -845,7 +934,7 @@ public abstract class DataConnection extends StateMachine {
" stale dp.tag=" + cp.tag + ", mTag=" + mTag);
}
}
retVal = true;
retVal = HANDLED;
break;
default:
@ -853,7 +942,7 @@ public abstract class DataConnection extends StateMachine {
log("DcDisconnectionErrorCreatingConnection not handled msg.what="
+ msg.what);
}
retVal = false;
retVal = NOT_HANDLED;
break;
}
return retVal;
@ -865,147 +954,26 @@ public abstract class DataConnection extends StateMachine {
// ******* public interface
/**
* Disconnect from the network.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj.
*/
public void 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.
* Bring up a connection to the apn and return an AsyncResult in onCompletedMsg.
* Used for cellular networks that use Acesss Point Names (APN) such
* as GSM networks.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj,
* AsyncResult.result = FailCause and AsyncResult.exception = Exception().
* @param apn is the 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)));
}
/**
* Connect to the apn and return an AsyncResult in onCompletedMsg.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj,
* AsyncResult.result = FailCause and AsyncResult.exception = Exception().
*/
public void connect(Message onCompletedMsg) {
sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(null, onCompletedMsg)));
}
/**
* Disconnect from the network.
* 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.
*/
public void disconnect(String reason, Message onCompletedMsg) {
public void tearDown(String reason, Message 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.IntentFilter;
import android.content.SharedPreferences;
import android.net.IConnectivityManager;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
@ -32,7 +31,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.ServiceManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@ -40,6 +38,8 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.R;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import java.util.ArrayList;
import java.util.HashMap;
@ -91,38 +91,39 @@ public abstract class DataConnectionTracker extends Handler {
public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
/***** Event Codes *****/
protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
protected static final int EVENT_RADIO_AVAILABLE = 3;
protected static final int EVENT_RECORDS_LOADED = 4;
protected static final int EVENT_TRY_SETUP_DATA = 5;
protected static final int EVENT_DATA_STATE_CHANGED = 6;
protected static final int EVENT_POLL_PDP = 7;
protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
protected static final int EVENT_VOICE_CALL_STARTED = 14;
protected static final int EVENT_VOICE_CALL_ENDED = 15;
protected static final int EVENT_DATA_CONNECTION_DETACHED = 19;
protected static final int EVENT_LINK_STATE_CHANGED = 20;
protected static final int EVENT_ROAMING_ON = 21;
protected static final int EVENT_ROAMING_OFF = 22;
protected static final int EVENT_ENABLE_NEW_APN = 23;
protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
protected static final int EVENT_DISCONNECT_DONE = 25;
protected static final int EVENT_DATA_CONNECTION_ATTACHED = 26;
protected static final int EVENT_START_NETSTAT_POLL = 27;
protected static final int EVENT_START_RECOVERY = 28;
protected static final int EVENT_APN_CHANGED = 29;
protected static final int EVENT_CDMA_DATA_DETACHED = 30;
protected static final int EVENT_NV_READY = 31;
protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
public static final int EVENT_CLEAN_UP_CONNECTION = 34;
protected static final int EVENT_CDMA_OTA_PROVISION = 35;
protected static final int EVENT_RESTART_RADIO = 36;
protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37;
protected static final int EVENT_RESET_DONE = 38;
public static final int CMD_SET_DATA_ENABLE = 39;
public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = 40;
public static final int CMD_SET_DEPENDENCY_MET = 41;
protected static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER;
protected static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0;
protected static final int EVENT_RADIO_AVAILABLE = BASE + 1;
protected static final int EVENT_RECORDS_LOADED = BASE + 2;
protected static final int EVENT_TRY_SETUP_DATA = BASE + 3;
protected static final int EVENT_DATA_STATE_CHANGED = BASE + 4;
protected static final int EVENT_POLL_PDP = BASE + 5;
protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6;
protected static final int EVENT_VOICE_CALL_STARTED = BASE + 7;
protected static final int EVENT_VOICE_CALL_ENDED = BASE + 8;
protected static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9;
protected static final int EVENT_LINK_STATE_CHANGED = BASE + 10;
protected static final int EVENT_ROAMING_ON = BASE + 11;
protected static final int EVENT_ROAMING_OFF = BASE + 12;
protected static final int EVENT_ENABLE_NEW_APN = BASE + 13;
protected static final int EVENT_RESTORE_DEFAULT_APN = BASE + 14;
protected static final int EVENT_DISCONNECT_DONE = BASE + 15;
protected static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16;
protected static final int EVENT_START_NETSTAT_POLL = BASE + 17;
protected static final int EVENT_START_RECOVERY = BASE + 18;
protected static final int EVENT_APN_CHANGED = BASE + 19;
protected static final int EVENT_CDMA_DATA_DETACHED = BASE + 20;
protected static final int EVENT_NV_READY = BASE + 21;
protected static final int EVENT_PS_RESTRICT_ENABLED = BASE + 22;
protected static final int EVENT_PS_RESTRICT_DISABLED = BASE + 23;
public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
protected static final int EVENT_CDMA_OTA_PROVISION = BASE + 25;
protected static final int EVENT_RESTART_RADIO = BASE + 26;
protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = BASE + 27;
protected static final int EVENT_RESET_DONE = BASE + 28;
public static final int CMD_SET_DATA_ENABLE = BASE + 29;
public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 30;
public static final int CMD_SET_DEPENDENCY_MET = BASE + 31;
/***** Constants *****/
@ -227,7 +228,7 @@ public abstract class DataConnectionTracker extends Handler {
/** indication of our availability (preconditions to trysetupData are met) **/
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;
// State of screen
@ -235,12 +236,6 @@ public abstract class DataConnectionTracker extends Handler {
// really a lower power mode")
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 */
protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
@ -248,6 +243,10 @@ public abstract class DataConnectionTracker extends Handler {
protected HashMap<Integer, DataConnection> mDataConnections =
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) */
protected HashMap<String, Integer> mApnToDataConnectionId =
new HashMap<String, Integer>();
@ -267,7 +266,6 @@ public abstract class DataConnectionTracker extends Handler {
/** Is packet service restricted by network */
protected boolean mIsPsRestricted = false;
/* Once disposed dont handle any messages */
protected boolean mIsDisposed = false;
@ -351,6 +349,10 @@ public abstract class DataConnectionTracker extends Handler {
}
public void dispose() {
for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
dcac.disconnect();
}
mDataConnectionAsyncChannels.clear();
mIsDisposed = true;
mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
}
@ -463,7 +465,13 @@ public abstract class DataConnectionTracker extends Handler {
@Override
public void handleMessage(Message msg) {
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:
onEnableApn(msg.arg1, msg.arg2);
break;
@ -528,19 +536,20 @@ public abstract class DataConnectionTracker extends Handler {
break;
}
case EVENT_RESET_DONE: {
if (DBG) log("EVENT_RESET_DONE");
onResetDone((AsyncResult) msg.obj);
break;
}
case CMD_SET_DATA_ENABLE: {
log("CMD_SET_DATA_ENABLE msg=" + msg);
boolean enabled = (msg.arg1 == ENABLED) ? true : false;
if (DBG) log("CMD_SET_DATA_ENABLE enabled=" + enabled);
onSetDataEnabled(enabled);
break;
}
case CMD_SET_DEPENDENCY_MET: {
log("CMD_SET_DEPENDENCY_MET msg=" + msg);
boolean met = (msg.arg1 == ENABLED) ? true : false;
if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met);
Bundle bundle = msg.getData();
if (bundle != null) {
String apnType = (String)bundle.get(APN_TYPE_KEY);
@ -552,7 +561,7 @@ public abstract class DataConnectionTracker extends Handler {
}
default:
Log.e("DATA", "Unidentified event = " + msg.what);
Log.e("DATA", "Unidentified event msg=" + msg);
break;
}
}
@ -618,7 +627,8 @@ public abstract class DataConnectionTracker extends Handler {
protected LinkProperties getLinkProperties(String apnType) {
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
return new LinkProperties(mLinkProperties);
DataConnectionAc dcac = mDataConnectionAsyncChannels.get(id);
return dcac.getLinkPropertiesSync();
} else {
return new LinkProperties();
}
@ -627,33 +637,13 @@ public abstract class DataConnectionTracker extends Handler {
protected LinkCapabilities getLinkCapabilities(String apnType) {
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
return new LinkCapabilities(mLinkCapabilities);
DataConnectionAc dcac = mDataConnectionAsyncChannels.get(id);
return dcac.getLinkCapabilitiesSync();
} else {
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
protected void notifyDataConnection(String reason) {
for (int id = 0; id < APN_NUM_TYPES; id++) {

View File

@ -20,7 +20,6 @@ import android.os.Message;
import android.util.Log;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
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.DataConnection.FailCause;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.Phone;
import com.android.internal.util.AsyncChannel;
import java.util.ArrayList;
@ -297,14 +299,18 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
boolean notificationDeferred = false;
for (DataConnection conn : mDataConnections.values()) {
if(conn != null) {
DataConnectionAc dcac =
mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
if (tearDown) {
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));
notificationDeferred = true;
} else {
if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
conn.resetSynchronously();
if (dcac != null) {
dcac.resetSync();
}
notificationDeferred = false;
}
}
@ -319,11 +325,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
private CdmaDataConnection findFreeDataConnection() {
for (DataConnection dc : mDataConnections.values()) {
if (dc.isInactive()) {
return (CdmaDataConnection) dc;
for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
if (dcac.isInactiveSync()) {
log("found free GsmDataConnection");
return (CdmaDataConnection) dcac.dataConnection;
}
}
log("NO free CdmaDataConnection");
return null;
}
@ -349,12 +357,12 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
mActiveApn = new ApnSetting(apnId, "", "", "", "", "", "", "", "", "",
"", 0, types, "IP", "IP");
if (DBG) log("setupData: mActiveApn=" + mActiveApn);
if (DBG) log("call conn.bringUp mActiveApn=" + mActiveApn);
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason;
conn.connect(msg, mActiveApn);
conn.bringUp(msg, mActiveApn);
setState(State.INITING);
notifyDataConnection(reason);
@ -653,11 +661,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
if (ar.exception == null) {
// TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
mLinkProperties = getLinkProperties(mPendingDataConnection);
mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
// everything is setup
// Everything is setup
notifyDefaultData(reason);
} else {
FailCause cause = (FailCause) (ar.result);
@ -767,6 +771,16 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
int id = mUniqueIdGenerator.getAndIncrement();
dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm);
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
public void handleMessage (Message msg) {
if (DBG) log("CdmaDCT handleMessage msg=" + msg);
if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
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.text.TextUtils;
import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.Phone;
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.DataCallState;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.Phone;
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.DataConnection.FailCause;
import com.android.internal.telephony.RILConstants;
import com.android.internal.util.AsyncChannel;
import java.io.IOException;
import java.net.InetAddress;
@ -119,7 +121,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
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 type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
@ -224,7 +226,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
boolean possible = (isDataAllowed()
&& !(getAnyDataEnabled() && (getOverallState() == State.FAILED)));
if (!possible && DBG && isDataAllowed()) {
log("Data not possible. No coverage: dataState = " + getOverallState());
if (DBG) log("Data not possible. No coverage: dataState = " + getOverallState());
}
return possible;
}
@ -319,10 +321,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected LinkProperties getLinkProperties(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext != null) {
DataConnection dataConnection = apnContext.getDataConnection();
if (dataConnection != null) {
if (DBG) log("get active pdp is not null, return link properites for " + apnType);
return dataConnection.getLinkProperties();
DataConnectionAc dcac = apnContext.getDataConnectionAc();
if (dcac != null) {
if (DBG) log("return link properites for " + apnType);
return dcac.getLinkPropertiesSync();
}
}
if (DBG) log("return new LinkProperties");
@ -333,10 +335,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected LinkCapabilities getLinkCapabilities(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext!=null) {
DataConnection dataConnection = apnContext.getDataConnection();
if (dataConnection != null) {
DataConnectionAc dataConnectionAc = apnContext.getDataConnectionAc();
if (dataConnectionAc != null) {
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");
@ -424,6 +426,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (!isAnyEnabled) { // Nothing enabled. return IDLE.
if (DBG) log( "overall state is IDLE");
return State.IDLE;
}
@ -450,34 +453,34 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
*/
@Override
public synchronized int enableApnType(String apnType) {
if (DBG) log("calling enableApnType with type:" + apnType);
ApnContext apnContext = mApnContexts.get(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;
}
// If already active, return
log("enableApnType(" + apnType + ")" + ", mState(" + apnContext.getState() + ")");
if (DBG) log("enableApnType: " + apnType + " mState(" + apnContext.getState() + ")");
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;
}
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;
}
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);
return Phone.APN_REQUEST_STARTED;
}
if (DBG) log("new apn request for type " + apnType + " is to be handled");
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;
}
@ -502,7 +505,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
public synchronized int disableApnType(String type) {
if (DBG) log("calling disableApnType with type:" + type);
if (DBG) log("disableApnType:" + type);
ApnContext apnContext = mApnContexts.get(type);
if (apnContext != null) {
@ -515,18 +518,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.setReason(Phone.REASON_DATA_DISABLED);
msg.obj = apnContext;
sendMessage(msg);
if (DBG) log("return APN_REQUEST_STARTED");
if (DBG) log("diableApnType: return APN_REQUEST_STARTED");
return Phone.APN_REQUEST_STARTED;
} else {
if (DBG) log("return APN_ALREADY_INACTIVE");
if (DBG) log("disableApnType: return APN_ALREADY_INACTIVE");
apnContext.setEnabled(false);
apnContext.setDataConnection(null);
return Phone.APN_ALREADY_INACTIVE;
}
} else {
if (DBG)
log("no apn context was found, return APN_REQUEST_FAILED");
if (DBG) {
log("disableApnType: no apn context was found, return 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
* when GPRS detaches, but we should stop the network polling.
*/
if (DBG) log ("onDataConnectionDetached: stop polling and notify detached");
stopNetStatPoll();
notifyDataConnection(Phone.REASON_DATA_DETACHED);
}
private void onDataConnectionAttached() {
if (DBG) log("onDataConnectionAttached");
if (getOverallState() == State.CONNECTED) {
if (DBG) log("onDataConnectionAttached: start polling notify attached");
startNetStatPoll();
notifyDataConnection(Phone.REASON_DATA_ATTACHED);
}
@ -624,11 +631,40 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (mIsPsRestricted) reason += " - mIsPsRestricted= true";
if (!desiredPowerState) reason += " - desiredPowerState= false";
log("Data not allowed due to" + reason);
if (DBG) log("isDataAllowed: not allowed due to" + reason);
}
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) {
// Only check for default APN state
for (ApnContext apnContext : mApnContexts.values()) {
@ -651,9 +687,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private boolean trySetupData(String reason, String type) {
if (DBG) {
log("***trySetupData for type:" + type +
" due to " + (reason == null ? "(unspecified)" : reason) +
" isPsRestricted=" + mIsPsRestricted);
log("trySetupData: " + type + " due to " + (reason == null ? "(unspecified)" : reason)
+ " isPsRestricted=" + mIsPsRestricted);
}
if (type == null) {
@ -663,18 +698,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
ApnContext apnContext = mApnContexts.get(type);
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);
mApnContexts.put(type, apnContext);
}
apnContext.setReason(reason);
return trySetupData(apnContext);
}
private boolean trySetupData(ApnContext apnContext) {
if (DBG) {
log("trySetupData for type:" + apnContext.getApnType() +
" due to " + apnContext.getReason());
@ -687,7 +720,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.setState(State.CONNECTED);
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;
}
@ -699,13 +732,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (apnContext.getState() == State.IDLE) {
ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
if (waitingApns.isEmpty()) {
if (DBG) log("No APN found");
if (DBG) log("trySetupData: No APN found");
notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
notifyOffApnsOfAvailability(apnContext.getReason(), false);
return false;
} else {
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()) {
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(),
apnContext.getApnType(),
Phone.DataState.DISCONNECTED);
@ -753,7 +788,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* @param reason reason for the clean up.
*/
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()) {
apnContext.setReason(reason);
@ -784,11 +819,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void cleanUpConnection(boolean tearDown, ApnContext apnContext) {
if (apnContext == null) {
if (DBG) log("apn context is null");
if (DBG) log("cleanUpConnection: apn context is null");
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.
if (apnContext.getReconnectIntent() != null) {
@ -799,24 +836,26 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
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;
}
if (apnContext.getState() == State.FAILED) {
if (DBG) log("state is in FAILED");
if (DBG) log("cleanUpConnection: state is in FAILED");
apnContext.setState(State.IDLE);
return;
}
DataConnection conn = apnContext.getDataConnection();
if (conn != null) {
DataConnectionAc dcac = mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
apnContext.setState(State.DISCONNECTING);
if (tearDown) {
Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
conn.disconnect(apnContext.getReason(), msg);
releaseApnContext(apnContext, tearDown);
} else {
conn.resetSynchronously();
if (dcac != null) {
dcac.resetSync();
}
apnContext.setState(State.IDLE);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
}
@ -871,27 +910,31 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
private GsmDataConnection findFreeDataConnection() {
for (DataConnection dc : mDataConnections.values()) {
if (dc.isInactive()) {
log("found free GsmDataConnection");
return (GsmDataConnection) dc;
for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
if (dcac.isInactiveSync()) {
log("findFreeDataConnection: found free GsmDataConnection");
return (GsmDataConnection) dcac.dataConnection;
}
}
log("NO free GsmDataConnection");
log("findFreeDataConnection: NO free GsmDataConnection");
return null;
}
protected GsmDataConnection findReadyDataConnection(ApnSetting apn) {
if (DBG)
log("findReadyDataConnection for apn string <" +
log("findReadyDataConnection: apn string <" +
(apn!=null?(apn.toString()):"null") +">");
for (DataConnection conn : mDataConnections.values()) {
GsmDataConnection dc = (GsmDataConnection) conn;
if (DBG) log("dc apn string <" +
(dc.getApn() != null ? (dc.getApn().toString()) : "null") + ">");
if (dc.getApn() != null && apn != null
&& dc.getApn().toString().equals(apn.toString())) {
return dc;
if (apn == null) {
return null;
}
for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
ApnSetting apnSetting = dcac.getApnSettingSync();
if (DBG) {
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;
@ -899,7 +942,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private boolean setupData(ApnContext apnContext) {
if (DBG) log("enter setupData!");
if (DBG) log("setupData: apnContext=" + apnContext);
ApnSetting apn;
GsmDataConnection dc;
@ -920,7 +963,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (dc == null) {
dc = createDataConnection(apnContext);
dc = createDataConnection(apnContext.getApnType());
}
if (dc == null) {
@ -928,17 +971,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return false;
}
apnContext.setApnSetting(apn);
apnContext.setDataConnection(dc);
dc.setProfileId( profileId );
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();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = apnContext;
if (DBG) log("dc connect!");
dc.connect(msg, apn);
dc.bringUp(msg, apn);
apnContext.setState(State.INITING);
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)
// match the current operator.
if (DBG) log("onApnChanged createAllApnList and cleanUpAllConnections");
if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections");
createAllApnList();
cleanUpAllConnections(isConnected, Phone.REASON_APN_CHANGED);
if (!isConnected) {
@ -998,25 +1043,30 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void onDataStateChanged (AsyncResult ar) {
ArrayList<DataCallState> dataCallStates;
if (DBG) log("onDataStateChanged(ar) E");
dataCallStates = (ArrayList<DataCallState>)(ar.result);
if (ar.exception != null) {
// This is probably "radio not available" or something
// of that sort. If so, the whole connection is going
// to come down soon anyway
if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
return;
}
for (ApnContext apnContext : mApnContexts.values()) {
onDataStateChanged(dataCallStates, apnContext);
}
if (DBG) log("onDataStateChanged(ar) X");
}
private void onDataStateChanged (ArrayList<DataCallState> dataCallStates,
ApnContext apnContext) {
if (DBG) log("onDataStateChanged(dataCallState, apnContext): apnContext=" + apnContext);
if (apnContext == null) {
// Should not happen
if (DBG) log("onDataStateChanged(dataCallState, apnContext): ignore apnContext=null");
return;
}
@ -1027,28 +1077,37 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// context is still listed with active = false, which
// makes it hard to distinguish an activating context from
// 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.
// 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
int cid = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
int cellLocationId = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
TelephonyManager.getDefault().getNetworkType());
cleanUpConnection(true, apnContext);
return;
} else if (!dataCallStatesHasActiveCID(dataCallStates,
apnContext.getDataConnection().getCid())) {
apnContext.getDataConnectionAc().getCidSync())) {
Log.i(LOG_TAG, "PDP connection has dropped (active=false case). "
+ " Reconnecting");
if (DBG) {
log("onDataStateChanged(dataCallStates,apnContext) " +
"PDP connection has dropped (active=false case). Reconnecting");
}
// Log the network drop on the event log.
int cid = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
int cellLocationId = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
TelephonyManager.getDefault().getNetworkType());
cleanUpConnection(true, apnContext);
@ -1057,9 +1116,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
private void notifyDefaultData(ApnContext apnContext) {
if (DBG)
log("notifyDefaultData for type: " + apnContext.getApnType()
if (DBG) {
log("notifyDefaultData: type=" + apnContext.getApnType()
+ ", reason:" + apnContext.getReason());
}
apnContext.setState(State.CONNECTED);
// setState(State.CONNECTED);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@ -1091,21 +1151,25 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (mPdpResetCount < maxPdpReset) {
mPdpResetCount++;
EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
if (DBG) log("doRecovery() cleanup all connections mPdpResetCount < max");
cleanUpAllConnections(true, Phone.REASON_PDP_RESET);
} else {
mPdpResetCount = 0;
EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
if (DBG) log("doRecovery() re-register getting preferred network type");
mPhone.getServiceStateTracker().reRegisterNetwork(null);
}
// TODO: Add increasingly drastic recovery steps, eg,
// reset the radio, reset the device.
} else {
if (DBG) log("doRecovery(): ignore, we're not connected");
}
}
@Override
protected void startNetStatPoll() {
if (getOverallState() == State.CONNECTED && mNetStatPollEnabled == false) {
log("[DataConnection] Start poll NetStat");
if (DBG) log("startNetStatPoll");
resetPollStats();
mNetStatPollEnabled = true;
mPollNetStat.run();
@ -1116,12 +1180,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void stopNetStatPoll() {
mNetStatPollEnabled = false;
removeCallbacks(mPollNetStat);
log("[DataConnection] Stop poll NetStat");
if (DBG) log("stopNetStatPoll");
}
@Override
protected void restartRadio() {
log("************TURN OFF RADIO**************");
if (DBG) log("restartRadio: ************TURN OFF RADIO**************");
cleanUpAllConnections(true, Phone.REASON_RADIO_TURNED_OFF);
mPhone.getServiceStateTracker().powerOffRadioSafely(this);
/* Note: no need to call setRadioPower(true). Assuming the desired
@ -1202,7 +1266,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (mNoRecvPollCount < noRecvPollLimit) {
// It's possible the PDP context went down and we weren't notified.
// 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));
mNoRecvPollCount++;
@ -1212,7 +1276,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
POLL_NETSTAT_SLOW_MILLIS);
} else {
if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) +
if (DBG) log("Polling: Sent " + String.valueOf(mSentSinceLastRecv) +
" pkts since last received start recovery process");
stopNetStatPoll();
sendMessage(obtainMessage(EVENT_START_RECOVERY));
@ -1262,14 +1326,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) {
if (apnContext == null) {
Log.d(LOG_TAG, "It is impossible");
loge("reconnectAfterFail: apnContext == null, impossible");
return;
}
if (apnContext.getState() == State.FAILED) {
if (!apnContext.getDataConnection().isRetryNeeded()) {
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);
if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)) {
notifyDataConnection(Phone.REASON_APN_FAILED);
return;
}
@ -1278,7 +1340,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.getDataConnection().retryForeverUsingLastTimeout();
} else {
// 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;
mPhone.getServiceStateTracker().reRegisterNetwork(null);
apnContext.getDataConnection().resetRetryCount();
@ -1287,8 +1349,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
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");
}
AlarmManager am =
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
@ -1305,8 +1369,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.getDataConnection().increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
Log.d(LOG_TAG, "NOT Posting GPRS Unavailable notification "
if (DBG) {
log("reconnectAfterFail: NOT Posting GPRS Unavailable notification "
+ "-- likely transient error");
}
} else {
notifyNoData(lastFailCauseCode, apnContext);
}
@ -1315,7 +1381,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode,
ApnContext apnContext) {
if (DBG) log( "notifyNoData for type:" + apnContext.getApnType());
if (DBG) log( "notifyNoData: type=" + apnContext.getApnType());
apnContext.setState(State.FAILED);
if (lastFailCauseCode.isPermanentFail()
&& (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT))) {
@ -1327,7 +1393,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (DBG) log("onRecordsLoaded: createAllApnList");
createAllApnList();
if (mRadioAvailable) {
if (DBG) log("onRecordsLoaded, notifying data availability");
if (DBG) log("onRecordsLoaded: notifying data availability");
notifyDataAvailability(null);
}
setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
@ -1337,7 +1403,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onSetDependencyMet(String apnType, boolean met) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext == null) {
log("ApnContext not found in onSetDependencyMet(" + apnType + ", " + met + ")");
loge("onSetDependencyMet: ApnContext not found in onSetDependencyMet(" +
apnType + ", " + met + ")");
return;
}
applyNewState(apnContext, apnContext.isEnabled(), met);
@ -1373,12 +1440,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
trySetup = true;
} else {
// TODO send notifications
if (DBG) {
log("Found existing connection for " + apnContext.getApnType() +
": " + conn);
}
int refCount = conn.incAndGetRefCount();
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();
if (conn != null) {
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;
}
@ -1405,43 +1482,47 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onEnableApn(int apnId, int enabled) {
ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));
if (apnContext == null) {
log("ApnContext not found in onEnableApn(" + apnId + ", " + enabled + ")");
loge("onEnableApn(" + apnId + ", " + enabled + "): NO ApnContext");
return;
}
// 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());
}
@Override
// TODO: We shouldnt need this.
protected boolean onTrySetupData(String reason) {
if (DBG) log("onTrySetupData: reason=" + reason);
setupDataOnReadyApns(reason);
return true;
}
protected boolean onTrySetupData(ApnContext apnContext) {
if (DBG) log("onTrySetupData: apnContext=" + apnContext);
return trySetupData(apnContext);
}
@Override
protected void onRoamingOff() {
if (DBG) log("onRoamingOff");
setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
}
@Override
protected void onRoamingOn() {
if (getDataOnRoamingEnabled()) {
if (DBG) log("onRoamingOn: setup data on roaming");
setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
} 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);
}
}
@Override
protected void onRadioAvailable() {
if (DBG) log("onRadioAvailable");
mRadioAvailable = true;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
@ -1449,7 +1530,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// setState(State.CONNECTED);
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()) {
@ -1477,7 +1558,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// FIXME this can be improved
log("We're on the simulator; assuming radio off is meaningless");
} 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);
}
notifyDataAvailability(null);
@ -1490,27 +1571,29 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if(ar.userObj instanceof ApnContext){
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) {
// Everything is setup
// TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
if (DBG) {
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();
if (apn.proxy != null && apn.proxy.length() != 0) {
try {
ProxyProperties proxy = new ProxyProperties(apn.proxy,
Integer.parseInt(apn.port), null);
mLinkProperties.setHttpProxy(proxy);
dcac.setLinkPropertiesHttpProxySync(proxy);
} catch (NumberFormatException e) {
loge("NumberFormatException making ProxyProperties (" + apn.port +
"): " + e);
loge("onDataSetupComplete: NumberFormatException making ProxyProperties (" +
apn.port + "): " + e);
}
}
@ -1518,7 +1601,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if(TextUtils.equals(apnContext.getApnType(),Phone.APN_TYPE_DEFAULT)) {
SystemProperties.set("gsm.defaultpdpcontext.active", "true");
if (canSetPreferApn && mPreferredApn == null) {
log("PREFERED APN is null");
if (DBG) log("onDataSetupComplete: PREFERED APN is null");
mPreferredApn = apnContext.getApnSetting();
if (mPreferredApn != null) {
setPreferredApn(mPreferredApn.id);
@ -1528,15 +1611,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
SystemProperties.set("gsm.defaultpdpcontext.active", "false");
}
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 {
int refCount = releaseApnContext(apnContext, false);
if (DBG) {
log(String.format("onDataSetupComplete: error apn=%s",
apnContext.getWaitingApns().get(0).apn) + " refCount=" + refCount);
}
GsmDataConnection.FailCause cause;
cause = (GsmDataConnection.FailCause) (ar.result);
if (DBG) {
@ -1573,7 +1654,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
log("onDataSetupComplete: All APN's had permanent failures, stop retrying");
}
apnContext.setState(State.FAILED);
apnContext.setDataConnection(null);
notifyDataConnection(Phone.REASON_APN_FAILED);
} else {
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) {
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) {
apnContext = (ApnContext) ar.userObj;
} else {
@ -1610,9 +1690,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// Check if APN disabled.
if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
apnContext.setEnabled(false);
apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE);
apnContext.setDataConnection(null);
}
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@ -1648,7 +1726,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
protected void onVoiceCallStarted() {
if (DBG) log("onVoiceCallStarted");
if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
if (DBG) log("onVoiceCallStarted stop polling");
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
}
@ -1656,6 +1736,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
protected void onVoiceCallEnded() {
if (DBG) log("onVoiceCallEnded");
if (isConnected()) {
if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
startNetStatPoll();
@ -1688,10 +1769,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
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()) {
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(),
apnContext.getApnType());
}
@ -1738,17 +1819,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
/** Return the id for a new data connection */
private GsmDataConnection createDataConnection(ApnContext apnContext) {
String apnType = apnContext.getApnType();
log("createDataConnection(" + apnType + ") E");
private GsmDataConnection createDataConnection(String apnType) {
if (DBG) log("createDataConnection(" + apnType + ") E");
RetryManager rm = new RetryManager();
if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple linear sequence.
log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+ DEFAULT_DATA_RETRY_CONFIG);
loge("createDataConnection: Could not configure using " +
"DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
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(SECONDARY_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple sequence.
log("Could note configure using SECONDARY_DATA_RETRY_CONFIG="
+ SECONDARY_DATA_RETRY_CONFIG);
loge("createDataConnection: Could note configure using " +
"SECONDARY_DATA_RETRY_CONFIG=" + SECONDARY_DATA_RETRY_CONFIG);
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);
conn.resetRetryCount();
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;
}
private void destroyDataConnections() {
if(mDataConnections != null) {
log("destroyDataConnectionList clear mDataConnectionList");
if (DBG) log("destroyDataConnections: clear mDataConnectionList");
mDataConnections.clear();
} 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();
if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
if (canSetPreferApn && mPreferredApn != null) {
log("Preferred APN:" + operator + ":"
if (DBG) {
log("buildWaitingApns: Preferred APN:" + operator + ":"
+ mPreferredApn.numeric + ":" + mPreferredApn);
}
if (mPreferredApn.numeric.equals(operator)) {
apnList.add(mPreferredApn);
if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
@ -1894,10 +1983,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
public void handleMessage (Message msg) {
if (DBG) log("GSMDataConnTrack handleMessage "+msg);
if (DBG) log("handleMessage msg=" + msg);
if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
log("Ignore GSM msgs since GSM phone is inactive");
loge("handleMessage: Ignore GSM msgs since GSM phone is inactive");
return;
}
@ -1941,7 +2030,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* PDP context and notify us with PDP_CONTEXT_CHANGED.
* 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();
mIsPsRestricted = true;
break;
@ -1951,7 +2040,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* When PS restrict is removed, we need setup PDP connection if
* PDP connection is down.
*/
log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
mIsPsRestricted = false;
if (isConnected()) {
startNetStatPoll();
@ -1968,19 +2057,20 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
case EVENT_TRY_SETUP_DATA:
if (msg.obj instanceof ApnContext) {
onTrySetupData((ApnContext)msg.obj);
} else if (msg.obj instanceof String) {
onTrySetupData((String)msg.obj);
} else {
if (msg.obj instanceof String) {
onTrySetupData((String)msg.obj);
}
loge("EVENT_TRY_SETUP request w/o apnContext or String");
}
break;
case EVENT_CLEAN_UP_CONNECTION:
boolean tearDown = (msg.arg1 == 0) ? false : true;
if (DBG) log("EVENT_CLEAN_UP_CONNECTION tearDown=" + tearDown);
if (msg.obj instanceof ApnContext) {
cleanUpConnection(tearDown, (ApnContext)msg.obj);
} else {
loge("[GsmDataConnectionTracker] connectpion cleanup request w/o apn context");
loge("EVENT_CLEAN_UP_CONNECTION request w/o apn context");
}
break;
default: