blob: f79ad71a114f52de0e1d38de6d3f44964f864b3c [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;
24
Jason Monk196d6392018-12-20 13:25:34 -050025import static com.android.systemui.Dependency.BG_LOOPER_NAME;
26
John Spurlockaf8d6c42014-05-07 17:49:08 -040027import android.content.BroadcastReceiver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
Jason Monk9c7844c2017-01-18 15:21:53 -050031import android.content.res.Configuration;
John Spurlockaf8d6c42014-05-07 17:49:08 -040032import android.content.res.Resources;
33import android.net.ConnectivityManager;
Anarghya Mitra678722f2018-05-11 14:29:54 -070034import android.net.Network;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090035import android.net.NetworkCapabilities;
John Spurlockaf8d6c42014-05-07 17:49:08 -040036import android.net.wifi.WifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040037import android.os.AsyncTask;
38import android.os.Bundle;
Jason Monk07b75fe2015-05-14 16:47:03 -040039import android.os.Handler;
Jason Monk30d80042015-05-08 16:54:18 -040040import android.os.Looper;
Wenting Xiong63364fe2017-02-07 19:12:27 +080041import android.os.PersistableBundle;
John Spurlockaf8d6c42014-05-07 17:49:08 -040042import android.provider.Settings;
Wenting Xiong63364fe2017-02-07 19:12:27 +080043import android.telephony.CarrierConfigManager;
Jason Monkb0808aa2015-07-22 16:34:36 -040044import android.telephony.ServiceState;
Jason Monk48edc0c2017-04-10 15:01:27 -040045import android.telephony.SignalStrength;
Jason Monkb5746272014-11-12 16:50:31 -050046import android.telephony.SubscriptionInfo;
47import android.telephony.SubscriptionManager;
48import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
John Spurlockaf8d6c42014-05-07 17:49:08 -040049import android.telephony.TelephonyManager;
Jason Monkb5746272014-11-12 16:50:31 -050050import android.text.TextUtils;
John Spurlockaf8d6c42014-05-07 17:49:08 -040051import android.util.Log;
John Spurlockcf053c12015-05-14 16:33:59 -040052import android.util.MathUtils;
Jason Monk8996b942017-03-02 13:58:19 -050053import android.util.SparseArray;
Winsonc0d70582016-01-29 10:24:39 -080054
Jason Monke0cdb602014-11-05 12:39:45 -050055import com.android.internal.annotations.VisibleForTesting;
Jason Monkb5746272014-11-12 16:50:31 -050056import com.android.internal.telephony.PhoneConstants;
John Spurlockaf8d6c42014-05-07 17:49:08 -040057import com.android.internal.telephony.TelephonyIntents;
Jason Monkf668d7c2016-01-14 10:38:41 -050058import com.android.settingslib.net.DataUsageController;
Jason Monk9c7844c2017-01-18 15:21:53 -050059import com.android.systemui.ConfigurationChangedReceiver;
John Spurlockaf8d6c42014-05-07 17:49:08 -040060import com.android.systemui.DemoMode;
Jason Monk9c7844c2017-01-18 15:21:53 -050061import com.android.systemui.Dumpable;
John Spurlockaf8d6c42014-05-07 17:49:08 -040062import com.android.systemui.R;
Jason Monk9c7844c2017-01-18 15:21:53 -050063import com.android.systemui.settings.CurrentUserTracker;
64import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
Pengquan Menga62d32b2018-12-06 17:38:38 -080065import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
John Spurlockaf8d6c42014-05-07 17:49:08 -040066
67import java.io.FileDescriptor;
68import java.io.PrintWriter;
69import java.util.ArrayList;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090070import java.util.BitSet;
Jason Monkb5746272014-11-12 16:50:31 -050071import java.util.Collections;
72import java.util.Comparator;
Pengquan Menga62d32b2018-12-06 17:38:38 -080073import java.util.HashMap;
John Spurlockaf8d6c42014-05-07 17:49:08 -040074import java.util.List;
75import java.util.Locale;
Pengquan Menga62d32b2018-12-06 17:38:38 -080076import java.util.Map;
John Spurlockaf8d6c42014-05-07 17:49:08 -040077
Jason Monk196d6392018-12-20 13:25:34 -050078import javax.inject.Inject;
79import javax.inject.Named;
80import javax.inject.Singleton;
81
John Spurlockaf8d6c42014-05-07 17:49:08 -040082/** Platform implementation of the network controller. **/
Jason Monk196d6392018-12-20 13:25:34 -050083@Singleton
John Spurlockaf8d6c42014-05-07 17:49:08 -040084public class NetworkControllerImpl extends BroadcastReceiver
Jason Monk9c7844c2017-01-18 15:21:53 -050085 implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider,
86 ConfigurationChangedReceiver, Dumpable {
John Spurlockaf8d6c42014-05-07 17:49:08 -040087 // debug
Jason Monkd2263cd2014-11-10 14:22:56 -050088 static final String TAG = "NetworkController";
89 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
90 // additional diagnostics, but not logspew
Jason Monk07b75fe2015-05-14 16:47:03 -040091 static final boolean CHATTY = Log.isLoggable(TAG + "Chat", Log.DEBUG);
John Spurlockaf8d6c42014-05-07 17:49:08 -040092
Jason Monk66845a32015-08-03 11:09:41 -040093 private static final int EMERGENCY_NO_CONTROLLERS = 0;
94 private static final int EMERGENCY_FIRST_CONTROLLER = 100;
95 private static final int EMERGENCY_VOICE_CONTROLLER = 200;
96 private static final int EMERGENCY_NO_SUB = 300;
Jason Monk8996b942017-03-02 13:58:19 -050097 private static final int EMERGENCY_ASSUMED_VOICE_CONTROLLER = 400;
Jason Monk66845a32015-08-03 11:09:41 -040098
Jason Monkd2263cd2014-11-10 14:22:56 -050099 private final Context mContext;
100 private final TelephonyManager mPhone;
101 private final WifiManager mWifiManager;
102 private final ConnectivityManager mConnectivityManager;
Jason Monkb5746272014-11-12 16:50:31 -0500103 private final SubscriptionManager mSubscriptionManager;
Jason Monkd2263cd2014-11-10 14:22:56 -0500104 private final boolean mHasMobileDataFeature;
Jason Monkc6cc6262015-06-11 11:10:15 -0400105 private final SubscriptionDefaults mSubDefaults;
Jason Monk9a4ce132016-01-21 15:27:17 -0500106 private final DataSaverController mDataSaverController;
Jason Monk9c7844c2017-01-18 15:21:53 -0500107 private final CurrentUserTracker mUserTracker;
Jason Monk3aaabd72014-12-12 11:11:44 -0500108 private Config mConfig;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400109
Jason Monkd2263cd2014-11-10 14:22:56 -0500110 // Subcontrollers.
111 @VisibleForTesting
112 final WifiSignalController mWifiSignalController;
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900113
114 @VisibleForTesting
115 final EthernetSignalController mEthernetSignalController;
116
Jason Monkd2263cd2014-11-10 14:22:56 -0500117 @VisibleForTesting
Jason Monk8996b942017-03-02 13:58:19 -0500118 final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>();
Jason Monkb5746272014-11-12 16:50:31 -0500119 // When no SIMs are around at setup, and one is added later, it seems to default to the first
120 // SIM for most actions. This may be null if there aren't any SIMs around.
121 private MobileSignalController mDefaultSignalController;
Jason Monk0e2400f2014-11-21 11:08:55 -0500122 private final AccessPointControllerImpl mAccessPoints;
Jason Monkf668d7c2016-01-14 10:38:41 -0500123 private final DataUsageController mDataUsageController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400124
Jason Monkd2263cd2014-11-10 14:22:56 -0500125 private boolean mInetCondition; // Used for Logging and demo.
Lorenzo Colitti23dd1762014-09-10 22:58:54 +0900126
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900127 // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are
128 // connected and validated, respectively.
129 private final BitSet mConnectedTransports = new BitSet();
130 private final BitSet mValidatedTransports = new BitSet();
131
Jason Monkd2263cd2014-11-10 14:22:56 -0500132 // States that don't belong to a subcontroller.
John Spurlockaf8d6c42014-05-07 17:49:08 -0400133 private boolean mAirplaneMode = false;
Jason Monk1ff77662017-09-29 11:17:05 -0400134 private boolean mHasNoSubs;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400135 private Locale mLocale = null;
Jason Monkb5746272014-11-12 16:50:31 -0500136 // This list holds our ordering.
John Spurlockcf053c12015-05-14 16:33:59 -0400137 private List<SubscriptionInfo> mCurrentSubscriptions = new ArrayList<>();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400138
Jason Monkc014dec2014-12-12 11:49:55 -0500139 @VisibleForTesting
140 boolean mListening;
John Spurlock7f8f22a2014-07-02 18:54:17 -0400141
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900142 // The current user ID.
143 private int mCurrentUserId;
144
Jason Monk8fcab352015-06-29 10:57:00 -0400145 private OnSubscriptionsChangedListener mSubscriptionListener;
146
Jason Monk07b75fe2015-05-14 16:47:03 -0400147 // Handler that all broadcasts are received on.
148 private final Handler mReceiverHandler;
149 // Handler that all callbacks are made on.
150 private final CallbackHandler mCallbackHandler;
151
Jason Monk66845a32015-08-03 11:09:41 -0400152 private int mEmergencySource;
153 private boolean mIsEmergency;
154
Jason Monkb0808aa2015-07-22 16:34:36 -0400155 @VisibleForTesting
156 ServiceState mLastServiceState;
Jason Monkfd57ea72016-04-29 13:37:58 -0400157 private boolean mUserSetup;
Jason Monk1ff77662017-09-29 11:17:05 -0400158 private boolean mSimDetected;
Jason Monkb0808aa2015-07-22 16:34:36 -0400159
John Spurlockaf8d6c42014-05-07 17:49:08 -0400160 /**
161 * Construct this controller object and register for updates.
162 */
Jason Monk196d6392018-12-20 13:25:34 -0500163 @Inject
164 public NetworkControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
Jason Monk9c7844c2017-01-18 15:21:53 -0500165 DeviceProvisionedController deviceProvisionedController) {
Jason Monkf13b4b32014-11-07 16:39:34 -0500166 this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
167 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
Jason Monk29f7a7b2014-11-17 14:40:56 -0500168 (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
Sundeep Ghuman9d10a3c2017-06-16 00:05:16 +0000169 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400170 new CallbackHandler(),
Tony Mantler0edf09b2017-09-28 15:03:37 -0700171 new AccessPointControllerImpl(context),
Jason Monkf668d7c2016-01-14 10:38:41 -0500172 new DataUsageController(context),
Jason Monk9c7844c2017-01-18 15:21:53 -0500173 new SubscriptionDefaults(),
174 deviceProvisionedController);
Jason Monk07b75fe2015-05-14 16:47:03 -0400175 mReceiverHandler.post(mRegisterListeners);
Jason Monkf13b4b32014-11-07 16:39:34 -0500176 }
177
178 @VisibleForTesting
179 NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
Sundeep Ghuman9d10a3c2017-06-16 00:05:16 +0000180 TelephonyManager telephonyManager, WifiManager wifiManager,
181 SubscriptionManager subManager, Config config, Looper bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400182 CallbackHandler callbackHandler,
Jason Monkd2263cd2014-11-10 14:22:56 -0500183 AccessPointControllerImpl accessPointController,
Jason Monkf668d7c2016-01-14 10:38:41 -0500184 DataUsageController dataUsageController,
Jason Monk9c7844c2017-01-18 15:21:53 -0500185 SubscriptionDefaults defaultsHandler,
186 DeviceProvisionedController deviceProvisionedController) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400187 mContext = context;
Jason Monkb5746272014-11-12 16:50:31 -0500188 mConfig = config;
Jason Monk07b75fe2015-05-14 16:47:03 -0400189 mReceiverHandler = new Handler(bgLooper);
190 mCallbackHandler = callbackHandler;
Jason Monk9abca5e2016-11-11 16:18:14 -0500191 mDataSaverController = new DataSaverControllerImpl(context);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400192
Jason Monkb5746272014-11-12 16:50:31 -0500193 mSubscriptionManager = subManager;
Jason Monkc6cc6262015-06-11 11:10:15 -0400194 mSubDefaults = defaultsHandler;
Jason Monkf13b4b32014-11-07 16:39:34 -0500195 mConnectivityManager = connectivityManager;
196 mHasMobileDataFeature =
197 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400198
John Spurlockaf8d6c42014-05-07 17:49:08 -0400199 // telephony
Jason Monk07b75fe2015-05-14 16:47:03 -0400200 mPhone = telephonyManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400201
202 // wifi
Jason Monkf13b4b32014-11-07 16:39:34 -0500203 mWifiManager = wifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400204
Jason Monkd2263cd2014-11-10 14:22:56 -0500205 mLocale = mContext.getResources().getConfiguration().locale;
Jason Monk29f7a7b2014-11-17 14:40:56 -0500206 mAccessPoints = accessPointController;
Jason Monkf668d7c2016-01-14 10:38:41 -0500207 mDataUsageController = dataUsageController;
208 mDataUsageController.setNetworkController(this);
209 // TODO: Find a way to move this into DataUsageController.
210 mDataUsageController.setCallback(new DataUsageController.Callback() {
Jason Monke0cdb602014-11-05 12:39:45 -0500211 @Override
212 public void onMobileDataEnabled(boolean enabled) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400213 mCallbackHandler.setMobileDataEnabled(enabled);
Jason Monke0cdb602014-11-05 12:39:45 -0500214 }
215 });
Jason Monkd2263cd2014-11-10 14:22:56 -0500216 mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
Amin Shaikhc7593b12018-03-09 16:07:09 -0500217 mCallbackHandler, this, mWifiManager);
Jason Monkd2263cd2014-11-10 14:22:56 -0500218
Jason Monk07b75fe2015-05-14 16:47:03 -0400219 mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900220
Jason Monkd2263cd2014-11-10 14:22:56 -0500221 // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
Jason Monkb5746272014-11-12 16:50:31 -0500222 updateAirplaneMode(true /* force callback */);
Jason Monk9c7844c2017-01-18 15:21:53 -0500223 mUserTracker = new CurrentUserTracker(mContext) {
224 @Override
225 public void onUserSwitched(int newUserId) {
226 NetworkControllerImpl.this.onUserSwitched(newUserId);
227 }
228 };
229 mUserTracker.startTracking();
230 deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
231 @Override
232 public void onUserSetupChanged() {
233 setUserSetupComplete(deviceProvisionedController.isUserSetup(
234 deviceProvisionedController.getCurrentUser()));
235 }
236 });
Anarghya Mitra678722f2018-05-11 14:29:54 -0700237
238 ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){
239 private Network mLastNetwork;
240 private NetworkCapabilities mLastNetworkCapabilities;
241
242 @Override
243 public void onCapabilitiesChanged(
244 Network network, NetworkCapabilities networkCapabilities) {
245 boolean lastValidated = (mLastNetworkCapabilities != null) &&
246 mLastNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
247 boolean validated =
248 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
249
250 // This callback is invoked a lot (i.e. when RSSI changes), so avoid updating
251 // icons when connectivity state has remained the same.
252 if (network.equals(mLastNetwork) &&
253 networkCapabilities.equalsTransportTypes(mLastNetworkCapabilities) &&
254 validated == lastValidated) {
255 return;
256 }
257 mLastNetwork = network;
258 mLastNetworkCapabilities = networkCapabilities;
259 updateConnectivity();
260 }
261 };
262 // Even though this callback runs on the receiver handler thread which also processes the
263 // CONNECTIVITY_ACTION broadcasts, the broadcast and callback might come in at different
264 // times. This is safe since updateConnectivity() builds the list of transports from
265 // scratch.
266 // TODO: Move off of the deprecated CONNECTIVITY_ACTION broadcast and rely on callbacks
267 // exclusively for status bar icons.
268 mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
Jason Monke0cdb602014-11-05 12:39:45 -0500269 }
270
Jason Monk9a4ce132016-01-21 15:27:17 -0500271 public DataSaverController getDataSaverController() {
272 return mDataSaverController;
273 }
274
Jason Monkf13b4b32014-11-07 16:39:34 -0500275 private void registerListeners() {
Jason Monk8996b942017-03-02 13:58:19 -0500276 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
277 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500278 mobileSignalController.registerListener();
279 }
Jason Monk8fcab352015-06-29 10:57:00 -0400280 if (mSubscriptionListener == null) {
281 mSubscriptionListener = new SubListener();
282 }
Wink Saville071743f2015-01-12 17:11:04 -0800283 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monke0cdb602014-11-05 12:39:45 -0500284
John Spurlockaf8d6c42014-05-07 17:49:08 -0400285 // broadcasts
286 IntentFilter filter = new IntentFilter();
287 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
288 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
289 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
290 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jason Monkb5746272014-11-12 16:50:31 -0500291 filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
292 filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
Jason Monkb0808aa2015-07-22 16:34:36 -0400293 filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400294 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Erik Kline32830cc2015-04-21 13:09:15 +0900295 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400296 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400297 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
Wenting Xiong63364fe2017-02-07 19:12:27 +0800298 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
Jason Monk07b75fe2015-05-14 16:47:03 -0400299 mContext.registerReceiver(this, filter, null, mReceiverHandler);
Jason Monkb5746272014-11-12 16:50:31 -0500300 mListening = true;
301
302 updateMobileControllers();
John Spurlockb98f7472014-07-08 17:09:42 -0400303 }
304
Jason Monkd2263cd2014-11-10 14:22:56 -0500305 private void unregisterListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500306 mListening = false;
Jason Monk8996b942017-03-02 13:58:19 -0500307 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
308 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500309 mobileSignalController.unregisterListener();
310 }
Wink Saville071743f2015-01-12 17:11:04 -0800311 mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monkd2263cd2014-11-10 14:22:56 -0500312 mContext.unregisterReceiver(this);
Jason Monk5d325072014-10-27 11:38:47 -0400313 }
314
Jason Monk0e2400f2014-11-21 11:08:55 -0500315 public int getConnectedWifiLevel() {
316 return mWifiSignalController.getState().level;
317 }
318
Jason Monk5d325072014-10-27 11:38:47 -0400319 @Override
Jason Monkd2263cd2014-11-10 14:22:56 -0500320 public AccessPointController getAccessPointController() {
321 return mAccessPoints;
322 }
323
324 @Override
Jason Monkf668d7c2016-01-14 10:38:41 -0500325 public DataUsageController getMobileDataController() {
326 return mDataUsageController;
Jason Monkd2263cd2014-11-10 14:22:56 -0500327 }
328
329 public void addEmergencyListener(EmergencyListener listener) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400330 mCallbackHandler.setListening(listener, true);
331 mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400332 }
333
Jason Monk46dbfb42016-02-25 14:59:20 -0500334 public void removeEmergencyListener(EmergencyListener listener) {
335 mCallbackHandler.setListening(listener, false);
336 }
337
John Spurlockaf8d6c42014-05-07 17:49:08 -0400338 public boolean hasMobileDataFeature() {
339 return mHasMobileDataFeature;
340 }
341
342 public boolean hasVoiceCallingFeature() {
343 return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
344 }
345
Jason Monkb5746272014-11-12 16:50:31 -0500346 private MobileSignalController getDataController() {
Jason Monkc6cc6262015-06-11 11:10:15 -0400347 int dataSubId = mSubDefaults.getDefaultDataSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800348 if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
Jason Monkb5746272014-11-12 16:50:31 -0500349 if (DEBUG) Log.e(TAG, "No data sim selected");
350 return mDefaultSignalController;
351 }
Jason Monk8996b942017-03-02 13:58:19 -0500352 if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500353 return mMobileSignalControllers.get(dataSubId);
354 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500355 if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
Jason Monkb5746272014-11-12 16:50:31 -0500356 return mDefaultSignalController;
357 }
358
Amin Shaikh329c8282018-03-09 14:50:59 -0500359 @Override
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700360 public String getMobileDataNetworkName() {
Jason Monkb5746272014-11-12 16:50:31 -0500361 MobileSignalController controller = getDataController();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700362 return controller != null ? controller.getState().networkNameData : "";
Jason Monkd2263cd2014-11-10 14:22:56 -0500363 }
364
John Spurlockaf8d6c42014-05-07 17:49:08 -0400365 public boolean isEmergencyOnly() {
Jason Monkb0808aa2015-07-22 16:34:36 -0400366 if (mMobileSignalControllers.size() == 0) {
367 // When there are no active subscriptions, determine emengency state from last
368 // broadcast.
Jason Monk66845a32015-08-03 11:09:41 -0400369 mEmergencySource = EMERGENCY_NO_CONTROLLERS;
Jason Monkb0808aa2015-07-22 16:34:36 -0400370 return mLastServiceState != null && mLastServiceState.isEmergencyOnly();
371 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400372 int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800373 if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
Jason Monk8996b942017-03-02 13:58:19 -0500374 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
375 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkc6cc6262015-06-11 11:10:15 -0400376 if (!mobileSignalController.getState().isEmergency) {
Jason Monk66845a32015-08-03 11:09:41 -0400377 mEmergencySource = EMERGENCY_FIRST_CONTROLLER
378 + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400379 if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag);
Jason Monkb5746272014-11-12 16:50:31 -0500380 return false;
381 }
382 }
383 }
Jason Monk8996b942017-03-02 13:58:19 -0500384 if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) {
Jason Monk66845a32015-08-03 11:09:41 -0400385 mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
Jason Monkc6cc6262015-06-11 11:10:15 -0400386 if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
387 return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
Jason Monkb5746272014-11-12 16:50:31 -0500388 }
Jason Monk8996b942017-03-02 13:58:19 -0500389 // If we have the wrong subId but there is only one sim anyway, assume it should be the
390 // default.
391 if (mMobileSignalControllers.size() == 1) {
392 mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER
393 + mMobileSignalControllers.keyAt(0);
394 if (DEBUG) Log.d(TAG, "Getting assumed emergency from "
395 + mMobileSignalControllers.keyAt(0));
396 return mMobileSignalControllers.valueAt(0).getState().isEmergency;
397 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500398 if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
Jason Monk66845a32015-08-03 11:09:41 -0400399 mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
Jason Monkb5746272014-11-12 16:50:31 -0500400 // Something is wrong, better assume we can't make calls...
401 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400402 }
403
Jason Monkd2263cd2014-11-10 14:22:56 -0500404 /**
405 * Emergency status may have changed (triggered by MobileSignalController),
406 * so we should recheck and send out the state to listeners.
407 */
408 void recalculateEmergency() {
Jason Monk66845a32015-08-03 11:09:41 -0400409 mIsEmergency = isEmergencyOnly();
410 mCallbackHandler.setEmergencyCallsOnly(mIsEmergency);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400411 }
412
Jason Monk88529052016-11-04 13:29:58 -0400413 public void addCallback(SignalCallback cb) {
Jason Monke06b0652016-03-02 16:35:27 -0500414 cb.setSubs(mCurrentSubscriptions);
415 cb.setIsAirplaneMode(new IconState(mAirplaneMode,
Jason Monk07b75fe2015-05-14 16:47:03 -0400416 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monk1ff77662017-09-29 11:17:05 -0400417 cb.setNoSims(mHasNoSubs, mSimDetected);
Jason Monke06b0652016-03-02 16:35:27 -0500418 mWifiSignalController.notifyListeners(cb);
419 mEthernetSignalController.notifyListeners(cb);
Jason Monk8996b942017-03-02 13:58:19 -0500420 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
421 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monke06b0652016-03-02 16:35:27 -0500422 mobileSignalController.notifyListeners(cb);
Jason Monkb5746272014-11-12 16:50:31 -0500423 }
Jason Monke06b0652016-03-02 16:35:27 -0500424 mCallbackHandler.setListening(cb, true);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400425 }
426
Jason Monk07b75fe2015-05-14 16:47:03 -0400427 @Override
Jason Monk88529052016-11-04 13:29:58 -0400428 public void removeCallback(SignalCallback cb) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400429 mCallbackHandler.setListening(cb, false);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400430 }
431
432 @Override
433 public void setWifiEnabled(final boolean enabled) {
434 new AsyncTask<Void, Void, Void>() {
435 @Override
436 protected Void doInBackground(Void... args) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400437 mWifiManager.setWifiEnabled(enabled);
438 return null;
439 }
440 }.execute();
441 }
442
Jason Monk9c7844c2017-01-18 15:21:53 -0500443 private void onUserSwitched(int newUserId) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900444 mCurrentUserId = newUserId;
445 mAccessPoints.onUserSwitched(newUserId);
446 updateConnectivity();
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900447 }
448
449 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400450 public void onReceive(Context context, Intent intent) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500451 if (CHATTY) {
452 Log.d(TAG, "onReceive: intent=" + intent);
453 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400454 final String action = intent.getAction();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800455 switch (action) {
456 case ConnectivityManager.CONNECTIVITY_ACTION:
457 case ConnectivityManager.INET_CONDITION_ACTION:
458 updateConnectivity();
459 break;
460 case Intent.ACTION_AIRPLANE_MODE_CHANGED:
461 refreshLocale();
462 updateAirplaneMode(false);
463 break;
464 case TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
465 // We are using different subs now, we might be able to make calls.
Jason Monkb0808aa2015-07-22 16:34:36 -0400466 recalculateEmergency();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800467 break;
468 case TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
469 // Notify every MobileSignalController so they can know whether they are the
470 // data sim or not.
471 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
472 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
473 controller.handleBroadcast(intent);
Wenting Xiong63364fe2017-02-07 19:12:27 +0800474 }
Niklas Lindgrena02964d2018-09-21 14:01:57 +0200475 mConfig = Config.readConfig(mContext);
476 mReceiverHandler.post(this::handleConfigurationChanged);
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800477 break;
478 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
479 // Avoid rebroadcast because SysUI is direct boot aware.
480 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
481 break;
482 }
483 // Might have different subscriptions now.
484 updateMobileControllers();
485 break;
486 case TelephonyIntents.ACTION_SERVICE_STATE_CHANGED:
487 mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
488 if (mMobileSignalControllers.size() == 0) {
489 // If none of the subscriptions are active, we might need to recalculate
490 // emergency state.
491 recalculateEmergency();
492 }
493 break;
494 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
495 mConfig = Config.readConfig(mContext);
496 mReceiverHandler.post(this::handleConfigurationChanged);
497 break;
498 default:
499 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
500 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
501 if (SubscriptionManager.isValidSubscriptionId(subId)) {
502 if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
503 mMobileSignalControllers.get(subId).handleBroadcast(intent);
504 } else {
505 // Can't find this subscription... We must be out of date.
506 updateMobileControllers();
507 }
Jason Monkb5746272014-11-12 16:50:31 -0500508 } else {
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800509 // No sub id, must be for the wifi.
510 mWifiSignalController.handleBroadcast(intent);
Jason Monkb5746272014-11-12 16:50:31 -0500511 }
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800512 break;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400513 }
Jason Monkb5746272014-11-12 16:50:31 -0500514 }
515
Jason Monk9c7844c2017-01-18 15:21:53 -0500516 public void onConfigurationChanged(Configuration newConfig) {
Sungmin Choi6be4f6b2015-07-07 13:06:59 +0900517 mConfig = Config.readConfig(mContext);
Jason Monk1c040db2015-07-20 09:45:54 -0400518 mReceiverHandler.post(new Runnable() {
519 @Override
520 public void run() {
521 handleConfigurationChanged();
522 }
523 });
524 }
525
526 @VisibleForTesting
527 void handleConfigurationChanged() {
Jason Monk8996b942017-03-02 13:58:19 -0500528 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
529 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
530 controller.setConfiguration(mConfig);
Jason Monk3aaabd72014-12-12 11:11:44 -0500531 }
532 refreshLocale();
Jason Monk3aaabd72014-12-12 11:11:44 -0500533 }
534
Jason Monkb5746272014-11-12 16:50:31 -0500535 private void updateMobileControllers() {
536 if (!mListening) {
537 return;
538 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400539 doUpdateMobileControllers();
540 }
541
542 @VisibleForTesting
543 void doUpdateMobileControllers() {
Malcolm Chend2d400cb2018-12-21 17:11:10 -0800544 List<SubscriptionInfo> subscriptions = mSubscriptionManager
545 .getActiveSubscriptionInfoList(true);
Jason Monkc9f05712014-12-15 12:24:10 -0500546 if (subscriptions == null) {
547 subscriptions = Collections.emptyList();
548 }
Jason Monkb5746272014-11-12 16:50:31 -0500549 // If there have been no relevant changes to any of the subscriptions, we can leave as is.
550 if (hasCorrectMobileControllers(subscriptions)) {
551 // Even if the controllers are correct, make sure we have the right no sims state.
552 // Such as on boot, don't need any controllers, because there are no sims,
553 // but we still need to update the no sim state.
554 updateNoSims();
555 return;
556 }
557 setCurrentSubscriptions(subscriptions);
558 updateNoSims();
Jason Monkc6cc6262015-06-11 11:10:15 -0400559 recalculateEmergency();
Jason Monkb5746272014-11-12 16:50:31 -0500560 }
561
Jason Monk21d05a02014-12-02 12:46:58 -0500562 @VisibleForTesting
563 protected void updateNoSims() {
Jason Monk1ff77662017-09-29 11:17:05 -0400564 boolean hasNoSubs = mHasMobileDataFeature && mMobileSignalControllers.size() == 0;
565 boolean simDetected = hasAnySim();
566 if (hasNoSubs != mHasNoSubs || simDetected != mSimDetected) {
567 mHasNoSubs = hasNoSubs;
568 mSimDetected = simDetected;
569 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
Jason Monkb5746272014-11-12 16:50:31 -0500570 }
571 }
572
Jason Monk1ff77662017-09-29 11:17:05 -0400573 private boolean hasAnySim() {
574 int simCount = mPhone.getSimCount();
575 for (int i = 0; i < simCount; i++) {
576 int state = mPhone.getSimState(i);
577 if (state != TelephonyManager.SIM_STATE_ABSENT
578 && state != TelephonyManager.SIM_STATE_UNKNOWN) {
579 return true;
580 }
581 }
582 return false;
583 }
584
Jason Monkb5746272014-11-12 16:50:31 -0500585 @VisibleForTesting
586 void setCurrentSubscriptions(List<SubscriptionInfo> subscriptions) {
587 Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() {
588 @Override
589 public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) {
590 return lhs.getSimSlotIndex() == rhs.getSimSlotIndex()
591 ? lhs.getSubscriptionId() - rhs.getSubscriptionId()
592 : lhs.getSimSlotIndex() - rhs.getSimSlotIndex();
593 }
594 });
Jason Monkb5746272014-11-12 16:50:31 -0500595 mCurrentSubscriptions = subscriptions;
596
Jason Monk8996b942017-03-02 13:58:19 -0500597 SparseArray<MobileSignalController> cachedControllers =
598 new SparseArray<MobileSignalController>();
599 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
600 cachedControllers.put(mMobileSignalControllers.keyAt(i),
601 mMobileSignalControllers.valueAt(i));
602 }
Jason Monkb5746272014-11-12 16:50:31 -0500603 mMobileSignalControllers.clear();
604 final int num = subscriptions.size();
605 for (int i = 0; i < num; i++) {
606 int subId = subscriptions.get(i).getSubscriptionId();
607 // If we have a copy of this controller already reuse it, otherwise make a new one.
Jason Monk8996b942017-03-02 13:58:19 -0500608 if (cachedControllers.indexOfKey(subId) >= 0) {
609 mMobileSignalControllers.put(subId, cachedControllers.get(subId));
610 cachedControllers.remove(subId);
Jason Monkb5746272014-11-12 16:50:31 -0500611 } else {
612 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
Jason Monk07b75fe2015-05-14 16:47:03 -0400613 mHasMobileDataFeature, mPhone, mCallbackHandler,
Jason Monkc6cc6262015-06-11 11:10:15 -0400614 this, subscriptions.get(i), mSubDefaults, mReceiverHandler.getLooper());
Jason Monkfd57ea72016-04-29 13:37:58 -0400615 controller.setUserSetupComplete(mUserSetup);
Jason Monkb5746272014-11-12 16:50:31 -0500616 mMobileSignalControllers.put(subId, controller);
617 if (subscriptions.get(i).getSimSlotIndex() == 0) {
618 mDefaultSignalController = controller;
619 }
620 if (mListening) {
621 controller.registerListener();
622 }
623 }
624 }
625 if (mListening) {
Jason Monk8996b942017-03-02 13:58:19 -0500626 for (int i = 0; i < cachedControllers.size(); i++) {
627 int key = cachedControllers.keyAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500628 if (cachedControllers.get(key) == mDefaultSignalController) {
629 mDefaultSignalController = null;
630 }
631 cachedControllers.get(key).unregisterListener();
632 }
633 }
Jason Monk8fcab352015-06-29 10:57:00 -0400634 mCallbackHandler.setSubs(subscriptions);
635 notifyAllListeners();
636
Jason Monk25d8a482014-12-09 12:27:24 -0500637 // There may be new MobileSignalControllers around, make sure they get the current
638 // inet condition and airplane mode.
639 pushConnectivityToSignals();
640 updateAirplaneMode(true /* force */);
Jason Monkb5746272014-11-12 16:50:31 -0500641 }
642
Jason Monk0288de02017-02-23 14:48:05 -0500643 private void setUserSetupComplete(final boolean userSetup) {
644 mReceiverHandler.post(() -> handleSetUserSetupComplete(userSetup));
Jason Monkfd57ea72016-04-29 13:37:58 -0400645 }
646
Jason Monk0288de02017-02-23 14:48:05 -0500647 private void handleSetUserSetupComplete(boolean userSetup) {
Jason Monkfd57ea72016-04-29 13:37:58 -0400648 mUserSetup = userSetup;
Jason Monk8996b942017-03-02 13:58:19 -0500649 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
650 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkfd57ea72016-04-29 13:37:58 -0400651 controller.setUserSetupComplete(mUserSetup);
652 }
653 }
654
Jason Monkc014dec2014-12-12 11:49:55 -0500655 @VisibleForTesting
656 boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) {
Jason Monkc9f05712014-12-15 12:24:10 -0500657 if (allSubscriptions.size() != mMobileSignalControllers.size()) {
658 return false;
Jason Monkb5746272014-11-12 16:50:31 -0500659 }
660 for (SubscriptionInfo info : allSubscriptions) {
Jason Monk8996b942017-03-02 13:58:19 -0500661 if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500662 return false;
663 }
664 }
665 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400666 }
667
Jason Monkd2263cd2014-11-10 14:22:56 -0500668 private void updateAirplaneMode(boolean force) {
669 boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
670 Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
671 if (airplaneMode != mAirplaneMode || force) {
672 mAirplaneMode = airplaneMode;
Jason Monk8996b942017-03-02 13:58:19 -0500673 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
674 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500675 mobileSignalController.setAirplaneMode(mAirplaneMode);
676 }
677 notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400678 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400679 }
680
681 private void refreshLocale() {
Jason Monkd2263cd2014-11-10 14:22:56 -0500682 Locale current = mContext.getResources().getConfiguration().locale;
Jason Monkb5746272014-11-12 16:50:31 -0500683 if (!current.equals(mLocale)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500684 mLocale = current;
Fabian Kozynskid9cb3842018-09-28 13:34:14 -0400685 mWifiSignalController.refreshLocale();
Jason Monkd2263cd2014-11-10 14:22:56 -0500686 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400687 }
688 }
689
Jason Monkd2263cd2014-11-10 14:22:56 -0500690 /**
Jason Monkb5746272014-11-12 16:50:31 -0500691 * Forces update of all callbacks on both SignalClusters and
692 * NetworkSignalChangedCallbacks.
693 */
Jason Monkd2263cd2014-11-10 14:22:56 -0500694 private void notifyAllListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500695 notifyListeners();
Jason Monk8996b942017-03-02 13:58:19 -0500696 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
697 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500698 mobileSignalController.notifyListeners();
699 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500700 mWifiSignalController.notifyListeners();
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900701 mEthernetSignalController.notifyListeners();
Jason Monkd2263cd2014-11-10 14:22:56 -0500702 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400703
Jason Monkb5746272014-11-12 16:50:31 -0500704 /**
705 * Notifies listeners of changes in state of to the NetworkController, but
706 * does not notify for any info on SignalControllers, for that call
707 * notifyAllListeners.
708 */
709 private void notifyListeners() {
Jason Monk07b75fe2015-05-14 16:47:03 -0400710 mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
711 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monk1ff77662017-09-29 11:17:05 -0400712 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400713 }
714
Jason Monkd2263cd2014-11-10 14:22:56 -0500715 /**
716 * Update the Inet conditions and what network we are connected to.
717 */
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900718 private void updateConnectivity() {
719 mConnectedTransports.clear();
720 mValidatedTransports.clear();
721 for (NetworkCapabilities nc :
722 mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
723 for (int transportType : nc.getTransportTypes()) {
724 mConnectedTransports.set(transportType);
725 if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
726 mValidatedTransports.set(transportType);
727 }
728 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400729 }
730
John Spurlockaf8d6c42014-05-07 17:49:08 -0400731 if (CHATTY) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900732 Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
733 Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400734 }
735
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900736 mInetCondition = !mValidatedTransports.isEmpty();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400737
Jason Monk25d8a482014-12-09 12:27:24 -0500738 pushConnectivityToSignals();
739 }
740
741 /**
742 * Pushes the current connectivity state to all SignalControllers.
743 */
744 private void pushConnectivityToSignals() {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400745 // We want to update all the icons, all at once, for any condition change
Jason Monk8996b942017-03-02 13:58:19 -0500746 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
747 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400748 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
Jason Monkb5746272014-11-12 16:50:31 -0500749 }
Jason Monk33f8ae72015-05-08 10:45:15 -0400750 mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
751 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400752 }
753
John Spurlockaf8d6c42014-05-07 17:49:08 -0400754 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
755 pw.println("NetworkController state:");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900756
John Spurlockaf8d6c42014-05-07 17:49:08 -0400757 pw.println(" - telephony ------");
758 pw.print(" hasVoiceCallingFeature()=");
759 pw.println(hasVoiceCallingFeature());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400760
John Spurlockaf8d6c42014-05-07 17:49:08 -0400761 pw.println(" - connectivity ------");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900762 pw.print(" mConnectedTransports=");
763 pw.println(mConnectedTransports);
764 pw.print(" mValidatedTransports=");
765 pw.println(mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400766 pw.print(" mInetCondition=");
767 pw.println(mInetCondition);
Jason Monkd2263cd2014-11-10 14:22:56 -0500768 pw.print(" mAirplaneMode=");
769 pw.println(mAirplaneMode);
770 pw.print(" mLocale=");
771 pw.println(mLocale);
Jason Monkb0808aa2015-07-22 16:34:36 -0400772 pw.print(" mLastServiceState=");
773 pw.println(mLastServiceState);
Jason Monk66845a32015-08-03 11:09:41 -0400774 pw.print(" mIsEmergency=");
775 pw.println(mIsEmergency);
776 pw.print(" mEmergencySource=");
777 pw.println(emergencyToString(mEmergencySource));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400778
Jason Monk8996b942017-03-02 13:58:19 -0500779 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
780 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500781 mobileSignalController.dump(pw);
782 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500783 mWifiSignalController.dump(pw);
Jason Monkd52356a2015-01-28 10:40:41 -0500784
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900785 mEthernetSignalController.dump(pw);
786
Jason Monkd52356a2015-01-28 10:40:41 -0500787 mAccessPoints.dump(pw);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400788 }
789
Jason Monk66845a32015-08-03 11:09:41 -0400790 private static final String emergencyToString(int emergencySource) {
791 if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk8996b942017-03-02 13:58:19 -0500792 return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER)
793 + ")";
794 } else if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk66845a32015-08-03 11:09:41 -0400795 return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
796 } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
797 return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
798 } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) {
799 return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")";
800 } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) {
801 return "NO_CONTROLLERS";
802 }
803 return "UNKNOWN_SOURCE";
804 }
805
John Spurlockaf8d6c42014-05-07 17:49:08 -0400806 private boolean mDemoMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400807 private boolean mDemoInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500808 private WifiSignalController.WifiState mDemoWifiState;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400809
810 @Override
811 public void dispatchDemoCommand(String command, Bundle args) {
812 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500813 if (DEBUG) Log.d(TAG, "Entering demo mode");
814 unregisterListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400815 mDemoMode = true;
Jason Monk33f8ae72015-05-08 10:45:15 -0400816 mDemoInetCondition = mInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500817 mDemoWifiState = mWifiSignalController.getState();
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100818 mDemoWifiState.ssid = "DemoMode";
John Spurlockaf8d6c42014-05-07 17:49:08 -0400819 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500820 if (DEBUG) Log.d(TAG, "Exiting demo mode");
John Spurlockaf8d6c42014-05-07 17:49:08 -0400821 mDemoMode = false;
Jason Monkb5746272014-11-12 16:50:31 -0500822 // Update what MobileSignalControllers, because they may change
823 // to set the number of sim slots.
824 updateMobileControllers();
Jason Monk8996b942017-03-02 13:58:19 -0500825 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
826 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500827 controller.resetLastState();
828 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500829 mWifiSignalController.resetLastState();
Jason Monk07b75fe2015-05-14 16:47:03 -0400830 mReceiverHandler.post(mRegisterListeners);
Jason Monkd2263cd2014-11-10 14:22:56 -0500831 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400832 } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
833 String airplane = args.getString("airplane");
834 if (airplane != null) {
835 boolean show = airplane.equals("show");
Jason Monk07b75fe2015-05-14 16:47:03 -0400836 mCallbackHandler.setIsAirplaneMode(new IconState(show,
837 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode,
838 mContext));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400839 }
840 String fully = args.getString("fully");
841 if (fully != null) {
Jason Monk33f8ae72015-05-08 10:45:15 -0400842 mDemoInetCondition = Boolean.parseBoolean(fully);
843 BitSet connected = new BitSet();
844
845 if (mDemoInetCondition) {
846 connected.set(mWifiSignalController.mTransportType);
847 }
848 mWifiSignalController.updateConnectivity(connected, connected);
Jason Monk8996b942017-03-02 13:58:19 -0500849 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
850 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400851 if (mDemoInetCondition) {
852 connected.set(controller.mTransportType);
853 }
854 controller.updateConnectivity(connected, connected);
Jason Monkb5746272014-11-12 16:50:31 -0500855 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400856 }
857 String wifi = args.getString("wifi");
858 if (wifi != null) {
859 boolean show = wifi.equals("show");
860 String level = args.getString("level");
861 if (level != null) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500862 mDemoWifiState.level = level.equals("null") ? -1
John Spurlockaf8d6c42014-05-07 17:49:08 -0400863 : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
Jason Monkd2263cd2014-11-10 14:22:56 -0500864 mDemoWifiState.connected = mDemoWifiState.level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400865 }
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100866 String activity = args.getString("activity");
867 if (activity != null) {
868 switch (activity) {
869 case "inout":
Roshan Pius80fb1372018-07-16 15:43:03 -0700870 mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100871 break;
872 case "in":
Roshan Pius80fb1372018-07-16 15:43:03 -0700873 mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100874 break;
875 case "out":
Roshan Pius80fb1372018-07-16 15:43:03 -0700876 mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100877 break;
878 default:
Roshan Pius80fb1372018-07-16 15:43:03 -0700879 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100880 break;
881 }
882 } else {
Roshan Pius80fb1372018-07-16 15:43:03 -0700883 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100884 }
Evan Laird27a99572017-09-27 14:09:30 -0400885 String ssid = args.getString("ssid");
886 if (ssid != null) {
887 mDemoWifiState.ssid = ssid;
888 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500889 mDemoWifiState.enabled = show;
890 mWifiSignalController.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400891 }
Jason Monkb5746272014-11-12 16:50:31 -0500892 String sims = args.getString("sims");
893 if (sims != null) {
John Spurlockcf053c12015-05-14 16:33:59 -0400894 int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
895 List<SubscriptionInfo> subs = new ArrayList<>();
Jason Monkb5746272014-11-12 16:50:31 -0500896 if (num != mMobileSignalControllers.size()) {
897 mMobileSignalControllers.clear();
898 int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
899 for (int i = start /* get out of normal index range */; i < start + num; i++) {
John Spurlockcf053c12015-05-14 16:33:59 -0400900 subs.add(addSignalController(i, i));
Jason Monkb5746272014-11-12 16:50:31 -0500901 }
Jason Monk33b60bb2015-07-13 10:42:23 -0400902 mCallbackHandler.setSubs(subs);
Evan Lairde1d13c92018-03-20 16:58:01 -0400903 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
904 int key = mMobileSignalControllers.keyAt(i);
905 MobileSignalController controller = mMobileSignalControllers.get(key);
906 controller.notifyListeners();
907 }
Jason Monkb5746272014-11-12 16:50:31 -0500908 }
Jason Monkb5746272014-11-12 16:50:31 -0500909 }
910 String nosim = args.getString("nosim");
911 if (nosim != null) {
Jason Monk1ff77662017-09-29 11:17:05 -0400912 mHasNoSubs = nosim.equals("show");
913 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
Jason Monkb5746272014-11-12 16:50:31 -0500914 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400915 String mobile = args.getString("mobile");
916 if (mobile != null) {
917 boolean show = mobile.equals("show");
918 String datatype = args.getString("datatype");
Jason Monkb5746272014-11-12 16:50:31 -0500919 String slotString = args.getString("slot");
920 int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
John Spurlockcf053c12015-05-14 16:33:59 -0400921 slot = MathUtils.constrain(slot, 0, 8);
922 // Ensure we have enough sim slots
923 List<SubscriptionInfo> subs = new ArrayList<>();
924 while (mMobileSignalControllers.size() <= slot) {
925 int nextSlot = mMobileSignalControllers.size();
926 subs.add(addSignalController(nextSlot, nextSlot));
927 }
928 if (!subs.isEmpty()) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400929 mCallbackHandler.setSubs(subs);
John Spurlockcf053c12015-05-14 16:33:59 -0400930 }
Jason Monkb5746272014-11-12 16:50:31 -0500931 // Hack to index linearly for easy use.
Jason Monk8996b942017-03-02 13:58:19 -0500932 MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
Jason Monkb5746272014-11-12 16:50:31 -0500933 controller.getState().dataSim = datatype != null;
Jason Monkb5950982017-01-24 15:53:53 -0500934 controller.getState().isDefault = datatype != null;
935 controller.getState().dataConnected = datatype != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400936 if (datatype != null) {
Jason Monkb5746272014-11-12 16:50:31 -0500937 controller.getState().iconGroup =
Jason Monkd2263cd2014-11-10 14:22:56 -0500938 datatype.equals("1x") ? TelephonyIcons.ONE_X :
939 datatype.equals("3g") ? TelephonyIcons.THREE_G :
940 datatype.equals("4g") ? TelephonyIcons.FOUR_G :
Ajay Nambi7965fa42015-05-14 18:48:33 -0700941 datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -0500942 datatype.equals("e") ? TelephonyIcons.E :
943 datatype.equals("g") ? TelephonyIcons.G :
944 datatype.equals("h") ? TelephonyIcons.H :
Amin Shaikhf5830ca2018-03-09 14:06:50 -0500945 datatype.equals("h+") ? TelephonyIcons.H_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -0500946 datatype.equals("lte") ? TelephonyIcons.LTE :
Jason Monkaa730be2016-07-13 14:22:52 -0400947 datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
Jason Monk7e6c83c2017-04-26 14:35:24 -0400948 datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
Jason Monkd2263cd2014-11-10 14:22:56 -0500949 TelephonyIcons.UNKNOWN;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400950 }
Jason Monk0f0de132016-12-19 15:36:13 -0500951 if (args.containsKey("roam")) {
952 controller.getState().roaming = "show".equals(args.getString("roam"));
953 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400954 String level = args.getString("level");
955 if (level != null) {
Jason Monkb5746272014-11-12 16:50:31 -0500956 controller.getState().level = level.equals("null") ? -1
Jason Monk48edc0c2017-04-10 15:01:27 -0400957 : Math.min(Integer.parseInt(level),
958 SignalStrength.NUM_SIGNAL_STRENGTH_BINS);
Jason Monkb5746272014-11-12 16:50:31 -0500959 controller.getState().connected = controller.getState().level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400960 }
Jason Monk0f0de132016-12-19 15:36:13 -0500961 String activity = args.getString("activity");
962 if (activity != null) {
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100963 controller.getState().dataConnected = true;
964 switch (activity) {
965 case "inout":
966 controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
967 break;
968 case "in":
969 controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
970 break;
971 case "out":
972 controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
973 break;
974 default:
975 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
976 break;
977 }
978 } else {
979 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
Jason Monk0f0de132016-12-19 15:36:13 -0500980 }
Jason Monkb5746272014-11-12 16:50:31 -0500981 controller.getState().enabled = show;
982 controller.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400983 }
Andrew Flynna478d702015-04-14 23:33:45 -0400984 String carrierNetworkChange = args.getString("carriernetworkchange");
985 if (carrierNetworkChange != null) {
986 boolean show = carrierNetworkChange.equals("show");
Jason Monk8996b942017-03-02 13:58:19 -0500987 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
988 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Andrew Flynna478d702015-04-14 23:33:45 -0400989 controller.setCarrierNetworkChangeMode(show);
990 }
991 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500992 }
993 }
994
John Spurlockcf053c12015-05-14 16:33:59 -0400995 private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
996 SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
Malcolm Chene89e0ce2018-08-09 17:01:35 -0700997 null, null, null, "", false, null, null);
Jason Monkb5950982017-01-24 15:53:53 -0500998 MobileSignalController controller = new MobileSignalController(mContext,
Jason Monk07b75fe2015-05-14 16:47:03 -0400999 mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
Jason Monkb5950982017-01-24 15:53:53 -05001000 mSubDefaults, mReceiverHandler.getLooper());
1001 mMobileSignalControllers.put(id, controller);
1002 controller.getState().userSetup = true;
John Spurlockcf053c12015-05-14 16:33:59 -04001003 return info;
1004 }
1005
Adrian Roos316bf542016-08-23 17:53:07 +02001006 public boolean hasEmergencyCryptKeeperText() {
1007 return EncryptionHelper.IS_DATA_ENCRYPTED;
1008 }
1009
1010 public boolean isRadioOn() {
1011 return !mAirplaneMode;
1012 }
1013
Jason Monk8fcab352015-06-29 10:57:00 -04001014 private class SubListener extends OnSubscriptionsChangedListener {
Jason Monkc9f05712014-12-15 12:24:10 -05001015 @Override
1016 public void onSubscriptionsChanged() {
Jason Monkb5746272014-11-12 16:50:31 -05001017 updateMobileControllers();
Jason Monk8fcab352015-06-29 10:57:00 -04001018 }
1019 }
Jason Monkb5746272014-11-12 16:50:31 -05001020
Jason Monk07b75fe2015-05-14 16:47:03 -04001021 /**
1022 * Used to register listeners from the BG Looper, this way the PhoneStateListeners that
1023 * get created will also run on the BG Looper.
1024 */
1025 private final Runnable mRegisterListeners = new Runnable() {
1026 @Override
1027 public void run() {
1028 registerListeners();
1029 }
1030 };
Jason Monkd2263cd2014-11-10 14:22:56 -05001031
Jason Monkc6cc6262015-06-11 11:10:15 -04001032 public static class SubscriptionDefaults {
1033 public int getDefaultVoiceSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -08001034 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -04001035 }
1036
1037 public int getDefaultDataSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -08001038 return SubscriptionManager.getDefaultDataSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -04001039 }
1040 }
1041
Jason Monkd2263cd2014-11-10 14:22:56 -05001042 @VisibleForTesting
1043 static class Config {
Pengquan Menga62d32b2018-12-06 17:38:38 -08001044 static final int NR_CONNECTED_MMWAVE = 1;
1045 static final int NR_CONNECTED = 2;
1046 static final int NR_NOT_RESTRICTED = 3;
1047 static final int NR_RESTRICTED = 4;
1048
1049 Map<Integer, MobileIconGroup> nr5GIconMap = new HashMap<>();
1050
Jason Monkb5746272014-11-12 16:50:31 -05001051 boolean showAtLeast3G = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001052 boolean alwaysShowCdmaRssi = false;
1053 boolean show4gForLte = false;
Robert Greenwalt37d34ba2016-07-27 14:54:34 -07001054 boolean hideLtePlus = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001055 boolean hspaDataDistinguishable;
Jason Monk43c14d12017-06-22 11:20:04 -04001056 boolean inflateSignalStrengths = false;
Wenting Xiong63364fe2017-02-07 19:12:27 +08001057 boolean alwaysShowDataRatIcon = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001058
Pengquan Menga62d32b2018-12-06 17:38:38 -08001059 /**
1060 * Mapping from NR 5G status string to an integer. The NR 5G status string should match
1061 * those in carrier config.
1062 */
1063 private static final Map<String, Integer> NR_STATUS_STRING_TO_INDEX;
1064 static {
1065 NR_STATUS_STRING_TO_INDEX = new HashMap<>(4);
1066 NR_STATUS_STRING_TO_INDEX.put("connected_mmwave", NR_CONNECTED_MMWAVE);
1067 NR_STATUS_STRING_TO_INDEX.put("connected", NR_CONNECTED);
1068 NR_STATUS_STRING_TO_INDEX.put("not_restricted", NR_NOT_RESTRICTED);
1069 NR_STATUS_STRING_TO_INDEX.put("restricted", NR_RESTRICTED);
1070 }
1071
Jason Monkd2263cd2014-11-10 14:22:56 -05001072 static Config readConfig(Context context) {
1073 Config config = new Config();
1074 Resources res = context.getResources();
1075
Jason Monkb5746272014-11-12 16:50:31 -05001076 config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
Jason Monkd2263cd2014-11-10 14:22:56 -05001077 config.alwaysShowCdmaRssi =
1078 res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
Jason Monkd2263cd2014-11-10 14:22:56 -05001079 config.hspaDataDistinguishable =
1080 res.getBoolean(R.bool.config_hspa_data_distinguishable);
Jason Monk43c14d12017-06-22 11:20:04 -04001081 config.inflateSignalStrengths = res.getBoolean(R.bool.config_inflateSignalStrength);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001082
1083 CarrierConfigManager configMgr = (CarrierConfigManager)
1084 context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001085 // Handle specific carrier config values for the default data SIM
1086 int defaultDataSubId = SubscriptionManager.from(context)
1087 .getDefaultDataSubscriptionId();
1088 PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001089 if (b != null) {
1090 config.alwaysShowDataRatIcon = b.getBoolean(
1091 CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001092 config.show4gForLte = b.getBoolean(
1093 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
1094 config.hideLtePlus = b.getBoolean(
1095 CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
Pengquan Menga62d32b2018-12-06 17:38:38 -08001096 String nr5GIconConfiguration =
1097 b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
1098 if (!TextUtils.isEmpty(nr5GIconConfiguration)) {
1099 String[] nr5GIconConfigPairs = nr5GIconConfiguration.trim().split(",");
1100 for (String pair : nr5GIconConfigPairs) {
1101 add5GIconMapping(pair, config);
1102 }
1103 }
Wenting Xiong63364fe2017-02-07 19:12:27 +08001104 }
Pengquan Menga62d32b2018-12-06 17:38:38 -08001105
Jason Monkd2263cd2014-11-10 14:22:56 -05001106 return config;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001107 }
Pengquan Menga62d32b2018-12-06 17:38:38 -08001108
1109 /**
1110 * Add a mapping from NR 5G status to the 5G icon. All the icon resources come from
1111 * {@link TelephonyIcons}.
1112 *
1113 * @param keyValuePair the NR 5G status and icon name separated by a colon.
1114 * @param config container that used to store the parsed configs.
1115 */
1116 @VisibleForTesting
1117 static void add5GIconMapping(String keyValuePair, Config config) {
1118 String[] kv = (keyValuePair.trim().toLowerCase()).split(":");
1119
1120 if (kv.length != 2) {
1121 if (DEBUG) Log.e(TAG, "Invalid 5G icon configuration, config = " + keyValuePair);
1122 return;
1123 }
1124
1125 String key = kv[0], value = kv[1];
1126
1127 // There is no icon config for the specific 5G status.
1128 if (value.equals("none")) return;
1129
1130 if (NR_STATUS_STRING_TO_INDEX.containsKey(key)
1131 && TelephonyIcons.ICON_NAME_TO_ICON.containsKey(value)) {
1132 config.nr5GIconMap.put(
1133 NR_STATUS_STRING_TO_INDEX.get(key),
1134 TelephonyIcons.ICON_NAME_TO_ICON.get(value));
1135 }
1136 }
John Spurlockaf8d6c42014-05-07 17:49:08 -04001137 }
1138}