blob: b21ba096c361495d99ca434b910ead497656b292 [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;
Jack Yue27d3fd2019-03-15 14:49:53 -070025import android.telephony.NetworkRegistrationInfo;
Jason Monkda68f592015-01-07 10:55:58 -050026import android.telephony.PhoneStateListener;
27import android.telephony.ServiceState;
28import android.telephony.SignalStrength;
29import android.telephony.SubscriptionInfo;
30import android.telephony.SubscriptionManager;
31import android.telephony.TelephonyManager;
Jason Monk93fb68f2015-07-20 11:43:56 -040032import android.text.TextUtils;
Jason Monkda68f592015-01-07 10:55:58 -050033import android.util.Log;
34import android.util.SparseArray;
35
36import com.android.internal.annotations.VisibleForTesting;
Jason Monkda68f592015-01-07 10:55:58 -050037import com.android.internal.telephony.TelephonyIntents;
38import com.android.internal.telephony.cdma.EriInfo;
SongFerngWang8cfb4d52018-08-21 18:04:29 +080039import com.android.settingslib.Utils;
Gus Prevasab336792018-11-14 13:52:20 -050040import com.android.settingslib.graph.SignalDrawable;
Antony Sargentc026de32019-05-21 16:29:04 -070041import com.android.settingslib.net.SignalStrengthUtil;
Jason Monkda68f592015-01-07 10:55:58 -050042import com.android.systemui.R;
Jason Monk07b75fe2015-05-14 16:47:03 -040043import com.android.systemui.statusbar.policy.NetworkController.IconState;
Jason Monke06b0652016-03-02 16:35:27 -050044import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
Jason Monkda68f592015-01-07 10:55:58 -050045import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
Jason Monkc6cc6262015-06-11 11:10:15 -040046import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
Jason Monkda68f592015-01-07 10:55:58 -050047
48import java.io.PrintWriter;
Jason Monk33f8ae72015-05-08 10:45:15 -040049import java.util.BitSet;
Jason Monkda68f592015-01-07 10:55:58 -050050import java.util.Objects;
SongFerngWang3cbcf752019-03-21 23:14:20 +080051import java.util.regex.Matcher;
52import java.util.regex.Pattern;
Jason Monkda68f592015-01-07 10:55:58 -050053
54
55public class MobileSignalController extends SignalController<
56 MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
57 private final TelephonyManager mPhone;
Jason Monkc6cc6262015-06-11 11:10:15 -040058 private final SubscriptionDefaults mDefaults;
Jason Monkda68f592015-01-07 10:55:58 -050059 private final String mNetworkNameDefault;
60 private final String mNetworkNameSeparator;
Jason Monk0288de02017-02-23 14:48:05 -050061 private final ContentObserver mObserver;
Jason Monkda68f592015-01-07 10:55:58 -050062 @VisibleForTesting
63 final PhoneStateListener mPhoneStateListener;
64 // Save entire info for logging, we only use the id.
Jason Monk66845a32015-08-03 11:09:41 -040065 final SubscriptionInfo mSubscriptionInfo;
Jason Monkda68f592015-01-07 10:55:58 -050066
67 // @VisibleForDemoMode
68 final SparseArray<MobileIconGroup> mNetworkToIconLookup;
69
70 // Since some pieces of the phone state are interdependent we store it locally,
71 // this could potentially become part of MobileState for simplification/complication
72 // of code.
Jason Monkda68f592015-01-07 10:55:58 -050073 private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
74 private int mDataState = TelephonyManager.DATA_DISCONNECTED;
75 private ServiceState mServiceState;
76 private SignalStrength mSignalStrength;
77 private MobileIconGroup mDefaultIcons;
78 private Config mConfig;
andychoub935e682019-04-11 23:40:49 +080079 @VisibleForTesting
80 boolean mInflateSignalStrengths = false;
SongFerngWang3cbcf752019-03-21 23:14:20 +080081 // Some specific carriers have 5GE network which is special LTE CA network.
82 private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1;
Jason Monkda68f592015-01-07 10:55:58 -050083
84 // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
85 // need listener lists anymore.
86 public MobileSignalController(Context context, Config config, boolean hasMobileData,
Jason Monk07b75fe2015-05-14 16:47:03 -040087 TelephonyManager phone, CallbackHandler callbackHandler,
Jason Monkc6cc6262015-06-11 11:10:15 -040088 NetworkControllerImpl networkController, SubscriptionInfo info,
89 SubscriptionDefaults defaults, Looper receiverLooper) {
Jason Monkda68f592015-01-07 10:55:58 -050090 super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
Jason Monk07b75fe2015-05-14 16:47:03 -040091 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
Jason Monkda68f592015-01-07 10:55:58 -050092 networkController);
93 mNetworkToIconLookup = new SparseArray<>();
94 mConfig = config;
95 mPhone = phone;
Jason Monkc6cc6262015-06-11 11:10:15 -040096 mDefaults = defaults;
Jason Monkda68f592015-01-07 10:55:58 -050097 mSubscriptionInfo = info;
chen xu84a90872019-03-28 15:44:12 -070098 mPhoneStateListener = new MobilePhoneStateListener(receiverLooper);
Jason Monkda68f592015-01-07 10:55:58 -050099 mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
100 mNetworkNameDefault = getStringIfExists(
101 com.android.internal.R.string.lockscreen_carrier_default);
102
103 mapIconSets();
104
Jason Monk00aa9d42015-08-10 10:12:02 -0400105 String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
106 : mNetworkNameDefault;
107 mLastState.networkName = mCurrentState.networkName = networkName;
108 mLastState.networkNameData = mCurrentState.networkNameData = networkName;
Jason Monkda68f592015-01-07 10:55:58 -0500109 mLastState.enabled = mCurrentState.enabled = hasMobileData;
110 mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
111 // Get initial data sim state.
112 updateDataSim();
Jason Monk0288de02017-02-23 14:48:05 -0500113 mObserver = new ContentObserver(new Handler(receiverLooper)) {
114 @Override
115 public void onChange(boolean selfChange) {
116 updateTelephony();
117 }
118 };
Jason Monkda68f592015-01-07 10:55:58 -0500119 }
120
121 public void setConfiguration(Config config) {
122 mConfig = config;
andychou9e396282019-04-10 20:49:06 +0800123 updateInflateSignalStrength();
Jason Monkda68f592015-01-07 10:55:58 -0500124 mapIconSets();
125 updateTelephony();
126 }
127
Jason Monkda68f592015-01-07 10:55:58 -0500128 public int getDataContentDescription() {
129 return getIcons().mDataContentDescription;
130 }
131
Jason Monkda68f592015-01-07 10:55:58 -0500132 public void setAirplaneMode(boolean airplaneMode) {
133 mCurrentState.airplaneMode = airplaneMode;
134 notifyListenersIfNecessary();
135 }
136
Jason Monkfd57ea72016-04-29 13:37:58 -0400137 public void setUserSetupComplete(boolean userSetup) {
138 mCurrentState.userSetup = userSetup;
139 notifyListenersIfNecessary();
140 }
141
Jason Monk33f8ae72015-05-08 10:45:15 -0400142 @Override
143 public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
144 boolean isValidated = validatedTransports.get(mTransportType);
145 mCurrentState.isDefault = connectedTransports.get(mTransportType);
146 // Only show this as not having connectivity if we are default.
147 mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0;
148 notifyListenersIfNecessary();
Jason Monkda68f592015-01-07 10:55:58 -0500149 }
150
Andrew Flynna478d702015-04-14 23:33:45 -0400151 public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) {
152 mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode;
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400153 updateTelephony();
Andrew Flynna478d702015-04-14 23:33:45 -0400154 }
155
Jason Monkda68f592015-01-07 10:55:58 -0500156 /**
157 * Start listening for phone state changes.
158 */
159 public void registerListener() {
160 mPhone.listen(mPhoneStateListener,
161 PhoneStateListener.LISTEN_SERVICE_STATE
162 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
163 | PhoneStateListener.LISTEN_CALL_STATE
164 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
Andrew Flynna478d702015-04-14 23:33:45 -0400165 | PhoneStateListener.LISTEN_DATA_ACTIVITY
166 | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
Jason Monk0288de02017-02-23 14:48:05 -0500167 mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
168 true, mObserver);
169 mContext.getContentResolver().registerContentObserver(Global.getUriFor(
170 Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()),
171 true, mObserver);
Jason Monkda68f592015-01-07 10:55:58 -0500172 }
173
174 /**
175 * Stop listening for phone state changes.
176 */
177 public void unregisterListener() {
178 mPhone.listen(mPhoneStateListener, 0);
Jason Monk0288de02017-02-23 14:48:05 -0500179 mContext.getContentResolver().unregisterContentObserver(mObserver);
Jason Monkda68f592015-01-07 10:55:58 -0500180 }
181
182 /**
183 * Produce a mapping of data network types to icon groups for simple and quick use in
184 * updateTelephony.
185 */
186 private void mapIconSets() {
187 mNetworkToIconLookup.clear();
188
189 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
190 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
191 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
192 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
193 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
Wileen Chiu4105ab02015-09-18 15:17:54 -0700194 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_TD_SCDMA, TelephonyIcons.THREE_G);
Jason Monkda68f592015-01-07 10:55:58 -0500195
196 if (!mConfig.showAtLeast3G) {
197 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
198 TelephonyIcons.UNKNOWN);
199 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
200 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
201 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
202
203 mDefaultIcons = TelephonyIcons.G;
204 } else {
205 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
206 TelephonyIcons.THREE_G);
207 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
208 TelephonyIcons.THREE_G);
209 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
210 TelephonyIcons.THREE_G);
211 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
212 TelephonyIcons.THREE_G);
213 mDefaultIcons = TelephonyIcons.THREE_G;
214 }
215
216 MobileIconGroup hGroup = TelephonyIcons.THREE_G;
Amin Shaikhf5830ca2018-03-09 14:06:50 -0500217 MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
Jason Monkda68f592015-01-07 10:55:58 -0500218 if (mConfig.hspaDataDistinguishable) {
219 hGroup = TelephonyIcons.H;
Amin Shaikhf5830ca2018-03-09 14:06:50 -0500220 hPlusGroup = TelephonyIcons.H_PLUS;
Jason Monkda68f592015-01-07 10:55:58 -0500221 }
222 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
223 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
224 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
Amin Shaikhf5830ca2018-03-09 14:06:50 -0500225 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hPlusGroup);
Jason Monkda68f592015-01-07 10:55:58 -0500226
227 if (mConfig.show4gForLte) {
228 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700229 if (mConfig.hideLtePlus) {
230 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
231 TelephonyIcons.FOUR_G);
232 } else {
233 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
234 TelephonyIcons.FOUR_G_PLUS);
235 }
Jason Monkda68f592015-01-07 10:55:58 -0500236 } else {
237 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700238 if (mConfig.hideLtePlus) {
239 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
240 TelephonyIcons.LTE);
241 } else {
242 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
243 TelephonyIcons.LTE_PLUS);
244 }
Jason Monkda68f592015-01-07 10:55:58 -0500245 }
SongFerngWang3cbcf752019-03-21 23:14:20 +0800246 mNetworkToIconLookup.put(NETWORK_TYPE_LTE_CA_5GE,
247 TelephonyIcons.LTE_CA_5G_E);
Jason Monk7150d7f2015-07-09 10:14:12 -0400248 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
Jason Monkda68f592015-01-07 10:55:58 -0500249 }
250
andychou9e396282019-04-10 20:49:06 +0800251 private void updateInflateSignalStrength() {
Antony Sargentc026de32019-05-21 16:29:04 -0700252 mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext,
253 mSubscriptionInfo.getSubscriptionId());
andychou9e396282019-04-10 20:49:06 +0800254 }
255
Jason Monk48edc0c2017-04-10 15:01:27 -0400256 private int getNumLevels() {
andychou9e396282019-04-10 20:49:06 +0800257 if (mInflateSignalStrengths) {
Jason Monk43c14d12017-06-22 11:20:04 -0400258 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1;
259 }
Jason Monk48edc0c2017-04-10 15:01:27 -0400260 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
261 }
262
263 @Override
264 public int getCurrentIconId() {
265 if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {
266 return SignalDrawable.getCarrierChangeState(getNumLevels());
267 } else if (mCurrentState.connected) {
Jason Monk43c14d12017-06-22 11:20:04 -0400268 int level = mCurrentState.level;
andychou9e396282019-04-10 20:49:06 +0800269 if (mInflateSignalStrengths) {
Jason Monk43c14d12017-06-22 11:20:04 -0400270 level++;
271 }
Amin Shaikhaf4c1932018-03-08 10:29:56 -0500272 boolean dataDisabled = mCurrentState.userSetup
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -0400273 && (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
274 || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA);
Amin Shaikhaf4c1932018-03-08 10:29:56 -0500275 boolean noInternet = mCurrentState.inetCondition == 0;
276 boolean cutOut = dataDisabled || noInternet;
277 return SignalDrawable.getState(level, getNumLevels(), cutOut);
Jason Monk48edc0c2017-04-10 15:01:27 -0400278 } else if (mCurrentState.enabled) {
279 return SignalDrawable.getEmptyState(getNumLevels());
280 } else {
281 return 0;
282 }
283 }
284
285 @Override
Jason Monk01df36f2017-06-07 13:02:47 -0400286 public int getQsCurrentIconId() {
287 return getCurrentIconId();
288 }
289
290 @Override
Jason Monke06b0652016-03-02 16:35:27 -0500291 public void notifyListeners(SignalCallback callback) {
Jason Monkda68f592015-01-07 10:55:58 -0500292 MobileIconGroup icons = getIcons();
293
294 String contentDescription = getStringIfExists(getContentDescription());
295 String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
Amin Shaikh43ad7fe2018-03-05 14:34:44 -0500296 if (mCurrentState.inetCondition == 0) {
297 dataContentDescription = mContext.getString(R.string.data_connection_no_internet);
298 }
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -0400299 final boolean dataDisabled = (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
300 || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA)
Jason Monkfd57ea72016-04-29 13:37:58 -0400301 && mCurrentState.userSetup;
Jeff Davidson5c7daaf2015-01-27 16:24:32 -0800302
Jason Monk0f0de132016-12-19 15:36:13 -0500303 // Show icon in QS when we are connected or data is disabled.
Jason Monk7e6c83c2017-04-26 14:35:24 -0400304 boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
Jason Monk07b75fe2015-05-14 16:47:03 -0400305 IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
306 getCurrentIconId(), contentDescription);
307
Jason Monk7e6c83c2017-04-26 14:35:24 -0400308 int qsTypeIcon = 0;
309 IconState qsIcon = null;
310 String description = null;
311 // Only send data sim callbacks to QS.
312 if (mCurrentState.dataSim) {
Evan Laird9dcd3222017-12-04 14:31:48 -0500313 qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mQsDataType : 0;
Jason Monk7e6c83c2017-04-26 14:35:24 -0400314 qsIcon = new IconState(mCurrentState.enabled
Jason Monk01df36f2017-06-07 13:02:47 -0400315 && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
Jason Monk7e6c83c2017-04-26 14:35:24 -0400316 description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
317 }
Jason Monk07b75fe2015-05-14 16:47:03 -0400318 boolean activityIn = mCurrentState.dataConnected
Jason Monk0288de02017-02-23 14:48:05 -0500319 && !mCurrentState.carrierNetworkChangeMode
320 && mCurrentState.activityIn;
Jason Monk07b75fe2015-05-14 16:47:03 -0400321 boolean activityOut = mCurrentState.dataConnected
Jason Monk0288de02017-02-23 14:48:05 -0500322 && !mCurrentState.carrierNetworkChangeMode
323 && mCurrentState.activityOut;
Jason Monk0f0de132016-12-19 15:36:13 -0500324 showDataIcon &= mCurrentState.isDefault || dataDisabled;
Wenting Xiong63364fe2017-02-07 19:12:27 +0800325 int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0;
Jason Monk7e6c83c2017-04-26 14:35:24 -0400326 callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
327 activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
328 mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
Andrew Flynna478d702015-04-14 23:33:45 -0400329 }
330
Jason Monkda68f592015-01-07 10:55:58 -0500331 @Override
332 protected MobileState cleanState() {
333 return new MobileState();
334 }
335
Jason Monkda68f592015-01-07 10:55:58 -0500336 private boolean isCdma() {
337 return (mSignalStrength != null) && !mSignalStrength.isGsm();
338 }
339
340 public boolean isEmergencyOnly() {
341 return (mServiceState != null && mServiceState.isEmergencyOnly());
342 }
343
344 private boolean isRoaming() {
Shishir Agrawal7ef5b882017-06-26 12:06:03 -0700345 // During a carrier change, roaming indications need to be supressed.
346 if (isCarrierNetworkChangeActive()) {
347 return false;
348 }
Jason Monke1531982017-09-05 11:20:30 -0400349 if (isCdma() && mServiceState != null) {
Jason Monkda68f592015-01-07 10:55:58 -0500350 final int iconMode = mServiceState.getCdmaEriIconMode();
351 return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
352 && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
Jason Monk0288de02017-02-23 14:48:05 -0500353 || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
Jason Monkda68f592015-01-07 10:55:58 -0500354 } else {
355 return mServiceState != null && mServiceState.getRoaming();
356 }
357 }
358
Andrew Flynna478d702015-04-14 23:33:45 -0400359 private boolean isCarrierNetworkChangeActive() {
Andrew Flynn55fc8002015-05-29 08:33:46 -0400360 return mCurrentState.carrierNetworkChangeMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400361 }
362
Jason Monkda68f592015-01-07 10:55:58 -0500363 public void handleBroadcast(Intent intent) {
364 String action = intent.getAction();
365 if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
366 updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
367 intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700368 intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN),
Jason Monkda68f592015-01-07 10:55:58 -0500369 intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
370 intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
371 notifyListenersIfNecessary();
372 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
373 updateDataSim();
Jason Monk8fcab352015-06-29 10:57:00 -0400374 notifyListenersIfNecessary();
Jason Monkda68f592015-01-07 10:55:58 -0500375 }
376 }
377
378 private void updateDataSim() {
Fabian Kozynskiccde55d2019-06-26 10:06:09 -0400379 int activeDataSubId = mDefaults.getActiveDataSubId();
380 if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) {
381 mCurrentState.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId();
Jason Monkda68f592015-01-07 10:55:58 -0500382 } else {
383 // There doesn't seem to be a data sim selected, however if
384 // there isn't a MobileSignalController with dataSim set, then
385 // QS won't get any callbacks and will be blank. Instead
386 // lets just assume we are the data sim (which will basically
387 // show one at random) in QS until one is selected. The user
388 // should pick one soon after, so we shouldn't be in this state
389 // for long.
390 mCurrentState.dataSim = true;
391 }
Jason Monkda68f592015-01-07 10:55:58 -0500392 }
393
SongFerngWang3cbcf752019-03-21 23:14:20 +0800394 private boolean isCarrierSpecificDataIcon() {
395 if (mConfig.patternOfCarrierSpecificDataIcon == null
396 || mConfig.patternOfCarrierSpecificDataIcon.length() == 0) {
397 return false;
398 }
399
400 Pattern stringPattern = Pattern.compile(mConfig.patternOfCarrierSpecificDataIcon);
401 String[] operatorNames = new String[]{mServiceState.getOperatorAlphaLongRaw(),
402 mServiceState.getOperatorAlphaShortRaw()};
403 for (String opName : operatorNames) {
404 if (!TextUtils.isEmpty(opName)) {
405 Matcher matcher = stringPattern.matcher(opName);
406 if (matcher.find()) {
407 return true;
408 }
409 }
410 }
411 return false;
412 }
413
Jason Monkda68f592015-01-07 10:55:58 -0500414 /**
415 * Updates the network's name based on incoming spn and plmn.
416 */
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700417 void updateNetworkName(boolean showSpn, String spn, String dataSpn,
418 boolean showPlmn, String plmn) {
Jason Monkda68f592015-01-07 10:55:58 -0500419 if (CHATTY) {
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700420 Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn
421 + " spn=" + spn + " dataSpn=" + dataSpn
Jason Monkda68f592015-01-07 10:55:58 -0500422 + " showPlmn=" + showPlmn + " plmn=" + plmn);
423 }
424 StringBuilder str = new StringBuilder();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700425 StringBuilder strData = new StringBuilder();
Jason Monkda68f592015-01-07 10:55:58 -0500426 if (showPlmn && plmn != null) {
427 str.append(plmn);
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700428 strData.append(plmn);
Jason Monkda68f592015-01-07 10:55:58 -0500429 }
430 if (showSpn && spn != null) {
431 if (str.length() != 0) {
432 str.append(mNetworkNameSeparator);
433 }
434 str.append(spn);
435 }
436 if (str.length() != 0) {
437 mCurrentState.networkName = str.toString();
438 } else {
439 mCurrentState.networkName = mNetworkNameDefault;
440 }
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700441 if (showSpn && dataSpn != null) {
442 if (strData.length() != 0) {
443 strData.append(mNetworkNameSeparator);
444 }
445 strData.append(dataSpn);
446 }
447 if (strData.length() != 0) {
448 mCurrentState.networkNameData = strData.toString();
449 } else {
450 mCurrentState.networkNameData = mNetworkNameDefault;
451 }
Jason Monkda68f592015-01-07 10:55:58 -0500452 }
453
454 /**
455 * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
456 * mDataState, and mSimState. It should be called any time one of these is updated.
457 * This will call listeners if necessary.
458 */
459 private final void updateTelephony() {
460 if (DEBUG) {
SongFerngWang8cfb4d52018-08-21 18:04:29 +0800461 Log.d(mTag, "updateTelephonySignalStrength: hasService=" +
462 Utils.isInService(mServiceState) + " ss=" + mSignalStrength);
Jason Monkda68f592015-01-07 10:55:58 -0500463 }
SongFerngWang8cfb4d52018-08-21 18:04:29 +0800464 mCurrentState.connected = Utils.isInService(mServiceState)
465 && mSignalStrength != null;
Jason Monkda68f592015-01-07 10:55:58 -0500466 if (mCurrentState.connected) {
467 if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
468 mCurrentState.level = mSignalStrength.getCdmaLevel();
469 } else {
470 mCurrentState.level = mSignalStrength.getLevel();
471 }
472 }
Pengquan Menga62d32b2018-12-06 17:38:38 -0800473
474 // When the device is camped on a 5G Non-Standalone network, the data network type is still
475 // LTE. In this case, we first check which 5G icon should be shown.
476 MobileIconGroup nr5GIconGroup = getNr5GIconGroup();
477 if (nr5GIconGroup != null) {
478 mCurrentState.iconGroup = nr5GIconGroup;
479 } else if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
Jason Monkda68f592015-01-07 10:55:58 -0500480 mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
481 } else {
482 mCurrentState.iconGroup = mDefaultIcons;
483 }
484 mCurrentState.dataConnected = mCurrentState.connected
Jason Monk7e6c83c2017-04-26 14:35:24 -0400485 && mDataState == TelephonyManager.DATA_CONNECTED;
Jason Monkda68f592015-01-07 10:55:58 -0500486
Jason Monk0f0de132016-12-19 15:36:13 -0500487 mCurrentState.roaming = isRoaming();
Andrew Flynna478d702015-04-14 23:33:45 -0400488 if (isCarrierNetworkChangeActive()) {
489 mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
Wenting Xiong63364fe2017-02-07 19:12:27 +0800490 } else if (isDataDisabled() && !mConfig.alwaysShowDataRatIcon) {
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -0400491 if (mSubscriptionInfo.getSubscriptionId()
492 != mDefaults.getDefaultDataSubId()) {
493 mCurrentState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA;
494 } else {
495 mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
496 }
Jason Monkda68f592015-01-07 10:55:58 -0500497 }
498 if (isEmergencyOnly() != mCurrentState.isEmergency) {
499 mCurrentState.isEmergency = isEmergencyOnly();
500 mNetworkController.recalculateEmergency();
501 }
502 // Fill in the network name if we think we have it.
Fabian Kozynskia9091992019-03-25 11:08:32 -0400503 if (mCurrentState.networkName.equals(mNetworkNameDefault) && mServiceState != null
Jason Monk93fb68f2015-07-20 11:43:56 -0400504 && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
Jason Monkda68f592015-01-07 10:55:58 -0500505 mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
506 }
Fabian Kozynskia9091992019-03-25 11:08:32 -0400507 // If this is the data subscription, update the currentState data name
508 if (mCurrentState.networkNameData.equals(mNetworkNameDefault) && mServiceState != null
509 && mCurrentState.dataSim
510 && !TextUtils.isEmpty(mServiceState.getDataOperatorAlphaShort())) {
511 mCurrentState.networkNameData = mServiceState.getDataOperatorAlphaShort();
512 }
Andrew Flynna478d702015-04-14 23:33:45 -0400513
Jason Monkda68f592015-01-07 10:55:58 -0500514 notifyListenersIfNecessary();
515 }
516
Pengquan Menga62d32b2018-12-06 17:38:38 -0800517 private MobileIconGroup getNr5GIconGroup() {
518 if (mServiceState == null) return null;
519
Jack Yu20d71402019-03-16 23:00:35 -0700520 int nrState = mServiceState.getNrState();
521 if (nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED) {
Pengquan Menga62d32b2018-12-06 17:38:38 -0800522 // Check if the NR 5G is using millimeter wave and the icon is config.
523 if (mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE) {
524 if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED_MMWAVE)) {
525 return mConfig.nr5GIconMap.get(Config.NR_CONNECTED_MMWAVE);
526 }
527 }
528
529 // If NR 5G is not using millimeter wave or there is no icon for millimeter wave, we
530 // check the normal 5G icon.
531 if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED)) {
532 return mConfig.nr5GIconMap.get(Config.NR_CONNECTED);
533 }
Jack Yu20d71402019-03-16 23:00:35 -0700534 } else if (nrState == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED) {
Pengquan Menga62d32b2018-12-06 17:38:38 -0800535 if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED)) {
536 return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED);
537 }
Jack Yu20d71402019-03-16 23:00:35 -0700538 } else if (nrState == NetworkRegistrationInfo.NR_STATE_RESTRICTED) {
Pengquan Menga62d32b2018-12-06 17:38:38 -0800539 if (mConfig.nr5GIconMap.containsKey(Config.NR_RESTRICTED)) {
540 return mConfig.nr5GIconMap.get(Config.NR_RESTRICTED);
541 }
542 }
543
544 return null;
545 }
546
Jason Monk1a95c862016-01-27 15:18:41 -0500547 private boolean isDataDisabled() {
Malcolm Chen04be9d12019-06-11 19:48:38 -0700548 return !mPhone.isDataCapable();
Jason Monk1a95c862016-01-27 15:18:41 -0500549 }
550
Jason Monkda68f592015-01-07 10:55:58 -0500551 @VisibleForTesting
552 void setActivity(int activity) {
553 mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
554 || activity == TelephonyManager.DATA_ACTIVITY_IN;
555 mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
556 || activity == TelephonyManager.DATA_ACTIVITY_OUT;
557 notifyListenersIfNecessary();
558 }
559
560 @Override
561 public void dump(PrintWriter pw) {
562 super.dump(pw);
563 pw.println(" mSubscription=" + mSubscriptionInfo + ",");
564 pw.println(" mServiceState=" + mServiceState + ",");
565 pw.println(" mSignalStrength=" + mSignalStrength + ",");
566 pw.println(" mDataState=" + mDataState + ",");
567 pw.println(" mDataNetType=" + mDataNetType + ",");
andychou9e396282019-04-10 20:49:06 +0800568 pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ",");
Malcolm Chen04be9d12019-06-11 19:48:38 -0700569 pw.println(" isDataDisabled=" + isDataDisabled() + ",");
Jason Monkda68f592015-01-07 10:55:58 -0500570 }
571
572 class MobilePhoneStateListener extends PhoneStateListener {
chen xu84a90872019-03-28 15:44:12 -0700573 public MobilePhoneStateListener(Looper looper) {
574 super(looper);
Jason Monkda68f592015-01-07 10:55:58 -0500575 }
576
577 @Override
578 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
579 if (DEBUG) {
580 Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
581 ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
582 }
583 mSignalStrength = signalStrength;
584 updateTelephony();
585 }
586
587 @Override
588 public void onServiceStateChanged(ServiceState state) {
589 if (DEBUG) {
590 Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
591 + " dataState=" + state.getDataRegState());
592 }
593 mServiceState = state;
SongFerngWang3cbcf752019-03-21 23:14:20 +0800594 if (mServiceState != null) {
595 updateDataNetType(mServiceState.getDataNetworkType());
Robert Greenwaltea0d71392016-07-28 18:50:10 -0700596 }
Jason Monkda68f592015-01-07 10:55:58 -0500597 updateTelephony();
598 }
599
600 @Override
601 public void onDataConnectionStateChanged(int state, int networkType) {
602 if (DEBUG) {
603 Log.d(mTag, "onDataConnectionStateChanged: state=" + state
604 + " type=" + networkType);
605 }
606 mDataState = state;
SongFerngWang3cbcf752019-03-21 23:14:20 +0800607 updateDataNetType(networkType);
Jason Monkda68f592015-01-07 10:55:58 -0500608 updateTelephony();
609 }
610
SongFerngWang3cbcf752019-03-21 23:14:20 +0800611 private void updateDataNetType(int networkType) {
612 mDataNetType = networkType;
613 if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE) {
614 if (isCarrierSpecificDataIcon()) {
615 mDataNetType = NETWORK_TYPE_LTE_CA_5GE;
616 } else if (mServiceState != null && mServiceState.isUsingCarrierAggregation()) {
617 mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
618 }
619 }
620 }
621
Jason Monkda68f592015-01-07 10:55:58 -0500622 @Override
623 public void onDataActivity(int direction) {
624 if (DEBUG) {
625 Log.d(mTag, "onDataActivity: direction=" + direction);
626 }
627 setActivity(direction);
628 }
Andrew Flynna478d702015-04-14 23:33:45 -0400629
630 @Override
631 public void onCarrierNetworkChange(boolean active) {
632 if (DEBUG) {
633 Log.d(mTag, "onCarrierNetworkChange: active=" + active);
634 }
635 mCurrentState.carrierNetworkChangeMode = active;
636
637 updateTelephony();
638 }
Jason Monkda68f592015-01-07 10:55:58 -0500639 };
640
641 static class MobileIconGroup extends SignalController.IconGroup {
642 final int mDataContentDescription; // mContentDescriptionDataType
643 final int mDataType;
644 final boolean mIsWide;
Jason Monk33f8ae72015-05-08 10:45:15 -0400645 final int mQsDataType;
Jason Monkda68f592015-01-07 10:55:58 -0500646
647 public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
648 int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
Amin Shaikhd64e6262018-03-08 10:08:13 -0500649 int discContentDesc, int dataContentDesc, int dataType, boolean isWide) {
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400650 super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
651 qsDiscState, discContentDesc);
Jason Monkda68f592015-01-07 10:55:58 -0500652 mDataContentDescription = dataContentDesc;
653 mDataType = dataType;
654 mIsWide = isWide;
Amin Shaikhd64e6262018-03-08 10:08:13 -0500655 mQsDataType = dataType; // TODO: remove this field
Jason Monkda68f592015-01-07 10:55:58 -0500656 }
657 }
658
659 static class MobileState extends SignalController.State {
660 String networkName;
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700661 String networkNameData;
Jason Monkda68f592015-01-07 10:55:58 -0500662 boolean dataSim;
663 boolean dataConnected;
664 boolean isEmergency;
665 boolean airplaneMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400666 boolean carrierNetworkChangeMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400667 boolean isDefault;
Jason Monkfd57ea72016-04-29 13:37:58 -0400668 boolean userSetup;
Jason Monk0f0de132016-12-19 15:36:13 -0500669 boolean roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500670
671 @Override
672 public void copyFrom(State s) {
673 super.copyFrom(s);
674 MobileState state = (MobileState) s;
675 dataSim = state.dataSim;
676 networkName = state.networkName;
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700677 networkNameData = state.networkNameData;
Jason Monkda68f592015-01-07 10:55:58 -0500678 dataConnected = state.dataConnected;
Jason Monk33f8ae72015-05-08 10:45:15 -0400679 isDefault = state.isDefault;
Jason Monkda68f592015-01-07 10:55:58 -0500680 isEmergency = state.isEmergency;
681 airplaneMode = state.airplaneMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400682 carrierNetworkChangeMode = state.carrierNetworkChangeMode;
Jason Monkfd57ea72016-04-29 13:37:58 -0400683 userSetup = state.userSetup;
Jason Monk0f0de132016-12-19 15:36:13 -0500684 roaming = state.roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500685 }
686
687 @Override
688 protected void toString(StringBuilder builder) {
689 super.toString(builder);
690 builder.append(',');
691 builder.append("dataSim=").append(dataSim).append(',');
692 builder.append("networkName=").append(networkName).append(',');
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700693 builder.append("networkNameData=").append(networkNameData).append(',');
Jason Monkda68f592015-01-07 10:55:58 -0500694 builder.append("dataConnected=").append(dataConnected).append(',');
Jason Monk0f0de132016-12-19 15:36:13 -0500695 builder.append("roaming=").append(roaming).append(',');
Jason Monk33f8ae72015-05-08 10:45:15 -0400696 builder.append("isDefault=").append(isDefault).append(',');
Jason Monkda68f592015-01-07 10:55:58 -0500697 builder.append("isEmergency=").append(isEmergency).append(',');
Andrew Flynna478d702015-04-14 23:33:45 -0400698 builder.append("airplaneMode=").append(airplaneMode).append(',');
Jason Monkfd57ea72016-04-29 13:37:58 -0400699 builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
700 .append(',');
701 builder.append("userSetup=").append(userSetup);
Jason Monkda68f592015-01-07 10:55:58 -0500702 }
703
704 @Override
705 public boolean equals(Object o) {
706 return super.equals(o)
707 && Objects.equals(((MobileState) o).networkName, networkName)
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700708 && Objects.equals(((MobileState) o).networkNameData, networkNameData)
Jason Monkda68f592015-01-07 10:55:58 -0500709 && ((MobileState) o).dataSim == dataSim
710 && ((MobileState) o).dataConnected == dataConnected
711 && ((MobileState) o).isEmergency == isEmergency
712 && ((MobileState) o).airplaneMode == airplaneMode
Andrew Flynna478d702015-04-14 23:33:45 -0400713 && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
Jason Monkfd57ea72016-04-29 13:37:58 -0400714 && ((MobileState) o).userSetup == userSetup
Jason Monk0f0de132016-12-19 15:36:13 -0500715 && ((MobileState) o).isDefault == isDefault
716 && ((MobileState) o).roaming == roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500717 }
718 }
719}