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