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