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