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