blob: c21f444d0bf34c476e34ec7519c77c575a48c5ce [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;
Jason Monk9c7844c2017-01-18 15:21:53 -050023import android.content.res.Configuration;
John Spurlockaf8d6c42014-05-07 17:49:08 -040024import android.content.res.Resources;
25import android.net.ConnectivityManager;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090026import android.net.NetworkCapabilities;
Sundeep Ghumand57f3242017-01-13 15:31:48 -080027import android.net.NetworkScoreManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040028import android.net.wifi.WifiManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040029import android.os.AsyncTask;
30import android.os.Bundle;
Jason Monk07b75fe2015-05-14 16:47:03 -040031import android.os.Handler;
Jason Monk30d80042015-05-08 16:54:18 -040032import android.os.Looper;
John Spurlockaf8d6c42014-05-07 17:49:08 -040033import android.provider.Settings;
Jason Monkb0808aa2015-07-22 16:34:36 -040034import android.telephony.ServiceState;
Jason Monk48edc0c2017-04-10 15:01:27 -040035import android.telephony.SignalStrength;
Jason Monkb5746272014-11-12 16:50:31 -050036import android.telephony.SubscriptionInfo;
37import android.telephony.SubscriptionManager;
38import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
John Spurlockaf8d6c42014-05-07 17:49:08 -040039import android.telephony.TelephonyManager;
Jason Monkb5746272014-11-12 16:50:31 -050040import android.text.TextUtils;
John Spurlockaf8d6c42014-05-07 17:49:08 -040041import android.util.Log;
John Spurlockcf053c12015-05-14 16:33:59 -040042import android.util.MathUtils;
Jason Monk8996b942017-03-02 13:58:19 -050043import android.util.SparseArray;
Winsonc0d70582016-01-29 10:24:39 -080044
Jason Monke0cdb602014-11-05 12:39:45 -050045import com.android.internal.annotations.VisibleForTesting;
Jason Monkb5746272014-11-12 16:50:31 -050046import com.android.internal.telephony.PhoneConstants;
John Spurlockaf8d6c42014-05-07 17:49:08 -040047import com.android.internal.telephony.TelephonyIntents;
Jason Monkf668d7c2016-01-14 10:38:41 -050048import com.android.settingslib.net.DataUsageController;
Jason Monk9c7844c2017-01-18 15:21:53 -050049import com.android.systemui.ConfigurationChangedReceiver;
John Spurlockaf8d6c42014-05-07 17:49:08 -040050import com.android.systemui.DemoMode;
Jason Monk9c7844c2017-01-18 15:21:53 -050051import com.android.systemui.Dumpable;
John Spurlockaf8d6c42014-05-07 17:49:08 -040052import com.android.systemui.R;
Jason Monk9c7844c2017-01-18 15:21:53 -050053import com.android.systemui.settings.CurrentUserTracker;
54import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
John Spurlockaf8d6c42014-05-07 17:49:08 -040055
56import java.io.FileDescriptor;
57import java.io.PrintWriter;
58import java.util.ArrayList;
Lorenzo Colitti403aa262014-11-28 11:21:30 +090059import java.util.BitSet;
Jason Monkb5746272014-11-12 16:50:31 -050060import java.util.Collections;
61import java.util.Comparator;
Jason Monkd2263cd2014-11-10 14:22:56 -050062import java.util.HashMap;
John Spurlockaf8d6c42014-05-07 17:49:08 -040063import java.util.List;
64import java.util.Locale;
Jason Monkd2263cd2014-11-10 14:22:56 -050065import java.util.Map;
John Spurlockaf8d6c42014-05-07 17:49:08 -040066
Jason Monk4cf95ae2015-11-16 15:59:53 -050067import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
68
John Spurlockaf8d6c42014-05-07 17:49:08 -040069/** Platform implementation of the network controller. **/
70public class NetworkControllerImpl extends BroadcastReceiver
Jason Monk9c7844c2017-01-18 15:21:53 -050071 implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider,
72 ConfigurationChangedReceiver, Dumpable {
John Spurlockaf8d6c42014-05-07 17:49:08 -040073 // debug
Jason Monkd2263cd2014-11-10 14:22:56 -050074 static final String TAG = "NetworkController";
75 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
76 // additional diagnostics, but not logspew
Jason Monk07b75fe2015-05-14 16:47:03 -040077 static final boolean CHATTY = Log.isLoggable(TAG + "Chat", Log.DEBUG);
John Spurlockaf8d6c42014-05-07 17:49:08 -040078
Jason Monk66845a32015-08-03 11:09:41 -040079 private static final int EMERGENCY_NO_CONTROLLERS = 0;
80 private static final int EMERGENCY_FIRST_CONTROLLER = 100;
81 private static final int EMERGENCY_VOICE_CONTROLLER = 200;
82 private static final int EMERGENCY_NO_SUB = 300;
Jason Monk8996b942017-03-02 13:58:19 -050083 private static final int EMERGENCY_ASSUMED_VOICE_CONTROLLER = 400;
Jason Monk66845a32015-08-03 11:09:41 -040084
Jason Monkd2263cd2014-11-10 14:22:56 -050085 private final Context mContext;
86 private final TelephonyManager mPhone;
87 private final WifiManager mWifiManager;
88 private final ConnectivityManager mConnectivityManager;
Jason Monkb5746272014-11-12 16:50:31 -050089 private final SubscriptionManager mSubscriptionManager;
Jason Monkd2263cd2014-11-10 14:22:56 -050090 private final boolean mHasMobileDataFeature;
Jason Monkc6cc6262015-06-11 11:10:15 -040091 private final SubscriptionDefaults mSubDefaults;
Jason Monk9a4ce132016-01-21 15:27:17 -050092 private final DataSaverController mDataSaverController;
Jason Monk9c7844c2017-01-18 15:21:53 -050093 private final CurrentUserTracker mUserTracker;
Jason Monk3aaabd72014-12-12 11:11:44 -050094 private Config mConfig;
Sundeep Ghumand57f3242017-01-13 15:31:48 -080095 private final NetworkScoreManager mNetworkScoreManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040096
Jason Monkd2263cd2014-11-10 14:22:56 -050097 // Subcontrollers.
98 @VisibleForTesting
99 final WifiSignalController mWifiSignalController;
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900100
101 @VisibleForTesting
102 final EthernetSignalController mEthernetSignalController;
103
Jason Monkd2263cd2014-11-10 14:22:56 -0500104 @VisibleForTesting
Jason Monk8996b942017-03-02 13:58:19 -0500105 final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>();
Jason Monkb5746272014-11-12 16:50:31 -0500106 // When no SIMs are around at setup, and one is added later, it seems to default to the first
107 // SIM for most actions. This may be null if there aren't any SIMs around.
108 private MobileSignalController mDefaultSignalController;
Jason Monk0e2400f2014-11-21 11:08:55 -0500109 private final AccessPointControllerImpl mAccessPoints;
Jason Monkf668d7c2016-01-14 10:38:41 -0500110 private final DataUsageController mDataUsageController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400111
Jason Monkd2263cd2014-11-10 14:22:56 -0500112 private boolean mInetCondition; // Used for Logging and demo.
Lorenzo Colitti23dd1762014-09-10 22:58:54 +0900113
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900114 // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are
115 // connected and validated, respectively.
116 private final BitSet mConnectedTransports = new BitSet();
117 private final BitSet mValidatedTransports = new BitSet();
118
Jason Monkd2263cd2014-11-10 14:22:56 -0500119 // States that don't belong to a subcontroller.
John Spurlockaf8d6c42014-05-07 17:49:08 -0400120 private boolean mAirplaneMode = false;
Jason Monkb5746272014-11-12 16:50:31 -0500121 private boolean mHasNoSims;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400122 private Locale mLocale = null;
Jason Monkb5746272014-11-12 16:50:31 -0500123 // This list holds our ordering.
John Spurlockcf053c12015-05-14 16:33:59 -0400124 private List<SubscriptionInfo> mCurrentSubscriptions = new ArrayList<>();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400125
Jason Monkc014dec2014-12-12 11:49:55 -0500126 @VisibleForTesting
127 boolean mListening;
John Spurlock7f8f22a2014-07-02 18:54:17 -0400128
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900129 // The current user ID.
130 private int mCurrentUserId;
131
Jason Monk8fcab352015-06-29 10:57:00 -0400132 private OnSubscriptionsChangedListener mSubscriptionListener;
133
Jason Monk07b75fe2015-05-14 16:47:03 -0400134 // Handler that all broadcasts are received on.
135 private final Handler mReceiverHandler;
136 // Handler that all callbacks are made on.
137 private final CallbackHandler mCallbackHandler;
138
Jason Monk66845a32015-08-03 11:09:41 -0400139 private int mEmergencySource;
140 private boolean mIsEmergency;
141
Jason Monkb0808aa2015-07-22 16:34:36 -0400142 @VisibleForTesting
143 ServiceState mLastServiceState;
Jason Monkfd57ea72016-04-29 13:37:58 -0400144 private boolean mUserSetup;
Jason Monkb0808aa2015-07-22 16:34:36 -0400145
John Spurlockaf8d6c42014-05-07 17:49:08 -0400146 /**
147 * Construct this controller object and register for updates.
148 */
Jason Monk9c7844c2017-01-18 15:21:53 -0500149 public NetworkControllerImpl(Context context, Looper bgLooper,
150 DeviceProvisionedController deviceProvisionedController) {
Jason Monkf13b4b32014-11-07 16:39:34 -0500151 this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
Sundeep Ghumand57f3242017-01-13 15:31:48 -0800152 context.getSystemService(NetworkScoreManager.class),
Jason Monkf13b4b32014-11-07 16:39:34 -0500153 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
Jason Monk29f7a7b2014-11-17 14:40:56 -0500154 (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
Sundeep Ghumand57f3242017-01-13 15:31:48 -0800155 SubscriptionManager.from(context),
156 Config.readConfig(context),
157 bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400158 new CallbackHandler(),
Jason Monk30d80042015-05-08 16:54:18 -0400159 new AccessPointControllerImpl(context, bgLooper),
Jason Monkf668d7c2016-01-14 10:38:41 -0500160 new DataUsageController(context),
Jason Monk9c7844c2017-01-18 15:21:53 -0500161 new SubscriptionDefaults(),
162 deviceProvisionedController);
Jason Monk07b75fe2015-05-14 16:47:03 -0400163 mReceiverHandler.post(mRegisterListeners);
Jason Monkf13b4b32014-11-07 16:39:34 -0500164 }
165
166 @VisibleForTesting
167 NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
Sundeep Ghumand57f3242017-01-13 15:31:48 -0800168 NetworkScoreManager networkScoreManager,
169 TelephonyManager telephonyManager,
170 WifiManager wifiManager,
171 SubscriptionManager subManager,
172 Config config,
173 Looper bgLooper,
Jason Monk07b75fe2015-05-14 16:47:03 -0400174 CallbackHandler callbackHandler,
Jason Monkd2263cd2014-11-10 14:22:56 -0500175 AccessPointControllerImpl accessPointController,
Jason Monkf668d7c2016-01-14 10:38:41 -0500176 DataUsageController dataUsageController,
Jason Monk9c7844c2017-01-18 15:21:53 -0500177 SubscriptionDefaults defaultsHandler,
178 DeviceProvisionedController deviceProvisionedController) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400179 mContext = context;
Jason Monkb5746272014-11-12 16:50:31 -0500180 mConfig = config;
Jason Monk07b75fe2015-05-14 16:47:03 -0400181 mReceiverHandler = new Handler(bgLooper);
182 mCallbackHandler = callbackHandler;
Jason Monk9abca5e2016-11-11 16:18:14 -0500183 mDataSaverController = new DataSaverControllerImpl(context);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400184
Jason Monkb5746272014-11-12 16:50:31 -0500185 mSubscriptionManager = subManager;
Jason Monkc6cc6262015-06-11 11:10:15 -0400186 mSubDefaults = defaultsHandler;
Jason Monkf13b4b32014-11-07 16:39:34 -0500187 mConnectivityManager = connectivityManager;
188 mHasMobileDataFeature =
189 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400190
John Spurlockaf8d6c42014-05-07 17:49:08 -0400191 // telephony
Jason Monk07b75fe2015-05-14 16:47:03 -0400192 mPhone = telephonyManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400193
194 // wifi
Jason Monkf13b4b32014-11-07 16:39:34 -0500195 mWifiManager = wifiManager;
Sundeep Ghumand57f3242017-01-13 15:31:48 -0800196 mNetworkScoreManager = networkScoreManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400197
Jason Monkd2263cd2014-11-10 14:22:56 -0500198 mLocale = mContext.getResources().getConfiguration().locale;
Jason Monk29f7a7b2014-11-17 14:40:56 -0500199 mAccessPoints = accessPointController;
Jason Monkf668d7c2016-01-14 10:38:41 -0500200 mDataUsageController = dataUsageController;
201 mDataUsageController.setNetworkController(this);
202 // TODO: Find a way to move this into DataUsageController.
203 mDataUsageController.setCallback(new DataUsageController.Callback() {
Jason Monke0cdb602014-11-05 12:39:45 -0500204 @Override
205 public void onMobileDataEnabled(boolean enabled) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400206 mCallbackHandler.setMobileDataEnabled(enabled);
Jason Monke0cdb602014-11-05 12:39:45 -0500207 }
208 });
Jason Monkd2263cd2014-11-10 14:22:56 -0500209 mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
Sundeep Ghumand57f3242017-01-13 15:31:48 -0800210 mCallbackHandler, this, mNetworkScoreManager);
Jason Monkd2263cd2014-11-10 14:22:56 -0500211
Jason Monk07b75fe2015-05-14 16:47:03 -0400212 mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900213
Jason Monkd2263cd2014-11-10 14:22:56 -0500214 // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
Jason Monkb5746272014-11-12 16:50:31 -0500215 updateAirplaneMode(true /* force callback */);
Jason Monk9c7844c2017-01-18 15:21:53 -0500216 mUserTracker = new CurrentUserTracker(mContext) {
217 @Override
218 public void onUserSwitched(int newUserId) {
219 NetworkControllerImpl.this.onUserSwitched(newUserId);
220 }
221 };
222 mUserTracker.startTracking();
223 deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
224 @Override
225 public void onUserSetupChanged() {
226 setUserSetupComplete(deviceProvisionedController.isUserSetup(
227 deviceProvisionedController.getCurrentUser()));
228 }
229 });
Jason Monke0cdb602014-11-05 12:39:45 -0500230 }
231
Jason Monk9a4ce132016-01-21 15:27:17 -0500232 public DataSaverController getDataSaverController() {
233 return mDataSaverController;
234 }
235
Jason Monkf13b4b32014-11-07 16:39:34 -0500236 private void registerListeners() {
Jason Monk8996b942017-03-02 13:58:19 -0500237 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
238 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500239 mobileSignalController.registerListener();
240 }
Jason Monk8fcab352015-06-29 10:57:00 -0400241 if (mSubscriptionListener == null) {
242 mSubscriptionListener = new SubListener();
243 }
Wink Saville071743f2015-01-12 17:11:04 -0800244 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monke0cdb602014-11-05 12:39:45 -0500245
John Spurlockaf8d6c42014-05-07 17:49:08 -0400246 // broadcasts
247 IntentFilter filter = new IntentFilter();
248 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
249 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
250 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
251 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Jason Monkb5746272014-11-12 16:50:31 -0500252 filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
253 filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
Jason Monkb0808aa2015-07-22 16:34:36 -0400254 filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400255 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
Erik Kline32830cc2015-04-21 13:09:15 +0900256 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400257 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400258 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
Jason Monk07b75fe2015-05-14 16:47:03 -0400259 mContext.registerReceiver(this, filter, null, mReceiverHandler);
Jason Monkb5746272014-11-12 16:50:31 -0500260 mListening = true;
261
262 updateMobileControllers();
John Spurlockb98f7472014-07-08 17:09:42 -0400263 }
264
Jason Monkd2263cd2014-11-10 14:22:56 -0500265 private void unregisterListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500266 mListening = false;
Jason Monk8996b942017-03-02 13:58:19 -0500267 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
268 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500269 mobileSignalController.unregisterListener();
270 }
Wink Saville071743f2015-01-12 17:11:04 -0800271 mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
Jason Monkd2263cd2014-11-10 14:22:56 -0500272 mContext.unregisterReceiver(this);
Jason Monk5d325072014-10-27 11:38:47 -0400273 }
274
Jason Monk0e2400f2014-11-21 11:08:55 -0500275 public int getConnectedWifiLevel() {
276 return mWifiSignalController.getState().level;
277 }
278
Jason Monk5d325072014-10-27 11:38:47 -0400279 @Override
Jason Monkd2263cd2014-11-10 14:22:56 -0500280 public AccessPointController getAccessPointController() {
281 return mAccessPoints;
282 }
283
284 @Override
Jason Monkf668d7c2016-01-14 10:38:41 -0500285 public DataUsageController getMobileDataController() {
286 return mDataUsageController;
Jason Monkd2263cd2014-11-10 14:22:56 -0500287 }
288
289 public void addEmergencyListener(EmergencyListener listener) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400290 mCallbackHandler.setListening(listener, true);
291 mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400292 }
293
Jason Monk46dbfb42016-02-25 14:59:20 -0500294 public void removeEmergencyListener(EmergencyListener listener) {
295 mCallbackHandler.setListening(listener, false);
296 }
297
John Spurlockaf8d6c42014-05-07 17:49:08 -0400298 public boolean hasMobileDataFeature() {
299 return mHasMobileDataFeature;
300 }
301
302 public boolean hasVoiceCallingFeature() {
303 return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
304 }
305
Jason Monkb5746272014-11-12 16:50:31 -0500306 private MobileSignalController getDataController() {
Jason Monkc6cc6262015-06-11 11:10:15 -0400307 int dataSubId = mSubDefaults.getDefaultDataSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800308 if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
Jason Monkb5746272014-11-12 16:50:31 -0500309 if (DEBUG) Log.e(TAG, "No data sim selected");
310 return mDefaultSignalController;
311 }
Jason Monk8996b942017-03-02 13:58:19 -0500312 if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500313 return mMobileSignalControllers.get(dataSubId);
314 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500315 if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
Jason Monkb5746272014-11-12 16:50:31 -0500316 return mDefaultSignalController;
317 }
318
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700319 public String getMobileDataNetworkName() {
Jason Monkb5746272014-11-12 16:50:31 -0500320 MobileSignalController controller = getDataController();
Pavel Zhamaitsiak5504d392015-03-27 09:24:47 -0700321 return controller != null ? controller.getState().networkNameData : "";
Jason Monkd2263cd2014-11-10 14:22:56 -0500322 }
323
John Spurlockaf8d6c42014-05-07 17:49:08 -0400324 public boolean isEmergencyOnly() {
Jason Monkb0808aa2015-07-22 16:34:36 -0400325 if (mMobileSignalControllers.size() == 0) {
326 // When there are no active subscriptions, determine emengency state from last
327 // broadcast.
Jason Monk66845a32015-08-03 11:09:41 -0400328 mEmergencySource = EMERGENCY_NO_CONTROLLERS;
Jason Monkb0808aa2015-07-22 16:34:36 -0400329 return mLastServiceState != null && mLastServiceState.isEmergencyOnly();
330 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400331 int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
Wink Savillea54bf652014-12-11 13:37:50 -0800332 if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
Jason Monk8996b942017-03-02 13:58:19 -0500333 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
334 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkc6cc6262015-06-11 11:10:15 -0400335 if (!mobileSignalController.getState().isEmergency) {
Jason Monk66845a32015-08-03 11:09:41 -0400336 mEmergencySource = EMERGENCY_FIRST_CONTROLLER
337 + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400338 if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag);
Jason Monkb5746272014-11-12 16:50:31 -0500339 return false;
340 }
341 }
342 }
Jason Monk8996b942017-03-02 13:58:19 -0500343 if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) {
Jason Monk66845a32015-08-03 11:09:41 -0400344 mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
Jason Monkc6cc6262015-06-11 11:10:15 -0400345 if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
346 return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
Jason Monkb5746272014-11-12 16:50:31 -0500347 }
Jason Monk8996b942017-03-02 13:58:19 -0500348 // If we have the wrong subId but there is only one sim anyway, assume it should be the
349 // default.
350 if (mMobileSignalControllers.size() == 1) {
351 mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER
352 + mMobileSignalControllers.keyAt(0);
353 if (DEBUG) Log.d(TAG, "Getting assumed emergency from "
354 + mMobileSignalControllers.keyAt(0));
355 return mMobileSignalControllers.valueAt(0).getState().isEmergency;
356 }
Dan Sandlerc8466322014-12-08 15:42:52 -0500357 if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
Jason Monk66845a32015-08-03 11:09:41 -0400358 mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
Jason Monkb5746272014-11-12 16:50:31 -0500359 // Something is wrong, better assume we can't make calls...
360 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400361 }
362
Jason Monkd2263cd2014-11-10 14:22:56 -0500363 /**
364 * Emergency status may have changed (triggered by MobileSignalController),
365 * so we should recheck and send out the state to listeners.
366 */
367 void recalculateEmergency() {
Jason Monk66845a32015-08-03 11:09:41 -0400368 mIsEmergency = isEmergencyOnly();
369 mCallbackHandler.setEmergencyCallsOnly(mIsEmergency);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400370 }
371
Jason Monk88529052016-11-04 13:29:58 -0400372 public void addCallback(SignalCallback cb) {
Jason Monke06b0652016-03-02 16:35:27 -0500373 cb.setSubs(mCurrentSubscriptions);
374 cb.setIsAirplaneMode(new IconState(mAirplaneMode,
Jason Monk07b75fe2015-05-14 16:47:03 -0400375 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
Jason Monke06b0652016-03-02 16:35:27 -0500376 cb.setNoSims(mHasNoSims);
377 mWifiSignalController.notifyListeners(cb);
378 mEthernetSignalController.notifyListeners(cb);
Jason Monk8996b942017-03-02 13:58:19 -0500379 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
380 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monke06b0652016-03-02 16:35:27 -0500381 mobileSignalController.notifyListeners(cb);
Jason Monkb5746272014-11-12 16:50:31 -0500382 }
Jason Monke06b0652016-03-02 16:35:27 -0500383 mCallbackHandler.setListening(cb, true);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400384 }
385
Jason Monk07b75fe2015-05-14 16:47:03 -0400386 @Override
Jason Monk88529052016-11-04 13:29:58 -0400387 public void removeCallback(SignalCallback cb) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400388 mCallbackHandler.setListening(cb, false);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400389 }
390
391 @Override
392 public void setWifiEnabled(final boolean enabled) {
393 new AsyncTask<Void, Void, Void>() {
394 @Override
395 protected Void doInBackground(Void... args) {
396 // Disable tethering if enabling Wifi
397 final int wifiApState = mWifiManager.getWifiApState();
398 if (enabled && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
Jason Monkd2263cd2014-11-10 14:22:56 -0500399 (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400400 mWifiManager.setWifiApEnabled(null, false);
401 }
402
403 mWifiManager.setWifiEnabled(enabled);
404 return null;
405 }
406 }.execute();
407 }
408
Jason Monk9c7844c2017-01-18 15:21:53 -0500409 private void onUserSwitched(int newUserId) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900410 mCurrentUserId = newUserId;
411 mAccessPoints.onUserSwitched(newUserId);
412 updateConnectivity();
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900413 }
414
415 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400416 public void onReceive(Context context, Intent intent) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500417 if (CHATTY) {
418 Log.d(TAG, "onReceive: intent=" + intent);
419 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400420 final String action = intent.getAction();
Erik Kline32830cc2015-04-21 13:09:15 +0900421 if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
Jason Monkd2263cd2014-11-10 14:22:56 -0500422 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900423 updateConnectivity();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400424 } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
425 refreshLocale();
Jason Monkd2263cd2014-11-10 14:22:56 -0500426 updateAirplaneMode(false);
Jason Monkb5746272014-11-12 16:50:31 -0500427 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED)) {
428 // We are using different subs now, we might be able to make calls.
429 recalculateEmergency();
430 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
431 // Notify every MobileSignalController so they can know whether they are the
432 // data sim or not.
Jason Monk8996b942017-03-02 13:58:19 -0500433 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
434 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500435 controller.handleBroadcast(intent);
436 }
437 } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
438 // Might have different subscriptions now.
439 updateMobileControllers();
Jason Monkb0808aa2015-07-22 16:34:36 -0400440 } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
441 mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
442 if (mMobileSignalControllers.size() == 0) {
443 // If none of the subscriptions are active, we might need to recalculate
444 // emergency state.
445 recalculateEmergency();
446 }
Jason Monkb5746272014-11-12 16:50:31 -0500447 } else {
448 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
449 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Savillea54bf652014-12-11 13:37:50 -0800450 if (SubscriptionManager.isValidSubscriptionId(subId)) {
Jason Monk8996b942017-03-02 13:58:19 -0500451 if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500452 mMobileSignalControllers.get(subId).handleBroadcast(intent);
453 } else {
454 // Can't find this subscription... We must be out of date.
455 updateMobileControllers();
456 }
457 } else {
458 // No sub id, must be for the wifi.
459 mWifiSignalController.handleBroadcast(intent);
460 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400461 }
Jason Monkb5746272014-11-12 16:50:31 -0500462 }
463
Jason Monk9c7844c2017-01-18 15:21:53 -0500464 public void onConfigurationChanged(Configuration newConfig) {
Sungmin Choi6be4f6b2015-07-07 13:06:59 +0900465 mConfig = Config.readConfig(mContext);
Jason Monk1c040db2015-07-20 09:45:54 -0400466 mReceiverHandler.post(new Runnable() {
467 @Override
468 public void run() {
469 handleConfigurationChanged();
470 }
471 });
472 }
473
474 @VisibleForTesting
475 void handleConfigurationChanged() {
Jason Monk8996b942017-03-02 13:58:19 -0500476 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
477 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
478 controller.setConfiguration(mConfig);
Jason Monk3aaabd72014-12-12 11:11:44 -0500479 }
480 refreshLocale();
Jason Monk3aaabd72014-12-12 11:11:44 -0500481 }
482
Jason Monkb5746272014-11-12 16:50:31 -0500483 private void updateMobileControllers() {
484 if (!mListening) {
485 return;
486 }
Jason Monkc6cc6262015-06-11 11:10:15 -0400487 doUpdateMobileControllers();
488 }
489
490 @VisibleForTesting
491 void doUpdateMobileControllers() {
Jason Monkb5746272014-11-12 16:50:31 -0500492 List<SubscriptionInfo> subscriptions = mSubscriptionManager.getActiveSubscriptionInfoList();
Jason Monkc9f05712014-12-15 12:24:10 -0500493 if (subscriptions == null) {
494 subscriptions = Collections.emptyList();
495 }
Jason Monkb5746272014-11-12 16:50:31 -0500496 // If there have been no relevant changes to any of the subscriptions, we can leave as is.
497 if (hasCorrectMobileControllers(subscriptions)) {
498 // Even if the controllers are correct, make sure we have the right no sims state.
499 // Such as on boot, don't need any controllers, because there are no sims,
500 // but we still need to update the no sim state.
501 updateNoSims();
502 return;
503 }
504 setCurrentSubscriptions(subscriptions);
505 updateNoSims();
Jason Monkc6cc6262015-06-11 11:10:15 -0400506 recalculateEmergency();
Jason Monkb5746272014-11-12 16:50:31 -0500507 }
508
Jason Monk21d05a02014-12-02 12:46:58 -0500509 @VisibleForTesting
510 protected void updateNoSims() {
511 boolean hasNoSims = mHasMobileDataFeature && mMobileSignalControllers.size() == 0;
Jason Monkb5746272014-11-12 16:50:31 -0500512 if (hasNoSims != mHasNoSims) {
513 mHasNoSims = hasNoSims;
Jason Monk259e06f2015-06-18 14:07:26 -0400514 mCallbackHandler.setNoSims(mHasNoSims);
Jason Monkb5746272014-11-12 16:50:31 -0500515 }
516 }
517
518 @VisibleForTesting
519 void setCurrentSubscriptions(List<SubscriptionInfo> subscriptions) {
520 Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() {
521 @Override
522 public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) {
523 return lhs.getSimSlotIndex() == rhs.getSimSlotIndex()
524 ? lhs.getSubscriptionId() - rhs.getSubscriptionId()
525 : lhs.getSimSlotIndex() - rhs.getSimSlotIndex();
526 }
527 });
Jason Monkb5746272014-11-12 16:50:31 -0500528 mCurrentSubscriptions = subscriptions;
529
Jason Monk8996b942017-03-02 13:58:19 -0500530 SparseArray<MobileSignalController> cachedControllers =
531 new SparseArray<MobileSignalController>();
532 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
533 cachedControllers.put(mMobileSignalControllers.keyAt(i),
534 mMobileSignalControllers.valueAt(i));
535 }
Jason Monkb5746272014-11-12 16:50:31 -0500536 mMobileSignalControllers.clear();
537 final int num = subscriptions.size();
538 for (int i = 0; i < num; i++) {
539 int subId = subscriptions.get(i).getSubscriptionId();
540 // If we have a copy of this controller already reuse it, otherwise make a new one.
Jason Monk8996b942017-03-02 13:58:19 -0500541 if (cachedControllers.indexOfKey(subId) >= 0) {
542 mMobileSignalControllers.put(subId, cachedControllers.get(subId));
543 cachedControllers.remove(subId);
Jason Monkb5746272014-11-12 16:50:31 -0500544 } else {
545 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
Jason Monk07b75fe2015-05-14 16:47:03 -0400546 mHasMobileDataFeature, mPhone, mCallbackHandler,
Jason Monkc6cc6262015-06-11 11:10:15 -0400547 this, subscriptions.get(i), mSubDefaults, mReceiverHandler.getLooper());
Jason Monkfd57ea72016-04-29 13:37:58 -0400548 controller.setUserSetupComplete(mUserSetup);
Jason Monkb5746272014-11-12 16:50:31 -0500549 mMobileSignalControllers.put(subId, controller);
550 if (subscriptions.get(i).getSimSlotIndex() == 0) {
551 mDefaultSignalController = controller;
552 }
553 if (mListening) {
554 controller.registerListener();
555 }
556 }
557 }
558 if (mListening) {
Jason Monk8996b942017-03-02 13:58:19 -0500559 for (int i = 0; i < cachedControllers.size(); i++) {
560 int key = cachedControllers.keyAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500561 if (cachedControllers.get(key) == mDefaultSignalController) {
562 mDefaultSignalController = null;
563 }
564 cachedControllers.get(key).unregisterListener();
565 }
566 }
Jason Monk8fcab352015-06-29 10:57:00 -0400567 mCallbackHandler.setSubs(subscriptions);
568 notifyAllListeners();
569
Jason Monk25d8a482014-12-09 12:27:24 -0500570 // There may be new MobileSignalControllers around, make sure they get the current
571 // inet condition and airplane mode.
572 pushConnectivityToSignals();
573 updateAirplaneMode(true /* force */);
Jason Monkb5746272014-11-12 16:50:31 -0500574 }
575
Jason Monk0288de02017-02-23 14:48:05 -0500576 private void setUserSetupComplete(final boolean userSetup) {
577 mReceiverHandler.post(() -> handleSetUserSetupComplete(userSetup));
Jason Monkfd57ea72016-04-29 13:37:58 -0400578 }
579
Jason Monk0288de02017-02-23 14:48:05 -0500580 private void handleSetUserSetupComplete(boolean userSetup) {
Jason Monkfd57ea72016-04-29 13:37:58 -0400581 mUserSetup = userSetup;
Jason Monk8996b942017-03-02 13:58:19 -0500582 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
583 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkfd57ea72016-04-29 13:37:58 -0400584 controller.setUserSetupComplete(mUserSetup);
585 }
586 }
587
Jason Monkc014dec2014-12-12 11:49:55 -0500588 @VisibleForTesting
589 boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) {
Jason Monkc9f05712014-12-15 12:24:10 -0500590 if (allSubscriptions.size() != mMobileSignalControllers.size()) {
591 return false;
Jason Monkb5746272014-11-12 16:50:31 -0500592 }
593 for (SubscriptionInfo info : allSubscriptions) {
Jason Monk8996b942017-03-02 13:58:19 -0500594 if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) {
Jason Monkb5746272014-11-12 16:50:31 -0500595 return false;
596 }
597 }
598 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400599 }
600
Jason Monkd2263cd2014-11-10 14:22:56 -0500601 private void updateAirplaneMode(boolean force) {
602 boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
603 Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
604 if (airplaneMode != mAirplaneMode || force) {
605 mAirplaneMode = airplaneMode;
Jason Monk8996b942017-03-02 13:58:19 -0500606 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
607 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500608 mobileSignalController.setAirplaneMode(mAirplaneMode);
609 }
610 notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400611 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400612 }
613
614 private void refreshLocale() {
Jason Monkd2263cd2014-11-10 14:22:56 -0500615 Locale current = mContext.getResources().getConfiguration().locale;
Jason Monkb5746272014-11-12 16:50:31 -0500616 if (!current.equals(mLocale)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500617 mLocale = current;
618 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400619 }
620 }
621
Jason Monkd2263cd2014-11-10 14:22:56 -0500622 /**
Jason Monkb5746272014-11-12 16:50:31 -0500623 * Forces update of all callbacks on both SignalClusters and
624 * NetworkSignalChangedCallbacks.
625 */
Jason Monkd2263cd2014-11-10 14:22:56 -0500626 private void notifyAllListeners() {
Jason Monkb5746272014-11-12 16:50:31 -0500627 notifyListeners();
Jason Monk8996b942017-03-02 13:58:19 -0500628 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
629 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500630 mobileSignalController.notifyListeners();
631 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500632 mWifiSignalController.notifyListeners();
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900633 mEthernetSignalController.notifyListeners();
Jason Monkd2263cd2014-11-10 14:22:56 -0500634 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400635
Jason Monkb5746272014-11-12 16:50:31 -0500636 /**
637 * Notifies listeners of changes in state of to the NetworkController, but
638 * does not notify for any info on SignalControllers, for that call
639 * notifyAllListeners.
640 */
641 private void notifyListeners() {
Jason Monk07b75fe2015-05-14 16:47:03 -0400642 mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
643 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
644 mCallbackHandler.setNoSims(mHasNoSims);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400645 }
646
Jason Monkd2263cd2014-11-10 14:22:56 -0500647 /**
648 * Update the Inet conditions and what network we are connected to.
649 */
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900650 private void updateConnectivity() {
651 mConnectedTransports.clear();
652 mValidatedTransports.clear();
653 for (NetworkCapabilities nc :
654 mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
655 for (int transportType : nc.getTransportTypes()) {
656 mConnectedTransports.set(transportType);
657 if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
658 mValidatedTransports.set(transportType);
659 }
660 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400661 }
662
John Spurlockaf8d6c42014-05-07 17:49:08 -0400663 if (CHATTY) {
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900664 Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
665 Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400666 }
667
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900668 mInetCondition = !mValidatedTransports.isEmpty();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400669
Jason Monk25d8a482014-12-09 12:27:24 -0500670 pushConnectivityToSignals();
671 }
672
673 /**
674 * Pushes the current connectivity state to all SignalControllers.
675 */
676 private void pushConnectivityToSignals() {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400677 // We want to update all the icons, all at once, for any condition change
Jason Monk8996b942017-03-02 13:58:19 -0500678 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
679 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400680 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
Jason Monkb5746272014-11-12 16:50:31 -0500681 }
Jason Monk33f8ae72015-05-08 10:45:15 -0400682 mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
683 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400684 }
685
John Spurlockaf8d6c42014-05-07 17:49:08 -0400686 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
687 pw.println("NetworkController state:");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900688
John Spurlockaf8d6c42014-05-07 17:49:08 -0400689 pw.println(" - telephony ------");
690 pw.print(" hasVoiceCallingFeature()=");
691 pw.println(hasVoiceCallingFeature());
John Spurlockaf8d6c42014-05-07 17:49:08 -0400692
John Spurlockaf8d6c42014-05-07 17:49:08 -0400693 pw.println(" - connectivity ------");
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900694 pw.print(" mConnectedTransports=");
695 pw.println(mConnectedTransports);
696 pw.print(" mValidatedTransports=");
697 pw.println(mValidatedTransports);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400698 pw.print(" mInetCondition=");
699 pw.println(mInetCondition);
Jason Monkd2263cd2014-11-10 14:22:56 -0500700 pw.print(" mAirplaneMode=");
701 pw.println(mAirplaneMode);
702 pw.print(" mLocale=");
703 pw.println(mLocale);
Jason Monkb0808aa2015-07-22 16:34:36 -0400704 pw.print(" mLastServiceState=");
705 pw.println(mLastServiceState);
Jason Monk66845a32015-08-03 11:09:41 -0400706 pw.print(" mIsEmergency=");
707 pw.println(mIsEmergency);
708 pw.print(" mEmergencySource=");
709 pw.println(emergencyToString(mEmergencySource));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400710
Jason Monk8996b942017-03-02 13:58:19 -0500711 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
712 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500713 mobileSignalController.dump(pw);
714 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500715 mWifiSignalController.dump(pw);
Jason Monkd52356a2015-01-28 10:40:41 -0500716
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900717 mEthernetSignalController.dump(pw);
718
Jason Monkd52356a2015-01-28 10:40:41 -0500719 mAccessPoints.dump(pw);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400720 }
721
Jason Monk66845a32015-08-03 11:09:41 -0400722 private static final String emergencyToString(int emergencySource) {
723 if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk8996b942017-03-02 13:58:19 -0500724 return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER)
725 + ")";
726 } else if (emergencySource > EMERGENCY_NO_SUB) {
Jason Monk66845a32015-08-03 11:09:41 -0400727 return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
728 } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
729 return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
730 } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) {
731 return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")";
732 } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) {
733 return "NO_CONTROLLERS";
734 }
735 return "UNKNOWN_SOURCE";
736 }
737
John Spurlockaf8d6c42014-05-07 17:49:08 -0400738 private boolean mDemoMode;
Jason Monk33f8ae72015-05-08 10:45:15 -0400739 private boolean mDemoInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500740 private WifiSignalController.WifiState mDemoWifiState;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400741
742 @Override
743 public void dispatchDemoCommand(String command, Bundle args) {
744 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500745 if (DEBUG) Log.d(TAG, "Entering demo mode");
746 unregisterListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400747 mDemoMode = true;
Jason Monk33f8ae72015-05-08 10:45:15 -0400748 mDemoInetCondition = mInetCondition;
Jason Monkd2263cd2014-11-10 14:22:56 -0500749 mDemoWifiState = mWifiSignalController.getState();
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100750 mDemoWifiState.ssid = "DemoMode";
John Spurlockaf8d6c42014-05-07 17:49:08 -0400751 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500752 if (DEBUG) Log.d(TAG, "Exiting demo mode");
John Spurlockaf8d6c42014-05-07 17:49:08 -0400753 mDemoMode = false;
Jason Monkb5746272014-11-12 16:50:31 -0500754 // Update what MobileSignalControllers, because they may change
755 // to set the number of sim slots.
756 updateMobileControllers();
Jason Monk8996b942017-03-02 13:58:19 -0500757 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
758 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monkb5746272014-11-12 16:50:31 -0500759 controller.resetLastState();
760 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500761 mWifiSignalController.resetLastState();
Jason Monk07b75fe2015-05-14 16:47:03 -0400762 mReceiverHandler.post(mRegisterListeners);
Jason Monkd2263cd2014-11-10 14:22:56 -0500763 notifyAllListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400764 } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
765 String airplane = args.getString("airplane");
766 if (airplane != null) {
767 boolean show = airplane.equals("show");
Jason Monk07b75fe2015-05-14 16:47:03 -0400768 mCallbackHandler.setIsAirplaneMode(new IconState(show,
769 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode,
770 mContext));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400771 }
772 String fully = args.getString("fully");
773 if (fully != null) {
Jason Monk33f8ae72015-05-08 10:45:15 -0400774 mDemoInetCondition = Boolean.parseBoolean(fully);
775 BitSet connected = new BitSet();
776
777 if (mDemoInetCondition) {
778 connected.set(mWifiSignalController.mTransportType);
779 }
780 mWifiSignalController.updateConnectivity(connected, connected);
Jason Monk8996b942017-03-02 13:58:19 -0500781 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
782 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Jason Monk33f8ae72015-05-08 10:45:15 -0400783 if (mDemoInetCondition) {
784 connected.set(controller.mTransportType);
785 }
786 controller.updateConnectivity(connected, connected);
Jason Monkb5746272014-11-12 16:50:31 -0500787 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400788 }
789 String wifi = args.getString("wifi");
790 if (wifi != null) {
791 boolean show = wifi.equals("show");
792 String level = args.getString("level");
793 if (level != null) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500794 mDemoWifiState.level = level.equals("null") ? -1
John Spurlockaf8d6c42014-05-07 17:49:08 -0400795 : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
Jason Monkd2263cd2014-11-10 14:22:56 -0500796 mDemoWifiState.connected = mDemoWifiState.level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400797 }
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100798 String activity = args.getString("activity");
799 if (activity != null) {
800 switch (activity) {
801 case "inout":
802 mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_INOUT);
803 break;
804 case "in":
805 mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_IN);
806 break;
807 case "out":
808 mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_OUT);
809 break;
810 default:
811 mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE);
812 break;
813 }
814 } else {
815 mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE);
816 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500817 mDemoWifiState.enabled = show;
818 mWifiSignalController.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400819 }
Jason Monkb5746272014-11-12 16:50:31 -0500820 String sims = args.getString("sims");
821 if (sims != null) {
John Spurlockcf053c12015-05-14 16:33:59 -0400822 int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
823 List<SubscriptionInfo> subs = new ArrayList<>();
Jason Monkb5746272014-11-12 16:50:31 -0500824 if (num != mMobileSignalControllers.size()) {
825 mMobileSignalControllers.clear();
826 int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
827 for (int i = start /* get out of normal index range */; i < start + num; i++) {
John Spurlockcf053c12015-05-14 16:33:59 -0400828 subs.add(addSignalController(i, i));
Jason Monkb5746272014-11-12 16:50:31 -0500829 }
Jason Monk33b60bb2015-07-13 10:42:23 -0400830 mCallbackHandler.setSubs(subs);
Jason Monkb5746272014-11-12 16:50:31 -0500831 }
Jason Monkb5746272014-11-12 16:50:31 -0500832 }
833 String nosim = args.getString("nosim");
834 if (nosim != null) {
Jason Monk259e06f2015-06-18 14:07:26 -0400835 mHasNoSims = nosim.equals("show");
836 mCallbackHandler.setNoSims(mHasNoSims);
Jason Monkb5746272014-11-12 16:50:31 -0500837 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400838 String mobile = args.getString("mobile");
839 if (mobile != null) {
840 boolean show = mobile.equals("show");
841 String datatype = args.getString("datatype");
Jason Monkb5746272014-11-12 16:50:31 -0500842 String slotString = args.getString("slot");
843 int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
John Spurlockcf053c12015-05-14 16:33:59 -0400844 slot = MathUtils.constrain(slot, 0, 8);
845 // Ensure we have enough sim slots
846 List<SubscriptionInfo> subs = new ArrayList<>();
847 while (mMobileSignalControllers.size() <= slot) {
848 int nextSlot = mMobileSignalControllers.size();
849 subs.add(addSignalController(nextSlot, nextSlot));
850 }
851 if (!subs.isEmpty()) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400852 mCallbackHandler.setSubs(subs);
John Spurlockcf053c12015-05-14 16:33:59 -0400853 }
Jason Monkb5746272014-11-12 16:50:31 -0500854 // Hack to index linearly for easy use.
Jason Monk8996b942017-03-02 13:58:19 -0500855 MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
Jason Monkb5746272014-11-12 16:50:31 -0500856 controller.getState().dataSim = datatype != null;
Jason Monkb5950982017-01-24 15:53:53 -0500857 controller.getState().isDefault = datatype != null;
858 controller.getState().dataConnected = datatype != null;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400859 if (datatype != null) {
Jason Monkb5746272014-11-12 16:50:31 -0500860 controller.getState().iconGroup =
Jason Monkd2263cd2014-11-10 14:22:56 -0500861 datatype.equals("1x") ? TelephonyIcons.ONE_X :
862 datatype.equals("3g") ? TelephonyIcons.THREE_G :
863 datatype.equals("4g") ? TelephonyIcons.FOUR_G :
Ajay Nambi7965fa42015-05-14 18:48:33 -0700864 datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
Jason Monkd2263cd2014-11-10 14:22:56 -0500865 datatype.equals("e") ? TelephonyIcons.E :
866 datatype.equals("g") ? TelephonyIcons.G :
867 datatype.equals("h") ? TelephonyIcons.H :
868 datatype.equals("lte") ? TelephonyIcons.LTE :
Jason Monkaa730be2016-07-13 14:22:52 -0400869 datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
Jason Monkb5950982017-01-24 15:53:53 -0500870 datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
Jason Monkd2263cd2014-11-10 14:22:56 -0500871 TelephonyIcons.UNKNOWN;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400872 }
Jason Monk0f0de132016-12-19 15:36:13 -0500873 if (args.containsKey("roam")) {
874 controller.getState().roaming = "show".equals(args.getString("roam"));
875 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400876 String level = args.getString("level");
877 if (level != null) {
Jason Monkb5746272014-11-12 16:50:31 -0500878 controller.getState().level = level.equals("null") ? -1
Jason Monk48edc0c2017-04-10 15:01:27 -0400879 : Math.min(Integer.parseInt(level),
880 SignalStrength.NUM_SIGNAL_STRENGTH_BINS);
Jason Monkb5746272014-11-12 16:50:31 -0500881 controller.getState().connected = controller.getState().level >= 0;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400882 }
Jason Monk0f0de132016-12-19 15:36:13 -0500883 String activity = args.getString("activity");
884 if (activity != null) {
Kenneth Westin5c88ffb2013-11-28 16:29:40 +0100885 controller.getState().dataConnected = true;
886 switch (activity) {
887 case "inout":
888 controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
889 break;
890 case "in":
891 controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
892 break;
893 case "out":
894 controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
895 break;
896 default:
897 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
898 break;
899 }
900 } else {
901 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
Jason Monk0f0de132016-12-19 15:36:13 -0500902 }
Jason Monkb5746272014-11-12 16:50:31 -0500903 controller.getState().enabled = show;
904 controller.notifyListeners();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400905 }
Andrew Flynna478d702015-04-14 23:33:45 -0400906 String carrierNetworkChange = args.getString("carriernetworkchange");
907 if (carrierNetworkChange != null) {
908 boolean show = carrierNetworkChange.equals("show");
Jason Monk8996b942017-03-02 13:58:19 -0500909 for (int i = 0; i < mMobileSignalControllers.size(); i++) {
910 MobileSignalController controller = mMobileSignalControllers.valueAt(i);
Andrew Flynna478d702015-04-14 23:33:45 -0400911 controller.setCarrierNetworkChangeMode(show);
912 }
913 }
Jason Monkd2263cd2014-11-10 14:22:56 -0500914 }
915 }
916
John Spurlockcf053c12015-05-14 16:33:59 -0400917 private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
918 SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
fionaxu1bf6ec22016-05-23 16:33:16 -0700919 null, 0, 0, "");
Jason Monkb5950982017-01-24 15:53:53 -0500920 MobileSignalController controller = new MobileSignalController(mContext,
Jason Monk07b75fe2015-05-14 16:47:03 -0400921 mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
Jason Monkb5950982017-01-24 15:53:53 -0500922 mSubDefaults, mReceiverHandler.getLooper());
923 mMobileSignalControllers.put(id, controller);
924 controller.getState().userSetup = true;
John Spurlockcf053c12015-05-14 16:33:59 -0400925 return info;
926 }
927
Adrian Roos316bf542016-08-23 17:53:07 +0200928 public boolean hasEmergencyCryptKeeperText() {
929 return EncryptionHelper.IS_DATA_ENCRYPTED;
930 }
931
932 public boolean isRadioOn() {
933 return !mAirplaneMode;
934 }
935
Jason Monk8fcab352015-06-29 10:57:00 -0400936 private class SubListener extends OnSubscriptionsChangedListener {
Jason Monkc9f05712014-12-15 12:24:10 -0500937 @Override
938 public void onSubscriptionsChanged() {
Jason Monkb5746272014-11-12 16:50:31 -0500939 updateMobileControllers();
Jason Monk8fcab352015-06-29 10:57:00 -0400940 }
941 }
Jason Monkb5746272014-11-12 16:50:31 -0500942
Jason Monk07b75fe2015-05-14 16:47:03 -0400943 /**
944 * Used to register listeners from the BG Looper, this way the PhoneStateListeners that
945 * get created will also run on the BG Looper.
946 */
947 private final Runnable mRegisterListeners = new Runnable() {
948 @Override
949 public void run() {
950 registerListeners();
951 }
952 };
Jason Monkd2263cd2014-11-10 14:22:56 -0500953
Jason Monkc6cc6262015-06-11 11:10:15 -0400954 public static class SubscriptionDefaults {
955 public int getDefaultVoiceSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -0800956 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400957 }
958
959 public int getDefaultDataSubId() {
Shishir Agrawal7ea3e8b2016-01-25 13:03:07 -0800960 return SubscriptionManager.getDefaultDataSubscriptionId();
Jason Monkc6cc6262015-06-11 11:10:15 -0400961 }
962 }
963
Jason Monkd2263cd2014-11-10 14:22:56 -0500964 @VisibleForTesting
965 static class Config {
Jason Monkb5746272014-11-12 16:50:31 -0500966 boolean showAtLeast3G = false;
Jason Monkd2263cd2014-11-10 14:22:56 -0500967 boolean alwaysShowCdmaRssi = false;
968 boolean show4gForLte = false;
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700969 boolean hideLtePlus = false;
Jason Monkd2263cd2014-11-10 14:22:56 -0500970 boolean hspaDataDistinguishable;
971
972 static Config readConfig(Context context) {
973 Config config = new Config();
974 Resources res = context.getResources();
975
Jason Monkb5746272014-11-12 16:50:31 -0500976 config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
Jason Monkd2263cd2014-11-10 14:22:56 -0500977 config.alwaysShowCdmaRssi =
978 res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
979 config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE);
980 config.hspaDataDistinguishable =
981 res.getBoolean(R.bool.config_hspa_data_distinguishable);
Robert Greenwalt37d34ba2016-07-27 14:54:34 -0700982 config.hideLtePlus = res.getBoolean(R.bool.config_hideLtePlus);
Jason Monkd2263cd2014-11-10 14:22:56 -0500983 return config;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400984 }
985 }
986}