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