OSDN Git Service

Delay radio reset to wait for data cleanup in CdmaDataConnectionTracker
authorYong Zhang <yzhang@motorola.com>
Mon, 17 Aug 2009 20:18:31 +0000 (15:18 -0500)
committerWink Saville <wink@google.com>
Fri, 21 Aug 2009 01:16:02 +0000 (18:16 -0700)
Issue to be addressed:
In radioRestart() method in CdmaDataConnectionTracker, if the radio is
restarted right after cleaning up connection, it is possible that the
connection setup request triggered by radio-on may happen before the
connection cleanup has been completed so that the connection may not
be set up correctly after the radio is restarted. The end result could
be that the phone lost the data capability.

The patch includes the following changes:
1) Add EVENT_RESTART_RADIO in DataConnectionTracker.
2) In CdmaDataConnectionTracker, method restartRadio(), send a message
   delayed by 20s, the purpose of which is to wait for connection cleanup
   to be completed, then to restart radio.
3) In CdmaDataConnectionTracker, method trySetupData(), don't try to setup
   data if there is pending message to restart radio.

Addtional notes:
   A system property is not used to config the delayed timer because we
   think this fix is to address the unusual error case and waiting for
   long time should not impact user experience much. 12s is the longest
   time to complete the data cleanup as we have seen so far, so we are
   using a 20s timer.

telephony/java/com/android/internal/telephony/DataConnectionTracker.java
telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java

index cc981c9..e187c37 100644 (file)
@@ -99,6 +99,7 @@ public abstract class DataConnectionTracker extends Handler {
     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;
 
     //***** Constants
 
index 8913e81..2b78097 100644 (file)
@@ -76,6 +76,10 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
     /** Currently active CdmaDataConnection */
     private CdmaDataConnection mActiveDataConnection;
 
+    private boolean mPendingRestartRadio = false;
+    private static final int TIME_DELAYED_TO_RESTART_RADIO =
+            SystemProperties.getInt("ro.cdma.timetoradiorestart", 20000);
+
     /**
      * Pool size of CdmaDataConnection objects.
      */
@@ -318,7 +322,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
                 && (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
                         phone.getState() == Phone.State.IDLE )
                 && isDataAllowed()
-                && desiredPowerState) {
+                && desiredPowerState
+                && !mPendingRestartRadio) {
 
             return setupData(reason);
 
@@ -334,7 +339,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
                     " dataEnabled=" + getAnyDataEnabled() +
                     " roaming=" + roaming +
                     " dataOnRoamingEnable=" + getDataOnRoamingEnabled() +
-                    " desiredPowerState=" + desiredPowerState);
+                    " desiredPowerState=" + desiredPowerState +
+                    " PendingRestartRadio=" + mPendingRestartRadio);
             }
             return false;
         }
@@ -445,16 +451,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
     }
 
     protected void restartRadio() {
-        Log.d(LOG_TAG, "************TURN OFF RADIO**************");
-        cleanUpConnection(true, Phone.REASON_CDMA_DATA_DETACHED);
-        phone.mCM.setRadioPower(false, null);
-        /* Note: no need to call setRadioPower(true).  Assuming the desired
-         * radio power state is still ON (as tracked by ServiceStateTracker),
-         * ServiceStateTracker will call setRadioPower when it receives the
-         * RADIO_STATE_CHANGED notification for the power off.  And if the
-         * desired power state has changed in the interim, we don't want to
-         * override it with an unconditional power on.
-         */
+        if (DBG) log("Cleanup connection and wait " +
+                (TIME_DELAYED_TO_RESTART_RADIO / 1000) + "s to restart radio");
+        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+        sendEmptyMessageDelayed(EVENT_RESTART_RADIO, TIME_DELAYED_TO_RESTART_RADIO);
+        mPendingRestartRadio = true;
     }
 
     private Runnable mPollNetStat = new Runnable() {
@@ -719,8 +720,18 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
         }
         setState(State.IDLE);
 
+        // Since the pending request to turn off or restart radio will be processed here,
+        // remove the pending event to restart radio from the message queue.
+        if (mPendingRestartRadio) removeMessages(EVENT_RESTART_RADIO);
+
+        // Process the pending request to turn off radio in ServiceStateTracker first.
+        // If radio is turned off in ServiceStateTracker, ignore the pending event to restart radio.
         CdmaServiceStateTracker ssTracker = mCdmaPhone.mSST;
-        ssTracker.processPendingRadioPowerOffAfterDataOff();
+        if (ssTracker.processPendingRadioPowerOffAfterDataOff()) {
+            mPendingRestartRadio = false;
+        } else {
+            onRestartRadio();
+        }
 
         phone.notifyDataConnection(reason);
         if (retryAfterDisconnected(reason)) {
@@ -816,6 +827,21 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
         }
     }
 
+    private void onRestartRadio() {
+        if (mPendingRestartRadio) {
+            Log.d(LOG_TAG, "************TURN OFF RADIO**************");
+            phone.mCM.setRadioPower(false, null);
+            /* Note: no need to call setRadioPower(true).  Assuming the desired
+             * radio power state is still ON (as tracked by ServiceStateTracker),
+             * ServiceStateTracker will call setRadioPower when it receives the
+             * RADIO_STATE_CHANGED notification for the power off.  And if the
+             * desired power state has changed in the interim, we don't want to
+             * override it with an unconditional power on.
+             */
+            mPendingRestartRadio = false;
+        }
+    }
+
     private void writeEventLogCdmaDataDrop() {
         CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
         int bsid = (loc != null) ? loc.getBaseStationId() : -1;
@@ -928,6 +954,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
                 onCdmaOtaProvision((AsyncResult) msg.obj);
                 break;
 
+            case EVENT_RESTART_RADIO:
+                if (DBG) log("EVENT_RESTART_RADIO");
+                onRestartRadio();
+                break;
+
             default:
                 // handle the message in the super class DataConnectionTracker
                 super.handleMessage(msg);