am 29d1dde9: Merge "Data connection retry pattern could be broken by PDP sharing" into honeycomb-LTE
* commit '29d1dde972acaaf3685b60de3da00c1809c510f9': Data connection retry pattern could be broken by PDP sharing
This commit is contained in:
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.internal.telephony;
|
package com.android.internal.telephony;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@@ -49,8 +47,6 @@ public class ApnContext {
|
|||||||
|
|
||||||
String mReason;
|
String mReason;
|
||||||
|
|
||||||
PendingIntent mReconnectIntent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* user/app requested connection on this APN
|
* user/app requested connection on this APN
|
||||||
*/
|
*/
|
||||||
@@ -90,9 +86,9 @@ public class ApnContext {
|
|||||||
|
|
||||||
public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
|
public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
|
||||||
if (dcac != null) {
|
if (dcac != null) {
|
||||||
dcac.addApnContext(this);
|
dcac.addApnContextSync(this);
|
||||||
} else {
|
} else {
|
||||||
if (mDataConnectionAc != null) mDataConnectionAc.removeApnContext(this);
|
if (mDataConnectionAc != null) mDataConnectionAc.removeApnContextSync(this);
|
||||||
}
|
}
|
||||||
mDataConnectionAc = dcac;
|
mDataConnectionAc = dcac;
|
||||||
}
|
}
|
||||||
@@ -169,16 +165,6 @@ public class ApnContext {
|
|||||||
return mReason;
|
return mReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setReconnectIntent(PendingIntent intent) {
|
|
||||||
if (DBG)
|
|
||||||
log("set ReconnectIntent for type " + mApnType);
|
|
||||||
mReconnectIntent = intent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized PendingIntent getReconnectIntent() {
|
|
||||||
return mReconnectIntent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReady() {
|
public boolean isReady() {
|
||||||
return mDataEnabled.get() && mDependencyMet.get();
|
return mDataEnabled.get() && mDependencyMet.get();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ 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.app.PendingIntent;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkCapabilities;
|
import android.net.LinkCapabilities;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
@@ -35,8 +36,10 @@ import android.os.Parcelable;
|
|||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,6 +71,8 @@ public abstract class DataConnection extends StateMachine {
|
|||||||
protected static int mCount;
|
protected static int mCount;
|
||||||
protected AsyncChannel mAc;
|
protected AsyncChannel mAc;
|
||||||
|
|
||||||
|
private List<ApnContext> mApnList = null;
|
||||||
|
PendingIntent mReconnectIntent = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally for saving connecting parameters.
|
* Used internally for saving connecting parameters.
|
||||||
@@ -250,6 +255,8 @@ public abstract class DataConnection extends StateMachine {
|
|||||||
addState(mDisconnectingState, mDefaultState);
|
addState(mDisconnectingState, mDefaultState);
|
||||||
addState(mDisconnectingErrorCreatingConnection, mDefaultState);
|
addState(mDisconnectingErrorCreatingConnection, mDefaultState);
|
||||||
setInitialState(mInactiveState);
|
setInitialState(mInactiveState);
|
||||||
|
|
||||||
|
mApnList = new ArrayList<ApnContext>();
|
||||||
if (DBG) log("DataConnection constructor X");
|
if (DBG) log("DataConnection constructor X");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,7 +669,41 @@ public abstract class DataConnection extends StateMachine {
|
|||||||
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mRefCount);
|
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mRefCount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DataConnectionAc.REQ_ADD_APNCONTEXT: {
|
||||||
|
ApnContext apnContext = (ApnContext) msg.obj;
|
||||||
|
if (VDBG) log("REQ_ADD_APNCONTEXT apn=" + apnContext.getApnType());
|
||||||
|
if (!mApnList.contains(apnContext)) {
|
||||||
|
mApnList.add(apnContext);
|
||||||
|
}
|
||||||
|
mAc.replyToMessage(msg, DataConnectionAc.RSP_ADD_APNCONTEXT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DataConnectionAc.REQ_REMOVE_APNCONTEXT: {
|
||||||
|
ApnContext apnContext = (ApnContext) msg.obj;
|
||||||
|
if (VDBG) log("REQ_REMOVE_APNCONTEXT apn=" + apnContext.getApnType());
|
||||||
|
mApnList.remove(apnContext);
|
||||||
|
mAc.replyToMessage(msg, DataConnectionAc.RSP_REMOVE_APNCONTEXT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DataConnectionAc.REQ_GET_APNCONTEXT_LIST: {
|
||||||
|
if (VDBG) log("REQ_GET_APNCONTEXT_LIST num in list=" + mApnList.size());
|
||||||
|
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNCONTEXT_LIST,
|
||||||
|
new ArrayList(mApnList));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DataConnectionAc.REQ_SET_RECONNECT_INTENT: {
|
||||||
|
PendingIntent intent = (PendingIntent) msg.obj;
|
||||||
|
if (VDBG) log("REQ_SET_RECONNECT_INTENT");
|
||||||
|
mReconnectIntent = intent;
|
||||||
|
mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_RECONNECT_INTENT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DataConnectionAc.REQ_GET_RECONNECT_INTENT: {
|
||||||
|
if (VDBG) log("REQ_GET_RECONNECT_INTENT");
|
||||||
|
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_RECONNECT_INTENT,
|
||||||
|
mReconnectIntent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case EVENT_CONNECT:
|
case EVENT_CONNECT:
|
||||||
if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
|
if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
|
||||||
ConnectionParams cp = (ConnectionParams) msg.obj;
|
ConnectionParams cp = (ConnectionParams) msg.obj;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.internal.telephony;
|
|||||||
import com.android.internal.util.AsyncChannel;
|
import com.android.internal.util.AsyncChannel;
|
||||||
import com.android.internal.util.Protocol;
|
import com.android.internal.util.Protocol;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.net.LinkCapabilities;
|
import android.net.LinkCapabilities;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.ProxyProperties;
|
import android.net.ProxyProperties;
|
||||||
@@ -26,8 +27,6 @@ import android.os.Message;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AsyncChannel to a DataConnection
|
* AsyncChannel to a DataConnection
|
||||||
@@ -35,7 +34,6 @@ import java.util.List;
|
|||||||
public class DataConnectionAc extends AsyncChannel {
|
public class DataConnectionAc extends AsyncChannel {
|
||||||
private static final boolean DBG = false;
|
private static final boolean DBG = false;
|
||||||
private String mLogTag;
|
private String mLogTag;
|
||||||
private List<ApnContext> mApnList = null;
|
|
||||||
|
|
||||||
public DataConnection dataConnection;
|
public DataConnection dataConnection;
|
||||||
|
|
||||||
@@ -68,6 +66,21 @@ public class DataConnectionAc extends AsyncChannel {
|
|||||||
public static final int REQ_GET_REFCOUNT = BASE + 16;
|
public static final int REQ_GET_REFCOUNT = BASE + 16;
|
||||||
public static final int RSP_GET_REFCOUNT = BASE + 17;
|
public static final int RSP_GET_REFCOUNT = BASE + 17;
|
||||||
|
|
||||||
|
public static final int REQ_ADD_APNCONTEXT = BASE + 18;
|
||||||
|
public static final int RSP_ADD_APNCONTEXT = BASE + 19;
|
||||||
|
|
||||||
|
public static final int REQ_REMOVE_APNCONTEXT = BASE + 20;
|
||||||
|
public static final int RSP_REMOVE_APNCONTEXT = BASE + 21;
|
||||||
|
|
||||||
|
public static final int REQ_GET_APNCONTEXT_LIST = BASE + 22;
|
||||||
|
public static final int RSP_GET_APNCONTEXT_LIST = BASE + 23;
|
||||||
|
|
||||||
|
public static final int REQ_SET_RECONNECT_INTENT = BASE + 24;
|
||||||
|
public static final int RSP_SET_RECONNECT_INTENT = BASE + 25;
|
||||||
|
|
||||||
|
public static final int REQ_GET_RECONNECT_INTENT = BASE + 26;
|
||||||
|
public static final int RSP_GET_RECONNECT_INTENT = BASE + 27;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum used to notify action taken or necessary to be
|
* enum used to notify action taken or necessary to be
|
||||||
* taken after the link property is changed.
|
* taken after the link property is changed.
|
||||||
@@ -91,7 +104,6 @@ public class DataConnectionAc extends AsyncChannel {
|
|||||||
public DataConnectionAc(DataConnection dc, String logTag) {
|
public DataConnectionAc(DataConnection dc, String logTag) {
|
||||||
dataConnection = dc;
|
dataConnection = dc;
|
||||||
mLogTag = logTag;
|
mLogTag = logTag;
|
||||||
mApnList = Collections.synchronizedList(new ArrayList<ApnContext>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -379,32 +391,147 @@ public class DataConnectionAc extends AsyncChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add ApnContext association.
|
* Request to add ApnContext association.
|
||||||
|
* Response RSP_ADD_APNCONTEXT when complete.
|
||||||
|
*/
|
||||||
|
public void reqAddApnContext(ApnContext apnContext) {
|
||||||
|
Message response = sendMessageSynchronously(REQ_ADD_APNCONTEXT, apnContext);
|
||||||
|
if (DBG) log("reqAddApnContext");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ApnContext association synchronoulsy.
|
||||||
*
|
*
|
||||||
* @param ApnContext to associate
|
* @param ApnContext to associate
|
||||||
*/
|
*/
|
||||||
public void addApnContext(ApnContext apnContext) {
|
public void addApnContextSync(ApnContext apnContext) {
|
||||||
if (!mApnList.contains(apnContext)) {
|
Message response = sendMessageSynchronously(REQ_ADD_APNCONTEXT, apnContext);
|
||||||
mApnList.add(apnContext);
|
if ((response != null) && (response.what == RSP_ADD_APNCONTEXT)) {
|
||||||
|
if (DBG) log("addApnContext ok");
|
||||||
|
} else {
|
||||||
|
log("addApnContext error response=" + response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to remove ApnContext association.
|
||||||
|
* Response RSP_REMOVE_APNCONTEXT when complete.
|
||||||
|
*/
|
||||||
|
public void reqRemomveApnContext(ApnContext apnContext) {
|
||||||
|
Message response = sendMessageSynchronously(REQ_REMOVE_APNCONTEXT, apnContext);
|
||||||
|
if (DBG) log("reqRemomveApnContext");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove ApnContext associateion.
|
* Remove ApnContext associateion.
|
||||||
*
|
*
|
||||||
* @param ApnContext to dissociate
|
* @param ApnContext to dissociate
|
||||||
*/
|
*/
|
||||||
public void removeApnContext(ApnContext apnContext) {
|
public void removeApnContextSync(ApnContext apnContext) {
|
||||||
mApnList.remove(apnContext);
|
Message response = sendMessageSynchronously(REQ_REMOVE_APNCONTEXT, apnContext);
|
||||||
|
if ((response != null) && (response.what == RSP_REMOVE_APNCONTEXT)) {
|
||||||
|
if (DBG) log("removeApnContext ok");
|
||||||
|
} else {
|
||||||
|
log("removeApnContext error response=" + response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve collection of ApnContext currently associated with the DataConnectionAc.
|
* Request to retrive ApnContext List associated with DC.
|
||||||
|
* Response RSP_GET_APNCONTEXT_LIST when complete.
|
||||||
|
*/
|
||||||
|
public void reqGetApnList(ApnContext apnContext) {
|
||||||
|
Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
|
||||||
|
if (DBG) log("reqGetApnList");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve Collection of ApnContext from the response message.
|
||||||
|
*
|
||||||
|
* @param Message sent from DC in response to REQ_GET_APNCONTEXT_LIST.
|
||||||
|
* @return Collection of ApnContext
|
||||||
|
*/
|
||||||
|
public Collection<ApnContext> rspApnList(Message response) {
|
||||||
|
Collection<ApnContext> retVal = (Collection<ApnContext>)response.obj;
|
||||||
|
if (retVal == null) retVal = new ArrayList<ApnContext>();
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve collection of ApnContext currently associated with
|
||||||
|
* the DataConnectionA synchronously.
|
||||||
*
|
*
|
||||||
* @return Collection of ApnContext
|
* @return Collection of ApnContext
|
||||||
*/
|
*/
|
||||||
public Collection<ApnContext> getApnList() {
|
public Collection<ApnContext> getApnListSync() {
|
||||||
return mApnList;
|
Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
|
||||||
|
if ((response != null) && (response.what == RSP_GET_APNCONTEXT_LIST)) {
|
||||||
|
if (DBG) log("getApnList ok");
|
||||||
|
return rspApnList(response);
|
||||||
|
} else {
|
||||||
|
log("getApnList error response=" + response);
|
||||||
|
// return dummy list with no entry
|
||||||
|
return new ArrayList<ApnContext>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to set Pending ReconnectIntent to DC.
|
||||||
|
* Response RSP_SET_RECONNECT_INTENT when complete.
|
||||||
|
*/
|
||||||
|
public void reqSetReconnectIntent(PendingIntent intent) {
|
||||||
|
Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
|
||||||
|
if (DBG) log("reqSetReconnectIntent");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set pending reconnect intent to DC synchronously.
|
||||||
|
*
|
||||||
|
* @param PendingIntent to set.
|
||||||
|
*/
|
||||||
|
public void setReconnectIntentSync(PendingIntent intent) {
|
||||||
|
Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
|
||||||
|
if ((response != null) && (response.what == RSP_SET_RECONNECT_INTENT)) {
|
||||||
|
if (DBG) log("setReconnectIntent ok");
|
||||||
|
} else {
|
||||||
|
log("setReconnectIntent error response=" + response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to get Pending ReconnectIntent to DC.
|
||||||
|
* Response RSP_GET_RECONNECT_INTENT when complete.
|
||||||
|
*/
|
||||||
|
public void reqGetReconnectIntent() {
|
||||||
|
Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
|
||||||
|
if (DBG) log("reqGetReconnectIntent");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve reconnect intent from response message from DC.
|
||||||
|
*
|
||||||
|
* @param Message which contains the reconnect intent.
|
||||||
|
* @return PendingIntent from the response.
|
||||||
|
*/
|
||||||
|
public PendingIntent rspReconnectIntent(Message response) {
|
||||||
|
PendingIntent retVal = (PendingIntent) response.obj;
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve reconnect intent currently set in DC synchronously.
|
||||||
|
*
|
||||||
|
* @return PendingIntent reconnect intent current ly set in DC
|
||||||
|
*/
|
||||||
|
public PendingIntent getReconnectIntentSync() {
|
||||||
|
Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
|
||||||
|
if ((response != null) && (response.what == RSP_GET_RECONNECT_INTENT)) {
|
||||||
|
if (DBG) log("getReconnectIntent ok");
|
||||||
|
return rspReconnectIntent(response);
|
||||||
|
} else {
|
||||||
|
log("getReconnectIntent error response=" + response);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log(String s) {
|
private void log(String s) {
|
||||||
|
|||||||
@@ -125,14 +125,20 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
if (DBG) 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);
|
int connectionId = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, -1);
|
||||||
ApnContext apnContext = mApnContexts.get(type);
|
|
||||||
if (apnContext != null) {
|
DataConnectionAc dcac= mDataConnectionAsyncChannels.get(connectionId);
|
||||||
apnContext.setReason(reason);
|
|
||||||
if (apnContext.getState() == State.FAILED) {
|
if (dcac != null) {
|
||||||
apnContext.setState(State.IDLE);
|
for (ApnContext apnContext : dcac.getApnListSync()) {
|
||||||
|
apnContext.setReason(reason);
|
||||||
|
if (apnContext.getState() == State.FAILED) {
|
||||||
|
apnContext.setState(State.IDLE);
|
||||||
|
}
|
||||||
|
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
|
||||||
}
|
}
|
||||||
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
|
// Alram had expired. Clear pending intent recorded on the DataConnection.
|
||||||
|
dcac.setReconnectIntentSync(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,17 +597,25 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupDataOnReadyApns(String reason) {
|
private void setupDataOnReadyApns(String reason) {
|
||||||
|
// Stop reconnect alarms on all data connections pending
|
||||||
|
// retry. Reset ApnContext state to IDLE.
|
||||||
|
for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
|
||||||
|
if (dcac.getReconnectIntentSync() != null) {
|
||||||
|
cancelReconnectAlarm(dcac);
|
||||||
|
if (dcac.dataConnection != null) {
|
||||||
|
dcac.dataConnection.resetRetryCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<ApnContext> apnList = dcac.getApnListSync();
|
||||||
|
for (ApnContext apnContext : apnList) {
|
||||||
|
apnContext.setState(State.IDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only check for default APN state
|
// Only check for default APN state
|
||||||
for (ApnContext apnContext : mApnContexts.values()) {
|
for (ApnContext apnContext : mApnContexts.values()) {
|
||||||
if (apnContext.isReady()) {
|
if (apnContext.isReady()) {
|
||||||
if (apnContext.getState() == State.FAILED) {
|
|
||||||
cleanApnContextBeforeRestart(apnContext);
|
|
||||||
if (apnContext.getDataConnection() != null) {
|
|
||||||
apnContext.getDataConnection().resetRetryCount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Do not start ApnContext in SCANNING state
|
|
||||||
// FAILED state must be reset to IDLE by now
|
|
||||||
if (apnContext.getState() == State.IDLE) {
|
if (apnContext.getState() == State.IDLE) {
|
||||||
apnContext.setReason(reason);
|
apnContext.setReason(reason);
|
||||||
trySetupData(apnContext);
|
trySetupData(apnContext);
|
||||||
@@ -751,53 +765,70 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
if (DBG) {
|
if (DBG) {
|
||||||
log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
|
log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
|
||||||
}
|
}
|
||||||
if (tearDown && cleanApnContextBeforeRestart(apnContext)) {
|
|
||||||
// if the request is tearDown and ApnContext does not hold an active connection,
|
|
||||||
// we're ok to return here.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataConnectionAc dcac = apnContext.getDataConnectionAc();
|
DataConnectionAc dcac = apnContext.getDataConnectionAc();
|
||||||
if (tearDown && (dcac != null)) {
|
if (tearDown) {
|
||||||
if (DBG) log("cleanUpConnection: tearing down");
|
boolean isConnected = (apnContext.getState() != State.IDLE
|
||||||
Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
|
&& apnContext.getState() != State.FAILED);
|
||||||
apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
|
if (!isConnected) {
|
||||||
apnContext.setState(State.DISCONNECTING);
|
// The request is tearDown and but ApnContext is not connected.
|
||||||
|
// If apnContext is not enabled anymore, break the linkage to the DCAC/DC.
|
||||||
|
apnContext.setState(State.IDLE);
|
||||||
|
if (!apnContext.isReady()) {
|
||||||
|
apnContext.setDataConnection(null);
|
||||||
|
apnContext.setDataConnectionAc(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Connection is still there. Try to clean up.
|
||||||
|
if (dcac != null) {
|
||||||
|
if (apnContext.getState() != State.DISCONNECTING) {
|
||||||
|
if (DBG) log("cleanUpConnection: tearing down");
|
||||||
|
Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
|
||||||
|
apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
|
||||||
|
apnContext.setState(State.DISCONNECTING);
|
||||||
|
} else {
|
||||||
|
// apn is connected but no reference to dcac.
|
||||||
|
// Should not be happen, but reset the state in case.
|
||||||
|
apnContext.setState(State.IDLE);
|
||||||
|
mPhone.notifyDataConnection(apnContext.getReason(),
|
||||||
|
apnContext.getApnType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// force clean up the data connection.
|
||||||
if (dcac != null) dcac.resetSync();
|
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());
|
||||||
apnContext.setDataConnection(null);
|
apnContext.setDataConnection(null);
|
||||||
apnContext.setDataConnectionAc(null);
|
apnContext.setDataConnectionAc(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure reconnection alarm is cleaned up if there is no ApnContext
|
||||||
|
// associated to the connection.
|
||||||
|
if (dcac != null) {
|
||||||
|
Collection<ApnContext> apnList = dcac.getApnListSync();
|
||||||
|
if (apnList.isEmpty()) {
|
||||||
|
cancelReconnectAlarm(dcac);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param APNContext to clean
|
* Cancels the alarm associated with DCAC.
|
||||||
* @return true if ApnContext is not connected anymore.
|
*
|
||||||
* false if ApnContext still holds a connection.
|
* @param DataConnectionAc on which the alarm should be stopped.
|
||||||
*/
|
*/
|
||||||
private boolean cleanApnContextBeforeRestart(ApnContext apnContext) {
|
private void cancelReconnectAlarm(DataConnectionAc dcac) {
|
||||||
if (apnContext == null) return true;
|
if (dcac == null) return;
|
||||||
|
|
||||||
// Clear the reconnect alarm, if set.
|
PendingIntent intent = dcac.getReconnectIntentSync();
|
||||||
if (apnContext.getReconnectIntent() != null) {
|
|
||||||
AlarmManager am =
|
|
||||||
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
|
|
||||||
am.cancel(apnContext.getReconnectIntent());
|
|
||||||
apnContext.setReconnectIntent(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
|
if (intent != null) {
|
||||||
if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
|
AlarmManager am =
|
||||||
return true;
|
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
|
||||||
|
am.cancel(intent);
|
||||||
|
dcac.setReconnectIntentSync(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apnContext.getState() == State.FAILED) {
|
|
||||||
apnContext.setState(State.IDLE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -936,17 +967,26 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
configureRetry(dc, apnContext.getApnType());
|
configureRetry(dc, apnContext.getApnType());
|
||||||
}
|
}
|
||||||
apnContext.setDataConnectionAc(dcac);
|
apnContext.setDataConnectionAc(dcac);
|
||||||
apnContext.setApnSetting(apn);
|
|
||||||
apnContext.setDataConnection(dc);
|
apnContext.setDataConnection(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apnContext.setApnSetting(apn);
|
||||||
|
apnContext.setState(State.INITING);
|
||||||
|
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
|
||||||
|
// If reconnect alarm is active on this DataConnection, wait for the alarm being
|
||||||
|
// fired so that we don't disruppt data retry pattern engaged.
|
||||||
|
if (apnContext.getDataConnectionAc().getReconnectIntentSync() != null) {
|
||||||
|
if (DBG) log("setupData: data reconnection pending");
|
||||||
|
apnContext.setState(State.FAILED);
|
||||||
|
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
dc.bringUp(msg, apn);
|
||||||
|
|
||||||
apnContext.setState(State.INITING);
|
|
||||||
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
|
|
||||||
if (DBG) log("setupData: initing!");
|
if (DBG) log("setupData: initing!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1063,13 +1103,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
// no associated DataConnection found. Ignore.
|
// no associated DataConnection found. Ignore.
|
||||||
if (dcac == null) continue;
|
if (dcac == null) continue;
|
||||||
|
|
||||||
Collection<ApnContext> apns = dcac.getApnList();
|
Collection<ApnContext> apns = dcac.getApnListSync();
|
||||||
|
|
||||||
// filter out ApnContext with "Connected" state.
|
// filter out ApnContext with "Connected" state.
|
||||||
ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
|
ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
|
||||||
for (ApnContext apnContext : apns) {
|
for (ApnContext apnContext : apns) {
|
||||||
if ((apnContext != null) &&
|
if (apnContext.getState() == State.CONNECTED) {
|
||||||
(apnContext.getState() == State.CONNECTED)) {
|
|
||||||
connectedApns.add(apnContext);
|
connectedApns.add(apnContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1449,21 +1488,28 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
+ (delay / 1000) + "s");
|
+ (delay / 1000) + "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataConnectionAc dcac = apnContext.getDataConnectionAc();
|
||||||
|
|
||||||
|
if ((dcac == null) || (dcac.dataConnection == null)) {
|
||||||
|
// should not happen, but just in case.
|
||||||
|
loge("null dcac or dc.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AlarmManager am =
|
AlarmManager am =
|
||||||
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
|
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
|
||||||
|
|
||||||
// TODO : Register the receiver only once maybe in baseclass.
|
Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' +
|
||||||
IntentFilter filter = new IntentFilter();
|
dcac.dataConnection.getDataConnectionId());
|
||||||
filter.addAction(INTENT_RECONNECT_ALARM + '.'+apnContext.getApnType());
|
|
||||||
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
|
|
||||||
|
|
||||||
Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
|
|
||||||
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
|
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
|
||||||
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnContext.getApnType());
|
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE,
|
||||||
apnContext.setReconnectIntent(PendingIntent.getBroadcast (
|
dcac.dataConnection.getDataConnectionId());
|
||||||
mPhone.getContext(), 0, intent, 0));
|
|
||||||
|
PendingIntent alarmIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
|
||||||
|
intent, 0);
|
||||||
|
dcac.setReconnectIntentSync(alarmIntent);
|
||||||
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||||
SystemClock.elapsedRealtime() + delay, apnContext.getReconnectIntent());
|
SystemClock.elapsedRealtime() + delay, alarmIntent);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1768,9 +1814,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apnContext.setState(State.IDLE);
|
apnContext.setState(State.IDLE);
|
||||||
apnContext.setApnSetting(null);
|
|
||||||
apnContext.setDataConnection(null);
|
|
||||||
apnContext.setDataConnectionAc(null);
|
|
||||||
|
|
||||||
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
|
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
|
||||||
|
|
||||||
@@ -1779,6 +1822,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
if (!isConnected()) {
|
if (!isConnected()) {
|
||||||
if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
|
if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
|
||||||
// Radio will be turned off. No need to retry data setup
|
// Radio will be turned off. No need to retry data setup
|
||||||
|
apnContext.setApnSetting(null);
|
||||||
|
apnContext.setDataConnection(null);
|
||||||
|
apnContext.setDataConnectionAc(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1790,6 +1836,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
// we're not tying up the RIL command channel.
|
// we're not tying up the RIL command channel.
|
||||||
// This also helps in any external dependency to turn off the context.
|
// This also helps in any external dependency to turn off the context.
|
||||||
startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
|
startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
|
||||||
|
} else {
|
||||||
|
apnContext.setApnSetting(null);
|
||||||
|
apnContext.setDataConnection(null);
|
||||||
|
apnContext.setDataConnectionAc(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1915,6 +1965,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
|||||||
" status=" + status);
|
" status=" + status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// install reconnect intent filter for this data connection.
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(INTENT_RECONNECT_ALARM + '.' + id);
|
||||||
|
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
|
||||||
|
|
||||||
if (DBG) log("createDataConnection() X id=" + id);
|
if (DBG) log("createDataConnection() X id=" + id);
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user