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

Commit 0826da53 authored by Nathan Harold's avatar Nathan Harold
Browse files

Cross check CellIdentity w NetworkType in RegState

Add a variety of cross-checks to ensure that the HAL is
reporting a valid combination of the network type and
the CellIdentity. If not, report an Anomaly and coerce
the NetworkType based on the less-fudge-able CellIdentity.

Bug: 202851802
Test: atest CellularNetworkServiceTest#testNetworkTypeForCellIdentity
Change-Id: Iae06e7824a8796dba9c0744885d45cd4ffc589ea
parent 66cf77fa
Loading
Loading
Loading
Loading
+125 −12
Original line number Diff line number Diff line
@@ -27,8 +27,14 @@ import android.os.Looper;
import android.os.Message;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AnomalyReporter;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityCdma;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
import android.telephony.CellIdentityNr;
import android.telephony.CellIdentityTdscdma;
import android.telephony.CellIdentityWcdma;
import android.telephony.LteVopsSupportInfo;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.NetworkService;
@@ -39,13 +45,17 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.VopsSupportInfo;
import android.text.TextUtils;
import android.util.ArrayMap;

import com.android.internal.annotations.VisibleForTesting;
import com.android.telephony.Rlog;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Implementation of network services for Cellular. It's a service that handles network requests
@@ -64,6 +74,41 @@ public class CellularNetworkService extends NetworkService {
    // From 24.008 6.1.3.0 and 10.5.6.2 the maximum number of PDP Contexts is 16.
    private static final int MAX_DATA_CALLS = 16;

    private static final Map<Class<? extends CellIdentity>, List<Integer>> sNetworkTypes;

    static {
        sNetworkTypes = new ArrayMap<>();
        sNetworkTypes.put(CellIdentityGsm.class,
                Arrays.asList(new Integer[]{
                    TelephonyManager.NETWORK_TYPE_GSM,
                    TelephonyManager.NETWORK_TYPE_GPRS,
                    TelephonyManager.NETWORK_TYPE_EDGE}));
        sNetworkTypes.put(CellIdentityWcdma.class,
                Arrays.asList(new Integer[]{
                    TelephonyManager.NETWORK_TYPE_UMTS,
                    TelephonyManager.NETWORK_TYPE_HSDPA,
                    TelephonyManager.NETWORK_TYPE_HSUPA,
                    TelephonyManager.NETWORK_TYPE_HSPA,
                    TelephonyManager.NETWORK_TYPE_HSPAP}));
        sNetworkTypes.put(CellIdentityCdma.class,
                Arrays.asList(new Integer[]{
                    TelephonyManager.NETWORK_TYPE_CDMA,
                    TelephonyManager.NETWORK_TYPE_1xRTT,
                    TelephonyManager.NETWORK_TYPE_EVDO_0,
                    TelephonyManager.NETWORK_TYPE_EVDO_A,
                    TelephonyManager.NETWORK_TYPE_EVDO_B,
                    TelephonyManager.NETWORK_TYPE_EHRPD}));
        sNetworkTypes.put(CellIdentityLte.class,
                Arrays.asList(new Integer[]{
                    TelephonyManager.NETWORK_TYPE_LTE}));
        sNetworkTypes.put(CellIdentityNr.class,
                Arrays.asList(new Integer[]{
                    TelephonyManager.NETWORK_TYPE_NR}));
        sNetworkTypes.put(CellIdentityTdscdma.class,
                Arrays.asList(new Integer[]{
                    TelephonyManager.NETWORK_TYPE_TD_SCDMA}));
    }

    private class CellularNetworkServiceProvider extends NetworkServiceProvider {

        private final Map<Message, NetworkServiceCallback> mCallbackMap = new HashMap<>();
@@ -381,11 +426,7 @@ public class CellularNetworkService extends NetworkService {
            final int reasonForDenial = regResult.reasonForDenial;

            int networkType = ServiceState.rilRadioTechnologyToNetworkType(regResult.rat);
            if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
                // In Radio HAL v1.5, NETWORK_TYPE_LTE_CA is ignored. Callers should use
                // PhysicalChannelConfig.
                networkType = TelephonyManager.NETWORK_TYPE_LTE;
            }
            networkType = getNetworkTypeForCellIdentity(networkType, cellIdentity);

            // Conditional parameters for specific RANs
            boolean cssSupported = false;
@@ -537,11 +578,7 @@ public class CellularNetworkService extends NetworkService {
            final int reasonForDenial = regResult.reasonForDenial;

            int networkType = ServiceState.rilRadioTechnologyToNetworkType(regResult.rat);
            if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
                // In Radio HAL v1.5, NETWORK_TYPE_LTE_CA is ignored. Callers should use
                // PhysicalChannelConfig.
                networkType = TelephonyManager.NETWORK_TYPE_LTE;
            }
            networkType = getNetworkTypeForCellIdentity(networkType, cellIdentity);

            // Conditional parameters for specific RANs
            boolean cssSupported = false;
@@ -643,6 +680,78 @@ public class CellularNetworkService extends NetworkService {
        }
    }

    /** Cross-check the network type against the CellIdentity type */
    @VisibleForTesting
    public static int getNetworkTypeForCellIdentity(int networkType, CellIdentity ci) {
        if (ci == null) {
            if (networkType != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
                // Network type is non-null but CellIdentity is null
                AnomalyReporter.reportAnomaly(
                        UUID.fromString("e67ea4ef-7251-4a69-a063-22c47fc58743"),
                            "RIL Unexpected NetworkType");
                if (android.os.Build.isDebuggable()) {
                    logw("Updating incorrect network type from "
                            + TelephonyManager.getNetworkTypeName(networkType) + " to UNKNOWN");
                    return TelephonyManager.NETWORK_TYPE_UNKNOWN;
                } else {
                    // If the build isn't debuggable and CellIdentity is null, there's no way to
                    // guess the approximately correct type so if it's valid it gets a pass.
                    for (List<Integer> values : sNetworkTypes.values()) {
                        if (values.contains(networkType)) return networkType;
                    }
                }
            }

            // No valid network type, so return UNKNOWN for safety.
            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
        }


        // If the type is reported as IWLAN but the CellIdentity is a cellular type,
        // report that; Devices post HAL 1.4 should be operating in AP-assisted mode
        if (networkType == TelephonyManager.NETWORK_TYPE_IWLAN) {
            AnomalyReporter.reportAnomaly(
                    UUID.fromString("07dfa183-b2e7-42b7-98a1-dd5ae2abdd4f"),
                            "RIL Reported IWLAN");
            if (!android.os.Build.isDebuggable()) return networkType;

            if (sNetworkTypes.containsKey(ci.getClass())) {
                final int updatedType = sNetworkTypes.get(ci.getClass()).get(0);
                logw("Updating incorrect network type from IWLAN to " + updatedType);
                return updatedType;
            } else {
                logw("Updating incorrect network type from IWLAN to UNKNOWN");
                return TelephonyManager.NETWORK_TYPE_UNKNOWN;
            }
        }

        if (!sNetworkTypes.containsKey(ci.getClass())) {
            AnomalyReporter.reportAnomaly(
                    UUID.fromString("469858cf-46e5-416e-bc11-5e7970917857"),
                        "RIL Unknown CellIdentity");
            return networkType;
        }

        // If the network type isn't valid for the CellIdentity type,
        final List<Integer> typesForCi = sNetworkTypes.get(ci.getClass());
        if (!typesForCi.contains(networkType)) {
            AnomalyReporter.reportAnomaly(
                    UUID.fromString("2fb634fa-cab3-44d2-bbe8-c7689b0f3e31"),
                        "RIL Mismatched NetworkType");
            // Since this is a plain-and-simple mismatch between two conflicting pieces of
            // data, and theres no way to know which one to trust, pick the one that's harder
            // to coerce / fake / set incorrectly and make them roughly match.
            // Note, this also does the fixup for LTE_CA -> LTE that was formerly done as a
            // special case.
            logw("Updating incorrect network type from "
                    + TelephonyManager.getNetworkTypeName(networkType)
                    + " to " + TelephonyManager.getNetworkTypeName(typesForCi.get(0)));
            return typesForCi.get(0);
        }

        return networkType;
    }

    @Override
    public NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex) {
        if (DBG) log("Cellular network service created for slot " + slotIndex);
@@ -653,11 +762,15 @@ public class CellularNetworkService extends NetworkService {
        return new CellularNetworkServiceProvider(slotIndex);
    }

    private void log(String s) {
    private static void log(String s) {
        Rlog.d(TAG, s);
    }

    private void loge(String s) {
    private static void logw(String s) {
        Rlog.w(TAG, s);
    }

    private static void loge(String s) {
        Rlog.e(TAG, s);
    }
}
+59 −14
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.telephony;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
@@ -27,6 +28,9 @@ import android.content.IntentFilter;
import android.content.pm.ServiceInfo;
import android.os.RemoteException;
import android.telephony.AccessNetworkConstants;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
import android.telephony.CellIdentityWcdma;
import android.telephony.INetworkService;
import android.telephony.INetworkServiceCallback;
import android.telephony.LteVopsSupportInfo;
@@ -36,8 +40,10 @@ import android.telephony.NetworkServiceCallback;
import android.telephony.NrVopsSupportInfo;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.VopsSupportInfo;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.internal.R;

@@ -182,7 +188,7 @@ public class CellularNetworkServiceTest extends TelephonyTest {
    public void testGetNetworkRegistrationInfoV1_5() {
        // common parameters
        int regState = NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
        int radioTech = ServiceState.RIL_RADIO_TECHNOLOGY_LTE;
        final int radioTech = ServiceState.RIL_RADIO_TECHNOLOGY_LTE;
        int reasonForDenial = 0;

        // voice services
@@ -211,9 +217,12 @@ public class CellularNetworkServiceTest extends TelephonyTest {
                new android.hardware.radio.V1_5.RegStateResult();

        regResult.regState = regState;
        regResult.rat = radioTech;
        regResult.reasonForDenial = reasonForDenial;

        regResult.rat = radioTech;
        regResult.cellIdentity = new android.hardware.radio.V1_5.CellIdentity();
        regResult.cellIdentity.lte(new android.hardware.radio.V1_5.CellIdentityLte());

        android.hardware.radio.V1_5.RegStateResult.AccessTechnologySpecificInfo
                .EutranRegistrationInfo eutranInfo = new android.hardware.radio.V1_5
                .RegStateResult.AccessTechnologySpecificInfo.EutranRegistrationInfo();
@@ -240,7 +249,8 @@ public class CellularNetworkServiceTest extends TelephonyTest {
        NetworkRegistrationInfo expectedState = new NetworkRegistrationInfo(
                NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                regState, ServiceState.rilRadioTechnologyToNetworkType(radioTech), reasonForDenial,
                false, availableVoiceServices, null, "", false, 0, 0, 0);
                false, availableVoiceServices,
                RILUtils.convertHalCellIdentity(regResult.cellIdentity), "", false, 0, 0, 0);

        try {
            verify(mCallback, timeout(1000).times(1)).onRequestNetworkRegistrationInfoComplete(
@@ -259,8 +269,9 @@ public class CellularNetworkServiceTest extends TelephonyTest {
        expectedState = new NetworkRegistrationInfo(
                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                regState, ServiceState.rilRadioTechnologyToNetworkType(radioTech), reasonForDenial,
                false, availableDataServices, null, "", maxDataCalls, isDcNrRestricted,
                isNrAvailable, isEndcAvailable, vops);
                false, availableDataServices,
                RILUtils.convertHalCellIdentity(regResult.cellIdentity),
                "", maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, vops);

        try {
            verify(mCallback, timeout(1000).times(1)).onRequestNetworkRegistrationInfoComplete(
@@ -275,7 +286,7 @@ public class CellularNetworkServiceTest extends TelephonyTest {
    public void testGetNetworkRegistrationInfoV1_6WithLte() {
        // common parameters
        int regState = NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
        int radioTech = ServiceState.RIL_RADIO_TECHNOLOGY_LTE;
        final int radioTech = ServiceState.RIL_RADIO_TECHNOLOGY_LTE;
        int reasonForDenial = 0;

        // voice services
@@ -304,9 +315,12 @@ public class CellularNetworkServiceTest extends TelephonyTest {
                new android.hardware.radio.V1_6.RegStateResult();

        regResult.regState = regState;
        regResult.rat = radioTech;
        regResult.reasonForDenial = reasonForDenial;

        regResult.rat = radioTech;
        regResult.cellIdentity = new android.hardware.radio.V1_5.CellIdentity();
        regResult.cellIdentity.lte(new android.hardware.radio.V1_5.CellIdentityLte());

        android.hardware.radio.V1_5.RegStateResult.AccessTechnologySpecificInfo
                .EutranRegistrationInfo eutranInfo = new android.hardware.radio.V1_5
                .RegStateResult.AccessTechnologySpecificInfo.EutranRegistrationInfo();
@@ -333,7 +347,8 @@ public class CellularNetworkServiceTest extends TelephonyTest {
        NetworkRegistrationInfo expectedState = new NetworkRegistrationInfo(
                NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                regState, ServiceState.rilRadioTechnologyToNetworkType(radioTech), reasonForDenial,
                false, availableVoiceServices, null, "", false, 0, 0, 0);
                false, availableVoiceServices,
                RILUtils.convertHalCellIdentity(regResult.cellIdentity), "", false, 0, 0, 0);

        try {
            verify(mCallback, timeout(1000).times(1)).onRequestNetworkRegistrationInfoComplete(
@@ -352,8 +367,9 @@ public class CellularNetworkServiceTest extends TelephonyTest {
        expectedState = new NetworkRegistrationInfo(
                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                regState, ServiceState.rilRadioTechnologyToNetworkType(radioTech), reasonForDenial,
                false, availableDataServices, null, "", maxDataCalls, isDcNrRestricted,
                isNrAvailable, isEndcAvailable, vops);
                false, availableDataServices,
                RILUtils.convertHalCellIdentity(regResult.cellIdentity),
                "", maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, vops);

        try {
            verify(mCallback, timeout(1000).times(1)).onRequestNetworkRegistrationInfoComplete(
@@ -369,7 +385,7 @@ public class CellularNetworkServiceTest extends TelephonyTest {
    public void testGetNetworkRegistrationInfoV1_6WithNr() {
        // common parameters
        int regState = NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
        int radioTech = ServiceState.RIL_RADIO_TECHNOLOGY_NR;
        final int radioTech = ServiceState.RIL_RADIO_TECHNOLOGY_NR;
        int reasonForDenial = 0;

        // voice services
@@ -394,9 +410,12 @@ public class CellularNetworkServiceTest extends TelephonyTest {
                new android.hardware.radio.V1_6.RegStateResult();

        regResult.regState = regState;
        regResult.rat = radioTech;
        regResult.reasonForDenial = reasonForDenial;

        regResult.rat = radioTech;
        regResult.cellIdentity = new android.hardware.radio.V1_5.CellIdentity();
        regResult.cellIdentity.nr(new android.hardware.radio.V1_5.CellIdentityNr());

        regResult.accessTechnologySpecificInfo.ngranNrVopsInfo(new android.hardware.radio.V1_6
                .NrVopsInfo());
        regResult.accessTechnologySpecificInfo.ngranNrVopsInfo().vopsSupported = vopsSupported;
@@ -419,7 +438,8 @@ public class CellularNetworkServiceTest extends TelephonyTest {
        NetworkRegistrationInfo expectedState = new NetworkRegistrationInfo(
                NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                regState, ServiceState.rilRadioTechnologyToNetworkType(radioTech), reasonForDenial,
                false, availableVoiceServices, null, "", false, 0, 0, 0);
                false, availableVoiceServices,
                RILUtils.convertHalCellIdentity(regResult.cellIdentity), "", false, 0, 0, 0);

        try {
            verify(mCallback, timeout(1000).times(1)).onRequestNetworkRegistrationInfoComplete(
@@ -438,7 +458,9 @@ public class CellularNetworkServiceTest extends TelephonyTest {
        expectedState = new NetworkRegistrationInfo(
                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                regState, ServiceState.rilRadioTechnologyToNetworkType(radioTech), reasonForDenial,
                false, availableDataServices, null, "", maxDataCalls, false, false, false, vops);
                false, availableDataServices,
                RILUtils.convertHalCellIdentity(regResult.cellIdentity),
                "", maxDataCalls, false, false, false, vops);

        try {
            verify(mCallback, timeout(1000).times(1)).onRequestNetworkRegistrationInfoComplete(
@@ -447,4 +469,27 @@ public class CellularNetworkServiceTest extends TelephonyTest {
            assertTrue(false);
        }
    }

    @Test
    @SmallTest
    public void testNetworkTypeForCellIdentity() {
        assertEquals(TelephonyManager.NETWORK_TYPE_GSM,
                    CellularNetworkService.getNetworkTypeForCellIdentity(
                            TelephonyManager.NETWORK_TYPE_HSDPA, new CellIdentityGsm()));
        assertEquals(TelephonyManager.NETWORK_TYPE_LTE,
                    CellularNetworkService.getNetworkTypeForCellIdentity(
                            TelephonyManager.NETWORK_TYPE_NR, new CellIdentityLte()));
        assertEquals(TelephonyManager.NETWORK_TYPE_LTE,
                    CellularNetworkService.getNetworkTypeForCellIdentity(
                        TelephonyManager.NETWORK_TYPE_IWLAN, new CellIdentityLte()));
        assertEquals(TelephonyManager.NETWORK_TYPE_LTE,
                CellularNetworkService.getNetworkTypeForCellIdentity(
                        TelephonyManager.NETWORK_TYPE_LTE_CA, new CellIdentityLte()));
        assertEquals(TelephonyManager.NETWORK_TYPE_EDGE,
                    CellularNetworkService.getNetworkTypeForCellIdentity(
                    TelephonyManager.NETWORK_TYPE_EDGE, new CellIdentityGsm()));
        assertEquals(TelephonyManager.NETWORK_TYPE_UMTS,
                    CellularNetworkService.getNetworkTypeForCellIdentity(
                    TelephonyManager.NETWORK_TYPE_UNKNOWN, new CellIdentityWcdma()));
    }
}