• 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.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.os.AsyncResult;
24 import android.os.Message;
25 import android.os.PersistableBundle;
26 import android.telephony.AccessNetworkConstants;
27 import android.telephony.Annotation;
28 import android.telephony.CarrierConfigManager;
29 import android.telephony.NetworkRegistrationInfo;
30 import android.telephony.PcoData;
31 import android.telephony.PhysicalChannelConfig;
32 import android.telephony.ServiceState;
33 import android.telephony.SubscriptionManager;
34 import android.telephony.TelephonyDisplayInfo;
35 import android.telephony.TelephonyManager;
36 import android.telephony.data.ApnSetting;
37 import android.text.TextUtils;
38 
39 import com.android.internal.telephony.dataconnection.DataConnection;
40 import com.android.internal.telephony.dataconnection.DcController;
41 import com.android.internal.telephony.dataconnection.DcController.PhysicalLinkState;
42 import com.android.internal.telephony.dataconnection.DcTracker;
43 import com.android.internal.telephony.util.ArrayUtils;
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.List;
56 import java.util.Map;
57 import java.util.regex.Matcher;
58 import java.util.regex.Pattern;
59 import java.util.stream.IntStream;
60 
61 /**
62  * The NetworkTypeController evaluates the override network type of {@link TelephonyDisplayInfo}
63  * and sends it to {@link DisplayInfoController}. The override network type can replace the signal
64  * icon displayed on the status bar. It is affected by changes in data RAT, NR state, NR frequency,
65  * data activity, physical channel config, and carrier configurations. Based on carrier configs,
66  * NetworkTypeController also allows timers between various 5G states to prevent flickering.
67  */
68 public class NetworkTypeController extends StateMachine {
69     private static final boolean DBG = true;
70     private static final String TAG = "NetworkTypeController";
71     private static final String ICON_5G = "5g";
72     private static final String ICON_5G_PLUS = "5g_plus";
73     private static final String STATE_CONNECTED_NR_ADVANCED = "connected_mmwave";
74     private static final String STATE_CONNECTED = "connected";
75     private static final String STATE_NOT_RESTRICTED_RRC_IDLE = "not_restricted_rrc_idle";
76     private static final String STATE_NOT_RESTRICTED_RRC_CON = "not_restricted_rrc_con";
77     private static final String STATE_RESTRICTED = "restricted";
78     private static final String STATE_ANY = "any";
79     private static final String STATE_LEGACY = "legacy";
80     private static final String[] ALL_STATES = {STATE_CONNECTED_NR_ADVANCED, STATE_CONNECTED,
81             STATE_NOT_RESTRICTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_CON, STATE_RESTRICTED,
82             STATE_LEGACY };
83 
84     /** Stop all timers and go to current state. */
85     public static final int EVENT_UPDATE = 0;
86     /** Quit after processing all existing messages. */
87     public static final int EVENT_QUIT = 1;
88     private static final int EVENT_DATA_RAT_CHANGED = 2;
89     private static final int EVENT_NR_STATE_CHANGED = 3;
90     private static final int EVENT_NR_FREQUENCY_CHANGED = 4;
91     private static final int EVENT_PHYSICAL_LINK_STATE_CHANGED = 5;
92     private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED = 6;
93     private static final int EVENT_CARRIER_CONFIG_CHANGED = 7;
94     private static final int EVENT_PRIMARY_TIMER_EXPIRED = 8;
95     private static final int EVENT_SECONDARY_TIMER_EXPIRED = 9;
96     private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 10;
97     private static final int EVENT_PREFERRED_NETWORK_MODE_CHANGED = 11;
98     private static final int EVENT_INITIALIZE = 12;
99     private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 13;
100     private static final int EVENT_PCO_DATA_CHANGED = 14;
101 
102     private static final String[] sEvents = new String[EVENT_PCO_DATA_CHANGED + 1];
103     static {
104         sEvents[EVENT_UPDATE] = "EVENT_UPDATE";
105         sEvents[EVENT_QUIT] = "EVENT_QUIT";
106         sEvents[EVENT_DATA_RAT_CHANGED] = "EVENT_DATA_RAT_CHANGED";
107         sEvents[EVENT_NR_STATE_CHANGED] = "EVENT_NR_STATE_CHANGED";
108         sEvents[EVENT_NR_FREQUENCY_CHANGED] = "EVENT_NR_FREQUENCY_CHANGED";
109         sEvents[EVENT_PHYSICAL_LINK_STATE_CHANGED] = "EVENT_PHYSICAL_LINK_STATE_CHANGED";
110         sEvents[EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED] =
111                 "EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED";
112         sEvents[EVENT_CARRIER_CONFIG_CHANGED] = "EVENT_CARRIER_CONFIG_CHANGED";
113         sEvents[EVENT_PRIMARY_TIMER_EXPIRED] = "EVENT_PRIMARY_TIMER_EXPIRED";
114         sEvents[EVENT_SECONDARY_TIMER_EXPIRED] = "EVENT_SECONDARY_TIMER_EXPIRED";
115         sEvents[EVENT_RADIO_OFF_OR_UNAVAILABLE] = "EVENT_RADIO_OFF_OR_UNAVAILABLE";
116         sEvents[EVENT_PREFERRED_NETWORK_MODE_CHANGED] = "EVENT_PREFERRED_NETWORK_MODE_CHANGED";
117         sEvents[EVENT_INITIALIZE] = "EVENT_INITIALIZE";
118         sEvents[EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED] = "EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED";
119         sEvents[EVENT_PCO_DATA_CHANGED] = "EVENT_PCO_DATA_CHANGED";
120     }
121 
122     private final Phone mPhone;
123     private final DisplayInfoController mDisplayInfoController;
124     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
125         @Override
126         public void onReceive(Context context, Intent intent) {
127             if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)
128                     && intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX,
129                     SubscriptionManager.INVALID_PHONE_INDEX) == mPhone.getPhoneId()
130                     && !intent.getBooleanExtra(CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK,
131                     false)) {
132                 sendMessage(EVENT_CARRIER_CONFIG_CHANGED);
133             }
134         }
135     };
136 
137     private Map<String, OverrideTimerRule> mOverrideTimerRules = new HashMap<>();
138     private String mLteEnhancedPattern = "";
139     private int mOverrideNetworkType;
140     private boolean mIsPhysicalChannelConfigOn;
141     private boolean mIsPrimaryTimerActive;
142     private boolean mIsSecondaryTimerActive;
143     private boolean mIsTimerResetEnabledForLegacyStateRRCIdle;
144     private int mLtePlusThresholdBandwidth;
145     private int[] mAdditionalNrAdvancedBandsList;
146     private String mPrimaryTimerState;
147     private String mSecondaryTimerState;
148     private String mPreviousState;
149     private @PhysicalLinkState int mPhysicalLinkState;
150     private boolean mIsPhysicalChannelConfig16Supported;
151     private Boolean mIsNrAdvancedAllowedByPco = false;
152     private int mNrAdvancedCapablePcoId = 0;
153     private boolean mIsUsingUserDataForRrcDetection = false;
154 
155     /**
156      * NetworkTypeController constructor.
157      *
158      * @param phone Phone object.
159      * @param displayInfoController DisplayInfoController to send override network types to.
160      */
NetworkTypeController(Phone phone, DisplayInfoController displayInfoController)161     public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController) {
162         super(TAG, displayInfoController);
163         mPhone = phone;
164         mDisplayInfoController = displayInfoController;
165         mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
166         mIsPhysicalChannelConfigOn = true;
167         addState(mDefaultState);
168         addState(mLegacyState, mDefaultState);
169         addState(mIdleState, mDefaultState);
170         addState(mLteConnectedState, mDefaultState);
171         addState(mNrConnectedState, mDefaultState);
172         setInitialState(mDefaultState);
173         start();
174         sendMessage(EVENT_INITIALIZE);
175     }
176 
177     /**
178      * @return The current override network type, used to create TelephonyDisplayInfo in
179      * DisplayInfoController.
180      */
getOverrideNetworkType()181     public @Annotation.OverrideNetworkType int getOverrideNetworkType() {
182         return mOverrideNetworkType;
183     }
184 
185     /**
186      * @return True if either the primary or secondary 5G hysteresis timer is active,
187      * and false if neither are.
188      */
is5GHysteresisActive()189     public boolean is5GHysteresisActive() {
190         return mIsPrimaryTimerActive || mIsSecondaryTimerActive;
191     }
192 
registerForAllEvents()193     private void registerForAllEvents() {
194         mPhone.registerForRadioOffOrNotAvailable(getHandler(),
195                 EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
196         mPhone.registerForPreferredNetworkTypeChanged(getHandler(),
197                 EVENT_PREFERRED_NETWORK_MODE_CHANGED, null);
198         mPhone.registerForPhysicalChannelConfig(getHandler(),
199                 EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, null);
200         mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(
201                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler(),
202                 EVENT_DATA_RAT_CHANGED, null);
203         mIsPhysicalChannelConfig16Supported = mPhone.getContext().getSystemService(
204                 TelephonyManager.class).isRadioInterfaceCapabilitySupported(
205                 TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
206         if (!mIsPhysicalChannelConfig16Supported) {
207             mPhone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
208                     .registerForPhysicalLinkStateChanged(getHandler(),
209                             EVENT_PHYSICAL_LINK_STATE_CHANGED);
210         }
211         mPhone.getServiceStateTracker().registerForNrStateChanged(getHandler(),
212                 EVENT_NR_STATE_CHANGED, null);
213         mPhone.getServiceStateTracker().registerForNrFrequencyChanged(getHandler(),
214                 EVENT_NR_FREQUENCY_CHANGED, null);
215         mPhone.getDeviceStateMonitor().registerForPhysicalChannelConfigNotifChanged(getHandler(),
216                 EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED, null);
217         IntentFilter filter = new IntentFilter();
218         filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
219         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
220         mPhone.mCi.registerForPcoData(getHandler(), EVENT_PCO_DATA_CHANGED, null);
221     }
222 
unRegisterForAllEvents()223     private void unRegisterForAllEvents() {
224         mPhone.unregisterForRadioOffOrNotAvailable(getHandler());
225         mPhone.unregisterForPreferredNetworkTypeChanged(getHandler());
226         mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(
227                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler());
228         mPhone.getServiceStateTracker().unregisterForNrStateChanged(getHandler());
229         mPhone.getServiceStateTracker().unregisterForNrFrequencyChanged(getHandler());
230         mPhone.getDeviceStateMonitor().unregisterForPhysicalChannelConfigNotifChanged(getHandler());
231         mPhone.getContext().unregisterReceiver(mIntentReceiver);
232         mPhone.mCi.unregisterForPcoData(getHandler());
233     }
234 
parseCarrierConfigs()235     private void parseCarrierConfigs() {
236         String nrIconConfiguration = CarrierConfigManager.getDefaultConfig().getString(
237                 CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
238         String overrideTimerRule = CarrierConfigManager.getDefaultConfig().getString(
239                 CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING);
240         String overrideSecondaryTimerRule = CarrierConfigManager.getDefaultConfig().getString(
241                 CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING);
242         mLteEnhancedPattern = CarrierConfigManager.getDefaultConfig().getString(
243                 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
244         mIsTimerResetEnabledForLegacyStateRRCIdle =
245                 CarrierConfigManager.getDefaultConfig().getBoolean(
246                         CarrierConfigManager.KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL);
247         mLtePlusThresholdBandwidth = CarrierConfigManager.getDefaultConfig().getInt(
248                 CarrierConfigManager.KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT);
249 
250         CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
251                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
252         if (configManager != null) {
253             PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
254             if (b != null) {
255                 if (b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING) != null) {
256                     nrIconConfiguration = b.getString(
257                             CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
258                 }
259                 if (b.getString(CarrierConfigManager
260                         .KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING) != null) {
261                     overrideTimerRule = b.getString(
262                             CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING);
263                 }
264                 if (b.getString(CarrierConfigManager
265                         .KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING) != null) {
266                     overrideSecondaryTimerRule = b.getString(
267                             CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING);
268                 }
269                 if (b.getString(CarrierConfigManager
270                         .KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING) != null) {
271                     mLteEnhancedPattern = b.getString(
272                             CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
273                 }
274                 mIsTimerResetEnabledForLegacyStateRRCIdle = b.getBoolean(
275                         CarrierConfigManager.KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL);
276                 mLtePlusThresholdBandwidth = b.getInt(
277                         CarrierConfigManager.KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT,
278                         mLtePlusThresholdBandwidth);
279                 mAdditionalNrAdvancedBandsList = b.getIntArray(
280                         CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY);
281                 mNrAdvancedCapablePcoId = b.getInt(
282                         CarrierConfigManager.KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT);
283                 mIsUsingUserDataForRrcDetection = b.getBoolean(
284                         CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL);
285                 if (mIsPhysicalChannelConfig16Supported && mIsUsingUserDataForRrcDetection) {
286                     mPhone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
287                             .registerForPhysicalLinkStateChanged(getHandler(),
288                                     EVENT_PHYSICAL_LINK_STATE_CHANGED);
289                 }
290             }
291         }
292         createTimerRules(nrIconConfiguration, overrideTimerRule, overrideSecondaryTimerRule);
293     }
294 
createTimerRules(String icons, String timers, String secondaryTimers)295     private void createTimerRules(String icons, String timers, String secondaryTimers) {
296         Map<String, OverrideTimerRule> tempRules = new HashMap<>();
297         if (!TextUtils.isEmpty(icons)) {
298             // Format: "STATE:ICON,STATE2:ICON2"
299             for (String pair : icons.trim().split(",")) {
300                 String[] kv = (pair.trim().toLowerCase()).split(":");
301                 if (kv.length != 2) {
302                     if (DBG) loge("Invalid 5G icon configuration, config = " + pair);
303                     continue;
304                 }
305                 int icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
306                 if (kv[1].equals(ICON_5G)) {
307                     icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
308                 } else if (kv[1].equals(ICON_5G_PLUS)) {
309                     icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED;
310                 } else {
311                     if (DBG) loge("Invalid 5G icon = " + kv[1]);
312                 }
313                 tempRules.put(kv[0], new OverrideTimerRule(kv[0], icon));
314             }
315         }
316         // Ensure all states have an associated OverrideTimerRule and icon
317         for (String state : ALL_STATES) {
318             if (!tempRules.containsKey(state)) {
319                 tempRules.put(state, new OverrideTimerRule(
320                         state, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE));
321             }
322         }
323 
324         if (!TextUtils.isEmpty(timers)) {
325             // Format: "FROM_STATE,TO_STATE,DURATION;FROM_STATE_2,TO_STATE_2,DURATION_2"
326             for (String triple : timers.trim().split(";")) {
327                 String[] kv = (triple.trim().toLowerCase()).split(",");
328                 if (kv.length != 3) {
329                     if (DBG) loge("Invalid 5G icon timer configuration, config = " + triple);
330                     continue;
331                 }
332                 int duration;
333                 try {
334                     duration = Integer.parseInt(kv[2]);
335                 } catch (NumberFormatException e) {
336                     continue;
337                 }
338                 if (kv[0].equals(STATE_ANY)) {
339                     for (String state : ALL_STATES) {
340                         OverrideTimerRule node = tempRules.get(state);
341                         node.addTimer(kv[1], duration);
342                     }
343                 } else {
344                     OverrideTimerRule node = tempRules.get(kv[0]);
345                     node.addTimer(kv[1], duration);
346                 }
347             }
348         }
349 
350         if (!TextUtils.isEmpty(secondaryTimers)) {
351             // Format: "PRIMARY_STATE,TO_STATE,DURATION;PRIMARY_STATE_2,TO_STATE_2,DURATION_2"
352             for (String triple : secondaryTimers.trim().split(";")) {
353                 String[] kv = (triple.trim().toLowerCase()).split(",");
354                 if (kv.length != 3) {
355                     if (DBG) {
356                         loge("Invalid 5G icon secondary timer configuration, config = " + triple);
357                     }
358                     continue;
359                 }
360                 int duration;
361                 try {
362                     duration = Integer.parseInt(kv[2]);
363                 } catch (NumberFormatException e) {
364                     continue;
365                 }
366                 if (kv[0].equals(STATE_ANY)) {
367                     for (String state : ALL_STATES) {
368                         OverrideTimerRule node = tempRules.get(state);
369                         node.addSecondaryTimer(kv[1], duration);
370                     }
371                 } else {
372                     OverrideTimerRule node = tempRules.get(kv[0]);
373                     node.addSecondaryTimer(kv[1], duration);
374                 }
375             }
376         }
377 
378         mOverrideTimerRules = tempRules;
379         if (DBG) log("mOverrideTimerRules: " + mOverrideTimerRules);
380     }
381 
updateOverrideNetworkType()382     private void updateOverrideNetworkType() {
383         if (mIsPrimaryTimerActive || mIsSecondaryTimerActive) {
384             if (DBG) log("Skip updating override network type since timer is active.");
385             return;
386         }
387         mOverrideNetworkType = getCurrentOverrideNetworkType();
388         mDisplayInfoController.updateTelephonyDisplayInfo();
389     }
390 
getCurrentOverrideNetworkType()391     private @Annotation.OverrideNetworkType int getCurrentOverrideNetworkType() {
392         int displayNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
393         int dataNetworkType = getDataNetworkType();
394         boolean nrNsa = isLte(dataNetworkType)
395                 && mPhone.getServiceState().getNrState() != NetworkRegistrationInfo.NR_STATE_NONE;
396         boolean nrSa = dataNetworkType == TelephonyManager.NETWORK_TYPE_NR;
397 
398         // NR display is not accurate when physical channel config notifications are off
399         if (mIsPhysicalChannelConfigOn && (nrNsa || nrSa)) {
400             // Process NR display network type
401             displayNetworkType = getNrDisplayType(nrSa);
402             if (displayNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
403                 // Use LTE values if 5G values aren't defined
404                 displayNetworkType = getLteDisplayType();
405             }
406         } else if (isLte(dataNetworkType)) {
407             // Process LTE display network type
408             displayNetworkType = getLteDisplayType();
409         }
410         return displayNetworkType;
411     }
412 
getNrDisplayType(boolean isNrSa)413     private @Annotation.OverrideNetworkType int getNrDisplayType(boolean isNrSa) {
414         // Don't show 5G icon if preferred network type does not include 5G
415         if ((mPhone.getCachedAllowedNetworkTypesBitmask()
416                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
417             return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
418         }
419         // Icon display keys in order of priority
420         List<String> keys = new ArrayList<>();
421         if (isNrSa && isNrAdvanced()) {
422             keys.add(STATE_CONNECTED_NR_ADVANCED);
423         } else {
424             switch (mPhone.getServiceState().getNrState()) {
425                 case NetworkRegistrationInfo.NR_STATE_CONNECTED:
426                     if (isNrAdvanced()) {
427                         keys.add(STATE_CONNECTED_NR_ADVANCED);
428                     }
429                     keys.add(STATE_CONNECTED);
430                     break;
431                 case NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED:
432                     keys.add(isPhysicalLinkActive() ? STATE_NOT_RESTRICTED_RRC_CON
433                             : STATE_NOT_RESTRICTED_RRC_IDLE);
434                     break;
435                 case NetworkRegistrationInfo.NR_STATE_RESTRICTED:
436                     keys.add(STATE_RESTRICTED);
437                     break;
438             }
439         }
440 
441         for (String key : keys) {
442             OverrideTimerRule rule = mOverrideTimerRules.get(key);
443             if (rule != null && rule.mOverrideType
444                     != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
445                 return rule.mOverrideType;
446             }
447         }
448         return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
449     }
450 
getLteDisplayType()451     private @Annotation.OverrideNetworkType int getLteDisplayType() {
452         int value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
453         if ((getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA
454                 || mPhone.getServiceState().isUsingCarrierAggregation())
455                 && (IntStream.of(mPhone.getServiceState().getCellBandwidths()).sum()
456                         > mLtePlusThresholdBandwidth)) {
457             value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA;
458         }
459         if (isLteEnhancedAvailable()) {
460             value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO;
461         }
462         return value;
463     }
464 
isLteEnhancedAvailable()465     private boolean isLteEnhancedAvailable() {
466         if (TextUtils.isEmpty(mLteEnhancedPattern)) {
467             return false;
468         }
469         Pattern stringPattern = Pattern.compile(mLteEnhancedPattern);
470         for (String opName : new String[] {mPhone.getServiceState().getOperatorAlphaLongRaw(),
471                 mPhone.getServiceState().getOperatorAlphaShortRaw()}) {
472             if (!TextUtils.isEmpty(opName)) {
473                 Matcher matcher = stringPattern.matcher(opName);
474                 if (matcher.find()) {
475                     return true;
476                 }
477             }
478         }
479         return false;
480     }
481 
482     /**
483      * The parent state for all other states.
484      */
485     private final class DefaultState extends State {
486         @Override
processMessage(Message msg)487         public boolean processMessage(Message msg) {
488             if (DBG) log("DefaultState: process " + getEventName(msg.what));
489             switch (msg.what) {
490                 case EVENT_UPDATE:
491                 case EVENT_PREFERRED_NETWORK_MODE_CHANGED:
492                     resetAllTimers();
493                     transitionToCurrentState();
494                     break;
495                 case EVENT_QUIT:
496                     resetAllTimers();
497                     unRegisterForAllEvents();
498                     quit();
499                     break;
500                 case EVENT_INITIALIZE:
501                     // The reason that we do it here is because some of the works below requires
502                     // other modules (e.g. DcTracker, ServiceStateTracker), which is not created
503                     // yet when NetworkTypeController is created.
504                     registerForAllEvents();
505                     parseCarrierConfigs();
506                     break;
507                 case EVENT_DATA_RAT_CHANGED:
508                 case EVENT_NR_STATE_CHANGED:
509                 case EVENT_NR_FREQUENCY_CHANGED:
510                 case EVENT_PCO_DATA_CHANGED:
511                     // ignored
512                     break;
513                 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
514                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
515                         mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
516                     }
517                     break;
518                 case EVENT_PHYSICAL_LINK_STATE_CHANGED:
519                     AsyncResult ar = (AsyncResult) msg.obj;
520                     mPhysicalLinkState = (int) ar.result;
521                     break;
522                 case EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED:
523                     AsyncResult result = (AsyncResult) msg.obj;
524                     mIsPhysicalChannelConfigOn = (boolean) result.result;
525                     if (DBG) {
526                         log("mIsPhysicalChannelConfigOn changed to: " + mIsPhysicalChannelConfigOn);
527                     }
528                     if (!mIsPhysicalChannelConfigOn) {
529                         resetAllTimers();
530                     }
531                     transitionToCurrentState();
532                     break;
533                 case EVENT_CARRIER_CONFIG_CHANGED:
534                     parseCarrierConfigs();
535                     resetAllTimers();
536                     transitionToCurrentState();
537                     break;
538                 case EVENT_PRIMARY_TIMER_EXPIRED:
539                     transitionWithSecondaryTimerTo((IState) msg.obj);
540                     break;
541                 case EVENT_SECONDARY_TIMER_EXPIRED:
542                     mIsSecondaryTimerActive = false;
543                     mSecondaryTimerState = "";
544                     updateTimers();
545                     updateOverrideNetworkType();
546                     break;
547                 case EVENT_RADIO_OFF_OR_UNAVAILABLE:
548                     resetAllTimers();
549                     transitionTo(mLegacyState);
550                     break;
551                 default:
552                     throw new RuntimeException("Received invalid event: " + msg.what);
553             }
554             return HANDLED;
555         }
556     }
557 
558     private final DefaultState mDefaultState = new DefaultState();
559 
560     /**
561      * Device does not have NR available, due to any of the below reasons:
562      * <ul>
563      *   <li> LTE cell does not support EN-DC
564      *   <li> LTE cell supports EN-DC, but the use of NR is restricted
565      *   <li> Data network type is not LTE, NR NSA, or NR SA
566      * </ul>
567      * This is the initial state.
568      */
569     private final class LegacyState extends State {
570         private Boolean mIsNrRestricted = false;
571 
572         @Override
enter()573         public void enter() {
574             if (DBG) log("Entering LegacyState");
575             updateTimers();
576             updateOverrideNetworkType();
577             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
578                 mIsNrRestricted = isNrRestricted();
579                 mPreviousState = getName();
580             }
581         }
582 
583         @Override
processMessage(Message msg)584         public boolean processMessage(Message msg) {
585             if (DBG) log("LegacyState: process " + getEventName(msg.what));
586             updateTimers();
587             int rat = getDataNetworkType();
588             switch (msg.what) {
589                 case EVENT_DATA_RAT_CHANGED:
590                     if (rat == TelephonyManager.NETWORK_TYPE_NR || isLte(rat) && isNrConnected()) {
591                         transitionTo(mNrConnectedState);
592                     } else if (isLte(rat) && isNrNotRestricted()) {
593                         transitionWithTimerTo(isPhysicalLinkActive()
594                                 ? mLteConnectedState : mIdleState);
595                     } else {
596                         if (!isLte(rat)) {
597                             // Rat is 3G or 2G, and it doesn't need NR timer.
598                             resetAllTimers();
599                         }
600                         updateOverrideNetworkType();
601                     }
602                     mIsNrRestricted = isNrRestricted();
603                     break;
604                 case EVENT_NR_STATE_CHANGED:
605                     if (isNrConnected()) {
606                         transitionTo(mNrConnectedState);
607                     } else if (isLte(rat) && isNrNotRestricted()) {
608                         transitionWithTimerTo(isPhysicalLinkActive()
609                                 ? mLteConnectedState : mIdleState);
610                     } else if (isLte(rat) && isNrRestricted()) {
611                         updateOverrideNetworkType();
612                     }
613                     mIsNrRestricted = isNrRestricted();
614                     break;
615                 case EVENT_NR_FREQUENCY_CHANGED:
616                     // ignored
617                     break;
618                 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
619                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
620                         mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
621                         if (mIsTimerResetEnabledForLegacyStateRRCIdle && !isPhysicalLinkActive()) {
622                             resetAllTimers();
623                         }
624                     }
625                     // Update in case of LTE/LTE+ switch
626                     updateOverrideNetworkType();
627                     break;
628                 case EVENT_PHYSICAL_LINK_STATE_CHANGED:
629                     AsyncResult ar = (AsyncResult) msg.obj;
630                     mPhysicalLinkState = (int) ar.result;
631                     if (mIsTimerResetEnabledForLegacyStateRRCIdle && !isPhysicalLinkActive()) {
632                         resetAllTimers();
633                         updateOverrideNetworkType();
634                     }
635                     break;
636                 default:
637                     return NOT_HANDLED;
638             }
639             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
640                 mPreviousState = getName();
641             }
642             return HANDLED;
643         }
644 
645         @Override
getName()646         public String getName() {
647             return mIsNrRestricted  ? STATE_RESTRICTED : STATE_LEGACY;
648         }
649     }
650 
651     private final LegacyState mLegacyState = new LegacyState();
652 
653     /**
654      * Device does not have any physical connection with the cell (RRC idle).
655      */
656     private final class IdleState extends State {
657         @Override
enter()658         public void enter() {
659             if (DBG) log("Entering IdleState");
660             updateTimers();
661             updateOverrideNetworkType();
662             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
663                 mPreviousState = getName();
664             }
665         }
666 
667         @Override
processMessage(Message msg)668         public boolean processMessage(Message msg) {
669             if (DBG) log("IdleState: process " + getEventName(msg.what));
670             updateTimers();
671             switch (msg.what) {
672                 case EVENT_DATA_RAT_CHANGED:
673                     int rat = getDataNetworkType();
674                     if (rat == TelephonyManager.NETWORK_TYPE_NR) {
675                         transitionTo(mNrConnectedState);
676                     } else if (!isLte(rat) || !isNrNotRestricted()) {
677                         transitionWithTimerTo(mLegacyState);
678                     }
679                     break;
680                 case EVENT_NR_STATE_CHANGED:
681                     if (isNrConnected()) {
682                         transitionTo(mNrConnectedState);
683                     } else if (!isNrNotRestricted()) {
684                         transitionWithTimerTo(mLegacyState);
685                     }
686                     break;
687                 case EVENT_NR_FREQUENCY_CHANGED:
688                     // ignore
689                     break;
690                 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
691                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
692                         mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
693                         if (isNrNotRestricted()) {
694                             // NOT_RESTRICTED_RRC_IDLE -> NOT_RESTRICTED_RRC_CON
695                             if (isPhysicalLinkActive()) {
696                                 transitionWithTimerTo(mLteConnectedState);
697                                 break;
698                             }
699                         } else {
700                             log("NR state changed. Sending EVENT_NR_STATE_CHANGED");
701                             sendMessage(EVENT_NR_STATE_CHANGED);
702                         }
703                     }
704                     // Update in case of LTE/LTE+ switch
705                     updateOverrideNetworkType();
706                     break;
707                 case EVENT_PHYSICAL_LINK_STATE_CHANGED:
708                     AsyncResult ar = (AsyncResult) msg.obj;
709                     mPhysicalLinkState = (int) ar.result;
710                     if (isNrNotRestricted()) {
711                         // NOT_RESTRICTED_RRC_IDLE -> NOT_RESTRICTED_RRC_CON
712                         if (isPhysicalLinkActive()) {
713                             transitionWithTimerTo(mLteConnectedState);
714                         }
715                     } else {
716                         log("NR state changed. Sending EVENT_NR_STATE_CHANGED");
717                         sendMessage(EVENT_NR_STATE_CHANGED);
718                     }
719                     break;
720                 default:
721                     return NOT_HANDLED;
722             }
723             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
724                 mPreviousState = getName();
725             }
726             return HANDLED;
727         }
728 
729         @Override
getName()730         public String getName() {
731             return STATE_NOT_RESTRICTED_RRC_IDLE;
732         }
733     }
734 
735     private final IdleState mIdleState = new IdleState();
736 
737     /**
738      * Device is connected to LTE as the primary cell (RRC connected).
739      */
740     private final class LteConnectedState extends State {
741         @Override
enter()742         public void enter() {
743             if (DBG) log("Entering LteConnectedState");
744             updateTimers();
745             updateOverrideNetworkType();
746             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
747                 mPreviousState = getName();
748             }
749         }
750 
751         @Override
processMessage(Message msg)752         public boolean processMessage(Message msg) {
753             if (DBG) log("LteConnectedState: process " + getEventName(msg.what));
754             updateTimers();
755             switch (msg.what) {
756                 case EVENT_DATA_RAT_CHANGED:
757                     int rat = getDataNetworkType();
758                     if (rat == TelephonyManager.NETWORK_TYPE_NR) {
759                         transitionTo(mNrConnectedState);
760                     } else if (!isLte(rat) || !isNrNotRestricted()) {
761                         transitionWithTimerTo(mLegacyState);
762                     }
763                     break;
764                 case EVENT_NR_STATE_CHANGED:
765                     if (isNrConnected()) {
766                         transitionTo(mNrConnectedState);
767                     } else if (!isNrNotRestricted()) {
768                         transitionWithTimerTo(mLegacyState);
769                     }
770                     break;
771                 case EVENT_NR_FREQUENCY_CHANGED:
772                     // ignore
773                     break;
774                 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
775                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
776                         mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
777                         if (isNrNotRestricted()) {
778                             // NOT_RESTRICTED_RRC_CON -> NOT_RESTRICTED_RRC_IDLE
779                             if (!isPhysicalLinkActive()) {
780                                 transitionWithTimerTo(mIdleState);
781                                 break;
782                             }
783                         } else {
784                             log("NR state changed. Sending EVENT_NR_STATE_CHANGED");
785                             sendMessage(EVENT_NR_STATE_CHANGED);
786                         }
787                     }
788                     // Update in case of LTE/LTE+ switch
789                     updateOverrideNetworkType();
790                     break;
791                 case EVENT_PHYSICAL_LINK_STATE_CHANGED:
792                     AsyncResult ar = (AsyncResult) msg.obj;
793                     mPhysicalLinkState = (int) ar.result;
794                     if (isNrNotRestricted()) {
795                         // NOT_RESTRICTED_RRC_CON -> NOT_RESTRICTED_RRC_IDLE
796                         if (!isPhysicalLinkActive()) {
797                             transitionWithTimerTo(mIdleState);
798                         }
799                     } else {
800                         log("NR state changed. Sending EVENT_NR_STATE_CHANGED");
801                         sendMessage(EVENT_NR_STATE_CHANGED);
802                     }
803                     break;
804                 default:
805                     return NOT_HANDLED;
806             }
807             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
808                 mPreviousState = getName();
809             }
810             return HANDLED;
811         }
812 
813         @Override
getName()814         public String getName() {
815             return STATE_NOT_RESTRICTED_RRC_CON;
816         }
817     }
818 
819     private final LteConnectedState mLteConnectedState = new LteConnectedState();
820 
821     /**
822      * Device is connected to 5G NR as the secondary cell.
823      */
824     private final class NrConnectedState extends State {
825         private Boolean mIsNrAdvanced = false;
826 
827         @Override
enter()828         public void enter() {
829             if (DBG) log("Entering NrConnectedState");
830             updateTimers();
831             updateOverrideNetworkType();
832             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
833                 mIsNrAdvanced = isNrAdvanced();
834                 mPreviousState = getName();
835             }
836         }
837 
838         @Override
processMessage(Message msg)839         public boolean processMessage(Message msg) {
840             if (DBG) log("NrConnectedState: process " + getEventName(msg.what));
841             updateTimers();
842             int rat = getDataNetworkType();
843             switch (msg.what) {
844                 case EVENT_DATA_RAT_CHANGED:
845                     if (rat == TelephonyManager.NETWORK_TYPE_NR || isLte(rat) && isNrConnected()) {
846                         updateOverrideNetworkType();
847                     } else if (isLte(rat) && isNrNotRestricted()) {
848                         transitionWithTimerTo(isPhysicalLinkActive()
849                                 ? mLteConnectedState : mIdleState);
850                     } else {
851                         transitionWithTimerTo(mLegacyState);
852                     }
853                     break;
854                 case EVENT_NR_STATE_CHANGED:
855                     if (isLte(rat) && isNrNotRestricted()) {
856                         transitionWithTimerTo(isPhysicalLinkActive()
857                                 ? mLteConnectedState : mIdleState);
858                     } else if (rat != TelephonyManager.NETWORK_TYPE_NR && !isNrConnected()) {
859                         transitionWithTimerTo(mLegacyState);
860                     }
861                     break;
862                 case EVENT_PCO_DATA_CHANGED:
863                     handlePcoData((AsyncResult) msg.obj);
864                     break;
865                 case EVENT_NR_FREQUENCY_CHANGED:
866                 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
867                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
868                         mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
869                     }
870                     updateNrAdvancedState();
871                     break;
872                 case EVENT_PHYSICAL_LINK_STATE_CHANGED:
873                     AsyncResult ar = (AsyncResult) msg.obj;
874                     mPhysicalLinkState = (int) ar.result;
875                     if (!isNrConnected()) {
876                         log("NR state changed. Sending EVENT_NR_STATE_CHANGED");
877                         sendMessage(EVENT_NR_STATE_CHANGED);
878                     }
879                     break;
880                 default:
881                     return NOT_HANDLED;
882             }
883             if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
884                 mPreviousState = getName();
885             }
886             return HANDLED;
887         }
888 
889         @Override
getName()890         public String getName() {
891             return mIsNrAdvanced ? STATE_CONNECTED_NR_ADVANCED : STATE_CONNECTED;
892         }
893 
updateNrAdvancedState()894         private void updateNrAdvancedState() {
895             if (!isNrConnected()) {
896                 log("NR state changed. Sending EVENT_NR_STATE_CHANGED");
897                 sendMessage(EVENT_NR_STATE_CHANGED);
898                 return;
899             }
900             if (!isNrAdvanced()) {
901                 // STATE_CONNECTED_NR_ADVANCED -> STATE_CONNECTED
902                 transitionWithTimerTo(mNrConnectedState);
903             } else {
904                 // STATE_CONNECTED -> STATE_CONNECTED_NR_ADVANCED
905                 transitionTo(mNrConnectedState);
906             }
907             mIsNrAdvanced = isNrAdvanced();
908         }
909 
handlePcoData(AsyncResult ar)910         private void handlePcoData(AsyncResult ar) {
911             if (ar.exception != null) {
912                 loge("PCO_DATA exception: " + ar.exception);
913                 return;
914             }
915             PcoData pcodata = (PcoData) ar.result;
916             if (pcodata == null) {
917                 return;
918             }
919             log("EVENT_PCO_DATA_CHANGED: pco data: " + pcodata);
920             DcTracker dcTracker = mPhone.getDcTracker(
921                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
922             DataConnection dc =
923                     dcTracker != null ? dcTracker.getDataConnectionByContextId(pcodata.cid) : null;
924             ApnSetting apnSettings = dc != null ? dc.getApnSetting() : null;
925             if (apnSettings != null && apnSettings.canHandleType(ApnSetting.TYPE_DEFAULT)
926                     && mNrAdvancedCapablePcoId > 0
927                     && pcodata.pcoId == mNrAdvancedCapablePcoId
928             ) {
929                 log("EVENT_PCO_DATA_CHANGED: Nr Advanced is allowed by PCO.");
930                 mIsNrAdvancedAllowedByPco = pcodata.contents[0] == 1;
931                 updateNrAdvancedState();
932             }
933         }
934     }
935 
936     private final NrConnectedState mNrConnectedState = new NrConnectedState();
937 
transitionWithTimerTo(IState destState)938     private void transitionWithTimerTo(IState destState) {
939         String destName = destState.getName();
940         OverrideTimerRule rule = mOverrideTimerRules.get(mPreviousState);
941         if (rule != null && rule.getTimer(destName) > 0) {
942             if (DBG) log("Primary timer started for state: " + mPreviousState);
943             mPrimaryTimerState = mPreviousState;
944             mPreviousState = getCurrentState().getName();
945             mIsPrimaryTimerActive = true;
946             sendMessageDelayed(EVENT_PRIMARY_TIMER_EXPIRED, destState,
947                     rule.getTimer(destName) * 1000);
948         }
949         transitionTo(destState);
950     }
951 
transitionWithSecondaryTimerTo(IState destState)952     private void transitionWithSecondaryTimerTo(IState destState) {
953         String currentName = getCurrentState().getName();
954         OverrideTimerRule rule = mOverrideTimerRules.get(mPrimaryTimerState);
955         if (rule != null && rule.getSecondaryTimer(currentName) > 0) {
956             if (DBG) log("Secondary timer started for state: " + currentName);
957             mSecondaryTimerState = currentName;
958             mPreviousState = currentName;
959             mIsSecondaryTimerActive = true;
960             sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState,
961                     rule.getSecondaryTimer(currentName) * 1000);
962         }
963         mIsPrimaryTimerActive = false;
964         transitionTo(getCurrentState());
965     }
966 
transitionToCurrentState()967     private void transitionToCurrentState() {
968         int dataRat = getDataNetworkType();
969         IState transitionState;
970         if (dataRat == TelephonyManager.NETWORK_TYPE_NR || isNrConnected()) {
971             transitionState = mNrConnectedState;
972             mPreviousState = isNrAdvanced() ? STATE_CONNECTED_NR_ADVANCED : STATE_CONNECTED;
973         } else if (isLte(dataRat) && isNrNotRestricted()) {
974             if (isPhysicalLinkActive()) {
975                 transitionState = mLteConnectedState;
976                 mPreviousState = STATE_NOT_RESTRICTED_RRC_CON;
977             } else {
978                 transitionState = mIdleState;
979                 mPreviousState = STATE_NOT_RESTRICTED_RRC_IDLE;
980             }
981         } else {
982             transitionState = mLegacyState;
983             mPreviousState = isNrRestricted() ? STATE_RESTRICTED : STATE_LEGACY;
984         }
985         if (!transitionState.equals(getCurrentState())) {
986             transitionTo(transitionState);
987         } else {
988             updateOverrideNetworkType();
989         }
990     }
991 
updateTimers()992     private void updateTimers() {
993         String currentState = getCurrentState().getName();
994 
995         if (mIsPrimaryTimerActive && getOverrideNetworkType() == getCurrentOverrideNetworkType()) {
996             // remove primary timer if device goes back to the original icon
997             if (DBG) {
998                 log("Remove primary timer since icon of primary state and current icon equal: "
999                         + mPrimaryTimerState);
1000             }
1001             removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
1002             mIsPrimaryTimerActive = false;
1003             mPrimaryTimerState = "";
1004         }
1005 
1006         if (mIsSecondaryTimerActive && !mSecondaryTimerState.equals(currentState)) {
1007             // remove secondary timer if devices is no longer in secondary timer state
1008             if (DBG) {
1009                 log("Remove secondary timer since current state (" +  currentState
1010                         + ") is no longer secondary timer state (" + mSecondaryTimerState + ").");
1011             }
1012             removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
1013             mIsSecondaryTimerActive = false;
1014             mSecondaryTimerState = "";
1015         }
1016 
1017         if (currentState.equals(STATE_CONNECTED_NR_ADVANCED)) {
1018             resetAllTimers();
1019         }
1020 
1021         int rat = getDataNetworkType();
1022         if (!isLte(rat) && rat != TelephonyManager.NETWORK_TYPE_NR) {
1023             // Rat is 3G or 2G, and it doesn't need NR timer.
1024             resetAllTimers();
1025         }
1026     }
1027 
resetAllTimers()1028     private void resetAllTimers() {
1029         if (DBG) {
1030             log("Remove all timers");
1031         }
1032         removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
1033         removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
1034         mIsPrimaryTimerActive = false;
1035         mIsSecondaryTimerActive = false;
1036         mPrimaryTimerState = "";
1037         mSecondaryTimerState = "";
1038     }
1039 
1040     /**
1041      * Private class defining timer rules between states to prevent flickering. These rules are
1042      * created in {@link #parseCarrierConfigs()} based on various carrier configs.
1043      */
1044     private class OverrideTimerRule {
1045         /** The 5G state this timer rule applies for. See {@link #ALL_STATES}. */
1046         final String mState;
1047 
1048         /**
1049          * The override network type associated with this 5G state. This is the icon that will be
1050          * displayed on the status bar. An override type of NONE will display the LTE value instead.
1051          */
1052         final int mOverrideType;
1053 
1054         /**
1055          * A map of destination states and associated timers. If the 5G state changes from mState
1056          * to the destination state, keep the override type until either the primary timer expires
1057          * or mState is regained.
1058          */
1059         final Map<String, Integer> mPrimaryTimers;
1060 
1061         /**
1062          * A map of secondary states and associated timers. After the primary timer expires, keep
1063          * the override type until either the secondary timer expires or the device is no longer in
1064          * the secondary state.
1065          */
1066         final Map<String, Integer> mSecondaryTimers;
1067 
OverrideTimerRule(String state, int overrideType)1068         OverrideTimerRule(String state, int overrideType) {
1069             mState = state;
1070             mOverrideType = overrideType;
1071             mPrimaryTimers = new HashMap<>();
1072             mSecondaryTimers = new HashMap<>();
1073         }
1074 
1075         /**
1076          * Add a primary timer.
1077          * @param destination Transitions from mState to the destination state.
1078          * @param duration How long to keep the override type after transition to destination state.
1079          */
addTimer(String destination, int duration)1080         public void addTimer(String destination, int duration) {
1081             mPrimaryTimers.put(destination, duration);
1082         }
1083 
1084         /**
1085          * Add a secondary timer
1086          * @param secondaryState Stays in secondaryState after primary timer expires.
1087          * @param duration How long to keep the override type while in secondaryState.
1088          */
addSecondaryTimer(String secondaryState, int duration)1089         public void addSecondaryTimer(String secondaryState, int duration) {
1090             mSecondaryTimers.put(secondaryState, duration);
1091         }
1092 
1093         /**
1094          * @return Primary timer duration from mState to destination state, or 0 if not defined.
1095          */
getTimer(String destination)1096         public int getTimer(String destination) {
1097             Integer timer = mPrimaryTimers.get(destination);
1098             timer = timer == null ? mPrimaryTimers.get(STATE_ANY) : timer;
1099             return timer == null ? 0 : timer;
1100         }
1101 
1102         /**
1103          * @return Secondary timer duration for secondaryState, or 0 if not defined.
1104          */
getSecondaryTimer(String secondaryState)1105         public int getSecondaryTimer(String secondaryState) {
1106             Integer secondaryTimer = mSecondaryTimers.get(secondaryState);
1107             secondaryTimer = secondaryTimer == null
1108                     ? mSecondaryTimers.get(STATE_ANY) : secondaryTimer;
1109             return secondaryTimer == null ? 0 : secondaryTimer;
1110         }
1111 
1112         @Override
toString()1113         public String toString() {
1114             return "{mState=" + mState
1115                     + ", mOverrideType="
1116                     + TelephonyDisplayInfo.overrideNetworkTypeToString(mOverrideType)
1117                     + ", mPrimaryTimers=" + mPrimaryTimers
1118                     + ", mSecondaryTimers=" + mSecondaryTimers + "}";
1119         }
1120     }
1121 
isNrConnected()1122     private boolean isNrConnected() {
1123         return mPhone.getServiceState().getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED;
1124     }
1125 
isNrNotRestricted()1126     private boolean isNrNotRestricted() {
1127         return mPhone.getServiceState().getNrState()
1128                 == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED;
1129     }
1130 
isNrRestricted()1131     private boolean isNrRestricted() {
1132         return mPhone.getServiceState().getNrState()
1133                 == NetworkRegistrationInfo.NR_STATE_RESTRICTED;
1134     }
1135 
isNrAdvanced()1136     private boolean isNrAdvanced() {
1137         return isNrAdvancedCapable() && (isNrMmwave() || isAdditionalNrAdvancedBand());
1138     }
1139 
isNrMmwave()1140     private boolean isNrMmwave() {
1141         return mPhone.getServiceState().getNrFrequencyRange()
1142                 == ServiceState.FREQUENCY_RANGE_MMWAVE;
1143     }
1144 
isAdditionalNrAdvancedBand()1145     private boolean isAdditionalNrAdvancedBand() {
1146         List<PhysicalChannelConfig> physicalChannelConfigList =
1147                 mPhone.getServiceStateTracker().getPhysicalChannelConfigList();
1148         if (ArrayUtils.isEmpty(mAdditionalNrAdvancedBandsList)
1149                 || physicalChannelConfigList == null) {
1150             return false;
1151         }
1152         for (PhysicalChannelConfig item : physicalChannelConfigList) {
1153             if (item.getNetworkType() == TelephonyManager.NETWORK_TYPE_NR
1154                     && ArrayUtils.contains(mAdditionalNrAdvancedBandsList, item.getBand())) {
1155                 return true;
1156             }
1157         }
1158         return false;
1159     }
1160 
isNrAdvancedCapable()1161     private boolean isNrAdvancedCapable() {
1162         if (mNrAdvancedCapablePcoId > 0) {
1163             return mIsNrAdvancedAllowedByPco;
1164         }
1165         return true;
1166     }
1167 
isLte(int rat)1168     private boolean isLte(int rat) {
1169         return rat == TelephonyManager.NETWORK_TYPE_LTE
1170                 || rat == TelephonyManager.NETWORK_TYPE_LTE_CA;
1171     }
1172 
isPhysicalLinkActive()1173     private boolean isPhysicalLinkActive() {
1174         return mPhysicalLinkState == DcController.PHYSICAL_LINK_ACTIVE;
1175     }
1176 
getPhysicalLinkStateFromPhysicalChannelConfig()1177     private int getPhysicalLinkStateFromPhysicalChannelConfig() {
1178         List<PhysicalChannelConfig> physicalChannelConfigList =
1179                 mPhone.getServiceStateTracker().getPhysicalChannelConfigList();
1180         return (physicalChannelConfigList == null || physicalChannelConfigList.isEmpty())
1181                 ? DcController.PHYSICAL_LINK_NOT_ACTIVE : DcController.PHYSICAL_LINK_ACTIVE;
1182     }
1183 
getDataNetworkType()1184     private int getDataNetworkType() {
1185         NetworkRegistrationInfo nri =  mPhone.getServiceState().getNetworkRegistrationInfo(
1186                 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1187         return nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN
1188                 : nri.getAccessNetworkTechnology();
1189     }
1190 
getEventName(int event)1191     private String getEventName(int event) {
1192         try {
1193             return sEvents[event];
1194         } catch (ArrayIndexOutOfBoundsException e) {
1195             return "EVENT_NOT_DEFINED";
1196         }
1197     }
1198 
isUsingPhysicalChannelConfigForRrcDetection()1199     private boolean isUsingPhysicalChannelConfigForRrcDetection() {
1200         return mIsPhysicalChannelConfig16Supported && !mIsUsingUserDataForRrcDetection;
1201     }
1202 
log(String s)1203     protected void log(String s) {
1204         Rlog.d(TAG, "[" + mPhone.getPhoneId() + "] " + s);
1205     }
1206 
loge(String s)1207     protected void loge(String s) {
1208         Rlog.e(TAG, "[" + mPhone.getPhoneId() + "] " + s);
1209     }
1210 
1211     @Override
toString()1212     public String toString() {
1213         return "mOverrideTimerRules=" + mOverrideTimerRules.toString()
1214                 + ", mLteEnhancedPattern=" + mLteEnhancedPattern
1215                 + ", mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn
1216                 + ", mIsPrimaryTimerActive=" + mIsPrimaryTimerActive
1217                 + ", mIsSecondaryTimerActive=" + mIsSecondaryTimerActive
1218                 + ", mPrimaryTimerState=" + mPrimaryTimerState
1219                 + ", mSecondaryTimerState=" + mSecondaryTimerState
1220                 + ", mPreviousState=" + mPreviousState
1221                 + ", misNrAdvanced=" + isNrAdvanced();
1222     }
1223 
1224     @Override
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1225     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
1226         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
1227         pw.print("NetworkTypeController: ");
1228         super.dump(fd, pw, args);
1229         pw.flush();
1230         pw.increaseIndent();
1231         pw.println("mSubId=" + mPhone.getSubId());
1232         pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString());
1233         pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern);
1234         pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn);
1235         pw.println("mIsPrimaryTimerActive=" + mIsPrimaryTimerActive);
1236         pw.println("mIsSecondaryTimerActive=" + mIsSecondaryTimerActive);
1237         pw.println("mIsTimerRestEnabledForLegacyStateRRCIdle="
1238                 + mIsTimerResetEnabledForLegacyStateRRCIdle);
1239         pw.println("mLtePlusThresholdBandwidth=" + mLtePlusThresholdBandwidth);
1240         pw.println("mPrimaryTimerState=" + mPrimaryTimerState);
1241         pw.println("mSecondaryTimerState=" + mSecondaryTimerState);
1242         pw.println("mPreviousState=" + mPreviousState);
1243         pw.println("mPhysicalLinkState=" + mPhysicalLinkState);
1244         pw.println("mAdditionalNrAdvancedBandsList="
1245                 + Arrays.toString(mAdditionalNrAdvancedBandsList));
1246         pw.println("mNrAdvancedCapablePcoId=" + mNrAdvancedCapablePcoId);
1247         pw.decreaseIndent();
1248         pw.flush();
1249     }
1250 }
1251