blob: 1c24bb9e88d14511c39b04594ad2318c76449475 [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;
John Spurlockaf8d6c42014-05-07 17:49:08 -040054import android.util.Log;
John Spurlockcf053c12015-05-14 16:33:59 -040055import android.util.MathUtils;
Jason Monk8996b942017-03-02 13:58:19 -050056import android.util.SparseArray;
Winsonc0d70582016-01-29 10:24:39 -080057
Evan Laird470ae842019-04-09 16:24:27 -040058import com.android.internal.annotations.GuardedBy;
Jason Monke0cdb602014-11-05 12:39:45 -050059import com.android.internal.annotations.VisibleForTesting;
Jason Monkb5746272014-11-12 16:50:31 -050060import com.android.internal.telephony.PhoneConstants;
John Spurlockaf8d6c42014-05-07 17:49:08 -040061import com.android.internal.telephony.TelephonyIntents;
Jason Monkf668d7c2016-01-14 10:38:41 -050062import com.android.settingslib.net.DataUsageController;
Jason Monk9c7844c2017-01-18 15:21:53 -050063import com.android.systemui.ConfigurationChangedReceiver;
John Spurlockaf8d6c42014-05-07 17:49:08 -040064import com.android.systemui.DemoMode;
Jason Monk9c7844c2017-01-18 15:21:53 -050065import com.android.systemui.Dumpable;
John Spurlockaf8d6c42014-05-07 17:49:08 -040066import com.android.systemui.R;
Jason Monk9c7844c2017-01-18 15:21:53 -050067import com.android.systemui.settings.CurrentUserTracker;
68import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
Pengquan Menga62d32b2018-12-06 17:38:38 -080069import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
John Spurlockaf8d6c42014-05-07 17:49:08 -040070
71import java.io.FileDescriptor;
72import java.io.PrintWriter;
73import java.util.ArrayList;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090074import java.util.BitSet;
Jason Monkb5746272014-11-12 16:50:31 -050075import java.util.Collections;
76import java.util.Comparator;
Pengquan Menga62d32b2018-12-06 17:38:38 -080077import java.util.HashMap;
John Spurlockaf8d6c42014-05-07 17:49:08 -040078import java.util.List;
79import java.util.Locale;
Pengquan Menga62d32b2018-12-06 17:38:38 -080080import java.util.Map;
John Spurlockaf8d6c42014-05-07 17:49:08 -040081
Jason Monk196d6392018-12-20 13:25:34 -050082import javax.inject.Inject;
83import javax.inject.Named;
84import javax.inject.Singleton;
85
John Spurlockaf8d6c42014-05-07 17:49:08 -040086/** Platform implementation of the network controller. **/
Jason Monk196d6392018-12-20 13:25:34 -050087@Singleton
John Spurlockaf8d6c42014-05-07 17:49:08 -040088public class NetworkControllerImpl extends BroadcastReceiver
Jason Monk9c7844c2017-01-18 15:21:53 -050089 implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider,
90 ConfigurationChangedReceiver, Dumpable {
John Spurlockaf8d6c42014-05-07 17:49:08 -040091 // debug
Jason Monkd2263cd2014-11-10 14:22:56 -050092 static final String TAG = "NetworkController";
93 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
94 // additional diagnostics, but not logspew
Jason Monk07b75fe2015-05-14 16:47:03 -040095 static final boolean CHATTY = Log.isLoggable(TAG + "Chat", Log.DEBUG);
John Spurlockaf8d6c42014-05-07 17:49:08 -040096
Jason Monk66845a32015-08-03 11:09:41 -040097 private static final int EMERGENCY_NO_CONTROLLERS = 0;
98 private static final int EMERGENCY_FIRST_CONTROLLER = 100;
99 private static final int EMERGENCY_VOICE_CONTROLLER = 200;
100 private static final int EMERGENCY_NO_SUB = 300;
Jason Monk8996b942017-03-02 13:58:19 -0500101 private static final int EMERGENCY_ASSUMED_VOICE_CONTROLLER = 400;
Jason Monk66845a32015-08-03 11:09:41 -0400102
Jason Monkd2263cd2014-11-10 14:22:56 -0500103 private final Context mContext;
104 private final TelephonyManager mPhone;
105 private final WifiManager mWifiManager;
106 private final ConnectivityManager mConnectivityManager;
Jason Monkb5746272014-11-12 16:50:31 -0500107 private final SubscriptionManager mSubscriptionManager;
Jason Monkd2263cd2014-11-10 14:22:56 -0500108 private final boolean mHasMobileDataFeature;
Jason Monkc6cc6262015-06-11 11:10:15 -0400109 private final SubscriptionDefaults mSubDefaults;
Jason Monk9a4ce132016-01-21 15:27:17 -0500110 private final DataSaverController mDataSaverController;
Jason Monk9c7844c2017-01-18 15:21:53 -0500111 private final CurrentUserTracker mUserTracker;
Evan Laird470ae842019-04-09 16:24:27 -0400112 private final Object mLock = new Object();
Jason Monk3aaabd72014-12-12 11:11:44 -0500113 private Config mConfig;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400114
Evan Laird470ae842019-04-09 16:24:27 -0400115 private PhoneStateListener mPhoneStateListener;
Malcolm Chen50ba9632019-02-26 16:49:56 -0800116 private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
117
Jason Monkd2263cd2014-11-10 14:22:56 -0500118 // Subcontrollers.
119 @VisibleForTesting
120 final WifiSignalController mWifiSignalController;
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900121
122 @VisibleForTesting
123 final EthernetSignalController mEthernetSignalController;
124
Jason Monkd2263cd2014-11-10 14:22:56 -0500125 @VisibleForTesting
Jason Monk8996b942017-03-02 13:58:19 -0500126 final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>();
Jason Monkb5746272014-11-12 16:50:31 -0500127 // When no SIMs are around at setup, and one is added later, it seems to default to the first
128 // SIM for most actions. This may be null if there aren't any SIMs around.
129 private MobileSignalController mDefaultSignalController;
Jason Monk0e2400f2014-11-21 11:08:55 -0500130 private final AccessPointControllerImpl mAccessPoints;
Jason Monkf668d7c2016-01-14 10:38:41 -0500131 private final DataUsageController mDataUsageController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400132
Jason Monkd2263cd2014-11-10 14:22:56 -0500133 private boolean mInetCondition; // Used for Logging and demo.
Lorenzo Colitti23dd1762014-09-10 22:58:54 +0900134
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900135 // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are
136 // connected and validated, respectively.
137 private final BitSet mConnectedTransports = new BitSet();
138 private final BitSet mValidatedTransports = new BitSet();
139
Jason Monkd2263cd2014-11-10 14:22:56 -0500140 // States that don't belong to a subcontroller.
John Spurlockaf8d6c42014-05-07 17:49:08 -0400141 private boolean mAirplaneMode = false;
Jason Monk1ff77662017-09-29 11:17:05 -0400142 private boolean mHasNoSubs;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400143 private Locale mLocale = null;
Jason Monkb5746272014-11-12 16:50:31 -0500144 // This list holds our ordering.
John Spurlockcf053c12015-05-14 16:33:59 -0400145 private List<SubscriptionInfo> mCurrentSubscriptions = new ArrayList<>();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400146
Jason Monkc014dec2014-12-12 11:49:55 -0500147 @VisibleForTesting
148 boolean mListening;
John Spurlock7f8f22a2014-07-02 18:54:17 -0400149
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900150 // The current user ID.
151 private int mCurrentUserId;
152
Jason Monk8fcab352015-06-29 10:57:00 -0400153 private OnSubscriptionsChangedListener mSubscriptionListener;
154
Jason Monk07b75fe2015-05-14 16:47:03 -0400155 // Handler that all broadcasts are received on.
156 private final Handler mReceiverHandler;
157 // Handler that all callbacks are made on.
158 private final CallbackHandler mCallbackHandler;
159
Jason Monk66845a32015-08-03 11:09:41 -0400160 private int mEmergencySource;
161 private boolean mIsEmergency;
162
Jason Monkb0808aa2015-07-22 16:34:36 -0400163 @VisibleForTesting
164 ServiceState mLastServiceState;
Jason Monkfd57ea72016-04-29 13:37:58 -0400165 private boolean mUserSetup;
Jason Monk1ff77662017-09-29 11:17:05 -0400166 private boolean mSimDetected;
Jason Monkb0808aa2015-07-22 16:34:36 -0400167
John Spurlockaf8d6c42014-05-07 17:49:08 -0400168 /**
169 * Construct this controller object and register for updates.
170 */
Jason Monk196d6392018-12-20 13:25:34 -0500171 @Inject
172 public NetworkControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
Jason Monk9c7844c2017-01-18 15:21:53 -0500173 DeviceProvisionedController deviceProvisionedController) {
Jason Monkf13b4b32014-11-07 16:39:34 -0500174 this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
175 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
Jason Monk29f7a7b2014-11-17 14:40:56 -0500176 (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
Sundeep Ghuman9d10a3c2017-06-16 00:05:16 +0000177 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400178 new CallbackHandler(),
Tony Mantler0edf09b2017-09-28 15:03:37 -0700179 new AccessPointControllerImpl(context),
Jason Monkf668d7c2016-01-14 10:38:41 -0500180 new DataUsageController(context),
Jason Monk9c7844c2017-01-18 15:21:53 -0500181 new SubscriptionDefaults(),
182 deviceProvisionedController);
Jason Monk07b75fe2015-05-14 16:47:03 -0400183 mReceiverHandler.post(mRegisterListeners);
Jason Monkf13b4b32014-11-07 16:39:34 -0500184 }
185
186 @VisibleForTesting
187 NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
Sundeep Ghuman9d10a3c2017-06-16 00:05:16 +0000188 TelephonyManager telephonyManager, WifiManager wifiManager,
189 SubscriptionManager subManager, Config config, Looper bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400190 CallbackHandler callbackHandler,
Jason Monkd2263cd2014-11-10 14:22:56 -0500191 AccessPointControllerImpl accessPointController,
Jason Monkf668d7c2016-01-14 10:38:41 -0500192 DataUsageController dataUsageController,
Jason Monk9c7844c2017-01-18 15:21:53 -0500193 SubscriptionDefaults defaultsHandler,
194 DeviceProvisionedController deviceProvisionedController) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400195 mContext = context;
Jason Monkb5746272014-11-12 16:50:31 -0500196 mConfig = config;
Jason Monk07b75fe2015-05-14 16:47:03 -0400197 mReceiverHandler = new Handler(bgLooper);
198 mCallbackHandler = callbackHandler;
Jason Monk9abca5e2016-11-11 16:18:14 -0500199 mDataSaverController = new DataSaverControllerImpl(context);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400200
Jason Monkb5746272014-11-12 16:50:31 -0500201 mSubscriptionManager = subManager;
Jason Monkc6cc6262015-06-11 11:10:15 -0400202 mSubDefaults = defaultsHandler;
Jason Monkf13b4b32014-11-07 16:39:34 -0500203 mConnectivityManager = connectivityManager;
204 mHasMobileDataFeature =
205 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400206
John Spurlockaf8d6c42014-05-07 17:49:08 -0400207 // telephony
Jason Monk07b75fe2015-05-14 16:47:03 -0400208 mPhone = telephonyManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400209
210 // wifi
Jason Monkf13b4b32014-11-07 16:39:34 -0500211 mWifiManager = wifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400212
Jason Monkd2263cd2014-11-10 14:22:56 -0500213 mLocale = mContext.getResources().getConfiguration().locale;
Jason Monk29f7a7b2014-11-17 14:40:56 -0500214 mAccessPoints = accessPointController;
Jason Monkf668d7c2016-01-14 10:38:41 -0500215 mDataUsageController = dataUsageController;
216 mDataUsageController.setNetworkController(this);
217 // TODO: Find a way to move this into DataUsageController.
218 mDataUsageController.setCallback(new DataUsageController.Callback() {
Jason Monke0cdb602014-11-05 12:39:45 -0500219 @Override
220 public void onMobileDataEnabled(boolean enabled) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400221 mCallbackHandler.setMobileDataEnabled(enabled);
Jason Monke0cdb602014-11-05 12:39:45 -0500222 }
223 });
Jason Monkd2263cd2014-11-10 14:22:56 -0500224 mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
Amin Shaikhc7593b12018-03-09 16:07:09 -0500225 mCallbackHandler, this, mWifiManager);
Jason Monkd2263cd2014-11-10 14:22:56 -0500226
Jason Monk07b75fe2015-05-14 16:47:03 -0400227 mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900228
Jason Monkd2263cd2014-11-10 14:22:56 -0500229 // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
Jason Monkb5746272014-11-12 16:50:31 -0500230 updateAirplaneMode(true /* force callback */);
Jason Monk9c7844c2017-01-18 15:21:53 -0500231 mUserTracker = new CurrentUserTracker(mContext) {
232 @Override
233 public void onUserSwitched(int newUserId) {
234 NetworkControllerImpl.this.onUserSwitched(newUserId);
235 }
236 };
237 mUserTracker.startTracking();
238 deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
239 @Override
240 public void onUserSetupChanged() {
241 setUserSetupComplete(deviceProvisionedController.isUserSetup(
242 deviceProvisionedController.getCurrentUser()));
243 }
244 });
Anarghya Mitra678722f2018-05-11 14:29:54 -0700245
246 ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){
247 private Network mLastNetwork;
248 private NetworkCapabilities mLastNetworkCapabilities;
249
250 @Override
251 public void onCapabilitiesChanged(
252 Network network, NetworkCapabilities networkCapabilities) {
253 boolean lastValidated = (mLastNetworkCapabilities != null) &&
254 mLastNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
255 boolean validated =
256 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
257
258 // This callback is invoked a lot (i.e. when RSSI changes), so avoid updating
259 // icons when connectivity state has remained the same.
260 if (network.equals(mLastNetwork) &&
261 networkCapabilities.equalsTransportTypes(mLastNetworkCapabilities) &&
262 validated == lastValidated) {
263 return;
264 }
265 mLastNetwork = network;
266 mLastNetworkCapabilities = networkCapabilities;
267 updateConnectivity();
268 }
269 };
270 // Even though this callback runs on the receiver handler thread which also processes the
271 // CONNECTIVITY_ACTION broadcasts, the broadcast and callback might come in at different
272 // times. This is safe since updateConnectivity() builds the list of transports from
273 // scratch.
274 // TODO: Move off of the deprecated CONNECTIVITY_ACTION broadcast and rely on callbacks
275 // exclusively for status bar icons.
276 mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
Evan Laird470ae842019-04-09 16:24:27 -0400277 // Register the listener on our bg looper
278 mPhoneStateListener = new PhoneStateListener(bgLooper) {
279 @Override
280 public void onActiveDataSubscriptionIdChanged(int subId) {
281 mActiveMobileDataSubscription = subId;
282 doUpdateMobileControllers();
283 }
284 };
Jason Monke0cdb602014-11-05 12:39:45 -0500285 }
286
Jason Monk9a4ce132016-01-21 15:27:17 -0500287 public DataSaverController getDataSaverController() {
288 return mDataSaverController;
289 }
290
Jason Monkf13b4b32014-11-07 16:39:34 -0500291 private void registerListeners() {
Jason Monk8996b942017-03-02 13:58:19 -0500292 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
293 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500294 mobileSignalController.registerListener();
295 }
Jason Monk8fcab352015-06-29 10:57:00 -0400296 if (mSubscriptionListener == null) {
297 mSubscriptionListener = new SubListener();
298 }
Wink Saville071743f2015-01-12 17:11:04 -0800299 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Malcolm Chen50ba9632019-02-26 16:49:56 -0800300 mPhone.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
Jason Monke0cdb602014-11-05 12:39:45 -0500301
John Spurlockaf8d6c42014-05-07 17:49:08 -0400302 // broadcasts
303 IntentFilter filter = new IntentFilter();
304 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
305 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
306 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
307 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jason Monkb5746272014-11-12 16:50:31 -0500308 filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
309 filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
Jason Monkb0808aa2015-07-22 16:34:36 -0400310 filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400311 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Erik Kline32830cc2015-04-21 13:09:15 +0900312 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400313 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400314 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
Wenting Xiong63364fe2017-02-07 19:12:27 +0800315 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
Jason Monk07b75fe2015-05-14 16:47:03 -0400316 mContext.registerReceiver(this, filter, null, mReceiverHandler);
Jason Monkb5746272014-11-12 16:50:31 -0500317 mListening = true;
318
319 updateMobileControllers();
John Spurlockb98f7472014-07-08 17:09:42 -0400320 }
321
Jason Monkd2263cd2014-11-10 14:22:56 -0500322 private void unregisterListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500323 mListening = false;
Jason Monk8996b942017-03-02 13:58:19 -0500324 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
325 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500326 mobileSignalController.unregisterListener();
327 }
Wink Saville071743f2015-01-12 17:11:04 -0800328 mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monkd2263cd2014-11-10 14:22:56 -0500329 mContext.unregisterReceiver(this);
Jason Monk5d325072014-10-27 11:38:47 -0400330 }
331
Jason Monk0e2400f2014-11-21 11:08:55 -0500332 public int getConnectedWifiLevel() {
333 return mWifiSignalController.getState().level;
334 }
335
Jason Monk5d325072014-10-27 11:38:47 -0400336 @Override
Jason Monkd2263cd2014-11-10 14:22:56 -0500337 public AccessPointController getAccessPointController() {
338 return mAccessPoints;
339 }
340
341 @Override
Jason Monkf668d7c2016-01-14 10:38:41 -0500342 public DataUsageController getMobileDataController() {
343 return mDataUsageController;
Jason Monkd2263cd2014-11-10 14:22:56 -0500344 }
345
346 public void addEmergencyListener(EmergencyListener listener) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400347 mCallbackHandler.setListening(listener, true);
348 mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400349 }
350
Jason Monk46dbfb42016-02-25 14:59:20 -0500351 public void removeEmergencyListener(EmergencyListener listener) {
352 mCallbackHandler.setListening(listener, false);
353 }
354
John Spurlockaf8d6c42014-05-07 17:49:08 -0400355 public boolean hasMobileDataFeature() {
356 return mHasMobileDataFeature;
357 }
358
359 public boolean hasVoiceCallingFeature() {
360 return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
361 }
362
Jason Monkb5746272014-11-12 16:50:31 -0500363 private MobileSignalController getDataController() {
Fabian Kozynskiccde55d2019-06-26 10:06:09 -0400364 int dataSubId = mSubDefaults.getActiveDataSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800365 if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
Jason Monkb5746272014-11-12 16:50:31 -0500366 if (DEBUG) Log.e(TAG, "No data sim selected");
367 return mDefaultSignalController;
368 }
Jason Monk8996b942017-03-02 13:58:19 -0500369 if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500370 return mMobileSignalControllers.get(dataSubId);
371 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500372 if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
Jason Monkb5746272014-11-12 16:50:31 -0500373 return mDefaultSignalController;
374 }
375
Amin Shaikh329c8282018-03-09 14:50:59 -0500376 @Override
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700377 public String getMobileDataNetworkName() {
Jason Monkb5746272014-11-12 16:50:31 -0500378 MobileSignalController controller = getDataController();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700379 return controller != null ? controller.getState().networkNameData : "";
Jason Monkd2263cd2014-11-10 14:22:56 -0500380 }
381
Fabian Kozynskif1c32a02019-03-22 15:09:30 -0400382 @Override
383 public int getNumberSubscriptions() {
384 return mMobileSignalControllers.size();
385 }
386
John Spurlockaf8d6c42014-05-07 17:49:08 -0400387 public boolean isEmergencyOnly() {
Jason Monkb0808aa2015-07-22 16:34:36 -0400388 if (mMobileSignalControllers.size() == 0) {
389 // When there are no active subscriptions, determine emengency state from last
390 // broadcast.
Jason Monk66845a32015-08-03 11:09:41 -0400391 mEmergencySource = EMERGENCY_NO_CONTROLLERS;
Jason Monkb0808aa2015-07-22 16:34:36 -0400392 return mLastServiceState != null && mLastServiceState.isEmergencyOnly();
393 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400394 int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800395 if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
Jason Monk8996b942017-03-02 13:58:19 -0500396 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
397 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkc6cc6262015-06-11 11:10:15 -0400398 if (!mobileSignalController.getState().isEmergency) {
Jason Monk66845a32015-08-03 11:09:41 -0400399 mEmergencySource = EMERGENCY_FIRST_CONTROLLER
400 + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400401 if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag);
Jason Monkb5746272014-11-12 16:50:31 -0500402 return false;
403 }
404 }
405 }
Jason Monk8996b942017-03-02 13:58:19 -0500406 if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) {
Jason Monk66845a32015-08-03 11:09:41 -0400407 mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
Jason Monkc6cc6262015-06-11 11:10:15 -0400408 if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
409 return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
Jason Monkb5746272014-11-12 16:50:31 -0500410 }
Jason Monk8996b942017-03-02 13:58:19 -0500411 // If we have the wrong subId but there is only one sim anyway, assume it should be the
412 // default.
413 if (mMobileSignalControllers.size() == 1) {
414 mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER
415 + mMobileSignalControllers.keyAt(0);
416 if (DEBUG) Log.d(TAG, "Getting assumed emergency from "
417 + mMobileSignalControllers.keyAt(0));
418 return mMobileSignalControllers.valueAt(0).getState().isEmergency;
419 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500420 if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
Jason Monk66845a32015-08-03 11:09:41 -0400421 mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
Jason Monkb5746272014-11-12 16:50:31 -0500422 // Something is wrong, better assume we can't make calls...
423 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400424 }
425
Jason Monkd2263cd2014-11-10 14:22:56 -0500426 /**
427 * Emergency status may have changed (triggered by MobileSignalController),
428 * so we should recheck and send out the state to listeners.
429 */
430 void recalculateEmergency() {
Jason Monk66845a32015-08-03 11:09:41 -0400431 mIsEmergency = isEmergencyOnly();
432 mCallbackHandler.setEmergencyCallsOnly(mIsEmergency);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400433 }
434
Jason Monk88529052016-11-04 13:29:58 -0400435 public void addCallback(SignalCallback cb) {
Jason Monke06b0652016-03-02 16:35:27 -0500436 cb.setSubs(mCurrentSubscriptions);
437 cb.setIsAirplaneMode(new IconState(mAirplaneMode,
Jason Monk07b75fe2015-05-14 16:47:03 -0400438 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monk1ff77662017-09-29 11:17:05 -0400439 cb.setNoSims(mHasNoSubs, mSimDetected);
Jason Monke06b0652016-03-02 16:35:27 -0500440 mWifiSignalController.notifyListeners(cb);
441 mEthernetSignalController.notifyListeners(cb);
Jason Monk8996b942017-03-02 13:58:19 -0500442 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
443 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monke06b0652016-03-02 16:35:27 -0500444 mobileSignalController.notifyListeners(cb);
Jason Monkb5746272014-11-12 16:50:31 -0500445 }
Jason Monke06b0652016-03-02 16:35:27 -0500446 mCallbackHandler.setListening(cb, true);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400447 }
448
Jason Monk07b75fe2015-05-14 16:47:03 -0400449 @Override
Jason Monk88529052016-11-04 13:29:58 -0400450 public void removeCallback(SignalCallback cb) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400451 mCallbackHandler.setListening(cb, false);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400452 }
453
454 @Override
455 public void setWifiEnabled(final boolean enabled) {
456 new AsyncTask<Void, Void, Void>() {
457 @Override
458 protected Void doInBackground(Void... args) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400459 mWifiManager.setWifiEnabled(enabled);
460 return null;
461 }
462 }.execute();
463 }
464
Jason Monk9c7844c2017-01-18 15:21:53 -0500465 private void onUserSwitched(int newUserId) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900466 mCurrentUserId = newUserId;
467 mAccessPoints.onUserSwitched(newUserId);
468 updateConnectivity();
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900469 }
470
471 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400472 public void onReceive(Context context, Intent intent) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500473 if (CHATTY) {
474 Log.d(TAG, "onReceive: intent=" + intent);
475 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400476 final String action = intent.getAction();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800477 switch (action) {
478 case ConnectivityManager.CONNECTIVITY_ACTION:
479 case ConnectivityManager.INET_CONDITION_ACTION:
480 updateConnectivity();
481 break;
482 case Intent.ACTION_AIRPLANE_MODE_CHANGED:
483 refreshLocale();
484 updateAirplaneMode(false);
485 break;
486 case TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
487 // We are using different subs now, we might be able to make calls.
Jason Monkb0808aa2015-07-22 16:34:36 -0400488 recalculateEmergency();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800489 break;
490 case TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
491 // Notify every MobileSignalController so they can know whether they are the
492 // data sim or not.
493 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
494 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
495 controller.handleBroadcast(intent);
Wenting Xiong63364fe2017-02-07 19:12:27 +0800496 }
Niklas Lindgrena02964d2018-09-21 14:01:57 +0200497 mConfig = Config.readConfig(mContext);
498 mReceiverHandler.post(this::handleConfigurationChanged);
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800499 break;
500 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
501 // Avoid rebroadcast because SysUI is direct boot aware.
502 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
503 break;
504 }
505 // Might have different subscriptions now.
506 updateMobileControllers();
507 break;
508 case TelephonyIntents.ACTION_SERVICE_STATE_CHANGED:
509 mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
510 if (mMobileSignalControllers.size() == 0) {
511 // If none of the subscriptions are active, we might need to recalculate
512 // emergency state.
513 recalculateEmergency();
514 }
515 break;
516 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
517 mConfig = Config.readConfig(mContext);
518 mReceiverHandler.post(this::handleConfigurationChanged);
519 break;
520 default:
521 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
522 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
523 if (SubscriptionManager.isValidSubscriptionId(subId)) {
524 if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
525 mMobileSignalControllers.get(subId).handleBroadcast(intent);
526 } else {
527 // Can't find this subscription... We must be out of date.
528 updateMobileControllers();
529 }
Jason Monkb5746272014-11-12 16:50:31 -0500530 } else {
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800531 // No sub id, must be for the wifi.
532 mWifiSignalController.handleBroadcast(intent);
Jason Monkb5746272014-11-12 16:50:31 -0500533 }
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800534 break;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400535 }
Jason Monkb5746272014-11-12 16:50:31 -0500536 }
537
Jason Monk9c7844c2017-01-18 15:21:53 -0500538 public void onConfigurationChanged(Configuration newConfig) {
Sungmin Choi6be4f6b2015-07-07 13:06:59 +0900539 mConfig = Config.readConfig(mContext);
Jason Monk1c040db2015-07-20 09:45:54 -0400540 mReceiverHandler.post(new Runnable() {
541 @Override
542 public void run() {
543 handleConfigurationChanged();
544 }
545 });
546 }
547
548 @VisibleForTesting
549 void handleConfigurationChanged() {
Malcolm Chen50ba9632019-02-26 16:49:56 -0800550 updateMobileControllers();
Jason Monk8996b942017-03-02 13:58:19 -0500551 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
552 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
553 controller.setConfiguration(mConfig);
Jason Monk3aaabd72014-12-12 11:11:44 -0500554 }
555 refreshLocale();
Jason Monk3aaabd72014-12-12 11:11:44 -0500556 }
557
Jason Monkb5746272014-11-12 16:50:31 -0500558 private void updateMobileControllers() {
559 if (!mListening) {
560 return;
561 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400562 doUpdateMobileControllers();
563 }
564
Malcolm Chen50ba9632019-02-26 16:49:56 -0800565 private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) {
566 if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) {
567 SubscriptionInfo info1 = subscriptions.get(0);
568 SubscriptionInfo info2 = subscriptions.get(1);
569 if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) {
570 // If both subscriptions are primary, show both.
571 if (!info1.isOpportunistic() && !info2.isOpportunistic()) return;
572
573 // If carrier required, always show signal bar of primary subscription.
574 // Otherwise, show whichever subscription is currently active for Internet.
575 boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig()
576 .getBoolean(CarrierConfigManager
577 .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN);
578 if (alwaysShowPrimary) {
579 subscriptions.remove(info1.isOpportunistic() ? info1 : info2);
580 } else {
581 subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription
582 ? info2 : info1);
583 }
584 }
585 }
586 }
587
Jason Monkc6cc6262015-06-11 11:10:15 -0400588 @VisibleForTesting
589 void doUpdateMobileControllers() {
Malcolm Chend2d400cb2018-12-21 17:11:10 -0800590 List<SubscriptionInfo> subscriptions = mSubscriptionManager
Malcolm Chen50ba9632019-02-26 16:49:56 -0800591 .getActiveSubscriptionInfoList(false);
Jason Monkc9f05712014-12-15 12:24:10 -0500592 if (subscriptions == null) {
593 subscriptions = Collections.emptyList();
594 }
Malcolm Chen50ba9632019-02-26 16:49:56 -0800595
596 filterMobileSubscriptionInSameGroup(subscriptions);
597
Jason Monkb5746272014-11-12 16:50:31 -0500598 // If there have been no relevant changes to any of the subscriptions, we can leave as is.
599 if (hasCorrectMobileControllers(subscriptions)) {
600 // Even if the controllers are correct, make sure we have the right no sims state.
601 // Such as on boot, don't need any controllers, because there are no sims,
602 // but we still need to update the no sim state.
603 updateNoSims();
604 return;
605 }
Evan Laird470ae842019-04-09 16:24:27 -0400606 synchronized (mLock) {
607 setCurrentSubscriptionsLocked(subscriptions);
608 }
Jason Monkb5746272014-11-12 16:50:31 -0500609 updateNoSims();
Jason Monkc6cc6262015-06-11 11:10:15 -0400610 recalculateEmergency();
Jason Monkb5746272014-11-12 16:50:31 -0500611 }
612
Jason Monk21d05a02014-12-02 12:46:58 -0500613 @VisibleForTesting
614 protected void updateNoSims() {
Jason Monk1ff77662017-09-29 11:17:05 -0400615 boolean hasNoSubs = mHasMobileDataFeature && mMobileSignalControllers.size() == 0;
616 boolean simDetected = hasAnySim();
617 if (hasNoSubs != mHasNoSubs || simDetected != mSimDetected) {
618 mHasNoSubs = hasNoSubs;
619 mSimDetected = simDetected;
620 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
Jason Monkb5746272014-11-12 16:50:31 -0500621 }
622 }
623
Jason Monk1ff77662017-09-29 11:17:05 -0400624 private boolean hasAnySim() {
625 int simCount = mPhone.getSimCount();
626 for (int i = 0; i < simCount; i++) {
627 int state = mPhone.getSimState(i);
628 if (state != TelephonyManager.SIM_STATE_ABSENT
629 && state != TelephonyManager.SIM_STATE_UNKNOWN) {
630 return true;
631 }
632 }
633 return false;
634 }
635
Evan Laird470ae842019-04-09 16:24:27 -0400636 @GuardedBy("mLock")
Jason Monkb5746272014-11-12 16:50:31 -0500637 @VisibleForTesting
Evan Laird470ae842019-04-09 16:24:27 -0400638 public void setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions) {
Jason Monkb5746272014-11-12 16:50:31 -0500639 Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() {
640 @Override
641 public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) {
642 return lhs.getSimSlotIndex() == rhs.getSimSlotIndex()
643 ? lhs.getSubscriptionId() - rhs.getSubscriptionId()
644 : lhs.getSimSlotIndex() - rhs.getSimSlotIndex();
645 }
646 });
Jason Monkb5746272014-11-12 16:50:31 -0500647 mCurrentSubscriptions = subscriptions;
648
Jason Monk8996b942017-03-02 13:58:19 -0500649 SparseArray<MobileSignalController> cachedControllers =
650 new SparseArray<MobileSignalController>();
651 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
652 cachedControllers.put(mMobileSignalControllers.keyAt(i),
653 mMobileSignalControllers.valueAt(i));
654 }
Jason Monkb5746272014-11-12 16:50:31 -0500655 mMobileSignalControllers.clear();
656 final int num = subscriptions.size();
657 for (int i = 0; i < num; i++) {
658 int subId = subscriptions.get(i).getSubscriptionId();
659 // If we have a copy of this controller already reuse it, otherwise make a new one.
Jason Monk8996b942017-03-02 13:58:19 -0500660 if (cachedControllers.indexOfKey(subId) >= 0) {
661 mMobileSignalControllers.put(subId, cachedControllers.get(subId));
662 cachedControllers.remove(subId);
Jason Monkb5746272014-11-12 16:50:31 -0500663 } else {
664 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
chen xu84a90872019-03-28 15:44:12 -0700665 mHasMobileDataFeature, mPhone.createForSubscriptionId(subId),
666 mCallbackHandler, this, subscriptions.get(i),
667 mSubDefaults, mReceiverHandler.getLooper());
Jason Monkfd57ea72016-04-29 13:37:58 -0400668 controller.setUserSetupComplete(mUserSetup);
Jason Monkb5746272014-11-12 16:50:31 -0500669 mMobileSignalControllers.put(subId, controller);
670 if (subscriptions.get(i).getSimSlotIndex() == 0) {
671 mDefaultSignalController = controller;
672 }
673 if (mListening) {
674 controller.registerListener();
675 }
676 }
677 }
678 if (mListening) {
Jason Monk8996b942017-03-02 13:58:19 -0500679 for (int i = 0; i < cachedControllers.size(); i++) {
680 int key = cachedControllers.keyAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500681 if (cachedControllers.get(key) == mDefaultSignalController) {
682 mDefaultSignalController = null;
683 }
684 cachedControllers.get(key).unregisterListener();
685 }
686 }
Jason Monk8fcab352015-06-29 10:57:00 -0400687 mCallbackHandler.setSubs(subscriptions);
688 notifyAllListeners();
689
Jason Monk25d8a482014-12-09 12:27:24 -0500690 // There may be new MobileSignalControllers around, make sure they get the current
691 // inet condition and airplane mode.
692 pushConnectivityToSignals();
693 updateAirplaneMode(true /* force */);
Jason Monkb5746272014-11-12 16:50:31 -0500694 }
695
Jason Monk0288de02017-02-23 14:48:05 -0500696 private void setUserSetupComplete(final boolean userSetup) {
697 mReceiverHandler.post(() -> handleSetUserSetupComplete(userSetup));
Jason Monkfd57ea72016-04-29 13:37:58 -0400698 }
699
Jason Monk0288de02017-02-23 14:48:05 -0500700 private void handleSetUserSetupComplete(boolean userSetup) {
Jason Monkfd57ea72016-04-29 13:37:58 -0400701 mUserSetup = userSetup;
Jason Monk8996b942017-03-02 13:58:19 -0500702 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
703 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkfd57ea72016-04-29 13:37:58 -0400704 controller.setUserSetupComplete(mUserSetup);
705 }
706 }
707
Jason Monkc014dec2014-12-12 11:49:55 -0500708 @VisibleForTesting
709 boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) {
Jason Monkc9f05712014-12-15 12:24:10 -0500710 if (allSubscriptions.size() != mMobileSignalControllers.size()) {
711 return false;
Jason Monkb5746272014-11-12 16:50:31 -0500712 }
713 for (SubscriptionInfo info : allSubscriptions) {
Jason Monk8996b942017-03-02 13:58:19 -0500714 if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500715 return false;
716 }
717 }
718 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400719 }
720
Jason Monkd2263cd2014-11-10 14:22:56 -0500721 private void updateAirplaneMode(boolean force) {
722 boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
723 Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
724 if (airplaneMode != mAirplaneMode || force) {
725 mAirplaneMode = airplaneMode;
Jason Monk8996b942017-03-02 13:58:19 -0500726 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
727 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500728 mobileSignalController.setAirplaneMode(mAirplaneMode);
729 }
730 notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400731 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400732 }
733
734 private void refreshLocale() {
Jason Monkd2263cd2014-11-10 14:22:56 -0500735 Locale current = mContext.getResources().getConfiguration().locale;
Jason Monkb5746272014-11-12 16:50:31 -0500736 if (!current.equals(mLocale)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500737 mLocale = current;
Fabian Kozynskid9cb3842018-09-28 13:34:14 -0400738 mWifiSignalController.refreshLocale();
Jason Monkd2263cd2014-11-10 14:22:56 -0500739 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400740 }
741 }
742
Jason Monkd2263cd2014-11-10 14:22:56 -0500743 /**
Jason Monkb5746272014-11-12 16:50:31 -0500744 * Forces update of all callbacks on both SignalClusters and
745 * NetworkSignalChangedCallbacks.
746 */
Jason Monkd2263cd2014-11-10 14:22:56 -0500747 private void notifyAllListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500748 notifyListeners();
Jason Monk8996b942017-03-02 13:58:19 -0500749 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
750 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500751 mobileSignalController.notifyListeners();
752 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500753 mWifiSignalController.notifyListeners();
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900754 mEthernetSignalController.notifyListeners();
Jason Monkd2263cd2014-11-10 14:22:56 -0500755 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400756
Jason Monkb5746272014-11-12 16:50:31 -0500757 /**
758 * Notifies listeners of changes in state of to the NetworkController, but
759 * does not notify for any info on SignalControllers, for that call
760 * notifyAllListeners.
761 */
762 private void notifyListeners() {
Jason Monk07b75fe2015-05-14 16:47:03 -0400763 mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
764 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monk1ff77662017-09-29 11:17:05 -0400765 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400766 }
767
Jason Monkd2263cd2014-11-10 14:22:56 -0500768 /**
769 * Update the Inet conditions and what network we are connected to.
770 */
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900771 private void updateConnectivity() {
772 mConnectedTransports.clear();
773 mValidatedTransports.clear();
774 for (NetworkCapabilities nc :
775 mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
776 for (int transportType : nc.getTransportTypes()) {
777 mConnectedTransports.set(transportType);
778 if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
779 mValidatedTransports.set(transportType);
780 }
781 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400782 }
783
John Spurlockaf8d6c42014-05-07 17:49:08 -0400784 if (CHATTY) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900785 Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
786 Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400787 }
788
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900789 mInetCondition = !mValidatedTransports.isEmpty();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400790
Jason Monk25d8a482014-12-09 12:27:24 -0500791 pushConnectivityToSignals();
792 }
793
794 /**
795 * Pushes the current connectivity state to all SignalControllers.
796 */
797 private void pushConnectivityToSignals() {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400798 // We want to update all the icons, all at once, for any condition change
Jason Monk8996b942017-03-02 13:58:19 -0500799 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
800 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400801 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
Jason Monkb5746272014-11-12 16:50:31 -0500802 }
Jason Monk33f8ae72015-05-08 10:45:15 -0400803 mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
804 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400805 }
806
John Spurlockaf8d6c42014-05-07 17:49:08 -0400807 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
808 pw.println("NetworkController state:");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900809
John Spurlockaf8d6c42014-05-07 17:49:08 -0400810 pw.println(" - telephony ------");
811 pw.print(" hasVoiceCallingFeature()=");
812 pw.println(hasVoiceCallingFeature());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400813
John Spurlockaf8d6c42014-05-07 17:49:08 -0400814 pw.println(" - connectivity ------");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900815 pw.print(" mConnectedTransports=");
816 pw.println(mConnectedTransports);
817 pw.print(" mValidatedTransports=");
818 pw.println(mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400819 pw.print(" mInetCondition=");
820 pw.println(mInetCondition);
Jason Monkd2263cd2014-11-10 14:22:56 -0500821 pw.print(" mAirplaneMode=");
822 pw.println(mAirplaneMode);
823 pw.print(" mLocale=");
824 pw.println(mLocale);
Jason Monkb0808aa2015-07-22 16:34:36 -0400825 pw.print(" mLastServiceState=");
826 pw.println(mLastServiceState);
Jason Monk66845a32015-08-03 11:09:41 -0400827 pw.print(" mIsEmergency=");
828 pw.println(mIsEmergency);
829 pw.print(" mEmergencySource=");
830 pw.println(emergencyToString(mEmergencySource));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400831
Jason Monk8996b942017-03-02 13:58:19 -0500832 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
833 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500834 mobileSignalController.dump(pw);
835 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500836 mWifiSignalController.dump(pw);
Jason Monkd52356a2015-01-28 10:40:41 -0500837
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900838 mEthernetSignalController.dump(pw);
839
Jason Monkd52356a2015-01-28 10:40:41 -0500840 mAccessPoints.dump(pw);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400841 }
842
Jason Monk66845a32015-08-03 11:09:41 -0400843 private static final String emergencyToString(int emergencySource) {
844 if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk8996b942017-03-02 13:58:19 -0500845 return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER)
846 + ")";
847 } else if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk66845a32015-08-03 11:09:41 -0400848 return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
849 } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
850 return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
851 } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) {
852 return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")";
853 } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) {
854 return "NO_CONTROLLERS";
855 }
856 return "UNKNOWN_SOURCE";
857 }
858
John Spurlockaf8d6c42014-05-07 17:49:08 -0400859 private boolean mDemoMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400860 private boolean mDemoInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500861 private WifiSignalController.WifiState mDemoWifiState;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400862
863 @Override
864 public void dispatchDemoCommand(String command, Bundle args) {
865 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500866 if (DEBUG) Log.d(TAG, "Entering demo mode");
867 unregisterListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400868 mDemoMode = true;
Jason Monk33f8ae72015-05-08 10:45:15 -0400869 mDemoInetCondition = mInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500870 mDemoWifiState = mWifiSignalController.getState();
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100871 mDemoWifiState.ssid = "DemoMode";
John Spurlockaf8d6c42014-05-07 17:49:08 -0400872 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500873 if (DEBUG) Log.d(TAG, "Exiting demo mode");
John Spurlockaf8d6c42014-05-07 17:49:08 -0400874 mDemoMode = false;
Jason Monkb5746272014-11-12 16:50:31 -0500875 // Update what MobileSignalControllers, because they may change
876 // to set the number of sim slots.
877 updateMobileControllers();
Jason Monk8996b942017-03-02 13:58:19 -0500878 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
879 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500880 controller.resetLastState();
881 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500882 mWifiSignalController.resetLastState();
Jason Monk07b75fe2015-05-14 16:47:03 -0400883 mReceiverHandler.post(mRegisterListeners);
Jason Monkd2263cd2014-11-10 14:22:56 -0500884 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400885 } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
886 String airplane = args.getString("airplane");
887 if (airplane != null) {
888 boolean show = airplane.equals("show");
Jason Monk07b75fe2015-05-14 16:47:03 -0400889 mCallbackHandler.setIsAirplaneMode(new IconState(show,
890 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode,
891 mContext));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400892 }
893 String fully = args.getString("fully");
894 if (fully != null) {
Jason Monk33f8ae72015-05-08 10:45:15 -0400895 mDemoInetCondition = Boolean.parseBoolean(fully);
896 BitSet connected = new BitSet();
897
898 if (mDemoInetCondition) {
899 connected.set(mWifiSignalController.mTransportType);
900 }
901 mWifiSignalController.updateConnectivity(connected, connected);
Jason Monk8996b942017-03-02 13:58:19 -0500902 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
903 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400904 if (mDemoInetCondition) {
905 connected.set(controller.mTransportType);
906 }
907 controller.updateConnectivity(connected, connected);
Jason Monkb5746272014-11-12 16:50:31 -0500908 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400909 }
910 String wifi = args.getString("wifi");
911 if (wifi != null) {
912 boolean show = wifi.equals("show");
913 String level = args.getString("level");
914 if (level != null) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500915 mDemoWifiState.level = level.equals("null") ? -1
John Spurlockaf8d6c42014-05-07 17:49:08 -0400916 : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
Jason Monkd2263cd2014-11-10 14:22:56 -0500917 mDemoWifiState.connected = mDemoWifiState.level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400918 }
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100919 String activity = args.getString("activity");
920 if (activity != null) {
921 switch (activity) {
922 case "inout":
Roshan Pius80fb1372018-07-16 15:43:03 -0700923 mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100924 break;
925 case "in":
Roshan Pius80fb1372018-07-16 15:43:03 -0700926 mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100927 break;
928 case "out":
Roshan Pius80fb1372018-07-16 15:43:03 -0700929 mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100930 break;
931 default:
Roshan Pius80fb1372018-07-16 15:43:03 -0700932 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100933 break;
934 }
935 } else {
Roshan Pius80fb1372018-07-16 15:43:03 -0700936 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100937 }
Evan Laird27a99572017-09-27 14:09:30 -0400938 String ssid = args.getString("ssid");
939 if (ssid != null) {
940 mDemoWifiState.ssid = ssid;
941 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500942 mDemoWifiState.enabled = show;
943 mWifiSignalController.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400944 }
Jason Monkb5746272014-11-12 16:50:31 -0500945 String sims = args.getString("sims");
946 if (sims != null) {
John Spurlockcf053c12015-05-14 16:33:59 -0400947 int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
948 List<SubscriptionInfo> subs = new ArrayList<>();
Jason Monkb5746272014-11-12 16:50:31 -0500949 if (num != mMobileSignalControllers.size()) {
950 mMobileSignalControllers.clear();
951 int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
952 for (int i = start /* get out of normal index range */; i < start + num; i++) {
John Spurlockcf053c12015-05-14 16:33:59 -0400953 subs.add(addSignalController(i, i));
Jason Monkb5746272014-11-12 16:50:31 -0500954 }
Jason Monk33b60bb2015-07-13 10:42:23 -0400955 mCallbackHandler.setSubs(subs);
Evan Lairde1d13c92018-03-20 16:58:01 -0400956 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
957 int key = mMobileSignalControllers.keyAt(i);
958 MobileSignalController controller = mMobileSignalControllers.get(key);
959 controller.notifyListeners();
960 }
Jason Monkb5746272014-11-12 16:50:31 -0500961 }
Jason Monkb5746272014-11-12 16:50:31 -0500962 }
963 String nosim = args.getString("nosim");
964 if (nosim != null) {
Jason Monk1ff77662017-09-29 11:17:05 -0400965 mHasNoSubs = nosim.equals("show");
966 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
Jason Monkb5746272014-11-12 16:50:31 -0500967 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400968 String mobile = args.getString("mobile");
969 if (mobile != null) {
970 boolean show = mobile.equals("show");
971 String datatype = args.getString("datatype");
Jason Monkb5746272014-11-12 16:50:31 -0500972 String slotString = args.getString("slot");
973 int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
John Spurlockcf053c12015-05-14 16:33:59 -0400974 slot = MathUtils.constrain(slot, 0, 8);
975 // Ensure we have enough sim slots
976 List<SubscriptionInfo> subs = new ArrayList<>();
977 while (mMobileSignalControllers.size() <= slot) {
978 int nextSlot = mMobileSignalControllers.size();
979 subs.add(addSignalController(nextSlot, nextSlot));
980 }
981 if (!subs.isEmpty()) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400982 mCallbackHandler.setSubs(subs);
John Spurlockcf053c12015-05-14 16:33:59 -0400983 }
Jason Monkb5746272014-11-12 16:50:31 -0500984 // Hack to index linearly for easy use.
Jason Monk8996b942017-03-02 13:58:19 -0500985 MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
Jason Monkb5746272014-11-12 16:50:31 -0500986 controller.getState().dataSim = datatype != null;
Jason Monkb5950982017-01-24 15:53:53 -0500987 controller.getState().isDefault = datatype != null;
988 controller.getState().dataConnected = datatype != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400989 if (datatype != null) {
Jason Monkb5746272014-11-12 16:50:31 -0500990 controller.getState().iconGroup =
Jason Monkd2263cd2014-11-10 14:22:56 -0500991 datatype.equals("1x") ? TelephonyIcons.ONE_X :
992 datatype.equals("3g") ? TelephonyIcons.THREE_G :
993 datatype.equals("4g") ? TelephonyIcons.FOUR_G :
Ajay Nambi7965fa42015-05-14 18:48:33 -0700994 datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -0500995 datatype.equals("e") ? TelephonyIcons.E :
996 datatype.equals("g") ? TelephonyIcons.G :
997 datatype.equals("h") ? TelephonyIcons.H :
Amin Shaikhf5830ca2018-03-09 14:06:50 -0500998 datatype.equals("h+") ? TelephonyIcons.H_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -0500999 datatype.equals("lte") ? TelephonyIcons.LTE :
Jason Monkaa730be2016-07-13 14:22:52 -04001000 datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
Jason Monk7e6c83c2017-04-26 14:35:24 -04001001 datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -04001002 datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA :
Jason Monkd2263cd2014-11-10 14:22:56 -05001003 TelephonyIcons.UNKNOWN;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001004 }
Jason Monk0f0de132016-12-19 15:36:13 -05001005 if (args.containsKey("roam")) {
1006 controller.getState().roaming = "show".equals(args.getString("roam"));
1007 }
John Spurlockaf8d6c42014-05-07 17:49:08 -04001008 String level = args.getString("level");
1009 if (level != null) {
Jason Monkb5746272014-11-12 16:50:31 -05001010 controller.getState().level = level.equals("null") ? -1
Jason Monk48edc0c2017-04-10 15:01:27 -04001011 : Math.min(Integer.parseInt(level),
1012 SignalStrength.NUM_SIGNAL_STRENGTH_BINS);
Jason Monkb5746272014-11-12 16:50:31 -05001013 controller.getState().connected = controller.getState().level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001014 }
Amin Shaikh0ad7e512019-04-29 07:36:34 -04001015 if (args.containsKey("inflate")) {
1016 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
1017 mMobileSignalControllers.valueAt(i).mInflateSignalStrengths =
1018 "true".equals(args.getString("inflate"));
1019 }
1020 }
Jason Monk0f0de132016-12-19 15:36:13 -05001021 String activity = args.getString("activity");
1022 if (activity != null) {
Kenneth Westin5c88ffb2013-11-28 16:29:40 +01001023 controller.getState().dataConnected = true;
1024 switch (activity) {
1025 case "inout":
1026 controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
1027 break;
1028 case "in":
1029 controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
1030 break;
1031 case "out":
1032 controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
1033 break;
1034 default:
1035 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
1036 break;
1037 }
1038 } else {
1039 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
Jason Monk0f0de132016-12-19 15:36:13 -05001040 }
Jason Monkb5746272014-11-12 16:50:31 -05001041 controller.getState().enabled = show;
1042 controller.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -04001043 }
Andrew Flynna478d702015-04-14 23:33:45 -04001044 String carrierNetworkChange = args.getString("carriernetworkchange");
1045 if (carrierNetworkChange != null) {
1046 boolean show = carrierNetworkChange.equals("show");
Jason Monk8996b942017-03-02 13:58:19 -05001047 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
1048 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Andrew Flynna478d702015-04-14 23:33:45 -04001049 controller.setCarrierNetworkChangeMode(show);
1050 }
1051 }
Jason Monkd2263cd2014-11-10 14:22:56 -05001052 }
1053 }
1054
John Spurlockcf053c12015-05-14 16:33:59 -04001055 private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
1056 SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
Malcolm Chene89e0ce2018-08-09 17:01:35 -07001057 null, null, null, "", false, null, null);
Jason Monkb5950982017-01-24 15:53:53 -05001058 MobileSignalController controller = new MobileSignalController(mContext,
chen xu84a90872019-03-28 15:44:12 -07001059 mConfig, mHasMobileDataFeature,
1060 mPhone.createForSubscriptionId(info.getSubscriptionId()), mCallbackHandler, this, info,
Jason Monkb5950982017-01-24 15:53:53 -05001061 mSubDefaults, mReceiverHandler.getLooper());
1062 mMobileSignalControllers.put(id, controller);
1063 controller.getState().userSetup = true;
John Spurlockcf053c12015-05-14 16:33:59 -04001064 return info;
1065 }
1066
Adrian Roos316bf542016-08-23 17:53:07 +02001067 public boolean hasEmergencyCryptKeeperText() {
1068 return EncryptionHelper.IS_DATA_ENCRYPTED;
1069 }
1070
1071 public boolean isRadioOn() {
1072 return !mAirplaneMode;
1073 }
1074
Jason Monk8fcab352015-06-29 10:57:00 -04001075 private class SubListener extends OnSubscriptionsChangedListener {
Jason Monkc9f05712014-12-15 12:24:10 -05001076 @Override
1077 public void onSubscriptionsChanged() {
Jason Monkb5746272014-11-12 16:50:31 -05001078 updateMobileControllers();
Jason Monk8fcab352015-06-29 10:57:00 -04001079 }
1080 }
Jason Monkb5746272014-11-12 16:50:31 -05001081
Jason Monk07b75fe2015-05-14 16:47:03 -04001082 /**
1083 * Used to register listeners from the BG Looper, this way the PhoneStateListeners that
1084 * get created will also run on the BG Looper.
1085 */
1086 private final Runnable mRegisterListeners = new Runnable() {
1087 @Override
1088 public void run() {
1089 registerListeners();
1090 }
1091 };
Jason Monkd2263cd2014-11-10 14:22:56 -05001092
Jason Monkc6cc6262015-06-11 11:10:15 -04001093 public static class SubscriptionDefaults {
1094 public int getDefaultVoiceSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -08001095 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -04001096 }
1097
1098 public int getDefaultDataSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -08001099 return SubscriptionManager.getDefaultDataSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -04001100 }
Fabian Kozynskiccde55d2019-06-26 10:06:09 -04001101
1102 public int getActiveDataSubId() {
1103 return SubscriptionManager.getActiveDataSubscriptionId();
1104 }
Jason Monkc6cc6262015-06-11 11:10:15 -04001105 }
1106
Jason Monkd2263cd2014-11-10 14:22:56 -05001107 @VisibleForTesting
1108 static class Config {
Pengquan Menga62d32b2018-12-06 17:38:38 -08001109 static final int NR_CONNECTED_MMWAVE = 1;
1110 static final int NR_CONNECTED = 2;
1111 static final int NR_NOT_RESTRICTED = 3;
1112 static final int NR_RESTRICTED = 4;
1113
1114 Map<Integer, MobileIconGroup> nr5GIconMap = new HashMap<>();
1115
Jason Monkb5746272014-11-12 16:50:31 -05001116 boolean showAtLeast3G = false;
vagdevi3f2b9a52019-08-09 09:45:14 -07001117 boolean show4gFor3g = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001118 boolean alwaysShowCdmaRssi = false;
1119 boolean show4gForLte = false;
Robert Greenwalt37d34ba2016-07-27 14:54:34 -07001120 boolean hideLtePlus = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001121 boolean hspaDataDistinguishable;
Jason Monk43c14d12017-06-22 11:20:04 -04001122 boolean inflateSignalStrengths = false;
Wenting Xiong63364fe2017-02-07 19:12:27 +08001123 boolean alwaysShowDataRatIcon = false;
SongFerngWang3cbcf752019-03-21 23:14:20 +08001124 public String patternOfCarrierSpecificDataIcon = "";
Jason Monkd2263cd2014-11-10 14:22:56 -05001125
Pengquan Menga62d32b2018-12-06 17:38:38 -08001126 /**
1127 * Mapping from NR 5G status string to an integer. The NR 5G status string should match
1128 * those in carrier config.
1129 */
1130 private static final Map<String, Integer> NR_STATUS_STRING_TO_INDEX;
1131 static {
1132 NR_STATUS_STRING_TO_INDEX = new HashMap<>(4);
1133 NR_STATUS_STRING_TO_INDEX.put("connected_mmwave", NR_CONNECTED_MMWAVE);
1134 NR_STATUS_STRING_TO_INDEX.put("connected", NR_CONNECTED);
1135 NR_STATUS_STRING_TO_INDEX.put("not_restricted", NR_NOT_RESTRICTED);
1136 NR_STATUS_STRING_TO_INDEX.put("restricted", NR_RESTRICTED);
1137 }
1138
Jason Monkd2263cd2014-11-10 14:22:56 -05001139 static Config readConfig(Context context) {
1140 Config config = new Config();
1141 Resources res = context.getResources();
1142
Jason Monkb5746272014-11-12 16:50:31 -05001143 config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
Jason Monkd2263cd2014-11-10 14:22:56 -05001144 config.alwaysShowCdmaRssi =
1145 res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
Jason Monkd2263cd2014-11-10 14:22:56 -05001146 config.hspaDataDistinguishable =
1147 res.getBoolean(R.bool.config_hspa_data_distinguishable);
Antony Sargentc026de32019-05-21 16:29:04 -07001148 config.inflateSignalStrengths = res.getBoolean(
1149 com.android.internal.R.bool.config_inflateSignalStrength);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001150
1151 CarrierConfigManager configMgr = (CarrierConfigManager)
1152 context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001153 // Handle specific carrier config values for the default data SIM
1154 int defaultDataSubId = SubscriptionManager.from(context)
1155 .getDefaultDataSubscriptionId();
1156 PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001157 if (b != null) {
1158 config.alwaysShowDataRatIcon = b.getBoolean(
1159 CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001160 config.show4gForLte = b.getBoolean(
1161 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
vagdevi3f2b9a52019-08-09 09:45:14 -07001162 config.show4gFor3g = b.getBoolean(
1163 CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001164 config.hideLtePlus = b.getBoolean(
1165 CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
SongFerngWang3cbcf752019-03-21 23:14:20 +08001166 config.patternOfCarrierSpecificDataIcon = b.getString(
1167 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
Pengquan Menga62d32b2018-12-06 17:38:38 -08001168 String nr5GIconConfiguration =
1169 b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
1170 if (!TextUtils.isEmpty(nr5GIconConfiguration)) {
1171 String[] nr5GIconConfigPairs = nr5GIconConfiguration.trim().split(",");
1172 for (String pair : nr5GIconConfigPairs) {
1173 add5GIconMapping(pair, config);
1174 }
1175 }
Wenting Xiong63364fe2017-02-07 19:12:27 +08001176 }
Pengquan Menga62d32b2018-12-06 17:38:38 -08001177
Jason Monkd2263cd2014-11-10 14:22:56 -05001178 return config;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001179 }
Pengquan Menga62d32b2018-12-06 17:38:38 -08001180
1181 /**
1182 * Add a mapping from NR 5G status to the 5G icon. All the icon resources come from
1183 * {@link TelephonyIcons}.
1184 *
1185 * @param keyValuePair the NR 5G status and icon name separated by a colon.
1186 * @param config container that used to store the parsed configs.
1187 */
1188 @VisibleForTesting
1189 static void add5GIconMapping(String keyValuePair, Config config) {
1190 String[] kv = (keyValuePair.trim().toLowerCase()).split(":");
1191
1192 if (kv.length != 2) {
1193 if (DEBUG) Log.e(TAG, "Invalid 5G icon configuration, config = " + keyValuePair);
1194 return;
1195 }
1196
1197 String key = kv[0], value = kv[1];
1198
1199 // There is no icon config for the specific 5G status.
1200 if (value.equals("none")) return;
1201
1202 if (NR_STATUS_STRING_TO_INDEX.containsKey(key)
1203 && TelephonyIcons.ICON_NAME_TO_ICON.containsKey(value)) {
1204 config.nr5GIconMap.put(
1205 NR_STATUS_STRING_TO_INDEX.get(key),
1206 TelephonyIcons.ICON_NAME_TO_ICON.get(value));
1207 }
1208 }
John Spurlockaf8d6c42014-05-07 17:49:08 -04001209 }
1210}