package android.telephony; import static android.telephony.ServiceState.DUPLEX_MODE_FDD; import static android.telephony.ServiceState.DUPLEX_MODE_TDD; import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN; import android.telephony.AccessNetworkConstants.EutranBand; import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency; import android.telephony.AccessNetworkConstants.GeranBand; import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency; import android.telephony.AccessNetworkConstants.NgranArfcnFrequency; import android.telephony.AccessNetworkConstants.NgranBands; import android.telephony.AccessNetworkConstants.UtranBand; import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency; import android.telephony.ServiceState.DuplexMode; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * Utilities to map between radio constants. * * @hide */ public class AccessNetworkUtils { // do not instantiate private AccessNetworkUtils() {} public static final int INVALID_BAND = -1; public static final int INVALID_FREQUENCY = -1; /** ISO country code of Japan. */ private static final String JAPAN_ISO_COUNTRY_CODE = "jp"; private static final String TAG = "AccessNetworkUtils"; private static final int FREQUENCY_KHZ = 1000; private static final int FREQUENCY_RANGE_LOW_KHZ = 1000000; private static final int FREQUENCY_RANGE_MID_KHZ = 3000000; private static final int FREQUENCY_RANGE_HIGH_KHZ = 6000000; private static final Set UARFCN_NOT_GENERAL_BAND; static { UARFCN_NOT_GENERAL_BAND = new HashSet(); UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_A); UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_B); UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_C); UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_D); UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_E); UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_F); } /** * Gets the duplex mode for the given EUTRAN operating band. * *

See 3GPP 36.101 sec 5.5-1 for calculation * * @param band The EUTRAN band number * @return The duplex mode of the given EUTRAN band */ @DuplexMode public static int getDuplexModeForEutranBand(int band) { if (band == INVALID_BAND) { return DUPLEX_MODE_UNKNOWN; } if (band > EutranBand.BAND_88) { return DUPLEX_MODE_UNKNOWN; } else if (band >= EutranBand.BAND_65) { return DUPLEX_MODE_FDD; } else if (band >= EutranBand.BAND_33) { return DUPLEX_MODE_TDD; } else if (band >= EutranBand.BAND_1) { return DUPLEX_MODE_FDD; } return DUPLEX_MODE_UNKNOWN; } /** * Gets the EUTRAN Operating band for a given downlink EARFCN. * *

See 3GPP TS 36.101 clause 5.7.3-1 for calculation. * * @param earfcn The downlink EARFCN * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists */ public static int getOperatingBandForEarfcn(int earfcn) { if (earfcn > 70645) { return INVALID_BAND; } else if (earfcn >= 70596) { return EutranBand.BAND_88; } else if (earfcn >= 70546) { return EutranBand.BAND_87; } else if (earfcn >= 70366) { return EutranBand.BAND_85; } else if (earfcn > 69465) { return INVALID_BAND; } else if (earfcn >= 69036) { return EutranBand.BAND_74; } else if (earfcn >= 68986) { return EutranBand.BAND_73; } else if (earfcn >= 68936) { return EutranBand.BAND_72; } else if (earfcn >= 68586) { return EutranBand.BAND_71; } else if (earfcn >= 68336) { return EutranBand.BAND_70; } else if (earfcn > 67835) { return INVALID_BAND; } else if (earfcn >= 67536) { return EutranBand.BAND_68; } else if (earfcn >= 67366) { return INVALID_BAND; // band 67 only for CarrierAgg } else if (earfcn >= 66436) { return EutranBand.BAND_66; } else if (earfcn >= 65536) { return EutranBand.BAND_65; } else if (earfcn > 60254) { return INVALID_BAND; } else if (earfcn >= 60140) { return EutranBand.BAND_53; } else if (earfcn >= 59140) { return EutranBand.BAND_52; } else if (earfcn >= 59090) { return EutranBand.BAND_51; } else if (earfcn >= 58240) { return EutranBand.BAND_50; } else if (earfcn >= 56740) { return EutranBand.BAND_49; } else if (earfcn >= 55240) { return EutranBand.BAND_48; } else if (earfcn >= 54540) { return EutranBand.BAND_47; } else if (earfcn >= 46790) { return EutranBand.BAND_46; } else if (earfcn >= 46590) { return EutranBand.BAND_45; } else if (earfcn >= 45590) { return EutranBand.BAND_44; } else if (earfcn >= 43590) { return EutranBand.BAND_43; } else if (earfcn >= 41590) { return EutranBand.BAND_42; } else if (earfcn >= 39650) { return EutranBand.BAND_41; } else if (earfcn >= 38650) { return EutranBand.BAND_40; } else if (earfcn >= 38250) { return EutranBand.BAND_39; } else if (earfcn >= 37750) { return EutranBand.BAND_38; } else if (earfcn >= 37550) { return EutranBand.BAND_37; } else if (earfcn >= 36950) { return EutranBand.BAND_36; } else if (earfcn >= 36350) { return EutranBand.BAND_35; } else if (earfcn >= 36200) { return EutranBand.BAND_34; } else if (earfcn >= 36000) { return EutranBand.BAND_33; } else if (earfcn > 10359) { return INVALID_BAND; } else if (earfcn >= 9920) { return INVALID_BAND; // band 32 only for CarrierAgg } else if (earfcn >= 9870) { return EutranBand.BAND_31; } else if (earfcn >= 9770) { return EutranBand.BAND_30; } else if (earfcn >= 9660) { return INVALID_BAND; // band 29 only for CarrierAgg } else if (earfcn >= 9210) { return EutranBand.BAND_28; } else if (earfcn >= 9040) { return EutranBand.BAND_27; } else if (earfcn >= 8690) { return EutranBand.BAND_26; } else if (earfcn >= 8040) { return EutranBand.BAND_25; } else if (earfcn >= 7700) { return EutranBand.BAND_24; } else if (earfcn >= 7500) { return EutranBand.BAND_23; } else if (earfcn >= 6600) { return EutranBand.BAND_22; } else if (earfcn >= 6450) { return EutranBand.BAND_21; } else if (earfcn >= 6150) { return EutranBand.BAND_20; } else if (earfcn >= 6000) { return EutranBand.BAND_19; } else if (earfcn >= 5850) { return EutranBand.BAND_18; } else if (earfcn >= 5730) { return EutranBand.BAND_17; } else if (earfcn > 5379) { return INVALID_BAND; } else if (earfcn >= 5280) { return EutranBand.BAND_14; } else if (earfcn >= 5180) { return EutranBand.BAND_13; } else if (earfcn >= 5010) { return EutranBand.BAND_12; } else if (earfcn >= 4750) { return EutranBand.BAND_11; } else if (earfcn >= 4150) { return EutranBand.BAND_10; } else if (earfcn >= 3800) { return EutranBand.BAND_9; } else if (earfcn >= 3450) { return EutranBand.BAND_8; } else if (earfcn >= 2750) { return EutranBand.BAND_7; } else if (earfcn >= 2650) { return EutranBand.BAND_6; } else if (earfcn >= 2400) { return EutranBand.BAND_5; } else if (earfcn >= 1950) { return EutranBand.BAND_4; } else if (earfcn >= 1200) { return EutranBand.BAND_3; } else if (earfcn >= 600) { return EutranBand.BAND_2; } else if (earfcn >= 0) { return EutranBand.BAND_1; } return INVALID_BAND; } /** * Gets the NR Operating band for a given downlink NRARFCN. * *

See 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1 and * Table 5.2-2 NR operating bands in FR2 * * @param nrarfcn The downlink NRARFCN * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists */ public static int getOperatingBandForNrarfcn(int nrarfcn) { if (nrarfcn >= 422000 && nrarfcn <= 434000) { return NgranBands.BAND_1; } else if (nrarfcn >= 386000 && nrarfcn <= 398000) { return NgranBands.BAND_2; } else if (nrarfcn >= 361000 && nrarfcn <= 376000) { return NgranBands.BAND_3; } else if (nrarfcn >= 173800 && nrarfcn <= 178800) { return NgranBands.BAND_5; } else if (nrarfcn >= 524000 && nrarfcn <= 538000) { return NgranBands.BAND_7; } else if (nrarfcn >= 185000 && nrarfcn <= 192000) { return NgranBands.BAND_8; } else if (nrarfcn >= 145800 && nrarfcn <= 149200) { return NgranBands.BAND_12; } else if (nrarfcn >= 151600 && nrarfcn <= 153600) { return NgranBands.BAND_14; } else if (nrarfcn >= 172000 && nrarfcn <= 175000) { return NgranBands.BAND_18; } else if (nrarfcn >= 158200 && nrarfcn <= 164200) { return NgranBands.BAND_20; } else if (nrarfcn >= 386000 && nrarfcn <= 399000) { return NgranBands.BAND_25; } else if (nrarfcn >= 171800 && nrarfcn <= 178800) { return NgranBands.BAND_26; } else if (nrarfcn >= 151600 && nrarfcn <= 160600) { return NgranBands.BAND_28; } else if (nrarfcn >= 143400 && nrarfcn <= 145600) { return NgranBands.BAND_29; } else if (nrarfcn >= 470000 && nrarfcn <= 472000) { return NgranBands.BAND_30; } else if (nrarfcn >= 402000 && nrarfcn <= 405000) { return NgranBands.BAND_34; } else if (nrarfcn >= 514000 && nrarfcn <= 524000) { return NgranBands.BAND_38; } else if (nrarfcn >= 376000 && nrarfcn <= 384000) { return NgranBands.BAND_39; } else if (nrarfcn >= 460000 && nrarfcn <= 480000) { return NgranBands.BAND_40; } else if (nrarfcn >= 499200 && nrarfcn <= 537999) { return NgranBands.BAND_41; } else if (nrarfcn >= 743334 && nrarfcn <= 795000) { return NgranBands.BAND_46; } else if (nrarfcn >= 636667 && nrarfcn <= 646666) { return NgranBands.BAND_48; } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { return NgranBands.BAND_50; } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { return NgranBands.BAND_51; } else if (nrarfcn >= 496700 && nrarfcn <= 499000) { return NgranBands.BAND_53; } else if (nrarfcn >= 422000 && nrarfcn <= 440000) { return NgranBands.BAND_65; // BAND_66 has the same channels } else if (nrarfcn >= 399000 && nrarfcn <= 404000) { return NgranBands.BAND_70; } else if (nrarfcn >= 123400 && nrarfcn <= 130400) { return NgranBands.BAND_71; } else if (nrarfcn >= 295000 && nrarfcn <= 303600) { return NgranBands.BAND_74; } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { return NgranBands.BAND_75; } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { return NgranBands.BAND_76; } else if (nrarfcn >= 620000 && nrarfcn <= 680000) { return NgranBands.BAND_77; } else if (nrarfcn >= 620000 && nrarfcn <= 653333) { return NgranBands.BAND_78; } else if (nrarfcn >= 693334 && nrarfcn <= 733333) { return NgranBands.BAND_79; } else if (nrarfcn >= 499200 && nrarfcn <= 538000) { return NgranBands.BAND_90; } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { return NgranBands.BAND_91; } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { return NgranBands.BAND_92; } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { return NgranBands.BAND_93; } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { return NgranBands.BAND_94; } else if (nrarfcn >= 795000 && nrarfcn <= 875000) { return NgranBands.BAND_96; } else if (nrarfcn >= 2054166 && nrarfcn <= 2104165) { return NgranBands.BAND_257; } else if (nrarfcn >= 2016667 && nrarfcn <= 2070832) { return NgranBands.BAND_258; } else if (nrarfcn >= 2229166 && nrarfcn <= 2279165) { return NgranBands.BAND_260; } else if (nrarfcn >= 2070833 && nrarfcn <= 2084999) { return NgranBands.BAND_261; } return INVALID_BAND; } /** * Gets the GERAN Operating band for a given ARFCN. * *

See 3GPP TS 45.005 clause 2 for calculation. * * @param arfcn The ARFCN * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists */ public static int getOperatingBandForArfcn(int arfcn) { if (arfcn >= 0 && arfcn <= 124) { return GeranBand.BAND_E900; } else if (arfcn >= 128 && arfcn <= 251) { return GeranBand.BAND_850; } else if (arfcn >= 259 && arfcn <= 293) { return GeranBand.BAND_450; } else if (arfcn >= 306 && arfcn <= 340) { return GeranBand.BAND_480; } else if (arfcn >= 438 && arfcn <= 511) { return GeranBand.BAND_750; } else if (arfcn >= 512 && arfcn <= 885) { // ARFCN between 512 and 810 are also part of BAND_PCS1900. // Returning BAND_DCS1800 in both cases. return GeranBand.BAND_DCS1800; } else if (arfcn >= 940 && arfcn <= 974) { return GeranBand.BAND_ER900; } else if (arfcn >= 975 && arfcn <= 1023) { return GeranBand.BAND_E900; } return INVALID_BAND; } /** * Gets the UTRAN Operating band for a given downlink UARFCN. * *

See 3GPP TS 25.101 clause 5.4.4 for calculation. * * @param uarfcn The downlink UARFCN * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists */ public static int getOperatingBandForUarfcn(int uarfcn) { // List of additional bands defined in TS 25.101. int[] addlBand2 = {412, 437, 462, 487, 512, 537, 562, 587, 612, 637, 662, 687}; int[] addlBand4 = {1887, 1912, 1937, 1962, 1987, 2012, 2037, 2062, 2087}; int[] addlBand5 = {1007, 1012, 1032, 1037, 1062, 1087}; int[] addlBand6 = {1037, 1062}; int[] addlBand7 = {2587, 2612, 2637, 2662, 2687, 2712, 2737, 2762, 2787, 2812, 2837, 2862, 2887, 2912}; int[] addlBand10 = {3412, 3437, 3462, 3487, 3512, 3537, 3562, 3587, 3612, 3637, 3662, 3687}; int[] addlBand12 = {3932, 3957, 3962, 3987, 3992}; int[] addlBand13 = {4067, 4092}; int[] addlBand14 = {4167, 4192}; int[] addlBand19 = {787, 812, 837}; int[] addlBand25 = {6292, 6317, 6342, 6367, 6392, 6417, 6442, 6467, 6492, 6517, 6542, 6567, 6592}; int[] addlBand26 = {5937, 5962, 5987, 5992, 6012, 6017, 6037, 6042, 6062, 6067, 6087}; if (uarfcn >= 10562 && uarfcn <= 10838) { return UtranBand.BAND_1; } else if ((uarfcn >= 9662 && uarfcn <= 9938) || Arrays.binarySearch(addlBand2, uarfcn) >= 0) { return UtranBand.BAND_2; } else if (uarfcn >= 1162 && uarfcn <= 1513) { return UtranBand.BAND_3; } else if ((uarfcn >= 1537 && uarfcn <= 1738) || Arrays.binarySearch(addlBand4, uarfcn) >= 0) { return UtranBand.BAND_4; } else if (uarfcn >= 4387 && uarfcn <= 4413) { // Band 6 is a subset of band 5. Only Japan uses band 6 and Japan does not have band 5. String country = TelephonyManager.getDefault().getNetworkCountryIso(); if (JAPAN_ISO_COUNTRY_CODE.compareToIgnoreCase(country) == 0) { return UtranBand.BAND_6; } else { return UtranBand.BAND_5; } } else if ((uarfcn >= 4357 && uarfcn <= 4458) || Arrays.binarySearch(addlBand5, uarfcn) >= 0) { return UtranBand.BAND_5; } else if (Arrays.binarySearch(addlBand6, uarfcn) >= 0) { return UtranBand.BAND_6; } else if ((uarfcn >= 2237 && uarfcn <= 2563) || Arrays.binarySearch(addlBand7, uarfcn) >= 0) { return UtranBand.BAND_7; } else if (uarfcn >= 2937 && uarfcn <= 3088) { return UtranBand.BAND_8; } else if (uarfcn >= 9237 && uarfcn <= 9387) { return UtranBand.BAND_9; } else if ((uarfcn >= 3112 && uarfcn <= 3388) || Arrays.binarySearch(addlBand10, uarfcn) >= 0) { return UtranBand.BAND_10; } else if (uarfcn >= 3712 && uarfcn <= 3787) { return UtranBand.BAND_11; } else if ((uarfcn >= 3842 && uarfcn <= 3903) || Arrays.binarySearch(addlBand12, uarfcn) >= 0) { return UtranBand.BAND_12; } else if ((uarfcn >= 4017 && uarfcn <= 4043) || Arrays.binarySearch(addlBand13, uarfcn) >= 0) { return UtranBand.BAND_13; } else if ((uarfcn >= 4117 && uarfcn <= 4143) || Arrays.binarySearch(addlBand14, uarfcn) >= 0) { return UtranBand.BAND_14; } else if ((uarfcn >= 712 && uarfcn <= 763) || Arrays.binarySearch(addlBand19, uarfcn) >= 0) { return UtranBand.BAND_19; } else if (uarfcn >= 4512 && uarfcn <= 4638) { return UtranBand.BAND_20; } else if (uarfcn >= 862 && uarfcn <= 912) { return UtranBand.BAND_21; } else if (uarfcn >= 4662 && uarfcn <= 5038) { return UtranBand.BAND_22; } else if ((uarfcn >= 5112 && uarfcn <= 5413) || Arrays.binarySearch(addlBand25, uarfcn) >= 0) { return UtranBand.BAND_25; } else if ((uarfcn >= 5762 && uarfcn <= 5913) || Arrays.binarySearch(addlBand26, uarfcn) >= 0) { return UtranBand.BAND_26; } return INVALID_BAND; } /** * Get geran bands from {@link PhysicalChannelConfig#getBand()} */ public static int getFrequencyRangeGroupFromGeranBand(@GeranBand.GeranBands int band) { switch (band) { case GeranBand.BAND_T380: case GeranBand.BAND_T410: case GeranBand.BAND_450: case GeranBand.BAND_480: case GeranBand.BAND_710: case GeranBand.BAND_750: case GeranBand.BAND_T810: case GeranBand.BAND_850: case GeranBand.BAND_P900: case GeranBand.BAND_E900: case GeranBand.BAND_R900: case GeranBand.BAND_ER900: return ServiceState.FREQUENCY_RANGE_LOW; case GeranBand.BAND_DCS1800: case GeranBand.BAND_PCS1900: return ServiceState.FREQUENCY_RANGE_MID; default: return ServiceState.FREQUENCY_RANGE_UNKNOWN; } } /** * Get utran bands from {@link PhysicalChannelConfig#getBand()} */ public static int getFrequencyRangeGroupFromUtranBand(@UtranBand.UtranBands int band) { switch (band) { case UtranBand.BAND_5: case UtranBand.BAND_6: case UtranBand.BAND_8: case UtranBand.BAND_12: case UtranBand.BAND_13: case UtranBand.BAND_14: case UtranBand.BAND_19: case UtranBand.BAND_20: case UtranBand.BAND_26: return ServiceState.FREQUENCY_RANGE_LOW; case UtranBand.BAND_1: case UtranBand.BAND_2: case UtranBand.BAND_3: case UtranBand.BAND_4: case UtranBand.BAND_7: case UtranBand.BAND_9: case UtranBand.BAND_10: case UtranBand.BAND_11: case UtranBand.BAND_21: case UtranBand.BAND_25: case UtranBand.BAND_A: case UtranBand.BAND_B: case UtranBand.BAND_C: case UtranBand.BAND_D: case UtranBand.BAND_E: case UtranBand.BAND_F: return ServiceState.FREQUENCY_RANGE_MID; case UtranBand.BAND_22: return ServiceState.FREQUENCY_RANGE_HIGH; default: return ServiceState.FREQUENCY_RANGE_UNKNOWN; } } /** * Get eutran bands from {@link PhysicalChannelConfig#getBand()} * 3GPP TS 36.101 Table 5.5 EUTRA operating bands */ public static int getFrequencyRangeGroupFromEutranBand(@EutranBand.EutranBands int band) { switch (band) { case EutranBand.BAND_5: case EutranBand.BAND_6: case EutranBand.BAND_8: case EutranBand.BAND_12: case EutranBand.BAND_13: case EutranBand.BAND_14: case EutranBand.BAND_17: case EutranBand.BAND_18: case EutranBand.BAND_19: case EutranBand.BAND_20: case EutranBand.BAND_26: case EutranBand.BAND_27: case EutranBand.BAND_28: case EutranBand.BAND_31: case EutranBand.BAND_44: case EutranBand.BAND_50: case EutranBand.BAND_51: case EutranBand.BAND_68: case EutranBand.BAND_71: case EutranBand.BAND_72: case EutranBand.BAND_73: case EutranBand.BAND_85: case EutranBand.BAND_87: case EutranBand.BAND_88: return ServiceState.FREQUENCY_RANGE_LOW; case EutranBand.BAND_1: case EutranBand.BAND_2: case EutranBand.BAND_3: case EutranBand.BAND_4: case EutranBand.BAND_7: case EutranBand.BAND_9: case EutranBand.BAND_10: case EutranBand.BAND_11: case EutranBand.BAND_21: case EutranBand.BAND_23: case EutranBand.BAND_24: case EutranBand.BAND_25: case EutranBand.BAND_30: case EutranBand.BAND_33: case EutranBand.BAND_34: case EutranBand.BAND_35: case EutranBand.BAND_36: case EutranBand.BAND_37: case EutranBand.BAND_38: case EutranBand.BAND_39: case EutranBand.BAND_40: case EutranBand.BAND_41: case EutranBand.BAND_45: case EutranBand.BAND_53: case EutranBand.BAND_65: case EutranBand.BAND_66: case EutranBand.BAND_70: case EutranBand.BAND_74: return ServiceState.FREQUENCY_RANGE_MID; case EutranBand.BAND_22: case EutranBand.BAND_42: case EutranBand.BAND_43: case EutranBand.BAND_46: case EutranBand.BAND_47: case EutranBand.BAND_48: case EutranBand.BAND_49: case EutranBand.BAND_52: return ServiceState.FREQUENCY_RANGE_HIGH; default: return ServiceState.FREQUENCY_RANGE_UNKNOWN; } } /** * Get ngran band from {@link PhysicalChannelConfig#getBand()} * 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1 * 3GPP TS 38.104 Table 5.2-2 NR operating bands in FR2 */ public static int getFrequencyRangeGroupFromNrBand(@NgranBands.NgranBand int band) { switch (band) { case NgranBands.BAND_5: case NgranBands.BAND_8: case NgranBands.BAND_12: case NgranBands.BAND_14: case NgranBands.BAND_18: case NgranBands.BAND_20: case NgranBands.BAND_26: case NgranBands.BAND_28: case NgranBands.BAND_29: case NgranBands.BAND_71: case NgranBands.BAND_81: case NgranBands.BAND_82: case NgranBands.BAND_83: case NgranBands.BAND_89: return ServiceState.FREQUENCY_RANGE_LOW; case NgranBands.BAND_1: case NgranBands.BAND_2: case NgranBands.BAND_3: case NgranBands.BAND_7: case NgranBands.BAND_25: case NgranBands.BAND_30: case NgranBands.BAND_34: case NgranBands.BAND_38: case NgranBands.BAND_39: case NgranBands.BAND_40: case NgranBands.BAND_41: case NgranBands.BAND_50: case NgranBands.BAND_51: case NgranBands.BAND_53: case NgranBands.BAND_65: case NgranBands.BAND_66: case NgranBands.BAND_70: case NgranBands.BAND_74: case NgranBands.BAND_75: case NgranBands.BAND_76: case NgranBands.BAND_80: case NgranBands.BAND_84: case NgranBands.BAND_86: case NgranBands.BAND_90: case NgranBands.BAND_91: case NgranBands.BAND_92: case NgranBands.BAND_93: case NgranBands.BAND_94: case NgranBands.BAND_95: return ServiceState.FREQUENCY_RANGE_MID; case NgranBands.BAND_46: case NgranBands.BAND_48: case NgranBands.BAND_77: case NgranBands.BAND_78: case NgranBands.BAND_79: return ServiceState.FREQUENCY_RANGE_HIGH; case NgranBands.BAND_96: case NgranBands.BAND_257: case NgranBands.BAND_258: case NgranBands.BAND_260: case NgranBands.BAND_261: return ServiceState.FREQUENCY_RANGE_MMWAVE; default: return ServiceState.FREQUENCY_RANGE_UNKNOWN; } } /** * 3GPP TS 38.104 Table 5.4.2.1-1 NR-ARFCN parameters for the global frequency raster. * Formula of NR-ARFCN convert to actual frequency: * Actual frequency(kHz) = (RANGE_OFFSET + GLOBAL_KHZ * (ARFCN - ARFCN_OFFSET)) */ public static int getFrequencyFromNrArfcn(int nrArfcn) { if (nrArfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) { return PhysicalChannelConfig.FREQUENCY_UNKNOWN; } int globalKhz = 0; int rangeOffset = 0; int arfcnOffset = 0; for (NgranArfcnFrequency nrArfcnFrequency : AccessNetworkConstants. NgranArfcnFrequency.values()) { if (nrArfcn >= nrArfcnFrequency.rangeFirst && nrArfcn <= nrArfcnFrequency.rangeLast) { globalKhz = nrArfcnFrequency.globalKhz; rangeOffset = nrArfcnFrequency.rangeOffset; arfcnOffset = nrArfcnFrequency.arfcnOffset; break; } } return rangeOffset + globalKhz * (nrArfcn - arfcnOffset); } /** * Get actual frequency from E-UTRA ARFCN. */ public static int getFrequencyFromEarfcn(int band, int earfcn, boolean isUplink) { int low = 0; int offset = 0; for (EutranBandArfcnFrequency earfcnFrequency : EutranBandArfcnFrequency.values()) { if (band == earfcnFrequency.band) { if (isInEarfcnRange(earfcn, earfcnFrequency, isUplink)) { low = isUplink ? earfcnFrequency.uplinkLowKhz : earfcnFrequency.downlinkLowKhz; offset = isUplink ? earfcnFrequency.uplinkOffset : earfcnFrequency.downlinkOffset; break; } else { Rlog.w(TAG,"Band and the range of EARFCN are not consistent: band = " + band + " ,earfcn = " + earfcn + " ,isUplink = " + isUplink); return INVALID_FREQUENCY; } } } return convertEarfcnToFrequency(low, earfcn, offset); } /** * 3GPP TS 36.101 Table 5.7.3-1 E-UTRA channel numbers. * Formula of E-UTRA ARFCN convert to actual frequency: * Actual frequency(kHz) = (DOWNLINK_LOW + 0.1 * (ARFCN - DOWNLINK_OFFSET)) * FREQUENCY_KHZ * Actual frequency(kHz) = (UPLINK_LOW + 0.1 * (ARFCN - UPLINK_OFFSET)) * FREQUENCY_KHZ */ private static int convertEarfcnToFrequency(int low, int earfcn, int offset) { return low + 100 * (earfcn - offset); } private static boolean isInEarfcnRange(int earfcn, EutranBandArfcnFrequency earfcnFrequency, boolean isUplink) { if (isUplink) { return earfcn >= earfcnFrequency.uplinkOffset && earfcn <= earfcnFrequency.uplinkRange; } else { return earfcn >= earfcnFrequency.downlinkOffset && earfcn <= earfcnFrequency.downlinkRange; } } /** * Get actual frequency from UTRA ARFCN. */ public static int getFrequencyFromUarfcn(int band, int uarfcn, boolean isUplink) { if (uarfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) { return PhysicalChannelConfig.FREQUENCY_UNKNOWN; } int offsetKhz = 0; for (UtranBandArfcnFrequency uarfcnFrequency : AccessNetworkConstants. UtranBandArfcnFrequency.values()) { if (band == uarfcnFrequency.band) { if (isInUarfcnRange(uarfcn, uarfcnFrequency, isUplink)) { offsetKhz = isUplink ? uarfcnFrequency.uplinkOffset : uarfcnFrequency.downlinkOffset; break; } else { Rlog.w(TAG,"Band and the range of UARFCN are not consistent: band = " + band + " ,uarfcn = " + uarfcn + " ,isUplink = " + isUplink); return INVALID_FREQUENCY; } } } if (!UARFCN_NOT_GENERAL_BAND.contains(band)) { return convertUarfcnToFrequency(offsetKhz, uarfcn); } else { return convertUarfcnTddToFrequency(band, uarfcn); } } /** * 3GPP TS 25.101, Table 5.1 UARFCN definition (general). * Formula of UTRA ARFCN convert to actual frequency: * For general bands: * Downlink actual frequency(kHz) = (DOWNLINK_OFFSET + 0.2 * ARFCN) * FREQUENCY_KHZ * Uplink actual frequency(kHz) = (UPLINK_OFFSET + 0.2 * ARFCN) * FREQUENCY_KHZ */ private static int convertUarfcnToFrequency(int offsetKhz, int uarfcn) { return offsetKhz + (200 * uarfcn); } /** * 3GPP TS 25.102, Table 5.2 UTRA Absolute Radio Frequency Channel Number 1.28 Mcps TDD Option. * For FDD bands A, B, C, E, F: * Actual frequency(kHz) = 5 * ARFCN * FREQUENCY_KHZ * For TDD bands D: * Actual frequency(kHz) = (5 * (ARFCN - 2150.1MHz)) * FREQUENCY_KHZ */ private static int convertUarfcnTddToFrequency(int band, int uarfcn) { if (band != UtranBand.BAND_D) { return 5 * uarfcn * FREQUENCY_KHZ; } else { return 5 * ((FREQUENCY_KHZ * uarfcn) - 2150100); } } private static boolean isInUarfcnRange(int uarfcn, UtranBandArfcnFrequency uarfcnFrequency, boolean isUplink) { if (isUplink) { return uarfcn >= uarfcnFrequency.uplinkRangeFirst && uarfcn <= uarfcnFrequency.uplinkRangeLast; } else { if (uarfcnFrequency.downlinkRangeFirst != 0 && uarfcnFrequency.downlinkRangeLast != 0) { return uarfcn >= uarfcnFrequency.downlinkRangeFirst && uarfcn <= uarfcnFrequency.downlinkRangeLast; } else { // BAND_C, BAND_D, BAND_E and BAND_F do not have the downlink range. return true; } } } /** * Get actual frequency from GERAN ARFCN. */ public static int getFrequencyFromArfcn(int band, int arfcn, boolean isUplink) { if (arfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) { return PhysicalChannelConfig.FREQUENCY_UNKNOWN; } int uplinkFrequencyFirst = 0; int arfcnOffset = 0; int downlinkOffset = 0; int frequency = 0; for (GeranBandArfcnFrequency arfcnFrequency : AccessNetworkConstants. GeranBandArfcnFrequency.values()) { if (band == arfcnFrequency.band) { if (arfcn >= arfcnFrequency.arfcnRangeFirst && arfcn <= arfcnFrequency.arfcnRangeLast) { uplinkFrequencyFirst = arfcnFrequency.uplinkFrequencyFirst; downlinkOffset = arfcnFrequency.downlinkOffset; arfcnOffset = arfcnFrequency.arfcnOffset; frequency = convertArfcnToFrequency(arfcn, uplinkFrequencyFirst, arfcnOffset); break; } else { Rlog.w(TAG,"Band and the range of ARFCN are not consistent: band = " + band + " ,arfcn = " + arfcn + " ,isUplink = " + isUplink); return INVALID_FREQUENCY; } } } return isUplink ? frequency : frequency + downlinkOffset; } /** * 3GPP TS 45.005 Table 2-1 Dynamically mapped ARFCN * Formula of Geran ARFCN convert to actual frequency: * Uplink actual frequency(kHz) = * (UPLINK_FREQUENCY_FIRST + 0.2 * (ARFCN - ARFCN_RANGE_FIRST)) * FREQUENCY_KHZ * Downlink actual frequency(kHz) = Uplink actual frequency + 10 */ private static int convertArfcnToFrequency(int arfcn, int uplinkFrequencyFirstKhz, int arfcnOffset) { return uplinkFrequencyFirstKhz + 200 * (arfcn - arfcnOffset); } public static int getFrequencyRangeFromArfcn(int frequency) { if (frequency < FREQUENCY_RANGE_LOW_KHZ) { return ServiceState.FREQUENCY_RANGE_LOW; } else if (frequency < FREQUENCY_RANGE_MID_KHZ && frequency >= FREQUENCY_RANGE_LOW_KHZ) { return ServiceState.FREQUENCY_RANGE_MID; } else if (frequency < FREQUENCY_RANGE_HIGH_KHZ && frequency >= FREQUENCY_RANGE_MID_KHZ) { return ServiceState.FREQUENCY_RANGE_HIGH; } else { return ServiceState.FREQUENCY_RANGE_MMWAVE; } } }