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