From a95bce0b29dd629b512b5e5aec8ece35f12be049 Mon Sep 17 00:00:00 2001 From: Ramesh Sudini Date: Tue, 17 May 2011 09:05:40 -0500 Subject: [PATCH] Map multiple apnType to one DataConnection fixes. With current design the code maps to the same DC, but no indications go out. With this, making it more async in nature that the request goes all the way to DC and all the data indications would be triggered by parallel paths through DCT. Change-Id: I4c6e64912dafe19154d910bbd0441b10ada36cff --- .../internal/telephony/DataConnection.java | 99 +++++++++---------- .../internal/telephony/DataConnectionAc.java | 37 +++++++ .../telephony/DataConnectionTracker.java | 2 +- .../gsm/GsmDataConnectionTracker.java | 63 +++++------- 4 files changed, 112 insertions(+), 89 deletions(-) diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java index dc07ef21cc26d..3636baa03cb03 100644 --- a/telephony/java/com/android/internal/telephony/DataConnection.java +++ b/telephony/java/com/android/internal/telephony/DataConnection.java @@ -205,6 +205,7 @@ public abstract class DataConnection extends StateMachine { protected long lastFailTime; protected FailCause lastFailCause; protected static final String NULL_IP = "0.0.0.0"; + private int mRefCount; Object userData; //***** Abstract methods @@ -413,49 +414,6 @@ public abstract class DataConnection extends StateMachine { return mRetryMgr.configure(configStr); } - 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 @@ -471,6 +429,7 @@ public abstract class DataConnection extends StateMachine { createTime = -1; lastFailTime = -1; lastFailCause = FailCause.NONE; + mRefCount = 0; mLinkProperties = new LinkProperties(); mApn = null; @@ -674,6 +633,11 @@ public abstract class DataConnection extends StateMachine { mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET); transitionTo(mInactiveState); break; + case DataConnectionAc.REQ_GET_REFCOUNT: { + log("REQ_GET_REFCOUNT refCount=" + mRefCount); + mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mRefCount); + break; + } case EVENT_CONNECT: if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected"); @@ -774,9 +738,13 @@ public abstract class DataConnection extends StateMachine { break; case EVENT_CONNECT: - if (DBG) log("DcInactiveState msg.what=EVENT_CONNECT"); ConnectionParams cp = (ConnectionParams) msg.obj; cp.tag = mTag; + if (DBG) { + log("DcInactiveState msg.what=EVENT_CONNECT." + "RefCount = " + + mRefCount); + } + mRefCount = 1; onConnect(cp); transitionTo(mActivatingState); retVal = HANDLED; @@ -804,7 +772,15 @@ public abstract class DataConnection extends StateMachine { switch (msg.what) { case EVENT_DISCONNECT: - if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT"); + if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT" + + mRefCount); + deferMessage(msg); + retVal = HANDLED; + break; + + case EVENT_CONNECT: + if (DBG) log("DcActivatingState deferring msg.what=EVENT_CONNECT refCount = " + + mRefCount); deferMessage(msg); retVal = HANDLED; break; @@ -928,12 +904,28 @@ public abstract class DataConnection extends StateMachine { boolean retVal; switch (msg.what) { + case EVENT_CONNECT: + mRefCount++; + if (DBG) log("DcActiveState msg.what=EVENT_CONNECT RefCount=" + mRefCount); + if (msg.obj != null) { + notifyConnectCompleted((ConnectionParams) msg.obj, FailCause.NONE); + } + retVal = HANDLED; + break; case EVENT_DISCONNECT: - if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT"); - DisconnectParams dp = (DisconnectParams) msg.obj; - dp.tag = mTag; - tearDownData(dp); - transitionTo(mDisconnectingState); + mRefCount--; + if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT RefCount=" + mRefCount); + if (mRefCount == 0) + { + DisconnectParams dp = (DisconnectParams) msg.obj; + dp.tag = mTag; + tearDownData(dp); + transitionTo(mDisconnectingState); + } else { + if (msg.obj != null) { + notifyDisconnectCompleted((DisconnectParams) msg.obj); + } + } retVal = HANDLED; break; @@ -956,6 +948,13 @@ public abstract class DataConnection extends StateMachine { boolean retVal; switch (msg.what) { + case EVENT_CONNECT: + if (DBG) log("DcDisconnectingState msg.what=EVENT_CONNECT. Defer. RefCount = " + + mRefCount); + deferMessage(msg); + retVal = HANDLED; + break; + case EVENT_DEACTIVATE_DONE: if (DBG) log("DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE"); AsyncResult ar = (AsyncResult) msg.obj; diff --git a/telephony/java/com/android/internal/telephony/DataConnectionAc.java b/telephony/java/com/android/internal/telephony/DataConnectionAc.java index 939bab2ca2938..a0d9b0f97ed60 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionAc.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java @@ -59,6 +59,9 @@ public class DataConnectionAc extends AsyncChannel { public static final int REQ_RESET = BASE + 14; public static final int RSP_RESET = BASE + 15; + public static final int REQ_GET_REFCOUNT = BASE + 16; + public static final int RSP_GET_REFCOUNT = BASE + 17; + /** * enum used to notify action taken or necessary to be * taken after the link property is changed. @@ -151,6 +154,40 @@ public class DataConnectionAc extends AsyncChannel { } } + /** + * Request the Reference Count. + * Response {@link #rspRefCount} + */ + public void reqRefCount() { + sendMessage(REQ_GET_REFCOUNT); + if (DBG) log("reqRefCount"); + } + + /** + * Evaluate a RSP_GET_REFCOUNT message and return the refCount. + * + * @param response Message + * @return ref count or -1 if an error + */ + public int rspRefCount(Message response) { + int retVal = response.arg1; + if (DBG) log("rspRefCount=" + retVal); + return retVal; + } + + /** + * @return connection id or -1 if an error + */ + public int getRefCountSync() { + Message response = sendMessageSynchronously(REQ_GET_REFCOUNT); + if ((response != null) && (response.what == RSP_GET_REFCOUNT)) { + return rspRefCount(response); + } else { + log("rspRefCount error response=" + response); + return -1; + } + } + /** * Request the connections ApnSetting. * Response {@link #rspApnSetting} diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index b7ac87975db34..5ddfcd1ad4f75 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -987,7 +987,7 @@ public abstract class DataConnectionTracker extends Handler { resetAllRetryCounts(); onTrySetupData(Phone.REASON_DATA_ENABLED); } else { - onCleanUpConnection(true, APN_DEFAULT_ID, Phone.REASON_DATA_DISABLED); + onCleanUpAllConnections(Phone.REASON_DATA_DISABLED); } } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index a48202fd531ee..024e063c19c99 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -612,28 +612,26 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * * @param apnContext * @param tearDown - * @return refCount + * @return none */ - private int releaseApnContext(ApnContext apnContext, boolean tearDown) { + private void releaseApnContext(ApnContext apnContext, boolean tearDown) { if (apnContext == null) { if (DBG) loge("releaseApnContext: apnContext null should not happen, ignore"); - return -1; + return; } DataConnection dc = apnContext.getDataConnection(); if (dc == null) { if (DBG) loge("releaseApnContext: apnContext dc == null should not happen, ignore"); - return -1; + return; } - int refCount = dc.decAndGetRefCount(); - if (DBG) log("releaseApnContext: dec refCount=" + refCount + " tearDown=" + tearDown); - if (tearDown && (refCount == 0)) { + if (tearDown) { 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; + return; } private void setupDataOnReadyApns(String reason) { @@ -809,12 +807,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { apnContext.setState(State.DISCONNECTING); releaseApnContext(apnContext, tearDown); } else { - // STOPSHIP: Reference counting logic in GDCT still have issue. - // Need to be cleaned up in later patch dcac.resetSync(); - if (apnContext.getDataConnection() != null) { - apnContext.getDataConnection().setRefCount(0); - } apnContext.setState(State.IDLE); mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType()); apnContext.setDataConnection(null); @@ -946,7 +939,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { dc = (GsmDataConnection)apnContext.getDataConnection(); if (dc == null) { - dc = findReadyDataConnection(apn); + + dc = (GsmDataConnection) checkForConnectionForApnContext(apnContext); + + if (dc == null) { + dc = findReadyDataConnection(apn); + } if (dc == null) { if (DBG) log("setupData: No ready GsmDataConnection found!"); @@ -964,16 +962,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return false; } + DataConnectionAc dcac = mDataConnectionAsyncChannels.get(dc.getDataConnectionId()); dc.setProfileId( profileId ); dc.setActiveApnType(apnContext.getApnType()); - int refCount = dc.incAndGetRefCount(); + int refCount = dcac.getRefCountSync(); if (DBG) log("setupData: init dc and apnContext refCount=" + refCount); // configure retry count if no other Apn is using the same connection. - if (refCount == 1) { + if (refCount == 0) { configureRetry(dc, apnContext.getApnType()); } - DataConnectionAc dcac = mDataConnectionAsyncChannels.get(dc.getDataConnectionId()); apnContext.setDataConnectionAc(mDataConnectionAsyncChannels.get(dc.getDataConnectionId())); apnContext.setApnSetting(apn); apnContext.setDataConnection(dc); @@ -1490,23 +1488,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } else { apnContext.setReason(Phone.REASON_DATA_ENABLED); } - DataConnection conn = checkForConnectionForApnContext(apnContext); - if (conn == null) { - if (apnContext.getState() == State.FAILED) { - apnContext.setState(State.IDLE); - } - trySetup = true; - } else { - 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); - } + if (apnContext.getState() == State.FAILED) { + apnContext.setState(State.IDLE); } + trySetup = true; } } apnContext.setEnabled(enabled); @@ -1641,7 +1626,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (DBG) { log(String.format("onDataSetupComplete: success apn=%s", - apnContext.getWaitingApns().get(0).apn) + " refCount=" + dc.getRefCount()); + apnContext.getWaitingApns().get(0).apn)); } ApnSetting apn = apnContext.getApnSetting(); if (apn.proxy != null && apn.proxy.length() != 0) { @@ -1709,10 +1694,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { apnContext.setState(State.FAILED); mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType()); - int refCount = releaseApnContext(apnContext, false); + releaseApnContext(apnContext, false); if (DBG) { - log("onDataSetupComplete: permanent error apn=%s" + apnString + - " refCount=" + refCount); + log("onDataSetupComplete: permanent error apn=%s" + apnString ); } } else { if (DBG) log("onDataSetupComplete: Not all permanent failures, retry"); @@ -1807,7 +1791,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { protected void onCleanUpConnection(boolean tearDown, int apnId, String reason) { if (DBG) log("onCleanUpConnection"); ApnContext apnContext = mApnContexts.get(apnIdToType(apnId)); - cleanUpConnection(tearDown, apnContext); + if (apnContext != null) { + apnContext.setReason(reason); + cleanUpConnection(tearDown, apnContext); + } } protected boolean isConnected() {