aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/java/com/android/internal/telephony/NetworkTypeController.java34
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java34
2 files changed, 62 insertions, 6 deletions
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 68d24a275d..67ca1e1aaf 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -26,6 +26,7 @@ import android.os.AsyncResult;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;
import android.telephony.CarrierConfigManager;
@@ -194,6 +195,7 @@ public class NetworkTypeController extends StateMachine {
private boolean mIsPhysicalChannelConfigOn;
private boolean mIsPrimaryTimerActive;
private boolean mIsSecondaryTimerActive;
+ private long mSecondaryTimerExpireTimestamp;
private boolean mIsTimerResetEnabledForLegacyStateRrcIdle;
/** Carrier config to reset timers when mccmnc changes */
private boolean mIsTimerResetEnabledOnPlmnChanges;
@@ -220,6 +222,7 @@ public class NetworkTypeController extends StateMachine {
// Cached copies below to prevent race conditions
@NonNull private ServiceState mServiceState;
+ /** Used to track link status to be DORMANT or ACTIVE */
@Nullable private List<PhysicalChannelConfig> mPhysicalChannelConfigs;
// Ratchet physical channel config fields to prevent 5G/5G+ flickering
@@ -666,6 +669,7 @@ public class NetworkTypeController extends StateMachine {
case EVENT_SECONDARY_TIMER_EXPIRED:
if (DBG) log("Secondary timer expired for state: " + mSecondaryTimerState);
mIsSecondaryTimerActive = false;
+ mSecondaryTimerExpireTimestamp = 0;
mSecondaryTimerState = "";
updateTimers();
mLastShownNrDueToAdvancedBand = false;
@@ -1251,6 +1255,8 @@ public class NetworkTypeController extends StateMachine {
private void updatePhysicalChannelConfigs(List<PhysicalChannelConfig> physicalChannelConfigs) {
boolean isPccListEmpty = physicalChannelConfigs == null || physicalChannelConfigs.isEmpty();
if (isPccListEmpty && isUsingPhysicalChannelConfigForRrcDetection()) {
+ // Clear mPrimaryCellChangedWhileIdle to allow later potential one-off PCI change.
+ // Update link status to be DORMANT, but keep ratcheted bands.
log("Physical channel configs updated: not updating PCC fields for empty PCC list "
+ "indicating RRC idle.");
mPrimaryCellChangedWhileIdle = false;
@@ -1310,6 +1316,7 @@ public class NetworkTypeController extends StateMachine {
+ mLastAnchorNrCellId + " -> " + anchorNrCellId);
mPrimaryCellChangedWhileIdle = true;
mLastAnchorNrCellId = anchorNrCellId;
+ reduceSecondaryTimerIfNeeded();
return;
}
if (mRatchetPccFieldsForSameAnchorNrCell) {
@@ -1330,6 +1337,27 @@ public class NetworkTypeController extends StateMachine {
}
}
+ /**
+ * Called when PCI change, specifically during idle state.
+ */
+ private void reduceSecondaryTimerIfNeeded() {
+ if (!mIsSecondaryTimerActive || mNrAdvancedBandsSecondaryTimer <= 0) return;
+ // Secondary timer is active, so we must have a valid secondary rule right now.
+ OverrideTimerRule secondaryRule = mOverrideTimerRules.get(mPrimaryTimerState);
+ if (secondaryRule != null) {
+ int secondaryDuration = secondaryRule.getSecondaryTimer(mSecondaryTimerState);
+ long durationMillis = secondaryDuration * 1000L;
+ if ((mSecondaryTimerExpireTimestamp - SystemClock.uptimeMillis()) > durationMillis) {
+ if (DBG) log("Due to PCI change, reduce the secondary timer to " + durationMillis);
+ removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
+ sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, mSecondaryTimerState,
+ durationMillis);
+ }
+ } else {
+ loge("!! Secondary timer is active, but found no rule for " + mPrimaryTimerState);
+ }
+ }
+
private void transitionWithTimerTo(IState destState) {
String destName = destState.getName();
if (mIsPrimaryTimerActive) {
@@ -1369,7 +1397,9 @@ public class NetworkTypeController extends StateMachine {
mSecondaryTimerState = currentName;
mPreviousState = currentName;
mIsSecondaryTimerActive = true;
- sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, duration * 1000L);
+ long durationMillis = duration * 1000L;
+ mSecondaryTimerExpireTimestamp = SystemClock.uptimeMillis() + durationMillis;
+ sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, durationMillis);
}
mIsPrimaryTimerActive = false;
transitionTo(getCurrentState());
@@ -1434,6 +1464,7 @@ public class NetworkTypeController extends StateMachine {
}
removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
mIsSecondaryTimerActive = false;
+ mSecondaryTimerExpireTimestamp = 0;
mSecondaryTimerState = "";
transitionToCurrentState();
return;
@@ -1464,6 +1495,7 @@ public class NetworkTypeController extends StateMachine {
removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
mIsPrimaryTimerActive = false;
mIsSecondaryTimerActive = false;
+ mSecondaryTimerExpireTimestamp = 0;
mPrimaryTimerState = "";
mSecondaryTimerState = "";
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index b8545350b7..e08abd98c9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -1550,7 +1550,7 @@ public class NetworkTypeControllerTest extends TelephonyTest {
mNetworkTypeController.getOverrideNetworkType());
assertTrue(mNetworkTypeController.areAnyTimersActive());
- // switch to connected_rrc_idle before primary timer expires
+ // empty PCC, switch to connected_rrc_idle before primary timer expires
physicalChannelConfigs.clear();
mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
new AsyncResult(null, physicalChannelConfigs, null));
@@ -1571,16 +1571,40 @@ public class NetworkTypeControllerTest extends TelephonyTest {
mNetworkTypeController.getOverrideNetworkType());
assertTrue(mNetworkTypeController.areAnyTimersActive());
- // 5 seconds passed during connected_mmwave -> connected_rrc_idle secondary timer
- moveTimeForward(5 * 1000);
+ // Verify secondary timer is still active after 6 seconds passed during
+ // connected_mmwave -> connected_rrc_idle secondary timer, should still keep the primary
+ // state icon.
+ moveTimeForward((5 + 1) * 1000);
processAllMessages();
assertEquals("connected_rrc_idle", getCurrentState().getName());
assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
mNetworkTypeController.getOverrideNetworkType());
assertTrue(mNetworkTypeController.areAnyTimersActive());
+ }
+
+ @Test
+ public void testSecondaryTimerAdvanceBandReduceOnPciChange() throws Exception {
+ // The advance band secondary timer has been running for 6 seconds, 20 - 6 seconds are left.
+ testSecondaryTimerAdvanceBand();
+
+ // PCI changed from 1 to 2 for the first while the timer is running.
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
+ new AsyncResult(null, List.of(
+ new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(2)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build()), null));
+ processAllMessages();
- // secondary timer expired
- moveTimeForward(15 * 1000);
+ // Verify the first PCI change is exempted from triggering state change.
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // Verify the timer has been reduced from 20 - 6s(advance band) to 5s(regular).
+ moveTimeForward(5 * 1000);
processAllMessages();
assertEquals("connected_rrc_idle", getCurrentState().getName());