blob: 34a03bf36c4735fdbe8867b9b35807e136937009 [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;
Jason Monkda68f592015-01-07 10:55:58 -050025import android.telephony.PhoneStateListener;
26import android.telephony.ServiceState;
27import android.telephony.SignalStrength;
28import android.telephony.SubscriptionInfo;
29import android.telephony.SubscriptionManager;
30import android.telephony.TelephonyManager;
Jason Monk93fb68f2015-07-20 11:43:56 -040031import android.text.TextUtils;
Jason Monkda68f592015-01-07 10:55:58 -050032import android.util.Log;
33import android.util.SparseArray;
34
35import com.android.internal.annotations.VisibleForTesting;
Jason Monkda68f592015-01-07 10:55:58 -050036import com.android.internal.telephony.TelephonyIntents;
37import com.android.internal.telephony.cdma.EriInfo;
38import com.android.systemui.R;
Jason Monk48edc0c2017-04-10 15:01:27 -040039import com.android.systemui.statusbar.phone.SignalDrawable;
Jason Monk07b75fe2015-05-14 16:47:03 -040040import com.android.systemui.statusbar.policy.NetworkController.IconState;
Jason Monke06b0652016-03-02 16:35:27 -050041import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
Jason Monkda68f592015-01-07 10:55:58 -050042import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
Jason Monkc6cc6262015-06-11 11:10:15 -040043import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
Jason Monkda68f592015-01-07 10:55:58 -050044
45import java.io.PrintWriter;
Jason Monk33f8ae72015-05-08 10:45:15 -040046import java.util.BitSet;
Jason Monkda68f592015-01-07 10:55:58 -050047import java.util.Objects;
48
49
50public class MobileSignalController extends SignalController<
51 MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
52 private final TelephonyManager mPhone;
Jason Monkc6cc6262015-06-11 11:10:15 -040053 private final SubscriptionDefaults mDefaults;
Jason Monkda68f592015-01-07 10:55:58 -050054 private final String mNetworkNameDefault;
55 private final String mNetworkNameSeparator;
Jason Monk0288de02017-02-23 14:48:05 -050056 private final ContentObserver mObserver;
Jason Monkda68f592015-01-07 10:55:58 -050057 @VisibleForTesting
58 final PhoneStateListener mPhoneStateListener;
59 // Save entire info for logging, we only use the id.
Jason Monk66845a32015-08-03 11:09:41 -040060 final SubscriptionInfo mSubscriptionInfo;
Jason Monkda68f592015-01-07 10:55:58 -050061
62 // @VisibleForDemoMode
63 final SparseArray<MobileIconGroup> mNetworkToIconLookup;
64
65 // Since some pieces of the phone state are interdependent we store it locally,
66 // this could potentially become part of MobileState for simplification/complication
67 // of code.
Jason Monkda68f592015-01-07 10:55:58 -050068 private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
69 private int mDataState = TelephonyManager.DATA_DISCONNECTED;
70 private ServiceState mServiceState;
71 private SignalStrength mSignalStrength;
72 private MobileIconGroup mDefaultIcons;
73 private Config mConfig;
74
75 // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
76 // need listener lists anymore.
77 public MobileSignalController(Context context, Config config, boolean hasMobileData,
Jason Monk07b75fe2015-05-14 16:47:03 -040078 TelephonyManager phone, CallbackHandler callbackHandler,
Jason Monkc6cc6262015-06-11 11:10:15 -040079 NetworkControllerImpl networkController, SubscriptionInfo info,
80 SubscriptionDefaults defaults, Looper receiverLooper) {
Jason Monkda68f592015-01-07 10:55:58 -050081 super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
Jason Monk07b75fe2015-05-14 16:47:03 -040082 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
Jason Monkda68f592015-01-07 10:55:58 -050083 networkController);
84 mNetworkToIconLookup = new SparseArray<>();
85 mConfig = config;
86 mPhone = phone;
Jason Monkc6cc6262015-06-11 11:10:15 -040087 mDefaults = defaults;
Jason Monkda68f592015-01-07 10:55:58 -050088 mSubscriptionInfo = info;
Jason Monk07b75fe2015-05-14 16:47:03 -040089 mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(),
90 receiverLooper);
Jason Monkda68f592015-01-07 10:55:58 -050091 mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
92 mNetworkNameDefault = getStringIfExists(
93 com.android.internal.R.string.lockscreen_carrier_default);
94
95 mapIconSets();
96
Jason Monk00aa9d42015-08-10 10:12:02 -040097 String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
98 : mNetworkNameDefault;
99 mLastState.networkName = mCurrentState.networkName = networkName;
100 mLastState.networkNameData = mCurrentState.networkNameData = networkName;
Jason Monkda68f592015-01-07 10:55:58 -0500101 mLastState.enabled = mCurrentState.enabled = hasMobileData;
102 mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
103 // Get initial data sim state.
104 updateDataSim();
Jason Monk0288de02017-02-23 14:48:05 -0500105 mObserver = new ContentObserver(new Handler(receiverLooper)) {
106 @Override
107 public void onChange(boolean selfChange) {
108 updateTelephony();
109 }
110 };
Jason Monkda68f592015-01-07 10:55:58 -0500111 }
112
113 public void setConfiguration(Config config) {
114 mConfig = config;
115 mapIconSets();
116 updateTelephony();
117 }
118
Jason Monkda68f592015-01-07 10:55:58 -0500119 public int getDataContentDescription() {
120 return getIcons().mDataContentDescription;
121 }
122
Jason Monkda68f592015-01-07 10:55:58 -0500123 public void setAirplaneMode(boolean airplaneMode) {
124 mCurrentState.airplaneMode = airplaneMode;
125 notifyListenersIfNecessary();
126 }
127
Jason Monkfd57ea72016-04-29 13:37:58 -0400128 public void setUserSetupComplete(boolean userSetup) {
129 mCurrentState.userSetup = userSetup;
130 notifyListenersIfNecessary();
131 }
132
Jason Monk33f8ae72015-05-08 10:45:15 -0400133 @Override
134 public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
135 boolean isValidated = validatedTransports.get(mTransportType);
136 mCurrentState.isDefault = connectedTransports.get(mTransportType);
137 // Only show this as not having connectivity if we are default.
138 mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0;
139 notifyListenersIfNecessary();
Jason Monkda68f592015-01-07 10:55:58 -0500140 }
141
Andrew Flynna478d702015-04-14 23:33:45 -0400142 public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) {
143 mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode;
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400144 updateTelephony();
Andrew Flynna478d702015-04-14 23:33:45 -0400145 }
146
Jason Monkda68f592015-01-07 10:55:58 -0500147 /**
148 * Start listening for phone state changes.
149 */
150 public void registerListener() {
151 mPhone.listen(mPhoneStateListener,
152 PhoneStateListener.LISTEN_SERVICE_STATE
153 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
154 | PhoneStateListener.LISTEN_CALL_STATE
155 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
Andrew Flynna478d702015-04-14 23:33:45 -0400156 | PhoneStateListener.LISTEN_DATA_ACTIVITY
157 | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
Jason Monk0288de02017-02-23 14:48:05 -0500158 mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
159 true, mObserver);
160 mContext.getContentResolver().registerContentObserver(Global.getUriFor(
161 Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()),
162 true, mObserver);
Jason Monkda68f592015-01-07 10:55:58 -0500163 }
164
165 /**
166 * Stop listening for phone state changes.
167 */
168 public void unregisterListener() {
169 mPhone.listen(mPhoneStateListener, 0);
Jason Monk0288de02017-02-23 14:48:05 -0500170 mContext.getContentResolver().unregisterContentObserver(mObserver);
Jason Monkda68f592015-01-07 10:55:58 -0500171 }
172
173 /**
174 * Produce a mapping of data network types to icon groups for simple and quick use in
175 * updateTelephony.
176 */
177 private void mapIconSets() {
178 mNetworkToIconLookup.clear();
179
180 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
181 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
182 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
183 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
184 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
185
186 if (!mConfig.showAtLeast3G) {
187 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
188 TelephonyIcons.UNKNOWN);
189 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
190 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
191 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
192
193 mDefaultIcons = TelephonyIcons.G;
194 } else {
195 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
196 TelephonyIcons.THREE_G);
197 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
198 TelephonyIcons.THREE_G);
199 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
200 TelephonyIcons.THREE_G);
201 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
202 TelephonyIcons.THREE_G);
203 mDefaultIcons = TelephonyIcons.THREE_G;
204 }
205
206 MobileIconGroup hGroup = TelephonyIcons.THREE_G;
207 if (mConfig.hspaDataDistinguishable) {
208 hGroup = TelephonyIcons.H;
209 }
210 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
211 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
212 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
213 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
214
215 if (mConfig.show4gForLte) {
216 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700217 if (mConfig.hideLtePlus) {
218 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
219 TelephonyIcons.FOUR_G);
220 } else {
221 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
222 TelephonyIcons.FOUR_G_PLUS);
223 }
Jason Monkda68f592015-01-07 10:55:58 -0500224 } else {
225 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700226 if (mConfig.hideLtePlus) {
227 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
228 TelephonyIcons.LTE);
229 } else {
230 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
231 TelephonyIcons.LTE_PLUS);
232 }
Jason Monkda68f592015-01-07 10:55:58 -0500233 }
Jason Monk7150d7f2015-07-09 10:14:12 -0400234 mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
Jason Monkda68f592015-01-07 10:55:58 -0500235 }
236
Jason Monk48edc0c2017-04-10 15:01:27 -0400237 private int getNumLevels() {
Jason Monk43c14d12017-06-22 11:20:04 -0400238 if (mConfig.inflateSignalStrengths) {
239 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1;
240 }
Jason Monk48edc0c2017-04-10 15:01:27 -0400241 return SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
242 }
243
244 @Override
245 public int getCurrentIconId() {
246 if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {
247 return SignalDrawable.getCarrierChangeState(getNumLevels());
248 } else if (mCurrentState.connected) {
Jason Monk43c14d12017-06-22 11:20:04 -0400249 int level = mCurrentState.level;
250 if (mConfig.inflateSignalStrengths) {
251 level++;
252 }
253 return SignalDrawable.getState(level, getNumLevels(),
Jason Monk7e6c83c2017-04-26 14:35:24 -0400254 mCurrentState.inetCondition == 0);
Jason Monk48edc0c2017-04-10 15:01:27 -0400255 } else if (mCurrentState.enabled) {
256 return SignalDrawable.getEmptyState(getNumLevels());
257 } else {
258 return 0;
259 }
260 }
261
262 @Override
Jason Monk01df36f2017-06-07 13:02:47 -0400263 public int getQsCurrentIconId() {
Evan Laird3d1aad62017-06-20 16:10:44 -0400264 if (mCurrentState.airplaneMode) {
265 return SignalDrawable.getAirplaneModeState(getNumLevels());
266 }
267
Jason Monk01df36f2017-06-07 13:02:47 -0400268 return getCurrentIconId();
269 }
270
271 @Override
Jason Monke06b0652016-03-02 16:35:27 -0500272 public void notifyListeners(SignalCallback callback) {
Jason Monkda68f592015-01-07 10:55:58 -0500273 MobileIconGroup icons = getIcons();
274
275 String contentDescription = getStringIfExists(getContentDescription());
276 String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
Jason Monk7e6c83c2017-04-26 14:35:24 -0400277 final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
Jason Monkfd57ea72016-04-29 13:37:58 -0400278 && mCurrentState.userSetup;
Jeff Davidson5c7daaf2015-01-27 16:24:32 -0800279
Jason Monk0f0de132016-12-19 15:36:13 -0500280 // Show icon in QS when we are connected or data is disabled.
Jason Monk7e6c83c2017-04-26 14:35:24 -0400281 boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
Jason Monk07b75fe2015-05-14 16:47:03 -0400282 IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
283 getCurrentIconId(), contentDescription);
284
Jason Monk7e6c83c2017-04-26 14:35:24 -0400285 int qsTypeIcon = 0;
286 IconState qsIcon = null;
287 String description = null;
288 // Only send data sim callbacks to QS.
289 if (mCurrentState.dataSim) {
Jason Monk01df36f2017-06-07 13:02:47 -0400290 qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
Jason Monk7e6c83c2017-04-26 14:35:24 -0400291 qsIcon = new IconState(mCurrentState.enabled
Jason Monk01df36f2017-06-07 13:02:47 -0400292 && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
Jason Monk7e6c83c2017-04-26 14:35:24 -0400293 description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
294 }
Jason Monk07b75fe2015-05-14 16:47:03 -0400295 boolean activityIn = mCurrentState.dataConnected
Jason Monk0288de02017-02-23 14:48:05 -0500296 && !mCurrentState.carrierNetworkChangeMode
297 && mCurrentState.activityIn;
Jason Monk07b75fe2015-05-14 16:47:03 -0400298 boolean activityOut = mCurrentState.dataConnected
Jason Monk0288de02017-02-23 14:48:05 -0500299 && !mCurrentState.carrierNetworkChangeMode
300 && mCurrentState.activityOut;
Jason Monk0f0de132016-12-19 15:36:13 -0500301 showDataIcon &= mCurrentState.isDefault || dataDisabled;
Jason Monkda68f592015-01-07 10:55:58 -0500302 int typeIcon = showDataIcon ? icons.mDataType : 0;
Jason Monk7e6c83c2017-04-26 14:35:24 -0400303 callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
304 activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
305 mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
Andrew Flynna478d702015-04-14 23:33:45 -0400306 }
307
Jason Monkda68f592015-01-07 10:55:58 -0500308 @Override
309 protected MobileState cleanState() {
310 return new MobileState();
311 }
312
313 private boolean hasService() {
314 if (mServiceState != null) {
315 // Consider the device to be in service if either voice or data
316 // service is available. Some SIM cards are marketed as data-only
317 // and do not support voice service, and on these SIM cards, we
318 // want to show signal bars for data service as well as the "no
319 // service" or "emergency calls only" text that indicates that voice
320 // is not available.
321 switch (mServiceState.getVoiceRegState()) {
322 case ServiceState.STATE_POWER_OFF:
323 return false;
324 case ServiceState.STATE_OUT_OF_SERVICE:
325 case ServiceState.STATE_EMERGENCY_ONLY:
326 return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
327 default:
328 return true;
329 }
330 } else {
331 return false;
332 }
333 }
334
335 private boolean isCdma() {
336 return (mSignalStrength != null) && !mSignalStrength.isGsm();
337 }
338
339 public boolean isEmergencyOnly() {
340 return (mServiceState != null && mServiceState.isEmergencyOnly());
341 }
342
343 private boolean isRoaming() {
Shishir Agrawal7ef5b882017-06-26 12:06:03 -0700344 // During a carrier change, roaming indications need to be supressed.
345 if (isCarrierNetworkChangeActive()) {
346 return false;
347 }
Jason Monke1531982017-09-05 11:20:30 -0400348 if (isCdma() && mServiceState != null) {
Jason Monkda68f592015-01-07 10:55:58 -0500349 final int iconMode = mServiceState.getCdmaEriIconMode();
350 return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
351 && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
Jason Monk0288de02017-02-23 14:48:05 -0500352 || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
Jason Monkda68f592015-01-07 10:55:58 -0500353 } else {
354 return mServiceState != null && mServiceState.getRoaming();
355 }
356 }
357
Andrew Flynna478d702015-04-14 23:33:45 -0400358 private boolean isCarrierNetworkChangeActive() {
Andrew Flynn55fc8002015-05-29 08:33:46 -0400359 return mCurrentState.carrierNetworkChangeMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400360 }
361
Jason Monkda68f592015-01-07 10:55:58 -0500362 public void handleBroadcast(Intent intent) {
363 String action = intent.getAction();
364 if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
365 updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
366 intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700367 intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN),
Jason Monkda68f592015-01-07 10:55:58 -0500368 intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
369 intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
370 notifyListenersIfNecessary();
371 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
372 updateDataSim();
Jason Monk8fcab352015-06-29 10:57:00 -0400373 notifyListenersIfNecessary();
Jason Monkda68f592015-01-07 10:55:58 -0500374 }
375 }
376
377 private void updateDataSim() {
Jason Monkc6cc6262015-06-11 11:10:15 -0400378 int defaultDataSub = mDefaults.getDefaultDataSubId();
Jason Monkda68f592015-01-07 10:55:58 -0500379 if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
380 mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
381 } else {
382 // There doesn't seem to be a data sim selected, however if
383 // there isn't a MobileSignalController with dataSim set, then
384 // QS won't get any callbacks and will be blank. Instead
385 // lets just assume we are the data sim (which will basically
386 // show one at random) in QS until one is selected. The user
387 // should pick one soon after, so we shouldn't be in this state
388 // for long.
389 mCurrentState.dataSim = true;
390 }
Jason Monkda68f592015-01-07 10:55:58 -0500391 }
392
393 /**
394 * Updates the network's name based on incoming spn and plmn.
395 */
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700396 void updateNetworkName(boolean showSpn, String spn, String dataSpn,
397 boolean showPlmn, String plmn) {
Jason Monkda68f592015-01-07 10:55:58 -0500398 if (CHATTY) {
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700399 Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn
400 + " spn=" + spn + " dataSpn=" + dataSpn
Jason Monkda68f592015-01-07 10:55:58 -0500401 + " showPlmn=" + showPlmn + " plmn=" + plmn);
402 }
403 StringBuilder str = new StringBuilder();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700404 StringBuilder strData = new StringBuilder();
Jason Monkda68f592015-01-07 10:55:58 -0500405 if (showPlmn && plmn != null) {
406 str.append(plmn);
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700407 strData.append(plmn);
Jason Monkda68f592015-01-07 10:55:58 -0500408 }
409 if (showSpn && spn != null) {
410 if (str.length() != 0) {
411 str.append(mNetworkNameSeparator);
412 }
413 str.append(spn);
414 }
415 if (str.length() != 0) {
416 mCurrentState.networkName = str.toString();
417 } else {
418 mCurrentState.networkName = mNetworkNameDefault;
419 }
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700420 if (showSpn && dataSpn != null) {
421 if (strData.length() != 0) {
422 strData.append(mNetworkNameSeparator);
423 }
424 strData.append(dataSpn);
425 }
426 if (strData.length() != 0) {
427 mCurrentState.networkNameData = strData.toString();
428 } else {
429 mCurrentState.networkNameData = mNetworkNameDefault;
430 }
Jason Monkda68f592015-01-07 10:55:58 -0500431 }
432
433 /**
434 * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
435 * mDataState, and mSimState. It should be called any time one of these is updated.
436 * This will call listeners if necessary.
437 */
438 private final void updateTelephony() {
439 if (DEBUG) {
440 Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
441 + " ss=" + mSignalStrength);
442 }
443 mCurrentState.connected = hasService() && mSignalStrength != null;
444 if (mCurrentState.connected) {
445 if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
446 mCurrentState.level = mSignalStrength.getCdmaLevel();
447 } else {
448 mCurrentState.level = mSignalStrength.getLevel();
449 }
450 }
451 if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
452 mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
453 } else {
454 mCurrentState.iconGroup = mDefaultIcons;
455 }
456 mCurrentState.dataConnected = mCurrentState.connected
Jason Monk7e6c83c2017-04-26 14:35:24 -0400457 && mDataState == TelephonyManager.DATA_CONNECTED;
Jason Monkda68f592015-01-07 10:55:58 -0500458
Jason Monk0f0de132016-12-19 15:36:13 -0500459 mCurrentState.roaming = isRoaming();
Andrew Flynna478d702015-04-14 23:33:45 -0400460 if (isCarrierNetworkChangeActive()) {
461 mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
Jason Monk7e6c83c2017-04-26 14:35:24 -0400462 } else if (isDataDisabled()) {
463 mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
Jason Monkda68f592015-01-07 10:55:58 -0500464 }
465 if (isEmergencyOnly() != mCurrentState.isEmergency) {
466 mCurrentState.isEmergency = isEmergencyOnly();
467 mNetworkController.recalculateEmergency();
468 }
469 // Fill in the network name if we think we have it.
470 if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
Jason Monk93fb68f2015-07-20 11:43:56 -0400471 && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
Jason Monkda68f592015-01-07 10:55:58 -0500472 mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
473 }
Andrew Flynna478d702015-04-14 23:33:45 -0400474
Jason Monkda68f592015-01-07 10:55:58 -0500475 notifyListenersIfNecessary();
476 }
477
Jason Monk1a95c862016-01-27 15:18:41 -0500478 private boolean isDataDisabled() {
479 return !mPhone.getDataEnabled(mSubscriptionInfo.getSubscriptionId());
480 }
481
Jason Monkda68f592015-01-07 10:55:58 -0500482 @VisibleForTesting
483 void setActivity(int activity) {
484 mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
485 || activity == TelephonyManager.DATA_ACTIVITY_IN;
486 mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
487 || activity == TelephonyManager.DATA_ACTIVITY_OUT;
488 notifyListenersIfNecessary();
489 }
490
491 @Override
492 public void dump(PrintWriter pw) {
493 super.dump(pw);
494 pw.println(" mSubscription=" + mSubscriptionInfo + ",");
495 pw.println(" mServiceState=" + mServiceState + ",");
496 pw.println(" mSignalStrength=" + mSignalStrength + ",");
497 pw.println(" mDataState=" + mDataState + ",");
498 pw.println(" mDataNetType=" + mDataNetType + ",");
499 }
500
501 class MobilePhoneStateListener extends PhoneStateListener {
Jason Monk07b75fe2015-05-14 16:47:03 -0400502 public MobilePhoneStateListener(int subId, Looper looper) {
503 super(subId, looper);
Jason Monkda68f592015-01-07 10:55:58 -0500504 }
505
506 @Override
507 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
508 if (DEBUG) {
509 Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
510 ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
511 }
512 mSignalStrength = signalStrength;
513 updateTelephony();
514 }
515
516 @Override
517 public void onServiceStateChanged(ServiceState state) {
518 if (DEBUG) {
519 Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
520 + " dataState=" + state.getDataRegState());
521 }
522 mServiceState = state;
Jason Monke1531982017-09-05 11:20:30 -0400523 if (state != null) {
524 mDataNetType = state.getDataNetworkType();
525 if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
526 mServiceState.isUsingCarrierAggregation()) {
527 mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
528 }
Robert Greenwaltea0d71392016-07-28 18:50:10 -0700529 }
Jason Monkda68f592015-01-07 10:55:58 -0500530 updateTelephony();
531 }
532
533 @Override
534 public void onDataConnectionStateChanged(int state, int networkType) {
535 if (DEBUG) {
536 Log.d(mTag, "onDataConnectionStateChanged: state=" + state
537 + " type=" + networkType);
538 }
539 mDataState = state;
540 mDataNetType = networkType;
Robert Greenwaltea0d71392016-07-28 18:50:10 -0700541 if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
542 mServiceState.isUsingCarrierAggregation()) {
543 mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
544 }
Jason Monkda68f592015-01-07 10:55:58 -0500545 updateTelephony();
546 }
547
548 @Override
549 public void onDataActivity(int direction) {
550 if (DEBUG) {
551 Log.d(mTag, "onDataActivity: direction=" + direction);
552 }
553 setActivity(direction);
554 }
Andrew Flynna478d702015-04-14 23:33:45 -0400555
556 @Override
557 public void onCarrierNetworkChange(boolean active) {
558 if (DEBUG) {
559 Log.d(mTag, "onCarrierNetworkChange: active=" + active);
560 }
561 mCurrentState.carrierNetworkChangeMode = active;
562
563 updateTelephony();
564 }
Jason Monkda68f592015-01-07 10:55:58 -0500565 };
566
567 static class MobileIconGroup extends SignalController.IconGroup {
568 final int mDataContentDescription; // mContentDescriptionDataType
569 final int mDataType;
570 final boolean mIsWide;
Jason Monk33f8ae72015-05-08 10:45:15 -0400571 final int mQsDataType;
Jason Monkda68f592015-01-07 10:55:58 -0500572
573 public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
574 int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
575 int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
Jason Monk33f8ae72015-05-08 10:45:15 -0400576 int qsDataType) {
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400577 super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
578 qsDiscState, discContentDesc);
Jason Monkda68f592015-01-07 10:55:58 -0500579 mDataContentDescription = dataContentDesc;
580 mDataType = dataType;
581 mIsWide = isWide;
582 mQsDataType = qsDataType;
583 }
584 }
585
586 static class MobileState extends SignalController.State {
587 String networkName;
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700588 String networkNameData;
Jason Monkda68f592015-01-07 10:55:58 -0500589 boolean dataSim;
590 boolean dataConnected;
591 boolean isEmergency;
592 boolean airplaneMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400593 boolean carrierNetworkChangeMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400594 boolean isDefault;
Jason Monkfd57ea72016-04-29 13:37:58 -0400595 boolean userSetup;
Jason Monk0f0de132016-12-19 15:36:13 -0500596 boolean roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500597
598 @Override
599 public void copyFrom(State s) {
600 super.copyFrom(s);
601 MobileState state = (MobileState) s;
602 dataSim = state.dataSim;
603 networkName = state.networkName;
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700604 networkNameData = state.networkNameData;
Jason Monkda68f592015-01-07 10:55:58 -0500605 dataConnected = state.dataConnected;
Jason Monk33f8ae72015-05-08 10:45:15 -0400606 isDefault = state.isDefault;
Jason Monkda68f592015-01-07 10:55:58 -0500607 isEmergency = state.isEmergency;
608 airplaneMode = state.airplaneMode;
Andrew Flynna478d702015-04-14 23:33:45 -0400609 carrierNetworkChangeMode = state.carrierNetworkChangeMode;
Jason Monkfd57ea72016-04-29 13:37:58 -0400610 userSetup = state.userSetup;
Jason Monk0f0de132016-12-19 15:36:13 -0500611 roaming = state.roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500612 }
613
614 @Override
615 protected void toString(StringBuilder builder) {
616 super.toString(builder);
617 builder.append(',');
618 builder.append("dataSim=").append(dataSim).append(',');
619 builder.append("networkName=").append(networkName).append(',');
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700620 builder.append("networkNameData=").append(networkNameData).append(',');
Jason Monkda68f592015-01-07 10:55:58 -0500621 builder.append("dataConnected=").append(dataConnected).append(',');
Jason Monk0f0de132016-12-19 15:36:13 -0500622 builder.append("roaming=").append(roaming).append(',');
Jason Monk33f8ae72015-05-08 10:45:15 -0400623 builder.append("isDefault=").append(isDefault).append(',');
Jason Monkda68f592015-01-07 10:55:58 -0500624 builder.append("isEmergency=").append(isEmergency).append(',');
Andrew Flynna478d702015-04-14 23:33:45 -0400625 builder.append("airplaneMode=").append(airplaneMode).append(',');
Jason Monkfd57ea72016-04-29 13:37:58 -0400626 builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
627 .append(',');
628 builder.append("userSetup=").append(userSetup);
Jason Monkda68f592015-01-07 10:55:58 -0500629 }
630
631 @Override
632 public boolean equals(Object o) {
633 return super.equals(o)
634 && Objects.equals(((MobileState) o).networkName, networkName)
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700635 && Objects.equals(((MobileState) o).networkNameData, networkNameData)
Jason Monkda68f592015-01-07 10:55:58 -0500636 && ((MobileState) o).dataSim == dataSim
637 && ((MobileState) o).dataConnected == dataConnected
638 && ((MobileState) o).isEmergency == isEmergency
639 && ((MobileState) o).airplaneMode == airplaneMode
Andrew Flynna478d702015-04-14 23:33:45 -0400640 && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
Jason Monkfd57ea72016-04-29 13:37:58 -0400641 && ((MobileState) o).userSetup == userSetup
Jason Monk0f0de132016-12-19 15:36:13 -0500642 && ((MobileState) o).isDefault == isDefault
643 && ((MobileState) o).roaming == roaming;
Jason Monkda68f592015-01-07 10:55:58 -0500644 }
645 }
646}