Handling data registration and radio technology changing. DO NOT MERGE.
Wink Saville [Fri, 16 Aug 2013 16:34:11 +0000 (09:34 -0700)]
When the DataRegistrationState (aka DRS) or RilDataRadioTechnology changes
aka Radio Access Technology or RAT) while retrying the DataConnection
StateMachine will return the connection as lost immediately. This allows
the connection to be retried with the correct handling of the changed
DRS or RAT quickly, rather than having to wait until retires are exhausted.

Changes:

- Pass RAT in bringUp
- Add the capability to register for DRS/RAT changes with SST
- When DRS/RAT changes in DcRetryState return LOST_CONNECTION to DcTracker

Bug: 9069568
Change-Id: I897168baf17ecaedd0f1df4ef3c2263066d70ece

src/java/com/android/internal/telephony/ServiceStateTracker.java
src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
src/java/com/android/internal/telephony/dataconnection/DataConnection.java
src/java/com/android/internal/telephony/dataconnection/DcAsyncChannel.java
src/java/com/android/internal/telephony/dataconnection/DcTracker.java
src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java

index 8c04d44..3bcfb71 100644 (file)
@@ -25,6 +25,7 @@ import android.os.SystemClock;
 import android.telephony.CellInfo;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
+import android.util.Pair;
 import android.util.TimeUtils;
 
 import java.io.FileDescriptor;
@@ -97,6 +98,7 @@ public abstract class ServiceStateTracker extends Handler {
     protected RegistrantList mRoamingOffRegistrants = new RegistrantList();
     protected RegistrantList mAttachedRegistrants = new RegistrantList();
     protected RegistrantList mDetachedRegistrants = new RegistrantList();
+    protected RegistrantList mDataRegStateOrRatChangedRegistrants = new RegistrantList();
     protected RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
     protected RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
     protected RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
@@ -236,6 +238,20 @@ public abstract class ServiceStateTracker extends Handler {
     }
 
     /**
+     * Notify all mDataConnectionRatChangeRegistrants using an
+     * AsyncResult in msg.obj where AsyncResult#result contains the
+     * new RAT as an Integer Object.
+     */
+    protected void notifyDataRegStateRilRadioTechnologyChanged() {
+        int rat = mSS.getRilDataRadioTechnology();
+        int drs = mSS.getDataRegState();
+        if (DBG) log("notifyDataRegStateRilRadioTechnologyChanged: drs=" + drs + " rat=" + rat);
+        mPhoneBase.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
+                ServiceState.rilRadioTechnologyToString(rat));
+        mDataRegStateOrRatChangedRegistrants.notifyResult(new Pair<Integer, Integer>(drs, rat));
+    }
+
+    /**
      * Some operators have been known to report registration failure
      * data only devices, to fix that use DataRegState.
      */
