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