1 /* 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 17 package com.android.systemui.statusbar.policy; 18 19 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 20 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 21 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN; 22 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT; 23 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE; 24 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT; 25 import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE; 26 27 import android.content.BroadcastReceiver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.content.res.Configuration; 32 import android.content.res.Resources; 33 import android.net.ConnectivityManager; 34 import android.net.Network; 35 import android.net.NetworkCapabilities; 36 import android.net.NetworkScoreManager; 37 import android.net.wifi.WifiManager; 38 import android.os.AsyncTask; 39 import android.os.Bundle; 40 import android.os.Handler; 41 import android.os.Looper; 42 import android.os.PersistableBundle; 43 import android.provider.Settings; 44 import android.telephony.CarrierConfigManager; 45 import android.telephony.CellSignalStrength; 46 import android.telephony.PhoneStateListener; 47 import android.telephony.ServiceState; 48 import android.telephony.SubscriptionInfo; 49 import android.telephony.SubscriptionManager; 50 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 51 import android.telephony.TelephonyManager; 52 import android.text.TextUtils; 53 import android.util.Log; 54 import android.util.MathUtils; 55 import android.util.SparseArray; 56 57 import com.android.internal.annotations.GuardedBy; 58 import com.android.internal.annotations.VisibleForTesting; 59 import com.android.settingslib.net.DataUsageController; 60 import com.android.systemui.DemoMode; 61 import com.android.systemui.Dumpable; 62 import com.android.systemui.R; 63 import com.android.systemui.broadcast.BroadcastDispatcher; 64 import com.android.systemui.dagger.qualifiers.Background; 65 import com.android.systemui.settings.CurrentUserTracker; 66 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; 67 68 import java.io.FileDescriptor; 69 import java.io.PrintWriter; 70 import java.util.ArrayList; 71 import java.util.BitSet; 72 import java.util.Collections; 73 import java.util.Comparator; 74 import java.util.List; 75 import java.util.Locale; 76 77 import javax.inject.Inject; 78 import javax.inject.Singleton; 79 80 /** Platform implementation of the network controller. **/ 81 @Singleton 82 public class NetworkControllerImpl extends BroadcastReceiver 83 implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider, Dumpable { 84 // debug 85 static final String TAG = "NetworkController"; 86 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 87 // additional diagnostics, but not logspew 88 static final boolean CHATTY = Log.isLoggable(TAG + "Chat", Log.DEBUG); 89 90 private static final int EMERGENCY_NO_CONTROLLERS = 0; 91 private static final int EMERGENCY_FIRST_CONTROLLER = 100; 92 private static final int EMERGENCY_VOICE_CONTROLLER = 200; 93 private static final int EMERGENCY_NO_SUB = 300; 94 private static final int EMERGENCY_ASSUMED_VOICE_CONTROLLER = 400; 95 96 private final Context mContext; 97 private final TelephonyManager mPhone; 98 private final WifiManager mWifiManager; 99 private final ConnectivityManager mConnectivityManager; 100 private final SubscriptionManager mSubscriptionManager; 101 private final boolean mHasMobileDataFeature; 102 private final SubscriptionDefaults mSubDefaults; 103 private final DataSaverController mDataSaverController; 104 private final CurrentUserTracker mUserTracker; 105 private final BroadcastDispatcher mBroadcastDispatcher; 106 private final Object mLock = new Object(); 107 private Config mConfig; 108 109 private PhoneStateListener mPhoneStateListener; 110 private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 111 112 // Subcontrollers. 113 @VisibleForTesting 114 final WifiSignalController mWifiSignalController; 115 116 @VisibleForTesting 117 final EthernetSignalController mEthernetSignalController; 118 119 @VisibleForTesting 120 final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>(); 121 // When no SIMs are around at setup, and one is added later, it seems to default to the first 122 // SIM for most actions. This may be null if there aren't any SIMs around. 123 private MobileSignalController mDefaultSignalController; 124 private final AccessPointControllerImpl mAccessPoints; 125 private final DataUsageController mDataUsageController; 126 127 private boolean mInetCondition; // Used for Logging and demo. 128 129 // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are 130 // connected and validated, respectively. 131 private final BitSet mConnectedTransports = new BitSet(); 132 private final BitSet mValidatedTransports = new BitSet(); 133 134 // States that don't belong to a subcontroller. 135 private boolean mAirplaneMode = false; 136 private boolean mHasNoSubs; 137 private Locale mLocale = null; 138 // This list holds our ordering. 139 private List<SubscriptionInfo> mCurrentSubscriptions = new ArrayList<>(); 140 141 @VisibleForTesting 142 boolean mListening; 143 144 // The current user ID. 145 private int mCurrentUserId; 146 147 private OnSubscriptionsChangedListener mSubscriptionListener; 148 149 // Handler that all broadcasts are received on. 150 private final Handler mReceiverHandler; 151 // Handler that all callbacks are made on. 152 private final CallbackHandler mCallbackHandler; 153 154 private int mEmergencySource; 155 private boolean mIsEmergency; 156 157 @VisibleForTesting 158 ServiceState mLastServiceState; 159 private boolean mUserSetup; 160 private boolean mSimDetected; 161 private boolean mForceCellularValidated; 162 163 private ConfigurationController.ConfigurationListener mConfigurationListener = 164 new ConfigurationController.ConfigurationListener() { 165 @Override 166 public void onConfigChanged(Configuration newConfig) { 167 mConfig = Config.readConfig(mContext); 168 mReceiverHandler.post(() -> handleConfigurationChanged()); 169 } 170 }; 171 /** 172 * Construct this controller object and register for updates. 173 */ 174 @Inject NetworkControllerImpl(Context context, @Background Looper bgLooper, DeviceProvisionedController deviceProvisionedController, BroadcastDispatcher broadcastDispatcher, ConnectivityManager connectivityManager, TelephonyManager telephonyManager, WifiManager wifiManager, NetworkScoreManager networkScoreManager)175 public NetworkControllerImpl(Context context, @Background Looper bgLooper, 176 DeviceProvisionedController deviceProvisionedController, 177 BroadcastDispatcher broadcastDispatcher, ConnectivityManager connectivityManager, 178 TelephonyManager telephonyManager, WifiManager wifiManager, 179 NetworkScoreManager networkScoreManager) { 180 this(context, connectivityManager, 181 telephonyManager, 182 wifiManager, 183 networkScoreManager, 184 SubscriptionManager.from(context), Config.readConfig(context), bgLooper, 185 new CallbackHandler(), 186 new AccessPointControllerImpl(context), 187 new DataUsageController(context), 188 new SubscriptionDefaults(), 189 deviceProvisionedController, 190 broadcastDispatcher); 191 mReceiverHandler.post(mRegisterListeners); 192 } 193 194 @VisibleForTesting NetworkControllerImpl(Context context, ConnectivityManager connectivityManager, TelephonyManager telephonyManager, WifiManager wifiManager, NetworkScoreManager networkScoreManager, SubscriptionManager subManager, Config config, Looper bgLooper, CallbackHandler callbackHandler, AccessPointControllerImpl accessPointController, DataUsageController dataUsageController, SubscriptionDefaults defaultsHandler, DeviceProvisionedController deviceProvisionedController, BroadcastDispatcher broadcastDispatcher)195 NetworkControllerImpl(Context context, ConnectivityManager connectivityManager, 196 TelephonyManager telephonyManager, WifiManager wifiManager, 197 NetworkScoreManager networkScoreManager, 198 SubscriptionManager subManager, Config config, Looper bgLooper, 199 CallbackHandler callbackHandler, 200 AccessPointControllerImpl accessPointController, 201 DataUsageController dataUsageController, 202 SubscriptionDefaults defaultsHandler, 203 DeviceProvisionedController deviceProvisionedController, 204 BroadcastDispatcher broadcastDispatcher) { 205 mContext = context; 206 mConfig = config; 207 mReceiverHandler = new Handler(bgLooper); 208 mCallbackHandler = callbackHandler; 209 mDataSaverController = new DataSaverControllerImpl(context); 210 mBroadcastDispatcher = broadcastDispatcher; 211 212 mSubscriptionManager = subManager; 213 mSubDefaults = defaultsHandler; 214 mConnectivityManager = connectivityManager; 215 mHasMobileDataFeature = 216 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); 217 218 // telephony 219 mPhone = telephonyManager; 220 221 // wifi 222 mWifiManager = wifiManager; 223 224 mLocale = mContext.getResources().getConfiguration().locale; 225 mAccessPoints = accessPointController; 226 mDataUsageController = dataUsageController; 227 mDataUsageController.setNetworkController(this); 228 // TODO: Find a way to move this into DataUsageController. 229 mDataUsageController.setCallback(new DataUsageController.Callback() { 230 @Override 231 public void onMobileDataEnabled(boolean enabled) { 232 mCallbackHandler.setMobileDataEnabled(enabled); 233 notifyControllersMobileDataChanged(); 234 } 235 }); 236 mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature, 237 mCallbackHandler, this, mWifiManager, mConnectivityManager, networkScoreManager); 238 239 mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this); 240 241 // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it 242 updateAirplaneMode(true /* force callback */); 243 mUserTracker = new CurrentUserTracker(broadcastDispatcher) { 244 @Override 245 public void onUserSwitched(int newUserId) { 246 NetworkControllerImpl.this.onUserSwitched(newUserId); 247 } 248 }; 249 mUserTracker.startTracking(); 250 deviceProvisionedController.addCallback(new DeviceProvisionedListener() { 251 @Override 252 public void onUserSetupChanged() { 253 setUserSetupComplete(deviceProvisionedController.isUserSetup( 254 deviceProvisionedController.getCurrentUser())); 255 } 256 }); 257 258 ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){ 259 private Network mLastNetwork; 260 private NetworkCapabilities mLastNetworkCapabilities; 261 262 @Override 263 public void onCapabilitiesChanged( 264 Network network, NetworkCapabilities networkCapabilities) { 265 boolean lastValidated = (mLastNetworkCapabilities != null) && 266 mLastNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED); 267 boolean validated = 268 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED); 269 270 // This callback is invoked a lot (i.e. when RSSI changes), so avoid updating 271 // icons when connectivity state has remained the same. 272 if (network.equals(mLastNetwork) && 273 networkCapabilities.equalsTransportTypes(mLastNetworkCapabilities) && 274 validated == lastValidated) { 275 return; 276 } 277 mLastNetwork = network; 278 mLastNetworkCapabilities = networkCapabilities; 279 updateConnectivity(); 280 } 281 }; 282 // Even though this callback runs on the receiver handler thread which also processes the 283 // CONNECTIVITY_ACTION broadcasts, the broadcast and callback might come in at different 284 // times. This is safe since updateConnectivity() builds the list of transports from 285 // scratch. 286 // TODO: Move off of the deprecated CONNECTIVITY_ACTION broadcast and rely on callbacks 287 // exclusively for status bar icons. 288 mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler); 289 // Register the listener on our bg looper 290 mPhoneStateListener = new PhoneStateListener(mReceiverHandler::post) { 291 @Override 292 public void onActiveDataSubscriptionIdChanged(int subId) { 293 // For data switching from A to B, we assume B is validated for up to 2 seconds iff: 294 // 1) A and B are in the same subscription group e.g. CBRS data switch. And 295 // 2) A was validated before the switch. 296 // This is to provide smooth transition for UI without showing cross during data 297 // switch. 298 if (keepCellularValidationBitInSwitch(mActiveMobileDataSubscription, subId)) { 299 if (DEBUG) Log.d(TAG, ": mForceCellularValidated to true."); 300 mForceCellularValidated = true; 301 mReceiverHandler.removeCallbacks(mClearForceValidated); 302 mReceiverHandler.postDelayed(mClearForceValidated, 2000); 303 } 304 mActiveMobileDataSubscription = subId; 305 doUpdateMobileControllers(); 306 } 307 }; 308 } 309 310 private final Runnable mClearForceValidated = () -> { 311 if (DEBUG) Log.d(TAG, ": mClearForceValidated"); 312 mForceCellularValidated = false; 313 updateConnectivity(); 314 }; 315 isInGroupDataSwitch(int subId1, int subId2)316 boolean isInGroupDataSwitch(int subId1, int subId2) { 317 SubscriptionInfo info1 = mSubscriptionManager.getActiveSubscriptionInfo(subId1); 318 SubscriptionInfo info2 = mSubscriptionManager.getActiveSubscriptionInfo(subId2); 319 return (info1 != null && info2 != null && info1.getGroupUuid() != null 320 && info1.getGroupUuid().equals(info2.getGroupUuid())); 321 } 322 keepCellularValidationBitInSwitch(int sourceSubId, int destSubId)323 boolean keepCellularValidationBitInSwitch(int sourceSubId, int destSubId) { 324 return mValidatedTransports.get(TRANSPORT_CELLULAR) 325 && isInGroupDataSwitch(sourceSubId, destSubId); 326 } 327 getDataSaverController()328 public DataSaverController getDataSaverController() { 329 return mDataSaverController; 330 } 331 332 @VisibleForTesting registerListeners()333 void registerListeners() { 334 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 335 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 336 mobileSignalController.registerListener(); 337 } 338 if (mSubscriptionListener == null) { 339 mSubscriptionListener = new SubListener(); 340 } 341 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); 342 mPhone.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); 343 344 // broadcasts 345 IntentFilter filter = new IntentFilter(); 346 filter.addAction(WifiManager.RSSI_CHANGED_ACTION); 347 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 348 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 349 filter.addAction(Intent.ACTION_SIM_STATE_CHANGED); 350 filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); 351 filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); 352 filter.addAction(Intent.ACTION_SERVICE_STATE); 353 filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED); 354 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 355 filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); 356 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 357 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 358 mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); 359 mListening = true; 360 361 // Initial setup of connectivity. Handled as if we had received a sticky broadcast of 362 // ConnectivityManager.CONNECTIVITY_ACTION or ConnectivityManager.INET_CONDITION_ACTION. 363 mReceiverHandler.post(this::updateConnectivity); 364 365 // Initial setup of WifiSignalController. Handled as if we had received a sticky broadcast 366 // of WifiManager.WIFI_STATE_CHANGED_ACTION or WifiManager.NETWORK_STATE_CHANGED_ACTION 367 mReceiverHandler.post(mWifiSignalController::fetchInitialState); 368 369 // Initial setup of mLastServiceState. Only run if there is no service state yet. 370 // Each MobileSignalController will also get their corresponding 371 mReceiverHandler.post(() -> { 372 if (mLastServiceState == null) { 373 mLastServiceState = mPhone.getServiceState(); 374 if (mMobileSignalControllers.size() == 0) { 375 recalculateEmergency(); 376 } 377 } 378 }); 379 380 updateMobileControllers(); 381 382 // Initial setup of emergency information. Handled as if we had received a sticky broadcast 383 // of TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED. 384 mReceiverHandler.post(this::recalculateEmergency); 385 } 386 unregisterListeners()387 private void unregisterListeners() { 388 mListening = false; 389 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 390 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 391 mobileSignalController.unregisterListener(); 392 } 393 mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener); 394 mBroadcastDispatcher.unregisterReceiver(this); 395 } 396 getConnectedWifiLevel()397 public int getConnectedWifiLevel() { 398 return mWifiSignalController.getState().level; 399 } 400 401 @Override getAccessPointController()402 public AccessPointController getAccessPointController() { 403 return mAccessPoints; 404 } 405 406 @Override getMobileDataController()407 public DataUsageController getMobileDataController() { 408 return mDataUsageController; 409 } 410 addEmergencyListener(EmergencyListener listener)411 public void addEmergencyListener(EmergencyListener listener) { 412 mCallbackHandler.setListening(listener, true); 413 mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly()); 414 } 415 removeEmergencyListener(EmergencyListener listener)416 public void removeEmergencyListener(EmergencyListener listener) { 417 mCallbackHandler.setListening(listener, false); 418 } 419 hasMobileDataFeature()420 public boolean hasMobileDataFeature() { 421 return mHasMobileDataFeature; 422 } 423 hasVoiceCallingFeature()424 public boolean hasVoiceCallingFeature() { 425 return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; 426 } 427 getDataController()428 private MobileSignalController getDataController() { 429 int dataSubId = mSubDefaults.getActiveDataSubId(); 430 if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) { 431 if (DEBUG) Log.e(TAG, "No data sim selected"); 432 return mDefaultSignalController; 433 } 434 if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) { 435 return mMobileSignalControllers.get(dataSubId); 436 } 437 if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId); 438 return mDefaultSignalController; 439 } 440 441 @Override getMobileDataNetworkName()442 public String getMobileDataNetworkName() { 443 MobileSignalController controller = getDataController(); 444 return controller != null ? controller.getState().networkNameData : ""; 445 } 446 447 @Override isMobileDataNetworkInService()448 public boolean isMobileDataNetworkInService() { 449 MobileSignalController controller = getDataController(); 450 return controller != null && controller.isInService(); 451 } 452 453 @Override getNumberSubscriptions()454 public int getNumberSubscriptions() { 455 return mMobileSignalControllers.size(); 456 } 457 isDataControllerDisabled()458 boolean isDataControllerDisabled() { 459 MobileSignalController dataController = getDataController(); 460 if (dataController == null) { 461 return false; 462 } 463 464 return dataController.isDataDisabled(); 465 } 466 notifyControllersMobileDataChanged()467 private void notifyControllersMobileDataChanged() { 468 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 469 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 470 mobileSignalController.onMobileDataChanged(); 471 } 472 } 473 isEmergencyOnly()474 public boolean isEmergencyOnly() { 475 if (mMobileSignalControllers.size() == 0) { 476 // When there are no active subscriptions, determine emengency state from last 477 // broadcast. 478 mEmergencySource = EMERGENCY_NO_CONTROLLERS; 479 return mLastServiceState != null && mLastServiceState.isEmergencyOnly(); 480 } 481 int voiceSubId = mSubDefaults.getDefaultVoiceSubId(); 482 if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) { 483 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 484 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 485 if (!mobileSignalController.getState().isEmergency) { 486 mEmergencySource = EMERGENCY_FIRST_CONTROLLER 487 + mobileSignalController.mSubscriptionInfo.getSubscriptionId(); 488 if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag); 489 return false; 490 } 491 } 492 } 493 if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) { 494 mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId; 495 if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId); 496 return mMobileSignalControllers.get(voiceSubId).getState().isEmergency; 497 } 498 // If we have the wrong subId but there is only one sim anyway, assume it should be the 499 // default. 500 if (mMobileSignalControllers.size() == 1) { 501 mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER 502 + mMobileSignalControllers.keyAt(0); 503 if (DEBUG) Log.d(TAG, "Getting assumed emergency from " 504 + mMobileSignalControllers.keyAt(0)); 505 return mMobileSignalControllers.valueAt(0).getState().isEmergency; 506 } 507 if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId); 508 mEmergencySource = EMERGENCY_NO_SUB + voiceSubId; 509 // Something is wrong, better assume we can't make calls... 510 return true; 511 } 512 513 /** 514 * Emergency status may have changed (triggered by MobileSignalController), 515 * so we should recheck and send out the state to listeners. 516 */ recalculateEmergency()517 void recalculateEmergency() { 518 mIsEmergency = isEmergencyOnly(); 519 mCallbackHandler.setEmergencyCallsOnly(mIsEmergency); 520 } 521 addCallback(SignalCallback cb)522 public void addCallback(SignalCallback cb) { 523 cb.setSubs(mCurrentSubscriptions); 524 cb.setIsAirplaneMode(new IconState(mAirplaneMode, 525 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext)); 526 cb.setNoSims(mHasNoSubs, mSimDetected); 527 mWifiSignalController.notifyListeners(cb); 528 mEthernetSignalController.notifyListeners(cb); 529 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 530 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 531 mobileSignalController.notifyListeners(cb); 532 } 533 mCallbackHandler.setListening(cb, true); 534 } 535 536 @Override removeCallback(SignalCallback cb)537 public void removeCallback(SignalCallback cb) { 538 mCallbackHandler.setListening(cb, false); 539 } 540 541 @Override setWifiEnabled(final boolean enabled)542 public void setWifiEnabled(final boolean enabled) { 543 new AsyncTask<Void, Void, Void>() { 544 @Override 545 protected Void doInBackground(Void... args) { 546 mWifiManager.setWifiEnabled(enabled); 547 return null; 548 } 549 }.execute(); 550 } 551 onUserSwitched(int newUserId)552 private void onUserSwitched(int newUserId) { 553 mCurrentUserId = newUserId; 554 mAccessPoints.onUserSwitched(newUserId); 555 updateConnectivity(); 556 } 557 558 @Override onReceive(Context context, Intent intent)559 public void onReceive(Context context, Intent intent) { 560 if (CHATTY) { 561 Log.d(TAG, "onReceive: intent=" + intent); 562 } 563 final String action = intent.getAction(); 564 switch (action) { 565 case ConnectivityManager.CONNECTIVITY_ACTION: 566 case ConnectivityManager.INET_CONDITION_ACTION: 567 updateConnectivity(); 568 break; 569 case Intent.ACTION_AIRPLANE_MODE_CHANGED: 570 refreshLocale(); 571 updateAirplaneMode(false); 572 break; 573 case TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED: 574 // We are using different subs now, we might be able to make calls. 575 recalculateEmergency(); 576 break; 577 case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED: 578 // Notify every MobileSignalController so they can know whether they are the 579 // data sim or not. 580 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 581 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 582 controller.handleBroadcast(intent); 583 } 584 mConfig = Config.readConfig(mContext); 585 mReceiverHandler.post(this::handleConfigurationChanged); 586 break; 587 case Intent.ACTION_SIM_STATE_CHANGED: 588 // Avoid rebroadcast because SysUI is direct boot aware. 589 if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) { 590 break; 591 } 592 // Might have different subscriptions now. 593 updateMobileControllers(); 594 break; 595 case Intent.ACTION_SERVICE_STATE: 596 mLastServiceState = ServiceState.newFromBundle(intent.getExtras()); 597 if (mMobileSignalControllers.size() == 0) { 598 // If none of the subscriptions are active, we might need to recalculate 599 // emergency state. 600 recalculateEmergency(); 601 } 602 break; 603 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED: 604 mConfig = Config.readConfig(mContext); 605 mReceiverHandler.post(this::handleConfigurationChanged); 606 break; 607 default: 608 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 609 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 610 if (SubscriptionManager.isValidSubscriptionId(subId)) { 611 if (mMobileSignalControllers.indexOfKey(subId) >= 0) { 612 mMobileSignalControllers.get(subId).handleBroadcast(intent); 613 } else { 614 // Can't find this subscription... We must be out of date. 615 updateMobileControllers(); 616 } 617 } else { 618 // No sub id, must be for the wifi. 619 mWifiSignalController.handleBroadcast(intent); 620 } 621 break; 622 } 623 } 624 625 @VisibleForTesting handleConfigurationChanged()626 void handleConfigurationChanged() { 627 updateMobileControllers(); 628 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 629 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 630 controller.setConfiguration(mConfig); 631 } 632 refreshLocale(); 633 } 634 updateMobileControllers()635 private void updateMobileControllers() { 636 if (!mListening) { 637 return; 638 } 639 doUpdateMobileControllers(); 640 } 641 filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions)642 private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) { 643 if (subscriptions.size() == 2) { 644 SubscriptionInfo info1 = subscriptions.get(0); 645 SubscriptionInfo info2 = subscriptions.get(1); 646 if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) { 647 // If both subscriptions are primary, show both. 648 if (!info1.isOpportunistic() && !info2.isOpportunistic()) return; 649 650 // If carrier required, always show signal bar of primary subscription. 651 // Otherwise, show whichever subscription is currently active for Internet. 652 boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig() 653 .getBoolean(CarrierConfigManager 654 .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN); 655 if (alwaysShowPrimary) { 656 subscriptions.remove(info1.isOpportunistic() ? info1 : info2); 657 } else { 658 subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription 659 ? info2 : info1); 660 } 661 } 662 } 663 } 664 665 @VisibleForTesting doUpdateMobileControllers()666 void doUpdateMobileControllers() { 667 List<SubscriptionInfo> subscriptions = mSubscriptionManager 668 .getCompleteActiveSubscriptionInfoList(); 669 if (subscriptions == null) { 670 subscriptions = Collections.emptyList(); 671 } 672 673 filterMobileSubscriptionInSameGroup(subscriptions); 674 675 // If there have been no relevant changes to any of the subscriptions, we can leave as is. 676 if (hasCorrectMobileControllers(subscriptions)) { 677 // Even if the controllers are correct, make sure we have the right no sims state. 678 // Such as on boot, don't need any controllers, because there are no sims, 679 // but we still need to update the no sim state. 680 updateNoSims(); 681 return; 682 } 683 synchronized (mLock) { 684 setCurrentSubscriptionsLocked(subscriptions); 685 } 686 updateNoSims(); 687 recalculateEmergency(); 688 } 689 690 @VisibleForTesting updateNoSims()691 protected void updateNoSims() { 692 boolean hasNoSubs = mHasMobileDataFeature && mMobileSignalControllers.size() == 0; 693 boolean simDetected = hasAnySim(); 694 if (hasNoSubs != mHasNoSubs || simDetected != mSimDetected) { 695 mHasNoSubs = hasNoSubs; 696 mSimDetected = simDetected; 697 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected); 698 } 699 } 700 hasAnySim()701 private boolean hasAnySim() { 702 int simCount = mPhone.getActiveModemCount(); 703 for (int i = 0; i < simCount; i++) { 704 int state = mPhone.getSimState(i); 705 if (state != TelephonyManager.SIM_STATE_ABSENT 706 && state != TelephonyManager.SIM_STATE_UNKNOWN) { 707 return true; 708 } 709 } 710 return false; 711 } 712 713 @GuardedBy("mLock") 714 @VisibleForTesting setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions)715 public void setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions) { 716 Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() { 717 @Override 718 public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) { 719 return lhs.getSimSlotIndex() == rhs.getSimSlotIndex() 720 ? lhs.getSubscriptionId() - rhs.getSubscriptionId() 721 : lhs.getSimSlotIndex() - rhs.getSimSlotIndex(); 722 } 723 }); 724 mCurrentSubscriptions = subscriptions; 725 726 SparseArray<MobileSignalController> cachedControllers = 727 new SparseArray<MobileSignalController>(); 728 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 729 cachedControllers.put(mMobileSignalControllers.keyAt(i), 730 mMobileSignalControllers.valueAt(i)); 731 } 732 mMobileSignalControllers.clear(); 733 final int num = subscriptions.size(); 734 for (int i = 0; i < num; i++) { 735 int subId = subscriptions.get(i).getSubscriptionId(); 736 // If we have a copy of this controller already reuse it, otherwise make a new one. 737 if (cachedControllers.indexOfKey(subId) >= 0) { 738 mMobileSignalControllers.put(subId, cachedControllers.get(subId)); 739 cachedControllers.remove(subId); 740 } else { 741 MobileSignalController controller = new MobileSignalController(mContext, mConfig, 742 mHasMobileDataFeature, mPhone.createForSubscriptionId(subId), 743 mCallbackHandler, this, subscriptions.get(i), 744 mSubDefaults, mReceiverHandler.getLooper()); 745 controller.setUserSetupComplete(mUserSetup); 746 mMobileSignalControllers.put(subId, controller); 747 if (subscriptions.get(i).getSimSlotIndex() == 0) { 748 mDefaultSignalController = controller; 749 } 750 if (mListening) { 751 controller.registerListener(); 752 } 753 } 754 } 755 if (mListening) { 756 for (int i = 0; i < cachedControllers.size(); i++) { 757 int key = cachedControllers.keyAt(i); 758 if (cachedControllers.get(key) == mDefaultSignalController) { 759 mDefaultSignalController = null; 760 } 761 cachedControllers.get(key).unregisterListener(); 762 } 763 } 764 mCallbackHandler.setSubs(subscriptions); 765 notifyAllListeners(); 766 767 // There may be new MobileSignalControllers around, make sure they get the current 768 // inet condition and airplane mode. 769 pushConnectivityToSignals(); 770 updateAirplaneMode(true /* force */); 771 } 772 setUserSetupComplete(final boolean userSetup)773 private void setUserSetupComplete(final boolean userSetup) { 774 mReceiverHandler.post(() -> handleSetUserSetupComplete(userSetup)); 775 } 776 handleSetUserSetupComplete(boolean userSetup)777 private void handleSetUserSetupComplete(boolean userSetup) { 778 mUserSetup = userSetup; 779 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 780 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 781 controller.setUserSetupComplete(mUserSetup); 782 } 783 } 784 785 @VisibleForTesting hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions)786 boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) { 787 if (allSubscriptions.size() != mMobileSignalControllers.size()) { 788 return false; 789 } 790 for (SubscriptionInfo info : allSubscriptions) { 791 if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) { 792 return false; 793 } 794 } 795 return true; 796 } 797 updateAirplaneMode(boolean force)798 private void updateAirplaneMode(boolean force) { 799 boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), 800 Settings.Global.AIRPLANE_MODE_ON, 0) == 1); 801 if (airplaneMode != mAirplaneMode || force) { 802 mAirplaneMode = airplaneMode; 803 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 804 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 805 mobileSignalController.setAirplaneMode(mAirplaneMode); 806 } 807 notifyListeners(); 808 } 809 } 810 refreshLocale()811 private void refreshLocale() { 812 Locale current = mContext.getResources().getConfiguration().locale; 813 if (!current.equals(mLocale)) { 814 mLocale = current; 815 mWifiSignalController.refreshLocale(); 816 notifyAllListeners(); 817 } 818 } 819 820 /** 821 * Forces update of all callbacks on both SignalClusters and 822 * NetworkSignalChangedCallbacks. 823 */ notifyAllListeners()824 private void notifyAllListeners() { 825 notifyListeners(); 826 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 827 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 828 mobileSignalController.notifyListeners(); 829 } 830 mWifiSignalController.notifyListeners(); 831 mEthernetSignalController.notifyListeners(); 832 } 833 834 /** 835 * Notifies listeners of changes in state of to the NetworkController, but 836 * does not notify for any info on SignalControllers, for that call 837 * notifyAllListeners. 838 */ notifyListeners()839 private void notifyListeners() { 840 mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode, 841 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext)); 842 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected); 843 } 844 845 /** 846 * Update the Inet conditions and what network we are connected to. 847 */ updateConnectivity()848 private void updateConnectivity() { 849 mConnectedTransports.clear(); 850 mValidatedTransports.clear(); 851 for (NetworkCapabilities nc : 852 mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) { 853 for (int transportType : nc.getTransportTypes()) { 854 mConnectedTransports.set(transportType); 855 if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) { 856 mValidatedTransports.set(transportType); 857 } 858 } 859 } 860 861 if (mForceCellularValidated) mValidatedTransports.set(TRANSPORT_CELLULAR); 862 863 if (CHATTY) { 864 Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports); 865 Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports); 866 } 867 868 mInetCondition = !mValidatedTransports.isEmpty(); 869 870 pushConnectivityToSignals(); 871 } 872 873 /** 874 * Pushes the current connectivity state to all SignalControllers. 875 */ pushConnectivityToSignals()876 private void pushConnectivityToSignals() { 877 // We want to update all the icons, all at once, for any condition change 878 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 879 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 880 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports); 881 } 882 mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports); 883 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports); 884 } 885 dump(FileDescriptor fd, PrintWriter pw, String[] args)886 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 887 pw.println("NetworkController state:"); 888 889 pw.println(" - telephony ------"); 890 pw.print(" hasVoiceCallingFeature()="); 891 pw.println(hasVoiceCallingFeature()); 892 pw.println(" mListening=" + mListening); 893 894 pw.println(" - connectivity ------"); 895 pw.print(" mConnectedTransports="); 896 pw.println(mConnectedTransports); 897 pw.print(" mValidatedTransports="); 898 pw.println(mValidatedTransports); 899 pw.print(" mInetCondition="); 900 pw.println(mInetCondition); 901 pw.print(" mAirplaneMode="); 902 pw.println(mAirplaneMode); 903 pw.print(" mLocale="); 904 pw.println(mLocale); 905 pw.print(" mLastServiceState="); 906 pw.println(mLastServiceState); 907 pw.print(" mIsEmergency="); 908 pw.println(mIsEmergency); 909 pw.print(" mEmergencySource="); 910 pw.println(emergencyToString(mEmergencySource)); 911 912 pw.println(" - config ------"); 913 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 914 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 915 mobileSignalController.dump(pw); 916 } 917 mWifiSignalController.dump(pw); 918 919 mEthernetSignalController.dump(pw); 920 921 mAccessPoints.dump(pw); 922 } 923 emergencyToString(int emergencySource)924 private static final String emergencyToString(int emergencySource) { 925 if (emergencySource > EMERGENCY_NO_SUB) { 926 return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) 927 + ")"; 928 } else if (emergencySource > EMERGENCY_NO_SUB) { 929 return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")"; 930 } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) { 931 return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")"; 932 } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) { 933 return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")"; 934 } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) { 935 return "NO_CONTROLLERS"; 936 } 937 return "UNKNOWN_SOURCE"; 938 } 939 940 private boolean mDemoMode; 941 private boolean mDemoInetCondition; 942 private WifiSignalController.WifiState mDemoWifiState; 943 944 @Override dispatchDemoCommand(String command, Bundle args)945 public void dispatchDemoCommand(String command, Bundle args) { 946 if (!mDemoMode && command.equals(COMMAND_ENTER)) { 947 if (DEBUG) Log.d(TAG, "Entering demo mode"); 948 unregisterListeners(); 949 mDemoMode = true; 950 mDemoInetCondition = mInetCondition; 951 mDemoWifiState = mWifiSignalController.getState(); 952 mDemoWifiState.ssid = "DemoMode"; 953 } else if (mDemoMode && command.equals(COMMAND_EXIT)) { 954 if (DEBUG) Log.d(TAG, "Exiting demo mode"); 955 mDemoMode = false; 956 // Update what MobileSignalControllers, because they may change 957 // to set the number of sim slots. 958 updateMobileControllers(); 959 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 960 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 961 controller.resetLastState(); 962 } 963 mWifiSignalController.resetLastState(); 964 mReceiverHandler.post(mRegisterListeners); 965 notifyAllListeners(); 966 } else if (mDemoMode && command.equals(COMMAND_NETWORK)) { 967 String airplane = args.getString("airplane"); 968 if (airplane != null) { 969 boolean show = airplane.equals("show"); 970 mCallbackHandler.setIsAirplaneMode(new IconState(show, 971 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, 972 mContext)); 973 } 974 String fully = args.getString("fully"); 975 if (fully != null) { 976 mDemoInetCondition = Boolean.parseBoolean(fully); 977 BitSet connected = new BitSet(); 978 979 if (mDemoInetCondition) { 980 connected.set(mWifiSignalController.mTransportType); 981 } 982 mWifiSignalController.updateConnectivity(connected, connected); 983 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 984 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 985 if (mDemoInetCondition) { 986 connected.set(controller.mTransportType); 987 } 988 controller.updateConnectivity(connected, connected); 989 } 990 } 991 String wifi = args.getString("wifi"); 992 if (wifi != null) { 993 boolean show = wifi.equals("show"); 994 String level = args.getString("level"); 995 if (level != null) { 996 mDemoWifiState.level = level.equals("null") ? -1 997 : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1); 998 mDemoWifiState.connected = mDemoWifiState.level >= 0; 999 } 1000 String activity = args.getString("activity"); 1001 if (activity != null) { 1002 switch (activity) { 1003 case "inout": 1004 mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT); 1005 break; 1006 case "in": 1007 mWifiSignalController.setActivity(DATA_ACTIVITY_IN); 1008 break; 1009 case "out": 1010 mWifiSignalController.setActivity(DATA_ACTIVITY_OUT); 1011 break; 1012 default: 1013 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE); 1014 break; 1015 } 1016 } else { 1017 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE); 1018 } 1019 String ssid = args.getString("ssid"); 1020 if (ssid != null) { 1021 mDemoWifiState.ssid = ssid; 1022 } 1023 mDemoWifiState.enabled = show; 1024 mWifiSignalController.notifyListeners(); 1025 } 1026 String sims = args.getString("sims"); 1027 if (sims != null) { 1028 int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8); 1029 List<SubscriptionInfo> subs = new ArrayList<>(); 1030 if (num != mMobileSignalControllers.size()) { 1031 mMobileSignalControllers.clear(); 1032 int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); 1033 for (int i = start /* get out of normal index range */; i < start + num; i++) { 1034 subs.add(addSignalController(i, i)); 1035 } 1036 mCallbackHandler.setSubs(subs); 1037 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 1038 int key = mMobileSignalControllers.keyAt(i); 1039 MobileSignalController controller = mMobileSignalControllers.get(key); 1040 controller.notifyListeners(); 1041 } 1042 } 1043 } 1044 String nosim = args.getString("nosim"); 1045 if (nosim != null) { 1046 mHasNoSubs = nosim.equals("show"); 1047 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected); 1048 } 1049 String mobile = args.getString("mobile"); 1050 if (mobile != null) { 1051 boolean show = mobile.equals("show"); 1052 String datatype = args.getString("datatype"); 1053 String slotString = args.getString("slot"); 1054 int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString); 1055 slot = MathUtils.constrain(slot, 0, 8); 1056 // Ensure we have enough sim slots 1057 List<SubscriptionInfo> subs = new ArrayList<>(); 1058 while (mMobileSignalControllers.size() <= slot) { 1059 int nextSlot = mMobileSignalControllers.size(); 1060 subs.add(addSignalController(nextSlot, nextSlot)); 1061 } 1062 if (!subs.isEmpty()) { 1063 mCallbackHandler.setSubs(subs); 1064 } 1065 // Hack to index linearly for easy use. 1066 MobileSignalController controller = mMobileSignalControllers.valueAt(slot); 1067 controller.getState().dataSim = datatype != null; 1068 controller.getState().isDefault = datatype != null; 1069 controller.getState().dataConnected = datatype != null; 1070 if (datatype != null) { 1071 controller.getState().iconGroup = 1072 datatype.equals("1x") ? TelephonyIcons.ONE_X : 1073 datatype.equals("3g") ? TelephonyIcons.THREE_G : 1074 datatype.equals("4g") ? TelephonyIcons.FOUR_G : 1075 datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS : 1076 datatype.equals("5g") ? TelephonyIcons.NR_5G : 1077 datatype.equals("5ge") ? TelephonyIcons.LTE_CA_5G_E : 1078 datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS : 1079 datatype.equals("e") ? TelephonyIcons.E : 1080 datatype.equals("g") ? TelephonyIcons.G : 1081 datatype.equals("h") ? TelephonyIcons.H : 1082 datatype.equals("h+") ? TelephonyIcons.H_PLUS : 1083 datatype.equals("lte") ? TelephonyIcons.LTE : 1084 datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS : 1085 datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED : 1086 datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA : 1087 TelephonyIcons.UNKNOWN; 1088 } 1089 if (args.containsKey("roam")) { 1090 controller.getState().roaming = "show".equals(args.getString("roam")); 1091 } 1092 String level = args.getString("level"); 1093 if (level != null) { 1094 controller.getState().level = level.equals("null") ? -1 1095 : Math.min(Integer.parseInt(level), 1096 CellSignalStrength.getNumSignalStrengthLevels()); 1097 controller.getState().connected = controller.getState().level >= 0; 1098 } 1099 if (args.containsKey("inflate")) { 1100 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 1101 mMobileSignalControllers.valueAt(i).mInflateSignalStrengths = 1102 "true".equals(args.getString("inflate")); 1103 } 1104 } 1105 String activity = args.getString("activity"); 1106 if (activity != null) { 1107 controller.getState().dataConnected = true; 1108 switch (activity) { 1109 case "inout": 1110 controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT); 1111 break; 1112 case "in": 1113 controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN); 1114 break; 1115 case "out": 1116 controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT); 1117 break; 1118 default: 1119 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE); 1120 break; 1121 } 1122 } else { 1123 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE); 1124 } 1125 controller.getState().enabled = show; 1126 controller.notifyListeners(); 1127 } 1128 String carrierNetworkChange = args.getString("carriernetworkchange"); 1129 if (carrierNetworkChange != null) { 1130 boolean show = carrierNetworkChange.equals("show"); 1131 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 1132 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 1133 controller.setCarrierNetworkChangeMode(show); 1134 } 1135 } 1136 } 1137 } 1138 addSignalController(int id, int simSlotIndex)1139 private SubscriptionInfo addSignalController(int id, int simSlotIndex) { 1140 SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0, 1141 null, null, null, "", false, null, null); 1142 MobileSignalController controller = new MobileSignalController(mContext, 1143 mConfig, mHasMobileDataFeature, 1144 mPhone.createForSubscriptionId(info.getSubscriptionId()), mCallbackHandler, this, info, 1145 mSubDefaults, mReceiverHandler.getLooper()); 1146 mMobileSignalControllers.put(id, controller); 1147 controller.getState().userSetup = true; 1148 return info; 1149 } 1150 hasEmergencyCryptKeeperText()1151 public boolean hasEmergencyCryptKeeperText() { 1152 return EncryptionHelper.IS_DATA_ENCRYPTED; 1153 } 1154 isRadioOn()1155 public boolean isRadioOn() { 1156 return !mAirplaneMode; 1157 } 1158 1159 private class SubListener extends OnSubscriptionsChangedListener { 1160 @Override onSubscriptionsChanged()1161 public void onSubscriptionsChanged() { 1162 updateMobileControllers(); 1163 } 1164 } 1165 1166 /** 1167 * Used to register listeners from the BG Looper, this way the PhoneStateListeners that 1168 * get created will also run on the BG Looper. 1169 */ 1170 private final Runnable mRegisterListeners = new Runnable() { 1171 @Override 1172 public void run() { 1173 registerListeners(); 1174 } 1175 }; 1176 1177 public static class SubscriptionDefaults { getDefaultVoiceSubId()1178 public int getDefaultVoiceSubId() { 1179 return SubscriptionManager.getDefaultVoiceSubscriptionId(); 1180 } 1181 getDefaultDataSubId()1182 public int getDefaultDataSubId() { 1183 return SubscriptionManager.getDefaultDataSubscriptionId(); 1184 } 1185 getActiveDataSubId()1186 public int getActiveDataSubId() { 1187 return SubscriptionManager.getActiveDataSubscriptionId(); 1188 } 1189 } 1190 1191 @VisibleForTesting 1192 static class Config { 1193 boolean showAtLeast3G = false; 1194 boolean show4gFor3g = false; 1195 boolean alwaysShowCdmaRssi = false; 1196 boolean show4gForLte = false; 1197 boolean hideLtePlus = false; 1198 boolean hspaDataDistinguishable; 1199 boolean inflateSignalStrengths = false; 1200 boolean alwaysShowDataRatIcon = false; 1201 readConfig(Context context)1202 static Config readConfig(Context context) { 1203 Config config = new Config(); 1204 Resources res = context.getResources(); 1205 1206 config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G); 1207 config.alwaysShowCdmaRssi = 1208 res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); 1209 config.hspaDataDistinguishable = 1210 res.getBoolean(R.bool.config_hspa_data_distinguishable); 1211 config.inflateSignalStrengths = res.getBoolean( 1212 com.android.internal.R.bool.config_inflateSignalStrength); 1213 1214 CarrierConfigManager configMgr = (CarrierConfigManager) 1215 context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1216 // Handle specific carrier config values for the default data SIM 1217 int defaultDataSubId = SubscriptionManager.from(context) 1218 .getDefaultDataSubscriptionId(); 1219 PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId); 1220 if (b != null) { 1221 config.alwaysShowDataRatIcon = b.getBoolean( 1222 CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL); 1223 config.show4gForLte = b.getBoolean( 1224 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL); 1225 config.show4gFor3g = b.getBoolean( 1226 CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL); 1227 config.hideLtePlus = b.getBoolean( 1228 CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL); 1229 } 1230 1231 return config; 1232 } 1233 } 1234 } 1235