Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01baee6f authored by Ling Ma's avatar Ling Ma
Browse files

Reduce Advance band timer when PCI changes

If the PCI changes during the nr_advanced_bands_secondary_timer_seconds_int timer, we should reduce the timer to regular secondary timer if the remained time is longer.

Fix: 326298347
Test: voice call + data browsing
Change-Id: I8d3642405312e6c7eef0dc8bd3d5a0aeb3f92d64
parent 0db22fad
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -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 = "";

+29 −5
Original line number Diff line number Diff line
@@ -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();

        // 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());

        // secondary timer expired
        moveTimeForward(15 * 1000);
        // Verify the timer has been reduced from 20 - 6s(advance band) to 5s(regular).
        moveTimeForward(5 * 1000);
        processAllMessages();

        assertEquals("connected_rrc_idle", getCurrentState().getName());