Merge cherrypicks of [19121301] into tm-release.

Change-Id: Ia76e950a27f3787d6ea1dc4a02c1c9f90a3458bf
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 751d59a..3cba6ac 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -1086,7 +1086,7 @@
     /**
      * Turn on or off radio power with option to specify whether it's for emergency call and specify
      * a reason for setting the power state.
-     * More details check {@link PhoneInternalInterface#setRadioPower(
+     * More details check {@link PhoneInternalInterface#setRadioPowerForReason(
      * boolean, boolean, boolean, boolean, int)}.
      */
     public void setRadioPowerForReason(boolean power, boolean forEmergencyCall,
@@ -1188,10 +1188,10 @@
         if (VDBG) log("received event " + msg.what);
         switch (msg.what) {
             case EVENT_SET_RADIO_POWER_OFF:
-                synchronized(this) {
+                synchronized (this) {
                     if (mPhone.isUsingNewDataStack()) {
-                        mPendingRadioPowerOffAfterDataOff = false;
                         log("Wait for all data networks torn down timed out. Power off now.");
+                        cancelPendingRadioPowerOff();
                         hangupAndPowerOff();
                         return;
                     }
@@ -1491,17 +1491,18 @@
             case EVENT_ALL_DATA_DISCONNECTED:
                 if (mPhone.isUsingNewDataStack()) {
                     log("EVENT_ALL_DATA_DISCONNECTED");
-                    if (mPendingRadioPowerOffAfterDataOff) {
-                        mPendingRadioPowerOffAfterDataOff = false;
-                        removeMessages(EVENT_SET_RADIO_POWER_OFF);
-                        if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now.");
-                        hangupAndPowerOff();
+                    synchronized (this) {
+                        if (mPendingRadioPowerOffAfterDataOff) {
+                            if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now.");
+                            cancelPendingRadioPowerOff();
+                            hangupAndPowerOff();
+                        }
                     }
                     return;
                 }
                 int dds = SubscriptionManager.getDefaultDataSubscriptionId();
                 ProxyController.getInstance().unregisterForAllDataDisconnected(dds, this);
-                synchronized(this) {
+                synchronized (this) {
                     if (mPendingRadioPowerOffAfterDataOff) {
                         if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now.");
                         hangupAndPowerOff();
@@ -3132,12 +3133,12 @@
                     && getRadioPowerOffDelayTimeoutForImsRegistration() > 0) {
                 if (DBG) log("setPowerStateToDesired: delaying power off until IMS dereg.");
                 startDelayRadioOffWaitingForImsDeregTimeout();
-                // Return early here as we do not want to hit the cancel timeout code below.
-                return;
             } else {
                 if (DBG) log("setPowerStateToDesired: powerOffRadioSafely()");
                 powerOffRadioSafely();
             }
+            // Return early here as we do not want to hit the cancel timeout code below.
+            return;
         } else if (mDeviceShuttingDown
                 && (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE)) {
             // !mDesiredPowerState condition above will happen first if the radio is on, so we will
@@ -3147,6 +3148,19 @@
         }
         // Cancel any pending timeouts because the state has been re-evaluated.
         cancelDelayRadioOffWaitingForImsDeregTimeout();
+        cancelPendingRadioPowerOff();
+    }
+
+    /**
+     * Cancel the pending radio power off request that was sent to force the radio to power off
+     * if waiting for all data to disconnect times out.
+     */
+    private synchronized void cancelPendingRadioPowerOff() {
+        if (mPhone.isUsingNewDataStack() && mPendingRadioPowerOffAfterDataOff) {
+            if (DBG) log("cancelPendingRadioPowerOff: cancelling.");
+            mPendingRadioPowerOffAfterDataOff = false;
+            removeMessages(EVENT_SET_RADIO_POWER_OFF);
+        }
     }
 
     /**
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 7d9891d..ff3e8b8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -92,6 +92,7 @@
 
 import com.android.internal.R;
 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
+import com.android.internal.telephony.data.DataNetworkController;
 import com.android.internal.telephony.metrics.ServiceStateStats;
 import com.android.internal.telephony.test.SimulatedCommands;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus;
@@ -380,6 +381,65 @@
     }
 
     @Test
+    public void testSetRadioPowerWaitForAllDataDisconnected() {
+        // Start with radio on
+        sst.setRadioPower(true);
+        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());
+
+        // Ensure data is connected
+        ArgumentCaptor<DataNetworkController.DataNetworkControllerCallback> callback =
+                ArgumentCaptor.forClass(DataNetworkController.DataNetworkControllerCallback.class);
+        verify(mDataNetworkController, times(1)).registerDataNetworkControllerCallback(
+                callback.capture());
+        callback.getValue().onAnyDataNetworkExistingChanged(true);
+
+        // Turn on APM and verify that SST is waiting for all data disconnected
+        sst.setRadioPower(false);
+        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());
+        verify(mDataNetworkController).tearDownAllDataNetworks(
+                eq(3 /* TEAR_DOWN_REASON_AIRPLANE_MODE_ON */));
+        assertTrue(sst.hasMessages(38 /* EVENT_SET_RADIO_POWER_OFF */));
+
+        // Data disconnected, radio should power off now
+        callback.getValue().onAnyDataNetworkExistingChanged(false);
+        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+        assertEquals(TelephonyManager.RADIO_POWER_OFF, mSimulatedCommands.getRadioState());
+    }
+
+    @Test
+    public void testSetRadioPowerCancelWaitForAllDataDisconnected() {
+        // Start with radio on
+        sst.setRadioPower(true);
+        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());
+
+        // Ensure data is connected
+        ArgumentCaptor<DataNetworkController.DataNetworkControllerCallback> callback =
+                ArgumentCaptor.forClass(DataNetworkController.DataNetworkControllerCallback.class);
+        verify(mDataNetworkController, times(1)).registerDataNetworkControllerCallback(
+                callback.capture());
+        callback.getValue().onAnyDataNetworkExistingChanged(true);
+
+        // Turn on APM and verify that SST is waiting for all data disconnected
+        sst.setRadioPower(false);
+        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());
+        verify(mDataNetworkController).tearDownAllDataNetworks(
+                eq(3 /* TEAR_DOWN_REASON_AIRPLANE_MODE_ON */));
+        assertTrue(sst.hasMessages(38 /* EVENT_SET_RADIO_POWER_OFF */));
+
+        // Turn off APM while waiting for data to disconnect
+        sst.setRadioPower(true);
+        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+
+        // Check that radio is on and pending power off messages were cleared
+        assertFalse(sst.hasMessages(38 /* EVENT_SET_RADIO_POWER_OFF */));
+        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());
+    }
+
+    @Test
     @SmallTest
     public void testSetRadioPowerOnForEmergencyCall() {
         // Turn off radio first.