Enhancement on ICS data stall polling logic

Put enhancements on data stall polling logic in ICS so that
stall recovery can kick in earler while screen is on.

Bug: 5767897
Change-Id: I4683fc45c0161f4374749c8e5840261c19a48f77
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 65b4e7e..84b0c8b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3642,11 +3642,20 @@
                 "pdp_watchdog_max_pdp_reset_fail_count";
 
         /**
-         * The number of milliseconds to delay when checking for data stalls
+         * The number of milliseconds to delay when checking for data stalls during
+         * non-aggressive detection. (screen is turned off.)
          * @hide
          */
-        public static final String DATA_STALL_ALARM_DELAY_IN_MS =
-                "data_stall_alarm_delay_in_ms";
+        public static final String DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS =
+                "data_stall_alarm_non_aggressive_delay_in_ms";
+
+        /**
+         * The number of milliseconds to delay when checking for data stalls during
+         * aggressive detection. (screen on or suspected data stall)
+         * @hide
+         */
+        public static final String DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS =
+                "data_stall_alarm_aggressive_delay_in_ms";
 
         /**
          * The interval in milliseconds at which to check gprs registration
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 6d9a2c2..2c4fdef 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -212,8 +212,10 @@
     // represents an invalid IP address
     protected static final String NULL_IP = "0.0.0.0";
 
-    // Default for the data stall alarm
-    protected static final int DATA_STALL_ALARM_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6;
+    // Default for the data stall alarm while non-aggressive stall detection
+    protected static final int DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6;
+    // Default for the data stall alarm for aggressive stall detection
+    protected static final int DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60;
     // If attempt is less than this value we're doing first level recovery
     protected static final int DATA_STALL_NO_RECV_POLL_LIMIT = 1;
     // Tag for tracking stale alarms
@@ -323,10 +325,12 @@
                 mIsScreenOn = true;
                 stopNetStatPoll();
                 startNetStatPoll();
+                restartDataStallAlarm();
             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
                 mIsScreenOn = false;
                 stopNetStatPoll();
                 startNetStatPoll();
+                restartDataStallAlarm();
             } else if (action.startsWith(getActionIntentReconnectAlarm())) {
                 log("Reconnect alarm. Previous state was " + mState);
                 onActionIntentReconnectAlarm(intent);
@@ -622,6 +626,7 @@
     protected abstract String getActionIntentDataStallAlarm();
     protected abstract void startNetStatPoll();
     protected abstract void stopNetStatPoll();
+    protected abstract void restartDataStallAlarm();
     protected abstract void restartRadio();
     protected abstract void log(String s);
     protected abstract void loge(String s);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 5889372..9b8d954 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -158,6 +158,9 @@
     }
 
     @Override
+    protected void restartDataStallAlarm() {}
+
+    @Override
     protected void setState(State s) {
         if (DBG) log ("setState: " + s);
         if (mState != s) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 963db2c..3c8ef40 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -97,13 +97,21 @@
     private ContentResolver mResolver;
 
     // Recovery action taken in case of data stall
-    class RecoveryAction {
+    private static class RecoveryAction {
         public static final int GET_DATA_CALL_LIST      = 0;
         public static final int CLEANUP                 = 1;
         public static final int REREGISTER              = 2;
         public static final int RADIO_RESTART           = 3;
         public static final int RADIO_RESTART_WITH_PROP = 4;
+
+        private static boolean isAggressiveRecovery(int value) {
+            return ((value == RecoveryAction.CLEANUP) ||
+                    (value == RecoveryAction.REREGISTER) ||
+                    (value == RecoveryAction.RADIO_RESTART) ||
+                    (value == RecoveryAction.RADIO_RESTART_WITH_PROP));
+        }
     }
+
     public int getRecoveryAction() {
         int action = Settings.System.getInt(mPhone.getContext().getContentResolver(),
                 "radio.data.stall.recovery.action", RecoveryAction.GET_DATA_CALL_LIST);
@@ -131,6 +139,9 @@
     static final String APN_ID = "apn_id";
     private boolean canSetPreferApn = false;
 
+    private static final boolean DATA_STALL_SUSPECTED = true;
+    private static final boolean DATA_STALL_NOT_SUSPECTED = false;
+
     @Override
     protected void onActionIntentReconnectAlarm(Intent intent) {
         if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
@@ -586,7 +597,7 @@
         if (getOverallState() == State.CONNECTED) {
             if (DBG) log("onDataConnectionAttached: start polling notify attached");
             startNetStatPoll();
-            startDataStallAlarm();
+            startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
             notifyDataConnection(Phone.REASON_DATA_ATTACHED);
         } else {
             // update APN availability so that APN can be enabled.
@@ -1271,7 +1282,7 @@
         // setState(State.CONNECTED);
         mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
         startNetStatPoll();
-        startDataStallAlarm();
+        startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
         // reset reconnect timer
         apnContext.getDataConnection().resetRetryCount();
     }
@@ -1437,10 +1448,12 @@
                 Settings.Secure.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
                 NUMBER_SENT_PACKETS_OF_HANG);
 
+        boolean suspectedStall = DATA_STALL_NOT_SUSPECTED;
         if (mSentSinceLastRecv >= hangWatchdogTrigger) {
             if (DBG) {
                 log("onDataStallAlarm: tag=" + tag + " do recovery action=" + getRecoveryAction());
             }
+            suspectedStall = DATA_STALL_SUSPECTED;
             sendMessage(obtainMessage(EVENT_DO_RECOVERY));
         } else {
             if (VDBG) {
@@ -1448,7 +1461,7 @@
                     " pkts since last received, < watchdogTrigger=" + hangWatchdogTrigger);
             }
         }
-        startDataStallAlarm();
+        startDataStallAlarm(suspectedStall);
     }
 
 
@@ -1614,12 +1627,24 @@
 
     }
 
-    private void startDataStallAlarm() {
-        int delayInMs = Settings.Secure.getInt(mResolver,
-                            Settings.Secure.DATA_STALL_ALARM_DELAY_IN_MS,
-                            DATA_STALL_ALARM_DELAY_IN_MS_DEFAULT);
+    private void startDataStallAlarm(boolean suspectedStall) {
+        int nextAction = getRecoveryAction();
+        int delayInMs;
+
+        // If screen is on or data stall is currently suspected, set the alarm
+        // with an aggresive timeout.
+        if (mIsScreenOn || suspectedStall || RecoveryAction.isAggressiveRecovery(nextAction)) {
+            delayInMs = Settings.Secure.getInt(mResolver,
+                                       Settings.Secure.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS,
+                                       DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT);
+        } else {
+            delayInMs = Settings.Secure.getInt(mResolver,
+                                       Settings.Secure.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS,
+                                       DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT);
+        }
+
         mDataStallAlarmTag += 1;
-        if (DBG) {
+        if (VDBG) {
             log("startDataStallAlarm: tag=" + mDataStallAlarmTag +
                     " delay=" + (delayInMs / 1000) + "s");
         }
@@ -1638,7 +1663,7 @@
         AlarmManager am =
             (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
 
-        if (DBG) {
+        if (VDBG) {
             log("stopDataStallAlarm: current tag=" + mDataStallAlarmTag +
                     " mDataStallAlarmIntent=" + mDataStallAlarmIntent);
         }
@@ -1649,6 +1674,20 @@
         }
     }
 
+    @Override
+    protected void restartDataStallAlarm() {
+        // To be called on screen status change.
+        // Do not cancel the alarm if it is set with aggressive timeout.
+        int nextAction = getRecoveryAction();
+
+        if (RecoveryAction.isAggressiveRecovery(nextAction)) {
+            if (DBG) log("data stall recovery action is pending. not resetting the alarm.");
+            return;
+        }
+        stopDataStallAlarm();
+        startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
+    }
+
     private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode,
                               ApnContext apnContext) {
         if (DBG) log( "notifyNoData: type=" + apnContext.getApnType());
@@ -2044,7 +2083,7 @@
         if (isConnected()) {
             if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                 startNetStatPoll();
-                startDataStallAlarm();
+                startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
                 notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
             } else {
                 // clean slate after call end.
@@ -2386,7 +2425,7 @@
                 mIsPsRestricted  = false;
                 if (isConnected()) {
                     startNetStatPoll();
-                    startDataStallAlarm();
+                    startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
                 } else {
                     // TODO: Should all PDN states be checked to fail?
                     if (mState == State.FAILED) {