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