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 getNumberSubscriptions()448 public int getNumberSubscriptions() { 449 return mMobileSignalControllers.size(); 450 } 451 isDataControllerDisabled()452 boolean isDataControllerDisabled() { 453 MobileSignalController dataController = getDataController(); 454 if (dataController == null) { 455 return false; 456 } 457 458 return dataController.isDataDisabled(); 459 } 460 notifyControllersMobileDataChanged()461 private void notifyControllersMobileDataChanged() { 462 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 463 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 464 mobileSignalController.onMobileDataChanged(); 465 } 466 } 467 isEmergencyOnly()468 public boolean isEmergencyOnly() { 469 if (mMobileSignalControllers.size() == 0) { 470 // When there are no active subscriptions, determine emengency state from last 471 // broadcast. 472 mEmergencySource = EMERGENCY_NO_CONTROLLERS; 473 return mLastServiceState != null && mLastServiceState.isEmergencyOnly(); 474 } 475 int voiceSubId = mSubDefaults.getDefaultVoiceSubId(); 476 if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) { 477 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 478 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 479 if (!mobileSignalController.getState().isEmergency) { 480 mEmergencySource = EMERGENCY_FIRST_CONTROLLER 481 + mobileSignalController.mSubscriptionInfo.getSubscriptionId(); 482 if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag); 483 return false; 484 } 485 } 486 } 487 if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) { 488 mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId; 489 if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId); 490 return mMobileSignalControllers.get(voiceSubId).getState().isEmergency; 491 } 492 // If we have the wrong subId but there is only one sim anyway, assume it should be the 493 // default. 494 if (mMobileSignalControllers.size() == 1) { 495 mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER 496 + mMobileSignalControllers.keyAt(0); 497 if (DEBUG) Log.d(TAG, "Getting assumed emergency from " 498 + mMobileSignalControllers.keyAt(0)); 499 return mMobileSignalControllers.valueAt(0).getState().isEmergency; 500 } 501 if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId); 502 mEmergencySource = EMERGENCY_NO_SUB + voiceSubId; 503 // Something is wrong, better assume we can't make calls... 504 return true; 505 } 506 507 /** 508 * Emergency status may have changed (triggered by MobileSignalController), 509 * so we should recheck and send out the state to listeners. 510 */ recalculateEmergency()511 void recalculateEmergency() { 512 mIsEmergency = isEmergencyOnly(); 513 mCallbackHandler.setEmergencyCallsOnly(mIsEmergency); 514 } 515 addCallback(SignalCallback cb)516 public void addCallback(SignalCallback cb) { 517 cb.setSubs(mCurrentSubscriptions); 518 cb.setIsAirplaneMode(new IconState(mAirplaneMode, 519 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext)); 520 cb.setNoSims(mHasNoSubs, mSimDetected); 521 mWifiSignalController.notifyListeners(cb); 522 mEthernetSignalController.notifyListeners(cb); 523 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 524 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 525 mobileSignalController.notifyListeners(cb); 526 } 527 mCallbackHandler.setListening(cb, true); 528 } 529 530 @Override removeCallback(SignalCallback cb)531 public void removeCallback(SignalCallback cb) { 532 mCallbackHandler.setListening(cb, false); 533 } 534 535 @Override setWifiEnabled(final boolean enabled)536 public void setWifiEnabled(final boolean enabled) { 537 new AsyncTask<Void, Void, Void>() { 538 @Override 539 protected Void doInBackground(Void... args) { 540 mWifiManager.setWifiEnabled(enabled); 541 return null; 542 } 543 }.execute(); 544 } 545 onUserSwitched(int newUserId)546 private void onUserSwitched(int newUserId) { 547 mCurrentUserId = newUserId; 548 mAccessPoints.onUserSwitched(newUserId); 549 updateConnectivity(); 550 } 551 552 @Override onReceive(Context context, Intent intent)553 public void onReceive(Context context, Intent intent) { 554 if (CHATTY) { 555 Log.d(TAG, "onReceive: intent=" + intent); 556 } 557 final String action = intent.getAction(); 558 switch (action) { 559 case ConnectivityManager.CONNECTIVITY_ACTION: 560 case ConnectivityManager.INET_CONDITION_ACTION: 561 updateConnectivity(); 562 break; 563 case Intent.ACTION_AIRPLANE_MODE_CHANGED: 564 refreshLocale(); 565 updateAirplaneMode(false); 566 break; 567 case TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED: 568 // We are using different subs now, we might be able to make calls. 569 recalculateEmergency(); 570 break; 571 case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED: 572 // Notify every MobileSignalController so they can know whether they are the 573 // data sim or not. 574 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 575 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 576 controller.handleBroadcast(intent); 577 } 578 mConfig = Config.readConfig(mContext); 579 mReceiverHandler.post(this::handleConfigurationChanged); 580 break; 581 case Intent.ACTION_SIM_STATE_CHANGED: 582 // Avoid rebroadcast because SysUI is direct boot aware. 583 if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) { 584 break; 585 } 586 // Might have different subscriptions now. 587 updateMobileControllers(); 588 break; 589 case Intent.ACTION_SERVICE_STATE: 590 mLastServiceState = ServiceState.newFromBundle(intent.getExtras()); 591 if (mMobileSignalControllers.size() == 0) { 592 // If none of the subscriptions are active, we might need to recalculate 593 // emergency state. 594 recalculateEmergency(); 595 } 596 break; 597 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED: 598 mConfig = Config.readConfig(mContext); 599 mReceiverHandler.post(this::handleConfigurationChanged); 600 break; 601 default: 602 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 603 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 604 if (SubscriptionManager.isValidSubscriptionId(subId)) { 605 if (mMobileSignalControllers.indexOfKey(subId) >= 0) { 606 mMobileSignalControllers.get(subId).handleBroadcast(intent); 607 } else { 608 // Can't find this subscription... We must be out of date. 609 updateMobileControllers(); 610 } 611 } else { 612 // No sub id, must be for the wifi. 613 mWifiSignalController.handleBroadcast(intent); 614 } 615 break; 616 } 617 } 618 619 @VisibleForTesting handleConfigurationChanged()620 void handleConfigurationChanged() { 621 updateMobileControllers(); 622 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 623 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 624 controller.setConfiguration(mConfig); 625 } 626 refreshLocale(); 627 } 628 updateMobileControllers()629 private void updateMobileControllers() { 630 if (!mListening) { 631 return; 632 } 633 doUpdateMobileControllers(); 634 } 635 filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions)636 private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) { 637 if (subscriptions.size() == 2) { 638 SubscriptionInfo info1 = subscriptions.get(0); 639 SubscriptionInfo info2 = subscriptions.get(1); 640 if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) { 641 // If both subscriptions are primary, show both. 642 if (!info1.isOpportunistic() && !info2.isOpportunistic()) return; 643 644 // If carrier required, always show signal bar of primary subscription. 645 // Otherwise, show whichever subscription is currently active for Internet. 646 boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig() 647 .getBoolean(CarrierConfigManager 648 .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN); 649 if (alwaysShowPrimary) { 650 subscriptions.remove(info1.isOpportunistic() ? info1 : info2); 651 } else { 652 subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription 653 ? info2 : info1); 654 } 655 } 656 } 657 } 658 659 @VisibleForTesting doUpdateMobileControllers()660 void doUpdateMobileControllers() { 661 List<SubscriptionInfo> subscriptions = mSubscriptionManager 662 .getCompleteActiveSubscriptionInfoList(); 663 if (subscriptions == null) { 664 subscriptions = Collections.emptyList(); 665 } 666 667 filterMobileSubscriptionInSameGroup(subscriptions); 668 669 // If there have been no relevant changes to any of the subscriptions, we can leave as is. 670 if (hasCorrectMobileControllers(subscriptions)) { 671 // Even if the controllers are correct, make sure we have the right no sims state. 672 // Such as on boot, don't need any controllers, because there are no sims, 673 // but we still need to update the no sim state. 674 updateNoSims(); 675 return; 676 } 677 synchronized (mLock) { 678 setCurrentSubscriptionsLocked(subscriptions); 679 } 680 updateNoSims(); 681 recalculateEmergency(); 682 } 683 684 @VisibleForTesting updateNoSims()685 protected void updateNoSims() { 686 boolean hasNoSubs = mHasMobileDataFeature && mMobileSignalControllers.size() == 0; 687 boolean simDetected = hasAnySim(); 688 if (hasNoSubs != mHasNoSubs || simDetected != mSimDetected) { 689 mHasNoSubs = hasNoSubs; 690 mSimDetected = simDetected; 691 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected); 692 } 693 } 694 hasAnySim()695 private boolean hasAnySim() { 696 int simCount = mPhone.getActiveModemCount(); 697 for (int i = 0; i < simCount; i++) { 698 int state = mPhone.getSimState(i); 699 if (state != TelephonyManager.SIM_STATE_ABSENT 700 && state != TelephonyManager.SIM_STATE_UNKNOWN) { 701 return true; 702 } 703 } 704 return false; 705 } 706 707 @GuardedBy("mLock") 708 @VisibleForTesting setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions)709 public void setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions) { 710 Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() { 711 @Override 712 public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) { 713 return lhs.getSimSlotIndex() == rhs.getSimSlotIndex() 714 ? lhs.getSubscriptionId() - rhs.getSubscriptionId() 715 : lhs.getSimSlotIndex() - rhs.getSimSlotIndex(); 716 } 717 }); 718 mCurrentSubscriptions = subscriptions; 719 720 SparseArray<MobileSignalController> cachedControllers = 721 new SparseArray<MobileSignalController>(); 722 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 723 cachedControllers.put(mMobileSignalControllers.keyAt(i), 724 mMobileSignalControllers.valueAt(i)); 725 } 726 mMobileSignalControllers.clear(); 727 final int num = subscriptions.size(); 728 for (int i = 0; i < num; i++) { 729 int subId = subscriptions.get(i).getSubscriptionId(); 730 // If we have a copy of this controller already reuse it, otherwise make a new one. 731 if (cachedControllers.indexOfKey(subId) >= 0) { 732 mMobileSignalControllers.put(subId, cachedControllers.get(subId)); 733 cachedControllers.remove(subId); 734 } else { 735 MobileSignalController controller = new MobileSignalController(mContext, mConfig, 736 mHasMobileDataFeature, mPhone.createForSubscriptionId(subId), 737 mCallbackHandler, this, subscriptions.get(i), 738 mSubDefaults, mReceiverHandler.getLooper()); 739 controller.setUserSetupComplete(mUserSetup); 740 mMobileSignalControllers.put(subId, controller); 741 if (subscriptions.get(i).getSimSlotIndex() == 0) { 742 mDefaultSignalController = controller; 743 } 744 if (mListening) { 745 controller.registerListener(); 746 } 747 } 748 } 749 if (mListening) { 750 for (int i = 0; i < cachedControllers.size(); i++) { 751 int key = cachedControllers.keyAt(i); 752 if (cachedControllers.get(key) == mDefaultSignalController) { 753 mDefaultSignalController = null; 754 } 755 cachedControllers.get(key).unregisterListener(); 756 } 757 } 758 mCallbackHandler.setSubs(subscriptions); 759 notifyAllListeners(); 760 761 // There may be new MobileSignalControllers around, make sure they get the current 762 // inet condition and airplane mode. 763 pushConnectivityToSignals(); 764 updateAirplaneMode(true /* force */); 765 } 766 setUserSetupComplete(final boolean userSetup)767 private void setUserSetupComplete(final boolean userSetup) { 768 mReceiverHandler.post(() -> handleSetUserSetupComplete(userSetup)); 769 } 770 handleSetUserSetupComplete(boolean userSetup)771 private void handleSetUserSetupComplete(boolean userSetup) { 772 mUserSetup = userSetup; 773 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 774 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 775 controller.setUserSetupComplete(mUserSetup); 776 } 777 } 778 779 @VisibleForTesting hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions)780 boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) { 781 if (allSubscriptions.size() != mMobileSignalControllers.size()) { 782 return false; 783 } 784 for (SubscriptionInfo info : allSubscriptions) { 785 if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) { 786 return false; 787 } 788 } 789 return true; 790 } 791 updateAirplaneMode(boolean force)792 private void updateAirplaneMode(boolean force) { 793 boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), 794 Settings.Global.AIRPLANE_MODE_ON, 0) == 1); 795 if (airplaneMode != mAirplaneMode || force) { 796 mAirplaneMode = airplaneMode; 797 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 798 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 799 mobileSignalController.setAirplaneMode(mAirplaneMode); 800 } 801 notifyListeners(); 802 } 803 } 804 refreshLocale()805 private void refreshLocale() { 806 Locale current = mContext.getResources().getConfiguration().locale; 807 if (!current.equals(mLocale)) { 808 mLocale = current; 809 mWifiSignalController.refreshLocale(); 810 notifyAllListeners(); 811 } 812 } 813 814 /** 815 * Forces update of all callbacks on both SignalClusters and 816 * NetworkSignalChangedCallbacks. 817 */ notifyAllListeners()818 private void notifyAllListeners() { 819 notifyListeners(); 820 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 821 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 822 mobileSignalController.notifyListeners(); 823 } 824 mWifiSignalController.notifyListeners(); 825 mEthernetSignalController.notifyListeners(); 826 } 827 828 /** 829 * Notifies listeners of changes in state of to the NetworkController, but 830 * does not notify for any info on SignalControllers, for that call 831 * notifyAllListeners. 832 */ notifyListeners()833 private void notifyListeners() { 834 mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode, 835 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext)); 836 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected); 837 } 838 839 /** 840 * Update the Inet conditions and what network we are connected to. 841 */ updateConnectivity()842 private void updateConnectivity() { 843 mConnectedTransports.clear(); 844 mValidatedTransports.clear(); 845 for (NetworkCapabilities nc : 846 mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) { 847 for (int transportType : nc.getTransportTypes()) { 848 mConnectedTransports.set(transportType); 849 if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) { 850 mValidatedTransports.set(transportType); 851 } 852 } 853 } 854 855 if (mForceCellularValidated) mValidatedTransports.set(TRANSPORT_CELLULAR); 856 857 if (CHATTY) { 858 Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports); 859 Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports); 860 } 861 862 mInetCondition = !mValidatedTransports.isEmpty(); 863 864 pushConnectivityToSignals(); 865 } 866 867 /** 868 * Pushes the current connectivity state to all SignalControllers. 869 */ pushConnectivityToSignals()870 private void pushConnectivityToSignals() { 871 // We want to update all the icons, all at once, for any condition change 872 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 873 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 874 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports); 875 } 876 mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports); 877 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports); 878 } 879 dump(FileDescriptor fd, PrintWriter pw, String[] args)880 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 881 pw.println("NetworkController state:"); 882 883 pw.println(" - telephony ------"); 884 pw.print(" hasVoiceCallingFeature()="); 885 pw.println(hasVoiceCallingFeature()); 886 pw.println(" mListening=" + mListening); 887 888 pw.println(" - connectivity ------"); 889 pw.print(" mConnectedTransports="); 890 pw.println(mConnectedTransports); 891 pw.print(" mValidatedTransports="); 892 pw.println(mValidatedTransports); 893 pw.print(" mInetCondition="); 894 pw.println(mInetCondition); 895 pw.print(" mAirplaneMode="); 896 pw.println(mAirplaneMode); 897 pw.print(" mLocale="); 898 pw.println(mLocale); 899 pw.print(" mLastServiceState="); 900 pw.println(mLastServiceState); 901 pw.print(" mIsEmergency="); 902 pw.println(mIsEmergency); 903 pw.print(" mEmergencySource="); 904 pw.println(emergencyToString(mEmergencySource)); 905 906 pw.println(" - config ------"); 907 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 908 MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); 909 mobileSignalController.dump(pw); 910 } 911 mWifiSignalController.dump(pw); 912 913 mEthernetSignalController.dump(pw); 914 915 mAccessPoints.dump(pw); 916 } 917 emergencyToString(int emergencySource)918 private static final String emergencyToString(int emergencySource) { 919 if (emergencySource > EMERGENCY_NO_SUB) { 920 return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) 921 + ")"; 922 } else if (emergencySource > EMERGENCY_NO_SUB) { 923 return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")"; 924 } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) { 925 return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")"; 926 } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) { 927 return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")"; 928 } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) { 929 return "NO_CONTROLLERS"; 930 } 931 return "UNKNOWN_SOURCE"; 932 } 933 934 private boolean mDemoMode; 935 private boolean mDemoInetCondition; 936 private WifiSignalController.WifiState mDemoWifiState; 937 938 @Override dispatchDemoCommand(String command, Bundle args)939 public void dispatchDemoCommand(String command, Bundle args) { 940 if (!mDemoMode && command.equals(COMMAND_ENTER)) { 941 if (DEBUG) Log.d(TAG, "Entering demo mode"); 942 unregisterListeners(); 943 mDemoMode = true; 944 mDemoInetCondition = mInetCondition; 945 mDemoWifiState = mWifiSignalController.getState(); 946 mDemoWifiState.ssid = "DemoMode"; 947 } else if (mDemoMode && command.equals(COMMAND_EXIT)) { 948 if (DEBUG) Log.d(TAG, "Exiting demo mode"); 949 mDemoMode = false; 950 // Update what MobileSignalControllers, because they may change 951 // to set the number of sim slots. 952 updateMobileControllers(); 953 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 954 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 955 controller.resetLastState(); 956 } 957 mWifiSignalController.resetLastState(); 958 mReceiverHandler.post(mRegisterListeners); 959 notifyAllListeners(); 960 } else if (mDemoMode && command.equals(COMMAND_NETWORK)) { 961 String airplane = args.getString("airplane"); 962 if (airplane != null) { 963 boolean show = airplane.equals("show"); 964 mCallbackHandler.setIsAirplaneMode(new IconState(show, 965 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, 966 mContext)); 967 } 968 String fully = args.getString("fully"); 969 if (fully != null) { 970 mDemoInetCondition = Boolean.parseBoolean(fully); 971 BitSet connected = new BitSet(); 972 973 if (mDemoInetCondition) { 974 connected.set(mWifiSignalController.mTransportType); 975 } 976 mWifiSignalController.updateConnectivity(connected, connected); 977 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 978 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 979 if (mDemoInetCondition) { 980 connected.set(controller.mTransportType); 981 } 982 controller.updateConnectivity(connected, connected); 983 } 984 } 985 String wifi = args.getString("wifi"); 986 if (wifi != null) { 987 boolean show = wifi.equals("show"); 988 String level = args.getString("level"); 989 if (level != null) { 990 mDemoWifiState.level = level.equals("null") ? -1 991 : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1); 992 mDemoWifiState.connected = mDemoWifiState.level >= 0; 993 } 994 String activity = args.getString("activity"); 995 if (activity != null) { 996 switch (activity) { 997 case "inout": 998 mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT); 999 break; 1000 case "in": 1001 mWifiSignalController.setActivity(DATA_ACTIVITY_IN); 1002 break; 1003 case "out": 1004 mWifiSignalController.setActivity(DATA_ACTIVITY_OUT); 1005 break; 1006 default: 1007 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE); 1008 break; 1009 } 1010 } else { 1011 mWifiSignalController.setActivity(DATA_ACTIVITY_NONE); 1012 } 1013 String ssid = args.getString("ssid"); 1014 if (ssid != null) { 1015 mDemoWifiState.ssid = ssid; 1016 } 1017 mDemoWifiState.enabled = show; 1018 mWifiSignalController.notifyListeners(); 1019 } 1020 String sims = args.getString("sims"); 1021 if (sims != null) { 1022 int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8); 1023 List<SubscriptionInfo> subs = new ArrayList<>(); 1024 if (num != mMobileSignalControllers.size()) { 1025 mMobileSignalControllers.clear(); 1026 int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); 1027 for (int i = start /* get out of normal index range */; i < start + num; i++) { 1028 subs.add(addSignalController(i, i)); 1029 } 1030 mCallbackHandler.setSubs(subs); 1031 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 1032 int key = mMobileSignalControllers.keyAt(i); 1033 MobileSignalController controller = mMobileSignalControllers.get(key); 1034 controller.notifyListeners(); 1035 } 1036 } 1037 } 1038 String nosim = args.getString("nosim"); 1039 if (nosim != null) { 1040 mHasNoSubs = nosim.equals("show"); 1041 mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected); 1042 } 1043 String mobile = args.getString("mobile"); 1044 if (mobile != null) { 1045 boolean show = mobile.equals("show"); 1046 String datatype = args.getString("datatype"); 1047 String slotString = args.getString("slot"); 1048 int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString); 1049 slot = MathUtils.constrain(slot, 0, 8); 1050 // Ensure we have enough sim slots 1051 List<SubscriptionInfo> subs = new ArrayList<>(); 1052 while (mMobileSignalControllers.size() <= slot) { 1053 int nextSlot = mMobileSignalControllers.size(); 1054 subs.add(addSignalController(nextSlot, nextSlot)); 1055 } 1056 if (!subs.isEmpty()) { 1057 mCallbackHandler.setSubs(subs); 1058 } 1059 // Hack to index linearly for easy use. 1060 MobileSignalController controller = mMobileSignalControllers.valueAt(slot); 1061 controller.getState().dataSim = datatype != null; 1062 controller.getState().isDefault = datatype != null; 1063 controller.getState().dataConnected = datatype != null; 1064 if (datatype != null) { 1065 controller.getState().iconGroup = 1066 datatype.equals("1x") ? TelephonyIcons.ONE_X : 1067 datatype.equals("3g") ? TelephonyIcons.THREE_G : 1068 datatype.equals("4g") ? TelephonyIcons.FOUR_G : 1069 datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS : 1070 datatype.equals("5g") ? TelephonyIcons.NR_5G : 1071 datatype.equals("5ge") ? TelephonyIcons.LTE_CA_5G_E : 1072 datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS : 1073 datatype.equals("e") ? TelephonyIcons.E : 1074 datatype.equals("g") ? TelephonyIcons.G : 1075 datatype.equals("h") ? TelephonyIcons.H : 1076 datatype.equals("h+") ? TelephonyIcons.H_PLUS : 1077 datatype.equals("lte") ? TelephonyIcons.LTE : 1078 datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS : 1079 datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED : 1080 datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA : 1081 TelephonyIcons.UNKNOWN; 1082 } 1083 if (args.containsKey("roam")) { 1084 controller.getState().roaming = "show".equals(args.getString("roam")); 1085 } 1086 String level = args.getString("level"); 1087 if (level != null) { 1088 controller.getState().level = level.equals("null") ? -1 1089 : Math.min(Integer.parseInt(level), 1090 CellSignalStrength.getNumSignalStrengthLevels()); 1091 controller.getState().connected = controller.getState().level >= 0; 1092 } 1093 if (args.containsKey("inflate")) { 1094 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 1095 mMobileSignalControllers.valueAt(i).mInflateSignalStrengths = 1096 "true".equals(args.getString("inflate")); 1097 } 1098 } 1099 String activity = args.getString("activity"); 1100 if (activity != null) { 1101 controller.getState().dataConnected = true; 1102 switch (activity) { 1103 case "inout": 1104 controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT); 1105 break; 1106 case "in": 1107 controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN); 1108 break; 1109 case "out": 1110 controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT); 1111 break; 1112 default: 1113 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE); 1114 break; 1115 } 1116 } else { 1117 controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE); 1118 } 1119 controller.getState().enabled = show; 1120 controller.notifyListeners(); 1121 } 1122 String carrierNetworkChange = args.getString("carriernetworkchange"); 1123 if (carrierNetworkChange != null) { 1124 boolean show = carrierNetworkChange.equals("show"); 1125 for (int i = 0; i < mMobileSignalControllers.size(); i++) { 1126 MobileSignalController controller = mMobileSignalControllers.valueAt(i); 1127 controller.setCarrierNetworkChangeMode(show); 1128 } 1129 } 1130 } 1131 } 1132 addSignalController(int id, int simSlotIndex)1133 private SubscriptionInfo addSignalController(int id, int simSlotIndex) { 1134 SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0, 1135 null, null, null, "", false, null, null); 1136 MobileSignalController controller = new MobileSignalController(mContext, 1137 mConfig, mHasMobileDataFeature, 1138 mPhone.createForSubscriptionId(info.getSubscriptionId()), mCallbackHandler, this, info, 1139 mSubDefaults, mReceiverHandler.getLooper()); 1140 mMobileSignalControllers.put(id, controller); 1141 controller.getState().userSetup = true; 1142 return info; 1143 } 1144 hasEmergencyCryptKeeperText()1145 public boolean hasEmergencyCryptKeeperText() { 1146 return EncryptionHelper.IS_DATA_ENCRYPTED; 1147 } 1148 isRadioOn()1149 public boolean isRadioOn() { 1150 return !mAirplaneMode; 1151 } 1152 1153 private class SubListener extends OnSubscriptionsChangedListener { 1154 @Override onSubscriptionsChanged()1155 public void onSubscriptionsChanged() { 1156 updateMobileControllers(); 1157 } 1158 } 1159 1160 /** 1161 * Used to register listeners from the BG Looper, this way the PhoneStateListeners that 1162 * get created will also run on the BG Looper. 1163 */ 1164 private final Runnable mRegisterListeners = new Runnable() { 1165 @Override 1166 public void run() { 1167 registerListeners(); 1168 } 1169 }; 1170 1171 public static class SubscriptionDefaults { getDefaultVoiceSubId()1172 public int getDefaultVoiceSubId() { 1173 return SubscriptionManager.getDefaultVoiceSubscriptionId(); 1174 } 1175 getDefaultDataSubId()1176 public int getDefaultDataSubId() { 1177 return SubscriptionManager.getDefaultDataSubscriptionId(); 1178 } 1179 getActiveDataSubId()1180 public int getActiveDataSubId() { 1181 return SubscriptionManager.getActiveDataSubscriptionId(); 1182 } 1183 } 1184 1185 @VisibleForTesting 1186 static class Config { 1187 boolean showAtLeast3G = false; 1188 boolean show4gFor3g = false; 1189 boolean alwaysShowCdmaRssi = false; 1190 boolean show4gForLte = false; 1191 boolean hideLtePlus = false; 1192 boolean hspaDataDistinguishable; 1193 boolean inflateSignalStrengths = false; 1194 boolean alwaysShowDataRatIcon = false; 1195 readConfig(Context context)1196 static Config readConfig(Context context) { 1197 Config config = new Config(); 1198 Resources res = context.getResources(); 1199 1200 config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G); 1201 config.alwaysShowCdmaRssi = 1202 res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); 1203 config.hspaDataDistinguishable = 1204 res.getBoolean(R.bool.config_hspa_data_distinguishable); 1205 config.inflateSignalStrengths = res.getBoolean( 1206 com.android.internal.R.bool.config_inflateSignalStrength); 1207 1208 CarrierConfigManager configMgr = (CarrierConfigManager) 1209 context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1210 // Handle specific carrier config values for the default data SIM 1211 int defaultDataSubId = SubscriptionManager.from(context) 1212 .getDefaultDataSubscriptionId(); 1213 PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId); 1214 if (b != null) { 1215 config.alwaysShowDataRatIcon = b.getBoolean( 1216 CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL); 1217 config.show4gForLte = b.getBoolean( 1218 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL); 1219 config.show4gFor3g = b.getBoolean( 1220 CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL); 1221 config.hideLtePlus = b.getBoolean( 1222 CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL); 1223 } 1224 1225 return config; 1226 } 1227 } 1228 } 1229