blob: 12d357731560272e2aabdf475296f24ad8cd0c01 [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 -050027
John Spurlockaf8d6c42014-05-07 17:49:08 -040028import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
Jason Monk9c7844c2017-01-18 15:21:53 -050032import android.content.res.Configuration;
John Spurlockaf8d6c42014-05-07 17:49:08 -040033import android.content.res.Resources;
34import android.net.ConnectivityManager;
Anarghya Mitra678722f2018-05-11 14:29:54 -070035import android.net.Network;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090036import android.net.NetworkCapabilities;
John Spurlockaf8d6c42014-05-07 17:49:08 -040037import android.net.wifi.WifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040038import android.os.AsyncTask;
39import android.os.Bundle;
Jason Monk07b75fe2015-05-14 16:47:03 -040040import android.os.Handler;
Jason Monk30d80042015-05-08 16:54:18 -040041import android.os.Looper;
Wenting Xiong63364fe2017-02-07 19:12:27 +080042import android.os.PersistableBundle;
John Spurlockaf8d6c42014-05-07 17:49:08 -040043import android.provider.Settings;
Wenting Xiong63364fe2017-02-07 19:12:27 +080044import android.telephony.CarrierConfigManager;
Malcolm Chen50ba9632019-02-26 16:49:56 -080045import android.telephony.PhoneStateListener;
Jason Monkb0808aa2015-07-22 16:34:36 -040046import android.telephony.ServiceState;
Jason Monk48edc0c2017-04-10 15:01:27 -040047import android.telephony.SignalStrength;
Jason Monkb5746272014-11-12 16:50:31 -050048import android.telephony.SubscriptionInfo;
49import android.telephony.SubscriptionManager;
50import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
John Spurlockaf8d6c42014-05-07 17:49:08 -040051import android.telephony.TelephonyManager;
Jason Monkb5746272014-11-12 16:50:31 -050052import android.text.TextUtils;
Bill Lin767c0db2019-08-15 20:42:06 +080053import android.text.format.DateUtils;
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;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000067import com.android.systemui.broadcast.BroadcastDispatcher;
Dave Mankofff4736812019-10-18 17:25:50 -040068import com.android.systemui.dagger.qualifiers.BgLooper;
Jason Monk9c7844c2017-01-18 15:21:53 -050069import com.android.systemui.settings.CurrentUserTracker;
70import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
Pengquan Menga62d32b2018-12-06 17:38:38 -080071import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
John Spurlockaf8d6c42014-05-07 17:49:08 -040072
73import java.io.FileDescriptor;
74import java.io.PrintWriter;
75import java.util.ArrayList;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090076import java.util.BitSet;
Jason Monkb5746272014-11-12 16:50:31 -050077import java.util.Collections;
78import java.util.Comparator;
Pengquan Menga62d32b2018-12-06 17:38:38 -080079import java.util.HashMap;
John Spurlockaf8d6c42014-05-07 17:49:08 -040080import java.util.List;
81import java.util.Locale;
Pengquan Menga62d32b2018-12-06 17:38:38 -080082import java.util.Map;
John Spurlockaf8d6c42014-05-07 17:49:08 -040083
Jason Monk196d6392018-12-20 13:25:34 -050084import javax.inject.Inject;
Jason Monk196d6392018-12-20 13:25:34 -050085import javax.inject.Singleton;
86
John Spurlockaf8d6c42014-05-07 17:49:08 -040087/** Platform implementation of the network controller. **/
Jason Monk196d6392018-12-20 13:25:34 -050088@Singleton
John Spurlockaf8d6c42014-05-07 17:49:08 -040089public class NetworkControllerImpl extends BroadcastReceiver
Jason Monk9c7844c2017-01-18 15:21:53 -050090 implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider,
91 ConfigurationChangedReceiver, Dumpable {
John Spurlockaf8d6c42014-05-07 17:49:08 -040092 // debug
Jason Monkd2263cd2014-11-10 14:22:56 -050093 static final String TAG = "NetworkController";
94 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
95 // additional diagnostics, but not logspew
Jason Monk07b75fe2015-05-14 16:47:03 -040096 static final boolean CHATTY = Log.isLoggable(TAG + "Chat", Log.DEBUG);
John Spurlockaf8d6c42014-05-07 17:49:08 -040097
Jason Monk66845a32015-08-03 11:09:41 -040098 private static final int EMERGENCY_NO_CONTROLLERS = 0;
99 private static final int EMERGENCY_FIRST_CONTROLLER = 100;
100 private static final int EMERGENCY_VOICE_CONTROLLER = 200;
101 private static final int EMERGENCY_NO_SUB = 300;
Jason Monk8996b942017-03-02 13:58:19 -0500102 private static final int EMERGENCY_ASSUMED_VOICE_CONTROLLER = 400;
Jason Monk66845a32015-08-03 11:09:41 -0400103
Jason Monkd2263cd2014-11-10 14:22:56 -0500104 private final Context mContext;
105 private final TelephonyManager mPhone;
106 private final WifiManager mWifiManager;
107 private final ConnectivityManager mConnectivityManager;
Jason Monkb5746272014-11-12 16:50:31 -0500108 private final SubscriptionManager mSubscriptionManager;
Jason Monkd2263cd2014-11-10 14:22:56 -0500109 private final boolean mHasMobileDataFeature;
Jason Monkc6cc6262015-06-11 11:10:15 -0400110 private final SubscriptionDefaults mSubDefaults;
Jason Monk9a4ce132016-01-21 15:27:17 -0500111 private final DataSaverController mDataSaverController;
Jason Monk9c7844c2017-01-18 15:21:53 -0500112 private final CurrentUserTracker mUserTracker;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000113 private final BroadcastDispatcher mBroadcastDispatcher;
Evan Laird470ae842019-04-09 16:24:27 -0400114 private final Object mLock = new Object();
Jason Monk3aaabd72014-12-12 11:11:44 -0500115 private Config mConfig;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400116
Evan Laird470ae842019-04-09 16:24:27 -0400117 private PhoneStateListener mPhoneStateListener;
Malcolm Chen50ba9632019-02-26 16:49:56 -0800118 private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
119
Jason Monkd2263cd2014-11-10 14:22:56 -0500120 // Subcontrollers.
121 @VisibleForTesting
122 final WifiSignalController mWifiSignalController;
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900123
124 @VisibleForTesting
125 final EthernetSignalController mEthernetSignalController;
126
Jason Monkd2263cd2014-11-10 14:22:56 -0500127 @VisibleForTesting
Jason Monk8996b942017-03-02 13:58:19 -0500128 final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>();
Jason Monkb5746272014-11-12 16:50:31 -0500129 // When no SIMs are around at setup, and one is added later, it seems to default to the first
130 // SIM for most actions. This may be null if there aren't any SIMs around.
131 private MobileSignalController mDefaultSignalController;
Jason Monk0e2400f2014-11-21 11:08:55 -0500132 private final AccessPointControllerImpl mAccessPoints;
Jason Monkf668d7c2016-01-14 10:38:41 -0500133 private final DataUsageController mDataUsageController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400134
Jason Monkd2263cd2014-11-10 14:22:56 -0500135 private boolean mInetCondition; // Used for Logging and demo.
Lorenzo Colitti23dd1762014-09-10 22:58:54 +0900136
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900137 // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are
138 // connected and validated, respectively.
139 private final BitSet mConnectedTransports = new BitSet();
140 private final BitSet mValidatedTransports = new BitSet();
141
Jason Monkd2263cd2014-11-10 14:22:56 -0500142 // States that don't belong to a subcontroller.
John Spurlockaf8d6c42014-05-07 17:49:08 -0400143 private boolean mAirplaneMode = false;
Jason Monk1ff77662017-09-29 11:17:05 -0400144 private boolean mHasNoSubs;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400145 private Locale mLocale = null;
Jason Monkb5746272014-11-12 16:50:31 -0500146 // This list holds our ordering.
John Spurlockcf053c12015-05-14 16:33:59 -0400147 private List<SubscriptionInfo> mCurrentSubscriptions = new ArrayList<>();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400148
Jason Monkc014dec2014-12-12 11:49:55 -0500149 @VisibleForTesting
150 boolean mListening;
John Spurlock7f8f22a2014-07-02 18:54:17 -0400151
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900152 // The current user ID.
153 private int mCurrentUserId;
154
Jason Monk8fcab352015-06-29 10:57:00 -0400155 private OnSubscriptionsChangedListener mSubscriptionListener;
156
Jason Monk07b75fe2015-05-14 16:47:03 -0400157 // Handler that all broadcasts are received on.
158 private final Handler mReceiverHandler;
159 // Handler that all callbacks are made on.
160 private final CallbackHandler mCallbackHandler;
161
Jason Monk66845a32015-08-03 11:09:41 -0400162 private int mEmergencySource;
163 private boolean mIsEmergency;
164
Jason Monkb0808aa2015-07-22 16:34:36 -0400165 @VisibleForTesting
166 ServiceState mLastServiceState;
Jason Monkfd57ea72016-04-29 13:37:58 -0400167 private boolean mUserSetup;
Jason Monk1ff77662017-09-29 11:17:05 -0400168 private boolean mSimDetected;
Jason Monkb0808aa2015-07-22 16:34:36 -0400169
John Spurlockaf8d6c42014-05-07 17:49:08 -0400170 /**
171 * Construct this controller object and register for updates.
172 */
Jason Monk196d6392018-12-20 13:25:34 -0500173 @Inject
Dave Mankofff4736812019-10-18 17:25:50 -0400174 public NetworkControllerImpl(Context context, @BgLooper Looper bgLooper,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000175 DeviceProvisionedController deviceProvisionedController,
176 BroadcastDispatcher broadcastDispatcher) {
Jason Monkf13b4b32014-11-07 16:39:34 -0500177 this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
178 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
Jason Monk29f7a7b2014-11-17 14:40:56 -0500179 (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
Sundeep Ghuman9d10a3c2017-06-16 00:05:16 +0000180 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400181 new CallbackHandler(),
Tony Mantler0edf09b2017-09-28 15:03:37 -0700182 new AccessPointControllerImpl(context),
Jason Monkf668d7c2016-01-14 10:38:41 -0500183 new DataUsageController(context),
Jason Monk9c7844c2017-01-18 15:21:53 -0500184 new SubscriptionDefaults(),
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000185 deviceProvisionedController,
186 broadcastDispatcher);
Jason Monk07b75fe2015-05-14 16:47:03 -0400187 mReceiverHandler.post(mRegisterListeners);
Jason Monkf13b4b32014-11-07 16:39:34 -0500188 }
189
190 @VisibleForTesting
191 NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
Sundeep Ghuman9d10a3c2017-06-16 00:05:16 +0000192 TelephonyManager telephonyManager, WifiManager wifiManager,
193 SubscriptionManager subManager, Config config, Looper bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400194 CallbackHandler callbackHandler,
Jason Monkd2263cd2014-11-10 14:22:56 -0500195 AccessPointControllerImpl accessPointController,
Jason Monkf668d7c2016-01-14 10:38:41 -0500196 DataUsageController dataUsageController,
Jason Monk9c7844c2017-01-18 15:21:53 -0500197 SubscriptionDefaults defaultsHandler,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000198 DeviceProvisionedController deviceProvisionedController,
199 BroadcastDispatcher broadcastDispatcher) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400200 mContext = context;
Jason Monkb5746272014-11-12 16:50:31 -0500201 mConfig = config;
Jason Monk07b75fe2015-05-14 16:47:03 -0400202 mReceiverHandler = new Handler(bgLooper);
203 mCallbackHandler = callbackHandler;
Jason Monk9abca5e2016-11-11 16:18:14 -0500204 mDataSaverController = new DataSaverControllerImpl(context);
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000205 mBroadcastDispatcher = broadcastDispatcher;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400206
Jason Monkb5746272014-11-12 16:50:31 -0500207 mSubscriptionManager = subManager;
Jason Monkc6cc6262015-06-11 11:10:15 -0400208 mSubDefaults = defaultsHandler;
Jason Monkf13b4b32014-11-07 16:39:34 -0500209 mConnectivityManager = connectivityManager;
210 mHasMobileDataFeature =
211 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400212
John Spurlockaf8d6c42014-05-07 17:49:08 -0400213 // telephony
Jason Monk07b75fe2015-05-14 16:47:03 -0400214 mPhone = telephonyManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400215
216 // wifi
Jason Monkf13b4b32014-11-07 16:39:34 -0500217 mWifiManager = wifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400218
Jason Monkd2263cd2014-11-10 14:22:56 -0500219 mLocale = mContext.getResources().getConfiguration().locale;
Jason Monk29f7a7b2014-11-17 14:40:56 -0500220 mAccessPoints = accessPointController;
Jason Monkf668d7c2016-01-14 10:38:41 -0500221 mDataUsageController = dataUsageController;
222 mDataUsageController.setNetworkController(this);
223 // TODO: Find a way to move this into DataUsageController.
224 mDataUsageController.setCallback(new DataUsageController.Callback() {
Jason Monke0cdb602014-11-05 12:39:45 -0500225 @Override
226 public void onMobileDataEnabled(boolean enabled) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400227 mCallbackHandler.setMobileDataEnabled(enabled);
Evan Laird2ea99c12019-09-19 16:52:58 -0400228 notifyControllersMobileDataChanged();
Jason Monke0cdb602014-11-05 12:39:45 -0500229 }
230 });
Jason Monkd2263cd2014-11-10 14:22:56 -0500231 mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
Amin Shaikhc7593b12018-03-09 16:07:09 -0500232 mCallbackHandler, this, mWifiManager);
Jason Monkd2263cd2014-11-10 14:22:56 -0500233
Jason Monk07b75fe2015-05-14 16:47:03 -0400234 mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900235
Jason Monkd2263cd2014-11-10 14:22:56 -0500236 // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
Jason Monkb5746272014-11-12 16:50:31 -0500237 updateAirplaneMode(true /* force callback */);
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000238 mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
Jason Monk9c7844c2017-01-18 15:21:53 -0500239 @Override
240 public void onUserSwitched(int newUserId) {
241 NetworkControllerImpl.this.onUserSwitched(newUserId);
242 }
243 };
244 mUserTracker.startTracking();
245 deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
246 @Override
247 public void onUserSetupChanged() {
248 setUserSetupComplete(deviceProvisionedController.isUserSetup(
249 deviceProvisionedController.getCurrentUser()));
250 }
251 });
Anarghya Mitra678722f2018-05-11 14:29:54 -0700252
253 ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){
254 private Network mLastNetwork;
255 private NetworkCapabilities mLastNetworkCapabilities;
256
257 @Override
258 public void onCapabilitiesChanged(
259 Network network, NetworkCapabilities networkCapabilities) {
260 boolean lastValidated = (mLastNetworkCapabilities != null) &&
261 mLastNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
262 boolean validated =
263 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
264
265 // This callback is invoked a lot (i.e. when RSSI changes), so avoid updating
266 // icons when connectivity state has remained the same.
267 if (network.equals(mLastNetwork) &&
268 networkCapabilities.equalsTransportTypes(mLastNetworkCapabilities) &&
269 validated == lastValidated) {
270 return;
271 }
272 mLastNetwork = network;
273 mLastNetworkCapabilities = networkCapabilities;
274 updateConnectivity();
275 }
276 };
277 // Even though this callback runs on the receiver handler thread which also processes the
278 // CONNECTIVITY_ACTION broadcasts, the broadcast and callback might come in at different
279 // times. This is safe since updateConnectivity() builds the list of transports from
280 // scratch.
281 // TODO: Move off of the deprecated CONNECTIVITY_ACTION broadcast and rely on callbacks
282 // exclusively for status bar icons.
283 mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
Evan Laird470ae842019-04-09 16:24:27 -0400284 // Register the listener on our bg looper
Jayachandran Cff50c8e2019-10-30 16:41:59 -0700285 mPhoneStateListener = new PhoneStateListener(mReceiverHandler::post) {
Evan Laird470ae842019-04-09 16:24:27 -0400286 @Override
287 public void onActiveDataSubscriptionIdChanged(int subId) {
288 mActiveMobileDataSubscription = subId;
289 doUpdateMobileControllers();
290 }
291 };
Jason Monke0cdb602014-11-05 12:39:45 -0500292 }
293
Jason Monk9a4ce132016-01-21 15:27:17 -0500294 public DataSaverController getDataSaverController() {
295 return mDataSaverController;
296 }
297
Jason Monkf13b4b32014-11-07 16:39:34 -0500298 private void registerListeners() {
Jason Monk8996b942017-03-02 13:58:19 -0500299 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
300 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500301 mobileSignalController.registerListener();
302 }
Jason Monk8fcab352015-06-29 10:57:00 -0400303 if (mSubscriptionListener == null) {
304 mSubscriptionListener = new SubListener();
305 }
Wink Saville071743f2015-01-12 17:11:04 -0800306 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Malcolm Chen50ba9632019-02-26 16:49:56 -0800307 mPhone.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
Jason Monke0cdb602014-11-05 12:39:45 -0500308
John Spurlockaf8d6c42014-05-07 17:49:08 -0400309 // broadcasts
310 IntentFilter filter = new IntentFilter();
311 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
312 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
313 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
314 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jason Monkb5746272014-11-12 16:50:31 -0500315 filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
316 filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
Jason Monkb0808aa2015-07-22 16:34:36 -0400317 filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400318 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Erik Kline32830cc2015-04-21 13:09:15 +0900319 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400320 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400321 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
Roshan Piuse01f30b2019-07-16 08:49:29 -0700322 filter.addAction(Intent.ACTION_BOOT_COMPLETED);
Wenting Xiong63364fe2017-02-07 19:12:27 +0800323 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000324 mBroadcastDispatcher.registerReceiver(this, filter, mReceiverHandler);
Jason Monkb5746272014-11-12 16:50:31 -0500325 mListening = true;
326
327 updateMobileControllers();
John Spurlockb98f7472014-07-08 17:09:42 -0400328 }
329
Jason Monkd2263cd2014-11-10 14:22:56 -0500330 private void unregisterListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500331 mListening = false;
Jason Monk8996b942017-03-02 13:58:19 -0500332 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
333 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500334 mobileSignalController.unregisterListener();
335 }
Wink Saville071743f2015-01-12 17:11:04 -0800336 mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monkd2263cd2014-11-10 14:22:56 -0500337 mContext.unregisterReceiver(this);
Jason Monk5d325072014-10-27 11:38:47 -0400338 }
339
Jason Monk0e2400f2014-11-21 11:08:55 -0500340 public int getConnectedWifiLevel() {
341 return mWifiSignalController.getState().level;
342 }
343
Jason Monk5d325072014-10-27 11:38:47 -0400344 @Override
Jason Monkd2263cd2014-11-10 14:22:56 -0500345 public AccessPointController getAccessPointController() {
346 return mAccessPoints;
347 }
348
349 @Override
Jason Monkf668d7c2016-01-14 10:38:41 -0500350 public DataUsageController getMobileDataController() {
351 return mDataUsageController;
Jason Monkd2263cd2014-11-10 14:22:56 -0500352 }
353
354 public void addEmergencyListener(EmergencyListener listener) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400355 mCallbackHandler.setListening(listener, true);
356 mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400357 }
358
Jason Monk46dbfb42016-02-25 14:59:20 -0500359 public void removeEmergencyListener(EmergencyListener listener) {
360 mCallbackHandler.setListening(listener, false);
361 }
362
John Spurlockaf8d6c42014-05-07 17:49:08 -0400363 public boolean hasMobileDataFeature() {
364 return mHasMobileDataFeature;
365 }
366
367 public boolean hasVoiceCallingFeature() {
368 return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
369 }
370
Jason Monkb5746272014-11-12 16:50:31 -0500371 private MobileSignalController getDataController() {
Fabian Kozynskiccde55d2019-06-26 10:06:09 -0400372 int dataSubId = mSubDefaults.getActiveDataSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800373 if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
Jason Monkb5746272014-11-12 16:50:31 -0500374 if (DEBUG) Log.e(TAG, "No data sim selected");
375 return mDefaultSignalController;
376 }
Jason Monk8996b942017-03-02 13:58:19 -0500377 if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500378 return mMobileSignalControllers.get(dataSubId);
379 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500380 if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
Jason Monkb5746272014-11-12 16:50:31 -0500381 return mDefaultSignalController;
382 }
383
Amin Shaikh329c8282018-03-09 14:50:59 -0500384 @Override
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700385 public String getMobileDataNetworkName() {
Jason Monkb5746272014-11-12 16:50:31 -0500386 MobileSignalController controller = getDataController();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700387 return controller != null ? controller.getState().networkNameData : "";
Jason Monkd2263cd2014-11-10 14:22:56 -0500388 }
389
Fabian Kozynskif1c32a02019-03-22 15:09:30 -0400390 @Override
391 public int getNumberSubscriptions() {
392 return mMobileSignalControllers.size();
393 }
394
Evan Laird2ea99c12019-09-19 16:52:58 -0400395 boolean isDataControllerDisabled() {
396 MobileSignalController dataController = getDataController();
397 if (dataController == null) {
398 return false;
399 }
400
401 return dataController.isDataDisabled();
402 }
403
404 private void notifyControllersMobileDataChanged() {
405 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
406 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
407 mobileSignalController.onMobileDataChanged();
408 }
409 }
410
John Spurlockaf8d6c42014-05-07 17:49:08 -0400411 public boolean isEmergencyOnly() {
Jason Monkb0808aa2015-07-22 16:34:36 -0400412 if (mMobileSignalControllers.size() == 0) {
413 // When there are no active subscriptions, determine emengency state from last
414 // broadcast.
Jason Monk66845a32015-08-03 11:09:41 -0400415 mEmergencySource = EMERGENCY_NO_CONTROLLERS;
Jason Monkb0808aa2015-07-22 16:34:36 -0400416 return mLastServiceState != null && mLastServiceState.isEmergencyOnly();
417 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400418 int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800419 if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
Jason Monk8996b942017-03-02 13:58:19 -0500420 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
421 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkc6cc6262015-06-11 11:10:15 -0400422 if (!mobileSignalController.getState().isEmergency) {
Jason Monk66845a32015-08-03 11:09:41 -0400423 mEmergencySource = EMERGENCY_FIRST_CONTROLLER
424 + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400425 if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag);
Jason Monkb5746272014-11-12 16:50:31 -0500426 return false;
427 }
428 }
429 }
Jason Monk8996b942017-03-02 13:58:19 -0500430 if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) {
Jason Monk66845a32015-08-03 11:09:41 -0400431 mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
Jason Monkc6cc6262015-06-11 11:10:15 -0400432 if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
433 return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
Jason Monkb5746272014-11-12 16:50:31 -0500434 }
Jason Monk8996b942017-03-02 13:58:19 -0500435 // If we have the wrong subId but there is only one sim anyway, assume it should be the
436 // default.
437 if (mMobileSignalControllers.size() == 1) {
438 mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER
439 + mMobileSignalControllers.keyAt(0);
440 if (DEBUG) Log.d(TAG, "Getting assumed emergency from "
441 + mMobileSignalControllers.keyAt(0));
442 return mMobileSignalControllers.valueAt(0).getState().isEmergency;
443 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500444 if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
Jason Monk66845a32015-08-03 11:09:41 -0400445 mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
Jason Monkb5746272014-11-12 16:50:31 -0500446 // Something is wrong, better assume we can't make calls...
447 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400448 }
449
Jason Monkd2263cd2014-11-10 14:22:56 -0500450 /**
451 * Emergency status may have changed (triggered by MobileSignalController),
452 * so we should recheck and send out the state to listeners.
453 */
454 void recalculateEmergency() {
Jason Monk66845a32015-08-03 11:09:41 -0400455 mIsEmergency = isEmergencyOnly();
456 mCallbackHandler.setEmergencyCallsOnly(mIsEmergency);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400457 }
458
Jason Monk88529052016-11-04 13:29:58 -0400459 public void addCallback(SignalCallback cb) {
Jason Monke06b0652016-03-02 16:35:27 -0500460 cb.setSubs(mCurrentSubscriptions);
461 cb.setIsAirplaneMode(new IconState(mAirplaneMode,
Jason Monk07b75fe2015-05-14 16:47:03 -0400462 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monk1ff77662017-09-29 11:17:05 -0400463 cb.setNoSims(mHasNoSubs, mSimDetected);
Jason Monke06b0652016-03-02 16:35:27 -0500464 mWifiSignalController.notifyListeners(cb);
465 mEthernetSignalController.notifyListeners(cb);
Jason Monk8996b942017-03-02 13:58:19 -0500466 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
467 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monke06b0652016-03-02 16:35:27 -0500468 mobileSignalController.notifyListeners(cb);
Jason Monkb5746272014-11-12 16:50:31 -0500469 }
Jason Monke06b0652016-03-02 16:35:27 -0500470 mCallbackHandler.setListening(cb, true);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400471 }
472
Jason Monk07b75fe2015-05-14 16:47:03 -0400473 @Override
Jason Monk88529052016-11-04 13:29:58 -0400474 public void removeCallback(SignalCallback cb) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400475 mCallbackHandler.setListening(cb, false);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400476 }
477
478 @Override
479 public void setWifiEnabled(final boolean enabled) {
480 new AsyncTask<Void, Void, Void>() {
481 @Override
482 protected Void doInBackground(Void... args) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400483 mWifiManager.setWifiEnabled(enabled);
484 return null;
485 }
486 }.execute();
487 }
488
Jason Monk9c7844c2017-01-18 15:21:53 -0500489 private void onUserSwitched(int newUserId) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900490 mCurrentUserId = newUserId;
491 mAccessPoints.onUserSwitched(newUserId);
492 updateConnectivity();
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900493 }
494
495 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400496 public void onReceive(Context context, Intent intent) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500497 if (CHATTY) {
498 Log.d(TAG, "onReceive: intent=" + intent);
499 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400500 final String action = intent.getAction();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800501 switch (action) {
502 case ConnectivityManager.CONNECTIVITY_ACTION:
503 case ConnectivityManager.INET_CONDITION_ACTION:
504 updateConnectivity();
505 break;
506 case Intent.ACTION_AIRPLANE_MODE_CHANGED:
507 refreshLocale();
508 updateAirplaneMode(false);
509 break;
510 case TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
511 // We are using different subs now, we might be able to make calls.
Jason Monkb0808aa2015-07-22 16:34:36 -0400512 recalculateEmergency();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800513 break;
514 case TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
515 // Notify every MobileSignalController so they can know whether they are the
516 // data sim or not.
517 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
518 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
519 controller.handleBroadcast(intent);
Wenting Xiong63364fe2017-02-07 19:12:27 +0800520 }
Niklas Lindgrena02964d2018-09-21 14:01:57 +0200521 mConfig = Config.readConfig(mContext);
522 mReceiverHandler.post(this::handleConfigurationChanged);
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800523 break;
524 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
525 // Avoid rebroadcast because SysUI is direct boot aware.
526 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
527 break;
528 }
529 // Might have different subscriptions now.
530 updateMobileControllers();
531 break;
532 case TelephonyIntents.ACTION_SERVICE_STATE_CHANGED:
533 mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
534 if (mMobileSignalControllers.size() == 0) {
535 // If none of the subscriptions are active, we might need to recalculate
536 // emergency state.
537 recalculateEmergency();
538 }
539 break;
Roshan Piuse01f30b2019-07-16 08:49:29 -0700540 case Intent.ACTION_BOOT_COMPLETED:
541 mWifiSignalController.handleBootCompleted();
542 break;
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800543 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
544 mConfig = Config.readConfig(mContext);
545 mReceiverHandler.post(this::handleConfigurationChanged);
546 break;
547 default:
548 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
549 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
550 if (SubscriptionManager.isValidSubscriptionId(subId)) {
551 if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
552 mMobileSignalControllers.get(subId).handleBroadcast(intent);
553 } else {
554 // Can't find this subscription... We must be out of date.
555 updateMobileControllers();
556 }
Jason Monkb5746272014-11-12 16:50:31 -0500557 } else {
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800558 // No sub id, must be for the wifi.
559 mWifiSignalController.handleBroadcast(intent);
Jason Monkb5746272014-11-12 16:50:31 -0500560 }
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800561 break;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400562 }
Jason Monkb5746272014-11-12 16:50:31 -0500563 }
564
Jason Monk9c7844c2017-01-18 15:21:53 -0500565 public void onConfigurationChanged(Configuration newConfig) {
Sungmin Choi6be4f6b2015-07-07 13:06:59 +0900566 mConfig = Config.readConfig(mContext);
Jason Monk1c040db2015-07-20 09:45:54 -0400567 mReceiverHandler.post(new Runnable() {
568 @Override
569 public void run() {
570 handleConfigurationChanged();
571 }
572 });
573 }
574
575 @VisibleForTesting
576 void handleConfigurationChanged() {
Malcolm Chen50ba9632019-02-26 16:49:56 -0800577 updateMobileControllers();
Jason Monk8996b942017-03-02 13:58:19 -0500578 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
579 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
580 controller.setConfiguration(mConfig);
Jason Monk3aaabd72014-12-12 11:11:44 -0500581 }
582 refreshLocale();
Jason Monk3aaabd72014-12-12 11:11:44 -0500583 }
584
Jason Monkb5746272014-11-12 16:50:31 -0500585 private void updateMobileControllers() {
586 if (!mListening) {
587 return;
588 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400589 doUpdateMobileControllers();
590 }
591
Malcolm Chen50ba9632019-02-26 16:49:56 -0800592 private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) {
593 if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) {
594 SubscriptionInfo info1 = subscriptions.get(0);
595 SubscriptionInfo info2 = subscriptions.get(1);
596 if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) {
597 // If both subscriptions are primary, show both.
598 if (!info1.isOpportunistic() && !info2.isOpportunistic()) return;
599
600 // If carrier required, always show signal bar of primary subscription.
601 // Otherwise, show whichever subscription is currently active for Internet.
602 boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig()
603 .getBoolean(CarrierConfigManager
604 .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN);
605 if (alwaysShowPrimary) {
606 subscriptions.remove(info1.isOpportunistic() ? info1 : info2);
607 } else {
608 subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription
609 ? info2 : info1);
610 }
611 }
612 }
613 }
614
Jason Monkc6cc6262015-06-11 11:10:15 -0400615 @VisibleForTesting
616 void doUpdateMobileControllers() {
Malcolm Chend2d400cb2018-12-21 17:11:10 -0800617 List<SubscriptionInfo> subscriptions = mSubscriptionManager
Malcolm Chen50ba9632019-02-26 16:49:56 -0800618 .getActiveSubscriptionInfoList(false);
Jason Monkc9f05712014-12-15 12:24:10 -0500619 if (subscriptions == null) {
620 subscriptions = Collections.emptyList();
621 }
Malcolm Chen50ba9632019-02-26 16:49:56 -0800622
623 filterMobileSubscriptionInSameGroup(subscriptions);
624
Jason Monkb5746272014-11-12 16:50:31 -0500625 // If there have been no relevant changes to any of the subscriptions, we can leave as is.
626 if (hasCorrectMobileControllers(subscriptions)) {
627 // Even if the controllers are correct, make sure we have the right no sims state.
628 // Such as on boot, don't need any controllers, because there are no sims,
629 // but we still need to update the no sim state.
630 updateNoSims();
631 return;
632 }
Evan Laird470ae842019-04-09 16:24:27 -0400633 synchronized (mLock) {
634 setCurrentSubscriptionsLocked(subscriptions);
635 }
Jason Monkb5746272014-11-12 16:50:31 -0500636 updateNoSims();
Jason Monkc6cc6262015-06-11 11:10:15 -0400637 recalculateEmergency();
Jason Monkb5746272014-11-12 16:50:31 -0500638 }
639
Jason Monk21d05a02014-12-02 12:46:58 -0500640 @VisibleForTesting
641 protected void updateNoSims() {
Jason Monk1ff77662017-09-29 11:17:05 -0400642 boolean hasNoSubs = mHasMobileDataFeature && mMobileSignalControllers.size() == 0;
643 boolean simDetected = hasAnySim();
644 if (hasNoSubs != mHasNoSubs || simDetected != mSimDetected) {
645 mHasNoSubs = hasNoSubs;
646 mSimDetected = simDetected;
647 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
Jason Monkb5746272014-11-12 16:50:31 -0500648 }
649 }
650
Jason Monk1ff77662017-09-29 11:17:05 -0400651 private boolean hasAnySim() {
Jayachandran Ca43d0a72019-11-01 17:39:38 -0700652 int simCount = mPhone.getActiveModemCount();
Jason Monk1ff77662017-09-29 11:17:05 -0400653 for (int i = 0; i < simCount; i++) {
654 int state = mPhone.getSimState(i);
655 if (state != TelephonyManager.SIM_STATE_ABSENT
656 && state != TelephonyManager.SIM_STATE_UNKNOWN) {
657 return true;
658 }
659 }
660 return false;
661 }
662
Evan Laird470ae842019-04-09 16:24:27 -0400663 @GuardedBy("mLock")
Jason Monkb5746272014-11-12 16:50:31 -0500664 @VisibleForTesting
Evan Laird470ae842019-04-09 16:24:27 -0400665 public void setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions) {
Jason Monkb5746272014-11-12 16:50:31 -0500666 Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() {
667 @Override
668 public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) {
669 return lhs.getSimSlotIndex() == rhs.getSimSlotIndex()
670 ? lhs.getSubscriptionId() - rhs.getSubscriptionId()
671 : lhs.getSimSlotIndex() - rhs.getSimSlotIndex();
672 }
673 });
Jason Monkb5746272014-11-12 16:50:31 -0500674 mCurrentSubscriptions = subscriptions;
675
Jason Monk8996b942017-03-02 13:58:19 -0500676 SparseArray<MobileSignalController> cachedControllers =
677 new SparseArray<MobileSignalController>();
678 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
679 cachedControllers.put(mMobileSignalControllers.keyAt(i),
680 mMobileSignalControllers.valueAt(i));
681 }
Jason Monkb5746272014-11-12 16:50:31 -0500682 mMobileSignalControllers.clear();
683 final int num = subscriptions.size();
684 for (int i = 0; i < num; i++) {
685 int subId = subscriptions.get(i).getSubscriptionId();
686 // If we have a copy of this controller already reuse it, otherwise make a new one.
Jason Monk8996b942017-03-02 13:58:19 -0500687 if (cachedControllers.indexOfKey(subId) >= 0) {
688 mMobileSignalControllers.put(subId, cachedControllers.get(subId));
689 cachedControllers.remove(subId);
Jason Monkb5746272014-11-12 16:50:31 -0500690 } else {
691 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
chen xu84a90872019-03-28 15:44:12 -0700692 mHasMobileDataFeature, mPhone.createForSubscriptionId(subId),
693 mCallbackHandler, this, subscriptions.get(i),
694 mSubDefaults, mReceiverHandler.getLooper());
Jason Monkfd57ea72016-04-29 13:37:58 -0400695 controller.setUserSetupComplete(mUserSetup);
Jason Monkb5746272014-11-12 16:50:31 -0500696 mMobileSignalControllers.put(subId, controller);
697 if (subscriptions.get(i).getSimSlotIndex() == 0) {
698 mDefaultSignalController = controller;
699 }
700 if (mListening) {
701 controller.registerListener();
702 }
703 }
704 }
705 if (mListening) {
Jason Monk8996b942017-03-02 13:58:19 -0500706 for (int i = 0; i < cachedControllers.size(); i++) {
707 int key = cachedControllers.keyAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500708 if (cachedControllers.get(key) == mDefaultSignalController) {
709 mDefaultSignalController = null;
710 }
711 cachedControllers.get(key).unregisterListener();
712 }
713 }
Jason Monk8fcab352015-06-29 10:57:00 -0400714 mCallbackHandler.setSubs(subscriptions);
715 notifyAllListeners();
716
Jason Monk25d8a482014-12-09 12:27:24 -0500717 // There may be new MobileSignalControllers around, make sure they get the current
718 // inet condition and airplane mode.
719 pushConnectivityToSignals();
720 updateAirplaneMode(true /* force */);
Jason Monkb5746272014-11-12 16:50:31 -0500721 }
722
Jason Monk0288de02017-02-23 14:48:05 -0500723 private void setUserSetupComplete(final boolean userSetup) {
724 mReceiverHandler.post(() -> handleSetUserSetupComplete(userSetup));
Jason Monkfd57ea72016-04-29 13:37:58 -0400725 }
726
Jason Monk0288de02017-02-23 14:48:05 -0500727 private void handleSetUserSetupComplete(boolean userSetup) {
Jason Monkfd57ea72016-04-29 13:37:58 -0400728 mUserSetup = userSetup;
Jason Monk8996b942017-03-02 13:58:19 -0500729 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
730 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkfd57ea72016-04-29 13:37:58 -0400731 controller.setUserSetupComplete(mUserSetup);
732 }
733 }
734
Jason Monkc014dec2014-12-12 11:49:55 -0500735 @VisibleForTesting
736 boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) {
Jason Monkc9f05712014-12-15 12:24:10 -0500737 if (allSubscriptions.size() != mMobileSignalControllers.size()) {
738 return false;
Jason Monkb5746272014-11-12 16:50:31 -0500739 }
740 for (SubscriptionInfo info : allSubscriptions) {
Jason Monk8996b942017-03-02 13:58:19 -0500741 if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500742 return false;
743 }
744 }
745 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400746 }
747
Jason Monkd2263cd2014-11-10 14:22:56 -0500748 private void updateAirplaneMode(boolean force) {
749 boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
750 Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
751 if (airplaneMode != mAirplaneMode || force) {
752 mAirplaneMode = airplaneMode;
Jason Monk8996b942017-03-02 13:58:19 -0500753 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
754 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500755 mobileSignalController.setAirplaneMode(mAirplaneMode);
756 }
757 notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400758 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400759 }
760
761 private void refreshLocale() {
Jason Monkd2263cd2014-11-10 14:22:56 -0500762 Locale current = mContext.getResources().getConfiguration().locale;
Jason Monkb5746272014-11-12 16:50:31 -0500763 if (!current.equals(mLocale)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500764 mLocale = current;
Fabian Kozynskid9cb3842018-09-28 13:34:14 -0400765 mWifiSignalController.refreshLocale();
Jason Monkd2263cd2014-11-10 14:22:56 -0500766 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400767 }
768 }
769
Jason Monkd2263cd2014-11-10 14:22:56 -0500770 /**
Jason Monkb5746272014-11-12 16:50:31 -0500771 * Forces update of all callbacks on both SignalClusters and
772 * NetworkSignalChangedCallbacks.
773 */
Jason Monkd2263cd2014-11-10 14:22:56 -0500774 private void notifyAllListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500775 notifyListeners();
Jason Monk8996b942017-03-02 13:58:19 -0500776 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
777 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500778 mobileSignalController.notifyListeners();
779 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500780 mWifiSignalController.notifyListeners();
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900781 mEthernetSignalController.notifyListeners();
Jason Monkd2263cd2014-11-10 14:22:56 -0500782 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400783
Jason Monkb5746272014-11-12 16:50:31 -0500784 /**
785 * Notifies listeners of changes in state of to the NetworkController, but
786 * does not notify for any info on SignalControllers, for that call
787 * notifyAllListeners.
788 */
789 private void notifyListeners() {
Jason Monk07b75fe2015-05-14 16:47:03 -0400790 mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
791 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monk1ff77662017-09-29 11:17:05 -0400792 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400793 }
794
Jason Monkd2263cd2014-11-10 14:22:56 -0500795 /**
796 * Update the Inet conditions and what network we are connected to.
797 */
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900798 private void updateConnectivity() {
799 mConnectedTransports.clear();
800 mValidatedTransports.clear();
801 for (NetworkCapabilities nc :
802 mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
803 for (int transportType : nc.getTransportTypes()) {
804 mConnectedTransports.set(transportType);
805 if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
806 mValidatedTransports.set(transportType);
807 }
808 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400809 }
810
John Spurlockaf8d6c42014-05-07 17:49:08 -0400811 if (CHATTY) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900812 Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
813 Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400814 }
815
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900816 mInetCondition = !mValidatedTransports.isEmpty();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400817
Jason Monk25d8a482014-12-09 12:27:24 -0500818 pushConnectivityToSignals();
819 }
820
821 /**
822 * Pushes the current connectivity state to all SignalControllers.
823 */
824 private void pushConnectivityToSignals() {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400825 // We want to update all the icons, all at once, for any condition change
Jason Monk8996b942017-03-02 13:58:19 -0500826 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
827 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400828 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
Jason Monkb5746272014-11-12 16:50:31 -0500829 }
Jason Monk33f8ae72015-05-08 10:45:15 -0400830 mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
831 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400832 }
833
John Spurlockaf8d6c42014-05-07 17:49:08 -0400834 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
835 pw.println("NetworkController state:");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900836
John Spurlockaf8d6c42014-05-07 17:49:08 -0400837 pw.println(" - telephony ------");
838 pw.print(" hasVoiceCallingFeature()=");
839 pw.println(hasVoiceCallingFeature());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400840
John Spurlockaf8d6c42014-05-07 17:49:08 -0400841 pw.println(" - connectivity ------");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900842 pw.print(" mConnectedTransports=");
843 pw.println(mConnectedTransports);
844 pw.print(" mValidatedTransports=");
845 pw.println(mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400846 pw.print(" mInetCondition=");
847 pw.println(mInetCondition);
Jason Monkd2263cd2014-11-10 14:22:56 -0500848 pw.print(" mAirplaneMode=");
849 pw.println(mAirplaneMode);
850 pw.print(" mLocale=");
851 pw.println(mLocale);
Jason Monkb0808aa2015-07-22 16:34:36 -0400852 pw.print(" mLastServiceState=");
853 pw.println(mLastServiceState);
Jason Monk66845a32015-08-03 11:09:41 -0400854 pw.print(" mIsEmergency=");
855 pw.println(mIsEmergency);
856 pw.print(" mEmergencySource=");
857 pw.println(emergencyToString(mEmergencySource));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400858
Bill Lin767c0db2019-08-15 20:42:06 +0800859 pw.println(" - config ------");
860 pw.print(" patternOfCarrierSpecificDataIcon=");
861 pw.println(mConfig.patternOfCarrierSpecificDataIcon);
862 pw.print(" nr5GIconMap=");
863 pw.println(mConfig.nr5GIconMap.toString());
864 pw.print(" nrIconDisplayGracePeriodMs=");
865 pw.println(mConfig.nrIconDisplayGracePeriodMs);
Jason Monk8996b942017-03-02 13:58:19 -0500866 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
867 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500868 mobileSignalController.dump(pw);
869 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500870 mWifiSignalController.dump(pw);
Jason Monkd52356a2015-01-28 10:40:41 -0500871
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900872 mEthernetSignalController.dump(pw);
873
Jason Monkd52356a2015-01-28 10:40:41 -0500874 mAccessPoints.dump(pw);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400875 }
876
Jason Monk66845a32015-08-03 11:09:41 -0400877 private static final String emergencyToString(int emergencySource) {
878 if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk8996b942017-03-02 13:58:19 -0500879 return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER)
880 + ")";
881 } else if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk66845a32015-08-03 11:09:41 -0400882 return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
883 } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
884 return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
885 } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) {
886 return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")";
887 } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) {
888 return "NO_CONTROLLERS";
889 }
890 return "UNKNOWN_SOURCE";
891 }
892
John Spurlockaf8d6c42014-05-07 17:49:08 -0400893 private boolean mDemoMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400894 private boolean mDemoInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500895 private WifiSignalController.WifiState mDemoWifiState;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400896
897 @Override
898 public void dispatchDemoCommand(String command, Bundle args) {
899 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500900 if (DEBUG) Log.d(TAG, "Entering demo mode");
901 unregisterListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400902 mDemoMode = true;
Jason Monk33f8ae72015-05-08 10:45:15 -0400903 mDemoInetCondition = mInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500904 mDemoWifiState = mWifiSignalController.getState();
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100905 mDemoWifiState.ssid = "DemoMode";
John Spurlockaf8d6c42014-05-07 17:49:08 -0400906 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500907 if (DEBUG) Log.d(TAG, "Exiting demo mode");
John Spurlockaf8d6c42014-05-07 17:49:08 -0400908 mDemoMode = false;
Jason Monkb5746272014-11-12 16:50:31 -0500909 // Update what MobileSignalControllers, because they may change
910 // to set the number of sim slots.
911 updateMobileControllers();
Jason Monk8996b942017-03-02 13:58:19 -0500912 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
913 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500914 controller.resetLastState();
915 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500916 mWifiSignalController.resetLastState();
Jason Monk07b75fe2015-05-14 16:47:03 -0400917 mReceiverHandler.post(mRegisterListeners);
Jason Monkd2263cd2014-11-10 14:22:56 -0500918 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400919 } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
920 String airplane = args.getString("airplane");
921 if (airplane != null) {
922 boolean show = airplane.equals("show");
Jason Monk07b75fe2015-05-14 16:47:03 -0400923 mCallbackHandler.setIsAirplaneMode(new IconState(show,
924 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode,
925 mContext));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400926 }
927 String fully = args.getString("fully");
928 if (fully != null) {
Jason Monk33f8ae72015-05-08 10:45:15 -0400929 mDemoInetCondition = Boolean.parseBoolean(fully);
930 BitSet connected = new BitSet();
931
932 if (mDemoInetCondition) {
933 connected.set(mWifiSignalController.mTransportType);
934 }
935 mWifiSignalController.updateConnectivity(connected, connected);
Jason Monk8996b942017-03-02 13:58:19 -0500936 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
937 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400938 if (mDemoInetCondition) {
939 connected.set(controller.mTransportType);
940 }
941 controller.updateConnectivity(connected, connected);
Jason Monkb5746272014-11-12 16:50:31 -0500942 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400943 }
944 String wifi = args.getString("wifi");
945 if (wifi != null) {
946 boolean show = wifi.equals("show");
947 String level = args.getString("level");
948 if (level != null) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500949 mDemoWifiState.level = level.equals("null") ? -1
John Spurlockaf8d6c42014-05-07 17:49:08 -0400950 : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
Jason Monkd2263cd2014-11-10 14:22:56 -0500951 mDemoWifiState.connected = mDemoWifiState.level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400952 }
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100953 String activity = args.getString("activity");
954 if (activity != null) {
955 switch (activity) {
956 case "inout":
Roshan Pius80fb1372018-07-16 15:43:03 -0700957 mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100958 break;
959 case "in":
Roshan Pius80fb1372018-07-16 15:43:03 -0700960 mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100961 break;
962 case "out":
Roshan Pius80fb1372018-07-16 15:43:03 -0700963 mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100964 break;
965 default:
Roshan Pius80fb1372018-07-16 15:43:03 -0700966 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100967 break;
968 }
969 } else {
Roshan Pius80fb1372018-07-16 15:43:03 -0700970 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100971 }
Evan Laird27a99572017-09-27 14:09:30 -0400972 String ssid = args.getString("ssid");
973 if (ssid != null) {
974 mDemoWifiState.ssid = ssid;
975 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500976 mDemoWifiState.enabled = show;
977 mWifiSignalController.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400978 }
Jason Monkb5746272014-11-12 16:50:31 -0500979 String sims = args.getString("sims");
980 if (sims != null) {
John Spurlockcf053c12015-05-14 16:33:59 -0400981 int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
982 List<SubscriptionInfo> subs = new ArrayList<>();
Jason Monkb5746272014-11-12 16:50:31 -0500983 if (num != mMobileSignalControllers.size()) {
984 mMobileSignalControllers.clear();
985 int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
986 for (int i = start /* get out of normal index range */; i < start + num; i++) {
John Spurlockcf053c12015-05-14 16:33:59 -0400987 subs.add(addSignalController(i, i));
Jason Monkb5746272014-11-12 16:50:31 -0500988 }
Jason Monk33b60bb2015-07-13 10:42:23 -0400989 mCallbackHandler.setSubs(subs);
Evan Lairde1d13c92018-03-20 16:58:01 -0400990 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
991 int key = mMobileSignalControllers.keyAt(i);
992 MobileSignalController controller = mMobileSignalControllers.get(key);
993 controller.notifyListeners();
994 }
Jason Monkb5746272014-11-12 16:50:31 -0500995 }
Jason Monkb5746272014-11-12 16:50:31 -0500996 }
997 String nosim = args.getString("nosim");
998 if (nosim != null) {
Jason Monk1ff77662017-09-29 11:17:05 -0400999 mHasNoSubs = nosim.equals("show");
1000 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected);
Jason Monkb5746272014-11-12 16:50:31 -05001001 }
John Spurlockaf8d6c42014-05-07 17:49:08 -04001002 String mobile = args.getString("mobile");
1003 if (mobile != null) {
1004 boolean show = mobile.equals("show");
1005 String datatype = args.getString("datatype");
Jason Monkb5746272014-11-12 16:50:31 -05001006 String slotString = args.getString("slot");
1007 int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
John Spurlockcf053c12015-05-14 16:33:59 -04001008 slot = MathUtils.constrain(slot, 0, 8);
1009 // Ensure we have enough sim slots
1010 List<SubscriptionInfo> subs = new ArrayList<>();
1011 while (mMobileSignalControllers.size() <= slot) {
1012 int nextSlot = mMobileSignalControllers.size();
1013 subs.add(addSignalController(nextSlot, nextSlot));
1014 }
1015 if (!subs.isEmpty()) {
Jason Monk07b75fe2015-05-14 16:47:03 -04001016 mCallbackHandler.setSubs(subs);
John Spurlockcf053c12015-05-14 16:33:59 -04001017 }
Jason Monkb5746272014-11-12 16:50:31 -05001018 // Hack to index linearly for easy use.
Jason Monk8996b942017-03-02 13:58:19 -05001019 MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
Jason Monkb5746272014-11-12 16:50:31 -05001020 controller.getState().dataSim = datatype != null;
Jason Monkb5950982017-01-24 15:53:53 -05001021 controller.getState().isDefault = datatype != null;
1022 controller.getState().dataConnected = datatype != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001023 if (datatype != null) {
Jason Monkb5746272014-11-12 16:50:31 -05001024 controller.getState().iconGroup =
Jason Monkd2263cd2014-11-10 14:22:56 -05001025 datatype.equals("1x") ? TelephonyIcons.ONE_X :
1026 datatype.equals("3g") ? TelephonyIcons.THREE_G :
1027 datatype.equals("4g") ? TelephonyIcons.FOUR_G :
Ajay Nambi7965fa42015-05-14 18:48:33 -07001028 datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
Bill Lin767c0db2019-08-15 20:42:06 +08001029 datatype.equals("5g") ? TelephonyIcons.NR_5G :
1030 datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -05001031 datatype.equals("e") ? TelephonyIcons.E :
1032 datatype.equals("g") ? TelephonyIcons.G :
1033 datatype.equals("h") ? TelephonyIcons.H :
Amin Shaikhf5830ca2018-03-09 14:06:50 -05001034 datatype.equals("h+") ? TelephonyIcons.H_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -05001035 datatype.equals("lte") ? TelephonyIcons.LTE :
Jason Monkaa730be2016-07-13 14:22:52 -04001036 datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
Jason Monk7e6c83c2017-04-26 14:35:24 -04001037 datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
Fabian Kozynskic7bc84b2019-03-11 13:57:31 -04001038 datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA :
Jason Monkd2263cd2014-11-10 14:22:56 -05001039 TelephonyIcons.UNKNOWN;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001040 }
Jason Monk0f0de132016-12-19 15:36:13 -05001041 if (args.containsKey("roam")) {
1042 controller.getState().roaming = "show".equals(args.getString("roam"));
1043 }
John Spurlockaf8d6c42014-05-07 17:49:08 -04001044 String level = args.getString("level");
1045 if (level != null) {
Jason Monkb5746272014-11-12 16:50:31 -05001046 controller.getState().level = level.equals("null") ? -1
Jason Monk48edc0c2017-04-10 15:01:27 -04001047 : Math.min(Integer.parseInt(level),
1048 SignalStrength.NUM_SIGNAL_STRENGTH_BINS);
Jason Monkb5746272014-11-12 16:50:31 -05001049 controller.getState().connected = controller.getState().level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001050 }
Amin Shaikh0ad7e512019-04-29 07:36:34 -04001051 if (args.containsKey("inflate")) {
1052 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
1053 mMobileSignalControllers.valueAt(i).mInflateSignalStrengths =
1054 "true".equals(args.getString("inflate"));
1055 }
1056 }
Jason Monk0f0de132016-12-19 15:36:13 -05001057 String activity = args.getString("activity");
1058 if (activity != null) {
Kenneth Westin5c88ffb2013-11-28 16:29:40 +01001059 controller.getState().dataConnected = true;
1060 switch (activity) {
1061 case "inout":
1062 controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
1063 break;
1064 case "in":
1065 controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
1066 break;
1067 case "out":
1068 controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
1069 break;
1070 default:
1071 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
1072 break;
1073 }
1074 } else {
1075 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
Jason Monk0f0de132016-12-19 15:36:13 -05001076 }
Jason Monkb5746272014-11-12 16:50:31 -05001077 controller.getState().enabled = show;
1078 controller.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -04001079 }
Andrew Flynna478d702015-04-14 23:33:45 -04001080 String carrierNetworkChange = args.getString("carriernetworkchange");
1081 if (carrierNetworkChange != null) {
1082 boolean show = carrierNetworkChange.equals("show");
Jason Monk8996b942017-03-02 13:58:19 -05001083 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
1084 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Andrew Flynna478d702015-04-14 23:33:45 -04001085 controller.setCarrierNetworkChangeMode(show);
1086 }
1087 }
Jason Monkd2263cd2014-11-10 14:22:56 -05001088 }
1089 }
1090
John Spurlockcf053c12015-05-14 16:33:59 -04001091 private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
1092 SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
Malcolm Chene89e0ce2018-08-09 17:01:35 -07001093 null, null, null, "", false, null, null);
Jason Monkb5950982017-01-24 15:53:53 -05001094 MobileSignalController controller = new MobileSignalController(mContext,
chen xu84a90872019-03-28 15:44:12 -07001095 mConfig, mHasMobileDataFeature,
1096 mPhone.createForSubscriptionId(info.getSubscriptionId()), mCallbackHandler, this, info,
Jason Monkb5950982017-01-24 15:53:53 -05001097 mSubDefaults, mReceiverHandler.getLooper());
1098 mMobileSignalControllers.put(id, controller);
1099 controller.getState().userSetup = true;
John Spurlockcf053c12015-05-14 16:33:59 -04001100 return info;
1101 }
1102
Adrian Roos316bf542016-08-23 17:53:07 +02001103 public boolean hasEmergencyCryptKeeperText() {
1104 return EncryptionHelper.IS_DATA_ENCRYPTED;
1105 }
1106
1107 public boolean isRadioOn() {
1108 return !mAirplaneMode;
1109 }
1110
Jason Monk8fcab352015-06-29 10:57:00 -04001111 private class SubListener extends OnSubscriptionsChangedListener {
Jason Monkc9f05712014-12-15 12:24:10 -05001112 @Override
1113 public void onSubscriptionsChanged() {
Jason Monkb5746272014-11-12 16:50:31 -05001114 updateMobileControllers();
Jason Monk8fcab352015-06-29 10:57:00 -04001115 }
1116 }
Jason Monkb5746272014-11-12 16:50:31 -05001117
Jason Monk07b75fe2015-05-14 16:47:03 -04001118 /**
1119 * Used to register listeners from the BG Looper, this way the PhoneStateListeners that
1120 * get created will also run on the BG Looper.
1121 */
1122 private final Runnable mRegisterListeners = new Runnable() {
1123 @Override
1124 public void run() {
1125 registerListeners();
1126 }
1127 };
Jason Monkd2263cd2014-11-10 14:22:56 -05001128
Jason Monkc6cc6262015-06-11 11:10:15 -04001129 public static class SubscriptionDefaults {
1130 public int getDefaultVoiceSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -08001131 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -04001132 }
1133
1134 public int getDefaultDataSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -08001135 return SubscriptionManager.getDefaultDataSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -04001136 }
Fabian Kozynskiccde55d2019-06-26 10:06:09 -04001137
1138 public int getActiveDataSubId() {
1139 return SubscriptionManager.getActiveDataSubscriptionId();
1140 }
Jason Monkc6cc6262015-06-11 11:10:15 -04001141 }
1142
Jason Monkd2263cd2014-11-10 14:22:56 -05001143 @VisibleForTesting
1144 static class Config {
Pengquan Menga62d32b2018-12-06 17:38:38 -08001145 static final int NR_CONNECTED_MMWAVE = 1;
1146 static final int NR_CONNECTED = 2;
SongFerngWang52dada72019-08-14 16:59:29 +08001147 static final int NR_NOT_RESTRICTED_RRC_IDLE = 3;
1148 static final int NR_NOT_RESTRICTED_RRC_CON = 4;
1149 static final int NR_RESTRICTED = 5;
Pengquan Menga62d32b2018-12-06 17:38:38 -08001150
1151 Map<Integer, MobileIconGroup> nr5GIconMap = new HashMap<>();
1152
Jason Monkb5746272014-11-12 16:50:31 -05001153 boolean showAtLeast3G = false;
vagdevi3f2b9a52019-08-09 09:45:14 -07001154 boolean show4gFor3g = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001155 boolean alwaysShowCdmaRssi = false;
1156 boolean show4gForLte = false;
Robert Greenwalt37d34ba2016-07-27 14:54:34 -07001157 boolean hideLtePlus = false;
Jason Monkd2263cd2014-11-10 14:22:56 -05001158 boolean hspaDataDistinguishable;
Jason Monk43c14d12017-06-22 11:20:04 -04001159 boolean inflateSignalStrengths = false;
Wenting Xiong63364fe2017-02-07 19:12:27 +08001160 boolean alwaysShowDataRatIcon = false;
SongFerngWang3cbcf752019-03-21 23:14:20 +08001161 public String patternOfCarrierSpecificDataIcon = "";
Bill Lin767c0db2019-08-15 20:42:06 +08001162 public long nrIconDisplayGracePeriodMs;
Jason Monkd2263cd2014-11-10 14:22:56 -05001163
Pengquan Menga62d32b2018-12-06 17:38:38 -08001164 /**
1165 * Mapping from NR 5G status string to an integer. The NR 5G status string should match
1166 * those in carrier config.
1167 */
1168 private static final Map<String, Integer> NR_STATUS_STRING_TO_INDEX;
1169 static {
SongFerngWang52dada72019-08-14 16:59:29 +08001170 NR_STATUS_STRING_TO_INDEX = new HashMap<>(5);
Pengquan Menga62d32b2018-12-06 17:38:38 -08001171 NR_STATUS_STRING_TO_INDEX.put("connected_mmwave", NR_CONNECTED_MMWAVE);
1172 NR_STATUS_STRING_TO_INDEX.put("connected", NR_CONNECTED);
SongFerngWang52dada72019-08-14 16:59:29 +08001173 NR_STATUS_STRING_TO_INDEX.put("not_restricted_rrc_idle", NR_NOT_RESTRICTED_RRC_IDLE);
1174 NR_STATUS_STRING_TO_INDEX.put("not_restricted_rrc_con", NR_NOT_RESTRICTED_RRC_CON);
Pengquan Menga62d32b2018-12-06 17:38:38 -08001175 NR_STATUS_STRING_TO_INDEX.put("restricted", NR_RESTRICTED);
1176 }
1177
Jason Monkd2263cd2014-11-10 14:22:56 -05001178 static Config readConfig(Context context) {
1179 Config config = new Config();
1180 Resources res = context.getResources();
1181
Jason Monkb5746272014-11-12 16:50:31 -05001182 config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
Jason Monkd2263cd2014-11-10 14:22:56 -05001183 config.alwaysShowCdmaRssi =
1184 res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
Jason Monkd2263cd2014-11-10 14:22:56 -05001185 config.hspaDataDistinguishable =
1186 res.getBoolean(R.bool.config_hspa_data_distinguishable);
Antony Sargentc026de32019-05-21 16:29:04 -07001187 config.inflateSignalStrengths = res.getBoolean(
1188 com.android.internal.R.bool.config_inflateSignalStrength);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001189
1190 CarrierConfigManager configMgr = (CarrierConfigManager)
1191 context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001192 // Handle specific carrier config values for the default data SIM
1193 int defaultDataSubId = SubscriptionManager.from(context)
1194 .getDefaultDataSubscriptionId();
1195 PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001196 if (b != null) {
1197 config.alwaysShowDataRatIcon = b.getBoolean(
1198 CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001199 config.show4gForLte = b.getBoolean(
1200 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
vagdevi3f2b9a52019-08-09 09:45:14 -07001201 config.show4gFor3g = b.getBoolean(
1202 CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
Niklas Lindgrena02964d2018-09-21 14:01:57 +02001203 config.hideLtePlus = b.getBoolean(
1204 CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
SongFerngWang3cbcf752019-03-21 23:14:20 +08001205 config.patternOfCarrierSpecificDataIcon = b.getString(
1206 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
Pengquan Menga62d32b2018-12-06 17:38:38 -08001207 String nr5GIconConfiguration =
1208 b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
1209 if (!TextUtils.isEmpty(nr5GIconConfiguration)) {
1210 String[] nr5GIconConfigPairs = nr5GIconConfiguration.trim().split(",");
1211 for (String pair : nr5GIconConfigPairs) {
1212 add5GIconMapping(pair, config);
1213 }
1214 }
Bill Lin767c0db2019-08-15 20:42:06 +08001215 setDisplayGraceTime(
1216 b.getInt(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT),
1217 config);
Wenting Xiong63364fe2017-02-07 19:12:27 +08001218 }
Pengquan Menga62d32b2018-12-06 17:38:38 -08001219
Jason Monkd2263cd2014-11-10 14:22:56 -05001220 return config;
John Spurlockaf8d6c42014-05-07 17:49:08 -04001221 }
Pengquan Menga62d32b2018-12-06 17:38:38 -08001222
1223 /**
1224 * Add a mapping from NR 5G status to the 5G icon. All the icon resources come from
1225 * {@link TelephonyIcons}.
1226 *
1227 * @param keyValuePair the NR 5G status and icon name separated by a colon.
1228 * @param config container that used to store the parsed configs.
1229 */
1230 @VisibleForTesting
1231 static void add5GIconMapping(String keyValuePair, Config config) {
1232 String[] kv = (keyValuePair.trim().toLowerCase()).split(":");
1233
1234 if (kv.length != 2) {
1235 if (DEBUG) Log.e(TAG, "Invalid 5G icon configuration, config = " + keyValuePair);
1236 return;
1237 }
1238
1239 String key = kv[0], value = kv[1];
1240
1241 // There is no icon config for the specific 5G status.
1242 if (value.equals("none")) return;
1243
1244 if (NR_STATUS_STRING_TO_INDEX.containsKey(key)
1245 && TelephonyIcons.ICON_NAME_TO_ICON.containsKey(value)) {
1246 config.nr5GIconMap.put(
1247 NR_STATUS_STRING_TO_INDEX.get(key),
1248 TelephonyIcons.ICON_NAME_TO_ICON.get(value));
1249 }
1250 }
Bill Lin767c0db2019-08-15 20:42:06 +08001251
1252 /**
1253 * Set display gracefully period time(MS) depend on carrierConfig KEY
1254 * KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, and this function will convert to ms.
1255 * {@link CarrierConfigManager}.
1256 *
1257 * @param time showing 5G icon gracefully in the period of the time(SECOND)
1258 * @param config container that used to store the parsed configs.
1259 */
1260 @VisibleForTesting
1261 static void setDisplayGraceTime(int time, Config config) {
1262 config.nrIconDisplayGracePeriodMs = time * DateUtils.SECOND_IN_MILLIS;
1263 }
John Spurlockaf8d6c42014-05-07 17:49:08 -04001264 }
1265}