@@ -468,6 +484,24 @@ public abstract class ServiceStateTracker extends Handler {
     }
 
     /**
+     * Registration for DataConnection RIL Data Radio Technology changing. The
+     * new radio technology will be returned AsyncResult#result as an Integer Object.
+     * The AsyncResult will be in the notification Message#obj.
+     *
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public void registerForDataRegStateOrRatChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        mDataRegStateOrRatChangedRegistrants.add(r);
+        notifyDataRegStateRilRadioTechnologyChanged();
+    }
+    public void unregisterForDataRegStateOrRatChanged(Handler h) {
+        mDataRegStateOrRatChangedRegistrants.remove(h);
+    }
+
+    /**
      * Registration point for transition into network attached.
      * @param h handler to notify
      * @param what what code of message when delivered
index 0cba267..4ca0405 100644 (file)
@@ -437,7 +437,7 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
         }
 
         if ((hasCdmaDataConnectionChanged || hasDataRadioTechnologyChanged)) {
-            log("pollStateDone: call notifyDataConnection");
+            notifyDataRegStateRilRadioTechnologyChanged();
             mPhone.notifyDataConnection(null);
         }
 
index 93fba28..6d94d7c 100644 (file)
@@ -1093,6 +1093,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
         }
 
         if (hasCdmaDataConnectionChanged || hasRilDataRadioTechnologyChanged) {
+            notifyDataRegStateRilRadioTechnologyChanged();
             mPhone.notifyDataConnection(null);
         }
 
index 879c20b..0b3ef26 100644 (file)
@@ -38,9 +38,11 @@ import android.os.Build;
 import android.os.Message;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.text.TextUtils;
 import android.telephony.Rlog;
+import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Pair;
 import android.util.Patterns;
 import android.util.TimeUtils;
 
@@ -104,13 +106,15 @@ public final class DataConnection extends StateMachine {
         ApnContext mApnContext;
         int mInitialMaxRetry;
         int mProfileId;
+        int mRilRat;
         Message mOnCompletedMsg;
 
         ConnectionParams(ApnContext apnContext, int initialMaxRetry, int profileId,
-                Message onCompletedMsg) {
+                int rilRadioTechnology, Message onCompletedMsg) {
             mApnContext = apnContext;
             mInitialMaxRetry = initialMaxRetry;
             mProfileId = profileId;
+            mRilRat = rilRadioTechnology;
             mOnCompletedMsg = onCompletedMsg;
         }
 
@@ -118,6 +122,7 @@ public final class DataConnection extends StateMachine {
         public String toString() {
             return "{mTag=" + mTag + " mApnContext=" + mApnContext
                     + " mInitialMaxRetry=" + mInitialMaxRetry + " mProfileId=" + mProfileId
+                    + " mRat=" + mRilRat
                     + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}";
         }
     }
@@ -158,6 +163,8 @@ public final class DataConnection extends StateMachine {
     private DcFailCause mLastFailCause;
     private static final String NULL_IP = "0.0.0.0";
     private Object mUserData;
+    private int mRilRat = Integer.MAX_VALUE;
+    private int mDataRegState = Integer.MAX_VALUE;
 
     //***** Package visible variables
     int mTag;
@@ -180,8 +187,9 @@ public final class DataConnection extends StateMachine {
     static final int EVENT_TEAR_DOWN_NOW = BASE + 8;
     static final int EVENT_LOST_CONNECTION = BASE + 9;
     static final int EVENT_RETRY_CONNECTION = BASE + 10;
+    static final int EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED = BASE + 11;
 
-    private static final int CMD_TO_STRING_COUNT = EVENT_RETRY_CONNECTION - BASE + 1;
+    private static final int CMD_TO_STRING_COUNT = EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED - BASE + 1;
     private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
     static {
         sCmdToString[EVENT_CONNECT - BASE] = "EVENT_CONNECT";
@@ -196,6 +204,8 @@ public final class DataConnection extends StateMachine {
         sCmdToString[EVENT_TEAR_DOWN_NOW - BASE] = "EVENT_TEAR_DOWN_NOW";
         sCmdToString[EVENT_LOST_CONNECTION - BASE] = "EVENT_LOST_CONNECTION";
         sCmdToString[EVENT_RETRY_CONNECTION - BASE] = "EVENT_RETRY_CONNECTION";
+        sCmdToString[EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED - BASE] =
+                "EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED";
     }
     // Convert cmd to string or null if unknown
     static String cmdToString(int cmd) {
@@ -312,6 +322,8 @@ public final class DataConnection extends StateMachine {
         mId = id;
         mCid = -1;
         mDcRetryAlarmController = new DcRetryAlarmController(mPhone, this);
+        mRilRat = mPhone.getServiceState().getRilDataRadioTechnology();
+        mDataRegState = mPhone.getServiceState().getDataRegState();
 
         addState(mDefaultState);
             addState(mInactiveState, mDefaultState);
@@ -439,7 +451,7 @@ public final class DataConnection extends StateMachine {
         }
 
         mPhone.mCi.setupDataCall(
-                Integer.toString(getRilRadioTechnology()),
+                Integer.toString(cp.mRilRat + 2),
                 Integer.toString(cp.mProfileId),
                 mApnSetting.apn, mApnSetting.user, mApnSetting.password,
                 Integer.toString(authType),
@@ -578,16 +590,6 @@ public final class DataConnection extends StateMachine {
         if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
     }
 
-    private int getRilRadioTechnology() {
-        int rilRadioTechnology;
-        if (mApnSetting.bearer > 0) {
-            rilRadioTechnology = mApnSetting.bearer + 2;
-        } else {
-            rilRadioTechnology = mPhone.getServiceState().getRilDataRadioTechnology() + 2;
-        }
-        return rilRadioTechnology;
-    }
-
     /*
      * **************************************************************************
      * Begin Members and methods owned by DataConnectionTracker but stored
@@ -766,6 +768,10 @@ public final class DataConnection extends StateMachine {
         public void enter() {
             if (DBG) log("DcDefaultState: enter");
 
+            // Register for DRS or RAT change
+            mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(getHandler(),
+                    DataConnection.EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED, null);
+
             // Add ourselves to the list of data connections
             mDcController.addDc(DataConnection.this);
         }
@@ -790,6 +796,9 @@ public final class DataConnection extends StateMachine {
             mLastFailCause = null;
             mUserData = null;
 
+            // Unregister for DRS or RAT change.
+            mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(getHandler());
+
             // Remove ourselves from the DC lists
             mDcController.removeDc(DataConnection.this);
 
@@ -800,7 +809,6 @@ public final class DataConnection extends StateMachine {
         @Override
         public boolean processMessage(Message msg) {
             boolean retVal = HANDLED;
-            AsyncResult ar;
 
             if (VDBG) {
                 log("DcDefault msg=" + getWhatToString(msg.what)
@@ -910,6 +918,18 @@ public final class DataConnection extends StateMachine {
                     }
                     break;
 
+                case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
+                    AsyncResult ar = (AsyncResult)msg.obj;
+                    Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>)ar.result;
+                    mDataRegState = drsRatPair.first;
+                    mRilRat = drsRatPair.second;
+                    if (DBG) {
+                        log("DcDefaultState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
+                                + " drs=" + mDataRegState
+                                + " mRilRat=" + mRilRat);
+                    }
+                    break;
+
                 default:
                     if (DBG) {
                         log("DcDefaultState: shouldn't happen but ignore msg.what="
@@ -1045,16 +1065,30 @@ public final class DataConnection extends StateMachine {
     private class DcRetryingState extends State {
         @Override
         public void enter() {
-            if (DBG) {
-                log("DcRetryingState: enter() mTag=" + mTag
-                    + ", call notifyAllOfDisconnectDcRetrying lostConnection");
-            }
+            if ((mConnectionParams.mRilRat != mRilRat)
+                    || (mDataRegState != ServiceState.STATE_IN_SERVICE)){
+                // RAT has changed or we're not in service so don't even begin retrying.
+                if (DBG) {
+                    String s = "DcRetryingState: enter() not retrying rat changed"
+                        + ", mConnectionParams.mRilRat=" + mConnectionParams.mRilRat
+                        + " != mRilRat:" + mRilRat
+                        + " transitionTo(mInactiveState)";
+                    logAndAddLogRec(s);
+                }
+                mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
+                transitionTo(mInactiveState);
+            } else {
+                if (DBG) {
+                    log("DcRetryingState: enter() mTag=" + mTag
+                        + ", call notifyAllOfDisconnectDcRetrying lostConnection");
+                }
 
-            notifyAllOfDisconnectDcRetrying(Phone.REASON_LOST_DATA_CONNECTION);
+                notifyAllOfDisconnectDcRetrying(Phone.REASON_LOST_DATA_CONNECTION);
 
-            // Remove ourselves from cid mapping
-            mDcController.removeActiveDcByCid(DataConnection.this);
-            mCid = -1;
+                // Remove ourselves from cid mapping
+                mDcController.removeActiveDcByCid(DataConnection.this);
+                mCid = -1;
+            }
         }
 
         @Override
@@ -1062,6 +1096,37 @@ public final class DataConnection extends StateMachine {
             boolean retVal;
 
             switch (msg.what) {
+                case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
+                    AsyncResult ar = (AsyncResult)msg.obj;
+                    Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>)ar.result;
+                    int drs = drsRatPair.first;
+                    int rat = drsRatPair.second;
+                    if ((rat == mRilRat) && (drs == mDataRegState)) {
+                        if (DBG) {
+                            log("DcRetryingState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
+                                    + " strange no change in drs=" + drs
+                                    + " rat=" + rat + " ignoring");
+                        }
+                    } else {
+                        // We've lost the connection and we're retrying but DRS or RAT changed
+                        // so we may never succeed, might as well give up.
+                        mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
+                        deferMessage(msg);
+                        transitionTo(mInactiveState);
+
+                        if (DBG) {
+                            String s = "DcRetryingState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
+                                    + " giving up changed from " + mRilRat
+                                    + " to rat=" + rat
+                                    + " or drs changed from " + mDataRegState + " to drs=" + drs;
+                            logAndAddLogRec(s);
+                        }
+                        mDataRegState = drs;
+                        mRilRat = rat;
+                    }
+                    retVal = HANDLED;
+                    break;
+
                 case EVENT_RETRY_CONNECTION: {
                     if (msg.arg1 == mTag) {
                         mRetryManager.increaseRetryCount();
@@ -1164,7 +1229,9 @@ public final class DataConnection extends StateMachine {
 
             if (DBG) log("DcActivatingState: msg=" + msgToString(msg));
             switch (msg.what) {
+                case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
                 case EVENT_CONNECT:
+                    // Activating can't process until we're done.
                     deferMessage(msg);
                     retVal = HANDLED;
                     break;
@@ -1716,6 +1783,8 @@ public final class DataConnection extends StateMachine {
         pw.flush();
         pw.println(" mLinkProperties=" + mLinkProperties);
         pw.flush();
+        pw.println(" mDataRegState=" + mDataRegState);
+        pw.println(" mRilRat=" + mRilRat);
         pw.println(" mLinkCapabilities=" + mLinkCapabilities);
         pw.println(" mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime));
         pw.println(" mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime));
index 8794eca..d181dec 100644 (file)
@@ -369,13 +369,14 @@ public class DcAsyncChannel extends AsyncChannel {
      *        AsyncResult.result = FailCause and AsyncResult.exception = Exception().
      */
     public void bringUp(ApnContext apnContext, int initialMaxRetry, int profileId,
-            Message onCompletedMsg) {
+            int rilRadioTechnology, Message onCompletedMsg) {
         if (DBG) {
             log("bringUp: apnContext=" + apnContext + " initialMaxRetry=" + initialMaxRetry
                 + " onCompletedMsg=" + onCompletedMsg);
         }
         sendMessage(DataConnection.EVENT_CONNECT,
-                    new ConnectionParams(apnContext, initialMaxRetry, profileId, onCompletedMsg));
+                    new ConnectionParams(apnContext, initialMaxRetry, profileId,
+                            rilRadioTechnology, onCompletedMsg));
     }
 
     /**
index 4df36c4..11a6233 100644 (file)
@@ -638,8 +638,11 @@ public final class DcTracker extends DcTrackerBase {
                 if (DBG) log("trySetupData: make a FAILED ApnContext IDLE so its reusable");
                 apnContext.setState(DctConstants.State.IDLE);
             }
+            int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
             if (apnContext.getState() == DctConstants.State.IDLE) {
-                ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
+
+                ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType(),
+                        radioTech);
                 if (waitingApns.isEmpty()) {
                     notifyNoData(DcFailCause.MISSING_UNKNOWN_APN, apnContext);
                     notifyOffApnsOfAvailability(apnContext.getReason());
@@ -658,7 +661,7 @@ public final class DcTracker extends DcTrackerBase {
                 log("trySetupData: call setupData, waitingApns : "
                         + apnListToString(apnContext.getWaitingApns()));
             }
-            boolean retValue = setupData(apnContext);
+            boolean retValue = setupData(apnContext, radioTech);
             notifyOffApnsOfAvailability(apnContext.getReason());
 
             if (DBG) log("trySetupData: X retValue=" + retValue);
@@ -990,7 +993,7 @@ public final class DcTracker extends DcTrackerBase {
         return null;
     }
 
-    private boolean setupData(ApnContext apnContext) {
+    private boolean setupData(ApnContext apnContext, int radioTech) {
         if (DBG) log("setupData: apnContext=" + apnContext);
         ApnSetting apnSetting;
         DcAsyncChannel dcac;
@@ -1033,7 +1036,7 @@ public final class DcTracker extends DcTrackerBase {
         Message msg = obtainMessage();
         msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;
         msg.obj = apnContext;
-        dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, msg);
+        dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, radioTech, msg);
 
         if (DBG) log("setupData: initing!");
         return true;
@@ -1873,7 +1876,7 @@ public final class DcTracker extends DcTrackerBase {
      * @return waitingApns list to be used to create PDP
      *          error when waitingApns.isEmpty()
      */
-    private ArrayList<ApnSetting> buildWaitingApns(String requestedApnType) {
+    private ArrayList<ApnSetting> buildWaitingApns(String requestedApnType, int radioTech) {
         if (DBG) log("buildWaitingApns: E requestedApnType=" + requestedApnType);
         ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>();
 
@@ -1888,7 +1891,6 @@ public final class DcTracker extends DcTrackerBase {
 
         IccRecords r = mIccRecords.get();
         String operator = (r != null) ? r.getOperatorNumeric() : "";
-        int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
 
         // This is a workaround for a bug (7305641) where we don't failover to other
         // suitable APNs if our preferred APN fails.  On prepaid ATT sims we need to
index acb4972..4f0dc9b 100644 (file)
@@ -1055,6 +1055,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
         }
 
         if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) {
+            notifyDataRegStateRilRadioTechnologyChanged();
             mPhone.notifyDataConnection(null);
         }