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