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

Commit 467e078a authored by fionaxu's avatar fionaxu
Browse files

fix ratratchet when CID change right before RAT change.

There is a timing gap of updating CID and DataRAT when moving between
cell from different RAT (e.g., move from EDGE to GPRS). In that case,
cell ID remains the same when handling rat change, thus ratratchet
will not report lower rate RAT for the purpose of battery-saving.

As its hard to gurantee synchronous cell location change and RAT change,
Frameworks will bypass ratratchet on the next RAT change event
following CID change. This will fix the timeline issue but with some
degree of performance regression when cell location change is not
followed with an immediate RAT change. In that case, we still report
lower rate RAT (only for the next RAT change) and update UI etc.

Bug: 65695609
Test: ServiceStateTrackerTest.java
(cherry picked from commit 277c6456)

Change-Id: Id7954fe5163cdf587eea39227b6f35d325e7a877
(cherry picked from commit f1f44401634c73cca9633ee7012abf734cd9927e)
parent 695d9b5a
Loading
Loading
Loading
Loading
+28 −10
Original line number Diff line number Diff line
@@ -22,11 +22,12 @@ import android.content.IntentFilter;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.Rlog;
import android.util.SparseArray;
import android.util.SparseIntArray;

import java.util.ArrayList;
import java.util.Arrays;

