• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package android.telephony;
2 
3 import static android.telephony.ServiceState.DUPLEX_MODE_FDD;
4 import static android.telephony.ServiceState.DUPLEX_MODE_TDD;
5 import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN;
6 
7 import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency;
8 import android.telephony.AccessNetworkConstants.EutranBand;
9 import android.telephony.AccessNetworkConstants.GeranBand;
10 import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency;
11 import android.telephony.AccessNetworkConstants.NgranArfcnFrequency;
12 import android.telephony.AccessNetworkConstants.NgranBands;
13 import android.telephony.AccessNetworkConstants.UtranBand;
14 import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency;
15 import android.telephony.ServiceState.DuplexMode;
16 import android.util.Log;
17 
18 import java.util.Arrays;
19 import java.util.HashSet;
20 import java.util.Set;
21 
22 /**
23  * Utilities to map between radio constants.
24  *
25  * @hide
26  */
27 public class AccessNetworkUtils {
28 
29     // do not instantiate
AccessNetworkUtils()30     private AccessNetworkUtils() {}
31 
32     public static final int INVALID_BAND = -1;
33     public static final int INVALID_FREQUENCY = -1;
34 
35     /** ISO country code of Japan. */
36     private static final String JAPAN_ISO_COUNTRY_CODE = "jp";
37     private static final String TAG = "AccessNetworkUtils";
38 
39     private static final int FREQUENCY_KHZ = 1000;
40     private static final int FREQUENCY_RANGE_LOW_KHZ = 1000000;
41     private static final int FREQUENCY_RANGE_MID_KHZ = 3000000;
42     private static final int FREQUENCY_RANGE_HIGH_KHZ = 6000000;
43 
44     private static final Set<Integer> UARFCN_NOT_GENERAL_BAND;
45     static {
46         UARFCN_NOT_GENERAL_BAND = new HashSet<Integer>();
47         UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_A);
48         UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_B);
49         UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_C);
50         UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_D);
51         UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_E);
52         UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_F);
53     }
54 
55     /**
56      * Gets the duplex mode for the given EUTRAN operating band.
57      *
58      * <p>See 3GPP 36.101 sec 5.5-1 for calculation
59      *
60      * @param band The EUTRAN band number
61      * @return The duplex mode of the given EUTRAN band
62      */
63     @DuplexMode
getDuplexModeForEutranBand(int band)64     public static int getDuplexModeForEutranBand(int band) {
65         if (band == INVALID_BAND) {
66             return DUPLEX_MODE_UNKNOWN;
67         }
68 
69         if (band > EutranBand.BAND_88) {
70             return DUPLEX_MODE_UNKNOWN;
71         } else if (band >= EutranBand.BAND_65) {
72             return DUPLEX_MODE_FDD;
73         } else if (band >= EutranBand.BAND_33) {
74             return DUPLEX_MODE_TDD;
75         } else if (band >= EutranBand.BAND_1) {
76             return DUPLEX_MODE_FDD;
77         }
78 
79         return DUPLEX_MODE_UNKNOWN;
80     }
81 
82     /**
83      * Gets the EUTRAN Operating band for a given downlink EARFCN.
84      *
85      * <p>See 3GPP TS 36.101 clause 5.7.3-1 for calculation.
86      *
87      * @param earfcn The downlink EARFCN
88      * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists
89      */
getOperatingBandForEarfcn(int earfcn)90     public static int getOperatingBandForEarfcn(int earfcn) {
91         if (earfcn > 70645) {
92             return INVALID_BAND;
93         } else if (earfcn >= 70596) {
94             return EutranBand.BAND_88;
95         } else if (earfcn >= 70546) {
96             return EutranBand.BAND_87;
97         } else if (earfcn >= 70366) {
98             return EutranBand.BAND_85;
99         } else if (earfcn > 69465) {
100             return INVALID_BAND;
101         } else if (earfcn >= 69036) {
102             return EutranBand.BAND_74;
103         } else if (earfcn >= 68986) {
104             return EutranBand.BAND_73;
105         } else if (earfcn >= 68936) {
106             return EutranBand.BAND_72;
107         } else if (earfcn >= 68586) {
108             return EutranBand.BAND_71;
109         } else if (earfcn >= 68336) {
110             return EutranBand.BAND_70;
111         } else if (earfcn > 67835) {
112             return INVALID_BAND;
113         } else if (earfcn >= 67536) {
114             return EutranBand.BAND_68;
115         } else if (earfcn >= 67366) {
116             return INVALID_BAND; // band 67 only for CarrierAgg
117         } else if (earfcn >= 66436) {
118             return EutranBand.BAND_66;
119         } else if (earfcn >= 65536) {
120             return EutranBand.BAND_65;
121         } else if (earfcn > 60254) {
122             return INVALID_BAND;
123         } else if (earfcn >= 60140) {
124             return EutranBand.BAND_53;
125         } else if (earfcn >= 59140) {
126             return EutranBand.BAND_52;
127         } else if (earfcn >= 59090) {
128             return EutranBand.BAND_51;
129         } else if (earfcn >= 58240) {
130             return EutranBand.BAND_50;
131         } else if (earfcn >= 56740) {
132             return EutranBand.BAND_49;
133         } else if (earfcn >= 55240) {
134             return EutranBand.BAND_48;
135         } else if (earfcn >= 54540) {
136             return EutranBand.BAND_47;
137         } else if (earfcn >= 46790) {
138             return EutranBand.BAND_46;
139         } else if (earfcn >= 46590) {
140             return EutranBand.BAND_45;
141         } else if (earfcn >= 45590) {
142             return EutranBand.BAND_44;
143         } else if (earfcn >= 43590) {
144             return EutranBand.BAND_43;
145         } else if (earfcn >= 41590) {
146             return EutranBand.BAND_42;
147         } else if (earfcn >= 39650) {
148             return EutranBand.BAND_41;
149         } else if (earfcn >= 38650) {
150             return EutranBand.BAND_40;
151         } else if (earfcn >= 38250) {
152             return EutranBand.BAND_39;
153         } else if (earfcn >= 37750) {
154             return EutranBand.BAND_38;
155         } else if (earfcn >= 37550) {
156             return EutranBand.BAND_37;
157         } else if (earfcn >= 36950) {
158             return EutranBand.BAND_36;
159         } else if (earfcn >= 36350) {
160             return EutranBand.BAND_35;
161         } else if (earfcn >= 36200) {
162             return EutranBand.BAND_34;
163         } else if (earfcn >= 36000) {
164             return EutranBand.BAND_33;
165         } else if (earfcn > 10359) {
166             return INVALID_BAND;
167         } else if (earfcn >= 9920) {
168             return INVALID_BAND; // band 32 only for CarrierAgg
169         } else if (earfcn >= 9870) {
170             return EutranBand.BAND_31;
171         } else if (earfcn >= 9770) {
172             return EutranBand.BAND_30;
173         } else if (earfcn >= 9660) {
174             return INVALID_BAND; // band 29 only for CarrierAgg
175         } else if (earfcn >= 9210) {
176             return EutranBand.BAND_28;
177         } else if (earfcn >= 9040) {
178             return EutranBand.BAND_27;
179         } else if (earfcn >= 8690) {
180             return EutranBand.BAND_26;
181         } else if (earfcn >= 8040) {
182             return EutranBand.BAND_25;
183         } else if (earfcn >= 7700) {
184             return EutranBand.BAND_24;
185         } else if (earfcn >= 7500) {
186             return EutranBand.BAND_23;
187         } else if (earfcn >= 6600) {
188             return EutranBand.BAND_22;
189         } else if (earfcn >= 6450) {
190             return EutranBand.BAND_21;
191         } else if (earfcn >= 6150) {
192             return EutranBand.BAND_20;
193         } else if (earfcn >= 6000) {
194             return EutranBand.BAND_19;
195         } else if (earfcn >= 5850) {
196             return EutranBand.BAND_18;
197         } else if (earfcn >= 5730) {
198             return EutranBand.BAND_17;
199         } else if (earfcn > 5379) {
200             return INVALID_BAND;
201         } else if (earfcn >= 5280) {
202             return EutranBand.BAND_14;
203         } else if (earfcn >= 5180) {
204             return EutranBand.BAND_13;
205         } else if (earfcn >= 5010) {
206             return EutranBand.BAND_12;
207         } else if (earfcn >= 4750) {
208             return EutranBand.BAND_11;
209         } else if (earfcn >= 4150) {
210             return EutranBand.BAND_10;
211         } else if (earfcn >= 3800) {
212             return EutranBand.BAND_9;
213         } else if (earfcn >= 3450) {
214             return EutranBand.BAND_8;
215         } else if (earfcn >= 2750) {
216             return EutranBand.BAND_7;
217         } else if (earfcn >= 2650) {
218             return EutranBand.BAND_6;
219         } else if (earfcn >= 2400) {
220             return EutranBand.BAND_5;
221         } else if (earfcn >= 1950) {
222             return EutranBand.BAND_4;
223         } else if (earfcn >= 1200) {
224             return EutranBand.BAND_3;
225         } else if (earfcn >= 600) {
226             return EutranBand.BAND_2;
227         } else if (earfcn >= 0) {
228             return EutranBand.BAND_1;
229         }
230 
231         return INVALID_BAND;
232     }
233 
234     /**
235      * Gets the GERAN Operating band for a given ARFCN.
236      *
237      * <p>See 3GPP TS 45.005 clause 2 for calculation.
238      *
239      * @param arfcn The ARFCN
240      * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists
241      */
getOperatingBandForArfcn(int arfcn)242     public static int getOperatingBandForArfcn(int arfcn) {
243         if (arfcn >= 0 && arfcn <= 124) {
244             return GeranBand.BAND_E900;
245         } else if (arfcn >= 128 && arfcn <= 251) {
246             return GeranBand.BAND_850;
247         } else if (arfcn >= 259 && arfcn <= 293) {
248             return GeranBand.BAND_450;
249         } else if (arfcn >= 306 && arfcn <= 340) {
250             return GeranBand.BAND_480;
251         } else if (arfcn >= 438 && arfcn <= 511) {
252             return GeranBand.BAND_750;
253         } else if (arfcn >= 512 && arfcn <= 885) {
254             // ARFCN between 512 and 810 are also part of BAND_PCS1900.
255             // Returning BAND_DCS1800 in both cases.
256             return GeranBand.BAND_DCS1800;
257         } else if (arfcn >= 940 && arfcn <= 974) {
258             return GeranBand.BAND_ER900;
259         } else if (arfcn >= 975 && arfcn <= 1023) {
260             return GeranBand.BAND_E900;
261         }
262         return INVALID_BAND;
263     }
264 
265     /**
266      * Gets the UTRAN Operating band for a given downlink UARFCN.
267      *
268      * <p>See 3GPP TS 25.101 clause 5.4.4 for calculation.
269      *
270      * @param uarfcn The downlink UARFCN
271      * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists
272      */
getOperatingBandForUarfcn(int uarfcn)273     public static int getOperatingBandForUarfcn(int uarfcn) {
274         // List of additional bands defined in TS 25.101.
275         int[] addlBand2 = {412, 437, 462, 487, 512, 537, 562, 587, 612, 637, 662, 687};
276         int[] addlBand4 = {1887, 1912, 1937, 1962, 1987, 2012, 2037, 2062, 2087};
277         int[] addlBand5 = {1007, 1012, 1032, 1037, 1062, 1087};
278         int[] addlBand6 = {1037, 1062};
279         int[] addlBand7 =
280                 {2587, 2612, 2637, 2662, 2687, 2712, 2737, 2762, 2787, 2812, 2837, 2862,
281                 2887, 2912};
282         int[] addlBand10 =
283                 {3412, 3437, 3462, 3487, 3512, 3537, 3562, 3587, 3612, 3637, 3662, 3687};
284         int[] addlBand12 = {3932, 3957, 3962, 3987, 3992};
285         int[] addlBand13 = {4067, 4092};
286         int[] addlBand14 = {4167, 4192};
287         int[] addlBand19 = {787, 812, 837};
288         int[] addlBand25 =
289                 {6292, 6317, 6342, 6367, 6392, 6417, 6442, 6467, 6492, 6517, 6542, 6567, 6592};
290         int[] addlBand26 = {5937, 5962, 5987, 5992, 6012, 6017, 6037, 6042, 6062, 6067, 6087};
291 
292         if (uarfcn >= 10562 && uarfcn <= 10838) {
293             return UtranBand.BAND_1;
294         } else if ((uarfcn >= 9662 && uarfcn <= 9938)
295                 || Arrays.binarySearch(addlBand2, uarfcn) >= 0) {
296             return UtranBand.BAND_2;
297         } else if (uarfcn >= 1162 && uarfcn <= 1513) {
298             return UtranBand.BAND_3;
299         } else if ((uarfcn >= 1537 && uarfcn <= 1738)
300                 || Arrays.binarySearch(addlBand4, uarfcn) >= 0) {
301             return UtranBand.BAND_4;
302         } else if (uarfcn >= 4387 && uarfcn <= 4413) {
303             // Band 6 is a subset of band 5. Only Japan uses band 6 and Japan does not have band 5.
304             String country = TelephonyManager.getDefault().getNetworkCountryIso();
305             if (JAPAN_ISO_COUNTRY_CODE.compareToIgnoreCase(country) == 0) {
306                 return UtranBand.BAND_6;
307             } else {
308                 return UtranBand.BAND_5;
309             }
310         } else if ((uarfcn >= 4357 && uarfcn <= 4458)
311                 || Arrays.binarySearch(addlBand5, uarfcn) >= 0) {
312             return UtranBand.BAND_5;
313         } else if (Arrays.binarySearch(addlBand6, uarfcn) >= 0) {
314             return UtranBand.BAND_6;
315         } else if ((uarfcn >= 2237 && uarfcn <= 2563)
316                 || Arrays.binarySearch(addlBand7, uarfcn) >= 0) {
317             return UtranBand.BAND_7;
318         } else if (uarfcn >= 2937 && uarfcn <= 3088) {
319             return UtranBand.BAND_8;
320         } else if (uarfcn >= 9237 && uarfcn <= 9387) {
321             return UtranBand.BAND_9;
322         } else if ((uarfcn >= 3112 && uarfcn <= 3388)
323                 || Arrays.binarySearch(addlBand10, uarfcn) >= 0) {
324             return UtranBand.BAND_10;
325         } else if (uarfcn >= 3712 && uarfcn <= 3787) {
326             return UtranBand.BAND_11;
327         } else if ((uarfcn >= 3842 && uarfcn <= 3903)
328                 || Arrays.binarySearch(addlBand12, uarfcn) >= 0) {
329             return UtranBand.BAND_12;
330         } else if ((uarfcn >= 4017 && uarfcn <= 4043)
331                 || Arrays.binarySearch(addlBand13, uarfcn) >= 0) {
332             return UtranBand.BAND_13;
333         } else if ((uarfcn >= 4117 && uarfcn <= 4143)
334                 || Arrays.binarySearch(addlBand14, uarfcn) >= 0) {
335             return UtranBand.BAND_14;
336         } else if ((uarfcn >= 712 && uarfcn <= 763)
337                 || Arrays.binarySearch(addlBand19, uarfcn) >= 0) {
338             return UtranBand.BAND_19;
339         } else if (uarfcn >= 4512 && uarfcn <= 4638) {
340             return UtranBand.BAND_20;
341         } else if (uarfcn >= 862 && uarfcn <= 912) {
342             return UtranBand.BAND_21;
343         } else if (uarfcn >= 4662 && uarfcn <= 5038) {
344             return UtranBand.BAND_22;
345         } else if ((uarfcn >= 5112 && uarfcn <= 5413)
346                 || Arrays.binarySearch(addlBand25, uarfcn) >= 0) {
347             return UtranBand.BAND_25;
348         } else if ((uarfcn >= 5762 && uarfcn <= 5913)
349                 || Arrays.binarySearch(addlBand26, uarfcn) >= 0) {
350             return UtranBand.BAND_26;
351         }
352         return INVALID_BAND;
353     }
354 
355     /**
356      * Get geran bands from {@link PhysicalChannelConfig#getBand()}
357      */
getFrequencyRangeGroupFromGeranBand(@eranBand.GeranBands int band)358     public static int getFrequencyRangeGroupFromGeranBand(@GeranBand.GeranBands int band) {
359         switch (band) {
360             case GeranBand.BAND_T380:
361             case GeranBand.BAND_T410:
362             case GeranBand.BAND_450:
363             case GeranBand.BAND_480:
364             case GeranBand.BAND_710:
365             case GeranBand.BAND_750:
366             case GeranBand.BAND_T810:
367             case GeranBand.BAND_850:
368             case GeranBand.BAND_P900:
369             case GeranBand.BAND_E900:
370             case GeranBand.BAND_R900:
371             case GeranBand.BAND_ER900:
372                 return ServiceState.FREQUENCY_RANGE_LOW;
373             case GeranBand.BAND_DCS1800:
374             case GeranBand.BAND_PCS1900:
375                 return ServiceState.FREQUENCY_RANGE_MID;
376             default:
377                 return ServiceState.FREQUENCY_RANGE_UNKNOWN;
378         }
379     }
380 
381     /**
382      * Get utran bands from {@link PhysicalChannelConfig#getBand()}
383      */
getFrequencyRangeGroupFromUtranBand(@tranBand.UtranBands int band)384     public static int getFrequencyRangeGroupFromUtranBand(@UtranBand.UtranBands int band) {
385         switch (band) {
386             case UtranBand.BAND_5:
387             case UtranBand.BAND_6:
388             case UtranBand.BAND_8:
389             case UtranBand.BAND_12:
390             case UtranBand.BAND_13:
391             case UtranBand.BAND_14:
392             case UtranBand.BAND_19:
393             case UtranBand.BAND_20:
394             case UtranBand.BAND_26:
395                 return ServiceState.FREQUENCY_RANGE_LOW;
396             case UtranBand.BAND_1:
397             case UtranBand.BAND_2:
398             case UtranBand.BAND_3:
399             case UtranBand.BAND_4:
400             case UtranBand.BAND_7:
401             case UtranBand.BAND_9:
402             case UtranBand.BAND_10:
403             case UtranBand.BAND_11:
404             case UtranBand.BAND_21:
405             case UtranBand.BAND_25:
406             case UtranBand.BAND_A:
407             case UtranBand.BAND_B:
408             case UtranBand.BAND_C:
409             case UtranBand.BAND_D:
410             case UtranBand.BAND_E:
411             case UtranBand.BAND_F:
412                 return ServiceState.FREQUENCY_RANGE_MID;
413             case UtranBand.BAND_22:
414                 return ServiceState.FREQUENCY_RANGE_HIGH;
415             default:
416                 return ServiceState.FREQUENCY_RANGE_UNKNOWN;
417         }
418     }
419 
420     /**
421      * Get eutran bands from {@link PhysicalChannelConfig#getBand()}
422      * 3GPP TS 36.101 Table 5.5 EUTRA operating bands
423      */
getFrequencyRangeGroupFromEutranBand(@utranBand.EutranBands int band)424     public static int getFrequencyRangeGroupFromEutranBand(@EutranBand.EutranBands int band) {
425         switch (band) {
426             case EutranBand.BAND_5:
427             case EutranBand.BAND_6:
428             case EutranBand.BAND_8:
429             case EutranBand.BAND_12:
430             case EutranBand.BAND_13:
431             case EutranBand.BAND_14:
432             case EutranBand.BAND_17:
433             case EutranBand.BAND_18:
434             case EutranBand.BAND_19:
435             case EutranBand.BAND_20:
436             case EutranBand.BAND_26:
437             case EutranBand.BAND_27:
438             case EutranBand.BAND_28:
439             case EutranBand.BAND_31:
440             case EutranBand.BAND_44:
441             case EutranBand.BAND_50:
442             case EutranBand.BAND_51:
443             case EutranBand.BAND_68:
444             case EutranBand.BAND_71:
445             case EutranBand.BAND_72:
446             case EutranBand.BAND_73:
447             case EutranBand.BAND_85:
448             case EutranBand.BAND_87:
449             case EutranBand.BAND_88:
450                 return ServiceState.FREQUENCY_RANGE_LOW;
451             case EutranBand.BAND_1:
452             case EutranBand.BAND_2:
453             case EutranBand.BAND_3:
454             case EutranBand.BAND_4:
455             case EutranBand.BAND_7:
456             case EutranBand.BAND_9:
457             case EutranBand.BAND_10:
458             case EutranBand.BAND_11:
459             case EutranBand.BAND_21:
460             case EutranBand.BAND_23:
461             case EutranBand.BAND_24:
462             case EutranBand.BAND_25:
463             case EutranBand.BAND_30:
464             case EutranBand.BAND_33:
465             case EutranBand.BAND_34:
466             case EutranBand.BAND_35:
467             case EutranBand.BAND_36:
468             case EutranBand.BAND_37:
469             case EutranBand.BAND_38:
470             case EutranBand.BAND_39:
471             case EutranBand.BAND_40:
472             case EutranBand.BAND_41:
473             case EutranBand.BAND_45:
474             case EutranBand.BAND_53:
475             case EutranBand.BAND_65:
476             case EutranBand.BAND_66:
477             case EutranBand.BAND_70:
478             case EutranBand.BAND_74:
479                 return ServiceState.FREQUENCY_RANGE_MID;
480             case EutranBand.BAND_22:
481             case EutranBand.BAND_42:
482             case EutranBand.BAND_43:
483             case EutranBand.BAND_46:
484             case EutranBand.BAND_47:
485             case EutranBand.BAND_48:
486             case EutranBand.BAND_49:
487             case EutranBand.BAND_52:
488                 return ServiceState.FREQUENCY_RANGE_HIGH;
489             default:
490                 return ServiceState.FREQUENCY_RANGE_UNKNOWN;
491         }
492     }
493 
494     /**
495      * Get ngran band from {@link PhysicalChannelConfig#getBand()}
496      * 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1
497      * 3GPP TS 38.104 Table 5.2-2 NR operating bands in FR2
498      */
getFrequencyRangeGroupFromNrBand(@granBands.NgranBand int band)499     public static int getFrequencyRangeGroupFromNrBand(@NgranBands.NgranBand int band) {
500         switch (band) {
501             case NgranBands.BAND_5:
502             case NgranBands.BAND_8:
503             case NgranBands.BAND_12:
504             case NgranBands.BAND_14:
505             case NgranBands.BAND_18:
506             case NgranBands.BAND_20:
507             case NgranBands.BAND_26:
508             case NgranBands.BAND_28:
509             case NgranBands.BAND_29:
510             case NgranBands.BAND_71:
511             case NgranBands.BAND_81:
512             case NgranBands.BAND_82:
513             case NgranBands.BAND_83:
514             case NgranBands.BAND_89:
515                 return ServiceState.FREQUENCY_RANGE_LOW;
516             case NgranBands.BAND_1:
517             case NgranBands.BAND_2:
518             case NgranBands.BAND_3:
519             case NgranBands.BAND_7:
520             case NgranBands.BAND_25:
521             case NgranBands.BAND_30:
522             case NgranBands.BAND_34:
523             case NgranBands.BAND_38:
524             case NgranBands.BAND_39:
525             case NgranBands.BAND_40:
526             case NgranBands.BAND_41:
527             case NgranBands.BAND_50:
528             case NgranBands.BAND_51:
529             case NgranBands.BAND_53:
530             case NgranBands.BAND_65:
531             case NgranBands.BAND_66:
532             case NgranBands.BAND_70:
533             case NgranBands.BAND_74:
534             case NgranBands.BAND_75:
535             case NgranBands.BAND_76:
536             case NgranBands.BAND_80:
537             case NgranBands.BAND_84:
538             case NgranBands.BAND_86:
539             case NgranBands.BAND_90:
540             case NgranBands.BAND_91:
541             case NgranBands.BAND_92:
542             case NgranBands.BAND_93:
543             case NgranBands.BAND_94:
544             case NgranBands.BAND_95:
545                 return ServiceState.FREQUENCY_RANGE_MID;
546             case NgranBands.BAND_46:
547             case NgranBands.BAND_48:
548             case NgranBands.BAND_77:
549             case NgranBands.BAND_78:
550             case NgranBands.BAND_79:
551                 return ServiceState.FREQUENCY_RANGE_HIGH;
552             case NgranBands.BAND_96:
553             case NgranBands.BAND_257:
554             case NgranBands.BAND_258:
555             case NgranBands.BAND_260:
556             case NgranBands.BAND_261:
557                 return ServiceState.FREQUENCY_RANGE_MMWAVE;
558             default:
559                 return ServiceState.FREQUENCY_RANGE_UNKNOWN;
560         }
561     }
562 
563     /**
564      * 3GPP TS 38.104 Table 5.4.2.1-1 NR-ARFCN parameters for the global frequency raster.
565      * Formula of NR-ARFCN convert to actual frequency:
566      * Actual frequency(kHz) = (RANGE_OFFSET + GLOBAL_KHZ * (ARFCN - ARFCN_OFFSET))
567      */
getFrequencyFromNrArfcn(int nrArfcn)568     public static int getFrequencyFromNrArfcn(int nrArfcn) {
569 
570         if (nrArfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) {
571             return PhysicalChannelConfig.FREQUENCY_UNKNOWN;
572         }
573 
574         int globalKhz = 0;
575         int rangeOffset = 0;
576         int arfcnOffset = 0;
577         for (NgranArfcnFrequency nrArfcnFrequency : AccessNetworkConstants.
578                 NgranArfcnFrequency.values()) {
579             if (nrArfcn >= nrArfcnFrequency.rangeFirst
580                     && nrArfcn <= nrArfcnFrequency.rangeLast) {
581                 globalKhz = nrArfcnFrequency.globalKhz;
582                 rangeOffset = nrArfcnFrequency.rangeOffset;
583                 arfcnOffset = nrArfcnFrequency.arfcnOffset;
584                 break;
585             }
586         }
587         return rangeOffset + globalKhz * (nrArfcn - arfcnOffset);
588     }
589 
590     /**
591      * Get actual frequency from E-UTRA ARFCN.
592      */
getFrequencyFromEarfcn(int band, int earfcn, boolean isUplink)593     public static int getFrequencyFromEarfcn(int band, int earfcn, boolean isUplink) {
594 
595         int low = 0;
596         int offset = 0;
597         for (EutranBandArfcnFrequency earfcnFrequency : EutranBandArfcnFrequency.values()) {
598             if (band == earfcnFrequency.band) {
599                 if (isInEarfcnRange(earfcn, earfcnFrequency, isUplink)) {
600                     low = isUplink ? earfcnFrequency.uplinkLowKhz : earfcnFrequency.downlinkLowKhz;
601                     offset = isUplink ? earfcnFrequency.uplinkOffset
602                             : earfcnFrequency.downlinkOffset;
603                     break;
604                 } else {
605                     Rlog.w(TAG,"Band and the range of EARFCN are not consistent: band = " + band
606                             + " ,earfcn = " + earfcn + " ,isUplink = " + isUplink);
607                     return INVALID_FREQUENCY;
608                 }
609             }
610         }
611         return convertEarfcnToFrequency(low, earfcn, offset);
612     }
613 
614     /**
615      * 3GPP TS 36.101 Table 5.7.3-1 E-UTRA channel numbers.
616      * Formula of E-UTRA ARFCN convert to actual frequency:
617      * Actual frequency(kHz) = (DOWNLINK_LOW + 0.1 * (ARFCN - DOWNLINK_OFFSET)) * FREQUENCY_KHZ
618      * Actual frequency(kHz) = (UPLINK_LOW + 0.1 * (ARFCN - UPLINK_OFFSET)) * FREQUENCY_KHZ
619      */
convertEarfcnToFrequency(int low, int earfcn, int offset)620     private static int convertEarfcnToFrequency(int low, int earfcn, int offset) {
621         return low + 100 * (earfcn - offset);
622     }
623 
isInEarfcnRange(int earfcn, EutranBandArfcnFrequency earfcnFrequency, boolean isUplink)624     private static boolean isInEarfcnRange(int earfcn, EutranBandArfcnFrequency earfcnFrequency,
625             boolean isUplink) {
626         if (isUplink) {
627             return earfcn >= earfcnFrequency.uplinkOffset && earfcn <= earfcnFrequency.uplinkRange;
628         } else {
629             return earfcn >= earfcnFrequency.downlinkOffset
630                     && earfcn <= earfcnFrequency.downlinkRange;
631         }
632     }
633 
634     /**
635      * Get actual frequency from UTRA ARFCN.
636      */
getFrequencyFromUarfcn(int band, int uarfcn, boolean isUplink)637     public static int getFrequencyFromUarfcn(int band, int uarfcn, boolean isUplink) {
638 
639         if (uarfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) {
640             return PhysicalChannelConfig.FREQUENCY_UNKNOWN;
641         }
642 
643         int offsetKhz = 0;
644         for (UtranBandArfcnFrequency uarfcnFrequency : AccessNetworkConstants.
645                 UtranBandArfcnFrequency.values()) {
646             if (band == uarfcnFrequency.band) {
647                 if (isInUarfcnRange(uarfcn, uarfcnFrequency, isUplink)) {
648                     offsetKhz = isUplink ? uarfcnFrequency.uplinkOffset
649                             : uarfcnFrequency.downlinkOffset;
650                     break;
651                 } else {
652                     Rlog.w(TAG,"Band and the range of UARFCN are not consistent: band = " + band
653                             + " ,uarfcn = " + uarfcn + " ,isUplink = " + isUplink);
654                     return INVALID_FREQUENCY;
655                 }
656             }
657         }
658 
659         if (!UARFCN_NOT_GENERAL_BAND.contains(band)) {
660             return convertUarfcnToFrequency(offsetKhz, uarfcn);
661         } else {
662             return convertUarfcnTddToFrequency(band, uarfcn);
663         }
664     }
665 
666     /**
667      * 3GPP TS 25.101, Table 5.1 UARFCN definition (general).
668      * Formula of UTRA ARFCN convert to actual frequency:
669      * For general bands:
670      * Downlink actual frequency(kHz) = (DOWNLINK_OFFSET + 0.2 * ARFCN) * FREQUENCY_KHZ
671      * Uplink actual frequency(kHz) = (UPLINK_OFFSET + 0.2 * ARFCN) * FREQUENCY_KHZ
672      */
convertUarfcnToFrequency(int offsetKhz, int uarfcn)673     private static int convertUarfcnToFrequency(int offsetKhz, int uarfcn) {
674         return offsetKhz + (200 * uarfcn);
675     }
676 
677     /**
678      * 3GPP TS 25.102, Table 5.2 UTRA Absolute Radio Frequency Channel Number 1.28 Mcps TDD Option.
679      * For FDD bands A, B, C, E, F:
680      * Actual frequency(kHz) =  5 * ARFCN * FREQUENCY_KHZ
681      * For TDD bands D:
682      * Actual frequency(kHz) =  (5 * (ARFCN - 2150.1MHz)) * FREQUENCY_KHZ
683      */
convertUarfcnTddToFrequency(int band, int uarfcn)684     private static int convertUarfcnTddToFrequency(int band, int uarfcn) {
685         if (band != UtranBand.BAND_D) {
686             return 5 * uarfcn * FREQUENCY_KHZ;
687         } else {
688             return 5 * ((FREQUENCY_KHZ * uarfcn) - 2150100);
689         }
690     }
691 
isInUarfcnRange(int uarfcn, UtranBandArfcnFrequency uarfcnFrequency, boolean isUplink)692     private static boolean isInUarfcnRange(int uarfcn, UtranBandArfcnFrequency uarfcnFrequency,
693                                            boolean isUplink) {
694         if (isUplink) {
695             return uarfcn >= uarfcnFrequency.uplinkRangeFirst
696                     && uarfcn <= uarfcnFrequency.uplinkRangeLast;
697         } else {
698             if (uarfcnFrequency.downlinkRangeFirst != 0 && uarfcnFrequency.downlinkRangeLast != 0) {
699                 return uarfcn >= uarfcnFrequency.downlinkRangeFirst
700                         && uarfcn <= uarfcnFrequency.downlinkRangeLast;
701             } else {
702                 // BAND_C, BAND_D, BAND_E and BAND_F do not have the downlink range.
703                 return true;
704             }
705         }
706     }
707 
708     /**
709      * Get actual frequency from GERAN ARFCN.
710      */
getFrequencyFromArfcn(int band, int arfcn, boolean isUplink)711     public static int getFrequencyFromArfcn(int band, int arfcn, boolean isUplink) {
712 
713         if (arfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) {
714             return PhysicalChannelConfig.FREQUENCY_UNKNOWN;
715         }
716 
717         int uplinkFrequencyFirst = 0;
718         int arfcnOffset = 0;
719         int downlinkOffset = 0;
720         int frequency = 0;
721         for (GeranBandArfcnFrequency arfcnFrequency : AccessNetworkConstants.
722                 GeranBandArfcnFrequency.values()) {
723             if (band == arfcnFrequency.band) {
724                 if (arfcn >= arfcnFrequency.arfcnRangeFirst
725                         && arfcn <= arfcnFrequency.arfcnRangeLast) {
726                     uplinkFrequencyFirst = arfcnFrequency.uplinkFrequencyFirst;
727                     downlinkOffset = arfcnFrequency.downlinkOffset;
728                     arfcnOffset = arfcnFrequency.arfcnOffset;
729                     frequency = convertArfcnToFrequency(arfcn, uplinkFrequencyFirst,
730                             arfcnOffset);
731                     break;
732                 } else {
733                     Rlog.w(TAG,"Band and the range of ARFCN are not consistent: band = " + band
734                             + " ,arfcn = " + arfcn + " ,isUplink = " + isUplink);
735                     return INVALID_FREQUENCY;
736                 }
737             }
738         }
739 
740         return isUplink ? frequency : frequency + downlinkOffset;
741     }
742 
743     /**
744      * 3GPP TS 45.005 Table 2-1 Dynamically mapped ARFCN
745      * Formula of Geran ARFCN convert to actual frequency:
746      * Uplink actual frequency(kHz) =
747      *      (UPLINK_FREQUENCY_FIRST + 0.2 * (ARFCN - ARFCN_RANGE_FIRST)) * FREQUENCY_KHZ
748      * Downlink actual frequency(kHz) = Uplink actual frequency + 10
749      */
convertArfcnToFrequency(int arfcn, int uplinkFrequencyFirstKhz, int arfcnOffset)750     private static int convertArfcnToFrequency(int arfcn, int uplinkFrequencyFirstKhz,
751             int arfcnOffset) {
752         return uplinkFrequencyFirstKhz + 200 * (arfcn - arfcnOffset);
753     }
754 
getFrequencyRangeFromArfcn(int frequency)755     public static int getFrequencyRangeFromArfcn(int frequency) {
756         if (frequency < FREQUENCY_RANGE_LOW_KHZ) {
757             return ServiceState.FREQUENCY_RANGE_LOW;
758         } else if (frequency < FREQUENCY_RANGE_MID_KHZ
759                 && frequency >= FREQUENCY_RANGE_LOW_KHZ) {
760             return ServiceState.FREQUENCY_RANGE_MID;
761         } else if (frequency < FREQUENCY_RANGE_HIGH_KHZ
762                 && frequency >= FREQUENCY_RANGE_MID_KHZ) {
763             return ServiceState.FREQUENCY_RANGE_HIGH;
764         } else {
765             return ServiceState.FREQUENCY_RANGE_MMWAVE;
766         }
767     }
768 }
769