blob: 7a09455017dd979ac1e41e588afdb9a38b9b5b59 [file] [log] [blame]
John Spurlockaf8d6c42014-05-07 17:49:08 -04001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar.policy;
18
Roshan Pius80fb1372018-07-16 15:43:03 -070019import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
20import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN;
21import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
22import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
23import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
Malcolm Chen50ba9632019-02-26 16:49:56 -080024import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
Roshan Pius80fb1372018-07-16 15:43:03 -070025
Malcolm Chen50ba9632019-02-26 16:49:56 -080026import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
Jason Monk196d6392018-12-20 13:25:34 -050027import static com.android.systemui.Dependency.BG_LOOPER_NAME;
28
John Spurlockaf8d6c42014-05-07 17:49:08 -040029import android.content.BroadcastReceiver;
30import android.content.Context;
31import android.content.Intent;
32import android.content.IntentFilter;
Jason Monk9c7844c2017-01-18 15:21:53 -050033import android.content.res.Configuration;
John Spurlockaf8d6c42014-05-07 17:49:08 -040034import android.content.res.Resources;
35import android.net.ConnectivityManager;
Anarghya Mitra678722f2018-05-11 14:29:54 -070036import android.net.Network;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090037import android.net.NetworkCapabilities;
John Spurlockaf8d6c42014-05-07 17:49:08 -040038import android.net.wifi.WifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040039import android.os.AsyncTask;
40import android.os.Bundle;
Jason Monk07b75fe2015-05-14 16:47:03 -040041import android.os.Handler;
Jason Monk30d80042015-05-08 16:54:18 -040042import android.os.Looper;
Wenting Xiong63364fe2017-02-07 19:12:27 +080043import android.os.PersistableBundle;
John Spurlockaf8d6c42014-05-07 17:49:08 -040044import android.provider.Settings;
Wenting Xiong63364fe2017-02-07 19:12:27 +080045import android.telephony.CarrierConfigManager;
Malcolm Chen50ba9632019-02-26 16:49:56 -080046import android.telephony.PhoneStateListener;
Jason Monkb0808aa2015-07-22 16:34:36 -040047import android.telephony.ServiceState;
Jason Monk48edc0c2017-04-10 15:01:27 -040048import android.telephony.SignalStrength;
Jason Monkb5746272014-11-12 16:50:31 -050049import android.telephony.SubscriptionInfo;
50import android.telephony.SubscriptionManager;
51import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
John Spurlockaf8d6c42014-05-07 17:49:08 -040052import android.telephony.TelephonyManager;
Jason Monkb5746272014-11-12 16:50:31 -050053import android.text.TextUtils;
Bill Lin767c0db2019-08-15 20:42:06 +080054import android.text.format.DateUtils;
John Spurlockaf8d6c42014-05-07 17:49:08 -040055import android.util.Log;
John Spurlockcf053c12015-05-14 16:33:59 -040056import android.util.MathUtils;
Jason Monk8996b942017-03-02 13:58:19 -050057import android.util.SparseArray;
Winsonc0d70582016-01-29 10:24:39 -080058
Evan Laird470ae842019-04-09 16:24:27 -040059import com.android.internal.annotations.GuardedBy;
Jason Monke0cdb602014-11-05 12:39:45 -050060import com.android.internal.annotations.VisibleForTesting;
Jason Monkb5746272014-11-12 16:50:31 -050061import com.android.internal.telephony.PhoneConstants;
John Spurlockaf8d6c42014-05-07 17:49:08 -040062import com.android.internal.telephony.TelephonyIntents;
Jason Monkf668d7c2016-01-14 10:38:41 -050063import com.android.settingslib.net.DataUsageController;
Jason Monk9c7844c2017-01-18 15:21:53 -050064import com.android.systemui.ConfigurationChangedReceiver;
John Spurlockaf8d6c42014-05-07 17:49:08 -040065import com.android.systemui.DemoMode;
Jason Monk9c7844c2017-01-18 15:21:53 -050066import com.android.systemui.Dumpable;
John Spurlockaf8d6c42014-05-07 17:49:08 -040067import com.android.systemui.R;
Jason Monk9c7844c2017-01-18 15:21:53 -050068import com.android.systemui.settings.CurrentUserTracker;
69import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
Pengquan Menga62d32b2018-12-06 17:38:38 -080070import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
John Spurlockaf8d6c42014-05-07 17:49:08 -040071
72import java.io.FileDescriptor;
73import java.io.PrintWriter;
74import java.util.ArrayList;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090075import java.util.BitSet;
Jason Monkb5746272014-11-12 16:50:31 -050076import java.util.Collections;
77import java.util.Comparator;
Pengquan Menga62d32b2018-12-06 17:38:38 -080078import java.util.HashMap;
John Spurlockaf8d6c42014-05-07 17:49:08 -040079import java.util.List;
80import java.util.Locale;
Pengquan Menga62d32b2018-12-06 17:38:38 -080081import java.util.Map;
John Spurlockaf8d6c42014-05-07 17:49:08 -040082
Jason Monk196d6392018-12-20 13:25:34 -050083import javax.inject.Inject;
84import javax.inject.Named;
85import javax.inject.Singleton;
86
John Spurlockaf8d6c42014-05-07 17:49:08 -040087/** Platform implementation of the network controller. **/
Jason Monk196d6392018-12-20 13:25:34 -050088@Singleton
John Spurlockaf8d6c42014-05-07 17:49:08 -040089public class NetworkControllerImpl extends BroadcastReceiver
Jason Monk9c7844c2017-01-18 15:21:53 -050090 implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider,
91 ConfigurationChangedReceiver, Dumpable {
John Spurlockaf8d6c42014-05-07 17:49:08 -040092 // debug
Jason Monkd2263cd2014-11-10 14:22:56 -050093 static final String TAG = "NetworkController";
94 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
95 // additional diagnostics, but not logspew
Jason Monk07b75fe2015-05-14 16:47:03 -040096 static final boolean CHATTY = Log.isLoggable(TAG + "Chat", Log.DEBUG);
John Spurlockaf8d6c42014-05-07 17:49:08 -040097
Jason Monk66845a32015-08-03 11:09:41 -040098 private static final int EMERGENCY_NO_CONTROLLERS = 0;
99 private static final int EMERGENCY_FIRST_CONTROLLER = 100;
100 private static final int EMERGENCY_VOICE_CONTROLLER = 200;
101 private static final int EMERGENCY_NO_SUB = 300;
Jason Monk8996b942017-03-02 13:58:19 -0500102 private static final int EMERGENCY_ASSUMED_VOICE_CONTROLLER = 400;
Jason Monk66845a32015-08-03 11:09:41 -0400103
Jason Monkd2263cd2014-11-10 14:22:56 -0500104 private final Context mContext;
105 private final TelephonyManager mPhone;
106 private final WifiManager mWifiManager;
107 private final ConnectivityManager mConnectivityManager;
Jason Monkb5746272014-11-12 16:50:31 -0500108 private final SubscriptionManager mSubscriptionManager;
Jason Monkd2263cd2014-11-10 14:22:56 -0500109 private final boolean mHasMobileDataFeature;
Jason Monkc6cc6262015-06-11 11:10:15 -0400110 private final SubscriptionDefaults mSubDefaults;
Jason Monk9a4ce132016-01-21 15:27:17 -0500111 private final DataSaverController mDataSaverController;
Jason Monk9c7844c2017-01-18 15:21:53 -0500112 private final CurrentUserTracker mUserTracker;
Evan Laird470ae842019-04-09 16:24:27 -0400113 private final Object mLock = new Object();
Jason Monk3aaabd72014-12-12 11:11:44 -0500114 private Config mConfig;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400115
Evan Laird470ae842019-04-09 16:24:27 -0400116 private PhoneStateListener mPhoneStateListener;
Malcolm Chen50ba9632019-02-26 16:49:56 -0800117 private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
118
Jason Monkd2263cd2014-11-10 14:22:56 -0500119 // Subcontrollers.
120 @VisibleForTesting
121 final WifiSignalController mWifiSignalController;
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900122
123 @VisibleForTesting
124 final EthernetSignalController mEthernetSignalController;
125
Jason Monkd2263cd2014-11-10 14:22:56 -0500126 @VisibleForTesting
Jason Monk8996b942017-03-02 13:58:19 -0500127 final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>();
Jason Monkb5746272014-11-12 16:50:31 -0500128 // When no SIMs are around at setup, and one is added later, it seems to default to the first
129 // SIM for most actions. This may be null if there aren't any SIMs around.
130 private MobileSignalController mDefaultSignalController;
Jason Monk0e2400f2014-11-21 11:08:55 -0500131 private final AccessPointControllerImpl mAccessPoints;
Jason Monkf668d7c2016-01-14 10:38:41 -0500132 private final DataUsageController mDataUsageController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400133
Jason Monkd2263cd2014-11-10 14:22:56 -0500134 private boolean mInetCondition; // Used for Logging and demo.
Lorenzo Colitti23dd1762014-09-10 22:58:54 +0900135
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900136 // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are
137 // connected and validated, respectively.
138 private final BitSet mConnectedTransports = new BitSet();
139 private final BitSet mValidatedTransports = new BitSet();
140
Jason Monkd2263cd2014-11-10 14:22:56 -0500141 // States that don't belong to a subcontroller.
John Spurlockaf8d6c42014-05-07 17:49:08 -0400142 private boolean mAirplaneMode = false;
Jason Monk1ff77662017-09-29 11:17:05 -0400143 private boolean mHasNoSubs;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400144 private Locale mLocale = null;
Jason Monkb5746272014-11-12 16:50:31 -0500145 // This list holds our ordering.
John Spurlockcf053c12015-05-14 16:33:59 -0400146 private List<SubscriptionInfo> mCurrentSubscriptions = new ArrayList<>();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400147
Jason Monkc014dec2014-12-12 11:49:55 -0500148 @VisibleForTesting
149 boolean mListening;
John Spurlock7f8f22a2014-07-02 18:54:17 -0400150
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900151 // The current user ID.
152 private int mCurrentUserId;
153
Jason Monk8fcab352015-06-29 10:57:00 -0400154 private OnSubscriptionsChangedListener mSubscriptionListener;
155
Jason Monk07b75fe2015-05-14 16:47:03 -0400156 // Handler that all broadcasts are received on.
157 private final Handler mReceiverHandler;
158 // Handler that all callbacks are made on.
159 private final CallbackHandler mCallbackHandler;
160
Jason Monk66845a32015-08-03 11:09:41 -0400161 private int mEmergencySource;
162 private boolean mIsEmergency;
163
Jason Monkb0808aa2015-07-22 16:34:36 -0400164 @VisibleForTesting
165 ServiceState mLastServiceState;
Jason Monkfd57ea72016-04-29 13:37:58 -0400166 private boolean mUserSetup;
Jason Monk1ff77662017-09-29 11:17:05 -0400167 private boolean mSimDetected;
Jason Monkb0808aa2015-07-22 16:34:36 -0400168
John Spurlockaf8d6c42014-05-07 17:49:08 -0400169 /**
170 * Construct this controller object and register for updates.
171 */
Jason Monk196d6392018-12-20 13:25:34 -0500172 @Inject
173 public NetworkControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
Jason Monk9c7844c2017-01-18 15:21:53 -0500174 DeviceProvisionedController deviceProvisionedController) {
Jason Monkf13b4b32014-11-07 16:39:34 -0500175 this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
176 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
Jason Monk29f7a7b2014-11-17 14:40:56 -0500177 (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
Sundeep Ghuman9d10a3c2017-06-16 00:05:16 +0000178 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400179 new CallbackHandler(),
Tony Mantler0edf09b2017-09-28 15:03:37 -0700180 new AccessPointControllerImpl(context),
Jason Monkf668d7c2016-01-14 10:38:41 -0500181 new DataUsageController(context),
Jason Monk9c7844c2017-01-18 15:21:53 -0500182 new SubscriptionDefaults(),
183 deviceProvisionedController);
Jason Monk07b75fe2015-05-14 16:47:03 -0400184 mReceiverHandler.post(mRegisterListeners);
Jason Monkf13b4b32014-11-07 16:39:34 -0500185 }
186
187 @VisibleForTesting
188 NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
Sundeep Ghuman9d10a3c2017-06-16 00:05:16 +0000189 TelephonyManager telephonyManager, WifiManager wifiManager,
190 SubscriptionManager subManager, Config config, Looper bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400191 CallbackHandler callbackHandler,
Jason Monkd2263cd2014-11-10 14:22:56 -0500192 AccessPointControllerImpl accessPointController,
Jason Monkf668d7c2016-01-14 10:38:41 -0500193 DataUsageController dataUsageController,
Jason Monk9c7844c2017-01-18 15:21:53 -0500194 SubscriptionDefaults defaultsHandler,
195 DeviceProvisionedController deviceProvisionedController) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400196 mContext = context;
Jason Monkb5746272014-11-12 16:50:31 -0500197 mConfig = config;
Jason Monk07b75fe2015-05-14 16:47:03 -0400198 mReceiverHandler = new Handler(bgLooper);
199 mCallbackHandler = callbackHandler;
Jason Monk9abca5e2016-11-11 16:18:14 -0500200 mDataSaverController = new DataSaverControllerImpl(context);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400201
Jason Monkb5746272014-11-12 16:50:31 -0500202 mSubscriptionManager = subManager;
Jason Monkc6cc6262015-06-11 11:10:15 -0400203 mSubDefaults = defaultsHandler;
Jason Monkf13b4b32014-11-07 16:39:34 -0500204 mConnectivityManager = connectivityManager;
205 mHasMobileDataFeature =
206 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400207
John Spurlockaf8d6c42014-05-07 17:49:08 -0400208 // telephony
Jason Monk07b75fe2015-05-14 16:47:03 -0400209 mPhone = telephonyManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400210
211 // wifi
Jason Monkf13b4b32014-11-07 16:39:34 -0500212 mWifiManager = wifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400213
Jason Monkd2263cd2014-11-10 14:22:56 -0500214 mLocale = mContext.getResources().getConfiguration().locale;
Jason Monk29f7a7b2014-11-17 14:40:56 -0500215 mAccessPoints = accessPointController;
Jason Monkf668d7c2016-01-14 10:38:41 -0500216 mDataUsageController = dataUsageController;
217 mDataUsageController.setNetworkController(this);
218 // TODO: Find a way to move this into DataUsageController.
219 mDataUsageController.setCallback(new DataUsageController.Callback() {
Jason Monke0cdb602014-11-05 12:39:45 -0500220 @Override
221 public void onMobileDataEnabled(boolean enabled) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400222 mCallbackHandler.setMobileDataEnabled(enabled);
Evan Laird2ea99c12019-09-19 16:52:58 -0400223 notifyControllersMobileDataChanged();
Jason Monke0cdb602014-11-05 12:39:45 -0500224 }
225 });
Jason Monkd2263cd2014-11-10 14:22:56 -0500226 mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
Amin Shaikhc7593b12018-03-09 16:07:09 -0500227 mCallbackHandler, this, mWifiManager);
Jason Monkd2263cd2014-11-10 14:22:56 -0500228
Jason Monk07b75fe2015-05-14 16:47:03 -0400229 mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900230
Jason Monkd2263cd2014-11-10 14:22:56 -0500231 // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
Jason Monkb5746272014-11-12 16:50:31 -0500232 updateAirplaneMode(true /* force callback */);
Jason Monk9c7844c2017-01-18 15:21:53 -0500233 mUserTracker = new CurrentUserTracker(mContext) {
234 @Override
235 public void onUserSwitched(int newUserId) {
236 NetworkControllerImpl.this.onUserSwitched(newUserId);
237 }
238 };
239 mUserTracker.startTracking();
240 deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
241 @Override
242 public void onUserSetupChanged() {
243 setUserSetupComplete(deviceProvisionedController.isUserSetup(
244 deviceProvisionedController.getCurrentUser()));
245 }
246 });
Anarghya Mitra678722f2018-05-11 14:29:54 -0700247
248 ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){
249 private Network mLastNetwork;
250 private NetworkCapabilities mLastNetworkCapabilities;
251
252 @Override
253 public void onCapabilitiesChanged(
254 Network network, NetworkCapabilities networkCapabilities) {
255 boolean lastValidated = (mLastNetworkCapabilities != null) &&
256 mLastNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
257 boolean validated =
258 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
259
260 // This callback is invoked a lot (i.e. when RSSI changes), so avoid updating
261 // icons when connectivity state has remained the same.
262 if (network.equals(mLastNetwork) &&
263 networkCapabilities.equalsTransportTypes(mLastNetworkCapabilities) &&
264 validated == lastValidated) {
265 return;
266 }
267 mLastNetwork = network;
268 mLastNetworkCapabilities = networkCapabilities;
269 updateConnectivity();
270 }
271 };
272 // Even though this callback runs on the receiver handler thread which also processes the
273 // CONNECTIVITY_ACTION broadcasts, the broadcast and callback might come in at different
274 // times. This is safe since updateConnectivity() builds the list of transports from
275 // scratch.
276 // TODO: Move off of the deprecated CONNECTIVITY_ACTION broadcast and rely on callbacks
277 // exclusively for status bar icons.
278 mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
Evan Laird470ae842019-04-09 16:24:27 -0400279 // Register the listener on our bg looper
280 mPhoneStateListener = new PhoneStateListener(bgLooper) {
281 @Override
282 public void onActiveDataSubscriptionIdChanged(int subId) {
283 mActiveMobileDataSubscription = subId;
284 doUpdateMobileControllers();
285 }
286 };
Jason Monke0cdb602014-11-05 12:39:45 -0500287 }
288
Jason Monk9a4ce132016-01-21 15:27:17 -0500289 public DataSaverController getDataSaverController() {
290 return mDataSaverController;
291 }
292
Jason Monkf13b4b32014-11-07 16:39:34 -0500293 private void registerListeners() {
Jason Monk8996b942017-03-02 13:58:19 -0500294 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
295 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500296 mobileSignalController.registerListener();
297 }
Jason Monk8fcab352015-06-29 10:57:00 -0400298 if (mSubscriptionListener == null) {
299 mSubscriptionListener = new SubListener();
300 }
Wink Saville071743f2015-01-12 17:11:04 -0800301 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Malcolm Chen50ba9632019-02-26 16:49:56 -0800302 mPhone.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
Jason Monke0cdb602014-11-05 12:39:45 -0500303
John Spurlockaf8d6c42014-05-07 17:49:08 -0400304 // broadcasts
305 IntentFilter filter = new IntentFilter();
306 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
307 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
308 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
309 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jason Monkb5746272014-11-12 16:50:31 -0500310 filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
311 filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
Jason Monkb0808aa2015-07-22 16:34:36 -0400312 filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400313 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Erik Kline32830cc2015-04-21 13:09:15 +0900314 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400315 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400316 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
Wenting Xiong63364fe2017-02-07 19:12:27 +0800317 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
Jason Monk07b75fe2015-05-14 16:47:03 -0400318 mContext.registerReceiver(this, filter, null, mReceiverHandler);
Jason Monkb5746272014-11-12 16:50:31 -0500319 mListening = true;
320
321 updateMobileControllers();
John Spurlockb98f7472014-07-08 17:09:42 -0400322 }
323
Jason Monkd2263cd2014-11-10 14:22:56 -0500324 private void unregisterListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500325 mListening = false;
Jason Monk8996b942017-03-02 13:58:19 -0500326 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
327 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500328 mobileSignalController.unregisterListener();
329 }
Wink Saville071743f2015-01-12 17:11:04 -0800330 mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monkd2263cd2014-11-10 14:22:56 -0500331 mContext.unregisterReceiver(this);
Jason Monk5d325072014-10-27 11:38:47 -0400332 }
333
Jason Monk0e2400f2014-11-21 11:08:55 -0500334 public int getConnectedWifiLevel() {
335 return mWifiSignalController.getState().level;
336 }
337
Jason Monk5d325072014-10-27 11:38:47 -0400338 @Override
Jason Monkd2263cd2014-11-10 14:22:56 -0500339 public AccessPointController getAccessPointController() {
340 return mAccessPoints;
341 }
342
343 @Override
Jason Monkf668d7c2016-01-14 10:38:41 -0500344 public DataUsageController getMobileDataController() {
345 return mDataUsageController;
Jason Monkd2263cd2014-11-10 14:22:56 -0500346 }
347
348 public void addEmergencyListener(EmergencyListener listener) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400349 mCallbackHandler.setListening(listener, true);
350 mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400351 }
352
Jason Monk46dbfb42016-02-25 14:59:20 -0500353 public void removeEmergencyListener(EmergencyListener listener) {
354 mCallbackHandler.setListening(listener, false);
355 }
356
John Spurlockaf8d6c42014-05-07 17:49:08 -0400357 public boolean hasMobileDataFeature() {
358 return mHasMobileDataFeature;
359 }
360
361 public boolean hasVoiceCallingFeature() {
362 return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
363 }
364
Jason Monkb5746272014-11-12 16:50:31 -0500365 private MobileSignalController getDataController() {
Fabian Kozynskiccde55d2019-06-26 10:06:09 -0400366 int dataSubId = mSubDefaults.getActiveDataSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800367 if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
Jason Monkb5746272014-11-12 16:50:31 -0500368 if (DEBUG) Log.e(TAG, "No data sim selected");
369 return mDefaultSignalController;
370 }
Jason Monk8996b942017-03-02 13:58:19 -0500371 if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500372 return mMobileSignalControllers.get(dataSubId);
373 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500374 if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
Jason Monkb5746272014-11-12 16:50:31 -0500375 return mDefaultSignalController;
376 }
377
Amin Shaikh329c8282018-03-09 14:50:59 -0500378 @Override
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700379 public String getMobileDataNetworkName() {
Jason Monkb5746272014-11-12 16:50:31 -0500380 MobileSignalController controller = getDataController();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700381 return controller != null ? controller.getState().networkNameData : "";
Jason Monkd2263cd2014-11-10 14:22:56 -0500382 }
383
Fabian Kozynskif1c32a02019-03-22 15:09:30 -0400384 @Override
385 public int getNumberSubscriptions() {
386 return mMobileSignalControllers.size();
387 }
388
Evan Laird2ea99c12019-09-19 16:52:58 -0400389 boolean isDataControllerDisabled() {
390 MobileSignalController dataController = getDataController();
391 if (dataController == null) {
392 return false;
393 }
394
395 return dataController.isDataDisabled();
396 }
397
398 private void notifyControllersMobileDataChanged() {
399 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
400 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
401 mobileSignalController.onMobileDataChanged();
402 }
403 }
404
John Spurlockaf8d6c42014-05-07 17:49:08 -0400405 public boolean isEmergencyOnly() {
Jason Monkb0808aa2015-07-22 16:34:36 -0400406 if (mMobileSignalControllers.size() == 0) {
407 // When there are no active subscriptions, determine emengency state from last
408 // broadcast.
Jason Monk66845a32015-08-03 11:09:41 -0400409 mEmergencySource = EMERGENCY_NO_CONTROLLERS;
Jason Monkb0808aa2015-07-22 16:34:36 -0400410 return mLastServiceState != null && mLastServiceState.isEmergencyOnly();
411 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400412 int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800413 if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
Jason Monk8996b942017-03-02 13:58:19 -0500414 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
415 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkc6cc6262015-06-11 11:10:15 -0400416 if (!mobileSignalController.getState().isEmergency) {
Jason Monk66845a32015-08-03 11:09:41 -0400417 mEmergencySource = EMERGENCY_FIRST_CONTROLLER
418 + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400419 if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag);
Jason Monkb5746272014-11-12 16:50:31 -0500420 return false;
421 }
422 }
423 }
Jason Monk8996b942017-03-02 13:58:19 -0500424 if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) {
Jason Monk66845a32015-08-03 11:09:41 -0400425 mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
Jason Monkc6cc6262015-06-11 11:10:15 -0400426 if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
427 return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
Jason Monkb5746272014-11-12 16:50:31 -0500428 }
Jason Monk8996b942017-03-02 13:58:19 -0500429 // If we have the wrong subId but there is only one sim anyway, assume it should be the
430 // default.
431 if (mMobileSignalControllers.size() == 1) {
432 mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER
433 + mMobileSignalControllers.keyAt(0);
434 if (DEBUG) Log.d(TAG, "Getting assumed emergency from "
435 + mMobileSignalControllers.keyAt(0));
436 return mMobileSignalControllers.valueAt(0).getState().isEmergency;
437 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500438 if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
Jason Monk66845a32015-08-03 11:09:41 -0400439 mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
Jason Monkb5746272014-11-12 16:50:31 -0500440 // Something is wrong, better assume we can't make calls...
441 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400442 }
443
Jason Monkd2263cd2014-11-10 14:22:56 -0500444 /**
445 * Emergency status may have changed (triggered by MobileSignalController),
446 * so we should recheck and send out the state to listeners.
447 */
448 void recalculateEmergency() {
Jason Monk66845a32015-08-03 11:09:41 -0400449 mIsEmergency = isEmergencyOnly();
450 mCallbackHandler.setEmergencyCallsOnly(mIsEmergency);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400451 }
452
Jason Monk88529052016-11-04 13:29:58 -0400453 public void addCallback(SignalCallback cb) {
Jason Monke06b0652016-03-02 16:35:27 -0500454 cb.setSubs(mCurrentSubscriptions);
455 cb.setIsAirplaneMode(new IconState(mAirplaneMode,
Jason Monk07b75fe2015-05-14 16:47:03 -0400456 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monk1ff77662017-09-29 11:17:05 -0400457 cb.setNoSims(mHasNoSubs, mSimDetected);
Jason Monke06b0652016-03-02 16:35:27 -0500458 mWifiSignalController.notifyListeners(cb);
459 mEthernetSignalController.notifyListeners(cb);
Jason Monk8996b942017-03-02 13:58:19 -0500460 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
461 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monke06b0652016-03-02 16:35:27 -0500462 mobileSignalController.notifyListeners(cb);
Jason Monkb5746272014-11-12 16:50:31 -0500463 }
Jason Monke06b0652016-03-02 16:35:27 -0500464 mCallbackHandler.setListening(cb, true);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400465 }
466
Jason Monk07b75fe2015-05-14 16:47:03 -0400467 @Override
Jason Monk88529052016-11-04 13:29:58 -0400468 public void removeCallback(SignalCallback cb) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400469 mCallbackHandler.setListening(cb, false);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400470 }
471
472 @Override
473 public void setWifiEnabled(final boolean enabled) {
474 new AsyncTask<Void, Void, Void>() {
475 @Override
476 protected Void doInBackground(Void... args) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400477 mWifiManager.setWifiEnabled(enabled);
478 return null;
479 }
480 }.execute();
481 }
482
Jason Monk9c7844c2017-01-18 15:21:53 -0500483 private void onUserSwitched(int newUserId) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900484 mCurrentUserId = newUserId;
485 mAccessPoints.onUserSwitched(newUserId);
486 updateConnectivity();
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900487 }
488
489 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400490 public void onReceive(Context context, Intent intent) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500491 if (CHATTY) {
492 Log.d(TAG, "onReceive: intent=" + intent);
493 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400494 final String action = intent.getAction();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800495 switch (action) {
496 case ConnectivityManager.CONNECTIVITY_ACTION:
497 case ConnectivityManager.INET_CONDITION_ACTION:
498 updateConnectivity();
499 break;
500 case Intent.ACTION_AIRPLANE_MODE_CHANGED:
501 refreshLocale();
502 updateAirplaneMode(false);
503 break;
504 case TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
505 // We are using different subs now, we might be able to make calls.
Jason Monkb0808aa2015-07-22 16:34:36 -0400506 recalculateEmergency();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800507 break;
508 case TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
509 // Notify every MobileSignalController so they can know whether they are the
510 // data sim or not.
511 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
512 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
513 controller.handleBroadcast(intent);
Wenting Xiong63364fe2017-02-07 19:12:27 +0800514 }
Niklas Lindgrena02964d2018-09-21 14:01:57 +0200515 mConfig = Config.readConfig(mContext);
516 mReceiverHandler.post(this::handleConfigurationChanged);
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800517 break;
518 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
519 // Avoid rebroadcast because SysUI is direct boot aware.
520 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
521 break;
522 }
523 // Might have different subscriptions now.
524 updateMobileControllers();
525 break;
526 case TelephonyIntents.ACTION_SERVICE_STATE_CHANGED:
527 mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
528 if (mMobileSignalControllers.size() == 0) {
529 // If none of the subscriptions are active, we might need to recalculate
530 // emergency state.
531 recalculateEmergency();
532 }
533 break;
534 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
535 mConfig = Config.readConfig(mContext);
536 mReceiverHandler.post(this::handleConfigurationChanged);
537 break;
538 default:
539 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
540 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
541 if (SubscriptionManager.isValidSubscriptionId(subId)) {
542 if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
543 mMobileSignalControllers.get(subId).handleBroadcast(intent);
544 } else {
545 // Can't find this subscription... We must be out of date.
546 updateMobileControllers();
547 }
Jason Monkb5746272014-11-12 16:50:31 -0500548 } else {
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800549 // No sub id, must be for the wifi.
550 mWifiSignalController.handleBroadcast(intent);
Jason Monkb5746272014-11-12 16:50:31 -0500551 }
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800552 break;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400553 }
Jason Monkb5746272014-11-12 16:50:31 -0500554 }
555
Jason Monk9c7844c2017-01-18 15:21:53 -0500556 public void onConfigurationChanged(Configuration newConfig) {
Sungmin Choi6be4f6b2015-07-07 13:06:59 +0900557 mConfig = Config.readConfig(mContext);
Jason Monk1c040db2015-07-20 09:45:54 -0400558 mReceiverHandler.post(new Runnable() {
559 @Override
560 public void run() {
561 handleConfigurationChanged();
562 }
563 });
564 }
565
566 @VisibleForTesting
567 void handleConfigurationChanged() {
Malcolm Chen50ba9632019-02-26 16:49:56 -0800568 updateMobileControllers();
Jason Monk8996b942017-03-02 13:58:19 -0500569 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
570 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
571 controller.setConfiguration(mConfig);
Jason Monk3aaabd72014-12-12 11:11:44 -0500572 }
573 refreshLocale();
Jason Monk3aaabd72014-12-12 11:11:44 -0500574 }
575
Jason Monkb5746272014-11-12 16:50:31 -0500576 private void updateMobileControllers() {
577 if (!mListening) {
578 return;
579 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400580 doUpdateMobileControllers();
581 }
582
Malcolm Chen50ba9632019-02-26 16:49:56 -0800583 private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) {
584 if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) {
585 SubscriptionInfo info1 = subscriptions.get(0);
586 SubscriptionInfo info2 = subscriptions.get(1);
587 if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) {
588 // If both subscriptions are primary, show both.
589 if (!info1.isOpportunistic() && !info2.isOpportunistic()) return;
590
591 // If carrier required, always show signal bar of primary subscription.
592 // Otherwise, show whichever subscription is currently active for Internet.
593 boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig()
594 .getBoolean(CarrierConfigManager
595 .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN);
596 if (alwaysShowPrimary) {
597 subscriptions.remove(info1.isOpportunistic() ? info1 : info2);
598 } else {
599 subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription
600 ? info2 : info1);
601 }
602 }
603 }
604 }
605
Jason Monkc6cc6262015-06-11 11:10:15 -0400606 @VisibleForTesting
607 void doUpdateMobileControllers() {
Malcolm Chend2d400cb2018-12-21 17:11:10 -0800608 List<SubscriptionInfo> subscriptions = mSubscriptionManager
Malcolm Chen50ba9632019-02-26 16:49:56 -0800609 .getActiveSubscriptionInfoList(false);
Jason Monkc9f05712014-12-15 12:24:10 -0500610 if (subscriptions == null) {
611 subscriptions = Collections.emptyList();
612 }
Malcolm Chen50ba9632019-02-26 16:49:56 -0800613
614 filterMobileSubscriptionInSameGroup(subscriptions);
615
Jason Monkb5746272014-11-12 16:50:31 -0500616 // If there have been no relevant changes to any of the subscriptions, we can leave as is.
617 if (hasCorrectMobileControllers(subscriptions)) {
618 // Even if the controllers are correct, make sure we have the right no sims state.
619 // Such as on boot, don't need any controllers, because there are no sims,
620 // but we still need to update the no sim state.
621 updateNoSims();
622 return;
623 }
Evan Laird470ae842019-04-09 16:24:27 -0400624 synchronized (mLock) {
625 setCurrentSubscriptionsLocked(subscriptions);
626 }
Jason Monkb5746272014-11-12 16:50:31 -0500627 updateNoSims();
Jason Monkc6cc6262015-06-11 11:10:15 -0400628 recalculateEmergency();
Jason Monkb5746272014-11-12 16:50:31 -0500629 }
630
Jason Monk21d05a02014-12-02 12:46:58 -0500631 @VisibleForTesting
632 protected void updateNoSims() {
Jason Monk1ff77662017-09-29 11:17:05 -0400633 boolean hasNoSubs = mHasMobileDataFeature && mMobileSignalControllers.size() == 0;
634 boolean simDetected = hasAnySim();
635 if (hasNoSubs != mHasNoSubs || simDetected != mSimDetected) {
636 mHasNoSubs = hasNoSubs;
637 mSimDetected = simDetected;
638 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
Jason Monkb5746272014-11-12 16:50:31 -0500639 }
640 }
641
Jason Monk1ff77662017-09-29 11:17:05 -0400642 private boolean hasAnySim() {
643 int simCount = mPhone.getSimCount();
644 for (int i = 0; i < simCount; i++) {
645 int state = mPhone.getSimState(i);
646 if (state != TelephonyManager.SIM_STATE_ABSENT
647 && state != TelephonyManager.SIM_STATE_UNKNOWN) {
648 return true;
649 }
650 }
651 return false;
652 }
653
Evan Laird470ae842019-04-09 16:24:27 -0400654 @GuardedBy("mLock")
Jason Monkb5746272014-11-12 16:50:31 -0500655 @VisibleForTesting
Evan Laird470ae842019-04-09 16:24:27 -0400656 public void setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions) {
Jason Monkb5746272014-11-12 16:50:31 -0500657 Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() {
658 @Override
659 public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) {
660 return lhs.getSimSlotIndex() == rhs.getSimSlotIndex()
661 ? lhs.getSubscriptionId() - rhs.getSubscriptionId()
662 : lhs.getSimSlotIndex() - rhs.getSimSlotIndex();
663 }
664 });
Jason Monkb5746272014-11-12 16:50:31 -0500665 mCurrentSubscriptions = subscriptions;
666
Jason Monk8996b942017-03-02 13:58:19 -0500667 SparseArray<MobileSignalController> cachedControllers =
668 new SparseArray<MobileSignalController>();
669 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
670 cachedControllers.put(mMobileSignalControllers.keyAt(i),
671 mMobileSignalControllers.valueAt(i));
672 }
Jason Monkb5746272014-11-12 16:50:31 -0500673 mMobileSignalControllers.clear();
674 final int num = subscriptions.size();
675 for (int i = 0; i < num; i++) {
676 int subId = subscriptions.get(i).getSubscriptionId();
677 // If we have a copy of this controller already reuse it, otherwise make a new one.
Jason Monk8996b942017-03-02 13:58:19 -0500678 if (cachedControllers.indexOfKey(subId) >= 0) {
679 mMobileSignalControllers.put(subId, cachedControllers.get(subId));
680 cachedControllers.remove(subId);
Jason Monkb5746272014-11-12 16:50:31 -0500681 } else {
682 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
chen xu84a90872019-03-28 15:44:12 -0700683 mHasMobileDataFeature, mPhone.createForSubscriptionId(subId),
684 mCallbackHandler, this, subscriptions.get(i),
685 mSubDefaults, mReceiverHandler.getLooper());
Jason Monkfd57ea72016-04-29 13:37:58 -0400686 controller.setUserSetupComplete(mUserSetup);
Jason Monkb5746272014-11-12 16:50:31 -0500687 mMobileSignalControllers.put(subId, controller);
688 if (subscriptions.get(i).getSimSlotIndex() == 0) {
689 mDefaultSignalController = controller;
690 }
691 if (mListening) {
692 controller.registerListener();
693 }
694 }
695 }
696 if (mListening) {
Jason Monk8996b942017-03-02 13:58:19 -0500697 for (int i = 0; i < cachedControllers.size(); i++) {
698 int key = cachedControllers.keyAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500699 if (cachedControllers.get(key) == mDefaultSignalController) {
700 mDefaultSignalController = null;
701 }
702 cachedControllers.get(key).unregisterListener();
703 }
704 }
Jason Monk8fcab352015-06-29 10:57:00 -0400705 mCallbackHandler.setSubs(subscriptions);
706 notifyAllListeners();
707
Jason Monk25d8a482014-12-09 12:27:24 -0500708 // There may be new MobileSignalControllers around, make sure they get the current
709 // inet condition and airplane mode.
710 pushConnectivityToSignals();
711 updateAirplaneMode(true /* force */);
Jason Monkb5746272014-11-12 16:50:31 -0500712 }
713
Jason Monk0288de02017-02-23 14:48:05 -0500714 private void setUserSetupComplete(final boolean userSetup) {
715 mReceiverHandler.post(() -> handleSetUserSetupComplete(userSetup));
Jason Monkfd57ea72016-04-29 13:37:58 -0400716 }
717
Jason Monk0288de02017-02-23 14:48:05 -0500718 private void handleSetUserSetupComplete(boolean userSetup) {
Jason Monkfd57ea72016-04-29 13:37:58 -0400719 mUserSetup = userSetup;
Jason Monk8996b942017-03-02 13:58:19 -0500720 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
721 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkfd57ea72016-04-29 13:37:58 -0400722 controller.setUserSetupComplete(mUserSetup);
723 }
724 }
725
Jason Monkc014dec2014-12-12 11:49:55 -0500726 @VisibleForTesting
727 boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) {
Jason Monkc9f05712014-12-15 12:24:10 -0500728 if (allSubscriptions.size() != mMobileSignalControllers.size()) {
729 return false;
Jason Monkb5746272014-11-12 16:50:31 -0500730 }
731 for (SubscriptionInfo info : allSubscriptions) {
Jason Monk8996b942017-03-02 13:58:19 -0500732 if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500733 return false;
734 }
735 }
736 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400737 }
738
Jason Monkd2263cd2014-11-10 14:22:56 -0500739 private void updateAirplaneMode(boolean force) {
740 boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
741 Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
742 if (airplaneMode != mAirplaneMode || force) {
743 mAirplaneMode = airplaneMode;
Jason Monk8996b942017-03-02 13:58:19 -0500744 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
745 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500746 mobileSignalController.setAirplaneMode(mAirplaneMode);
747 }
748 notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400749 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400750 }
751
752 private void refreshLocale() {
Jason Monkd2263cd2014-11-10 14:22:56 -0500753 Locale current = mContext.getResources().getConfiguration().locale;
Jason Monkb5746272014-11-12 16:50:31 -0500754 if (!current.equals(mLocale)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500755 mLocale = current;
Fabian Kozynskid9cb3842018-09-28 13:34:14 -0400756 mWifiSignalController.refreshLocale();
Jason Monkd2263cd2014-11-10 14:22:56 -0500757 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400758 }
759 }
760
Jason Monkd2263cd2014-11-10 14:22:56 -0500761 /**
Jason Monkb5746272014-11-12 16:50:31 -0500762 * Forces update of all callbacks on both SignalClusters and
763 * NetworkSignalChangedCallbacks.
764 */
Jason Monkd2263cd2014-11-10 14:22:56 -0500765 private void notifyAllListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500766 notifyListeners();
Jason Monk8996b942017-03-02 13:58:19 -0500767 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
768 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500769 mobileSignalController.notifyListeners();
770 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500771 mWifiSignalController.notifyListeners();
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900772 mEthernetSignalController.notifyListeners();
Jason Monkd2263cd2014-11-10 14:22:56 -0500773 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400774
Jason Monkb5746272014-11-12 16:50:31 -0500775 /**
776 * Notifies listeners of changes in state of to the NetworkController, but
777 * does not notify for any info on SignalControllers, for that call
778 * notifyAllListeners.
779 */
780 private void notifyListeners() {
Jason Monk07b75fe2015-05-14 16:47:03 -0400781 mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
782 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monk1ff77662017-09-29 11:17:05 -0400783 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400784 }
785
Jason Monkd2263cd2014-11-10 14:22:56 -0500786 /**
787 * Update the Inet conditions and what network we are connected to.
788 */
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900789 private void updateConnectivity() {
790 mConnectedTransports.clear();
791 mValidatedTransports.clear();
792 for (NetworkCapabilities nc :
793 mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
794 for (int transportType : nc.getTransportTypes()) {
795 mConnectedTransports.set(transportType);
796 if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
797 mValidatedTransports.set(transportType);
798 }
799 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400800 }
801
John Spurlockaf8d6c42014-05-07 17:49:08 -0400802 if (CHATTY) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900803 Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
804 Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400805 }
806
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900807 mInetCondition = !mValidatedTransports.isEmpty();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400808
Jason Monk25d8a482014-12-09 12:27:24 -0500809 pushConnectivityToSignals();
810 }
811
812 /**
813 * Pushes the current connectivity state to all SignalControllers.
814 */
815 private void pushConnectivityToSignals() {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400816 // We want to update all the icons, all at once, for any condition change
Jason Monk8996b942017-03-02 13:58:19 -0500817 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
818 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400819 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
Jason Monkb5746272014-11-12 16:50:31 -0500820 }
Jason Monk33f8ae72015-05-08 10:45:15 -0400821 mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
822 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400823 }
824
John Spurlockaf8d6c42014-05-07 17:49:08 -0400825 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
826 pw.println("NetworkController state:");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900827
John Spurlockaf8d6c42014-05-07 17:49:08 -0400828 pw.println(" - telephony ------");
829 pw.print(" hasVoiceCallingFeature()=");
830 pw.println(hasVoiceCallingFeature());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400831
John Spurlockaf8d6c42014-05-07 17:49:08 -0400832 pw.println(" - connectivity ------");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900833 pw.print(" mConnectedTransports=");
834 pw.println(mConnectedTransports);
835 pw.print(" mValidatedTransports=");
836 pw.println(mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400837 pw.print(" mInetCondition=");
838 pw.println(mInetCondition);
Jason Monkd2263cd2014-11-10 14:22:56 -0500839 pw.print(" mAirplaneMode=");
840 pw.println(mAirplaneMode);
841 pw.print(" mLocale=");
842 pw.println(mLocale);
Jason Monkb0808aa2015-07-22 16:34:36 -0400843 pw.print(" mLastServiceState=");
844 pw.println(mLastServiceState);
Jason Monk66845a32015-08-03 11:09:41 -0400845 pw.print(" mIsEmergency=");
846 pw.println(mIsEmergency);
847 pw.print(" mEmergencySource=");
848 pw.println(emergencyToString(mEmergencySource));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400849
Bill Lin767c0db2019-08-15 20:42:06 +0800850 pw.println(" - config ------");
851 pw.print(" patternOfCarrierSpecificDataIcon=");
852 pw.println(mConfig.patternOfCarrierSpecificDataIcon);
853 pw.print(" nr5GIconMap=");
854 pw.println(mConfig.nr5GIconMap.toString());
855 pw.print(" nrIconDisplayGracePeriodMs=");
856 pw.println(mConfig.nrIconDisplayGracePeriodMs);
Jason Monk8996b942017-03-02 13:58:19 -0500857 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
858 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500859 mobileSignalController.dump(pw);
860 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500861 mWifiSignalController.dump(pw);
Jason Monkd52356a2015-01-28 10:40:41 -0500862
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900863 mEthernetSignalController.dump(pw);
864
Jason Monkd52356a2015-01-28 10:40:41 -0500865 mAccessPoints.dump(pw);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400866 }
867
Jason Monk66845a32015-08-03 11:09:41 -0400868 private static final String emergencyToString(int emergencySource) {
869 if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk8996b942017-03-02 13:58:19 -0500870 return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER)
871 + ")";
872 } else if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk66845a32015-08-03 11:09:41 -0400873 return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
874 } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
875 return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
876 } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) {
877 return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")";
878 } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) {
879 return "NO_CONTROLLERS";
880 }
881 return "UNKNOWN_SOURCE";
882 }
883
John Spurlockaf8d6c42014-05-07 17:49:08 -0400884 private boolean mDemoMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400885 private boolean mDemoInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500886 private WifiSignalController.WifiState mDemoWifiState;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400887
888 @Override
889 public void dispatchDemoCommand(String command, Bundle args) {
890 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500891 if (DEBUG) Log.d(TAG, "Entering demo mode");
892 unregisterListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400893 mDemoMode = true;
Jason Monk33f8ae72015-05-08 10:45:15 -0400894 mDemoInetCondition = mInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500895 mDemoWifiState = mWifiSignalController.getState();
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100896 mDemoWifiState.ssid = "DemoMode";
John Spurlockaf8d6c42014-05-07 17:49:08 -0400897 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500898 if (DEBUG) Log.d(TAG, "Exiting demo mode");
John Spurlockaf8d6c42014-05-07 17:49:08 -0400899 mDemoMode = false;
Jason Monkb5746272014-11-12 16:50:31 -0500900 // Update what MobileSignalControllers, because they may change
901 // to set the number of sim slots.
902 updateMobileControllers();
Jason Monk8996b942017-03-02 13:58:19 -0500903 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
904 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500905 controller.resetLastState();
906 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500907 mWifiSignalController.resetLastState();
Jason Monk07b75fe2015-05-14 16:47:03 -0400908 mReceiverHandler.post(mRegisterListeners);
Jason Monkd2263cd2014-11-10 14:22:56 -0500909 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400910 } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
911 String airplane = args.getString("airplane");
912 if (airplane != null) {
913 boolean show = airplane.equals("show");
Jason Monk07b75fe2015-05-14 16:47:03 -0400914 mCallbackHandler.setIsAirplaneMode(new IconState(show,
915 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode,
916 mContext));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400917 }
918 String fully = args.getString("fully");
919 if (fully != null) {
Jason Monk33f8ae72015-05-08 10:45:15 -0400920 mDemoInetCondition = Boolean.parseBoolean(fully);
921 BitSet connected = new BitSet();
922
923 if (mDemoInetCondition) {
924 connected.set(mWifiSignalController.mTransportType);
925 }
926 mWifiSignalController.updateConnectivity(connected, connected);
Jason Monk8996b942017-03-02 13:58:19 -0500927 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
928 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400929 if (mDemoInetCondition) {
930 connected.set(controller.mTransportType);
931 }
932 controller.updateConnectivity(connected, connected);
Jason Monkb5746272014-11-12 16:50:31 -0500933 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400934 }
935 String wifi = args.getString("wifi");
936 if (wifi != null) {
937 boolean show = wifi.equals("show");
938 String level = args.getString("level");
939 if (level != null) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500940 mDemoWifiState.level = level.equals("null") ? -1
John Spurlockaf8d6c42014-05-07 17:49:08 -0400941 : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
Jason Monkd2263cd2014-11-10 14:22:56 -0500942 mDemoWifiState.connected = mDemoWifiState.level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400943 }
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100944 String activity = args.getString("activity");
945 if (activity != null) {
946 switch (activity) {
947 case "inout":
Roshan Pius80fb1372018-07-16 15:43:03 -0700948 mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100949 break;
950 case "in":
Roshan Pius80fb1372018-07-16 15:43:03 -0700951 mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100952 break;
953 case "out":
Roshan Pius80fb1372018-07-16 15:43:03 -0700954 mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100955 break;
956 default:
Roshan Pius80fb1372018-07-16 15:43:03 -0700957 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100958 break;
959 }
960 } else {
Roshan Pius80fb1372018-07-16 15:43:03 -0700961 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100962 }
Evan Laird27a99572017-09-27 14:09:30 -0400963 String ssid = args.getString("ssid");
964 if (ssid != null) {
965 mDemoWifiState.ssid = ssid;
966 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500967 mDemoWifiState.enabled = show;
968 mWifiSignalController.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400969 }
Jason Monkb5746272014-11-12 16:50:31 -0500970 String sims = args.getString("sims");
971 if (sims != null) {
John Spurlockcf053c12015-05-14 16:33:59 -0400972 int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
973 List<SubscriptionInfo> subs = new ArrayList<>();
Jason Monkb5746272014-11-12 16:50:31 -0500974 if (num != mMobileSignalControllers.size()) {
975 mMobileSignalControllers.clear();
976 int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
977 for (int i = start /* get out of normal index range */; i < start + num; i++) {
John Spurlockcf053c12015-05-14 16:33:59 -0400978 subs.add(addSignalController(i, i));
Jason Monkb5746272014-11-12 16:50:31 -0500979 }
Jason Monk33b60bb2015-07-13 10:42:23 -0400980 mCallbackHandler.setSubs(subs);
Evan Lairde1d13c92018-03-20 16:58:01 -0400981 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
982 int key = mMobileSignalControllers.keyAt(i);
983 MobileSignalController controller = mMobileSignalControllers.get(key);
984 controller.notifyListeners();
985 }
Jason Monkb5746272014-11-12 16:50:31 -0500986 }
Jason Monkb5746272014-11-12 16:50:31 -0500987 }
988 String nosim = args.getString("nosim");
989 if (nosim != null) {
Jason Monk1ff77662017-09-29 11:17:05 -0400990 mHasNoSubs = nosim.equals("show");
991 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
Jason Monkb5746272014-11-12 16:50:31 -0500992 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400993 String mobile = args.getString("mobile");
994 if (mobile != null) {
995 boolean show = mobile.equals("show");
996 String datatype = args.getString("datatype");
Jason Monkb5746272014-11-12 16:50:31 -0500997 String slotString = args.getString("slot");
998 int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
John Spurlockcf053c12015-05-14 16:33:59 -0400999 slot = MathUtils.constrain(slot, 0, 8);
1000 // Ensure we have enough sim slots
1001 List<SubscriptionInfo> subs = new ArrayList<>();
1002 while (mMobileSignalControllers.size() <= slot) {
1003 int nextSlot = mMobileSignalControllers.size();
1004 subs.add(addSignalController(nextSlot, nextSlot));
1005 }
1006 if (!subs.isEmpty()) {
Jason Monk07b75fe2015-05-14 16:47:03 -04001007 mCallbackHandler.setSubs(subs);
John Spurlockcf053c12015-05-14 16:33:59 -04001008 }
Jason Monkb5746272014-11-12 16:50:31 -05001009 // Hack to index linearly for easy use.
Jason Monk8996b942017-03-02 13:58:19 -05001010 MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
Jason Monkb5746272014-11-12 16:50:31 -05001011 controller.getState().dataSim = datatype != null;
Jason Monkb5950982017-01-24 15:53:53 -05001012 controller.getState().isDefault = datatype != null;
1013 controller.getState().dataConnected = datatype != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001014 if (datatype != null) {
Jason Monkb5746272014-11-12 16:50:31 -05001015 controller.getState().iconGroup =
Jason Monkd2263cd2014-11-10 14:22:56 -05001016 datatype.equals("1x") ? TelephonyIcons.ONE_X :
1017 datatype.equals("3g") ? TelephonyIcons.THREE_G :
1018 datatype.equals("4g") ? TelephonyIcons.FOUR_G :
Ajay Nambi7965fa42015-05-14 18:48:33 -07001019 datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
Bill Lin767c0db2019-08-15 20:42:06 +08001020 datatype.equals("5g") ? TelephonyIcons.NR_5G :
Evan Laird83c87e52019-09-24 19:14:05 -04001021 datatype.equals("5ge") ? TelephonyIcons.LTE_CA_5G_E :
Bill Lin767c0db2019-08-15 20:42:06 +08001022 datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -05001023 datatype.equals("e") ? TelephonyIcons.E :
1024 datatype.equals("g") ? TelephonyIcons.G :
1025 datatype.equals("h") ? TelephonyIcons.H :
Amin Shaikhf5830ca2018-03-09 14:06:50 -05001026 datatype.equals("h+") ? TelephonyIcons.H_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -05001027 datatype.equals("lte") ? TelephonyIcons.LTE :
Jason Monkaa730be2016-07-13 14:22:52 -04001028 datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
Jason Monk7e6c83c2017-04-26 14:35:24 -04001029 datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -04001030 datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA :
Jason Monkd2263cd2014-11-10 14:22:56 -05001031 TelephonyIcons.UNKNOWN;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001032 }
Jason Monk0f0de132016-12-19 15:36:13 -05001033 if (args.containsKey("roam")) {
1034 controller.getState().roaming = "show".equals(args.getString("roam"));
1035 }
John Spurlockaf8d6c42014-05-07 17:49:08 -04001036 String level = args.getString("level");
1037 if (level != null) {
Jason Monkb5746272014-11-12 16:50:31 -05001038 controller.getState().level = level.equals("null") ? -1
Jason Monk48edc0c2017-04-10 15:01:27 -04001039 : Math.min(Integer.parseInt(level),
1040 SignalStrength.NUM_SIGNAL_STRENGTH_BINS);
Jason Monkb5746272014-11-12 16:50:31 -05001041 controller.getState().connected = controller.getState().level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001042 }
Amin Shaikh0ad7e512019-04-29 07:36:34 -04001043 if (args.containsKey("inflate")) {
1044 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
1045 mMobileSignalControllers.valueAt(i).mInflateSignalStrengths =
1046 "true".equals(args.getString("inflate"));
1047 }
1048 }
Jason Monk0f0de132016-12-19 15:36:13 -05001049 String activity = args.getString("activity");
1050 if (activity != null) {
Kenneth Westin5c88ffb2013-11-28 16:29:40 +01001051 controller.getState().dataConnected = true;
1052 switch (activity) {
1053 case "inout":
1054 controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
1055 break;
1056 case "in":
1057 controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
1058 break;
1059 case "out":
1060 controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
1061 break;
1062 default:
1063 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
1064 break;
1065 }
1066 } else {
1067 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
Jason Monk0f0de132016-12-19 15:36:13 -05001068 }
Jason Monkb5746272014-11-12 16:50:31 -05001069 controller.getState().enabled = show;
1070 controller.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -04001071 }
Andrew Flynna478d702015-04-14 23:33:45 -04001072 String carrierNetworkChange = args.getString("carriernetworkchange");
1073 if (carrierNetworkChange != null) {
1074 boolean show = carrierNetworkChange.equals("show");
Jason Monk8996b942017-03-02 13:58:19 -05001075 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
1076 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Andrew Flynna478d702015-04-14 23:33:45 -04001077 controller.setCarrierNetworkChangeMode(show);
1078 }
1079 }
Jason Monkd2263cd2014-11-10 14:22:56 -05001080 }
1081 }
1082
John Spurlockcf053c12015-05-14 16:33:59 -04001083 private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
1084 SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
Malcolm Chene89e0ce2018-08-09 17:01:35 -07001085 null, null, null, "", false, null, null);
Jason Monkb5950982017-01-24 15:53:53 -05001086 MobileSignalController controller = new MobileSignalController(mContext,
chen xu84a90872019-03-28 15:44:12 -07001087 mConfig, mHasMobileDataFeature,
1088 mPhone.createForSubscriptionId(info.getSubscriptionId()), mCallbackHandler, this, info,
Jason Monkb5950982017-01-24 15:53:53 -05001089 mSubDefaults, mReceiverHandler.getLooper());
1090 mMobileSignalControllers.put(id, controller);
1091 controller.getState().userSetup = true;
John Spurlockcf053c12015-05-14 16:33:59 -04001092 return info;
1093 }
1094
Adrian Roos316bf542016-08-23 17:53:07 +02001095 public boolean hasEmergencyCryptKeeperText() {
1096 return EncryptionHelper.IS_DATA_ENCRYPTED;
1097 }
1098
1099 public boolean isRadioOn() {
1100 return !mAirplaneMode;
1101 }
1102
Jason Monk8fcab352015-06-29 10:57:00 -04001103 private class SubListener extends OnSubscriptionsChangedListener {
Jason Monkc9f05712014-12-15 12:24:10 -05001104 @Override
1105 public void onSubscriptionsChanged() {
Jason Monkb5746272014-11-12 16:50:31 -05001106 updateMobileControllers();
Jason Monk8fcab352015-06-29 10:57:00 -04001107 }
1108 }
Jason Monkb5746272014-11-12 16:50:31 -05001109
Jason Monk07b75fe2015-05-14 16:47:03 -04001110 /**
1111 * Used to register listeners from the BG Looper, this way the PhoneStateListeners that
1112 * get created will also run on the BG Looper.
1113 */
1114 private final Runnable mRegisterListeners = new Runnable() {
1115 @Override
1116 public void run() {
1117 registerListeners();
1118 }
1119 };
Jason Monkd2263cd2014-11-10 14:22:56 -05001120
Jason Monkc6cc6262015-06-11 11:10:15 -04001121 public static class SubscriptionDefaults {
1122 public int getDefaultVoiceSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -08001123 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -04001124 }
1125
1126 public int getDefaultDataSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -08001127 return SubscriptionManager.getDefaultDataSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -04001128 }
Fabian Kozynskiccde55d2019-06-26 10:06:09 -04001129
1130 public int getActiveDataSubId() {
1131 return SubscriptionManager.getActiveDataSubscriptionId();
1132 }
Jason Monkc6cc6262015-06-11 11:10:15 -04001133 }
1134
Jason Monkd2263cd2014-11-10 14:22:56 -05001135 @VisibleForTesting
1136 static class Config {
Pengquan Menga62d32b2018-12-06 17:38:38 -08001137 static final int NR_CONNECTED_MMWAVE = 1;
1138 static final int NR_CONNECTED = 2;
SongFerngWang52dada72019-08-14 16:59:29 +08001139 static final int NR_NOT_RESTRICTED_RRC_IDLE = 3;
1140 static final int NR_NOT_RESTRICTED_RRC_CON = 4;
1141 static final int NR_RESTRICTED = 5;
Pengquan Menga62d32b2018-12-06 17:38:38 -08001142
1143 Map<Integer, MobileIconGroup> nr5GIconMap = new HashMap<>();
1144
Jason Monkb5746272014-11-12 16:50:31 -05001145 boolean showAtLeast3G = false;
vagdevi3f2b9a52019-08-09 09:45:14 -07001146 boolean show4gFor3g = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001147 boolean alwaysShowCdmaRssi = false;
1148 boolean show4gForLte = false;
Robert Greenwalt37d34ba2016-07-27 14:54:34 -07001149 boolean hideLtePlus = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001150 boolean hspaDataDistinguishable;
Jason Monk43c14d12017-06-22 11:20:04 -04001151 boolean inflateSignalStrengths = false;
Wenting Xiong63364fe2017-02-07 19:12:27 +08001152 boolean alwaysShowDataRatIcon = false;
SongFerngWang3cbcf752019-03-21 23:14:20 +08001153 public String patternOfCarrierSpecificDataIcon = "";
Bill Lin767c0db2019-08-15 20:42:06 +08001154 public long nrIconDisplayGracePeriodMs;
Jason Monkd2263cd2014-11-10 14:22:56 -05001155
Pengquan Menga62d32b2018-12-06 17:38:38 -08001156 /**
1157 * Mapping from NR 5G status string to an integer. The NR 5G status string should match
1158 * those in carrier config.
1159 */
1160 private static final Map<String, Integer> NR_STATUS_STRING_TO_INDEX;
1161 static {
SongFerngWang52dada72019-08-14 16:59:29 +08001162 NR_STATUS_STRING_TO_INDEX = new HashMap<>(5);
Pengquan Menga62d32b2018-12-06 17:38:38 -08001163 NR_STATUS_STRING_TO_INDEX.put("connected_mmwave", NR_CONNECTED_MMWAVE);
1164 NR_STATUS_STRING_TO_INDEX.put("connected", NR_CONNECTED);
SongFerngWang52dada72019-08-14 16:59:29 +08001165 NR_STATUS_STRING_TO_INDEX.put("not_restricted_rrc_idle", NR_NOT_RESTRICTED_RRC_IDLE);
1166 NR_STATUS_STRING_TO_INDEX.put("not_restricted_rrc_con", NR_NOT_RESTRICTED_RRC_CON);
Pengquan Menga62d32b2018-12-06 17:38:38 -08001167 NR_STATUS_STRING_TO_INDEX.put("restricted", NR_RESTRICTED);
1168 }
1169
Jason Monkd2263cd2014-11-10 14:22:56 -05001170 static Config readConfig(Context context) {
1171 Config config = new Config();
1172 Resources res = context.getResources();
1173
Jason Monkb5746272014-11-12 16:50:31 -05001174 config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
Jason Monkd2263cd2014-11-10 14:22:56 -05001175 config.alwaysShowCdmaRssi =
1176 res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
Jason Monkd2263cd2014-11-10 14:22:56 -05001177 config.hspaDataDistinguishable =
1178 res.getBoolean(R.bool.config_hspa_data_distinguishable);
Antony Sargentc026de32019-05-21 16:29:04 -07001179 config.inflateSignalStrengths = res.getBoolean(
1180 com.android.internal.R.bool.config_inflateSignalStrength);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001181
1182 CarrierConfigManager configMgr = (CarrierConfigManager)
1183 context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001184 // Handle specific carrier config values for the default data SIM
1185 int defaultDataSubId = SubscriptionManager.from(context)
1186 .getDefaultDataSubscriptionId();
1187 PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001188 if (b != null) {
1189 config.alwaysShowDataRatIcon = b.getBoolean(
1190 CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001191 config.show4gForLte = b.getBoolean(
1192 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
vagdevi3f2b9a52019-08-09 09:45:14 -07001193 config.show4gFor3g = b.getBoolean(
1194 CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001195 config.hideLtePlus = b.getBoolean(
1196 CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
SongFerngWang3cbcf752019-03-21 23:14:20 +08001197 config.patternOfCarrierSpecificDataIcon = b.getString(
1198 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
Pengquan Menga62d32b2018-12-06 17:38:38 -08001199 String nr5GIconConfiguration =
1200 b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
1201 if (!TextUtils.isEmpty(nr5GIconConfiguration)) {
1202 String[] nr5GIconConfigPairs = nr5GIconConfiguration.trim().split(",");
1203 for (String pair : nr5GIconConfigPairs) {
1204 add5GIconMapping(pair, config);
1205 }
1206 }
Bill Lin767c0db2019-08-15 20:42:06 +08001207 setDisplayGraceTime(
1208 b.getInt(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT),
1209 config);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001210 }
Pengquan Menga62d32b2018-12-06 17:38:38 -08001211
Jason Monkd2263cd2014-11-10 14:22:56 -05001212 return config;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001213 }
Pengquan Menga62d32b2018-12-06 17:38:38 -08001214
1215 /**
1216 * Add a mapping from NR 5G status to the 5G icon. All the icon resources come from
1217 * {@link TelephonyIcons}.
1218 *
1219 * @param keyValuePair the NR 5G status and icon name separated by a colon.
1220 * @param config container that used to store the parsed configs.
1221 */
1222 @VisibleForTesting
1223 static void add5GIconMapping(String keyValuePair, Config config) {
1224 String[] kv = (keyValuePair.trim().toLowerCase()).split(":");
1225
1226 if (kv.length != 2) {
1227 if (DEBUG) Log.e(TAG, "Invalid 5G icon configuration, config = " + keyValuePair);
1228 return;
1229 }
1230
1231 String key = kv[0], value = kv[1];
1232
1233 // There is no icon config for the specific 5G status.
1234 if (value.equals("none")) return;
1235
1236 if (NR_STATUS_STRING_TO_INDEX.containsKey(key)
1237 && TelephonyIcons.ICON_NAME_TO_ICON.containsKey(value)) {
1238 config.nr5GIconMap.put(
1239 NR_STATUS_STRING_TO_INDEX.get(key),
1240 TelephonyIcons.ICON_NAME_TO_ICON.get(value));
1241 }
1242 }
Bill Lin767c0db2019-08-15 20:42:06 +08001243
1244 /**
1245 * Set display gracefully period time(MS) depend on carrierConfig KEY
1246 * KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, and this function will convert to ms.
1247 * {@link CarrierConfigManager}.
1248 *
1249 * @param time showing 5G icon gracefully in the period of the time(SECOND)
1250 * @param config container that used to store the parsed configs.
1251 */
1252 @VisibleForTesting
1253 static void setDisplayGraceTime(int time, Config config) {
1254 config.nrIconDisplayGracePeriodMs = time * DateUtils.SECOND_IN_MILLIS;
1255 }
John Spurlockaf8d6c42014-05-07 17:49:08 -04001256 }
1257}