aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Chin <sarahchin@google.com>2022-07-01 23:15:33 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-07-01 23:15:33 +0000
commit34d8acbfb0b7a3765b0bda11e05028ee666a4cda (patch)
treeeef029cd35865af2f596e4ad49ceee42699bc2c7
parentfec1b69a236e5c5850b9a57d96ec755c7800f8a9 (diff)
parent9b9286746ec909e7507600c5bb24e495ae88ce74 (diff)
downloadtelephony-34d8acbfb0b7a3765b0bda11e05028ee666a4cda.tar.gz
Fix APM race conditions in ServiceStateTracker am: 9b9286746e
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/19121301 Change-Id: I52335ca8233715fa3f7dec5a67991b4bd2a0276d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rwxr-xr-xsrc/java/com/android/internal/telephony/ServiceStateTracker.java36
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java60
2 files changed, 85 insertions, 11 deletions
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 751d59a623..3cba6acb77 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -1086,7 +1086,7 @@ public class ServiceStateTracker extends Handler {
/**
* 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 @@ public class ServiceStateTracker extends Handler {
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 @@ public class ServiceStateTracker extends Handler {
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 @@ public class ServiceStateTracker extends Handler {
&& 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 @@ public class ServiceStateTracker extends Handler {
}
// 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 7d9891d374..ff3e8b8990 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 androidx.test.filters.FlakyTest;
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 @@ public class ServiceStateTrackerTest extends TelephonyTest {
}
@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.