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

Commit c88d8b6e authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Implement Radio HAL Fallback Compatibility."

parents ce9d5ade 788cd94e
Loading
Loading
Loading
Loading
+88 −6
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.android.internal.telephony.RILConstants.*;
import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.radio.V1_0.Carrier;
@@ -132,6 +133,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
@@ -266,6 +268,13 @@ public class RIL extends BaseCommands implements CommandsInterface {
    final RadioProxyDeathRecipient mRadioProxyDeathRecipient;
    final RilHandler mRilHandler;

    // Thread-safe HashMap to map from RIL_REQUEST_XXX constant to HalVersion.
    // This is for Radio HAL Fallback Compatibility feature. When a RIL request
    // is received, the HAL method from the mapping HalVersion here (if present),
    // instead of the latest HalVersion, will be invoked.
    private ConcurrentHashMap<Integer, HalVersion> mCompatOverrides =
            new ConcurrentHashMap<>();

    //***** Events
    static final int EVENT_WAKE_LOCK_TIMEOUT    = 2;
    static final int EVENT_ACK_WAKE_LOCK_TIMEOUT    = 4;
@@ -432,6 +441,25 @@ public class RIL extends BaseCommands implements CommandsInterface {
        getOemHookProxy(null);
    }

    /** Set a radio HAL fallback compatibility override. */
    @VisibleForTesting
    public void setCompatVersion(int rilRequest, @NonNull HalVersion halVersion) {
        HalVersion oldVersion = getCompatVersion(rilRequest);
        // Do not allow to set same or greater verions
        if (oldVersion != null && halVersion.greaterOrEqual(oldVersion)) {
            riljLoge("setCompatVersion with equal or greater one, ignored, halVerion=" + halVersion
                    + ", oldVerion=" + oldVersion);
            return;
        }
        mCompatOverrides.put(rilRequest, halVersion);
    }

    /** Get a radio HAL fallback compatibility override, or null if not exist. */
    @VisibleForTesting
    public @Nullable HalVersion getCompatVersion(int rilRequest) {
        return mCompatOverrides.getOrDefault(rilRequest, null);
    }

    /** Returns a {@link IRadio} instance or null if the service is not available. */
    @VisibleForTesting
    public synchronized IRadio getRadioProxy(Message result) {
@@ -695,6 +723,13 @@ public class RIL extends BaseCommands implements CommandsInterface {
        return rr;
    }

    private RILRequest obtainRequest(int request, Message result, WorkSource workSource,
            Object... args) {
        RILRequest rr = RILRequest.obtain(request, result, workSource, args);
        addRequest(rr);
        return rr;
    }

    private void handleRadioProxyExceptionForRR(RILRequest rr, String caller, Exception e) {
        riljLoge(caller + ": " + e);
        resetProxyAndRequestList();
@@ -1452,7 +1487,13 @@ public class RIL extends BaseCommands implements CommandsInterface {

            if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
            HalVersion overrideHalVersion = getCompatVersion(RIL_REQUEST_VOICE_REGISTRATION_STATE);
            if (RILJ_LOGD) {
                riljLog("getVoiceRegistrationState: overrideHalVersion=" + overrideHalVersion);
            }
            if ((overrideHalVersion == null
                        || overrideHalVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5))
                    && mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
                final android.hardware.radio.V1_5.IRadio radioProxy15 =
                        (android.hardware.radio.V1_5.IRadio) radioProxy;
                try {
@@ -1479,8 +1520,13 @@ public class RIL extends BaseCommands implements CommandsInterface {

            if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));


            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
            HalVersion overrideHalVersion = getCompatVersion(RIL_REQUEST_DATA_REGISTRATION_STATE);
            if (RILJ_LOGD) {
                riljLog("getDataRegistrationState: overrideHalVersion=" + overrideHalVersion);
            }
            if ((overrideHalVersion == null
                        || overrideHalVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5))
                    && mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
                final android.hardware.radio.V1_5.IRadio radioProxy15 =
                        (android.hardware.radio.V1_5.IRadio) radioProxy;
                try {
@@ -2437,11 +2483,25 @@ public class RIL extends BaseCommands implements CommandsInterface {
        return rasInHalFormat;
    }

    /**
     * Radio HAL fallback compatibility feature (b/151106728) assumes that the input parameter
     * networkScanRequest is immutable (read-only) here. Once the caller invokes the method, the
     * parameter networkScanRequest should not be modified. This helps us keep a consistent and
     * simple data model that avoid copying it in the scan result.
     */
    @Override
    public void startNetworkScan(NetworkScanRequest nsr, Message result) {
    public void startNetworkScan(NetworkScanRequest networkScanRequest, Message result) {
        final NetworkScanRequest nsr = networkScanRequest;
        IRadio radioProxy = getRadioProxy(result);
        if (radioProxy != null) {
            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {

            HalVersion overrideHalVersion = getCompatVersion(RIL_REQUEST_START_NETWORK_SCAN);
            if (RILJ_LOGD) {
                riljLog("startNetworkScan: overrideHalVersion=" + overrideHalVersion);
            }
            if ((overrideHalVersion == null
                        || overrideHalVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5))
                    && mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
                android.hardware.radio.V1_5.NetworkScanRequest request =
                        new android.hardware.radio.V1_5.NetworkScanRequest();
                request.type = nsr.getScanType();
@@ -2463,7 +2523,7 @@ public class RIL extends BaseCommands implements CommandsInterface {

                request.mccMncs.addAll(nsr.getPlmns());
                RILRequest rr = obtainRequest(RIL_REQUEST_START_NETWORK_SCAN, result,
                        mRILDefaultWorkSource);
                        mRILDefaultWorkSource, nsr);

                if (RILJ_LOGD) {
                    riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -5508,6 +5568,28 @@ public class RIL extends BaseCommands implements CommandsInterface {
            }
            rr.onError(responseInfo.error, ret);
        }
        processResponseCleanUp(rr, responseInfo, ret);
    }

    /**
     * This is a helper function to be called at the end of all RadioResponse callbacks for
     * radio HAL fallback cases. It takes care of logging, decrementing wakelock if needed, and
     * releases the request from memory pool. Unlike processResponseDone, it will not send
     * error response to caller.
     * @param rr RILRequest for which response callback was called
     * @param responseInfo RadioResponseInfo received in the callback
     * @param ret object to be returned to request sender
     */
    @VisibleForTesting
    public void processResponseFallback(RILRequest rr, RadioResponseInfo responseInfo, Object ret) {
        if (responseInfo.error == REQUEST_NOT_SUPPORTED && RILJ_LOGD) {
            riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)
                    + " request not supported, falling back");
        }
        processResponseCleanUp(rr, responseInfo, ret);
    }

    private void processResponseCleanUp(RILRequest rr, RadioResponseInfo responseInfo, Object ret) {
        mMetrics.writeOnRilSolicitedResponse(mPhoneId, rr.mSerial, responseInfo.error,
                rr.mRequest, ret);
        if (rr != null) {
+22 −0
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ public class RILRequest {
    String mClientId;
    // time in ms when RIL request was made
    long mStartTimeMs;
    /** Argument list for radio HAL fallback method call */
    Object[] mArguments;

    public int getSerial() {
        return mSerial;
@@ -133,6 +135,25 @@ public class RILRequest {
        return rr;
    }

    /**
     * Retrieves a new RILRequest instance from the pool and sets the clientId
     *
     * @param request RIL_REQUEST_*
     * @param result sent when operation completes
     * @param workSource WorkSource to track the client
     * @param args The list of parameters used to call the fallback HAL method
     * @return a RILRequest instance from the pool.
     */
    // @VisibleForTesting
    public static RILRequest obtain(int request, Message result, WorkSource workSource,
            Object... args) {
        RILRequest rr = obtain(request, result, workSource);

        rr.mArguments = args;

        return rr;
    }

    /**
     * Generate a String client ID from the WorkSource.
     */
@@ -175,6 +196,7 @@ public class RILRequest {
                                + serialString());
                    }
                }
                mArguments = null;
            }
        }
    }
+71 −25
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.telephony.CarrierRestrictionRules;
import android.telephony.CellInfo;
import android.telephony.ModemActivityInfo;
import android.telephony.NeighboringCellInfo;
import android.telephony.NetworkScanRequest;
import android.telephony.PhoneNumberUtils;
import android.telephony.RadioAccessFamily;
import android.telephony.SignalStrength;
@@ -357,14 +358,27 @@ public class RadioResponse extends IRadioResponse.Stub {
    public void getVoiceRegistrationStateResponse_1_5(RadioResponseInfo responseInfo,
            android.hardware.radio.V1_5.RegStateResult voiceRegResponse) {
        RILRequest rr = mRil.processResponse(responseInfo);
        if (rr == null) {
            return;
        }

        if (rr != null) {
            if (responseInfo.error == RadioError.NONE) {
        if (responseInfo.error == RadioError.REQUEST_NOT_SUPPORTED) {
            // Move the data needed for fallback call from rr which will be released soon
            final int request = rr.getRequest();
            final Message result = rr.getResult();

            mRil.mRilHandler.post(() -> {
                mRil.setCompatVersion(request, RIL.RADIO_HAL_VERSION_1_4);
                mRil.getVoiceRegistrationState(result);
            });

            mRil.processResponseFallback(rr, responseInfo, voiceRegResponse);
            return;
        } else if (responseInfo.error == RadioError.NONE) {
            sendMessageResponse(rr.mResult, voiceRegResponse);
        }
        mRil.processResponseDone(rr, responseInfo, voiceRegResponse);
    }
    }

    /**
     * @param responseInfo Response info struct containing response type, serial no. and error
@@ -425,14 +439,27 @@ public class RadioResponse extends IRadioResponse.Stub {
    public void getDataRegistrationStateResponse_1_5(RadioResponseInfo responseInfo,
            android.hardware.radio.V1_5.RegStateResult dataRegResponse) {
        RILRequest rr = mRil.processResponse(responseInfo);
        if (rr == null) {
            return;
        }

        if (rr != null) {
            if (responseInfo.error == RadioError.NONE) {
        if (responseInfo.error == RadioError.REQUEST_NOT_SUPPORTED) {
            // Move the data needed for fallback call from rr which will be released soon
            final int request = rr.getRequest();
            final Message result = rr.getResult();

            mRil.mRilHandler.post(() -> {
                mRil.setCompatVersion(request, RIL.RADIO_HAL_VERSION_1_4);
                mRil.getDataRegistrationState(result);
            });

            mRil.processResponseFallback(rr, responseInfo, dataRegResponse);
            return;
        } else if (responseInfo.error == RadioError.NONE) {
            sendMessageResponse(rr.mResult, dataRegResponse);
        }
        mRil.processResponseDone(rr, responseInfo, dataRegResponse);
    }
    }

    /**
     * @param responseInfo Response info struct containing response type, serial no. and error
@@ -684,26 +711,26 @@ public class RadioResponse extends IRadioResponse.Stub {
     * @param responseInfo Response info struct containing response type, serial no. and error
     */
    public void startNetworkScanResponse(RadioResponseInfo responseInfo) {
        responseScanStatus(responseInfo);
        responseScanStatus(responseInfo, null /*fallbackHalVersion*/);
    }

    /**
     * The same method as startNetworkScanResponse, except disallowing error codes
     * OPERATION_NOT_ALLOWED and REQUEST_NOT_SUPPORTED.
     * OPERATION_NOT_ALLOWED.
     *
     * @param responseInfo Response info struct containing response type, serial no. and error
     */
    public void startNetworkScanResponse_1_4(RadioResponseInfo responseInfo) {
        responseScanStatus(responseInfo);
        responseScanStatus(responseInfo, null /*fallbackHalVersion*/);
    }

    /**
     * The same method as startNetworkScanResponse_1_5.
     * The same method as startNetworkScanResponse_1_4.
     *
     * @param responseInfo Response info struct containing response type, serial no. and error
     */
    public void startNetworkScanResponse_1_5(RadioResponseInfo responseInfo) {
        responseScanStatus(responseInfo);
        responseScanStatus(responseInfo, RIL.RADIO_HAL_VERSION_1_4);
    }

    /**
@@ -711,7 +738,7 @@ public class RadioResponse extends IRadioResponse.Stub {
     * @param responseInfo Response info struct containing response type, serial no. and error
     */
    public void stopNetworkScanResponse(RadioResponseInfo responseInfo) {
        responseScanStatus(responseInfo);
        responseScanStatus(responseInfo, null /*fallbackHalVersion*/);
    }

    /**
@@ -2207,10 +2234,30 @@ public class RadioResponse extends IRadioResponse.Stub {
        }
    }

    private void responseScanStatus(RadioResponseInfo responseInfo) {
    private void responseScanStatus(RadioResponseInfo responseInfo, HalVersion fallbackHalVersion) {
        RILRequest rr = mRil.processResponse(responseInfo);
        if (rr == null) {
            return;
        }

        final boolean needFallback = responseInfo.error == RadioError.REQUEST_NOT_SUPPORTED
                && fallbackHalVersion != null && rr.mArguments != null && rr.mArguments.length > 0
                && rr.mArguments[0] instanceof NetworkScanRequest;
        if (needFallback) {
            // Move the data needed for fallback call from rr which will be released soon
            final int request = rr.getRequest();
            final Message result = rr.getResult();
            final NetworkScanRequest scanRequest = (NetworkScanRequest) rr.mArguments[0];

            mRil.mRilHandler.post(() -> {
                mRil.setCompatVersion(request, RIL.RADIO_HAL_VERSION_1_4);
                mRil.startNetworkScan(scanRequest, result);
            });

            mRil.processResponseFallback(rr, responseInfo, null);
            return;
        }

        if (rr != null) {
        NetworkScanResult nsr = null;
        if (responseInfo.error == RadioError.NONE) {
            nsr = new NetworkScanResult(
@@ -2219,7 +2266,6 @@ public class RadioResponse extends IRadioResponse.Stub {
        }
        mRil.processResponseDone(rr, responseInfo, nsr);
    }
    }

    private void responseDataCallList(RadioResponseInfo responseInfo,
                                      List<? extends Object> dataCallResultList) {
+174 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SIM_AUTHEN
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SIM_CLOSE_CHANNEL;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SIM_OPEN_CHANNEL;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_START_LCE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_START_NETWORK_SCAN;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STOP_LCE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE;
@@ -83,6 +84,7 @@ import static com.android.internal.telephony.RILConstants.RIL_REQUEST_WRITE_SMS_
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -141,6 +143,8 @@ import android.telephony.CellSignalStrengthLte;
import android.telephony.CellSignalStrengthNr;
import android.telephony.CellSignalStrengthTdscdma;
import android.telephony.CellSignalStrengthWcdma;
import android.telephony.NetworkScanRequest;
import android.telephony.RadioAccessSpecifier;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SmsManager;
@@ -168,6 +172,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -543,6 +548,108 @@ public class RILTest extends TelephonyTest {
                RIL_REQUEST_VOICE_REGISTRATION_STATE);
    }

    private RadioAccessSpecifier getRadioAccessSpecifier(CellInfo cellInfo) {
        RadioAccessSpecifier ras;
        if (cellInfo instanceof CellInfoLte) {
            int ranLte = AccessNetworkConstants.AccessNetworkType.EUTRAN;
            int[] lteChannels = {((CellInfoLte) cellInfo).getCellIdentity().getEarfcn()};
            ras = new RadioAccessSpecifier(ranLte, null /* bands */, lteChannels);
        } else if (cellInfo instanceof CellInfoWcdma) {
            int ranLte = AccessNetworkConstants.AccessNetworkType.UTRAN;
            int[] wcdmaChannels = {((CellInfoWcdma) cellInfo).getCellIdentity().getUarfcn()};
            ras = new RadioAccessSpecifier(ranLte, null /* bands */, wcdmaChannels);
        } else if (cellInfo instanceof CellInfoGsm) {
            int ranGsm = AccessNetworkConstants.AccessNetworkType.GERAN;
            int[] gsmChannels = {((CellInfoGsm) cellInfo).getCellIdentity().getArfcn()};
            ras = new RadioAccessSpecifier(ranGsm, null /* bands */, gsmChannels);
        } else {
            ras = null;
        }
        return ras;
    }

    private NetworkScanRequest getNetworkScanRequestForTesting() {
        // Construct a NetworkScanRequest for testing
        List<CellInfo> allCellInfo = mTelephonyManager.getAllCellInfo();
        List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>();
        for (int i = 0; i < allCellInfo.size(); i++) {
            RadioAccessSpecifier ras = getRadioAccessSpecifier(allCellInfo.get(i));
            if (ras != null) {
                radioAccessSpecifier.add(ras);
            }
        }
        if (radioAccessSpecifier.size() == 0) {
            RadioAccessSpecifier gsm = new RadioAccessSpecifier(
                    AccessNetworkConstants.AccessNetworkType.GERAN,
                    null /* bands */,
                    null /* channels */);
            radioAccessSpecifier.add(gsm);
        }
        RadioAccessSpecifier[] radioAccessSpecifierArray =
                new RadioAccessSpecifier[radioAccessSpecifier.size()];
        return new NetworkScanRequest(
                NetworkScanRequest.SCAN_TYPE_ONE_SHOT /* scan type */,
                radioAccessSpecifier.toArray(radioAccessSpecifierArray),
                5 /* search periodicity */,
                60 /* max search time */,
                true /*enable incremental results*/,
                5 /* incremental results periodicity */,
                null /* List of PLMN ids (MCC-MNC) */);
    }

    @FlakyTest
    @Test
    public void testStartNetworkScanWithUnsupportedResponse() throws Exception {
        // Use Radio HAL v1.5
        try {
            replaceInstance(RIL.class, "mRadioVersion", mRILUnderTest, mRadioVersionV15);
        } catch (Exception e) {
        }
        NetworkScanRequest nsr = getNetworkScanRequestForTesting();
        mRILUnderTest.startNetworkScan(nsr, obtainMessage());

        // Verify the v1.5 HAL methed is called firstly
        verify(mRadioProxy).startNetworkScan_1_5(mSerialNumberCaptor.capture(), any());

        // Before we find a way to trigger real RadioResponse method, emulate the behaivor.
        Consumer<RILRequest> unsupportedResponseEmulator = rr -> {
            mRILUnderTest.setCompatVersion(rr.getRequest(), RIL.RADIO_HAL_VERSION_1_4);
            mRILUnderTest.startNetworkScan(nsr, Message.obtain(rr.getResult()));
        };

        verifyRILUnsupportedResponse(mRILUnderTest, mSerialNumberCaptor.getValue(),
                RIL_REQUEST_START_NETWORK_SCAN, unsupportedResponseEmulator);

        // Verify the fallback method is invoked
        verify(mRadioProxy).startNetworkScan_1_4(eq(mSerialNumberCaptor.getValue() + 1), any());
    }

    @FlakyTest
    @Test
    public void testGetVoiceRegistrationStateWithUnsupportedResponse() throws Exception {
        // Use Radio HAL v1.5
        try {
            replaceInstance(RIL.class, "mRadioVersion", mRILUnderTest, mRadioVersionV15);
        } catch (Exception e) {
        }
        mRILUnderTest.getVoiceRegistrationState(obtainMessage());

        // Verify the v1.5 HAL method is called
        verify(mRadioProxy).getVoiceRegistrationState_1_5(mSerialNumberCaptor.capture());

        // Before we find a way to trigger real RadioResponse method, emulate the behaivor.
        Consumer<RILRequest> unsupportedResponseEmulator = rr -> {
            mRILUnderTest.setCompatVersion(rr.getRequest(), RIL.RADIO_HAL_VERSION_1_4);
            mRILUnderTest.getVoiceRegistrationState(Message.obtain(rr.getResult()));
        };

        verifyRILUnsupportedResponse(mRILUnderTest, mSerialNumberCaptor.getValue(),
                RIL_REQUEST_VOICE_REGISTRATION_STATE, unsupportedResponseEmulator);

        // Verify the fallback method is invoked
        verify(mRadioProxy).getVoiceRegistrationState(mSerialNumberCaptor.getValue() + 1);
    }

    @FlakyTest
    @Test
    public void testGetDataRegistrationState() throws Exception {
@@ -552,6 +659,32 @@ public class RILTest extends TelephonyTest {
                mRILUnderTest, mSerialNumberCaptor.getValue(), RIL_REQUEST_DATA_REGISTRATION_STATE);
    }

    @FlakyTest
    @Test
    public void testGetDataRegistrationStateWithUnsupportedResponse() throws Exception {
        // Use Radio HAL v1.5
        try {
            replaceInstance(RIL.class, "mRadioVersion", mRILUnderTest, mRadioVersionV15);
        } catch (Exception e) {
        }

        // Verify the v1.5 HAL method is called
        mRILUnderTest.getDataRegistrationState(obtainMessage());
        verify(mRadioProxy).getDataRegistrationState_1_5(mSerialNumberCaptor.capture());

        // Before we find a way to trigger real RadioResponse method, emulate the behaivor.
        Consumer<RILRequest> unsupportedResponseEmulator = rr -> {
            mRILUnderTest.setCompatVersion(rr.getRequest(), RIL.RADIO_HAL_VERSION_1_4);
            mRILUnderTest.getDataRegistrationState(Message.obtain(rr.getResult()));
        };

        verifyRILUnsupportedResponse(mRILUnderTest, mSerialNumberCaptor.getValue(),
                RIL_REQUEST_DATA_REGISTRATION_STATE, unsupportedResponseEmulator);

        // Verify the fallback method is invoked
        verify(mRadioProxy).getDataRegistrationState(mSerialNumberCaptor.getValue() + 1);
    }

    @FlakyTest
    @Test
    public void testGetOperator() throws Exception {
@@ -1157,6 +1290,27 @@ public class RILTest extends TelephonyTest {
        assertFalse(ril.getWakeLock(RIL.FOR_WAKELOCK).isHeld());
    }

    private static void verifyRILUnsupportedResponse(RIL ril, int serial, int requestType,
            Consumer<RILRequest> unsupportedResponseEmulator) {
        RadioResponseInfo responseInfo =
                createFakeRadioResponseInfo(serial, RadioError.REQUEST_NOT_SUPPORTED,
                        RadioResponseType.SOLICITED);

        RILRequest rr = ril.processResponse(responseInfo);
        assertNotNull(rr);

        assertEquals(serial, rr.getSerial());
        assertEquals(requestType, rr.getRequest());
        assertTrue(ril.getWakeLock(RIL.FOR_WAKELOCK).isHeld());

        unsupportedResponseEmulator.accept(rr);

        ril.processResponseDone(rr, responseInfo, null);

        assertEquals(1, ril.getRilRequestList().size());
        assertTrue(ril.getWakeLock(RIL.FOR_WAKELOCK).isHeld());
    }

    private static RadioResponseInfo createFakeRadioResponseInfo(int serial, int error, int type) {
        RadioResponseInfo respInfo = new RadioResponseInfo();
        respInfo.serial = serial;
@@ -2330,4 +2484,24 @@ public class RILTest extends TelephonyTest {
        verifyRILResponse(mRILUnderTest, mSerialNumberCaptor.getValue(),
                RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT);
    }

    @Test
    public void testSetGetCompatVersion() throws Exception {
        final int testRequest = RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT;

        // getCompactVersion should return null before first setting
        assertNull(mRILUnderTest.getCompatVersion(testRequest));

        // first time setting any valid HalVersion will success
        mRILUnderTest.setCompatVersion(testRequest, RIL.RADIO_HAL_VERSION_1_4);
        assertEquals(RIL.RADIO_HAL_VERSION_1_4, mRILUnderTest.getCompatVersion(testRequest));

        // try to set a lower HalVersion will success
        mRILUnderTest.setCompatVersion(testRequest, RIL.RADIO_HAL_VERSION_1_3);
        assertEquals(RIL.RADIO_HAL_VERSION_1_3, mRILUnderTest.getCompatVersion(testRequest));

        // try to set a greater HalVersion will not success
        mRILUnderTest.setCompatVersion(testRequest, RIL.RADIO_HAL_VERSION_1_5);
        assertEquals(RIL.RADIO_HAL_VERSION_1_3, mRILUnderTest.getCompatVersion(testRequest));
    }
}