Merge changes from topics "displayinfocontroller", "remove_displayinfo"
* changes:
Remove DisplayInfo logic from DcTracker
DisplayInfoController and NetworkTypeController skeleton implementation
diff --git a/src/java/com/android/internal/telephony/DeviceStateMonitor.java b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
index 30153ea..f940919 100644
--- a/src/java/com/android/internal/telephony/DeviceStateMonitor.java
+++ b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
@@ -35,6 +35,8 @@
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
+import android.os.Registrant;
+import android.os.RegistrantList;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CarrierConfigManager;
import android.telephony.SignalThresholdInfo;
@@ -83,6 +85,8 @@
private final LocalLog mLocalLog = new LocalLog(100);
+ private final RegistrantList mPhysicalChannelConfigRegistrants = new RegistrantList();
+
private final NetworkRequest mWifiNetworkRequest =
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
@@ -492,6 +496,13 @@
newFilter |= IndicationFilter.BARRING_INFO;
}
+ // notify PhysicalChannelConfig registrants if state changes
+ if ((newFilter & IndicationFilter.PHYSICAL_CHANNEL_CONFIG)
+ != (mUnsolicitedResponseFilter & IndicationFilter.PHYSICAL_CHANNEL_CONFIG)) {
+ mPhysicalChannelConfigRegistrants.notifyResult(
+ (newFilter & IndicationFilter.PHYSICAL_CHANNEL_CONFIG) != 0);
+ }
+
setUnsolResponseFilter(newFilter, false);
// Pull barring info AFTER setting filter, the order matters
@@ -656,6 +667,28 @@
}
/**
+ * Register for PhysicalChannelConfig notifications changed. On change, msg.obj will be an
+ * AsyncResult with a boolean result. AsyncResult.result is true if notifications are enabled
+ * and false if they are disabled.
+ *
+ * @param h Handler to notify
+ * @param what msg.what when the message is delivered
+ * @param obj AsyncResult.userObj when the message is delivered
+ */
+ public void registerForPhysicalChannelConfigNotifChanged(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mPhysicalChannelConfigRegistrants.add(r);
+ }
+
+ /**
+ * Unregister for PhysicalChannelConfig notifications changed.
+ * @param h Handler to notify
+ */
+ public void unregisterForPhysicalChannelConfigNotifChanged(Handler h) {
+ mPhysicalChannelConfigRegistrants.remove(h);
+ }
+
+ /**
* @param msg Debug message
* @param logIntoLocalLog True if log into the local log
*/
diff --git a/src/java/com/android/internal/telephony/DisplayInfoController.java b/src/java/com/android/internal/telephony/DisplayInfoController.java
new file mode 100644
index 0000000..c73c1ea
--- /dev/null
+++ b/src/java/com/android/internal/telephony/DisplayInfoController.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.Handler;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.telephony.TelephonyDisplayInfo;
+
+import com.android.telephony.Rlog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * The DisplayInfoController updates and broadcasts all changes to {@link TelephonyDisplayInfo}.
+ * It manages all the information necessary for display purposes. Clients can register for display
+ * info changes via {@link #registerForTelephonyDisplayInfoChanged} and obtain the current
+ * TelephonyDisplayInfo via {@link #getTelephonyDisplayInfo}.
+ */
+public class DisplayInfoController extends Handler {
+ private static final String TAG = "DisplayInfoController";
+ private final Phone mPhone;
+ private final NetworkTypeController mNetworkTypeController;
+ private final RegistrantList mTelephonyDisplayInfoChangedRegistrants = new RegistrantList();
+ private TelephonyDisplayInfo mTelephonyDisplayInfo;
+
+ public DisplayInfoController(Phone phone) {
+ mPhone = phone;
+ mNetworkTypeController = new NetworkTypeController(phone, this);
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+ }
+
+ /**
+ * @return the current TelephonyDisplayInfo
+ */
+ public TelephonyDisplayInfo getTelephonyDisplayInfo() {
+ return mTelephonyDisplayInfo;
+ }
+
+ /**
+ * Update TelephonyDisplayInfo based on network type and override network type, received from
+ * NetworkTypeController.
+ */
+ public void updateTelephonyDisplayInfo() {
+ TelephonyDisplayInfo newDisplayInfo = new TelephonyDisplayInfo(
+ mPhone.getServiceState().getDataNetworkType(),
+ mNetworkTypeController.getOverrideNetworkType());
+ if (!newDisplayInfo.equals(mTelephonyDisplayInfo)) {
+ Rlog.d(TAG, "TelephonyDisplayInfo changed from " + mTelephonyDisplayInfo + " to "
+ + newDisplayInfo);
+ mTelephonyDisplayInfo = newDisplayInfo;
+ mTelephonyDisplayInfoChangedRegistrants.notifyRegistrants();
+ mPhone.notifyDisplayInfoChanged(mTelephonyDisplayInfo);
+ }
+ }
+
+ /**
+ * Register for TelephonyDisplayInfo changed.
+ * @param h Handler to notify
+ * @param what msg.what when the message is delivered
+ * @param obj msg.obj when the message is delivered
+ */
+ public void registerForTelephonyDisplayInfoChanged(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mTelephonyDisplayInfoChangedRegistrants.add(r);
+ }
+
+ /**
+ * Unregister for TelephonyDisplayInfo changed.
+ * @param h Handler to notify
+ */
+ public void unregisterForTelephonyDisplayInfoChanged(Handler h) {
+ mTelephonyDisplayInfoChangedRegistrants.remove(h);
+ }
+
+ /**
+ * Dump the current state.
+ */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("DisplayInfoController:");
+ pw.println(" mPhone=" + mPhone.getPhoneName());
+ pw.println(" mTelephonyDisplayInfo=" + mTelephonyDisplayInfo.toString());
+ pw.flush();
+ pw.println(" ***************************************");
+ mNetworkTypeController.dump(fd, pw, args);
+ pw.flush();
+ }
+}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 5d7fba4..29f57f4 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -264,8 +264,16 @@
this, this.mCi);
mDataEnabledSettings = mTelephonyComponentFactory
.inject(DataEnabledSettings.class.getName()).makeDataEnabledSettings(this);
+ mDeviceStateMonitor = mTelephonyComponentFactory.inject(DeviceStateMonitor.class.getName())
+ .makeDeviceStateMonitor(this);
- // DcTracker uses SST so needs to be created after it is instantiated
+ // DisplayInfoController creates an OverrideNetworkTypeController, which uses
+ // DeviceStateMonitor so needs to be crated after it is instantiated.
+ mDisplayInfoController = mTelephonyComponentFactory.inject(
+ DisplayInfoController.class.getName()).makeDisplayInfoController(this);
+
+ // DcTracker uses ServiceStateTracker and DisplayInfoController so needs to be created
+ // after they are instantiated
for (int transport : mTransportManager.getAvailableTransports()) {
mDcTrackers.put(transport, mTelephonyComponentFactory.inject(DcTracker.class.getName())
.makeDcTracker(this, transport));
@@ -279,9 +287,6 @@
EVENT_SET_CARRIER_DATA_ENABLED, null, false);
mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
- mDeviceStateMonitor = mTelephonyComponentFactory.inject(DeviceStateMonitor.class.getName())
- .makeDeviceStateMonitor(this);
-
mSST.registerForVoiceRegStateOrRatChanged(this, EVENT_VRS_OR_RAT_CHANGED, null);
mSettingsObserver = new SettingsObserver(context, this);
@@ -586,6 +591,16 @@
}
@Override
+ public DeviceStateMonitor getDeviceStateMonitor() {
+ return mDeviceStateMonitor;
+ }
+
+ @Override
+ public DisplayInfoController getDisplayInfoController() {
+ return mDisplayInfoController;
+ }
+
+ @Override
public void updateVoiceMail() {
if (isPhoneTypeGsm()) {
int countVoiceMessages = 0;
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
new file mode 100644
index 0000000..86b7902
--- /dev/null
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.Annotation;
+import android.telephony.CarrierConfigManager;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyDisplayInfo;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.android.internal.util.IState;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+import com.android.telephony.Rlog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * The NetworkTypeController evaluates the override network type of {@link TelephonyDisplayInfo}
+ * and sends it to {@link DisplayInfoController}. The override network type can replace the signal
+ * icon displayed on the status bar. It is affected by changes in data RAT, NR state, NR frequency,
+ * data activity, physical channel config, and carrier configurations. Based on carrier configs,
+ * NetworkTypeController also allows timers between various 5G states to prevent flickering.
+ */
+public class NetworkTypeController extends StateMachine {
+ private static final boolean DBG = true;
+ private static final String TAG = "NetworkTypeController";
+ private static final String ICON_5G = "5g";
+ private static final String ICON_5G_PLUS = "5g_plus";
+ private static final String STATE_CONNECTED_MMWAVE = "connected_mmwave";
+ private static final String STATE_CONNECTED = "connected";
+ private static final String STATE_NOT_RESTRICTED_RRC_IDLE = "not_restricted_rrc_idle";
+ private static final String STATE_NOT_RESTRICTED_RRC_CON = "not_restricted_rrc_con";
+ private static final String STATE_RESTRICTED = "restricted";
+ private static final String STATE_ANY = "any";
+ private static final String STATE_LEGACY = "legacy";
+ private static final String[] ALL_STATES = { STATE_CONNECTED_MMWAVE, STATE_CONNECTED,
+ STATE_NOT_RESTRICTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_CON, STATE_RESTRICTED };
+
+ /** Stop all timers and go to current state. */
+ public static final int EVENT_UPDATE = 0;
+ /** Quit after processing all existing messages. */
+ public static final int EVENT_QUIT = 1;
+ private static final int EVENT_DATA_RAT_CHANGED = 2;
+ private static final int EVENT_NR_STATE_CHANGED = 3;
+ private static final int EVENT_NR_FREQUENCY_CHANGED = 4;
+ private static final int EVENT_DATA_ACTIVITY_CHANGED = 5;
+ private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED = 6;
+ private static final int EVENT_CARRIER_CONFIG_CHANGED = 7;
+ private static final int EVENT_PRIMARY_TIMER_EXPIRED = 8;
+ private static final int EVENT_SECONDARY_TIMER_EXPIRED = 9;
+ private static final int[] ALL_EVENTS = { EVENT_DATA_RAT_CHANGED, EVENT_NR_STATE_CHANGED,
+ EVENT_NR_FREQUENCY_CHANGED, EVENT_DATA_ACTIVITY_CHANGED,
+ EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED, EVENT_CARRIER_CONFIG_CHANGED,
+ EVENT_PRIMARY_TIMER_EXPIRED, EVENT_SECONDARY_TIMER_EXPIRED };
+
+ private static final String[] sEvents = new String[EVENT_SECONDARY_TIMER_EXPIRED + 1];
+ static {
+ sEvents[EVENT_UPDATE] = "EVENT_UPDATE";
+ sEvents[EVENT_QUIT] = "EVENT_QUIT";
+ sEvents[EVENT_DATA_RAT_CHANGED] = "EVENT_DATA_RAT_CHANGED";
+ sEvents[EVENT_NR_STATE_CHANGED] = "EVENT_NR_STATE_CHANGED";
+ sEvents[EVENT_NR_FREQUENCY_CHANGED] = "EVENT_NR_FREQUENCY_CHANGED";
+ sEvents[EVENT_DATA_ACTIVITY_CHANGED] = "EVENT_DATA_ACTIVITY_CHANGED";
+ sEvents[EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED] =
+ "EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED";
+ sEvents[EVENT_CARRIER_CONFIG_CHANGED] = "EVENT_CARRIER_CONFIG_CHANGED";
+ sEvents[EVENT_PRIMARY_TIMER_EXPIRED] = "EVENT_PRIMARY_TIMER_EXPIRED";
+ sEvents[EVENT_SECONDARY_TIMER_EXPIRED] = "EVENT_SECONDARY_TIMER_EXPIRED";
+ }
+
+ private final Phone mPhone;
+ private final DisplayInfoController mDisplayInfoController;
+ private final TelephonyManager mTelephonyManager;
+ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)
+ && intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX,
+ SubscriptionManager.INVALID_PHONE_INDEX) == mPhone.getPhoneId()
+ && !intent.getBooleanExtra(CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK,
+ false)) {
+ sendMessage(EVENT_CARRIER_CONFIG_CHANGED);
+ }
+ }
+ };
+ private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onDataActivity(int direction) {
+ sendMessage(EVENT_DATA_ACTIVITY_CHANGED);
+ }
+ };
+
+ private Map<String, OverrideTimerRule> mOverrideTimerRules = new HashMap<>();
+ private String mLteEnhancedPattern = "";
+ private int mOverrideNetworkType;
+ private boolean mIsPhysicalChannelConfigOn;
+ private boolean mIsPrimaryTimerActive;
+ private boolean mIsSecondaryTimerActive;
+ private String mPrimaryTimerState;
+ private String mSecondaryTimerState;
+ private String mPreviousState;
+
+ /**
+ * NetworkTypeController constructor.
+ *
+ * @param phone Phone object.
+ * @param displayInfoController DisplayInfoController to send override network types to.
+ */
+ public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController) {
+ super(TAG, displayInfoController);
+ mPhone = phone;
+ mDisplayInfoController = displayInfoController;
+ mTelephonyManager = TelephonyManager.from(phone.getContext())
+ .createForSubscriptionId(phone.getSubId());
+ mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
+ mIsPhysicalChannelConfigOn = true;
+ addState(mDefaultState);
+ addState(mLegacyState, mDefaultState);
+ addState(mIdleState, mDefaultState);
+ addState(mLteConnectedState, mDefaultState);
+ addState(mNrConnectedState, mDefaultState);
+ setInitialState(mDefaultState);
+ registerForAllEvents();
+ parseCarrierConfigs();
+ start();
+ }
+
+ /**
+ * @return The current override network type, used to create TelephonyDisplayInfo in
+ * DisplayInfoController.
+ */
+ public @Annotation.OverrideNetworkType int getOverrideNetworkType() {
+ return mOverrideNetworkType;
+ }
+
+ private void registerForAllEvents() {
+ mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler(),
+ EVENT_DATA_RAT_CHANGED, null);
+ mPhone.getServiceStateTracker().registerForNrStateChanged(getHandler(),
+ EVENT_NR_STATE_CHANGED, null);
+ mPhone.getServiceStateTracker().registerForNrFrequencyChanged(getHandler(),
+ EVENT_NR_FREQUENCY_CHANGED, null);
+ mPhone.getDeviceStateMonitor().registerForPhysicalChannelConfigNotifChanged(getHandler(),
+ EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED, null);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+ if (mTelephonyManager != null) {
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_DATA_ACTIVITY);
+ }
+ }
+
+ private void unRegisterForAllEvents() {
+ mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler());
+ mPhone.getServiceStateTracker().unregisterForNrStateChanged(getHandler());
+ mPhone.getServiceStateTracker().unregisterForNrFrequencyChanged(getHandler());
+ mPhone.mDeviceStateMonitor.unregisterForPhysicalChannelConfigNotifChanged(getHandler());
+ mPhone.getContext().unregisterReceiver(mIntentReceiver);
+ if (mTelephonyManager != null) {
+ mTelephonyManager.listen(mPhoneStateListener, 0);
+ }
+ }
+
+ private void parseCarrierConfigs() {
+ String nrIconConfiguration = CarrierConfigManager.getDefaultConfig().getString(
+ CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
+ String overrideTimerRule = CarrierConfigManager.getDefaultConfig().getString(
+ CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING);
+ String overrideSecondaryTimerRule = CarrierConfigManager.getDefaultConfig().getString(
+ CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING);
+ mLteEnhancedPattern = CarrierConfigManager.getDefaultConfig().getString(
+ CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
+
+ CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager != null) {
+ PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
+ if (b != null) {
+ if (b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING) != null) {
+ nrIconConfiguration = b.getString(
+ CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
+ }
+ if (b.getString(CarrierConfigManager
+ .KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING) != null) {
+ overrideTimerRule = b.getString(
+ CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING);
+ }
+ if (b.getString(CarrierConfigManager
+ .KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING) != null) {
+ overrideSecondaryTimerRule = b.getString(
+ CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING);
+ }
+ if (b.getString(CarrierConfigManager
+ .KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING) != null) {
+ mLteEnhancedPattern = b.getString(
+ CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
+ }
+ }
+ }
+ createTimerRules(nrIconConfiguration, overrideTimerRule, overrideSecondaryTimerRule);
+ }
+
+ private void createTimerRules(String icons, String timers, String secondaryTimers) {
+ Map<String, OverrideTimerRule> tempRules = new HashMap<>();
+ if (!TextUtils.isEmpty(icons)) {
+ // Format: "STATE:ICON,STATE2:ICON2"
+ for (String pair : icons.trim().split(",")) {
+ String[] kv = (pair.trim().toLowerCase()).split(":");
+ if (kv.length != 2) {
+ if (DBG) loge("Invalid 5G icon configuration, config = " + pair);
+ continue;
+ }
+ int icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
+ if (kv[1].equals(ICON_5G)) {
+ icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
+ } else if (kv[1].equals(ICON_5G_PLUS)) {
+ icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE;
+ } else {
+ if (DBG) loge("Invalid 5G icon = " + kv[1]);
+ }
+ tempRules.put(kv[0], new OverrideTimerRule(kv[0], icon));
+ }
+ }
+ // Ensure all states have an associated OverrideTimerRule and icon
+ for (String state : ALL_STATES) {
+ if (!tempRules.containsKey(state)) {
+ tempRules.put(state, new OverrideTimerRule(
+ state, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE));
+ }
+ }
+
+ if (!TextUtils.isEmpty(timers)) {
+ // Format: "FROM_STATE,TO_STATE,DURATION;FROM_STATE_2,TO_STATE_2,DURATION_2"
+ for (String triple : timers.trim().split(";")) {
+ String[] kv = (triple.trim().toLowerCase()).split(",");
+ if (kv.length != 3) {
+ if (DBG) loge("Invalid 5G icon timer configuration, config = " + triple);
+ continue;
+ }
+ int duration;
+ try {
+ duration = Integer.parseInt(kv[2]);
+ } catch (NumberFormatException e) {
+ continue;
+ }
+ if (kv[0].equals(STATE_ANY)) {
+ for (String state : ALL_STATES) {
+ OverrideTimerRule node = tempRules.get(state);
+ node.addTimer(kv[1], duration);
+ }
+ } else {
+ OverrideTimerRule node = tempRules.get(kv[0]);
+ node.addTimer(kv[1], duration);
+ }
+ }
+ }
+
+ if (!TextUtils.isEmpty(secondaryTimers)) {
+ // Format: "PRIMARY_STATE,TO_STATE,DURATION;PRIMARY_STATE_2,TO_STATE_2,DURATION_2"
+ for (String triple : secondaryTimers.trim().split(";")) {
+ String[] kv = (triple.trim().toLowerCase()).split(",");
+ if (kv.length != 3) {
+ if (DBG) {
+ loge("Invalid 5G icon secondary timer configuration, config = " + triple);
+ }
+ continue;
+ }
+ int duration;
+ try {
+ duration = Integer.parseInt(kv[2]);
+ } catch (NumberFormatException e) {
+ continue;
+ }
+ if (kv[0].equals(STATE_ANY)) {
+ for (String state : ALL_STATES) {
+ OverrideTimerRule node = tempRules.get(state);
+ node.addSecondaryTimer(kv[1], duration);
+ }
+ } else {
+ OverrideTimerRule node = tempRules.get(kv[0]);
+ node.addSecondaryTimer(kv[1], duration);
+ }
+ }
+ }
+
+ mOverrideTimerRules = tempRules;
+ if (DBG) log("mOverrideTimerRules: " + mOverrideTimerRules);
+ }
+
+ private void updateOverrideNetworkType() {
+ if (mIsPrimaryTimerActive || mIsSecondaryTimerActive) {
+ if (DBG) log("Skip updating override network type since timer is active.");
+ return;
+ }
+ int displayNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
+ int dataNetworkType = mPhone.getServiceState().getDataNetworkType();
+ // NR display is not accurate when physical channel config notifications are off
+ if (mIsPhysicalChannelConfigOn
+ && (mPhone.getServiceState().getNrState() != NetworkRegistrationInfo.NR_STATE_NONE
+ || dataNetworkType == TelephonyManager.NETWORK_TYPE_NR)) {
+ // Process NR display network type
+ displayNetworkType = getNrDisplayType();
+ if (displayNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
+ // Use LTE values if 5G values aren't defined
+ displayNetworkType = getLteDisplayType();
+ }
+ } else if (isLte(dataNetworkType)) {
+ // Process LTE display network type
+ displayNetworkType = getLteDisplayType();
+ }
+ mOverrideNetworkType = displayNetworkType;
+ mDisplayInfoController.updateTelephonyDisplayInfo();
+ }
+
+ private @Annotation.OverrideNetworkType int getNrDisplayType() {
+ // Icon display keys in order of priority
+ List<String> keys = new ArrayList<>();
+ // TODO: Update for NR SA
+ switch (mPhone.getServiceState().getNrState()) {
+ case NetworkRegistrationInfo.NR_STATE_CONNECTED:
+ if (isNrMmwave()) {
+ keys.add(STATE_CONNECTED_MMWAVE);
+ }
+ keys.add(STATE_CONNECTED);
+ break;
+ case NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED:
+ keys.add(isDataActive() ? STATE_NOT_RESTRICTED_RRC_CON
+ : STATE_NOT_RESTRICTED_RRC_IDLE);
+ break;
+ case NetworkRegistrationInfo.NR_STATE_RESTRICTED:
+ keys.add(STATE_RESTRICTED);
+ break;
+ }
+
+ for (String key : keys) {
+ OverrideTimerRule rule = mOverrideTimerRules.get(key);
+ if (rule != null && rule.mOverrideType
+ != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
+ return rule.mOverrideType;
+ }
+ }
+ return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
+ }
+
+ private @Annotation.OverrideNetworkType int getLteDisplayType() {
+ int value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
+ if (mPhone.getServiceState().getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA
+ || mPhone.getServiceState().isUsingCarrierAggregation()) {
+ value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA;
+ }
+ if (isLteEnhancedAvailable()) {
+ value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO;
+ }
+ return value;
+ }
+
+ private boolean isLteEnhancedAvailable() {
+ if (TextUtils.isEmpty(mLteEnhancedPattern)) {
+ return false;
+ }
+ Pattern stringPattern = Pattern.compile(mLteEnhancedPattern);
+ for (String opName : new String[] {mPhone.getServiceState().getOperatorAlphaLongRaw(),
+ mPhone.getServiceState().getOperatorAlphaShortRaw()}) {
+ if (!TextUtils.isEmpty(opName)) {
+ Matcher matcher = stringPattern.matcher(opName);
+ if (matcher.find()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * The parent state for all other states.
+ */
+ private final class DefaultState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("DefaultState: process " + getEventName(msg.what));
+ switch (msg.what) {
+ case EVENT_UPDATE:
+ resetAllTimers();
+ transitionToCurrentState();
+ break;
+ case EVENT_QUIT:
+ resetAllTimers();
+ unRegisterForAllEvents();
+ quit();
+ break;
+ case EVENT_DATA_RAT_CHANGED:
+ case EVENT_NR_STATE_CHANGED:
+ case EVENT_NR_FREQUENCY_CHANGED:
+ case EVENT_DATA_ACTIVITY_CHANGED:
+ // ignored
+ break;
+ case EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED:
+ AsyncResult result = (AsyncResult) msg.obj;
+ mIsPhysicalChannelConfigOn = (boolean) result.result;
+ for (int event : ALL_EVENTS) {
+ removeMessages(event);
+ }
+ if (!mIsPhysicalChannelConfigOn) {
+ resetAllTimers();
+ }
+ transitionToCurrentState();
+ break;
+ case EVENT_CARRIER_CONFIG_CHANGED:
+ for (int event : ALL_EVENTS) {
+ removeMessages(event);
+ }
+ parseCarrierConfigs();
+ resetAllTimers();
+ transitionToCurrentState();
+ break;
+ case EVENT_PRIMARY_TIMER_EXPIRED:
+ transitionWithSecondaryTimerTo((IState) msg.obj);
+ break;
+ case EVENT_SECONDARY_TIMER_EXPIRED:
+ mIsSecondaryTimerActive = false;
+ mSecondaryTimerState = "";
+ updateTimers();
+ updateOverrideNetworkType();
+ break;
+ default:
+ throw new RuntimeException("Received invalid event: " + msg.what);
+ }
+ return HANDLED;
+ }
+ }
+
+ private final DefaultState mDefaultState = new DefaultState();
+
+ /**
+ * Device does not have NR available, due to any of the below reasons:
+ * <ul>
+ * <li> LTE cell does not support EN-DC
+ * <li> LTE cell supports EN-DC, but the use of NR is restricted
+ * <li> Data network type is not LTE, NR NSA, or NR SA
+ * </ul>
+ * This is the initial state.
+ */
+ private final class LegacyState extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("Entering LegacyState");
+ updateTimers();
+ updateOverrideNetworkType();
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("LegacyState: process " + getEventName(msg.what));
+ updateTimers();
+ int rat = mPhone.getServiceState().getDataNetworkType();
+ switch (msg.what) {
+ case EVENT_DATA_RAT_CHANGED:
+ if (rat == TelephonyManager.NETWORK_TYPE_NR || isLte(rat) && isNrConnected()) {
+ transitionTo(mNrConnectedState);
+ } else if (isLte(rat) && isNrNotRestricted()) {
+ transitionWithTimerTo(isDataActive() ? mLteConnectedState : mIdleState);
+ }
+ break;
+ case EVENT_NR_STATE_CHANGED:
+ if (isNrConnected()) {
+ transitionTo(mNrConnectedState);
+ } else if (isLte(rat) && isNrNotRestricted()) {
+ transitionWithTimerTo(isDataActive() ? mLteConnectedState : mIdleState);
+ } else if (isLte(rat) && isNrRestricted()) {
+ updateOverrideNetworkType();
+ }
+ break;
+ case EVENT_NR_FREQUENCY_CHANGED:
+ case EVENT_DATA_ACTIVITY_CHANGED:
+ // ignored
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ return HANDLED;
+ }
+
+ @Override
+ public String getName() {
+ return isNrRestricted() ? STATE_RESTRICTED : STATE_LEGACY;
+ }
+ }
+
+ private final LegacyState mLegacyState = new LegacyState();
+
+ /**
+ * Device does not have any physical connection with the cell (RRC idle).
+ */
+ private final class IdleState extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("Entering IdleState");
+ updateTimers();
+ updateOverrideNetworkType();
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("IdleState: process " + getEventName(msg.what));
+ updateTimers();
+ switch (msg.what) {
+ case EVENT_DATA_RAT_CHANGED:
+ int rat = mPhone.getServiceState().getDataNetworkType();
+ if (rat == TelephonyManager.NETWORK_TYPE_NR) {
+ transitionTo(mNrConnectedState);
+ } else if (!isLte(rat) || !isNrNotRestricted()) {
+ transitionWithTimerTo(mLegacyState);
+ }
+ break;
+ case EVENT_NR_STATE_CHANGED:
+ if (isNrConnected()) {
+ transitionTo(mNrConnectedState);
+ } else if (!isNrNotRestricted()) {
+ transitionWithTimerTo(mLegacyState);
+ }
+ break;
+ case EVENT_NR_FREQUENCY_CHANGED:
+ // ignore
+ break;
+ case EVENT_DATA_ACTIVITY_CHANGED:
+ if (isDataActive()) {
+ transitionWithTimerTo(mLteConnectedState);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ return HANDLED;
+ }
+
+ @Override
+ public String getName() {
+ return STATE_NOT_RESTRICTED_RRC_IDLE;
+ }
+ }
+
+ private final IdleState mIdleState = new IdleState();
+
+ /**
+ * Device is connected to LTE as the primary cell (RRC connected).
+ */
+ private final class LteConnectedState extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("Entering LteConnectedState");
+ updateTimers();
+ updateOverrideNetworkType();
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("LteConnectedState: process " + getEventName(msg.what));
+ updateTimers();
+ switch (msg.what) {
+ case EVENT_DATA_RAT_CHANGED:
+ int rat = mPhone.getServiceState().getDataNetworkType();
+ if (rat == TelephonyManager.NETWORK_TYPE_NR) {
+ transitionTo(mNrConnectedState);
+ } else if (!isLte(rat) || !isNrNotRestricted()) {
+ transitionWithTimerTo(mLegacyState);
+ }
+ break;
+ case EVENT_NR_STATE_CHANGED:
+ if (isNrConnected()) {
+ transitionTo(mNrConnectedState);
+ } else if (!isNrNotRestricted()) {
+ transitionWithTimerTo(mLegacyState);
+ }
+ break;
+ case EVENT_NR_FREQUENCY_CHANGED:
+ // ignore
+ break;
+ case EVENT_DATA_ACTIVITY_CHANGED:
+ if (!isDataActive()) {
+ transitionWithTimerTo(mIdleState);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ return HANDLED;
+ }
+
+ @Override
+ public String getName() {
+ return STATE_NOT_RESTRICTED_RRC_CON;
+ }
+ }
+
+ private final LteConnectedState mLteConnectedState = new LteConnectedState();
+
+ /**
+ * Device is connected to 5G NR as the secondary cell.
+ */
+ private final class NrConnectedState extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("Entering NrConnectedState");
+ updateTimers();
+ updateOverrideNetworkType();
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("NrConnectedState: process " + getEventName(msg.what));
+ updateTimers();
+ int rat = mPhone.getServiceState().getDataNetworkType();
+ switch (msg.what) {
+ case EVENT_DATA_RAT_CHANGED:
+ if (rat == TelephonyManager.NETWORK_TYPE_NR || isLte(rat) && isNrConnected()) {
+ updateOverrideNetworkType();
+ } else if (isLte(rat) && isNrNotRestricted()) {
+ transitionWithTimerTo(isDataActive() ? mLteConnectedState : mIdleState);
+ } else {
+ transitionWithTimerTo(mLegacyState);
+ }
+ break;
+ case EVENT_NR_STATE_CHANGED:
+ if (isLte(rat) && isNrNotRestricted()) {
+ transitionWithTimerTo(isDataActive() ? mLteConnectedState : mIdleState);
+ } else if (rat != TelephonyManager.NETWORK_TYPE_NR && !isNrConnected()) {
+ transitionWithTimerTo(mLegacyState);
+ }
+ break;
+ case EVENT_NR_FREQUENCY_CHANGED:
+ if (!isNrMmwave()) {
+ transitionWithTimerTo(mNrConnectedState);
+ } else {
+ updateOverrideNetworkType();
+ }
+ break;
+ case EVENT_DATA_ACTIVITY_CHANGED:
+ // ignore
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ return HANDLED;
+ }
+
+ @Override
+ public String getName() {
+ return isNrMmwave() ? STATE_CONNECTED_MMWAVE : STATE_CONNECTED;
+ }
+ }
+
+ private final NrConnectedState mNrConnectedState = new NrConnectedState();
+
+ private void transitionWithTimerTo(IState destState) {
+ String destName = destState.getName();
+ OverrideTimerRule rule = mOverrideTimerRules.get(mPreviousState);
+ if (rule != null && rule.getTimer(destName) > 0) {
+ if (DBG) log("Primary timer started for state: " + mPreviousState);
+ mPrimaryTimerState = mPreviousState;
+ mPreviousState = getCurrentState().getName();
+ mIsPrimaryTimerActive = true;
+ sendMessageDelayed(EVENT_PRIMARY_TIMER_EXPIRED, destState,
+ rule.getTimer(destName) * 1000);
+ }
+ transitionTo(destState);
+ }
+
+ private void transitionWithSecondaryTimerTo(IState destState) {
+ String destName = destState.getName();
+ OverrideTimerRule rule = mOverrideTimerRules.get(mPrimaryTimerState);
+ if (rule != null && rule.getSecondaryTimer(destName) > 0) {
+ String currentName = getCurrentState().getName();
+ if (DBG) log("Secondary timer started for state: " + currentName);
+ mSecondaryTimerState = currentName;
+ mPreviousState = currentName;
+ mIsSecondaryTimerActive = true;
+ sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState,
+ rule.getSecondaryTimer(destName) * 1000);
+ }
+ mIsPrimaryTimerActive = false;
+ transitionTo(destState);
+ }
+
+ private void transitionToCurrentState() {
+ int dataRat = mPhone.getServiceState().getDataNetworkType();
+ if (dataRat == TelephonyManager.NETWORK_TYPE_NR || isNrConnected()) {
+ transitionTo(mNrConnectedState);
+ mPreviousState = isNrMmwave() ? STATE_CONNECTED_MMWAVE : STATE_CONNECTED;
+ } else if (isLte(dataRat) && isNrNotRestricted()) {
+ if (isDataActive()) {
+ transitionTo(mLteConnectedState);
+ mPreviousState = STATE_NOT_RESTRICTED_RRC_CON;
+ } else {
+ transitionTo(mIdleState);
+ mPreviousState = STATE_NOT_RESTRICTED_RRC_IDLE;
+ }
+ } else {
+ transitionTo(mLegacyState);
+ mPreviousState = isNrRestricted() ? STATE_RESTRICTED : STATE_LEGACY;
+ }
+ }
+
+ private void updateTimers() {
+ String currentState = getCurrentState().getName();
+ if (mIsPrimaryTimerActive && mPrimaryTimerState.equals(currentState)) {
+ // remove primary timer if device goes back to the original state
+ if (DBG) {
+ log("Remove primary timer since primary state and current state equal: "
+ + mPrimaryTimerState);
+ }
+ removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
+ mIsPrimaryTimerActive = false;
+ mPrimaryTimerState = "";
+ }
+
+ if (mIsSecondaryTimerActive && !mSecondaryTimerState.equals(currentState)) {
+ // remove secondary timer if devices is no longer in secondary timer state
+ if (DBG) {
+ log("Remove secondary timer since current state (" + currentState
+ + ") is no longer secondary timer state (" + mSecondaryTimerState + ").");
+ }
+ removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
+ mIsSecondaryTimerActive = false;
+ mSecondaryTimerState = "";
+ }
+ }
+
+ private void resetAllTimers() {
+ removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
+ removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
+ mIsPrimaryTimerActive = false;
+ mIsSecondaryTimerActive = false;
+ mPrimaryTimerState = "";
+ mSecondaryTimerState = "";
+ }
+
+ /**
+ * Private class defining timer rules between states to prevent flickering. These rules are
+ * created in {@link #parseCarrierConfigs()} based on various carrier configs.
+ */
+ private class OverrideTimerRule {
+ /** The 5G state this timer rule applies for. See {@link #ALL_STATES}. */
+ final String mState;
+
+ /**
+ * The override network type associated with this 5G state. This is the icon that will be
+ * displayed on the status bar. An override type of NONE will display the LTE value instead.
+ */
+ final int mOverrideType;
+
+ /**
+ * A map of destination states and associated timers. If the 5G state changes from mState
+ * to the destination state, keep the override type until either the primary timer expires
+ * or mState is regained.
+ */
+ final Map<String, Integer> mPrimaryTimers;
+
+ /**
+ * A map of secondary states and associated timers. After the primary timer expires, keep
+ * the override type until either the secondary timer expires or the device is no longer in
+ * the secondary state.
+ */
+ final Map<String, Integer> mSecondaryTimers;
+
+ OverrideTimerRule(String state, int overrideType) {
+ mState = state;
+ mOverrideType = overrideType;
+ mPrimaryTimers = new HashMap<>();
+ mSecondaryTimers = new HashMap<>();
+ }
+
+ /**
+ * Add a primary timer.
+ * @param destination Transitions from mState to the destination state.
+ * @param duration How long to keep the override type after transition to destination state.
+ */
+ public void addTimer(String destination, int duration) {
+ mPrimaryTimers.put(destination, duration);
+ }
+
+ /**
+ * Add a secondary timer
+ * @param secondaryState Stays in secondaryState after primary timer expires.
+ * @param duration How long to keep the override type while in secondaryState.
+ */
+ public void addSecondaryTimer(String secondaryState, int duration) {
+ mSecondaryTimers.put(secondaryState, duration);
+ }
+
+ /**
+ * @return Primary timer duration from mState to destination state, or 0 if not defined.
+ */
+ public int getTimer(String destination) {
+ Integer timer = mPrimaryTimers.get(destination);
+ timer = timer == null ? mPrimaryTimers.get(STATE_ANY) : timer;
+ return timer == null ? 0 : timer;
+ }
+
+ /**
+ * @return Secondary timer duration for secondaryState, or 0 if not defined.
+ */
+ public int getSecondaryTimer(String secondaryState) {
+ Integer secondaryTimer = mSecondaryTimers.get(secondaryState);
+ secondaryTimer = secondaryTimer == null
+ ? mSecondaryTimers.get(STATE_ANY) : secondaryTimer;
+ return secondaryTimer == null ? 0 : secondaryTimer;
+ }
+
+ @Override
+ public String toString() {
+ return "{mState=" + mState
+ + ", mOverrideType="
+ + TelephonyDisplayInfo.overrideNetworkTypeToString(mOverrideType)
+ + ", mPrimaryTimers=" + mPrimaryTimers
+ + ", mSecondaryTimers=" + mSecondaryTimers + "}";
+ }
+ }
+
+ private boolean isNrConnected() {
+ return mPhone.getServiceState().getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED;
+ }
+
+ private boolean isNrNotRestricted() {
+ return mPhone.getServiceState().getNrState()
+ == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED;
+ }
+
+ private boolean isNrRestricted() {
+ return mPhone.getServiceState().getNrState()
+ == NetworkRegistrationInfo.NR_STATE_RESTRICTED;
+ }
+
+ private boolean isNrMmwave() {
+ return mPhone.getServiceState().getNrFrequencyRange()
+ == ServiceState.FREQUENCY_RANGE_MMWAVE;
+ }
+
+ private boolean isLte(int rat) {
+ return rat == TelephonyManager.NETWORK_TYPE_LTE
+ || rat == TelephonyManager.NETWORK_TYPE_LTE_CA;
+ }
+
+ private boolean isDataActive() {
+ PhoneInternalInterface.DataActivityState activity = mPhone.getDataActivityState();
+ return activity != PhoneInternalInterface.DataActivityState.DORMANT
+ && activity != PhoneInternalInterface.DataActivityState.NONE;
+ }
+
+ private String getEventName(int event) {
+ try {
+ return sEvents[event];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return "EVENT_NOT_DEFINED";
+ }
+ }
+
+ protected void log(String s) {
+ Rlog.d(TAG, s);
+ }
+
+ protected void loge(String s) {
+ Rlog.e(TAG, s);
+ }
+
+ @Override
+ public String toString() {
+ return "mOverrideTimerRules=" + mOverrideTimerRules.toString()
+ + ", mLteEnhancedPattern=" + mLteEnhancedPattern
+ + ", mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn
+ + ", mIsPrimaryTimerActive=" + mIsPrimaryTimerActive
+ + ", mIsSecondaryTimerActive=" + mIsSecondaryTimerActive
+ + ", mPrimaryTimerState=" + mPrimaryTimerState
+ + ", mSecondaryTimerState=" + mSecondaryTimerState
+ + ", mPreviousState=" + mPreviousState;
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
+ IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
+ pw.print("NetworkTypeController: ");
+ super.dump(fd, pw, args);
+ pw.flush();
+ pw.increaseIndent();
+ pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString());
+ pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern);
+ pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn);
+ pw.println("mIsPrimaryTimerActive=" + mIsPrimaryTimerActive);
+ pw.println("mIsSecondaryTimerActive=" + mIsSecondaryTimerActive);
+ pw.println("mPrimaryTimerState=" + mPrimaryTimerState);
+ pw.println("mSecondaryTimerState=" + mSecondaryTimerState);
+ pw.println("mPreviousState=" + mPreviousState);
+ pw.decreaseIndent();
+ pw.flush();
+ }
+}
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 5af1c93..fe89b52 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -315,6 +315,7 @@
private final String mActionDetached;
private final String mActionAttached;
protected DeviceStateMonitor mDeviceStateMonitor;
+ protected DisplayInfoController mDisplayInfoController;
protected TransportManager mTransportManager;
protected DataEnabledSettings mDataEnabledSettings;
// Used for identify the carrier of current subscription
@@ -1806,6 +1807,20 @@
}
/**
+ * Retrieves the DeviceStateMonitor of the phone instance.
+ */
+ public DeviceStateMonitor getDeviceStateMonitor() {
+ return null;
+ }
+
+ /**
+ * Retrieves the DisplayInfoController of the phone instance.
+ */
+ public DisplayInfoController getDisplayInfoController() {
+ return null;
+ }
+
+ /**
* Update voice activation state
*/
public void setVoiceActivationState(int state) {
@@ -4344,6 +4359,17 @@
pw.println("++++++++++++++++++++++++++++++++");
}
+ if (getDisplayInfoController() != null) {
+ try {
+ getDisplayInfoController().dump(fd, pw, args);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ pw.flush();
+ pw.println("++++++++++++++++++++++++++++++++");
+ }
+
if (mCarrierResolver != null) {
try {
mCarrierResolver.dump(fd, pw, args);
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index d851f19..5a88887 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -2006,15 +2006,6 @@
return cdmaRoaming && !isSameOperatorNameFromSimAndSS(s);
}
- private boolean isNrStateChanged(
- NetworkRegistrationInfo oldRegState, NetworkRegistrationInfo newRegState) {
- if (oldRegState == null || newRegState == null) {
- return oldRegState != newRegState;
- }
-
- return oldRegState.getNrState() != newRegState.getNrState();
- }
-
private boolean updateNrFrequencyRangeFromPhysicalChannelConfigs(
List<PhysicalChannelConfig> physicalChannelConfigs, ServiceState ss) {
int newFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
@@ -3268,11 +3259,7 @@
boolean hasNrFrequencyRangeChanged =
mSS.getNrFrequencyRange() != mNewSS.getNrFrequencyRange();
- boolean hasNrStateChanged = isNrStateChanged(
- mSS.getNetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkType.EUTRAN),
- mNewSS.getNetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkType.EUTRAN));
+ boolean hasNrStateChanged = mSS.getNrState() != mNewSS.getNrState();
final List<CellIdentity> prioritizedCids = getPrioritizedCellIdentities(mNewSS);
@@ -3588,6 +3575,14 @@
mPhone.notifyLocationChanged(getCellIdentity());
}
+ if (hasNrStateChanged) {
+ mNrStateChangedRegistrants.notifyRegistrants();
+ }
+
+ if (hasNrFrequencyRangeChanged) {
+ mNrFrequencyChangedRegistrants.notifyRegistrants();
+ }
+
if (mPhone.isPhoneTypeGsm()) {
if (!isGprsConsistent(mSS.getDataRegistrationState(), mSS.getState())) {
if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index bdc28a5..9ed42ad 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -433,6 +433,13 @@
return PhoneSwitcher.make(maxDataAttachModemCount, context, looper);
}
+ /**
+ * Create a new DisplayInfoController.
+ */
+ public DisplayInfoController makeDisplayInfoController(Phone phone) {
+ return new DisplayInfoController(phone);
+ }
+
public MultiSimSettingController initMultiSimSettingController(Context c,
SubscriptionController sc) {
return MultiSimSettingController.init(c, sc);
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index bbcd93a..8463deb 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -131,8 +131,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
@@ -314,9 +312,9 @@
private final LocalLog mDataRoamingLeakageLog = new LocalLog(50);
private final LocalLog mApnSettingsInitializationLog = new LocalLog(50);
- /* Default for 5G connection reevaluation alarm durations */
- private int mHysteresisTimeSec = 0;
+ /* 5G connection reevaluation watchdog alarm constants */
private long mWatchdogTimeMs = 1000 * 60 * 60;
+ private boolean mWatchdog = false;
/* Default for whether 5G frequencies are considered unmetered */
private boolean mNrNsaAllUnmetered = false;
@@ -327,21 +325,9 @@
private boolean mNrSaSub6Unmetered = false;
private boolean mRoamingUnmetered = false;
- /* Used to check whether 5G timers are currently active and waiting to go off */
- private boolean mHysteresis = false;
- private boolean mWatchdog = false;
-
/* List of SubscriptionPlans, updated on SubscriptionManager.setSubscriptionPlans */
private List<SubscriptionPlan> mSubscriptionPlans = null;
- /* Used to check whether phone was recently connected to 5G. */
- private boolean m5GWasConnected = false;
-
- /* Used to determine TelephonyDisplayInfo to send to SysUI. */
- private TelephonyDisplayInfo mTelephonyDisplayInfo = null;
- private final Map<String, Integer> m5GIconMapping = new HashMap<>();
- private String mDataIconPattern = "";
-
@SimState
private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
@@ -357,16 +343,12 @@
stopNetStatPoll();
startNetStatPoll();
restartDataStallAlarm();
- reevaluateUnmeteredConnections();
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
if (DBG) log("screen off");
mIsScreenOn = false;
stopNetStatPoll();
startNetStatPoll();
restartDataStallAlarm();
- stopHysteresisAlarm();
- stopWatchdogAlarm();
- setDataConnectionUnmetered(false);
} else if (action.equals(INTENT_DATA_STALL_ALARM)) {
onActionIntentDataStallAlarm(intent);
} else if (action.equals(INTENT_PROVISIONING_APN_ALARM)) {
@@ -780,8 +762,6 @@
DctConstants.EVENT_PS_RESTRICT_DISABLED, null);
mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(mTransportType, this,
DctConstants.EVENT_DATA_RAT_CHANGED, null);
- // listens for PhysicalChannelConfig changes
- mPhone.registerForServiceStateChanged(this, DctConstants.EVENT_SERVICE_STATE_CHANGED, null);
}
public void unregisterServiceStateTrackerEvents() {
@@ -791,9 +771,7 @@
mPhone.getServiceStateTracker().unregisterForDataRoamingOff(this);
mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this);
mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this);
- mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType,
- this);
- mPhone.unregisterForServiceStateChanged(this);
+ mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType, this);
}
private void registerForAllEvents() {
@@ -813,6 +791,8 @@
DctConstants.EVENT_VOICE_CALL_ENDED, null);
mPhone.getCallTracker().registerForVoiceCallStarted(this,
DctConstants.EVENT_VOICE_CALL_STARTED, null);
+ mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged(this,
+ DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED, null);
registerServiceStateTrackerEvents();
mDataServiceManager.registerForServiceBindingChanged(this,
DctConstants.EVENT_DATA_SERVICE_BINDING_CHANGED, null);
@@ -859,9 +839,9 @@
mPhone.getCallTracker().unregisterForVoiceCallEnded(this);
mPhone.getCallTracker().unregisterForVoiceCallStarted(this);
+ mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged(this);
unregisterServiceStateTrackerEvents();
mDataServiceManager.unregisterForServiceBindingChanged(this);
-
mDataEnabledSettings.unregisterForDataEnabledChanged(this);
mDataEnabledSettings.unregisterForDataEnabledOverrideChanged(this);
}
@@ -896,7 +876,6 @@
log("setActivity = " + activity);
mActivity = activity;
mPhone.notifyDataActivity();
- updateDisplayInfo();
}
public void requestNetwork(NetworkRequest networkRequest, @RequestNetworkType int type,
@@ -3828,21 +3807,13 @@
case DctConstants.EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED:
onDataEnabledOverrideRulesChanged();
break;
- case DctConstants.EVENT_SERVICE_STATE_CHANGED:
- if (!reevaluateUnmeteredConnections()) {
- // always update on ServiceState changed so MobileSignalController gets
- // accurate display info
- mPhone.notifyDisplayInfoChanged(mTelephonyDisplayInfo);
- }
- break;
- case DctConstants.EVENT_5G_TIMER_HYSTERESIS:
- reevaluateUnmeteredConnections();
- mHysteresis = false;
- break;
- case DctConstants.EVENT_5G_TIMER_WATCHDOG:
+ case DctConstants.EVENT_NR_TIMER_WATCHDOG:
mWatchdog = false;
reevaluateUnmeteredConnections();
break;
+ case DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED:
+ reevaluateUnmeteredConnections();
+ break;
case DctConstants.EVENT_CARRIER_CONFIG_CHANGED:
onCarrierConfigChanged();
break;
@@ -3938,26 +3909,6 @@
return mBandwidths.get(ratName);
}
- private void update5GIconMapping(String config) {
- synchronized (m5GIconMapping) {
- m5GIconMapping.clear();
- for (String pair : config.trim().split(",")) {
- String[] kv = (pair.trim().toLowerCase()).split(":");
- if (kv.length != 2) {
- if (DBG) log("Invalid 5G icon configuration, config = " + pair);
- continue;
- }
- int value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
- if (kv[1].equals("5g")) {
- value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
- } else if (kv[1].equals("5g_plus")) {
- value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE;
- }
- m5GIconMapping.put(kv[0], value);
- }
- }
- }
-
@VisibleForTesting
public boolean shouldAutoAttach() {
if (mAutoAttachEnabled.get()) return true;
@@ -4032,49 +3983,25 @@
}
}
- private boolean reevaluateUnmeteredConnections() {
+ private void reevaluateUnmeteredConnections() {
log("reevaluateUnmeteredConnections");
- int networkType = ServiceState.rilRadioTechnologyToNetworkType(getDataRat());
- boolean nrUnmetered = isNetworkTypeUnmetered(NETWORK_TYPE_NR);
- boolean nrNsaUnmetered = isNrNsaFrequencyRangeUnmetered();
- boolean nrSaUnmetered = isNrSaFrequencyRangeUnmetered();
- if ((nrUnmetered || nrNsaUnmetered || nrSaUnmetered)
+ int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType();
+ int override = mPhone.getDisplayInfoController().getTelephonyDisplayInfo()
+ .getOverrideNetworkType();
+ boolean nrPlanUnmetered = isNetworkTypeUnmetered(NETWORK_TYPE_NR) && (rat == NETWORK_TYPE_NR
+ || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA
+ || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE);
+ if ((nrPlanUnmetered || isNrNsaFrequencyRangeUnmetered() || isNrSaFrequencyRangeUnmetered())
&& !mPhone.getServiceState().getRoaming() || mRoamingUnmetered) {
if (DBG) log("NR is unmetered");
- if ((nrUnmetered || nrNsaUnmetered) && mPhone.getServiceState().getNrState()
- == NetworkRegistrationInfo.NR_STATE_CONNECTED
- || (nrUnmetered || nrSaUnmetered) && networkType == NETWORK_TYPE_NR) {
- if (!m5GWasConnected) { // 4G -> 5G
- stopHysteresisAlarm();
- setDataConnectionUnmetered(true);
- }
- if (!mWatchdog) {
- startWatchdogAlarm();
- }
- m5GWasConnected = true;
- } else {
- if (m5GWasConnected) { // 5G -> 4G
- if (!mHysteresis && !startHysteresisAlarm()) {
- // hysteresis is not active but carrier does not support hysteresis
- stopWatchdogAlarm();
- setDataConnectionUnmetered(isNetworkTypeUnmetered(networkType));
- }
- m5GWasConnected = false;
- } else { // 4G -> 4G
- if (!hasMessages(DctConstants.EVENT_5G_TIMER_HYSTERESIS)) {
- stopWatchdogAlarm();
- setDataConnectionUnmetered(isNetworkTypeUnmetered(networkType));
- }
- // do nothing if waiting for hysteresis alarm to go off
- }
+ setDataConnectionUnmetered(true);
+ if (!mWatchdog) {
+ startWatchdogAlarm();
}
} else {
stopWatchdogAlarm();
- stopHysteresisAlarm();
- setDataConnectionUnmetered(isNetworkTypeUnmetered(networkType));
- m5GWasConnected = false;
+ setDataConnectionUnmetered(isNetworkTypeUnmetered(rat));
}
- return updateDisplayInfo();
}
private void setDataConnectionUnmetered(boolean isUnmetered) {
@@ -4121,18 +4048,24 @@
}
private boolean isNrNsaFrequencyRangeUnmetered() {
+ int override = mPhone.getDisplayInfoController().getTelephonyDisplayInfo()
+ .getOverrideNetworkType();
if (mNrNsaMmwaveUnmetered || mNrNsaSub6Unmetered) {
- int frequencyRange = mPhone.getServiceState().getNrFrequencyRange();
- boolean mmwave = frequencyRange == ServiceState.FREQUENCY_RANGE_MMWAVE;
- // frequency range LOW, MID, or HIGH
- boolean sub6 = frequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN && !mmwave;
- return mNrNsaMmwaveUnmetered && mmwave || mNrNsaSub6Unmetered && sub6;
+ return (mNrNsaMmwaveUnmetered
+ && override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE)
+ || (mNrNsaSub6Unmetered
+ && override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA);
} else {
- return mNrNsaAllUnmetered;
+ return mNrNsaAllUnmetered
+ && (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE
+ || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA);
}
}
private boolean isNrSaFrequencyRangeUnmetered() {
+ if (ServiceState.rilRadioTechnologyToNetworkType(getDataRat()) != NETWORK_TYPE_NR) {
+ return false;
+ }
if (mNrSaMmwaveUnmetered || mNrSaSub6Unmetered) {
int frequencyRange = mPhone.getServiceState().getNrFrequencyRange();
boolean mmwave = frequencyRange == ServiceState.FREQUENCY_RANGE_MMWAVE;
@@ -4144,94 +4077,6 @@
}
}
- private boolean updateDisplayInfo() {
- int displayNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
- int dataNetworkType = mPhone.getServiceState().getDataNetworkType();
- if (mPhone.getServiceState().getNrState() != NetworkRegistrationInfo.NR_STATE_NONE
- || dataNetworkType == TelephonyManager.NETWORK_TYPE_NR || mHysteresis) {
- // process NR display network type
- displayNetworkType = getNrDisplayType();
- if (displayNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
- // use LTE values if 5G values aren't defined
- displayNetworkType = getLteDisplayType();
- }
- } else if (dataNetworkType == TelephonyManager.NETWORK_TYPE_LTE
- || dataNetworkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
- // process LTE display network type
- displayNetworkType = getLteDisplayType();
- }
- TelephonyDisplayInfo telephonyDisplayInfo =
- new TelephonyDisplayInfo(dataNetworkType, displayNetworkType);
- if (!telephonyDisplayInfo.equals(mTelephonyDisplayInfo)) {
- log("Display info changed: " + telephonyDisplayInfo);
- mTelephonyDisplayInfo = telephonyDisplayInfo;
- mPhone.notifyDisplayInfoChanged(telephonyDisplayInfo);
- return true;
- }
- return false;
- }
-
- private int getNrDisplayType() {
- // icon display keys in order of priority
- List<String> keys = new ArrayList<>();
- switch (mPhone.getServiceState().getNrState()) {
- case NetworkRegistrationInfo.NR_STATE_CONNECTED:
- if (mPhone.getServiceState().getNrFrequencyRange()
- == ServiceState.FREQUENCY_RANGE_MMWAVE) {
- keys.add("connected_mmwave");
- }
- keys.add("connected");
- break;
- case NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED:
- if (mActivity == DctConstants.Activity.DORMANT) {
- keys.add("not_restricted_rrc_idle");
- } else {
- keys.add("not_restricted_rrc_con");
- }
- break;
- case NetworkRegistrationInfo.NR_STATE_RESTRICTED:
- keys.add("restricted");
- break;
- }
-
- for (String key : keys) {
- if (m5GIconMapping.containsKey(key)
- && m5GIconMapping.get(key) != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
- return m5GIconMapping.get(key);
- }
- }
- return TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
- }
-
- private int getLteDisplayType() {
- int value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
- if (mPhone.getServiceState().getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA
- || mPhone.getServiceState().isUsingCarrierAggregation()) {
- value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA;
- }
- if (isLteEnhancedAvailable()) {
- value = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO;
- }
- return value;
- }
-
- private boolean isLteEnhancedAvailable() {
- if (TextUtils.isEmpty(mDataIconPattern)) {
- return false;
- }
- Pattern stringPattern = Pattern.compile(mDataIconPattern);
- for (String opName : new String[] {mPhone.getServiceState().getOperatorAlphaLongRaw(),
- mPhone.getServiceState().getOperatorAlphaShortRaw()}) {
- if (!TextUtils.isEmpty(opName)) {
- Matcher matcher = stringPattern.matcher(opName);
- if (matcher.find()) {
- return true;
- }
- }
- }
- return false;
- }
-
protected void log(String s) {
Rlog.d(mLogTag, s);
}
@@ -4627,7 +4472,6 @@
log("updateDataActivity: newActivity=" + newActivity);
mActivity = newActivity;
mPhone.notifyDataActivity();
- updateDisplayInfo();
}
}
}
@@ -5072,32 +4916,15 @@
}
/**
- * 5G connection reevaluation alarms
+ * 5G connection reevaluation alarm
*/
- private boolean startHysteresisAlarm() {
- if (mHysteresisTimeSec > 0) {
- // only create hysteresis alarm if CarrierConfig allows it
- sendMessageDelayed(obtainMessage(DctConstants.EVENT_5G_TIMER_HYSTERESIS),
- mHysteresisTimeSec * 1000);
- mHysteresis = true;
- return true;
- } else {
- return false;
- }
- }
-
- private void stopHysteresisAlarm() {
- removeMessages(DctConstants.EVENT_5G_TIMER_HYSTERESIS);
- mHysteresis = false;
- }
-
private void startWatchdogAlarm() {
- sendMessageDelayed(obtainMessage(DctConstants.EVENT_5G_TIMER_WATCHDOG), mWatchdogTimeMs);
+ sendMessageDelayed(obtainMessage(DctConstants.EVENT_NR_TIMER_WATCHDOG), mWatchdogTimeMs);
mWatchdog = true;
}
private void stopWatchdogAlarm() {
- removeMessages(DctConstants.EVENT_5G_TIMER_WATCHDOG);
+ removeMessages(DctConstants.EVENT_NR_TIMER_WATCHDOG);
mWatchdog = false;
}
@@ -5189,50 +5016,28 @@
return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
}
- // TODO: Move icon related to display info controller.
private void read5GConfiguration() {
if (DBG) log("read5GConfiguration");
- String nr5GIconConfiguration = CarrierConfigManager.getDefaultConfig().getString(
- CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
String[] bandwidths = CarrierConfigManager.getDefaultConfig().getStringArray(
CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY);
boolean useLte = false;
- mDataIconPattern = CarrierConfigManager.getDefaultConfig().getString(
- CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager != null) {
PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
if (b != null) {
- if (b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING)
- != null) {
- nr5GIconConfiguration = b.getString(
- CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
- }
- if (b.getString(CarrierConfigManager
- .KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING) != null) {
- mDataIconPattern = b.getString(
- CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
- }
- if (b.getStringArray(CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY)
- != null) {
- bandwidths = b.getStringArray(
- CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY);
+ if (b.getStringArray(CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY) != null) {
+ bandwidths = b.getStringArray(CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY);
}
useLte = b.getBoolean(CarrierConfigManager
.KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPSTREAM_BOOL);
- mHysteresisTimeSec = b.getInt(
- CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT);
- mWatchdogTimeMs = b.getLong(
- CarrierConfigManager.KEY_5G_WATCHDOG_TIME_MS_LONG);
- mNrNsaAllUnmetered = b.getBoolean(
- CarrierConfigManager.KEY_UNMETERED_NR_NSA_BOOL);
+ mWatchdogTimeMs = b.getLong(CarrierConfigManager.KEY_5G_WATCHDOG_TIME_MS_LONG);
+ mNrNsaAllUnmetered = b.getBoolean(CarrierConfigManager.KEY_UNMETERED_NR_NSA_BOOL);
mNrNsaMmwaveUnmetered = b.getBoolean(
CarrierConfigManager.KEY_UNMETERED_NR_NSA_MMWAVE_BOOL);
mNrNsaSub6Unmetered = b.getBoolean(
CarrierConfigManager.KEY_UNMETERED_NR_NSA_SUB6_BOOL);
- mNrSaAllUnmetered = b.getBoolean(
- CarrierConfigManager.KEY_UNMETERED_NR_SA_BOOL);
+ mNrSaAllUnmetered = b.getBoolean(CarrierConfigManager.KEY_UNMETERED_NR_SA_BOOL);
mNrSaMmwaveUnmetered = b.getBoolean(
CarrierConfigManager.KEY_UNMETERED_NR_SA_MMWAVE_BOOL);
mNrSaSub6Unmetered = b.getBoolean(
@@ -5241,8 +5046,6 @@
CarrierConfigManager.KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL);
}
}
-
updateLinkBandwidths(bandwidths, useLte);
- update5GIconMapping(nr5GIconConfiguration);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
new file mode 100644
index 0000000..fbca14a
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -0,0 +1,588 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Intent;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyDisplayInfo;
+import android.telephony.TelephonyManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.util.IState;
+import com.android.internal.util.StateMachine;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Method;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NetworkTypeControllerTest extends TelephonyTest {
+ // private constants copied over from NetworkTypeController
+ private static final int EVENT_DATA_RAT_CHANGED = 2;
+ private static final int EVENT_NR_STATE_CHANGED = 3;
+ private static final int EVENT_NR_FREQUENCY_CHANGED = 4;
+ private static final int EVENT_DATA_ACTIVITY_CHANGED = 5;
+ private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED = 6;
+ private static final int EVENT_CARRIER_CONFIG_CHANGED = 7;
+ private static final int EVENT_PRIMARY_TIMER_EXPIRED = 8;
+ private static final int EVENT_SECONDARY_TIMER_EXPIRED = 9;
+
+ private NetworkTypeController mNetworkTypeController;
+ private PersistableBundle mBundle;
+
+ private IState getCurrentState() throws Exception {
+ Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
+ method.setAccessible(true);
+ return (IState) method.invoke(mNetworkTypeController);
+ }
+
+ private void updateOverrideNetworkType() throws Exception {
+ Method method = NetworkTypeController.class.getDeclaredMethod("updateOverrideNetworkType");
+ method.setAccessible(true);
+ method.invoke(mNetworkTypeController);
+ }
+
+ private void broadcastCarrierConfigs() {
+ Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, mPhone.getSubId());
+ intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, mPhone.getPhoneId());
+ mContext.sendBroadcast(intent);
+ processAllMessages();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ mBundle = mContextFixture.getCarrierConfigBundle();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING,
+ "connected_mmwave:5G_Plus,connected:5G,not_restricted_rrc_idle:5G,"
+ + "not_restricted_rrc_con:5G");
+ broadcastCarrierConfigs();
+
+ replaceInstance(Handler.class, "mLooper", mDisplayInfoController, Looper.myLooper());
+ mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mNetworkTypeController.getHandler().removeCallbacksAndMessages(null);
+ mNetworkTypeController = null;
+ super.tearDown();
+ }
+
+ @Test
+ public void testUpdateOverrideNetworkTypeNrNsa() throws Exception {
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+
+ // not NR
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+ updateOverrideNetworkType();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // NR NSA, restricted
+ doReturn(NetworkRegistrationInfo.NR_STATE_RESTRICTED).when(mServiceState).getNrState();
+ updateOverrideNetworkType();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // NR NSA, not restricted
+ doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
+ updateOverrideNetworkType();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // NR NSA, sub 6 frequency
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_LOW).when(mServiceState).getNrFrequencyRange();
+ updateOverrideNetworkType();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // NR NSA, millimeter wave frequency
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ updateOverrideNetworkType();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testUpdateOverrideNetworkTypeLte() throws Exception {
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+
+ // normal LTE
+ updateOverrideNetworkType();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // LTE CA
+ doReturn(true).when(mServiceState).isUsingCarrierAggregation();
+ updateOverrideNetworkType();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // LTE ADVANCED PRO
+ doReturn("test_patternShowAdvanced").when(mServiceState).getOperatorAlphaLongRaw();
+ mBundle.putString(CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING,
+ ".*_patternShowAdvanced");
+ broadcastCarrierConfigs();
+ updateOverrideNetworkType();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testTransitionToCurrentStateLegacy() throws Exception {
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(TelephonyManager.NETWORK_TYPE_HSPAP).when(mServiceState).getDataNetworkType();
+
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+ processAllMessages();
+ assertEquals("legacy", getCurrentState().getName());
+ }
+
+ @Test
+ public void testTransitionToCurrentStateRestricted() throws Exception {
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_RESTRICTED).when(mServiceState).getNrState();
+
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+ processAllMessages();
+ assertEquals("restricted", getCurrentState().getName());
+ }
+
+ @Test
+ public void testTransitionToCurrentStateIdle() throws Exception {
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
+ doReturn(PhoneInternalInterface.DataActivityState.DORMANT)
+ .when(mPhone).getDataActivityState();
+
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+ processAllMessages();
+ assertEquals("not_restricted_rrc_idle", getCurrentState().getName());
+ }
+
+ @Test
+ public void testTransitionToCurrentStateLteConnected() throws Exception {
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
+ doReturn(PhoneInternalInterface.DataActivityState.DATAINANDOUT)
+ .when(mPhone).getDataActivityState();
+
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+ processAllMessages();
+ assertEquals("not_restricted_rrc_con", getCurrentState().getName());
+ }
+
+ @Test
+ public void testTransitionToCurrentStateNrConnected() throws Exception {
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+ processAllMessages();
+ assertEquals("connected", getCurrentState().getName());
+ }
+
+ @Test
+ public void testTransitionToCurrentStateNrConnectedMmwave() throws Exception {
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+ processAllMessages();
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ }
+
+ @Test
+ public void testEventDataRatChanged() throws Exception {
+ testTransitionToCurrentStateLegacy();
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+
+ mNetworkTypeController.sendMessage(EVENT_DATA_RAT_CHANGED);
+ processAllMessages();
+ assertEquals("connected", getCurrentState().getName());
+ }
+
+ @Test
+ public void testEventNrStateChanged() throws Exception {
+ testTransitionToCurrentStateNrConnected();
+ doReturn(NetworkRegistrationInfo.NR_STATE_RESTRICTED).when(mServiceState).getNrState();
+
+ mNetworkTypeController.sendMessage(EVENT_NR_STATE_CHANGED);
+ processAllMessages();
+ assertEquals("restricted", getCurrentState().getName());
+ }
+
+ @Test
+ public void testEventNrFrequencyRangeChanged() throws Exception {
+ testTransitionToCurrentStateNrConnectedMmwave();
+ doReturn(ServiceState.FREQUENCY_RANGE_LOW).when(mServiceState).getNrFrequencyRange();
+
+ mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+ processAllMessages();
+ assertEquals("connected", getCurrentState().getName());
+ }
+
+ @Test
+ public void testEventDataActivityChanged() throws Exception {
+ testTransitionToCurrentStateLteConnected();
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ doReturn(PhoneInternalInterface.DataActivityState.DORMANT)
+ .when(mPhone).getDataActivityState();
+
+ mNetworkTypeController.sendMessage(EVENT_DATA_ACTIVITY_CHANGED);
+ processAllMessages();
+ assertEquals("not_restricted_rrc_idle", getCurrentState().getName());
+ }
+
+ @Test
+ public void testEventPhysicalChannelConfigNotifChanged() throws Exception {
+ testTransitionToCurrentStateNrConnected();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ mNetworkTypeController.sendMessage(EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED,
+ new AsyncResult(null, false, null));
+ processAllMessages();
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testPrimaryTimerExpire() throws Exception {
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+ broadcastCarrierConfigs();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second timer
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_NR_STATE_CHANGED);
+ processAllMessages();
+
+ assertEquals("legacy", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ assertEquals("legacy", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testPrimaryTimerReset() throws Exception {
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+ broadcastCarrierConfigs();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // trigger 10 second timer after disconnecting from NR
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_NR_STATE_CHANGED);
+ processAllMessages();
+
+ assertEquals("legacy", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // reconnect to NR in the middle of the timer
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_NR_STATE_CHANGED);
+
+ // timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // timer should not have gone off
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testPrimaryTimerExpireMmwave() throws Exception {
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+ broadcastCarrierConfigs();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second timer
+ doReturn(ServiceState.FREQUENCY_RANGE_LOW).when(mServiceState).getNrFrequencyRange();
+ mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+ processAllMessages();
+
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testPrimaryTimerResetMmwave() throws Exception {
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+ broadcastCarrierConfigs();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // trigger 10 second timer after disconnecting from NR
+ doReturn(ServiceState.FREQUENCY_RANGE_LOW).when(mServiceState).getNrFrequencyRange();
+ mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // reconnect to NR in the middle of the timer
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+
+ // timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // timer should not have gone off
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testSecondaryTimerExpire() throws Exception {
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected,any,30");
+ broadcastCarrierConfigs();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_NR_STATE_CHANGED);
+ processAllMessages();
+
+ assertEquals("legacy", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("legacy", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // secondary timer expires
+ moveTimeForward(30 * 1000);
+ processAllMessages();
+
+ assertEquals("legacy", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testSecondaryTimerReset() throws Exception {
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected,any,30");
+ broadcastCarrierConfigs();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_NR_STATE_CHANGED);
+ processAllMessages();
+
+ assertEquals("legacy", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("legacy", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // reconnect to NR in the middle of the timer
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_NR_STATE_CHANGED);
+
+ // secondary timer expires
+ moveTimeForward(30 * 1000);
+ processAllMessages();
+
+ // timer should not have gone off
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testSecondaryTimerExpireMmwave() throws Exception {
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,30");
+ broadcastCarrierConfigs();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ doReturn(ServiceState.FREQUENCY_RANGE_LOW).when(mServiceState).getNrFrequencyRange();
+ mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // secondary timer expires
+ moveTimeForward(30 * 1000);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
+ public void testSecondaryTimerResetMmwave() throws Exception {
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,30");
+ broadcastCarrierConfigs();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ doReturn(ServiceState.FREQUENCY_RANGE_LOW).when(mServiceState).getNrFrequencyRange();
+ mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // reconnect to NR in the middle of the timer
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+
+ // secondary timer expires
+ moveTimeForward(30 * 1000);
+ processAllMessages();
+
+ // timer should not have gone off
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 3abec86..87804b0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -174,6 +174,8 @@
@Mock
protected DcTracker mDcTracker;
@Mock
+ protected DisplayInfoController mDisplayInfoController;
+ @Mock
protected GsmCdmaCall mGsmCdmaCall;
@Mock
protected ImsCall mImsCall;
@@ -446,6 +448,8 @@
.makeIccPhoneBookInterfaceManager(nullable(Phone.class));
doReturn(mDcTracker).when(mTelephonyComponentFactory)
.makeDcTracker(nullable(Phone.class), anyInt());
+ doReturn(mDisplayInfoController).when(mTelephonyComponentFactory)
+ .makeDisplayInfoController(nullable(Phone.class));
doReturn(mWspTypeDecoder).when(mTelephonyComponentFactory)
.makeWspTypeDecoder(nullable(byte[].class));
doReturn(mImsCT).when(mTelephonyComponentFactory)
@@ -490,6 +494,8 @@
doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mPhone).getPhoneType();
doReturn(mCT).when(mPhone).getCallTracker();
doReturn(mSST).when(mPhone).getServiceStateTracker();
+ doReturn(mDeviceStateMonitor).when(mPhone).getDeviceStateMonitor();
+ doReturn(mDisplayInfoController).when(mPhone).getDisplayInfoController();
doReturn(mEmergencyNumberTracker).when(mPhone).getEmergencyNumberTracker();
doReturn(mCarrierSignalAgent).when(mPhone).getCarrierSignalAgent();
doReturn(mCarrierActionAgent).when(mPhone).getCarrierActionAgent();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index 110098a..89cfd85 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -1705,12 +1705,6 @@
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
}
- private boolean getHysteresisStatus() throws Exception {
- Field field = DcTracker.class.getDeclaredField(("mHysteresis"));
- field.setAccessible(true);
- return (boolean) field.get(mDct);
- }
-
private boolean getWatchdogStatus() throws Exception {
Field field = DcTracker.class.getDeclaredField(("mWatchdog"));
field.setAccessible(true);
@@ -1757,11 +1751,13 @@
int id = setUpDataConnection();
setUpSubscriptionPlans(false);
setUpWatchdogTimer();
- doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA))
+ .when(mDisplayInfoController).getTelephonyDisplayInfo();
doReturn(1).when(mPhone).getSubId();
// NetCapability should be metered when connected to 5G with no unmetered plan or frequency
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
verify(mDataConnection, times(1)).onMeterednessChanged(false);
@@ -1774,14 +1770,18 @@
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
// NetCapability should switch to unmetered when fr=MMWAVE and MMWAVE unmetered
- doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
+ doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE))
+ .when(mDisplayInfoController).getTelephonyDisplayInfo();
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
verify(mDataConnection, times(1)).onMeterednessChanged(true);
// NetCapability should switch to metered when fr=SUB6 and MMWAVE unmetered
- doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
+ doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA))
+ .when(mDisplayInfoController).getTelephonyDisplayInfo();
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
verify(mDataConnection, times(2)).onMeterednessChanged(false);
@@ -1795,7 +1795,7 @@
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
// NetCapability should switch to unmetered when fr=SUB6 and SUB6 unmetered
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
verify(mDataConnection, times(2)).onMeterednessChanged(true);
@@ -1810,14 +1810,18 @@
setUpWatchdogTimer();
// NetCapability should be unmetered when connected to 5G
- doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
+ doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA))
+ .when(mDisplayInfoController).getTelephonyDisplayInfo();
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
verify(mDataConnection, times(1)).onMeterednessChanged(true);
// NetCapability should be metered when disconnected from 5G
- doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
+ doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE))
+ .when(mDisplayInfoController).getTelephonyDisplayInfo();
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
verify(mDataConnection, times(1)).onMeterednessChanged(false);
@@ -1825,221 +1829,37 @@
}
@Test
- public void testReevaluateUnmeteredConnectionsOnHysteresis() throws Exception {
- initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
- int id = setUpDataConnection();
- setUpSubscriptionPlans(true);
- setUpWatchdogTimer();
-
- // Hysteresis active for 100s
- doReturn(1).when(mPhone).getSubId();
- mBundle.putInt(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 100);
- Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, mPhone.getPhoneId());
- intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, mPhone.getSubId());
- mContext.sendBroadcast(intent);
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- // Hysteresis inactive when unmetered and never connected to 5G
- doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_5G_TIMER_HYSTERESIS));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
- assertFalse(getHysteresisStatus());
-
- // Hysteresis inactive when unmetered and connected to 5G
- doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
- assertFalse(getHysteresisStatus());
-
- // Hysteresis active when unmetered and disconnected after connected to 5G
- doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
- assertTrue(getHysteresisStatus());
-
- // NetCapability metered when hysteresis timer goes off
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_5G_TIMER_HYSTERESIS));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
- assertFalse(getHysteresisStatus());
- verify(mDataConnection, times(1)).onMeterednessChanged(true);
-
- // Hysteresis inactive when reconnected after timer goes off
- doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
- assertFalse(getHysteresisStatus());
-
- // Hysteresis disabled
- doReturn(2).when(mPhone).getSubId();
- mBundle.putInt(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 0);
- intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, mPhone.getPhoneId());
- intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, mPhone.getSubId());
- mContext.sendBroadcast(intent);
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- // Hysteresis inactive when CarrierConfig is set to 0
- doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
- assertFalse(getHysteresisStatus());
-
- resetDataConnection(id);
- }
-
- @Test
public void testReevaluateUnmeteredConnectionsOnWatchdog() throws Exception {
initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
int id = setUpDataConnection();
setUpSubscriptionPlans(true);
setUpWatchdogTimer();
- // Watchdog inactive when unmetered and never connected to 5G
- doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_5G_TIMER_WATCHDOG));
+ // Watchdog inactive when unmetered and not connected to 5G
+ doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE))
+ .when(mDisplayInfoController).getTelephonyDisplayInfo();
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NR_TIMER_WATCHDOG));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
assertFalse(getWatchdogStatus());
- // Hysteresis active for 100s
- doReturn(1).when(mPhone).getSubId();
- mBundle.putInt(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 100);
- Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, mPhone.getPhoneId());
- intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, mPhone.getSubId());
- mContext.sendBroadcast(intent);
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
// Watchdog active when unmetered and connected to 5G
- doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
+ doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA))
+ .when(mDisplayInfoController).getTelephonyDisplayInfo();
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
assertTrue(getWatchdogStatus());
- assertFalse(getHysteresisStatus());
-
- // Watchdog active during hysteresis
- doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
- assertTrue(getHysteresisStatus());
- assertTrue(getWatchdogStatus());
// Watchdog inactive when metered
setUpSubscriptionPlans(false);
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED));
waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
assertFalse(getWatchdogStatus());
resetDataConnection(id);
}
- @Test
- public void testGetNrDisplayType() {
- ArgumentCaptor<TelephonyDisplayInfo> captor =
- ArgumentCaptor.forClass(TelephonyDisplayInfo.class);
- doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
-
- // set up 5G icon configuration
- mBundle.putString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING,
- "connected_mmwave:5G_Plus,connected:5G,not_restricted_rrc_idle:5G,"
- + "not_restricted_rrc_con:5G");
- doReturn(1).when(mPhone).getSubId();
- Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, mPhone.getPhoneId());
- intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, mPhone.getSubId());
- mContext.sendBroadcast(intent);
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- // not NR
- doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- verify(mPhone, times(1)).notifyDisplayInfoChanged(captor.capture());
- assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
- captor.getValue().getOverrideNetworkType());
-
- // NR NSA, restricted
- doReturn(NetworkRegistrationInfo.NR_STATE_RESTRICTED).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- verify(mPhone, times(2)).notifyDisplayInfoChanged(captor.capture());
- assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
- captor.getValue().getOverrideNetworkType());
-
- // NR NSA, not restricted
- doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- verify(mPhone, times(3)).notifyDisplayInfoChanged(captor.capture());
- assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
- captor.getValue().getOverrideNetworkType());
-
- doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
-
- // NR NSA, sub 6 frequency
- doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(mServiceState).getNrFrequencyRange();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- verify(mPhone, times(4)).notifyDisplayInfoChanged(captor.capture());
- assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
- captor.getValue().getOverrideNetworkType());
-
- // NR NSA, millimeter wave frequency
- doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- verify(mPhone, times(5)).notifyDisplayInfoChanged(captor.capture());
- assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
- captor.getValue().getOverrideNetworkType());
- }
-
- @Test
- public void testGetLteDisplayType() {
- ArgumentCaptor<TelephonyDisplayInfo> captor =
- ArgumentCaptor.forClass(TelephonyDisplayInfo.class);
-
- // normal LTE
- doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- verify(mPhone, times(1)).notifyDisplayInfoChanged(captor.capture());
- assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
- captor.getValue().getOverrideNetworkType());
-
- // LTE CA
- doReturn(TelephonyManager.NETWORK_TYPE_LTE_CA).when(mServiceState).getDataNetworkType();
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- verify(mPhone, times(2)).notifyDisplayInfoChanged(captor.capture());
- assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA,
- captor.getValue().getOverrideNetworkType());
-
- // TODO: LTE ADVANCED PRO
- }
-
- @Test
- public void testUpdateDisplayInfo() {
- ArgumentCaptor<TelephonyDisplayInfo> captor =
- ArgumentCaptor.forClass(TelephonyDisplayInfo.class);
- doReturn(TelephonyManager.NETWORK_TYPE_HSPAP).when(mServiceState).getDataNetworkType();
-
- mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_SERVICE_STATE_CHANGED));
- waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
-
- verify(mPhone, times(1)).notifyDisplayInfoChanged(captor.capture());
- TelephonyDisplayInfo telephonyDisplayInfo = captor.getValue();
- assertEquals(TelephonyManager.NETWORK_TYPE_HSPAP, telephonyDisplayInfo.getNetworkType());
- assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
- telephonyDisplayInfo.getOverrideNetworkType());
- }
-
/**
* Test if this is a path prefix match against the given Uri. Verifies that
* scheme, authority, and atomic path segments match.