Loading src/java/com/android/internal/telephony/RIL.java +88 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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(); Loading Loading @@ -1458,7 +1493,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 { Loading @@ -1485,8 +1526,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 { Loading Loading @@ -2443,11 +2489,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(); Loading @@ -2469,7 +2529,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)); Loading Loading @@ -5514,6 +5574,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) { Loading src/java/com/android/internal/telephony/RILRequest.java +22 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. */ Loading Loading @@ -175,6 +196,7 @@ public class RILRequest { + serialString()); } } mArguments = null; } } } Loading src/java/com/android/internal/telephony/RadioResponse.java +71 −25 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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); } /** Loading @@ -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*/); } /** Loading Loading @@ -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( Loading @@ -2219,7 +2266,6 @@ public class RadioResponse extends IRadioResponse.Stub { } mRil.processResponseDone(rr, responseInfo, nsr); } } private void responseDataCallList(RadioResponseInfo responseInfo, List<? extends Object> dataCallResultList) { Loading tests/telephonytests/src/com/android/internal/telephony/RILTest.java +174 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -142,6 +144,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; Loading Loading @@ -169,6 +173,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 Loading Loading @@ -544,6 +549,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 { Loading @@ -553,6 +660,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 { Loading Loading @@ -1158,6 +1291,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; Loading Loading @@ -2333,4 +2487,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)); } } Loading
src/java/com/android/internal/telephony/RIL.java +88 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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(); Loading Loading @@ -1458,7 +1493,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 { Loading @@ -1485,8 +1526,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 { Loading Loading @@ -2443,11 +2489,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(); Loading @@ -2469,7 +2529,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)); Loading Loading @@ -5514,6 +5574,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) { Loading
src/java/com/android/internal/telephony/RILRequest.java +22 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. */ Loading Loading @@ -175,6 +196,7 @@ public class RILRequest { + serialString()); } } mArguments = null; } } } Loading
src/java/com/android/internal/telephony/RadioResponse.java +71 −25 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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); } /** Loading @@ -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*/); } /** Loading Loading @@ -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( Loading @@ -2219,7 +2266,6 @@ public class RadioResponse extends IRadioResponse.Stub { } mRil.processResponseDone(rr, responseInfo, nsr); } } private void responseDataCallList(RadioResponseInfo responseInfo, List<? extends Object> dataCallResultList) { Loading
tests/telephonytests/src/com/android/internal/telephony/RILTest.java +174 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -142,6 +144,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; Loading Loading @@ -169,6 +173,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 Loading Loading @@ -544,6 +549,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 { Loading @@ -553,6 +660,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 { Loading Loading @@ -1158,6 +1291,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; Loading Loading @@ -2333,4 +2487,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)); } }