blob: 1a9756f78e364f8a247ba16d16f0568be6a57d26 [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
19import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.content.res.Resources;
24import android.net.ConnectivityManager;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090025import android.net.NetworkCapabilities;
John Spurlockaf8d6c42014-05-07 17:49:08 -040026import android.net.wifi.WifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040027import android.os.AsyncTask;
28import android.os.Bundle;
Jason Monk07b75fe2015-05-14 16:47:03 -040029import android.os.Handler;
Jason Monk30d80042015-05-08 16:54:18 -040030import android.os.Looper;
John Spurlockaf8d6c42014-05-07 17:49:08 -040031import android.provider.Settings;
Jason Monkb0808aa2015-07-22 16:34:36 -040032import android.telephony.ServiceState;
Jason Monkb5746272014-11-12 16:50:31 -050033import android.telephony.SubscriptionInfo;
34import android.telephony.SubscriptionManager;
35import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
John Spurlockaf8d6c42014-05-07 17:49:08 -040036import android.telephony.TelephonyManager;
Jason Monkb5746272014-11-12 16:50:31 -050037import android.text.TextUtils;
John Spurlockaf8d6c42014-05-07 17:49:08 -040038import android.util.Log;
John Spurlockcf053c12015-05-14 16:33:59 -040039import android.util.MathUtils;
Winsonc0d70582016-01-29 10:24:39 -080040
Jason Monke0cdb602014-11-05 12:39:45 -050041import com.android.internal.annotations.VisibleForTesting;
Jason Monkb5746272014-11-12 16:50:31 -050042import com.android.internal.telephony.PhoneConstants;
John Spurlockaf8d6c42014-05-07 17:49:08 -040043import com.android.internal.telephony.TelephonyIntents;
Jason Monkf668d7c2016-01-14 10:38:41 -050044import com.android.settingslib.net.DataUsageController;
John Spurlockaf8d6c42014-05-07 17:49:08 -040045import com.android.systemui.DemoMode;
46import com.android.systemui.R;
47
48import java.io.FileDescriptor;
49import java.io.PrintWriter;
50import java.util.ArrayList;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090051import java.util.BitSet;
Jason Monkb5746272014-11-12 16:50:31 -050052import java.util.Collections;
53import java.util.Comparator;
Jason Monkd2263cd2014-11-10 14:22:56 -050054import java.util.HashMap;
John Spurlockaf8d6c42014-05-07 17:49:08 -040055import java.util.List;
56import java.util.Locale;
Jason Monkd2263cd2014-11-10 14:22:56 -050057import java.util.Map;
John Spurlockaf8d6c42014-05-07 17:49:08 -040058
Jason Monk4cf95ae2015-11-16 15:59:53 -050059import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
60
John Spurlockaf8d6c42014-05-07 17:49:08 -040061/** Platform implementation of the network controller. **/
62public class NetworkControllerImpl extends BroadcastReceiver
Jason Monkf668d7c2016-01-14 10:38:41 -050063 implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider {
John Spurlockaf8d6c42014-05-07 17:49:08 -040064 // debug
Jason Monkd2263cd2014-11-10 14:22:56 -050065 static final String TAG = "NetworkController";
66 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
67 // additional diagnostics, but not logspew
Jason Monk07b75fe2015-05-14 16:47:03 -040068 static final boolean CHATTY = Log.isLoggable(TAG + "Chat", Log.DEBUG);
John Spurlockaf8d6c42014-05-07 17:49:08 -040069
Jason Monk66845a32015-08-03 11:09:41 -040070 private static final int EMERGENCY_NO_CONTROLLERS = 0;
71 private static final int EMERGENCY_FIRST_CONTROLLER = 100;
72 private static final int EMERGENCY_VOICE_CONTROLLER = 200;
73 private static final int EMERGENCY_NO_SUB = 300;
74
Jason Monkd2263cd2014-11-10 14:22:56 -050075 private final Context mContext;
76 private final TelephonyManager mPhone;
77 private final WifiManager mWifiManager;
78 private final ConnectivityManager mConnectivityManager;
Jason Monkb5746272014-11-12 16:50:31 -050079 private final SubscriptionManager mSubscriptionManager;
Jason Monkd2263cd2014-11-10 14:22:56 -050080 private final boolean mHasMobileDataFeature;
Jason Monkc6cc6262015-06-11 11:10:15 -040081 private final SubscriptionDefaults mSubDefaults;
Jason Monk9a4ce132016-01-21 15:27:17 -050082 private final DataSaverController mDataSaverController;
Jason Monk3aaabd72014-12-12 11:11:44 -050083 private Config mConfig;
John Spurlockaf8d6c42014-05-07 17:49:08 -040084
Jason Monkd2263cd2014-11-10 14:22:56 -050085 // Subcontrollers.
86 @VisibleForTesting
87 final WifiSignalController mWifiSignalController;
Lorenzo Colittid46bb582015-04-27 20:32:01 +090088
89 @VisibleForTesting
90 final EthernetSignalController mEthernetSignalController;
91
Jason Monkd2263cd2014-11-10 14:22:56 -050092 @VisibleForTesting
Jason Monkb5746272014-11-12 16:50:31 -050093 final Map<Integer, MobileSignalController> mMobileSignalControllers =
94 new HashMap<Integer, MobileSignalController>();
95 // When no SIMs are around at setup, and one is added later, it seems to default to the first
96 // SIM for most actions. This may be null if there aren't any SIMs around.
97 private MobileSignalController mDefaultSignalController;
Jason Monk0e2400f2014-11-21 11:08:55 -050098 private final AccessPointControllerImpl mAccessPoints;
Jason Monkf668d7c2016-01-14 10:38:41 -050099 private final DataUsageController mDataUsageController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400100
Jason Monkd2263cd2014-11-10 14:22:56 -0500101 private boolean mInetCondition; // Used for Logging and demo.
Lorenzo Colitti23dd1762014-09-10 22:58:54 +0900102
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900103 // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are
104 // connected and validated, respectively.
105 private final BitSet mConnectedTransports = new BitSet();
106 private final BitSet mValidatedTransports = new BitSet();
107
Jason Monkd2263cd2014-11-10 14:22:56 -0500108 // States that don't belong to a subcontroller.
John Spurlockaf8d6c42014-05-07 17:49:08 -0400109 private boolean mAirplaneMode = false;
Jason Monkb5746272014-11-12 16:50:31 -0500110 private boolean mHasNoSims;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400111 private Locale mLocale = null;
Jason Monkb5746272014-11-12 16:50:31 -0500112 // This list holds our ordering.
John Spurlockcf053c12015-05-14 16:33:59 -0400113 private List<SubscriptionInfo> mCurrentSubscriptions = new ArrayList<>();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400114
Jason Monkc014dec2014-12-12 11:49:55 -0500115 @VisibleForTesting
116 boolean mListening;
John Spurlock7f8f22a2014-07-02 18:54:17 -0400117
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900118 // The current user ID.
119 private int mCurrentUserId;
120
Jason Monk8fcab352015-06-29 10:57:00 -0400121 private OnSubscriptionsChangedListener mSubscriptionListener;
122
Jason Monk07b75fe2015-05-14 16:47:03 -0400123 // Handler that all broadcasts are received on.
124 private final Handler mReceiverHandler;
125 // Handler that all callbacks are made on.
126 private final CallbackHandler mCallbackHandler;
127
Jason Monk66845a32015-08-03 11:09:41 -0400128 private int mEmergencySource;
129 private boolean mIsEmergency;
130
Jason Monkb0808aa2015-07-22 16:34:36 -0400131 @VisibleForTesting
132 ServiceState mLastServiceState;
Jason Monkfd57ea72016-04-29 13:37:58 -0400133 private boolean mUserSetup;
Jason Monkb0808aa2015-07-22 16:34:36 -0400134
John Spurlockaf8d6c42014-05-07 17:49:08 -0400135 /**
136 * Construct this controller object and register for updates.
137 */
Jason Monk30d80042015-05-08 16:54:18 -0400138 public NetworkControllerImpl(Context context, Looper bgLooper) {
Jason Monkf13b4b32014-11-07 16:39:34 -0500139 this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
140 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
Jason Monk29f7a7b2014-11-17 14:40:56 -0500141 (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
Jason Monk07b75fe2015-05-14 16:47:03 -0400142 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
143 new CallbackHandler(),
Jason Monk30d80042015-05-08 16:54:18 -0400144 new AccessPointControllerImpl(context, bgLooper),
Jason Monkf668d7c2016-01-14 10:38:41 -0500145 new DataUsageController(context),
Jason Monkc6cc6262015-06-11 11:10:15 -0400146 new SubscriptionDefaults());
Jason Monk07b75fe2015-05-14 16:47:03 -0400147 mReceiverHandler.post(mRegisterListeners);
Jason Monkf13b4b32014-11-07 16:39:34 -0500148 }
149
150 @VisibleForTesting
151 NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
Jason Monkb5746272014-11-12 16:50:31 -0500152 TelephonyManager telephonyManager, WifiManager wifiManager,
Jason Monk07b75fe2015-05-14 16:47:03 -0400153 SubscriptionManager subManager, Config config, Looper bgLooper,
154 CallbackHandler callbackHandler,
Jason Monkd2263cd2014-11-10 14:22:56 -0500155 AccessPointControllerImpl accessPointController,
Jason Monkf668d7c2016-01-14 10:38:41 -0500156 DataUsageController dataUsageController,
Jason Monkc6cc6262015-06-11 11:10:15 -0400157 SubscriptionDefaults defaultsHandler) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400158 mContext = context;
Jason Monkb5746272014-11-12 16:50:31 -0500159 mConfig = config;
Jason Monk07b75fe2015-05-14 16:47:03 -0400160 mReceiverHandler = new Handler(bgLooper);
161 mCallbackHandler = callbackHandler;
Jason Monk9a4ce132016-01-21 15:27:17 -0500162 mDataSaverController = new DataSaverController(context);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400163
Jason Monkb5746272014-11-12 16:50:31 -0500164 mSubscriptionManager = subManager;
Jason Monkc6cc6262015-06-11 11:10:15 -0400165 mSubDefaults = defaultsHandler;
Jason Monkf13b4b32014-11-07 16:39:34 -0500166 mConnectivityManager = connectivityManager;
167 mHasMobileDataFeature =
168 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400169
John Spurlockaf8d6c42014-05-07 17:49:08 -0400170 // telephony
Jason Monk07b75fe2015-05-14 16:47:03 -0400171 mPhone = telephonyManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400172
173 // wifi
Jason Monkf13b4b32014-11-07 16:39:34 -0500174 mWifiManager = wifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400175
Jason Monkd2263cd2014-11-10 14:22:56 -0500176 mLocale = mContext.getResources().getConfiguration().locale;
Jason Monk29f7a7b2014-11-17 14:40:56 -0500177 mAccessPoints = accessPointController;
Jason Monkf668d7c2016-01-14 10:38:41 -0500178 mDataUsageController = dataUsageController;
179 mDataUsageController.setNetworkController(this);
180 // TODO: Find a way to move this into DataUsageController.
181 mDataUsageController.setCallback(new DataUsageController.Callback() {
Jason Monke0cdb602014-11-05 12:39:45 -0500182 @Override
183 public void onMobileDataEnabled(boolean enabled) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400184 mCallbackHandler.setMobileDataEnabled(enabled);
Jason Monke0cdb602014-11-05 12:39:45 -0500185 }
186 });
Jason Monkd2263cd2014-11-10 14:22:56 -0500187 mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
Jason Monk07b75fe2015-05-14 16:47:03 -0400188 mCallbackHandler, this);
Jason Monkd2263cd2014-11-10 14:22:56 -0500189
Jason Monk07b75fe2015-05-14 16:47:03 -0400190 mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900191
Jason Monkd2263cd2014-11-10 14:22:56 -0500192 // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
Jason Monkb5746272014-11-12 16:50:31 -0500193 updateAirplaneMode(true /* force callback */);
Jason Monke0cdb602014-11-05 12:39:45 -0500194 }
195
Jason Monk9a4ce132016-01-21 15:27:17 -0500196 public DataSaverController getDataSaverController() {
197 return mDataSaverController;
198 }
199
Jason Monkf13b4b32014-11-07 16:39:34 -0500200 private void registerListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500201 for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
202 mobileSignalController.registerListener();
203 }
Jason Monk8fcab352015-06-29 10:57:00 -0400204 if (mSubscriptionListener == null) {
205 mSubscriptionListener = new SubListener();
206 }
Wink Saville071743f2015-01-12 17:11:04 -0800207 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monke0cdb602014-11-05 12:39:45 -0500208
John Spurlockaf8d6c42014-05-07 17:49:08 -0400209 // broadcasts
210 IntentFilter filter = new IntentFilter();
211 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
212 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
213 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
214 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jason Monkb5746272014-11-12 16:50:31 -0500215 filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
216 filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
Jason Monkb0808aa2015-07-22 16:34:36 -0400217 filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400218 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Erik Kline32830cc2015-04-21 13:09:15 +0900219 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400220 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400221 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
Jason Monk07b75fe2015-05-14 16:47:03 -0400222 mContext.registerReceiver(this, filter, null, mReceiverHandler);
Jason Monkb5746272014-11-12 16:50:31 -0500223 mListening = true;
224
225 updateMobileControllers();
John Spurlockb98f7472014-07-08 17:09:42 -0400226 }
227
Jason Monkd2263cd2014-11-10 14:22:56 -0500228 private void unregisterListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500229 mListening = false;
230 for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
231 mobileSignalController.unregisterListener();
232 }
Wink Saville071743f2015-01-12 17:11:04 -0800233 mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monkd2263cd2014-11-10 14:22:56 -0500234 mContext.unregisterReceiver(this);
Jason Monk5d325072014-10-27 11:38:47 -0400235 }
236
Jason Monk0e2400f2014-11-21 11:08:55 -0500237 public int getConnectedWifiLevel() {
238 return mWifiSignalController.getState().level;
239 }
240
Jason Monk5d325072014-10-27 11:38:47 -0400241 @Override
Jason Monkd2263cd2014-11-10 14:22:56 -0500242 public AccessPointController getAccessPointController() {
243 return mAccessPoints;
244 }
245
246 @Override
Jason Monkf668d7c2016-01-14 10:38:41 -0500247 public DataUsageController getMobileDataController() {
248 return mDataUsageController;
Jason Monkd2263cd2014-11-10 14:22:56 -0500249 }
250
251 public void addEmergencyListener(EmergencyListener listener) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400252 mCallbackHandler.setListening(listener, true);
253 mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400254 }
255
Jason Monk46dbfb42016-02-25 14:59:20 -0500256 public void removeEmergencyListener(EmergencyListener listener) {
257 mCallbackHandler.setListening(listener, false);
258 }
259
John Spurlockaf8d6c42014-05-07 17:49:08 -0400260 public boolean hasMobileDataFeature() {
261 return mHasMobileDataFeature;
262 }
263
264 public boolean hasVoiceCallingFeature() {
265 return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
266 }
267
Jason Monkb5746272014-11-12 16:50:31 -0500268 private MobileSignalController getDataController() {
Jason Monkc6cc6262015-06-11 11:10:15 -0400269 int dataSubId = mSubDefaults.getDefaultDataSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800270 if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
Jason Monkb5746272014-11-12 16:50:31 -0500271 if (DEBUG) Log.e(TAG, "No data sim selected");
272 return mDefaultSignalController;
273 }
274 if (mMobileSignalControllers.containsKey(dataSubId)) {
275 return mMobileSignalControllers.get(dataSubId);
276 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500277 if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
Jason Monkb5746272014-11-12 16:50:31 -0500278 return mDefaultSignalController;
279 }
280
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700281 public String getMobileDataNetworkName() {
Jason Monkb5746272014-11-12 16:50:31 -0500282 MobileSignalController controller = getDataController();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700283 return controller != null ? controller.getState().networkNameData : "";
Jason Monkd2263cd2014-11-10 14:22:56 -0500284 }
285
John Spurlockaf8d6c42014-05-07 17:49:08 -0400286 public boolean isEmergencyOnly() {
Jason Monkb0808aa2015-07-22 16:34:36 -0400287 if (mMobileSignalControllers.size() == 0) {
288 // When there are no active subscriptions, determine emengency state from last
289 // broadcast.
Jason Monk66845a32015-08-03 11:09:41 -0400290 mEmergencySource = EMERGENCY_NO_CONTROLLERS;
Jason Monkb0808aa2015-07-22 16:34:36 -0400291 return mLastServiceState != null && mLastServiceState.isEmergencyOnly();
292 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400293 int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800294 if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
295 for (MobileSignalController mobileSignalController :
296 mMobileSignalControllers.values()) {
Jason Monkc6cc6262015-06-11 11:10:15 -0400297 if (!mobileSignalController.getState().isEmergency) {
Jason Monk66845a32015-08-03 11:09:41 -0400298 mEmergencySource = EMERGENCY_FIRST_CONTROLLER
299 + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400300 if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag);
Jason Monkb5746272014-11-12 16:50:31 -0500301 return false;
302 }
303 }
304 }
305 if (mMobileSignalControllers.containsKey(voiceSubId)) {
Jason Monk66845a32015-08-03 11:09:41 -0400306 mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
Jason Monkc6cc6262015-06-11 11:10:15 -0400307 if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
308 return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
Jason Monkb5746272014-11-12 16:50:31 -0500309 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500310 if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
Jason Monk66845a32015-08-03 11:09:41 -0400311 mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
Jason Monkb5746272014-11-12 16:50:31 -0500312 // Something is wrong, better assume we can't make calls...
313 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400314 }
315
Jason Monkd2263cd2014-11-10 14:22:56 -0500316 /**
317 * Emergency status may have changed (triggered by MobileSignalController),
318 * so we should recheck and send out the state to listeners.
319 */
320 void recalculateEmergency() {
Jason Monk66845a32015-08-03 11:09:41 -0400321 mIsEmergency = isEmergencyOnly();
322 mCallbackHandler.setEmergencyCallsOnly(mIsEmergency);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400323 }
324
Jason Monk88529052016-11-04 13:29:58 -0400325 public void addCallback(SignalCallback cb) {
Jason Monke06b0652016-03-02 16:35:27 -0500326 cb.setSubs(mCurrentSubscriptions);
327 cb.setIsAirplaneMode(new IconState(mAirplaneMode,
Jason Monk07b75fe2015-05-14 16:47:03 -0400328 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monke06b0652016-03-02 16:35:27 -0500329 cb.setNoSims(mHasNoSims);
330 mWifiSignalController.notifyListeners(cb);
331 mEthernetSignalController.notifyListeners(cb);
Jason Monkb5746272014-11-12 16:50:31 -0500332 for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
Jason Monke06b0652016-03-02 16:35:27 -0500333 mobileSignalController.notifyListeners(cb);
Jason Monkb5746272014-11-12 16:50:31 -0500334 }
Jason Monke06b0652016-03-02 16:35:27 -0500335 mCallbackHandler.setListening(cb, true);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400336 }
337
Jason Monk07b75fe2015-05-14 16:47:03 -0400338 @Override
Jason Monk88529052016-11-04 13:29:58 -0400339 public void removeCallback(SignalCallback cb) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400340 mCallbackHandler.setListening(cb, false);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400341 }
342
343 @Override
344 public void setWifiEnabled(final boolean enabled) {
345 new AsyncTask<Void, Void, Void>() {
346 @Override
347 protected Void doInBackground(Void... args) {
348 // Disable tethering if enabling Wifi
349 final int wifiApState = mWifiManager.getWifiApState();
350 if (enabled && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
Jason Monkd2263cd2014-11-10 14:22:56 -0500351 (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400352 mWifiManager.setWifiApEnabled(null, false);
353 }
354
355 mWifiManager.setWifiEnabled(enabled);
356 return null;
357 }
358 }.execute();
359 }
360
John Spurlockb98f7472014-07-08 17:09:42 -0400361 @Override
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900362 public void onUserSwitched(int newUserId) {
363 mCurrentUserId = newUserId;
364 mAccessPoints.onUserSwitched(newUserId);
365 updateConnectivity();
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900366 }
367
368 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400369 public void onReceive(Context context, Intent intent) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500370 if (CHATTY) {
371 Log.d(TAG, "onReceive: intent=" + intent);
372 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400373 final String action = intent.getAction();
Erik Kline32830cc2015-04-21 13:09:15 +0900374 if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
Jason Monkd2263cd2014-11-10 14:22:56 -0500375 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900376 updateConnectivity();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400377 } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
378 refreshLocale();
Jason Monkd2263cd2014-11-10 14:22:56 -0500379 updateAirplaneMode(false);
Jason Monkb5746272014-11-12 16:50:31 -0500380 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED)) {
381 // We are using different subs now, we might be able to make calls.
382 recalculateEmergency();
383 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
384 // Notify every MobileSignalController so they can know whether they are the
385 // data sim or not.
386 for (MobileSignalController controller : mMobileSignalControllers.values()) {
387 controller.handleBroadcast(intent);
388 }
389 } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
390 // Might have different subscriptions now.
391 updateMobileControllers();
Jason Monkb0808aa2015-07-22 16:34:36 -0400392 } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
393 mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
394 if (mMobileSignalControllers.size() == 0) {
395 // If none of the subscriptions are active, we might need to recalculate
396 // emergency state.
397 recalculateEmergency();
398 }
Jason Monkb5746272014-11-12 16:50:31 -0500399 } else {
400 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
401 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Savillea54bf652014-12-11 13:37:50 -0800402 if (SubscriptionManager.isValidSubscriptionId(subId)) {
Jason Monkb5746272014-11-12 16:50:31 -0500403 if (mMobileSignalControllers.containsKey(subId)) {
404 mMobileSignalControllers.get(subId).handleBroadcast(intent);
405 } else {
406 // Can't find this subscription... We must be out of date.
407 updateMobileControllers();
408 }
409 } else {
410 // No sub id, must be for the wifi.
411 mWifiSignalController.handleBroadcast(intent);
412 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400413 }
Jason Monkb5746272014-11-12 16:50:31 -0500414 }
415
Jason Monk1c040db2015-07-20 09:45:54 -0400416 public void onConfigurationChanged() {
Sungmin Choi6be4f6b2015-07-07 13:06:59 +0900417 mConfig = Config.readConfig(mContext);
Jason Monk1c040db2015-07-20 09:45:54 -0400418 mReceiverHandler.post(new Runnable() {
419 @Override
420 public void run() {
421 handleConfigurationChanged();
422 }
423 });
424 }
425
426 @VisibleForTesting
427 void handleConfigurationChanged() {
Jason Monk3aaabd72014-12-12 11:11:44 -0500428 for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
429 mobileSignalController.setConfiguration(mConfig);
430 }
431 refreshLocale();
Jason Monk3aaabd72014-12-12 11:11:44 -0500432 }
433
Jason Monkb5746272014-11-12 16:50:31 -0500434 private void updateMobileControllers() {
435 if (!mListening) {
436 return;
437 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400438 doUpdateMobileControllers();
439 }
440
441 @VisibleForTesting
442 void doUpdateMobileControllers() {
Jason Monkb5746272014-11-12 16:50:31 -0500443 List<SubscriptionInfo> subscriptions = mSubscriptionManager.getActiveSubscriptionInfoList();
Jason Monkc9f05712014-12-15 12:24:10 -0500444 if (subscriptions == null) {
445 subscriptions = Collections.emptyList();
446 }
Jason Monkb5746272014-11-12 16:50:31 -0500447 // If there have been no relevant changes to any of the subscriptions, we can leave as is.
448 if (hasCorrectMobileControllers(subscriptions)) {
449 // Even if the controllers are correct, make sure we have the right no sims state.
450 // Such as on boot, don't need any controllers, because there are no sims,
451 // but we still need to update the no sim state.
452 updateNoSims();
453 return;
454 }
455 setCurrentSubscriptions(subscriptions);
456 updateNoSims();
Jason Monkc6cc6262015-06-11 11:10:15 -0400457 recalculateEmergency();
Jason Monkb5746272014-11-12 16:50:31 -0500458 }
459
Jason Monk21d05a02014-12-02 12:46:58 -0500460 @VisibleForTesting
461 protected void updateNoSims() {
462 boolean hasNoSims = mHasMobileDataFeature && mMobileSignalControllers.size() == 0;
Jason Monkb5746272014-11-12 16:50:31 -0500463 if (hasNoSims != mHasNoSims) {
464 mHasNoSims = hasNoSims;
Jason Monk259e06f2015-06-18 14:07:26 -0400465 mCallbackHandler.setNoSims(mHasNoSims);
Jason Monkb5746272014-11-12 16:50:31 -0500466 }
467 }
468
469 @VisibleForTesting
470 void setCurrentSubscriptions(List<SubscriptionInfo> subscriptions) {
471 Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() {
472 @Override
473 public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) {
474 return lhs.getSimSlotIndex() == rhs.getSimSlotIndex()
475 ? lhs.getSubscriptionId() - rhs.getSubscriptionId()
476 : lhs.getSimSlotIndex() - rhs.getSimSlotIndex();
477 }
478 });
Jason Monkb5746272014-11-12 16:50:31 -0500479 mCurrentSubscriptions = subscriptions;
480
481 HashMap<Integer, MobileSignalController> cachedControllers =
482 new HashMap<Integer, MobileSignalController>(mMobileSignalControllers);
483 mMobileSignalControllers.clear();
484 final int num = subscriptions.size();
485 for (int i = 0; i < num; i++) {
486 int subId = subscriptions.get(i).getSubscriptionId();
487 // If we have a copy of this controller already reuse it, otherwise make a new one.
488 if (cachedControllers.containsKey(subId)) {
Jason Monkc014dec2014-12-12 11:49:55 -0500489 mMobileSignalControllers.put(subId, cachedControllers.remove(subId));
Jason Monkb5746272014-11-12 16:50:31 -0500490 } else {
491 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
Jason Monk07b75fe2015-05-14 16:47:03 -0400492 mHasMobileDataFeature, mPhone, mCallbackHandler,
Jason Monkc6cc6262015-06-11 11:10:15 -0400493 this, subscriptions.get(i), mSubDefaults, mReceiverHandler.getLooper());
Jason Monkfd57ea72016-04-29 13:37:58 -0400494 controller.setUserSetupComplete(mUserSetup);
Jason Monkb5746272014-11-12 16:50:31 -0500495 mMobileSignalControllers.put(subId, controller);
496 if (subscriptions.get(i).getSimSlotIndex() == 0) {
497 mDefaultSignalController = controller;
498 }
499 if (mListening) {
500 controller.registerListener();
501 }
502 }
503 }
504 if (mListening) {
505 for (Integer key : cachedControllers.keySet()) {
506 if (cachedControllers.get(key) == mDefaultSignalController) {
507 mDefaultSignalController = null;
508 }
509 cachedControllers.get(key).unregisterListener();
510 }
511 }
Jason Monk8fcab352015-06-29 10:57:00 -0400512 mCallbackHandler.setSubs(subscriptions);
513 notifyAllListeners();
514
Jason Monk25d8a482014-12-09 12:27:24 -0500515 // There may be new MobileSignalControllers around, make sure they get the current
516 // inet condition and airplane mode.
517 pushConnectivityToSignals();
518 updateAirplaneMode(true /* force */);
Jason Monkb5746272014-11-12 16:50:31 -0500519 }
520
Jason Monkfd57ea72016-04-29 13:37:58 -0400521 public void setUserSetupComplete(final boolean userSetup) {
522 mReceiverHandler.post(new Runnable() {
523 @Override
524 public void run() {
525 handleSetUserSetupComplete(userSetup);
526 }
527 });
528 }
529
530 @VisibleForTesting
531 void handleSetUserSetupComplete(boolean userSetup) {
532 mUserSetup = userSetup;
533 for (MobileSignalController controller : mMobileSignalControllers.values()) {
534 controller.setUserSetupComplete(mUserSetup);
535 }
536 }
537
Jason Monkc014dec2014-12-12 11:49:55 -0500538 @VisibleForTesting
539 boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) {
Jason Monkc9f05712014-12-15 12:24:10 -0500540 if (allSubscriptions.size() != mMobileSignalControllers.size()) {
541 return false;
Jason Monkb5746272014-11-12 16:50:31 -0500542 }
543 for (SubscriptionInfo info : allSubscriptions) {
544 if (!mMobileSignalControllers.containsKey(info.getSubscriptionId())) {
545 return false;
546 }
547 }
548 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400549 }
550
Jason Monkd2263cd2014-11-10 14:22:56 -0500551 private void updateAirplaneMode(boolean force) {
552 boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
553 Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
554 if (airplaneMode != mAirplaneMode || force) {
555 mAirplaneMode = airplaneMode;
Jason Monkb5746272014-11-12 16:50:31 -0500556 for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
557 mobileSignalController.setAirplaneMode(mAirplaneMode);
558 }
559 notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400560 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400561 }
562
563 private void refreshLocale() {
Jason Monkd2263cd2014-11-10 14:22:56 -0500564 Locale current = mContext.getResources().getConfiguration().locale;
Jason Monkb5746272014-11-12 16:50:31 -0500565 if (!current.equals(mLocale)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500566 mLocale = current;
567 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400568 }
569 }
570
Jason Monkd2263cd2014-11-10 14:22:56 -0500571 /**
Jason Monkb5746272014-11-12 16:50:31 -0500572 * Forces update of all callbacks on both SignalClusters and
573 * NetworkSignalChangedCallbacks.
574 */
Jason Monkd2263cd2014-11-10 14:22:56 -0500575 private void notifyAllListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500576 notifyListeners();
577 for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
578 mobileSignalController.notifyListeners();
579 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500580 mWifiSignalController.notifyListeners();
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900581 mEthernetSignalController.notifyListeners();
Jason Monkd2263cd2014-11-10 14:22:56 -0500582 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400583
Jason Monkb5746272014-11-12 16:50:31 -0500584 /**
585 * Notifies listeners of changes in state of to the NetworkController, but
586 * does not notify for any info on SignalControllers, for that call
587 * notifyAllListeners.
588 */
589 private void notifyListeners() {
Jason Monk07b75fe2015-05-14 16:47:03 -0400590 mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
591 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
592 mCallbackHandler.setNoSims(mHasNoSims);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400593 }
594
Jason Monkd2263cd2014-11-10 14:22:56 -0500595 /**
596 * Update the Inet conditions and what network we are connected to.
597 */
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900598 private void updateConnectivity() {
599 mConnectedTransports.clear();
600 mValidatedTransports.clear();
601 for (NetworkCapabilities nc :
602 mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
603 for (int transportType : nc.getTransportTypes()) {
604 mConnectedTransports.set(transportType);
605 if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
606 mValidatedTransports.set(transportType);
607 }
608 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400609 }
610
John Spurlockaf8d6c42014-05-07 17:49:08 -0400611 if (CHATTY) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900612 Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
613 Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400614 }
615
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900616 mInetCondition = !mValidatedTransports.isEmpty();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400617
Jason Monk25d8a482014-12-09 12:27:24 -0500618 pushConnectivityToSignals();
619 }
620
621 /**
622 * Pushes the current connectivity state to all SignalControllers.
623 */
624 private void pushConnectivityToSignals() {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400625 // We want to update all the icons, all at once, for any condition change
Jason Monkb5746272014-11-12 16:50:31 -0500626 for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
Jason Monk33f8ae72015-05-08 10:45:15 -0400627 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
Jason Monkb5746272014-11-12 16:50:31 -0500628 }
Jason Monk33f8ae72015-05-08 10:45:15 -0400629 mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
630 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400631 }
632
John Spurlockaf8d6c42014-05-07 17:49:08 -0400633 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
634 pw.println("NetworkController state:");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900635
John Spurlockaf8d6c42014-05-07 17:49:08 -0400636 pw.println(" - telephony ------");
637 pw.print(" hasVoiceCallingFeature()=");
638 pw.println(hasVoiceCallingFeature());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400639
John Spurlockaf8d6c42014-05-07 17:49:08 -0400640 pw.println(" - connectivity ------");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900641 pw.print(" mConnectedTransports=");
642 pw.println(mConnectedTransports);
643 pw.print(" mValidatedTransports=");
644 pw.println(mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400645 pw.print(" mInetCondition=");
646 pw.println(mInetCondition);
Jason Monkd2263cd2014-11-10 14:22:56 -0500647 pw.print(" mAirplaneMode=");
648 pw.println(mAirplaneMode);
649 pw.print(" mLocale=");
650 pw.println(mLocale);
Jason Monkb0808aa2015-07-22 16:34:36 -0400651 pw.print(" mLastServiceState=");
652 pw.println(mLastServiceState);
Jason Monk66845a32015-08-03 11:09:41 -0400653 pw.print(" mIsEmergency=");
654 pw.println(mIsEmergency);
655 pw.print(" mEmergencySource=");
656 pw.println(emergencyToString(mEmergencySource));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400657
Jason Monkb5746272014-11-12 16:50:31 -0500658 for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
659 mobileSignalController.dump(pw);
660 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500661 mWifiSignalController.dump(pw);
Jason Monkd52356a2015-01-28 10:40:41 -0500662
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900663 mEthernetSignalController.dump(pw);
664
Jason Monkd52356a2015-01-28 10:40:41 -0500665 mAccessPoints.dump(pw);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400666 }
667
Jason Monk66845a32015-08-03 11:09:41 -0400668 private static final String emergencyToString(int emergencySource) {
669 if (emergencySource > EMERGENCY_NO_SUB) {
670 return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
671 } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
672 return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
673 } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) {
674 return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")";
675 } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) {
676 return "NO_CONTROLLERS";
677 }
678 return "UNKNOWN_SOURCE";
679 }
680
John Spurlockaf8d6c42014-05-07 17:49:08 -0400681 private boolean mDemoMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400682 private boolean mDemoInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500683 private WifiSignalController.WifiState mDemoWifiState;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400684
685 @Override
686 public void dispatchDemoCommand(String command, Bundle args) {
687 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500688 if (DEBUG) Log.d(TAG, "Entering demo mode");
689 unregisterListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400690 mDemoMode = true;
Jason Monk33f8ae72015-05-08 10:45:15 -0400691 mDemoInetCondition = mInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500692 mDemoWifiState = mWifiSignalController.getState();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400693 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500694 if (DEBUG) Log.d(TAG, "Exiting demo mode");
John Spurlockaf8d6c42014-05-07 17:49:08 -0400695 mDemoMode = false;
Jason Monkb5746272014-11-12 16:50:31 -0500696 // Update what MobileSignalControllers, because they may change
697 // to set the number of sim slots.
698 updateMobileControllers();
699 for (MobileSignalController controller : mMobileSignalControllers.values()) {
700 controller.resetLastState();
701 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500702 mWifiSignalController.resetLastState();
Jason Monk07b75fe2015-05-14 16:47:03 -0400703 mReceiverHandler.post(mRegisterListeners);
Jason Monkd2263cd2014-11-10 14:22:56 -0500704 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400705 } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
706 String airplane = args.getString("airplane");
707 if (airplane != null) {
708 boolean show = airplane.equals("show");
Jason Monk07b75fe2015-05-14 16:47:03 -0400709 mCallbackHandler.setIsAirplaneMode(new IconState(show,
710 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode,
711 mContext));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400712 }
713 String fully = args.getString("fully");
714 if (fully != null) {
Jason Monk33f8ae72015-05-08 10:45:15 -0400715 mDemoInetCondition = Boolean.parseBoolean(fully);
716 BitSet connected = new BitSet();
717
718 if (mDemoInetCondition) {
719 connected.set(mWifiSignalController.mTransportType);
720 }
721 mWifiSignalController.updateConnectivity(connected, connected);
Jason Monkb5746272014-11-12 16:50:31 -0500722 for (MobileSignalController controller : mMobileSignalControllers.values()) {
Jason Monk33f8ae72015-05-08 10:45:15 -0400723 if (mDemoInetCondition) {
724 connected.set(controller.mTransportType);
725 }
726 controller.updateConnectivity(connected, connected);
Jason Monkb5746272014-11-12 16:50:31 -0500727 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400728 }
729 String wifi = args.getString("wifi");
730 if (wifi != null) {
731 boolean show = wifi.equals("show");
732 String level = args.getString("level");
733 if (level != null) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500734 mDemoWifiState.level = level.equals("null") ? -1
John Spurlockaf8d6c42014-05-07 17:49:08 -0400735 : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
Jason Monkd2263cd2014-11-10 14:22:56 -0500736 mDemoWifiState.connected = mDemoWifiState.level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400737 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500738 mDemoWifiState.enabled = show;
739 mWifiSignalController.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400740 }
Jason Monkb5746272014-11-12 16:50:31 -0500741 String sims = args.getString("sims");
742 if (sims != null) {
John Spurlockcf053c12015-05-14 16:33:59 -0400743 int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
744 List<SubscriptionInfo> subs = new ArrayList<>();
Jason Monkb5746272014-11-12 16:50:31 -0500745 if (num != mMobileSignalControllers.size()) {
746 mMobileSignalControllers.clear();
747 int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
748 for (int i = start /* get out of normal index range */; i < start + num; i++) {
John Spurlockcf053c12015-05-14 16:33:59 -0400749 subs.add(addSignalController(i, i));
Jason Monkb5746272014-11-12 16:50:31 -0500750 }
Jason Monk33b60bb2015-07-13 10:42:23 -0400751 mCallbackHandler.setSubs(subs);
Jason Monkb5746272014-11-12 16:50:31 -0500752 }
Jason Monkb5746272014-11-12 16:50:31 -0500753 }
754 String nosim = args.getString("nosim");
755 if (nosim != null) {
Jason Monk259e06f2015-06-18 14:07:26 -0400756 mHasNoSims = nosim.equals("show");
757 mCallbackHandler.setNoSims(mHasNoSims);
Jason Monkb5746272014-11-12 16:50:31 -0500758 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400759 String mobile = args.getString("mobile");
760 if (mobile != null) {
761 boolean show = mobile.equals("show");
762 String datatype = args.getString("datatype");
Jason Monkb5746272014-11-12 16:50:31 -0500763 String slotString = args.getString("slot");
764 int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
John Spurlockcf053c12015-05-14 16:33:59 -0400765 slot = MathUtils.constrain(slot, 0, 8);
766 // Ensure we have enough sim slots
767 List<SubscriptionInfo> subs = new ArrayList<>();
768 while (mMobileSignalControllers.size() <= slot) {
769 int nextSlot = mMobileSignalControllers.size();
770 subs.add(addSignalController(nextSlot, nextSlot));
771 }
772 if (!subs.isEmpty()) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400773 mCallbackHandler.setSubs(subs);
John Spurlockcf053c12015-05-14 16:33:59 -0400774 }
Jason Monkb5746272014-11-12 16:50:31 -0500775 // Hack to index linearly for easy use.
776 MobileSignalController controller = mMobileSignalControllers
777 .values().toArray(new MobileSignalController[0])[slot];
778 controller.getState().dataSim = datatype != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400779 if (datatype != null) {
Jason Monkb5746272014-11-12 16:50:31 -0500780 controller.getState().iconGroup =
Jason Monkd2263cd2014-11-10 14:22:56 -0500781 datatype.equals("1x") ? TelephonyIcons.ONE_X :
782 datatype.equals("3g") ? TelephonyIcons.THREE_G :
783 datatype.equals("4g") ? TelephonyIcons.FOUR_G :
Ajay Nambi7965fa42015-05-14 18:48:33 -0700784 datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -0500785 datatype.equals("e") ? TelephonyIcons.E :
786 datatype.equals("g") ? TelephonyIcons.G :
787 datatype.equals("h") ? TelephonyIcons.H :
788 datatype.equals("lte") ? TelephonyIcons.LTE :
Jason Monkaa730be2016-07-13 14:22:52 -0400789 datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -0500790 datatype.equals("roam") ? TelephonyIcons.ROAMING :
791 TelephonyIcons.UNKNOWN;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400792 }
793 int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH;
794 String level = args.getString("level");
795 if (level != null) {
Jason Monkb5746272014-11-12 16:50:31 -0500796 controller.getState().level = level.equals("null") ? -1
John Spurlockaf8d6c42014-05-07 17:49:08 -0400797 : Math.min(Integer.parseInt(level), icons[0].length - 1);
Jason Monkb5746272014-11-12 16:50:31 -0500798 controller.getState().connected = controller.getState().level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400799 }
Jason Monkb5746272014-11-12 16:50:31 -0500800 controller.getState().enabled = show;
801 controller.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400802 }
Andrew Flynna478d702015-04-14 23:33:45 -0400803 String carrierNetworkChange = args.getString("carriernetworkchange");
804 if (carrierNetworkChange != null) {
805 boolean show = carrierNetworkChange.equals("show");
806 for (MobileSignalController controller : mMobileSignalControllers.values()) {
807 controller.setCarrierNetworkChangeMode(show);
808 }
809 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500810 }
811 }
812
John Spurlockcf053c12015-05-14 16:33:59 -0400813 private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
814 SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
fionaxu1bf6ec22016-05-23 16:33:16 -0700815 null, 0, 0, "");
John Spurlockcf053c12015-05-14 16:33:59 -0400816 mMobileSignalControllers.put(id, new MobileSignalController(mContext,
Jason Monk07b75fe2015-05-14 16:47:03 -0400817 mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
Jason Monkc6cc6262015-06-11 11:10:15 -0400818 mSubDefaults, mReceiverHandler.getLooper()));
John Spurlockcf053c12015-05-14 16:33:59 -0400819 return info;
820 }
821
Adrian Roos316bf542016-08-23 17:53:07 +0200822 public boolean hasEmergencyCryptKeeperText() {
823 return EncryptionHelper.IS_DATA_ENCRYPTED;
824 }
825
826 public boolean isRadioOn() {
827 return !mAirplaneMode;
828 }
829
Jason Monk8fcab352015-06-29 10:57:00 -0400830 private class SubListener extends OnSubscriptionsChangedListener {
Jason Monkc9f05712014-12-15 12:24:10 -0500831 @Override
832 public void onSubscriptionsChanged() {
Jason Monkb5746272014-11-12 16:50:31 -0500833 updateMobileControllers();
Jason Monk8fcab352015-06-29 10:57:00 -0400834 }
835 }
Jason Monkb5746272014-11-12 16:50:31 -0500836
Jason Monk07b75fe2015-05-14 16:47:03 -0400837 /**
838 * Used to register listeners from the BG Looper, this way the PhoneStateListeners that
839 * get created will also run on the BG Looper.
840 */
841 private final Runnable mRegisterListeners = new Runnable() {
842 @Override
843 public void run() {
844 registerListeners();
845 }
846 };
Jason Monkd2263cd2014-11-10 14:22:56 -0500847
Jason Monkc6cc6262015-06-11 11:10:15 -0400848 public static class SubscriptionDefaults {
849 public int getDefaultVoiceSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -0800850 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400851 }
852
853 public int getDefaultDataSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -0800854 return SubscriptionManager.getDefaultDataSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400855 }
856 }
857
Jason Monkd2263cd2014-11-10 14:22:56 -0500858 @VisibleForTesting
859 static class Config {
Jason Monkb5746272014-11-12 16:50:31 -0500860 boolean showAtLeast3G = false;
Jason Monkd2263cd2014-11-10 14:22:56 -0500861 boolean alwaysShowCdmaRssi = false;
862 boolean show4gForLte = false;
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700863 boolean hideLtePlus = false;
Jason Monkd2263cd2014-11-10 14:22:56 -0500864 boolean hspaDataDistinguishable;
865
866 static Config readConfig(Context context) {
867 Config config = new Config();
868 Resources res = context.getResources();
869
Jason Monkb5746272014-11-12 16:50:31 -0500870 config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
Jason Monkd2263cd2014-11-10 14:22:56 -0500871 config.alwaysShowCdmaRssi =
872 res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
873 config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE);
874 config.hspaDataDistinguishable =
875 res.getBoolean(R.bool.config_hspa_data_distinguishable);
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700876 config.hideLtePlus = res.getBoolean(R.bool.config_hideLtePlus);
Jason Monkd2263cd2014-11-10 14:22:56 -0500877 return config;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400878 }
879 }
880}