/**
@@ -48,6 +49,8 @@ public class RatRatcheter {
    private final SparseArray<SparseIntArray> mRatFamilyMap = new SparseArray<>();

    private final Phone mPhone;
    private boolean mVoiceRatchetEnabled = true;
    private boolean mDataRatchetEnabled = true;

    /**
     * Updates the ServiceState with a new set of cell bandwidths IFF the new bandwidth list has a
@@ -98,22 +101,37 @@ public class RatRatcheter {
    }

    /** Ratchets RATs and cell bandwidths if oldSS and newSS have the same RAT family. */
    public void ratchet(ServiceState oldSS, ServiceState newSS) {
    public void ratchet(ServiceState oldSS, ServiceState newSS, boolean locationChange) {
        if (isSameRatFamily(oldSS, newSS)) {
            updateBandwidths(oldSS.getCellBandwidths(), newSS);
        }
        // temporarily disable rat ratchet on location change.
        if (locationChange) {
            mVoiceRatchetEnabled = false;
            mDataRatchetEnabled = false;
            return;
        }
        if (mVoiceRatchetEnabled) {
            int newVoiceRat = ratchetRat(oldSS.getRilVoiceRadioTechnology(),
                    newSS.getRilVoiceRadioTechnology());
            newSS.setRilVoiceRadioTechnology(newVoiceRat);
        } else if (oldSS.getRilVoiceRadioTechnology() != newSS.getRilVoiceRadioTechnology()) {
            // resume rat ratchet on following rat change within the same location
            mVoiceRatchetEnabled = true;
        }

        if (mDataRatchetEnabled) {
            int newDataRat = ratchetRat(oldSS.getRilDataRadioTechnology(),
                    newSS.getRilDataRadioTechnology());

        if (isSameRatFamily(oldSS, newSS)) {
            updateBandwidths(oldSS.getCellBandwidths(), newSS);
            newSS.setRilDataRadioTechnology(newDataRat);
        } else if (oldSS.getRilVoiceRadioTechnology() != newSS.getRilVoiceRadioTechnology()) {
            // resume rat ratchet on following rat change within the same location
            mVoiceRatchetEnabled = true;
        }

        boolean newUsingCA = oldSS.isUsingCarrierAggregation()
                || newSS.isUsingCarrierAggregation()
                || newSS.getCellBandwidths().length > 1;

        newSS.setRilVoiceRadioTechnology(newVoiceRat);
        newSS.setRilDataRadioTechnology(newDataRat);
        newSS.setIsUsingCarrierAggregation(newUsingCA);
    }

+4 −3
Original line number Diff line number Diff line
@@ -139,7 +139,8 @@ public class ServiceStateTracker extends Handler {
     * and ignore stale responses.  The value is a count-down of
     * expected responses in this pollingContext.
     */
    private int[] mPollingContext;
    @VisibleForTesting
    public int[] mPollingContext;
    private boolean mDesiredPowerState;

    /**
@@ -2655,8 +2656,8 @@ public class ServiceStateTracker extends Handler {
        // ratchet the new tech up through its rat family but don't drop back down
        // until cell change or device is OOS
        boolean isDataInService = mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
        if (!hasLocationChanged && isDataInService) {
            mRatRatcheter.ratchet(mSS, mNewSS);
        if (isDataInService) {
            mRatRatcheter.ratchet(mSS, mNewSS, hasLocationChanged);
        }

        boolean hasRilVoiceRadioTechnologyChanged =
+130 −0
Original line number Diff line number Diff line
@@ -158,6 +158,10 @@ public class ServiceStateTrackerTest extends TelephonyTest {
        mBundle.putStringArray(
                CarrierConfigManager.KEY_NON_ROAMING_OPERATOR_STRING_ARRAY, new String[]{"123456"});

        mBundle.putStringArray(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES,
                // UMTS < GPRS < EDGE
                new String[]{"3,1,2"});

        mSimulatedCommands.setVoiceRegState(NetworkRegistrationState.REG_STATE_HOME);
        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_HSPA);
        mSimulatedCommands.setDataRegState(NetworkRegistrationState.REG_STATE_HOME);
@@ -1330,4 +1334,130 @@ public class ServiceStateTrackerTest extends TelephonyTest {
            assertTrue(actualNitzSignal.mElapsedRealtime <= SystemClock.elapsedRealtime());
        }
    }

    // Edge and GPRS are grouped under the same family and Edge has higher rate than GPRS.
    // Expect no rat update when move from E to G.
    @Test
    public void testRatRatchet() throws Exception {
        CellIdentityGsm cellIdentity = new CellIdentityGsm(-1, -1, -1, -1, -1, -1);
        NetworkRegistrationState dataResult = new NetworkRegistrationState(
                0, 0, 1, 2, 0, false, null, cellIdentity, 1);
        sst.mPollingContext[0] = 2;
        // update data reg state to be in service
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_GPRS,
                new AsyncResult(sst.mPollingContext, dataResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.STATE_IN_SERVICE, mSST.getCurrentDataConnectionState());

        NetworkRegistrationState voiceResult = new NetworkRegistrationState(
                0, 0, 1, 2, 0, false, null, cellIdentity, false, 0, 0, 0);
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_REGISTRATION,
                new AsyncResult(sst.mPollingContext, voiceResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.RIL_RADIO_TECHNOLOGY_EDGE, sst.mSS.getRilVoiceRadioTechnology());

        // EDGE -> GPRS
        voiceResult = new NetworkRegistrationState(
                0, 0, 1, 1, 0, false, null,
                cellIdentity, false, 0, 0, 0);
        sst.mPollingContext[0] = 2;
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_GPRS,
                new AsyncResult(sst.mPollingContext, dataResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.STATE_IN_SERVICE, mSST.getCurrentDataConnectionState());

        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_REGISTRATION,
                new AsyncResult(sst.mPollingContext, voiceResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.RIL_RADIO_TECHNOLOGY_EDGE, sst.mSS.getRilVoiceRadioTechnology());
    }

    // Edge and GPRS are grouped under the same family and Edge has higher rate than GPRS.
    // Bypass rat rachet when cell id changed. Expect rat update from E to G
    @Test
    public void testRatRatchetWithCellChange() throws Exception {
        CellIdentityGsm cellIdentity = new CellIdentityGsm(-1, -1, -1, -1, -1, -1);
        NetworkRegistrationState dataResult = new NetworkRegistrationState(
                0, 0, 1, 2, 0, false, null, cellIdentity, 1);
        sst.mPollingContext[0] = 2;
        // update data reg state to be in service
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_GPRS,
                new AsyncResult(sst.mPollingContext, dataResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.STATE_IN_SERVICE, mSST.getCurrentDataConnectionState());

        NetworkRegistrationState voiceResult = new NetworkRegistrationState(
                0, 0, 1, 2, 0, false, null, cellIdentity, false, 0, 0, 0);
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_REGISTRATION,
                new AsyncResult(sst.mPollingContext, voiceResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.RIL_RADIO_TECHNOLOGY_EDGE, sst.mSS.getRilVoiceRadioTechnology());

        // RAT: EDGE -> GPRS cell ID: -1 -> 5
        cellIdentity = new CellIdentityGsm(-1, -1, -1, 5, -1, -1);
        voiceResult = new NetworkRegistrationState(
                0, 0, 1, 1, 0, false, null, cellIdentity, false, 0, 0, 0);
        sst.mPollingContext[0] = 2;
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_GPRS,
                new AsyncResult(sst.mPollingContext, dataResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.STATE_IN_SERVICE, mSST.getCurrentDataConnectionState());

        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_REGISTRATION,
                new AsyncResult(sst.mPollingContext, voiceResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.RIL_RADIO_TECHNOLOGY_GPRS, sst.mSS.getRilVoiceRadioTechnology());
    }

    // Edge, GPRS and UMTS are grouped under the same family where Edge > GPRS > UMTS  .
    // Expect no rat update from E to G immediately following cell id change.
    // Expect ratratchet (from G to UMTS) for the following rat update within the cell location.
    @Test
    public void testRatRatchetWithCellChangeBeforeRatChange() throws Exception {
        // cell ID update
        CellIdentityGsm cellIdentity = new CellIdentityGsm(-1, -1, -1, 5, -1, -1);
        NetworkRegistrationState dataResult = new NetworkRegistrationState(
                0, 0, 1, 2, 0, false, null, cellIdentity, 1);
        sst.mPollingContext[0] = 2;
        // update data reg state to be in service
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_GPRS,
                new AsyncResult(sst.mPollingContext, dataResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.STATE_IN_SERVICE, mSST.getCurrentDataConnectionState());

        NetworkRegistrationState voiceResult = new NetworkRegistrationState(
                0, 0, 1, 2, 0, false, null, cellIdentity, false, 0, 0, 0);
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_REGISTRATION,
                new AsyncResult(sst.mPollingContext, voiceResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.RIL_RADIO_TECHNOLOGY_EDGE, sst.mSS.getRilVoiceRadioTechnology());

        // RAT: EDGE -> GPRS, cell ID unchanged. Expect no rat ratchet following cell Id change.
        voiceResult = new NetworkRegistrationState(
                0, 0, 1, 1, 0, false, null, cellIdentity, false, 0, 0, 0);
        sst.mPollingContext[0] = 2;
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_GPRS,
                new AsyncResult(sst.mPollingContext, dataResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.STATE_IN_SERVICE, mSST.getCurrentDataConnectionState());

        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_REGISTRATION,
                new AsyncResult(sst.mPollingContext, voiceResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.RIL_RADIO_TECHNOLOGY_GPRS, sst.mSS.getRilVoiceRadioTechnology());

        // RAT: GPRS -> UMTS
        voiceResult = new NetworkRegistrationState(
                0, 0, 1, 3, 0, false, null, cellIdentity, false, 0, 0, 0);
        sst.mPollingContext[0] = 2;
        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_GPRS,
                new AsyncResult(sst.mPollingContext, dataResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.STATE_IN_SERVICE, mSST.getCurrentDataConnectionState());

        sst.sendMessage(sst.obtainMessage(ServiceStateTracker.EVENT_POLL_STATE_REGISTRATION,
                new AsyncResult(sst.mPollingContext, voiceResult, null)));
        waitForMs(200);
        assertEquals(ServiceState.RIL_RADIO_TECHNOLOGY_GPRS, sst.mSS.getRilVoiceRadioTechnology());
    }
}