• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.os.AsyncResult;
26 import android.os.Message;
27 import android.os.PersistableBundle;
28 import android.os.PowerManager;
29 import android.telephony.AccessNetworkConstants;
30 import android.telephony.Annotation;
31 import android.telephony.CarrierConfigManager;
32 import android.telephony.CellInfo;
33 import android.telephony.NetworkRegistrationInfo;
34 import android.telephony.PhysicalChannelConfig;
35 import android.telephony.ServiceState;
36 import android.telephony.TelephonyDisplayInfo;
37 import android.telephony.TelephonyManager;
38 import android.telephony.data.DataCallResponse;
39 import android.telephony.data.DataCallResponse.LinkStatus;
40 import android.text.TextUtils;
41 
42 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
43 import com.android.internal.telephony.data.DataUtils;
44 import com.android.internal.util.IState;
45 import com.android.internal.util.IndentingPrintWriter;
46 import com.android.internal.util.State;
47 import com.android.internal.util.StateMachine;
48 import com.android.telephony.Rlog;
49 
50 import java.io.FileDescriptor;
51 import java.io.PrintWriter;
52 import java.util.ArrayList;
53 import java.util.Arrays;
54 import java.util.HashMap;
55 import java.util.HashSet;
56 import java.util.List;
57 import java.util.Locale;
58 import java.util.Map;
59 import java.util.Set;
60 import java.util.regex.Matcher;
61 import java.util.regex.Pattern;
62 import java.util.stream.IntStream;
63 
64 /**
65  * The NetworkTypeController evaluates the override network type of {@link TelephonyDisplayInfo}
66  * and sends it to {@link DisplayInfoController}. The override network type can replace the signal
67  * icon displayed on the status bar. It is affected by changes in data RAT, NR state, NR frequency,
68  * data activity, physical channel config, and carrier configurations. Based on carrier configs,
69  * NetworkTypeController also allows timers between various 5G states to prevent flickering.
70  */
71 public class NetworkTypeController extends StateMachine {
72     private static final boolean DBG = true;
73     private static final String TAG = "NetworkTypeController";
74     private static final String ICON_5G = "5g";
75     private static final String ICON_5G_PLUS = "5g_plus";
76     private static final String STATE_CONNECTED_NR_ADVANCED = "connected_mmwave";
77     private static final String STATE_CONNECTED = "connected";
78     private static final String STATE_NOT_RESTRICTED_RRC_IDLE = "not_restricted_rrc_idle";
79     private static final String STATE_NOT_RESTRICTED_RRC_CON = "not_restricted_rrc_con";
80     private static final String STATE_RESTRICTED = "restricted";
81     private static final String STATE_ANY = "any";
82     private static final String STATE_LEGACY = "legacy";
83     private static final String[] ALL_STATES = {STATE_CONNECTED_NR_ADVANCED, STATE_CONNECTED,
84             STATE_NOT_RESTRICTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_CON, STATE_RESTRICTED,
85             STATE_LEGACY };
86 
87     /** Stop all timers and go to current state. */
88     public static final int EVENT_UPDATE = 0;
89     /** Quit after processing all existing messages. */
90     private static final int EVENT_QUIT = 1;
91     /** Initialize all events. */
92     private static final int EVENT_INITIALIZE = 2;
93     /** Event for service state changed (data rat, bandwidth, NR state, NR frequency, etc). */
94     private static final int EVENT_SERVICE_STATE_CHANGED = 3;
95     /** Event for physical link status changed. */
96     private static final int EVENT_PHYSICAL_LINK_STATUS_CHANGED = 4;
97     /** Event for physical channel config indications turned on/off. */
98     private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED = 5;
99     /** Event for carrier configs changed. */
100     private static final int EVENT_CARRIER_CONFIG_CHANGED = 6;
101     /** Event for primary timer expired. If a secondary timer exists, it will begin afterwards. */
102     private static final int EVENT_PRIMARY_TIMER_EXPIRED = 7;
103     /** Event for secondary timer expired. */
104     private static final int EVENT_SECONDARY_TIMER_EXPIRED = 8;
105     /** Event for radio off or unavailable. */
106     private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 9;
107     /** Event for preferred network mode changed. */
108     private static final int EVENT_PREFERRED_NETWORK_MODE_CHANGED = 10;
109     /** Event for physical channel configs changed. */
110     private static final int EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED = 11;
111     /** Event for device idle mode changed, when device goes to deep sleep and pauses all timers. */
112     private static final int EVENT_DEVICE_IDLE_MODE_CHANGED = 12;
113 
114     private static final String[] sEvents = new String[EVENT_DEVICE_IDLE_MODE_CHANGED + 1];
115     static {
116         sEvents[EVENT_UPDATE] = "EVENT_UPDATE";
117         sEvents[EVENT_QUIT] = "EVENT_QUIT";
118         sEvents[EVENT_SERVICE_STATE_CHANGED] = "EVENT_SERVICE_STATE_CHANGED";
119         sEvents[EVENT_PHYSICAL_LINK_STATUS_CHANGED] = "EVENT_PHYSICAL_LINK_STATUS_CHANGED";
120         sEvents[EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED] =
121                 "EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED";
122         sEvents[EVENT_CARRIER_CONFIG_CHANGED] = "EVENT_CARRIER_CONFIG_CHANGED";
123         sEvents[EVENT_PRIMARY_TIMER_EXPIRED] = "EVENT_PRIMARY_TIMER_EXPIRED";
124         sEvents[EVENT_SECONDARY_TIMER_EXPIRED] = "EVENT_SECONDARY_TIMER_EXPIRED";
125         sEvents[EVENT_RADIO_OFF_OR_UNAVAILABLE] = "EVENT_RADIO_OFF_OR_UNAVAILABLE";
126         sEvents[EVENT_PREFERRED_NETWORK_MODE_CHANGED] = "EVENT_PREFERRED_NETWORK_MODE_CHANGED";
127         sEvents[EVENT_INITIALIZE] = "EVENT_INITIALIZE";
128         sEvents[EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED] = "EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED";
129         sEvents[EVENT_DEVICE_IDLE_MODE_CHANGED] = "EVENT_DEVICE_IDLE_MODE_CHANGED";
130     }
131 
132     @NonNull private final Phone mPhone;
133     @NonNull private final DisplayInfoController mDisplayInfoController;
134     @NonNull private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
135         @Override
136         public void onReceive(Context context, Intent intent) {
137             switch (intent.getAction()) {
138                 case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
139                     sendMessage(EVENT_DEVICE_IDLE_MODE_CHANGED);
140                     break;
141             }
142         }
143     };
144 
145     @NonNull private final CarrierConfigManager.CarrierConfigChangeListener
146             mCarrierConfigChangeListener =
147             new CarrierConfigManager.CarrierConfigChangeListener() {
148                 @Override
149                 public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId,
150                         int specificCarrierId) {
151                     // CarrierConfigChangeListener wouldn't send notification on device unlock
152                     if (slotIndex == mPhone.getPhoneId()) {
153                         sendMessage(EVENT_CARRIER_CONFIG_CHANGED);
154                     }
155                 }
156             };
157 
158     @NonNull private Map<String, OverrideTimerRule> mOverrideTimerRules = new HashMap<>();
159     @NonNull private String mLteEnhancedPattern = "";
160     @Annotation.OverrideNetworkType private int mOverrideNetworkType;
161     private boolean mIsPhysicalChannelConfigOn;
162     private boolean mIsPrimaryTimerActive;
163     private boolean mIsSecondaryTimerActive;
164     private boolean mIsTimerResetEnabledForLegacyStateRrcIdle;
165     private int mLtePlusThresholdBandwidth;
166     private int mNrAdvancedThresholdBandwidth;
167     private boolean mIncludeLteForNrAdvancedThresholdBandwidth;
168     private boolean mRatchetPccFieldsForSameAnchorNrCell;
169     @NonNull private final Set<Integer> mAdditionalNrAdvancedBands = new HashSet<>();
170     @NonNull private String mPrimaryTimerState;
171     @NonNull private String mSecondaryTimerState;
172     @NonNull private String mPreviousState;
173     @LinkStatus private int mPhysicalLinkStatus;
174     private boolean mIsPhysicalChannelConfig16Supported;
175     private boolean mIsNrAdvancedAllowedByPco = false;
176     private int mNrAdvancedCapablePcoId = 0;
177     private boolean mIsUsingUserDataForRrcDetection = false;
178     private boolean mEnableNrAdvancedWhileRoaming = true;
179     private boolean mIsDeviceIdleMode = false;
180 
181     @Nullable private DataNetworkControllerCallback mNrAdvancedCapableByPcoChangedCallback = null;
182     @Nullable private DataNetworkControllerCallback mNrPhysicalLinkStatusChangedCallback = null;
183 
184     // Cached copies below to prevent race conditions
185     @NonNull private ServiceState mServiceState;
186     @Nullable private List<PhysicalChannelConfig> mPhysicalChannelConfigs;
187 
188     // Ratchet physical channel config fields to prevent 5G/5G+ flickering
189     @NonNull private Set<Integer> mRatchetedNrBands = new HashSet<>();
190     private int mRatchetedNrBandwidths = 0;
191     private int mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
192 
193     /**
194      * NetworkTypeController constructor.
195      *
196      * @param phone Phone object.
197      * @param displayInfoController DisplayInfoController to send override network types to.
198      */
NetworkTypeController(Phone phone, DisplayInfoController displayInfoController)199     public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController) {
200         super(TAG, displayInfoController);
201         mPhone = phone;
202         mDisplayInfoController = displayInfoController;
203         mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
204         mIsPhysicalChannelConfigOn = true;
205         mPrimaryTimerState = "";
206         mSecondaryTimerState = "";
207         mPreviousState = "";
208         DefaultState defaultState = new DefaultState();
209         addState(defaultState);
210         addState(mLegacyState, defaultState);
211         addState(mIdleState, defaultState);
212         addState(mLteConnectedState, defaultState);
213         addState(mNrConnectedState, defaultState);
214         addState(mNrConnectedAdvancedState, defaultState);
215         setInitialState(defaultState);
216         start();
217 
218         mServiceState = mPhone.getServiceStateTracker().getServiceState();
219         mPhysicalChannelConfigs = mPhone.getServiceStateTracker().getPhysicalChannelConfigList();
220 
221         sendMessage(EVENT_INITIALIZE);
222     }
223 
224     /**
225      * @return The current override network type, used to create TelephonyDisplayInfo in
226      * DisplayInfoController.
227      */
getOverrideNetworkType()228     public @Annotation.OverrideNetworkType int getOverrideNetworkType() {
229         return mOverrideNetworkType;
230     }
231 
232     /**
233      * @return The current data network type, used to create TelephonyDisplayInfo in
234      * DisplayInfoController.
235      */
getDataNetworkType()236     public @Annotation.NetworkType int getDataNetworkType() {
237         NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo(
238                 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
239         return nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN
240                 : nri.getAccessNetworkTechnology();
241     }
242 
243     /**
244      * @return {@code true} if either the primary or secondary 5G icon timers are active,
245      * and {@code false} if neither are.
246      */
areAnyTimersActive()247     public boolean areAnyTimersActive() {
248         return mIsPrimaryTimerActive || mIsSecondaryTimerActive;
249     }
250 
registerForAllEvents()251     private void registerForAllEvents() {
252         mPhone.registerForRadioOffOrNotAvailable(getHandler(),
253                 EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
254         mPhone.registerForPreferredNetworkTypeChanged(getHandler(),
255                 EVENT_PREFERRED_NETWORK_MODE_CHANGED, null);
256         mPhone.registerForPhysicalChannelConfig(getHandler(),
257                 EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED, null);
258         mPhone.getServiceStateTracker().registerForServiceStateChanged(getHandler(),
259                 EVENT_SERVICE_STATE_CHANGED, null);
260         mIsPhysicalChannelConfig16Supported = mPhone.getContext().getSystemService(
261                 TelephonyManager.class).isRadioInterfaceCapabilitySupported(
262                 TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
263         mPhone.getDeviceStateMonitor().registerForPhysicalChannelConfigNotifChanged(getHandler(),
264                 EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED, null);
265         IntentFilter filter = new IntentFilter();
266         filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
267         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
268         CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
269         ccm.registerCarrierConfigChangeListener(Runnable::run, mCarrierConfigChangeListener);
270     }
271 
unRegisterForAllEvents()272     private void unRegisterForAllEvents() {
273         mPhone.unregisterForRadioOffOrNotAvailable(getHandler());
274         mPhone.unregisterForPreferredNetworkTypeChanged(getHandler());
275         mPhone.getServiceStateTracker().unregisterForServiceStateChanged(getHandler());
276         mPhone.getDeviceStateMonitor().unregisterForPhysicalChannelConfigNotifChanged(getHandler());
277         mPhone.getContext().unregisterReceiver(mIntentReceiver);
278         CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
279         if (mCarrierConfigChangeListener != null) {
280             ccm.unregisterCarrierConfigChangeListener(mCarrierConfigChangeListener);
281         }
282     }
283 
parseCarrierConfigs()284     private void parseCarrierConfigs() {
285         PersistableBundle config = CarrierConfigManager.getDefaultConfig();
286         CarrierConfigManager configManager =
287                 mPhone.getContext().getSystemService(CarrierConfigManager.class);
288         if (configManager != null) {
289             PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
290             if (b != null) {
291                 config = b;
292             }
293         }
294         mLteEnhancedPattern = config.getString(
295                 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
296         mIsTimerResetEnabledForLegacyStateRrcIdle = config.getBoolean(
297                 CarrierConfigManager.KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL);
298         mLtePlusThresholdBandwidth = config.getInt(
299                 CarrierConfigManager.KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT);
300         mNrAdvancedThresholdBandwidth = config.getInt(
301                 CarrierConfigManager.KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT);
302         mIncludeLteForNrAdvancedThresholdBandwidth = config.getBoolean(
303                 CarrierConfigManager.KEY_INCLUDE_LTE_FOR_NR_ADVANCED_THRESHOLD_BANDWIDTH_BOOL);
304         mRatchetPccFieldsForSameAnchorNrCell = config.getBoolean(
305                 CarrierConfigManager.KEY_RATCHET_NR_ADVANCED_BANDWIDTH_IF_RRC_IDLE_BOOL);
306         mEnableNrAdvancedWhileRoaming = config.getBoolean(
307                 CarrierConfigManager.KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL);
308         mAdditionalNrAdvancedBands.clear();
309         int[] additionalNrAdvancedBands = config.getIntArray(
310                 CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY);
311         if (additionalNrAdvancedBands != null) {
312             Arrays.stream(additionalNrAdvancedBands).forEach(mAdditionalNrAdvancedBands::add);
313         }
314         mNrAdvancedCapablePcoId = config.getInt(
315                 CarrierConfigManager.KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT);
316         if (mNrAdvancedCapablePcoId > 0 && mNrAdvancedCapableByPcoChangedCallback == null) {
317             mNrAdvancedCapableByPcoChangedCallback =
318                     new DataNetworkControllerCallback(getHandler()::post) {
319                         @Override
320                         public void onNrAdvancedCapableByPcoChanged(boolean nrAdvancedCapable) {
321                             log("mIsNrAdvancedAllowedByPco=" + nrAdvancedCapable);
322                             mIsNrAdvancedAllowedByPco = nrAdvancedCapable;
323                             sendMessage(EVENT_UPDATE);
324                         }
325                     };
326             mPhone.getDataNetworkController().registerDataNetworkControllerCallback(
327                     mNrAdvancedCapableByPcoChangedCallback);
328         } else if (mNrAdvancedCapablePcoId == 0 && mNrAdvancedCapableByPcoChangedCallback != null) {
329             mPhone.getDataNetworkController().unregisterDataNetworkControllerCallback(
330                     mNrAdvancedCapableByPcoChangedCallback);
331             mNrAdvancedCapableByPcoChangedCallback = null;
332         }
333         mIsUsingUserDataForRrcDetection = config.getBoolean(
334                 CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL);
335         if (!isUsingPhysicalChannelConfigForRrcDetection()) {
336             if (mNrPhysicalLinkStatusChangedCallback == null) {
337                 mNrPhysicalLinkStatusChangedCallback =
338                         new DataNetworkControllerCallback(getHandler()::post) {
339                             @Override
340                             public void onPhysicalLinkStatusChanged(@LinkStatus int status) {
341                                 sendMessage(obtainMessage(EVENT_PHYSICAL_LINK_STATUS_CHANGED,
342                                         new AsyncResult(null, status, null)));
343                             }
344                         };
345                 mPhone.getDataNetworkController().registerDataNetworkControllerCallback(
346                         mNrPhysicalLinkStatusChangedCallback);
347             }
348         } else if (mNrPhysicalLinkStatusChangedCallback != null) {
349             mPhone.getDataNetworkController().unregisterDataNetworkControllerCallback(
350                     mNrPhysicalLinkStatusChangedCallback);
351             mNrPhysicalLinkStatusChangedCallback = null;
352         }
353         String nrIconConfiguration = config.getString(
354                 CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
355         String overrideTimerRule = config.getString(
356                 CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING);
357         String overrideSecondaryTimerRule = config.getString(
358                 CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING);
359         createTimerRules(nrIconConfiguration, overrideTimerRule, overrideSecondaryTimerRule);
360         updatePhysicalChannelConfigs();
361     }
362 
createTimerRules(String icons, String timers, String secondaryTimers)363     private void createTimerRules(String icons, String timers, String secondaryTimers) {
364         Map<String, OverrideTimerRule> tempRules = new HashMap<>();
365         if (!TextUtils.isEmpty(icons)) {
366             // Format: "STATE:ICON,STATE2:ICON2"
367             for (String pair : icons.trim().split(",")) {
368                 String[] kv = (pair.trim().toLowerCase(Locale.ROOT)).split(":");
369                 if (kv.length != 2) {
370                     if (DBG) loge("Invalid 5G icon configuration, config = " + pair);
371                     continue;
372                 }
373                 int icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
374                 if (kv[1].equals(ICON_5G)) {
375                     icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
376                 } else if (kv[1].equals(ICON_5G_PLUS)) {
377                     icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED;
378                 } else {
379                     if (DBG) loge("Invalid 5G icon = " + kv[1]);
380                 }
381                 tempRules.put(kv[0], new OverrideTimerRule(kv[0], icon));
382             }
383         }
384         // Ensure all states have an associated OverrideTimerRule and icon
385         for (String state : ALL_STATES) {
386             if (!tempRules.containsKey(state)) {
387                 tempRules.put(state, new OverrideTimerRule(
388                         state, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE));
389             }
390         }
391 
392         if (!TextUtils.isEmpty(timers)) {
393             // Format: "FROM_STATE,TO_STATE,DURATION;FROM_STATE_2,TO_STATE_2,DURATION_2"
394             for (String triple : timers.trim().split(";")) {
395                 String[] kv = (triple.trim().toLowerCase(Locale.ROOT)).split(",");
396                 if (kv.length != 3) {
397                     if (DBG) loge("Invalid 5G icon timer configuration, config = " + triple);
398                     continue;
399                 }
400                 int duration;
401                 try {
402                     duration = Integer.parseInt(kv[2]);
403                 } catch (NumberFormatException e) {
404                     continue;
405                 }
406                 if (kv[0].equals(STATE_ANY)) {
407                     for (String state : ALL_STATES) {
408                         OverrideTimerRule node = tempRules.get(state);
409                         node.addTimer(kv[1], duration);
410                     }
411                 } else {
412                     OverrideTimerRule node = tempRules.get(kv[0]);
413                     node.addTimer(kv[1], duration);
414                 }
415             }
416         }
417 
418         if (!TextUtils.isEmpty(secondaryTimers)) {
419             // Format: "PRIMARY_STATE,TO_STATE,DURATION;PRIMARY_STATE_2,TO_STATE_2,DURATION_2"
420             for (String triple : secondaryTimers.trim().split(";")) {
421                 String[] kv = (triple.trim().toLowerCase(Locale.ROOT)).split(",");
422                 if (kv.length != 3) {
423                     if (DBG) {
424                         loge("Invalid 5G icon secondary timer configuration, config = " + triple);
425                     }
426                     continue;
427                 }
428                 int duration;
429                 try {
430                     duration = Integer.parseInt(kv[2]);
431                 } catch (NumberFormatException e) {
432                     continue;
433                 }
434                 if (kv[0].equals(STATE_ANY)) {
435                     for (String state : ALL_STATES) {
436                         OverrideTimerRule node = tempRules.get(state);
437                         node.addSecondaryTimer(kv[1], duration);
438                     }
439                 } else {
440                     OverrideTimerRule node = tempRules.get(kv[0]);
441                     node.addSecondaryTimer(kv[1], duration);
442                 }
443             }
444         }
445 
446         mOverrideTimerRules = tempRules;
447         if (DBG) log("mOverrideTimerRules: " + mOverrideTimerRules);
448     }
449 
updateOverrideNetworkType()450     private void updateOverrideNetworkType() {
451         if (mIsPrimaryTimerActive || mIsSecondaryTimerActive) {
452             if (DBG) log("Skip updating override network type since timer is active.");
453             return;
454         }
455         mOverrideNetworkType = getCurrentOverrideNetworkType();
456         mDisplayInfoController.updateTelephonyDisplayInfo();
457     }
458 
getCurrentOverrideNetworkType()459     private @Annotation.OverrideNetworkType int getCurrentOverrideNetworkType() {
460         int displayNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
461         int dataNetworkType = getDataNetworkType();
462         boolean nrNsa = isLte(dataNetworkType)
463                 && mServiceState.getNrState() != NetworkRegistrationInfo.NR_STATE_NONE;
464         boolean nrSa = dataNetworkType == TelephonyManager.NETWORK_TYPE_NR;
465 
466         // NR display is not accurate when physical channel config notifications are off
467         if (mIsPhysicalChannelConfigOn && (nrNsa || nrSa)) {
468             // Process NR display network type
469             displayNetworkType = getNrDisplayType(nrSa);
470             if (displayNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE && !nrSa) {
471                 // Use LTE values if 5G values aren't defined
472                 displayNetworkType = getLteDisplayType();
473             }
474         } else if (isLte(dataNetworkType)) {
475             // Process LTE display network type
476             displayNetworkType = getLteDisplayType();
477         }
478         return displayNetworkType;
479     }
480 
getNrDisplayType(boolean isNrSa)481     private @Annotation.OverrideNetworkType int getNrDisplayType(boolean isNrSa) {
482         // Don't show 5G icon if preferred network type does not include 5G
483         if ((mPhone.getCachedAllowedNetworkTypesBitmask()
484                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
485             return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
486         }
487         // Icon display keys in order of priority
488         List<String> keys = new ArrayList<>();
489         if (isNrSa) {
490             if (isNrAdvanced()) {
491                 keys.add(STATE_CONNECTED_NR_ADVANCED);
492             }
493         } else {
494             switch (mServiceState.getNrState()) {
495                 case NetworkRegistrationInfo.NR_STATE_CONNECTED:
496                     if (isNrAdvanced()) {
497                         keys.add(STATE_CONNECTED_NR_ADVANCED);
498                     }
499                     keys.add(STATE_CONNECTED);
500                     break;
501                 case NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED:
502                     keys.add(isPhysicalLinkActive() ? STATE_NOT_RESTRICTED_RRC_CON
503                             : STATE_NOT_RESTRICTED_RRC_IDLE);
504                     break;
505                 case NetworkRegistrationInfo.NR_STATE_RESTRICTED:
506                     keys.add(STATE_RESTRICTED);
507                     break;
508             }
509         }
510 
511         for (String key : keys) {
512             OverrideTimerRule rule = mOverrideTimerRules.get(key);
513             if (rule != null && rule.mOverrideType
514                     != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
515                 return rule.mOverrideType;
516             }
517         }
518         return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
519     }
520 
getLteDisplayType()521     private @Annotation.OverrideNetworkType int getLteDisplayType() {
522         int value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
523         if ((getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA
524                 || mServiceState.isUsingCarrierAggregation())
525                 && IntStream.of(mServiceState.getCellBandwidths()).sum()
526                 > mLtePlusThresholdBandwidth) {
527             value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA;
528         }
529         if (isLteEnhancedAvailable()) {
530             value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO;
531         }
532         return value;
533     }
534 
isLteEnhancedAvailable()535     private boolean isLteEnhancedAvailable() {
536         if (TextUtils.isEmpty(mLteEnhancedPattern)) {
537             return false;
538         }
539         Pattern stringPattern = Pattern.compile(mLteEnhancedPattern);
540         for (String opName : new String[] {mServiceState.getOperatorAlphaLongRaw(),
541                 mServiceState.getOperatorAlphaShortRaw()}) {
542             if (!TextUtils.isEmpty(opName)) {
543                 Matcher matcher = stringPattern.matcher(opName);
544                 if (matcher.find()) {
545                     return true;
546                 }
547             }
548         }
549         return false;
550     }
551 
552     /**
553      * The parent state for all other states.
554      */
555     private final class DefaultState extends State {
556         @Override
processMessage(Message msg)557         public boolean processMessage(Message msg) {
558             if (DBG) log("DefaultState: process " + getEventName(msg.what));
559             switch (msg.what) {
560                 case EVENT_UPDATE:
561                     resetAllTimers();
562                     transitionToCurrentState();
563                     break;
564                 case EVENT_QUIT:
565                     if (DBG) log("Reset timers on state machine quitting.");
566                     resetAllTimers();
567                     unRegisterForAllEvents();
568                     quit();
569                     break;
570                 case EVENT_INITIALIZE:
571                     // The reason that we do it here is that the work below requires other modules
572                     // (e.g. DataNetworkController, ServiceStateTracker), which are not created
573                     // when NetworkTypeController is created.
574                     registerForAllEvents();
575                     parseCarrierConfigs();
576                     break;
577                 case EVENT_SERVICE_STATE_CHANGED:
578                     mServiceState = mPhone.getServiceStateTracker().getServiceState();
579                     if (DBG) log("ServiceState updated: " + mServiceState);
580                     transitionToCurrentState();
581                     break;
582                 case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
583                     AsyncResult ar = (AsyncResult) msg.obj;
584                     mPhysicalLinkStatus = (int) ar.result;
585                     break;
586                 case EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED:
587                     AsyncResult result = (AsyncResult) msg.obj;
588                     mIsPhysicalChannelConfigOn = (boolean) result.result;
589                     if (DBG) {
590                         log("mIsPhysicalChannelConfigOn changed to: " + mIsPhysicalChannelConfigOn);
591                     }
592                     if (!mIsPhysicalChannelConfigOn) {
593                         if (DBG) {
594                             log("Reset timers since physical channel config indications are off.");
595                         }
596                         resetAllTimers();
597                         mRatchetedNrBands.clear();
598                         mRatchetedNrBandwidths = 0;
599                         mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
600                     }
601                     transitionToCurrentState();
602                     break;
603                 case EVENT_CARRIER_CONFIG_CHANGED:
604                     parseCarrierConfigs();
605                     if (DBG) log("Reset timers since carrier configurations changed.");
606                     resetAllTimers();
607                     transitionToCurrentState();
608                     break;
609                 case EVENT_PRIMARY_TIMER_EXPIRED:
610                     if (DBG) log("Primary timer expired for state: " + mPrimaryTimerState);
611                     transitionWithSecondaryTimerTo((IState) msg.obj);
612                     break;
613                 case EVENT_SECONDARY_TIMER_EXPIRED:
614                     if (DBG) log("Secondary timer expired for state: " + mSecondaryTimerState);
615                     mIsSecondaryTimerActive = false;
616                     mSecondaryTimerState = "";
617                     updateTimers();
618                     updateOverrideNetworkType();
619                     break;
620                 case EVENT_RADIO_OFF_OR_UNAVAILABLE:
621                     if (DBG) log("Reset timers since radio is off or unavailable.");
622                     resetAllTimers();
623                     transitionTo(mLegacyState);
624                     break;
625                 case EVENT_PREFERRED_NETWORK_MODE_CHANGED:
626                     if (DBG) log("Reset timers since preferred network mode changed.");
627                     resetAllTimers();
628                     transitionToCurrentState();
629                     break;
630                 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED:
631                     updatePhysicalChannelConfigs();
632                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
633                         mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
634                     }
635                     transitionToCurrentState();
636                     break;
637                 case EVENT_DEVICE_IDLE_MODE_CHANGED:
638                     PowerManager pm = mPhone.getContext().getSystemService(PowerManager.class);
639                     mIsDeviceIdleMode = pm.isDeviceIdleMode();
640                     if (DBG) {
641                         log("mIsDeviceIdleMode changed to: " + mIsDeviceIdleMode);
642                     }
643                     if (mIsDeviceIdleMode) {
644                         if (DBG) log("Reset timers since device is in idle mode.");
645                         resetAllTimers();
646                     }
647                     transitionToCurrentState();
648                     break;
649                 default:
650                     throw new RuntimeException("Received invalid event: " + msg.what);
651             }
652             return HANDLED;
653         }
654     }
655 
656     /**
657      * Device does not have NR available, due to any of the below reasons:
658      * <ul>
659      *   <li> LTE cell does not support EN-DC
660      *   <li> LTE cell supports EN-DC, but the use of NR is restricted
661      *   <li> Data network type is not LTE, NR NSA, or NR SA
662      * </ul>
663      * This is the initial state.
664      */
665     private final class LegacyState extends State {
666         private boolean mIsNrRestricted = false;
667 
668         @Override
enter()669         public void enter() {
670             if (DBG) log("Entering LegacyState");
671             updateTimers();
672             updateOverrideNetworkType();
673             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
674                 mIsNrRestricted = isNrRestricted();
675                 mPreviousState = getName();
676             }
677         }
678 
679         @Override
processMessage(Message msg)680         public boolean processMessage(Message msg) {
681             if (DBG) log("LegacyState: process " + getEventName(msg.what));
682             updateTimers();
683             switch (msg.what) {
684                 case EVENT_SERVICE_STATE_CHANGED:
685                     mServiceState = mPhone.getServiceStateTracker().getServiceState();
686                     if (DBG) log("ServiceState updated: " + mServiceState);
687                     // fallthrough
688                 case EVENT_UPDATE:
689                     int rat = getDataNetworkType();
690                     if (rat == TelephonyManager.NETWORK_TYPE_NR || isLte(rat) && isNrConnected()) {
691                         if (isNrAdvanced()) {
692                             transitionTo(mNrConnectedAdvancedState);
693                         } else {
694                             transitionTo(mNrConnectedState);
695                         }
696                     } else if (isLte(rat) && isNrNotRestricted()) {
697                         transitionWithTimerTo(isPhysicalLinkActive()
698                                 ? mLteConnectedState : mIdleState);
699                     } else {
700                         if (!isLte(rat)) {
701                             if (DBG) log("Reset timers since 2G and 3G don't need NR timers.");
702                             resetAllTimers();
703                         }
704                         updateOverrideNetworkType();
705                     }
706                     mIsNrRestricted = isNrRestricted();
707                     break;
708                 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED:
709                     updatePhysicalChannelConfigs();
710                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
711                         mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
712                         if (mIsTimerResetEnabledForLegacyStateRrcIdle && !isPhysicalLinkActive()) {
713                             if (DBG) log("Reset timers since timer reset is enabled for RRC idle.");
714                             resetAllTimers();
715                         }
716                     }
717                     break;
718                 case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
719                     AsyncResult ar = (AsyncResult) msg.obj;
720                     mPhysicalLinkStatus = (int) ar.result;
721                     if (mIsTimerResetEnabledForLegacyStateRrcIdle && !isPhysicalLinkActive()) {
722                         if (DBG) log("Reset timers since timer reset is enabled for RRC idle.");
723                         resetAllTimers();
724                         updateOverrideNetworkType();
725                     }
726                     break;
727                 default:
728                     return NOT_HANDLED;
729             }
730             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
731                 mPreviousState = getName();
732             }
733             return HANDLED;
734         }
735 
736         @Override
getName()737         public String getName() {
738             return mIsNrRestricted ? STATE_RESTRICTED : STATE_LEGACY;
739         }
740     }
741 
742     private final LegacyState mLegacyState = new LegacyState();
743 
744     /**
745      * Device does not have any physical connection with the cell (RRC idle).
746      */
747     private final class IdleState extends State {
748         @Override
enter()749         public void enter() {
750             if (DBG) log("Entering IdleState");
751             updateTimers();
752             updateOverrideNetworkType();
753             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
754                 mPreviousState = getName();
755             }
756         }
757 
758         @Override
processMessage(Message msg)759         public boolean processMessage(Message msg) {
760             if (DBG) log("IdleState: process " + getEventName(msg.what));
761             updateTimers();
762             switch (msg.what) {
763                 case EVENT_SERVICE_STATE_CHANGED:
764                     mServiceState = mPhone.getServiceStateTracker().getServiceState();
765                     if (DBG) log("ServiceState updated: " + mServiceState);
766                     // fallthrough
767                 case EVENT_UPDATE:
768                     int rat = getDataNetworkType();
769                     if (rat == TelephonyManager.NETWORK_TYPE_NR
770                             || (isLte(rat) && isNrConnected())) {
771                         if (isNrAdvanced()) {
772                             transitionTo(mNrConnectedAdvancedState);
773                         } else {
774                             transitionTo(mNrConnectedState);
775                         }
776                     } else if (!isLte(rat) || !isNrNotRestricted()) {
777                         transitionWithTimerTo(mLegacyState);
778                     } else {
779                         if (isPhysicalLinkActive()) {
780                             transitionWithTimerTo(mLteConnectedState);
781                         } else {
782                             // Update in case the override network type changed
783                             updateOverrideNetworkType();
784                         }
785                     }
786                     break;
787                 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED:
788                     updatePhysicalChannelConfigs();
789                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
790                         mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
791                         if (isPhysicalLinkActive()) {
792                             transitionWithTimerTo(mLteConnectedState);
793                         } else {
794                             log("Reevaluating state due to link status changed.");
795                             sendMessage(EVENT_UPDATE);
796                         }
797                     }
798                     break;
799                 case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
800                     AsyncResult ar = (AsyncResult) msg.obj;
801                     mPhysicalLinkStatus = (int) ar.result;
802                     if (isPhysicalLinkActive()) {
803                         transitionWithTimerTo(mLteConnectedState);
804                     } else {
805                         log("Reevaluating state due to link status changed.");
806                         sendMessage(EVENT_UPDATE);
807                     }
808                     break;
809                 default:
810                     return NOT_HANDLED;
811             }
812             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
813                 mPreviousState = getName();
814             }
815             return HANDLED;
816         }
817 
818         @Override
getName()819         public String getName() {
820             return STATE_NOT_RESTRICTED_RRC_IDLE;
821         }
822     }
823 
824     private final IdleState mIdleState = new IdleState();
825 
826     /**
827      * Device is connected to LTE as the primary cell (RRC connected).
828      */
829     private final class LteConnectedState extends State {
830         @Override
enter()831         public void enter() {
832             if (DBG) log("Entering LteConnectedState");
833             updateTimers();
834             updateOverrideNetworkType();
835             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
836                 mPreviousState = getName();
837             }
838         }
839 
840         @Override
processMessage(Message msg)841         public boolean processMessage(Message msg) {
842             if (DBG) log("LteConnectedState: process " + getEventName(msg.what));
843             updateTimers();
844             switch (msg.what) {
845                 case EVENT_SERVICE_STATE_CHANGED:
846                     mServiceState = mPhone.getServiceStateTracker().getServiceState();
847                     if (DBG) log("ServiceState updated: " + mServiceState);
848                     // fallthrough
849                 case EVENT_UPDATE:
850                     int rat = getDataNetworkType();
851                     if (rat == TelephonyManager.NETWORK_TYPE_NR
852                             || (isLte(rat) && isNrConnected())) {
853                         if (isNrAdvanced()) {
854                             transitionTo(mNrConnectedAdvancedState);
855                         } else {
856                             transitionTo(mNrConnectedState);
857                         }
858                     } else if (!isLte(rat) || !isNrNotRestricted()) {
859                         transitionWithTimerTo(mLegacyState);
860                     } else {
861                         if (!isPhysicalLinkActive()) {
862                             transitionWithTimerTo(mIdleState);
863                         } else {
864                             // Update in case the override network type changed
865                             updateOverrideNetworkType();
866                         }
867                     }
868                     break;
869                 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED:
870                     updatePhysicalChannelConfigs();
871                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
872                         mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
873                         if (!isPhysicalLinkActive()) {
874                             transitionWithTimerTo(mIdleState);
875                         } else {
876                             log("Reevaluating state due to link status changed.");
877                             sendMessage(EVENT_UPDATE);
878                         }
879                     }
880                     break;
881                 case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
882                     AsyncResult ar = (AsyncResult) msg.obj;
883                     mPhysicalLinkStatus = (int) ar.result;
884                     if (!isPhysicalLinkActive()) {
885                         transitionWithTimerTo(mIdleState);
886                     } else {
887                         log("Reevaluating state due to link status changed.");
888                         sendMessage(EVENT_UPDATE);
889                     }
890                     break;
891                 default:
892                     return NOT_HANDLED;
893             }
894             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
895                 mPreviousState = getName();
896             }
897             return HANDLED;
898         }
899 
900         @Override
getName()901         public String getName() {
902             return STATE_NOT_RESTRICTED_RRC_CON;
903         }
904     }
905 
906     private final LteConnectedState mLteConnectedState = new LteConnectedState();
907 
908     /**
909      * Device is connected to 5G NR as the primary or secondary cell.
910      */
911     private final class NrConnectedState extends State {
912         @Override
enter()913         public void enter() {
914             if (DBG) log("Entering NrConnectedState");
915             updateTimers();
916             updateOverrideNetworkType();
917             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
918                 mPreviousState = getName();
919             }
920         }
921 
922         @Override
processMessage(Message msg)923         public boolean processMessage(Message msg) {
924             if (DBG) log("NrConnectedState: process " + getEventName(msg.what));
925             updateTimers();
926             switch (msg.what) {
927                 case EVENT_SERVICE_STATE_CHANGED:
928                     mServiceState = mPhone.getServiceStateTracker().getServiceState();
929                     if (DBG) log("ServiceState updated: " + mServiceState);
930                     // fallthrough
931                 case EVENT_UPDATE:
932                     int rat = getDataNetworkType();
933                     if (rat == TelephonyManager.NETWORK_TYPE_NR
934                             || (isLte(rat) && isNrConnected())) {
935                         if (isNrAdvanced()) {
936                             transitionTo(mNrConnectedAdvancedState);
937                         } else {
938                             // Update in case the override network type changed
939                             updateOverrideNetworkType();
940                         }
941                     } else if (isLte(rat) && isNrNotRestricted()) {
942                         transitionWithTimerTo(isPhysicalLinkActive()
943                                 ? mLteConnectedState : mIdleState);
944                     } else {
945                         transitionWithTimerTo(mLegacyState);
946                     }
947                     break;
948                 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED:
949                     updatePhysicalChannelConfigs();
950                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
951                         mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
952                     }
953                     // Check NR advanced in case NR advanced bands were added
954                     if (isNrAdvanced()) {
955                         transitionTo(mNrConnectedAdvancedState);
956                     }
957                     break;
958                 case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
959                     AsyncResult ar = (AsyncResult) msg.obj;
960                     mPhysicalLinkStatus = (int) ar.result;
961                     break;
962                 default:
963                     return NOT_HANDLED;
964             }
965             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
966                 mPreviousState = getName();
967             }
968             return HANDLED;
969         }
970 
971         @Override
getName()972         public String getName() {
973             return STATE_CONNECTED;
974         }
975     }
976 
977     private final NrConnectedState mNrConnectedState = new NrConnectedState();
978 
979     /**
980      * Device is connected to 5G NR as the primary cell and the data rate is higher than
981      * the generic 5G data rate.
982      */
983     private final class NrConnectedAdvancedState extends State {
984         @Override
enter()985         public void enter() {
986             if (DBG) log("Entering NrConnectedAdvancedState");
987             updateTimers();
988             updateOverrideNetworkType();
989             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
990                 mPreviousState = getName();
991             }
992         }
993 
994         @Override
processMessage(Message msg)995         public boolean processMessage(Message msg) {
996             if (DBG) log("NrConnectedAdvancedState: process " + getEventName(msg.what));
997             updateTimers();
998             switch (msg.what) {
999                 case EVENT_SERVICE_STATE_CHANGED:
1000                     mServiceState = mPhone.getServiceStateTracker().getServiceState();
1001                     if (DBG) log("ServiceState updated: " + mServiceState);
1002                     // fallthrough
1003                 case EVENT_UPDATE:
1004                     int rat = getDataNetworkType();
1005                     if (rat == TelephonyManager.NETWORK_TYPE_NR
1006                             || (isLte(rat) && isNrConnected())) {
1007                         if (isNrAdvanced()) {
1008                             // Update in case the override network type changed
1009                             updateOverrideNetworkType();
1010                         } else {
1011                             if (rat == TelephonyManager.NETWORK_TYPE_NR && mOverrideNetworkType
1012                                     != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED) {
1013                                 // manually override network type after data rat changes since
1014                                 // timer will prevent it from being updated
1015                                 mOverrideNetworkType =
1016                                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
1017                             }
1018                             transitionWithTimerTo(mNrConnectedState);
1019                         }
1020                     } else if (isLte(rat) && isNrNotRestricted()) {
1021                         transitionWithTimerTo(isPhysicalLinkActive()
1022                                 ? mLteConnectedState : mIdleState);
1023                     } else {
1024                         transitionWithTimerTo(mLegacyState);
1025                     }
1026                     break;
1027                 case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED:
1028                     updatePhysicalChannelConfigs();
1029                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
1030                         mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
1031                     }
1032                     // Check NR advanced in case NR advanced bands were removed
1033                     if (!isNrAdvanced()) {
1034                         transitionWithTimerTo(mNrConnectedState);
1035                     }
1036                     break;
1037                 case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
1038                     AsyncResult ar = (AsyncResult) msg.obj;
1039                     mPhysicalLinkStatus = (int) ar.result;
1040                     break;
1041                 default:
1042                     return NOT_HANDLED;
1043             }
1044             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
1045                 mPreviousState = getName();
1046             }
1047             return HANDLED;
1048         }
1049 
1050         @Override
getName()1051         public String getName() {
1052             return STATE_CONNECTED_NR_ADVANCED;
1053         }
1054     }
1055 
1056     private final NrConnectedAdvancedState mNrConnectedAdvancedState =
1057             new NrConnectedAdvancedState();
1058 
updatePhysicalChannelConfigs()1059     private void updatePhysicalChannelConfigs() {
1060         List<PhysicalChannelConfig> physicalChannelConfigs =
1061                 mPhone.getServiceStateTracker().getPhysicalChannelConfigList();
1062         boolean isPccListEmpty = physicalChannelConfigs == null || physicalChannelConfigs.isEmpty();
1063         if (isPccListEmpty && isUsingPhysicalChannelConfigForRrcDetection()) {
1064             log("Physical channel configs updated: not updating PCC fields for empty PCC list "
1065                     + "indicating RRC idle.");
1066             mPhysicalChannelConfigs = physicalChannelConfigs;
1067             return;
1068         }
1069 
1070         int anchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
1071         int anchorLteCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
1072         int nrBandwidths = 0;
1073         Set<Integer> nrBands = new HashSet<>();
1074         if (physicalChannelConfigs != null) {
1075             for (PhysicalChannelConfig config : physicalChannelConfigs) {
1076                 if (config.getNetworkType() == TelephonyManager.NETWORK_TYPE_NR) {
1077                     if (config.getConnectionStatus() == CellInfo.CONNECTION_PRIMARY_SERVING
1078                             && anchorNrCellId == PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN) {
1079                         anchorNrCellId = config.getPhysicalCellId();
1080                     }
1081                     nrBandwidths += config.getCellBandwidthDownlinkKhz();
1082                     nrBands.add(config.getBand());
1083                 } else if (config.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
1084                     if (config.getConnectionStatus() == CellInfo.CONNECTION_PRIMARY_SERVING
1085                             && anchorLteCellId == PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN) {
1086                         anchorLteCellId = config.getPhysicalCellId();
1087                     }
1088                     if (mIncludeLteForNrAdvancedThresholdBandwidth) {
1089                         nrBandwidths += config.getCellBandwidthDownlinkKhz();
1090                     }
1091                 }
1092             }
1093         }
1094 
1095         // Update anchor NR cell from anchor LTE cell for NR NSA
1096         if (anchorNrCellId == PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN
1097                 && anchorLteCellId != PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN) {
1098             anchorNrCellId = anchorLteCellId;
1099         }
1100 
1101         if (anchorNrCellId == PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN) {
1102             if (!isPccListEmpty) {
1103                 log("Ignoring physical channel config fields without an anchor NR cell, "
1104                         + "either due to LTE-only configs or an unspecified cell ID.");
1105             }
1106             mRatchetedNrBandwidths = 0;
1107             mRatchetedNrBands.clear();
1108         } else if (anchorNrCellId == mLastAnchorNrCellId && mRatchetPccFieldsForSameAnchorNrCell) {
1109             log("Ratchet physical channel config fields since anchor NR cell is the same.");
1110             mRatchetedNrBandwidths = Math.max(mRatchetedNrBandwidths, nrBandwidths);
1111             mRatchetedNrBands.addAll(nrBands);
1112         } else {
1113             if (mRatchetPccFieldsForSameAnchorNrCell) {
1114                 log("Not ratcheting physical channel config fields since anchor NR cell changed: "
1115                         + mLastAnchorNrCellId + " -> " + anchorNrCellId);
1116             }
1117             mRatchetedNrBandwidths = nrBandwidths;
1118             mRatchetedNrBands = nrBands;
1119         }
1120 
1121         mLastAnchorNrCellId = anchorNrCellId;
1122         mPhysicalChannelConfigs = physicalChannelConfigs;
1123         if (DBG) {
1124             log("Physical channel configs updated: anchorNrCell=" + mLastAnchorNrCellId
1125                     + ", nrBandwidths=" + mRatchetedNrBandwidths + ", nrBands=" +  mRatchetedNrBands
1126                     + ", configs=" + mPhysicalChannelConfigs);
1127         }
1128     }
1129 
transitionWithTimerTo(IState destState)1130     private void transitionWithTimerTo(IState destState) {
1131         String destName = destState.getName();
1132         if (DBG) log("Transition with primary timer from " + mPreviousState + " to " + destName);
1133         OverrideTimerRule rule = mOverrideTimerRules.get(mPreviousState);
1134         if (!mIsDeviceIdleMode && rule != null && rule.getTimer(destName) > 0) {
1135             int duration = rule.getTimer(destName);
1136             if (DBG) log(duration + "s primary timer started for state: " + mPreviousState);
1137             mPrimaryTimerState = mPreviousState;
1138             mPreviousState = getCurrentState().getName();
1139             mIsPrimaryTimerActive = true;
1140             sendMessageDelayed(EVENT_PRIMARY_TIMER_EXPIRED, destState, duration * 1000L);
1141         }
1142         transitionTo(destState);
1143     }
1144 
transitionWithSecondaryTimerTo(IState destState)1145     private void transitionWithSecondaryTimerTo(IState destState) {
1146         String currentName = getCurrentState().getName();
1147         OverrideTimerRule rule = mOverrideTimerRules.get(mPrimaryTimerState);
1148         if (DBG) {
1149             log("Transition with secondary timer from " + currentName + " to "
1150                     + destState.getName());
1151         }
1152         if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) {
1153             int duration = rule.getSecondaryTimer(currentName);
1154             if (DBG) log(duration + "s secondary timer started for state: " + currentName);
1155             mSecondaryTimerState = currentName;
1156             mPreviousState = currentName;
1157             mIsSecondaryTimerActive = true;
1158             sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, duration * 1000L);
1159         }
1160         mIsPrimaryTimerActive = false;
1161         transitionTo(getCurrentState());
1162     }
1163 
transitionToCurrentState()1164     private void transitionToCurrentState() {
1165         int dataRat = getDataNetworkType();
1166         IState transitionState;
1167         if (dataRat == TelephonyManager.NETWORK_TYPE_NR || (isLte(dataRat) && isNrConnected())) {
1168             if (isNrAdvanced()) {
1169                 transitionState = mNrConnectedAdvancedState;
1170             } else {
1171                 transitionState = mNrConnectedState;
1172             }
1173         } else if (isLte(dataRat) && isNrNotRestricted()) {
1174             if (isPhysicalLinkActive()) {
1175                 transitionState = mLteConnectedState;
1176             } else {
1177                 transitionState = mIdleState;
1178             }
1179         } else {
1180             transitionState = mLegacyState;
1181         }
1182         if (!transitionState.equals(getCurrentState())) {
1183             mPreviousState = getCurrentState().getName();
1184             transitionTo(transitionState);
1185         } else {
1186             updateOverrideNetworkType();
1187         }
1188     }
1189 
updateTimers()1190     private void updateTimers() {
1191         if ((mPhone.getCachedAllowedNetworkTypesBitmask()
1192                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
1193             if (DBG) log("Reset timers since NR is not allowed.");
1194             resetAllTimers();
1195             return;
1196         }
1197 
1198         String currentState = getCurrentState().getName();
1199 
1200         if (mIsPrimaryTimerActive && getOverrideNetworkType() == getCurrentOverrideNetworkType()) {
1201             // remove primary timer if device goes back to the original icon
1202             if (DBG) {
1203                 log("Remove primary timer since icon of primary state and current icon equal: "
1204                         + mPrimaryTimerState);
1205             }
1206             removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
1207             mIsPrimaryTimerActive = false;
1208             mPrimaryTimerState = "";
1209             transitionToCurrentState();
1210             return;
1211         }
1212 
1213         if (mIsSecondaryTimerActive && !mSecondaryTimerState.equals(currentState)) {
1214             // remove secondary timer if devices is no longer in secondary timer state
1215             if (DBG) {
1216                 log("Remove secondary timer since current state (" +  currentState
1217                         + ") is no longer secondary timer state (" + mSecondaryTimerState + ").");
1218             }
1219             removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
1220             mIsSecondaryTimerActive = false;
1221             mSecondaryTimerState = "";
1222             transitionToCurrentState();
1223             return;
1224         }
1225 
1226         if (mIsPrimaryTimerActive || mIsSecondaryTimerActive) {
1227             if (currentState.equals(STATE_CONNECTED_NR_ADVANCED)) {
1228                 if (DBG) log("Reset timers since state is NR_ADVANCED.");
1229                 resetAllTimers();
1230             } else if (currentState.equals(STATE_CONNECTED)
1231                     && !mPrimaryTimerState.equals(STATE_CONNECTED_NR_ADVANCED)
1232                     && !mSecondaryTimerState.equals(STATE_CONNECTED_NR_ADVANCED)) {
1233                 if (DBG) log("Reset non-NR_ADVANCED timers since state is NR_CONNECTED");
1234                 resetAllTimers();
1235             } else {
1236                 int rat = getDataNetworkType();
1237                 if (!isLte(rat) && rat != TelephonyManager.NETWORK_TYPE_NR) {
1238                     if (DBG) log("Reset timers since 2G and 3G don't need NR timers.");
1239                     resetAllTimers();
1240                 }
1241             }
1242         }
1243     }
1244 
resetAllTimers()1245     private void resetAllTimers() {
1246         removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
1247         removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
1248         mIsPrimaryTimerActive = false;
1249         mIsSecondaryTimerActive = false;
1250         mPrimaryTimerState = "";
1251         mSecondaryTimerState = "";
1252     }
1253 
1254     /**
1255      * Private class defining timer rules between states to prevent flickering. These rules are
1256      * created in {@link #parseCarrierConfigs()} based on various carrier configs.
1257      */
1258     private static class OverrideTimerRule {
1259         /** The 5G state this timer rule applies for. See {@link #ALL_STATES}. */
1260         final String mState;
1261 
1262         /**
1263          * The override network type associated with this 5G state. This is the icon that will be
1264          * displayed on the status bar. An override type of NONE will display the LTE value instead.
1265          */
1266         final int mOverrideType;
1267 
1268         /**
1269          * A map of destination states and associated timers. If the 5G state changes from mState
1270          * to the destination state, keep the override type until either the primary timer expires
1271          * or mState is regained.
1272          */
1273         final Map<String, Integer> mPrimaryTimers;
1274 
1275         /**
1276          * A map of secondary states and associated timers. After the primary timer expires, keep
1277          * the override type until either the secondary timer expires or the device is no longer in
1278          * the secondary state.
1279          */
1280         final Map<String, Integer> mSecondaryTimers;
1281 
OverrideTimerRule(String state, int overrideType)1282         OverrideTimerRule(String state, int overrideType) {
1283             mState = state;
1284             mOverrideType = overrideType;
1285             mPrimaryTimers = new HashMap<>();
1286             mSecondaryTimers = new HashMap<>();
1287         }
1288 
1289         /**
1290          * Add a primary timer.
1291          * @param destination Transitions from mState to the destination state.
1292          * @param duration How long to keep the override type after transition to destination state.
1293          */
addTimer(String destination, int duration)1294         public void addTimer(String destination, int duration) {
1295             mPrimaryTimers.put(destination, duration);
1296         }
1297 
1298         /**
1299          * Add a secondary timer
1300          * @param secondaryState Stays in secondaryState after primary timer expires.
1301          * @param duration How long to keep the override type while in secondaryState.
1302          */
addSecondaryTimer(String secondaryState, int duration)1303         public void addSecondaryTimer(String secondaryState, int duration) {
1304             mSecondaryTimers.put(secondaryState, duration);
1305         }
1306 
1307         /**
1308          * @return Primary timer duration from mState to destination state, or 0 if not defined.
1309          */
getTimer(String destination)1310         public int getTimer(String destination) {
1311             Integer timer = mPrimaryTimers.get(destination);
1312             timer = timer == null ? mPrimaryTimers.get(STATE_ANY) : timer;
1313             return timer == null ? 0 : timer;
1314         }
1315 
1316         /**
1317          * @return Secondary timer duration for secondaryState, or 0 if not defined.
1318          */
getSecondaryTimer(String secondaryState)1319         public int getSecondaryTimer(String secondaryState) {
1320             Integer secondaryTimer = mSecondaryTimers.get(secondaryState);
1321             secondaryTimer = secondaryTimer == null
1322                     ? mSecondaryTimers.get(STATE_ANY) : secondaryTimer;
1323             return secondaryTimer == null ? 0 : secondaryTimer;
1324         }
1325 
1326         @Override
toString()1327         public String toString() {
1328             return "{mState=" + mState
1329                     + ", mOverrideType="
1330                     + TelephonyDisplayInfo.overrideNetworkTypeToString(mOverrideType)
1331                     + ", mPrimaryTimers=" + mPrimaryTimers
1332                     + ", mSecondaryTimers=" + mSecondaryTimers + "}";
1333         }
1334     }
1335 
isNrConnected()1336     private boolean isNrConnected() {
1337         return mServiceState.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED;
1338     }
1339 
isNrNotRestricted()1340     private boolean isNrNotRestricted() {
1341         return mServiceState.getNrState() == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED;
1342     }
1343 
isNrRestricted()1344     private boolean isNrRestricted() {
1345         return mServiceState.getNrState() == NetworkRegistrationInfo.NR_STATE_RESTRICTED;
1346     }
1347 
1348     /**
1349      * @return {@code true} if the device is in NR advanced mode (i.e. 5G+).
1350      */
isNrAdvanced()1351     private boolean isNrAdvanced() {
1352         // Check PCO requirement. For carriers using PCO to indicate whether the data connection is
1353         // NR advanced capable, mNrAdvancedCapablePcoId should be configured to non-zero.
1354         if (mNrAdvancedCapablePcoId > 0 && !mIsNrAdvancedAllowedByPco) {
1355             if (DBG) log("isNrAdvanced: not allowed by PCO for PCO ID " + mNrAdvancedCapablePcoId);
1356             return false;
1357         }
1358 
1359         // Check if NR advanced is enabled when the device is roaming. Some carriers disable it
1360         // while the device is roaming.
1361         if (mServiceState.getDataRoaming() && !mEnableNrAdvancedWhileRoaming) {
1362             if (DBG) log("isNrAdvanced: false because NR advanced is unavailable while roaming.");
1363             return false;
1364         }
1365 
1366         // Check if meeting minimum bandwidth requirement. For most carriers, there is no minimum
1367         // bandwidth requirement and mNrAdvancedThresholdBandwidth is 0.
1368         if (mNrAdvancedThresholdBandwidth > 0
1369                 && mRatchetedNrBandwidths < mNrAdvancedThresholdBandwidth) {
1370             if (DBG) {
1371                 log("isNrAdvanced: false because bandwidths=" + mRatchetedNrBandwidths
1372                         + " does not meet the threshold=" + mNrAdvancedThresholdBandwidth);
1373             }
1374             return false;
1375         }
1376 
1377         // If all above tests passed, then check if the device is using millimeter wave bands or
1378         // carrier designated bands.
1379         return isNrMmwave() || isAdditionalNrAdvancedBand();
1380     }
1381 
isNrMmwave()1382     private boolean isNrMmwave() {
1383         return mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE;
1384     }
1385 
isAdditionalNrAdvancedBand()1386     private boolean isAdditionalNrAdvancedBand() {
1387         if (mAdditionalNrAdvancedBands.isEmpty() || mRatchetedNrBands.isEmpty()) {
1388             if (DBG && !mAdditionalNrAdvancedBands.isEmpty()) {
1389                 // Only log if mAdditionalNrAdvancedBands is empty to prevent log spam
1390                 log("isAdditionalNrAdvancedBand: false because bands are empty; configs="
1391                         + mAdditionalNrAdvancedBands + ", bands=" + mRatchetedNrBands);
1392             }
1393             return false;
1394         }
1395         Set<Integer> intersection = new HashSet<>(mAdditionalNrAdvancedBands);
1396         intersection.retainAll(mRatchetedNrBands);
1397         return !intersection.isEmpty();
1398     }
1399 
isLte(int rat)1400     private boolean isLte(int rat) {
1401         return rat == TelephonyManager.NETWORK_TYPE_LTE
1402                 || rat == TelephonyManager.NETWORK_TYPE_LTE_CA;
1403     }
1404 
isPhysicalLinkActive()1405     private boolean isPhysicalLinkActive() {
1406         return mPhysicalLinkStatus == DataCallResponse.LINK_STATUS_ACTIVE;
1407     }
1408 
getPhysicalLinkStatusFromPhysicalChannelConfig()1409     private int getPhysicalLinkStatusFromPhysicalChannelConfig() {
1410         return (mPhysicalChannelConfigs == null || mPhysicalChannelConfigs.isEmpty())
1411                 ? DataCallResponse.LINK_STATUS_DORMANT : DataCallResponse.LINK_STATUS_ACTIVE;
1412     }
1413 
getEventName(int event)1414     private String getEventName(int event) {
1415         try {
1416             return sEvents[event];
1417         } catch (ArrayIndexOutOfBoundsException e) {
1418             return "EVENT_NOT_DEFINED";
1419         }
1420     }
1421 
isUsingPhysicalChannelConfigForRrcDetection()1422     private boolean isUsingPhysicalChannelConfigForRrcDetection() {
1423         return mIsPhysicalChannelConfig16Supported && !mIsUsingUserDataForRrcDetection;
1424     }
1425 
log(String s)1426     protected void log(String s) {
1427         Rlog.d(TAG, "[" + mPhone.getPhoneId() + "] " + s);
1428     }
1429 
loge(String s)1430     protected void loge(String s) {
1431         Rlog.e(TAG, "[" + mPhone.getPhoneId() + "] " + s);
1432     }
1433 
1434     @Override
toString()1435     public String toString() {
1436         return "mOverrideTimerRules=" + mOverrideTimerRules.toString()
1437                 + ", mLteEnhancedPattern=" + mLteEnhancedPattern
1438                 + ", mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn
1439                 + ", mIsPrimaryTimerActive=" + mIsPrimaryTimerActive
1440                 + ", mIsSecondaryTimerActive=" + mIsSecondaryTimerActive
1441                 + ", mPrimaryTimerState=" + mPrimaryTimerState
1442                 + ", mSecondaryTimerState=" + mSecondaryTimerState
1443                 + ", mPreviousState=" + mPreviousState
1444                 + ", mIsNrAdvanced=" + isNrAdvanced();
1445     }
1446 
1447     @Override
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1448     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
1449         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
1450         pw.print("NetworkTypeController: ");
1451         super.dump(fd, pw, args);
1452         pw.flush();
1453         pw.increaseIndent();
1454         pw.println("mSubId=" + mPhone.getSubId());
1455         pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString());
1456         pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern);
1457         pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn);
1458         pw.println("mIsPrimaryTimerActive=" + mIsPrimaryTimerActive);
1459         pw.println("mIsSecondaryTimerActive=" + mIsSecondaryTimerActive);
1460         pw.println("mIsTimerResetEnabledForLegacyStateRrcIdle="
1461                 + mIsTimerResetEnabledForLegacyStateRrcIdle);
1462         pw.println("mLtePlusThresholdBandwidth=" + mLtePlusThresholdBandwidth);
1463         pw.println("mNrAdvancedThresholdBandwidth=" + mNrAdvancedThresholdBandwidth);
1464         pw.println("mIncludeLteForNrAdvancedThresholdBandwidth="
1465                 + mIncludeLteForNrAdvancedThresholdBandwidth);
1466         pw.println("mRatchetPccFieldsForSameAnchorNrCell=" + mRatchetPccFieldsForSameAnchorNrCell);
1467         pw.println("mRatchetedNrBandwidths=" + mRatchetedNrBandwidths);
1468         pw.println("mAdditionalNrAdvancedBandsList=" + mAdditionalNrAdvancedBands);
1469         pw.println("mRatchetedNrBands=" + mRatchetedNrBands);
1470         pw.println("mLastAnchorNrCellId=" + mLastAnchorNrCellId);
1471         pw.println("mPrimaryTimerState=" + mPrimaryTimerState);
1472         pw.println("mSecondaryTimerState=" + mSecondaryTimerState);
1473         pw.println("mPreviousState=" + mPreviousState);
1474         pw.println("mPhysicalLinkStatus=" + DataUtils.linkStatusToString(mPhysicalLinkStatus));
1475         pw.println("mIsPhysicalChannelConfig16Supported=" + mIsPhysicalChannelConfig16Supported);
1476         pw.println("mIsNrAdvancedAllowedByPco=" + mIsNrAdvancedAllowedByPco);
1477         pw.println("mNrAdvancedCapablePcoId=" + mNrAdvancedCapablePcoId);
1478         pw.println("mIsUsingUserDataForRrcDetection=" + mIsUsingUserDataForRrcDetection);
1479         pw.println("mEnableNrAdvancedWhileRoaming=" + mEnableNrAdvancedWhileRoaming);
1480         pw.println("mIsDeviceIdleMode=" + mIsDeviceIdleMode);
1481         pw.decreaseIndent();
1482         pw.flush();
1483     }
1484 }
1485