blob: c519f5694e5a828dd1d0dbf2bb2adeea0acf7b2c [file] [log] [blame]
Jason Monkda68f592015-01-07 10:55:58 -05001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.systemui.statusbar.policy;
17
18import android.content.Context;
19import android.content.Intent;
Jason Monk0288de02017-02-23 14:48:05 -050020import android.database.ContentObserver;
Jason Monkda68f592015-01-07 10:55:58 -050021import android.net.NetworkCapabilities;
Jason Monk0288de02017-02-23 14:48:05 -050022import android.os.Handler;
Jason Monk07b75fe2015-05-14 16:47:03 -040023import android.os.Looper;
Jason Monk0288de02017-02-23 14:48:05 -050024import android.provider.Settings.Global;
Jayachandran Ca6f9b6d2019-11-07 17:26:02 -080025import android.telephony.CellSignalStrength;
26import android.telephony.CellSignalStrengthCdma;
Jack Yue27d3fd2019-03-15 14:49:53 -070027import android.telephony.NetworkRegistrationInfo;
Jason Monkda68f592015-01-07 10:55:58 -050028import android.telephony.PhoneStateListener;
29import android.telephony.ServiceState;
30import android.telephony.SignalStrength;
31import android.telephony.SubscriptionInfo;
32import android.telephony.SubscriptionManager;
33import android.telephony.TelephonyManager;
Jason Monk93fb68f2015-07-20 11:43:56 -040034import android.text.TextUtils;
Jason Monkda68f592015-01-07 10:55:58 -050035import android.util.Log;
36import android.util.SparseArray;
37
38import com.android.internal.annotations.VisibleForTesting;
Jason Monkda68f592015-01-07 10:55:58 -050039import com.android.internal.telephony.TelephonyIntents;
40import com.android.internal.telephony.cdma.EriInfo;
SongFerngWang8cfb4d52018-08-21 18:04:29 +080041import com.android.settingslib.Utils;
Gus Prevasab336792018-11-14 13:52:20 -050042import com.android.settingslib.graph.SignalDrawable;
Antony Sargentc026de32019-05-21 16:29:04 -070043import com.android.settingslib.net.SignalStrengthUtil;
Jason Monkda68f592015-01-07 10:55:58 -050044import com.android.systemui.R;
Jason Monk07b75fe2015-05-14 16:47:03 -040045import com.android.systemui.statusbar.policy.NetworkController.IconState;
Jason Monke06b0652016-03-02 16:35:27 -050046import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
Jason Monkda68f592015-01-07 10:55:58 -050047import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
Jason Monkc6cc6262015-06-11 11:10:15 -040048import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
Jason Monkda68f592015-01-07 10:55:58 -050049
50import java.io.PrintWriter;
Jason Monk33f8ae72015-05-08 10:45:15 -040051import java.util.BitSet;
Jason Monkda68f592015-01-07 10:55:58 -050052import java.util.Objects;
Jayachandran Ca6f9b6d2019-11-07 17:26:02 -080053import java.util.List;
SongFerngWang3cbcf752019-03-21 23:14:20 +080054import java.util.regex.Matcher;
55import java.util.regex.Pattern;
Jason Monkda68f592015-01-07 10:55:58 -050056
57
58public class MobileSignalController extends SignalController<
59 MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
60 private final TelephonyManager mPhone;
Jason Monkc6cc6262015-06-11 11:10:15 -040061 private final SubscriptionDefaults mDefaults;
Jason Monkda68f592015-01-07 10:55:58 -050062 private final String mNetworkNameDefault;
63 private final String mNetworkNameSeparator;
Jason Monk0288de02017-02-23 14:48:05 -050064 private final ContentObserver mObserver;
Jason Monkda68f592015-01-07 10:55:58 -050065 @VisibleForTesting
66 final PhoneStateListener mPhoneStateListener;
67 // Save entire info for logging, we only use the id.
Jason Monk66845a32015-08-03 11:09:41 -040068 final SubscriptionInfo mSubscriptionInfo;
Jason Monkda68f592015-01-07 10:55:58 -050069
70 // @VisibleForDemoMode
71 final SparseArray<MobileIconGroup> mNetworkToIconLookup;
72
73 // Since some pieces of the phone state are interdependent we store it locally,
74 // this could potentially become part of MobileState for simplification/complication
75 // of code.
Jason Monkda68f592015-01-07 10:55:58 -050076 private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
77 private int mDataState = TelephonyManager.DATA_DISCONNECTED;
78 private ServiceState mServiceState;
79 private SignalStrength mSignalStrength;
80 private MobileIconGroup mDefaultIcons;
81 private Config mConfig;
andychoub935e682019-04-11 23:40:49 +080082 @VisibleForTesting
83 boolean mInflateSignalStrengths = false;
SongFerngWang3cbcf752019-03-21 23:14:20 +080084 // Some specific carriers have 5GE network which is special LTE CA network.
85 private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1;
Jason Monkda68f592015-01-07 10:55:58 -050086
87 // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
88 // need listener lists anymore.
89 public MobileSignalController(Context context, Config config, boolean hasMobileData,
Jason Monk07b75fe2015-05-14 16:47:03 -040090 TelephonyManager phone, CallbackHandler callbackHandler,
Jason Monkc6cc6262015-06-11 11:10:15 -040091 NetworkControllerImpl networkController, SubscriptionInfo info,
92 SubscriptionDefaults defaults, Looper receiverLooper) {
Jason Monkda68f592015-01-07 10:55:58 -050093 super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
Jason Monk07b75fe2015-05-14 16:47:03 -040094 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
Jason Monkda68f592015-01-07 10:55:58 -050095 networkController);
96 mNetworkToIconLookup = new SparseArray<>();
97 mConfig = config;
98 mPhone = phone;
Jason Monkc6cc6262015-06-11 11:10:15 -040099 mDefaults = defaults;
Jason Monkda68f592015-01-07 10:55:58 -0500100 mSubscriptionInfo = info;
chen xu84a90872019-03-28 15:44:12 -0700101 mPhoneStateListener = new MobilePhoneStateListener(receiverLooper);
Jason Monkda68f592015-01-07 10:55:58 -0500102 mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
103 mNetworkNameDefault = getStringIfExists(
104 com.android.internal.R.string.lockscreen_carrier_default);
105
106 mapIconSets();
107
Jason Monk00aa9d42015-08-10 10:12:02 -0400108 String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
109 : mNetworkNameDefault;
110 mLastState.networkName = mCurrentState.networkName = networkName;
111 mLastState.networkNameData = mCurrentState.networkNameData = networkName;
Jason Monkda68f592015-01-07 10:55:58 -0500112 mLastState.enabled = mCurrentState.enabled = hasMobileData;
113 mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
114 // Get initial data sim state.
115 updateDataSim();
Jason Monk0288de02017-02-23 14:48:05 -0500116 mObserver = new ContentObserver(new Handler(receiverLooper)) {
117 @Override
118 public void onChange(boolean selfChange) {
119 updateTelephony();
120 }
121 };
Jason Monkda68f592015-01-07 10:55:58 -0500122 }
123
124 public void setConfiguration(Config config) {
125 mConfig = config;
andychou9e396282019-04-10 20:49:06 +0800126 updateInflateSignalStrength();
Jason Monkda68f592015-01-07 10:55:58 -0500127 mapIconSets();
128 updateTelephony();
129 }
130
Jason Monkda68f592015-01-07 10:55:58 -0500131 public int getDataContentDescription() {
132 return getIcons().mDataContentDescription;
133 }
134
Jason Monkda68f592015-01-07 10:55:58 -0500135 public void setAirplaneMode(boolean airplaneMode) {
136 mCurrentState.airplaneMode = airplaneMode;
137 notifyListenersIfNecessary();
138 }
139
Jason Monkfd57ea72016-04-29 13:37:58 -0400140 public void setUserSetupComplete(boolean userSetup) {
141 mCurrentState.userSetup = userSetup;
142 notifyListenersIfNecessary();
143 }
144
Jason Monk33f8ae72015-05-08 10:45:15 -0400145 @Override
146 public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
147 boolean isValidated = validatedTransports.get(mTransportType);
148 mCurrentState.isDefault = connectedTransports.get(mTransportType);
149 // Only show this as not having connectivity if we are default.
150 mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0;
151 notifyListenersIfNecessary();
Jason Monkda68f592015-01-07 10:55:58 -0500152 }
153
Andrew Flynna478d702015-04-14 23:33:45 -0400154 public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) {
155 mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode;
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400156 updateTelephony();
Andrew Flynna478d702015-04-14 23:33:45 -0400157 }
158
Jason Monkda68f592015-01-07 10:55:58 -0500159 /**
160 * Start listening for phone state changes.
161 */
162 public void registerListener() {
163 mPhone.listen(mPhoneStateListener,
164 PhoneStateListener.LISTEN_SERVICE_STATE
165 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
166 | PhoneStateListener.LISTEN_CALL_STATE
167 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
Andrew Flynna478d702015-04-14 23:33:45 -0400168 | PhoneStateListener.LISTEN_DATA_ACTIVITY
Fabian Kozynskiaaf78972019-07-08 10:02:08 -0400169 | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE
170 | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
Jason Monk0288de02017-02-23 14:48:05 -0500171 mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
172 true, mObserver);
173 mContext.getContentResolver().registerContentObserver(Global.getUriFor(
174 Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()),
175 true, mObserver);
Jason Monkda68f592015-01-07 10:55:58 -0500176 }
177
178 /**
179 * Stop listening for phone state changes.
180 */
181 public void unregisterListener() {
182 mPhone.listen(mPhoneStateListener, 0);
Jason Monk0288de02017-02-23 14:48:05 -0500183 mContext.getContentResolver().unregisterContentObserver(mObserver);
Jason Monkda68f592015-01-07 10:55:58 -0500184 }
185
186 /**
187 * Produce a mapping of data network types to icon groups for simple and quick use in
188 * updateTelephony.
189 */
190 private void mapIconSets() {
191 mNetworkToIconLookup.clear();
192
193 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
194 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
195 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
196 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
197 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
Wileen Chiu4105ab02015-09-18 15:17:54 -0700198 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_TD_SCDMA, TelephonyIcons.THREE_G);
Jason Monkda68f592015-01-07 10:55:58 -0500199
200 if (!mConfig.showAtLeast3G) {
201 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
202 TelephonyIcons.UNKNOWN);
203 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
204 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
205 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
206
207 mDefaultIcons = TelephonyIcons.G;
208 } else {
209 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
210 TelephonyIcons.THREE_G);
211 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
212 TelephonyIcons.THREE_G);
213 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
214 TelephonyIcons.THREE_G);
215 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
216 TelephonyIcons.THREE_G);
217 mDefaultIcons = TelephonyIcons.THREE_G;
218 }
219
220 MobileIconGroup hGroup = TelephonyIcons.THREE_G;
Amin Shaikhf5830ca2018-03-09 14:06:50 -0500221 MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
vagdevi3f2b9a52019-08-09 09:45:14 -0700222 if (mConfig.show4gFor3g) {
223 hGroup = TelephonyIcons.FOUR_G;
224 hPlusGroup = TelephonyIcons.FOUR_G;
225 } else if (mConfig.hspaDataDistinguishable) {
Jason Monkda68f592015-01-07 10:55:58 -0500226 hGroup = TelephonyIcons.H;
Amin Shaikhf5830ca2018-03-09 14:06:50 -0500227 hPlusGroup = TelephonyIcons.H_PLUS;
Jason Monkda68f592015-01-07 10:55:58 -0500228 }
vagdevi3f2b9a52019-08-09 09:45:14 -0700229
Jason Monkda68f592015-01-07 10:55:58 -0500230 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
231 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
232 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
Amin Shaikhf5830ca2018-03-09 14:06:50 -0500233 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hPlusGroup);
Jason Monkda68f592015-01-07 10:55:58 -0500234
235 if (mConfig.show4gForLte) {
236 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700237 if (mConfig.hideLtePlus) {
238 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
239 TelephonyIcons.FOUR_G);
240 } else {
241 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
242 TelephonyIcons.FOUR_G_PLUS);
243 }
Jason Monkda68f592015-01-07 10:55:58 -0500244 } else {
245 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700246 if (mConfig.hideLtePlus) {
247 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
248 TelephonyIcons.LTE);
249 } else {
250 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
251 TelephonyIcons.LTE_PLUS);
252 }
Jason Monkda68f592015-01-07 10:55:58 -0500253 }
SongFerngWang3cbcf752019-03-21 23:14:20 +0800254 mNetworkToIconLookup.put(NETWORK_TYPE_LTE_CA_5GE,
255 TelephonyIcons.LTE_CA_5G_E);
Jason Monk7150d7f2015-07-09 10:14:12 -0400256 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
Jason Monkda68f592015-01-07 10:55:58 -0500257 }
258
andychou9e396282019-04-10 20:49:06 +0800259 private void updateInflateSignalStrength() {
Antony Sargentc026de32019-05-21 16:29:04 -0700260 mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext,
261 mSubscriptionInfo.getSubscriptionId());
andychou9e396282019-04-10 20:49:06 +0800262 }
263
Jason Monk48edc0c2017-04-10 15:01:27 -0400264 private int getNumLevels() {
andychou9e396282019-04-10 20:49:06 +0800265 if (mInflateSignalStrengths) {
Jason Monk43c14d12017-06-22 11:20:04 -0400266 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1;
267 }
Jason Monk48edc0c2017-04-10 15:01:27 -0400268 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
269 }
270
271 @Override
272 public int getCurrentIconId() {
273 if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {
274 return SignalDrawable.getCarrierChangeState(getNumLevels());
275 } else if (mCurrentState.connected) {
Jason Monk43c14d12017-06-22 11:20:04 -0400276 int level = mCurrentState.level;
andychou9e396282019-04-10 20:49:06 +0800277 if (mInflateSignalStrengths) {
Jason Monk43c14d12017-06-22 11:20:04 -0400278 level++;
279 }
Amin Shaikhaf4c1932018-03-08 10:29:56 -0500280 boolean dataDisabled = mCurrentState.userSetup
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -0400281 && (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
282 || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA);
Amin Shaikhaf4c1932018-03-08 10:29:56 -0500283 boolean noInternet = mCurrentState.inetCondition == 0;
284 boolean cutOut = dataDisabled || noInternet;
285 return SignalDrawable.getState(level, getNumLevels(), cutOut);
Jason Monk48edc0c2017-04-10 15:01:27 -0400286 } else if (mCurrentState.enabled) {
287 return SignalDrawable.getEmptyState(getNumLevels());
288 } else {
289 return 0;
290 }
291 }
292
293 @Override
Jason Monk01df36f2017-06-07 13:02:47 -0400294 public int getQsCurrentIconId() {
295 return getCurrentIconId();
296 }
297
298 @Override
Jason Monke06b0652016-03-02 16:35:27 -0500299 public void notifyListeners(SignalCallback callback) {
Jason Monkda68f592015-01-07 10:55:58 -0500300 MobileIconGroup icons = getIcons();
301
302 String contentDescription = getStringIfExists(getContentDescription());
303 String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
Amin Shaikh43ad7fe2018-03-05 14:34:44 -0500304 if (mCurrentState.inetCondition == 0) {
305 dataContentDescription = mContext.getString(R.string.data_connection_no_internet);
306 }
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -0400307 final boolean dataDisabled = (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
308 || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA)
Jason Monkfd57ea72016-04-29 13:37:58 -0400309 && mCurrentState.userSetup;
Jeff Davidson5c7daaf2015-01-27 16:24:32 -0800310
Jason Monk0f0de132016-12-19 15:36:13 -0500311 // Show icon in QS when we are connected or data is disabled.
Jason Monk7e6c83c2017-04-26 14:35:24 -0400312 boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
Jason Monk07b75fe2015-05-14 16:47:03 -0400313 IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
314 getCurrentIconId(), contentDescription);
315
Jason Monk7e6c83c2017-04-26 14:35:24 -0400316 int qsTypeIcon = 0;
317 IconState qsIcon = null;
318 String description = null;
319 // Only send data sim callbacks to QS.
320 if (mCurrentState.dataSim) {
Evan Laird9dcd3222017-12-04 14:31:48 -0500321 qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mQsDataType : 0;
Jason Monk7e6c83c2017-04-26 14:35:24 -0400322 qsIcon = new IconState(mCurrentState.enabled
Jason Monk01df36f2017-06-07 13:02:47 -0400323 && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
Jason Monk7e6c83c2017-04-26 14:35:24 -0400324 description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
325 }
Jason Monk07b75fe2015-05-14 16:47:03 -0400326 boolean activityIn = mCurrentState.dataConnected
Jason Monk0288de02017-02-23 14:48:05 -0500327 && !mCurrentState.carrierNetworkChangeMode
328 && mCurrentState.activityIn;
Jason Monk07b75fe2015-05-14 16:47:03 -0400329 boolean activityOut = mCurrentState.dataConnected
Jason Monk0288de02017-02-23 14:48:05 -0500330 && !mCurrentState.carrierNetworkChangeMode
331 && mCurrentState.activityOut;
Jason Monk0f0de132016-12-19 15:36:13 -0500332 showDataIcon &= mCurrentState.isDefault || dataDisabled;
Wenting Xiong63364fe2017-02-07 19:12:27 +0800333 int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0;
Jason Monk7e6c83c2017-04-26 14:35:24 -0400334 callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
335 activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
336 mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
Andrew Flynna478d702015-04-14 23:33:45 -0400337 }
338
Jason Monkda68f592015-01-07 10:55:58 -0500339 @Override
340 protected MobileState cleanState() {
341 return new MobileState();
342 }
343
Jason Monkda68f592015-01-07 10:55:58 -0500344 private boolean isCdma() {
345 return (mSignalStrength != null) && !mSignalStrength.isGsm();
346 }
347
348 public boolean isEmergencyOnly() {
349 return (mServiceState != null && mServiceState.isEmergencyOnly());
350 }
351
352 private boolean isRoaming() {
Shishir Agrawal7ef5b882017-06-26 12:06:03 -0700353 // During a carrier change, roaming indications need to be supressed.
354 if (isCarrierNetworkChangeActive()) {
355 return false;
356 }
Jason Monke1531982017-09-05 11:20:30 -0400357 if (isCdma() && mServiceState != null) {
Jason Monkda68f592015-01-07 10:55:58 -0500358 final int iconMode = mServiceState.getCdmaEriIconMode();
359 return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
360 && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
Jason Monk0288de02017-02-23 14:48:05 -0500361 || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
Jason Monkda68f592015-01-07 10:55:58 -0500362 } else {
363 return mServiceState != null && mServiceState.getRoaming();
364 }
365 }
366
Andrew Flynna478d702015-04-14 23:33:45 -0400367 private boolean isCarrierNetworkChangeActive() {
Andrew Flynn55fc8002015-05-29 08:33:46 -0400368 return mCurrentState.carrierNetworkChangeMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400369 }
370
Jason Monkda68f592015-01-07 10:55:58 -0500371 public void handleBroadcast(Intent intent) {
372 String action = intent.getAction();
373 if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
374 updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
375 intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700376 intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN),
Jason Monkda68f592015-01-07 10:55:58 -0500377 intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
378 intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
379 notifyListenersIfNecessary();
380 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
381 updateDataSim();
Jason Monk8fcab352015-06-29 10:57:00 -0400382 notifyListenersIfNecessary();
Jason Monkda68f592015-01-07 10:55:58 -0500383 }
384 }
385
386 private void updateDataSim() {
Fabian Kozynskiccde55d2019-06-26 10:06:09 -0400387 int activeDataSubId = mDefaults.getActiveDataSubId();
388 if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) {
389 mCurrentState.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId();
Jason Monkda68f592015-01-07 10:55:58 -0500390 } else {
391 // There doesn't seem to be a data sim selected, however if
392 // there isn't a MobileSignalController with dataSim set, then
393 // QS won't get any callbacks and will be blank. Instead
394 // lets just assume we are the data sim (which will basically
395 // show one at random) in QS until one is selected. The user
396 // should pick one soon after, so we shouldn't be in this state
397 // for long.
398 mCurrentState.dataSim = true;
399 }
Jason Monkda68f592015-01-07 10:55:58 -0500400 }
401
SongFerngWang3cbcf752019-03-21 23:14:20 +0800402 private boolean isCarrierSpecificDataIcon() {
403 if (mConfig.patternOfCarrierSpecificDataIcon == null
404 || mConfig.patternOfCarrierSpecificDataIcon.length() == 0) {
405 return false;
406 }
407
408 Pattern stringPattern = Pattern.compile(mConfig.patternOfCarrierSpecificDataIcon);
409 String[] operatorNames = new String[]{mServiceState.getOperatorAlphaLongRaw(),
410 mServiceState.getOperatorAlphaShortRaw()};
411 for (String opName : operatorNames) {
412 if (!TextUtils.isEmpty(opName)) {
413 Matcher matcher = stringPattern.matcher(opName);
414 if (matcher.find()) {
415 return true;
416 }
417 }
418 }
419 return false;
420 }
421
Jason Monkda68f592015-01-07 10:55:58 -0500422 /**
423 * Updates the network's name based on incoming spn and plmn.
424 */
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700425 void updateNetworkName(boolean showSpn, String spn, String dataSpn,
426 boolean showPlmn, String plmn) {
Jason Monkda68f592015-01-07 10:55:58 -0500427 if (CHATTY) {
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700428 Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn
429 + " spn=" + spn + " dataSpn=" + dataSpn
Jason Monkda68f592015-01-07 10:55:58 -0500430 + " showPlmn=" + showPlmn + " plmn=" + plmn);
431 }
432 StringBuilder str = new StringBuilder();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700433 StringBuilder strData = new StringBuilder();
Jason Monkda68f592015-01-07 10:55:58 -0500434 if (showPlmn && plmn != null) {
435 str.append(plmn);
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700436 strData.append(plmn);
Jason Monkda68f592015-01-07 10:55:58 -0500437 }
438 if (showSpn && spn != null) {
439 if (str.length() != 0) {
440 str.append(mNetworkNameSeparator);
441 }
442 str.append(spn);
443 }
444 if (str.length() != 0) {
445 mCurrentState.networkName = str.toString();
446 } else {
447 mCurrentState.networkName = mNetworkNameDefault;
448 }
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700449 if (showSpn && dataSpn != null) {
450 if (strData.length() != 0) {
451 strData.append(mNetworkNameSeparator);
452 }
453 strData.append(dataSpn);
454 }
455 if (strData.length() != 0) {
456 mCurrentState.networkNameData = strData.toString();
457 } else {
458 mCurrentState.networkNameData = mNetworkNameDefault;
459 }
Jason Monkda68f592015-01-07 10:55:58 -0500460 }
461
462 /**
Jayachandran Ca6f9b6d2019-11-07 17:26:02 -0800463 * Extracts the CellSignalStrengthCdma from SignalStrength then returns the level
464 */
465 private final int getCdmaLevel() {
466 List<CellSignalStrengthCdma> signalStrengthCdma =
467 mSignalStrength.getCellSignalStrengths(CellSignalStrengthCdma.class);
468 if (!signalStrengthCdma.isEmpty()) {
469 return signalStrengthCdma.get(0).getLevel();
470 }
471 return CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
472 }
473
474 /**
Jason Monkda68f592015-01-07 10:55:58 -0500475 * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
476 * mDataState, and mSimState. It should be called any time one of these is updated.
477 * This will call listeners if necessary.
478 */
479 private final void updateTelephony() {
480 if (DEBUG) {
SongFerngWang8cfb4d52018-08-21 18:04:29 +0800481 Log.d(mTag, "updateTelephonySignalStrength: hasService=" +
482 Utils.isInService(mServiceState) + " ss=" + mSignalStrength);
Jason Monkda68f592015-01-07 10:55:58 -0500483 }
SongFerngWang8cfb4d52018-08-21 18:04:29 +0800484 mCurrentState.connected = Utils.isInService(mServiceState)
485 && mSignalStrength != null;
Jason Monkda68f592015-01-07 10:55:58 -0500486 if (mCurrentState.connected) {
487 if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
Jayachandran Ca6f9b6d2019-11-07 17:26:02 -0800488 mCurrentState.level = getCdmaLevel();
Jason Monkda68f592015-01-07 10:55:58 -0500489 } else {
490 mCurrentState.level = mSignalStrength.getLevel();
491 }
492 }
Pengquan Menga62d32b2018-12-06 17:38:38 -0800493
494 // When the device is camped on a 5G Non-Standalone network, the data network type is still
495 // LTE. In this case, we first check which 5G icon should be shown.
496 MobileIconGroup nr5GIconGroup = getNr5GIconGroup();
497 if (nr5GIconGroup != null) {
498 mCurrentState.iconGroup = nr5GIconGroup;
499 } else if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
Jason Monkda68f592015-01-07 10:55:58 -0500500 mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
501 } else {
502 mCurrentState.iconGroup = mDefaultIcons;
503 }
504 mCurrentState.dataConnected = mCurrentState.connected
Jason Monk7e6c83c2017-04-26 14:35:24 -0400505 && mDataState == TelephonyManager.DATA_CONNECTED;
Jason Monkda68f592015-01-07 10:55:58 -0500506
Jason Monk0f0de132016-12-19 15:36:13 -0500507 mCurrentState.roaming = isRoaming();
Andrew Flynna478d702015-04-14 23:33:45 -0400508 if (isCarrierNetworkChangeActive()) {
509 mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
Wenting Xiong63364fe2017-02-07 19:12:27 +0800510 } else if (isDataDisabled() && !mConfig.alwaysShowDataRatIcon) {
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -0400511 if (mSubscriptionInfo.getSubscriptionId()
512 != mDefaults.getDefaultDataSubId()) {
513 mCurrentState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA;
514 } else {
515 mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
516 }
Jason Monkda68f592015-01-07 10:55:58 -0500517 }
518 if (isEmergencyOnly() != mCurrentState.isEmergency) {
519 mCurrentState.isEmergency = isEmergencyOnly();
520 mNetworkController.recalculateEmergency();
521 }
522 // Fill in the network name if we think we have it.
Fabian Kozynskia9091992019-03-25 11:08:32 -0400523 if (mCurrentState.networkName.equals(mNetworkNameDefault) && mServiceState != null
Jason Monk93fb68f2015-07-20 11:43:56 -0400524 && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
Jason Monkda68f592015-01-07 10:55:58 -0500525 mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
526 }
Fabian Kozynskia9091992019-03-25 11:08:32 -0400527 // If this is the data subscription, update the currentState data name
528 if (mCurrentState.networkNameData.equals(mNetworkNameDefault) && mServiceState != null
529 && mCurrentState.dataSim
530 && !TextUtils.isEmpty(mServiceState.getDataOperatorAlphaShort())) {
531 mCurrentState.networkNameData = mServiceState.getDataOperatorAlphaShort();
532 }
Andrew Flynna478d702015-04-14 23:33:45 -0400533
Jason Monkda68f592015-01-07 10:55:58 -0500534 notifyListenersIfNecessary();
535 }
536
Pengquan Menga62d32b2018-12-06 17:38:38 -0800537 private MobileIconGroup getNr5GIconGroup() {
538 if (mServiceState == null) return null;
539
Jack Yu20d71402019-03-16 23:00:35 -0700540 int nrState = mServiceState.getNrState();
541 if (nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED) {
Pengquan Menga62d32b2018-12-06 17:38:38 -0800542 // Check if the NR 5G is using millimeter wave and the icon is config.
543 if (mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE) {
544 if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED_MMWAVE)) {
545 return mConfig.nr5GIconMap.get(Config.NR_CONNECTED_MMWAVE);
546 }
547 }
548
549 // If NR 5G is not using millimeter wave or there is no icon for millimeter wave, we
550 // check the normal 5G icon.
551 if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED)) {
552 return mConfig.nr5GIconMap.get(Config.NR_CONNECTED);
553 }
Jack Yu20d71402019-03-16 23:00:35 -0700554 } else if (nrState == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED) {
Pengquan Menga62d32b2018-12-06 17:38:38 -0800555 if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED)) {
556 return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED);
557 }
Jack Yu20d71402019-03-16 23:00:35 -0700558 } else if (nrState == NetworkRegistrationInfo.NR_STATE_RESTRICTED) {
Pengquan Menga62d32b2018-12-06 17:38:38 -0800559 if (mConfig.nr5GIconMap.containsKey(Config.NR_RESTRICTED)) {
560 return mConfig.nr5GIconMap.get(Config.NR_RESTRICTED);
561 }
562 }
563
564 return null;
565 }
566
Jason Monk1a95c862016-01-27 15:18:41 -0500567 private boolean isDataDisabled() {
Malcolm Chen04be9d12019-06-11 19:48:38 -0700568 return !mPhone.isDataCapable();
Jason Monk1a95c862016-01-27 15:18:41 -0500569 }
570
Jason Monkda68f592015-01-07 10:55:58 -0500571 @VisibleForTesting
572 void setActivity(int activity) {
573 mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
574 || activity == TelephonyManager.DATA_ACTIVITY_IN;
575 mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
576 || activity == TelephonyManager.DATA_ACTIVITY_OUT;
577 notifyListenersIfNecessary();
578 }
579
580 @Override
581 public void dump(PrintWriter pw) {
582 super.dump(pw);
583 pw.println(" mSubscription=" + mSubscriptionInfo + ",");
584 pw.println(" mServiceState=" + mServiceState + ",");
585 pw.println(" mSignalStrength=" + mSignalStrength + ",");
586 pw.println(" mDataState=" + mDataState + ",");
587 pw.println(" mDataNetType=" + mDataNetType + ",");
andychou9e396282019-04-10 20:49:06 +0800588 pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ",");
Malcolm Chen04be9d12019-06-11 19:48:38 -0700589 pw.println(" isDataDisabled=" + isDataDisabled() + ",");
Jason Monkda68f592015-01-07 10:55:58 -0500590 }
591
592 class MobilePhoneStateListener extends PhoneStateListener {
chen xu84a90872019-03-28 15:44:12 -0700593 public MobilePhoneStateListener(Looper looper) {
594 super(looper);
Jason Monkda68f592015-01-07 10:55:58 -0500595 }
596
597 @Override
598 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
599 if (DEBUG) {
600 Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
601 ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
602 }
603 mSignalStrength = signalStrength;
604 updateTelephony();
605 }
606
607 @Override
608 public void onServiceStateChanged(ServiceState state) {
609 if (DEBUG) {
610 Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
611 + " dataState=" + state.getDataRegState());
612 }
613 mServiceState = state;
SongFerngWang3cbcf752019-03-21 23:14:20 +0800614 if (mServiceState != null) {
615 updateDataNetType(mServiceState.getDataNetworkType());
Robert Greenwaltea0d71392016-07-28 18:50:10 -0700616 }
Jason Monkda68f592015-01-07 10:55:58 -0500617 updateTelephony();
618 }
619
620 @Override
621 public void onDataConnectionStateChanged(int state, int networkType) {
622 if (DEBUG) {
623 Log.d(mTag, "onDataConnectionStateChanged: state=" + state
624 + " type=" + networkType);
625 }
626 mDataState = state;
SongFerngWang3cbcf752019-03-21 23:14:20 +0800627 updateDataNetType(networkType);
Jason Monkda68f592015-01-07 10:55:58 -0500628 updateTelephony();
629 }
630
SongFerngWang3cbcf752019-03-21 23:14:20 +0800631 private void updateDataNetType(int networkType) {
632 mDataNetType = networkType;
633 if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE) {
634 if (isCarrierSpecificDataIcon()) {
635 mDataNetType = NETWORK_TYPE_LTE_CA_5GE;
636 } else if (mServiceState != null && mServiceState.isUsingCarrierAggregation()) {
637 mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
638 }
639 }
640 }
641
Jason Monkda68f592015-01-07 10:55:58 -0500642 @Override
643 public void onDataActivity(int direction) {
644 if (DEBUG) {
645 Log.d(mTag, "onDataActivity: direction=" + direction);
646 }
647 setActivity(direction);
648 }
Andrew Flynna478d702015-04-14 23:33:45 -0400649
650 @Override
651 public void onCarrierNetworkChange(boolean active) {
652 if (DEBUG) {
653 Log.d(mTag, "onCarrierNetworkChange: active=" + active);
654 }
655 mCurrentState.carrierNetworkChangeMode = active;
656
657 updateTelephony();
658 }
Fabian Kozynskiaaf78972019-07-08 10:02:08 -0400659
660 @Override
661 public void onActiveDataSubscriptionIdChanged(int subId) {
662 if (DEBUG) Log.d(mTag, "onActiveDataSubscriptionIdChanged: subId=" + subId);
663 updateDataSim();
664 updateTelephony();
665 }
Jason Monkda68f592015-01-07 10:55:58 -0500666 };
667
668 static class MobileIconGroup extends SignalController.IconGroup {
669 final int mDataContentDescription; // mContentDescriptionDataType
670 final int mDataType;
671 final boolean mIsWide;
Jason Monk33f8ae72015-05-08 10:45:15 -0400672 final int mQsDataType;
Jason Monkda68f592015-01-07 10:55:58 -0500673
674 public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
675 int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
Amin Shaikhd64e6262018-03-08 10:08:13 -0500676 int discContentDesc, int dataContentDesc, int dataType, boolean isWide) {
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400677 super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
678 qsDiscState, discContentDesc);
Jason Monkda68f592015-01-07 10:55:58 -0500679 mDataContentDescription = dataContentDesc;
680 mDataType = dataType;
681 mIsWide = isWide;
Amin Shaikhd64e6262018-03-08 10:08:13 -0500682 mQsDataType = dataType; // TODO: remove this field
Jason Monkda68f592015-01-07 10:55:58 -0500683 }
684 }
685
686 static class MobileState extends SignalController.State {
687 String networkName;
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700688 String networkNameData;
Jason Monkda68f592015-01-07 10:55:58 -0500689 boolean dataSim;
690 boolean dataConnected;
691 boolean isEmergency;
692 boolean airplaneMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400693 boolean carrierNetworkChangeMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400694 boolean isDefault;
Jason Monkfd57ea72016-04-29 13:37:58 -0400695 boolean userSetup;
Jason Monk0f0de132016-12-19 15:36:13 -0500696 boolean roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500697
698 @Override
699 public void copyFrom(State s) {
700 super.copyFrom(s);
701 MobileState state = (MobileState) s;
702 dataSim = state.dataSim;
703 networkName = state.networkName;
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700704 networkNameData = state.networkNameData;
Jason Monkda68f592015-01-07 10:55:58 -0500705 dataConnected = state.dataConnected;
Jason Monk33f8ae72015-05-08 10:45:15 -0400706 isDefault = state.isDefault;
Jason Monkda68f592015-01-07 10:55:58 -0500707 isEmergency = state.isEmergency;
708 airplaneMode = state.airplaneMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400709 carrierNetworkChangeMode = state.carrierNetworkChangeMode;
Jason Monkfd57ea72016-04-29 13:37:58 -0400710 userSetup = state.userSetup;
Jason Monk0f0de132016-12-19 15:36:13 -0500711 roaming = state.roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500712 }
713
714 @Override
715 protected void toString(StringBuilder builder) {
716 super.toString(builder);
717 builder.append(',');
718 builder.append("dataSim=").append(dataSim).append(',');
719 builder.append("networkName=").append(networkName).append(',');
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700720 builder.append("networkNameData=").append(networkNameData).append(',');
Jason Monkda68f592015-01-07 10:55:58 -0500721 builder.append("dataConnected=").append(dataConnected).append(',');
Jason Monk0f0de132016-12-19 15:36:13 -0500722 builder.append("roaming=").append(roaming).append(',');
Jason Monk33f8ae72015-05-08 10:45:15 -0400723 builder.append("isDefault=").append(isDefault).append(',');
Jason Monkda68f592015-01-07 10:55:58 -0500724 builder.append("isEmergency=").append(isEmergency).append(',');
Andrew Flynna478d702015-04-14 23:33:45 -0400725 builder.append("airplaneMode=").append(airplaneMode).append(',');
Jason Monkfd57ea72016-04-29 13:37:58 -0400726 builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
727 .append(',');
728 builder.append("userSetup=").append(userSetup);
Jason Monkda68f592015-01-07 10:55:58 -0500729 }
730
731 @Override
732 public boolean equals(Object o) {
733 return super.equals(o)
734 && Objects.equals(((MobileState) o).networkName, networkName)
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700735 && Objects.equals(((MobileState) o).networkNameData, networkNameData)
Jason Monkda68f592015-01-07 10:55:58 -0500736 && ((MobileState) o).dataSim == dataSim
737 && ((MobileState) o).dataConnected == dataConnected
738 && ((MobileState) o).isEmergency == isEmergency
739 && ((MobileState) o).airplaneMode == airplaneMode
Andrew Flynna478d702015-04-14 23:33:45 -0400740 && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
Jason Monkfd57ea72016-04-29 13:37:58 -0400741 && ((MobileState) o).userSetup == userSetup
Jason Monk0f0de132016-12-19 15:36:13 -0500742 && ((MobileState) o).isDefault == isDefault
743 && ((MobileState) o).roaming == roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500744 }
745 }
746}