Android 6.0 System UI Network Signal Bar Display Refresh

Keywords: Android Java network Mobile

The display refresh of Android's network signal bar is also part of the System UI. The main business logic is also in the System UI module. The whole process begins in PhoneStatusBar.java.

frameworks/base/packages/SystemUI/src/com/Android/systemui/statusbar/phone/PhoneStatusBar.Java;


Starting with the layout:
makeStatusBarView() of PhoneStatusBar.java loads super_status_bar.xml uniformly. In Android, there are three main places on the system UI to display the signal status bar, namely the status bar, the status bar under the lock screen interface and the quick setting area of the drop-down notification bar. The three references are status_bar.xml, keyguard_status_bar.xml, status_bar_expanded_header.xml, and the three layout files all go to include a system_icons.xml layout.
This layout is where the network signal bar display and battery icon display view are sought.

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:id="@+id/system_icons"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="match_parent"  
  5.     android:gravity="center_vertical">  
  6.   
  7.     <com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/statusIcons"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="match_parent"  
  10.         android:gravity="center_vertical"  
  11.         android:orientation="horizontal"/>  
  12.   
  13.     <include layout="@layout/signal_cluster_view"  
  14.         android:id="@+id/signal_cluster"  
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_marginStart="2.5dp"/>  
  18.   
  19.     <!-- battery must be padded below to match assets -->  
  20.     <com.android.systemui.BatteryMeterView android:id="@+id/battery"  
  21.         android:layout_height="14.5dp"  
  22.         android:layout_width="9.5dp"  
  23.         android:layout_marginBottom="@dimen/battery_margin_bottom"/>  
  24. </LinearLayout>  
This layout will include a signal_cluster_view.xml layout, that is, this layout is the layout file of the specific signal bar.

  1. <com.android.systemui.statusbar.SignalClusterView  
  2.     xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_height="match_parent"  
  4.     android:layout_width="wrap_content"  
  5.     android:gravity="center_vertical"  
  6.     android:orientation="horizontal"  
  7.     android:paddingEnd="@dimen/signal_cluster_battery_padding"  
  8.     >  
  9.     <ImageView  
  10.         android:id="@+id/vpn"  
  11.         android:layout_height="wrap_content"  
  12.         android:layout_width="wrap_content"  
  13.         android:paddingEnd="6dp"  
  14.         android:src="@drawable/stat_sys_vpn_ic"  
  15.         />  
  16.     <FrameLayout  
  17.         android:id="@+id/wifi_combo"  
  18.         android:layout_height="wrap_content"  
  19.         android:layout_width="wrap_content"  
  20.         >  
  21.         <ImageView  
  22.             android:id="@+id/wifi_signal"  
  23.             android:layout_height="wrap_content"  
  24.             android:layout_width="wrap_content"  
  25.             />  
  26.     </FrameLayout>  
  27.     <View  
  28.         android:id="@+id/wifi_signal_spacer"  
  29.         android:layout_width="4dp"  
  30.         android:layout_height="4dp"  
  31.         android:visibility="gone"  
  32.         />  
  33.     <LinearLayout  
  34.         android:id="@+id/mobile_signal_group"  
  35.         android:layout_height="wrap_content"  
  36.         android:layout_width="wrap_content"  
  37.         >  
  38.     </LinearLayout>  
  39.     <ImageView  
  40.         android:id="@+id/no_sims"  
  41.         android:layout_height="wrap_content"  
  42.         android:layout_width="wrap_content"  
  43.         android:src="@drawable/stat_sys_no_sims"  
  44.         />  
  45.     <View  
  46.         android:id="@+id/wifi_airplane_spacer"  
  47.         android:layout_width="4dp"  
  48.         android:layout_height="4dp"  
  49.         android:visibility="gone"  
  50.         />  
  51.     <ImageView  
  52.         android:id="@+id/airplane"  
  53.         android:layout_height="wrap_content"  
  54.         android:layout_width="wrap_content"  
  55.         />  
  56. </com.android.systemui.statusbar.SignalClusterView>  


Code logic:
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
makeStatusBarView() method:

In this method, we first create two controllers, mNetwork Controller and mSecurity Controller.

  1. mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());  
  2. mSecurityController = new SecurityControllerImpl(mContext);  
NetworkController Impl. Java inherits from Broadcast Receiver. Look at how NetworkController Impl is constructed:

  1. public NetworkControllerImpl(Context context, Looper bgLooper) {  
  2.         this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),  
  3.                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),  
  4.                 (WifiManager) context.getSystemService(Context.WIFI_SERVICE),  
  5.                 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,  
  6.                 new CallbackHandler(),  
  7.                 new AccessPointControllerImpl(context, bgLooper),  
  8.                 new MobileDataControllerImpl(context),  
  9.                 new SubscriptionDefaults());  
  10.         mReceiverHandler.post(mRegisterListeners);  
  11.     }  
In this constructor, another constructor will be called first.

  1. @VisibleForTesting  
  2.     NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,  
  3.             TelephonyManager telephonyManager, WifiManager wifiManager,  
  4.             SubscriptionManager subManager, Config config, Looper bgLooper,  
  5.             CallbackHandler callbackHandler,  
  6.             AccessPointControllerImpl accessPointController,  
  7.             MobileDataControllerImpl mobileDataController,  
  8.             SubscriptionDefaults defaultsHandler) {  
  9.         mContext = context;  
  10.         mConfig = config;  
  11.         mReceiverHandler = new Handler(bgLooper);  
  12.         mCallbackHandler = callbackHandler;  
  13.   
  14.         mSubscriptionManager = subManager;  
  15.         mSubDefaults = defaultsHandler;  
  16.         mConnectivityManager = connectivityManager;  
  17.         mHasMobileDataFeature =  
  18.                 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);  
  19.   
  20.         // telephony  
  21.         mPhone = telephonyManager;  
  22.   
  23.         // wifi  
  24.         mWifiManager = wifiManager;  
  25.   
  26.         mLocale = mContext.getResources().getConfiguration().locale;  
  27.         mAccessPoints = accessPointController;  
  28.         mMobileDataController = mobileDataController;  
  29.         mMobileDataController.setNetworkController(this);  
  30.         // TODO: Find a way to move this into MobileDataController.  
  31.         mMobileDataController.setCallback(new MobileDataControllerImpl.Callback() {  
  32.             @Override  
  33.             public void onMobileDataEnabled(boolean enabled) {  
  34.                 mCallbackHandler.setMobileDataEnabled(enabled);  
  35.             }  
  36.         });  
  37.         mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,  
  38.                 mCallbackHandler, this);  
  39.   
  40.         mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);  
  41.   
  42.         // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it  
  43.         updateAirplaneMode(true /* force callback */);  
  44.     }  
1. Assigning the corresponding member variables;
2. Create handler, mReceiver Handler, mCallbackHandler;
3. Create mMobile Data Controller controller and set callbacks for it.
4. Create mWifiSignalController, mEthernetSignalController controller;
5. Check and update flight mode;


After executing this internal construction method, we will use mReceiver Handler to perform a registered broadcast operation, which is responsible for monitoring wifi, SIM card status, service state, flight mode and so on. Finally, we call the updateMobileControllers() method to initialize the signal bar display:

  1. mReceiverHandler.post(mRegisterListeners);  
  1. /** 
  2.  * Used to register listeners from the BG Looper, this way the PhoneStateListeners that 
  3.  * get created will also run on the BG Looper. 
  4.  */  
  5. private final Runnable mRegisterListeners = new Runnable() {  
  6.     @Override  
  7.     public void run() {  
  8.         registerListeners();  
  9.     }  
  10. };  
  1. private void registerListeners() {  
  2.     for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {  
  3.         mobileSignalController.registerListener();  
  4.     }  
  5.     if (mSubscriptionListener == null) {  
  6.         mSubscriptionListener = new SubListener();  
  7.     }  
  8.     mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);  
  9.   
  10.     // broadcasts  
  11.     IntentFilter filter = new IntentFilter();  
  12.     filter.addAction(WifiManager.RSSI_CHANGED_ACTION);  
  13.     filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);  
  14.     filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);  
  15.     filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);  
  16.     filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);  
  17.     filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);  
  18.     filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);  
  19.     filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);  
  20.     filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);  
  21.     filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);  
  22.     filter.addAction(Intent.ACTION_LOCALE_CHANGED);  
  23.     filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);  
  24.     if (carrier != null && (CarrierAppUtils.CARRIER.TELEPHONY_CARRIER_ONE  
  25.             == carrier)) {  
  26.     filter.addAction(ACTION_EMBMS_STATUS);  
  27.     }  
  28.     mContext.registerReceiver(this, filter, null, mReceiverHandler);  
  29.     mListening = true;  
  30.   
  31.     updateMobileControllers();  
  32. }  
After analyzing the construction method of Network Controller Impl. java, we can basically know that Network Controller Impl. Java is a data control class as a signal bar, responsible for monitoring wifi, service state, flight mode and so on.


Look at the construction method of SecurityController Impl. java. First we get some instances of system services, then we register a network callback interface when users switch.

  1. public SecurityControllerImpl(Context context) {  
  2.     mContext = context;  
  3.     mDevicePolicyManager = (DevicePolicyManager)  
  4.             context.getSystemService(Context.DEVICE_POLICY_SERVICE);  
  5.     mConnectivityManager = (ConnectivityManager)  
  6.             context.getSystemService(Context.CONNECTIVITY_SERVICE);  
  7.     mConnectivityManagerService = IConnectivityManager.Stub.asInterface(  
  8.             ServiceManager.getService(Context.CONNECTIVITY_SERVICE));  
  9.     mUserManager = (UserManager)  
  10.             context.getSystemService(Context.USER_SERVICE);  
  11.   
  12.     // TODO: re-register network callback on user change.  
  13.     mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);  
  14.     onUserSwitched(ActivityManager.getCurrentUser());  
  15. }  



Returning to PhoneStatusBar.java's makeStatusBarView() method, we instantiate the custom view object SignalClusterView. As mentioned above, we need to use the network signal status bar in all three parts of the Android System UI, so we instantiate it three times and add corresponding interfaces to it.

  1. final SignalClusterView signalCluster =  
  2.                 (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);  
  3.         final SignalClusterView signalClusterKeyguard =  
  4.                 (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);  
  5.         final SignalClusterView signalClusterQs =  
  6.                 (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);  
  7.         mNetworkController.addSignalCallback(signalCluster);  
  8.         mNetworkController.addSignalCallback(signalClusterKeyguard);  
  9.         mNetworkController.addSignalCallback(signalClusterQs);  
  10.         signalCluster.setSecurityController(mSecurityController);  
  11.         signalCluster.setNetworkController(mNetworkController);  
  12.         signalClusterKeyguard.setSecurityController(mSecurityController);  
  13.         signalClusterKeyguard.setNetworkController(mNetworkController);  
  14.         signalClusterQs.setSecurityController(mSecurityController);  
  15.         signalClusterQs.setNetworkController(mNetworkController);  
Let's first look at the addSignalCallback() method, which passes in an object with the parameter SignalClusterView.java. That is to say, it can be boldly assumed that the function of this method should be to establish callback calls between SignalClusterView.java and NetworkController Impl. java. Specifically, the main implementation of this method is in NetworkController Impl. java.

  1. public void addSignalCallback(SignalCallback cb) {  
  2.         mCallbackHandler.setListening(cb, true);  
  3.         mCallbackHandler.setSubs(mCurrentSubscriptions);  
  4.         mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,  
  5.                 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));  
  6.         mCallbackHandler.setNoSims(mHasNoSims);  
  7.         mWifiSignalController.notifyListeners();  
  8.         mEthernetSignalController.notifyListeners();  
  9.         for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {  
  10.             mobileSignalController.notifyListeners();  
  11.         }  
  12.     }  
Call the CallbackHandler.setXXX() method, which mainly performs the corresponding operation by sending an msg to handler. Take the setListening() method as an example:
Send a message to handler that msg is MSG_ADD_REMOVE_SIGNAL:

  1. public void setListening(SignalCallback listener, boolean listening) {  
  2.     obtainMessage(MSG_ADD_REMOVE_SIGNAL, listening ? 1 : 00, listener).sendToTarget();  
  3. }  
Add callback to the collection and store it in handler to complete the setListening() method:

  1. case MSG_ADD_REMOVE_SIGNAL:  
  2.     if (msg.arg1 != 0) {  
  3.         mSignalCallbacks.add((SignalCallback) msg.obj);  
  4.      } else {  
  5.         mSignalCallbacks.remove((SignalCallback) msg.obj);  
  6.      }  
  7.      break;  
Through the analysis of these setXXX() methods, it is found that CallBackHandler.java class is mainly used for message transmission between Network Controller Impl. Java and SignalClusterView.java, which is realized by callback of Network Controller. SignalCallback interface.

Next, we call the notifyListeners() method of wifi, Ethernet signal and mobile signal controller respectively to perform the initialization information status operation.

Go back to PhoneStatusBar.java's makeStatusBarView() method, and then continue calling SignalClusterView.java's method:

  1. signalCluster.setSecurityController(mSecurityController);  
  2. signalCluster.setNetworkController(mNetworkController);  
  1. setNetworkController()The main method is to instantiate this class. NetworkControllerImpl control object;  
  2.     public void setNetworkController(NetworkControllerImpl nc) {  
  3.         if (DEBUG) Log.d(TAG, "NetworkController=" + nc);  
  4.         mNC = nc;  
  5.     }  
  6.   
  7.     public void setSecurityController(SecurityController sc) {  
  8.         if (DEBUG) Log.d(TAG, "SecurityController=" + sc);  
  9.         mSC = sc;  
  10.         mSC.addCallback(this);  
  11.         mVpnVisible = mSC.isVpnEnabled();  
  12.     }  

The setSecurityController() method not only needs to assign values to member variables, but also needs to call the addCallback() method of SecurityController Impl. java to add the callback object of the controller to the set mCallbacks to save.

  1. @Override  
  2. public void addCallback(SecurityControllerCallback callback) {  
  3.     synchronized (mCallbacks) {  
  4.         if (callback == null || mCallbacks.contains(callback)) return;  
  5.         if (DEBUG) Log.d(TAG, "addCallback " + callback);  
  6.         mCallbacks.add(callback);  
  7.     }  
  8. }  
This completes the signal bar analysis in PhoneStatusBar.java's makeStatusBarView().

Summary of Process Execution in PhoneStatusBar.java's makeStatusBarView():
1. Instantiate two controller implementation objects, NetworkController Impl. Java and SecurityController Impl. java. Register the broadcasting of corresponding state changes in the construction method of NetworkController Impl. java, and register the monitoring callback of network state changes when users switch in SecurityController Impl. java.
2. Initialize the signal bar object, SignalClusterView.java;
3. Connect Network Controller Impl. java with ignalClusterView. Java through CallbackHandler.java, and control communication between Network Controller Impl. Java and SignalClusterView.java through callback.
4. SignalClusterView.java calls setSecurityController() to implement the SecurityController Callback interface. By calling back onStateChanged(), it can monitor the changes of network state when switching users.
5. Network Controller Impl. Java is a data control class of signal bar, inherited from Broadcast Receiver, responsible for monitoring wifi, SIM card status, service state, flight mode and so on.
6. SignalClusterView.java is used to refresh and display the interface.



Next, we will analyze the process of system UI execution when some states change. Take inserting SIM card as an example:

1. When the SIM card is inserted, the android system will send Telephone Intents. ACTION_SIM_STATE_CHANGED broadcasting.
2. Network Controller Impl. Java inherits from Broadcast Receiver and monitors some corresponding system broadcasts.

3. Call the onReceiver() method of NetworkController Impl. Java and the updateMobileControllers() method after receiving the broadcast of TelephonyIntents.ACTION_SIM_STATE_CHANGED.

  1. if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {  
  2.     // Might have different subscriptions now.  
  3.     updateMobileControllers();  
  4. }   
4. Internally call the doUpdateMobileControllers() method;

  1. private void updateMobileControllers() {  
  2.         if (!mListening) {  
  3.             return;  
  4.         }  
  5.         doUpdateMobileControllers();  
  6.     }  
5. Get the information of the sim card in the current device and empty the set if it returns. If the subscription information of the sim card does not change, it will enter the if() statement and then call the updateNoSims() method and return. Because the current analysis is to insert the sim card, it will not enter the if() statement.
  1. @VisibleForTesting  
  2. void doUpdateMobileControllers() {  
  3.     List<SubscriptionInfo> subscriptions = mSubscriptionManager.getActiveSubscriptionInfoList();  
  4.     if (subscriptions == null) {  
  5.         subscriptions = Collections.emptyList();  
  6.     }  
  7.     // If there have been no relevant changes to any of the subscriptions, we can leave as is.  
  8.     if (hasCorrectMobileControllers(subscriptions)) {  
  9.         // Even if the controllers are correct, make sure we have the right no sims state.  
  10.         // Such as on boot, don't need any controllers, because there are no sims,  
  11.         // but we still need to update the no sim state.  
  12.         updateNoSims();  
  13.         return;  
  14.     }  
  15.     setCurrentSubscriptions(subscriptions);  
  16.     updateNoSims();  
  17.     recalculateEmergency();  
  18. }  

The setCurrentSubscriptions() method is called, which constructs the Mobile Signal Controller based on the returned sim card subscription information set and stores it with the set Map < Integer, Mobile Signal Controller > mMobile Signal Controllers.

  1. @VisibleForTesting  
  2. void setCurrentSubscriptions(List<SubscriptionInfo> subscriptions) {  
  3.     Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() {  
  4.         @Override  
  5.         public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) {  
  6.             return lhs.getSimSlotIndex() == rhs.getSimSlotIndex()  
  7.                     ? lhs.getSubscriptionId() - rhs.getSubscriptionId()  
  8.                     : lhs.getSimSlotIndex() - rhs.getSimSlotIndex();  
  9.         }  
  10.     });  
  11.     mCurrentSubscriptions = subscriptions;  
  12.   
  13.     HashMap<Integer, MobileSignalController> cachedControllers =  
  14.             new HashMap<Integer, MobileSignalController>(mMobileSignalControllers);  
  15.     mMobileSignalControllers.clear();  
  16.     final int num = subscriptions.size();  
  17.     for (int i = 0; i < num; i++) {  
  18.         int subId = subscriptions.get(i).getSubscriptionId();  
  19.         // If we have a copy of this controller already reuse it, otherwise make a new one.  
  20.         if (cachedControllers.containsKey(subId)) {  
  21.             mMobileSignalControllers.put(subId, cachedControllers.remove(subId));  
  22.         } else {  
  23.             MobileSignalController controller = new MobileSignalController(mContext, mConfig,  
  24.                     mHasMobileDataFeature, mPhone, mCallbackHandler,  
  25.                     this, subscriptions.get(i), mSubDefaults, mReceiverHandler.getLooper());  
  26.             mMobileSignalControllers.put(subId, controller);  
  27.             if (subscriptions.get(i).getSimSlotIndex() == 0) {  
  28.                 mDefaultSignalController = controller;  
  29.             }  
  30.             if (mListening) {  
  31.                 controller.registerListener();  
  32.             }  
  33.         }  
  34.     }  
  35.     if (mListening) {  
  36.         for (Integer key : cachedControllers.keySet()) {  
  37.             if (cachedControllers.get(key) == mDefaultSignalController) {  
  38.                 mDefaultSignalController = null;  
  39.             }  
  40.             cachedControllers.get(key).unregisterListener();  
  41.         }  
  42.     }  
  43.     mCallbackHandler.setSubs(subscriptions);  
  44.     notifyAllListeners();  
  45.   
  46.     // There may be new MobileSignalControllers around, make sure they get the current  
  47.     // inet condition and airplane mode.  
  48.     pushConnectivityToSignals();  
  49.     updateAirplaneMode(true /* force */);  
  50. }  
MobileSignalController.java is a class used to encapsulate Icon controllers based on signal strength, operator, network type, etc.

  1. public MobileSignalController(Context context, Config config, boolean hasMobileData,  
  2.         TelephonyManager phone, CallbackHandler callbackHandler,  
  3.         NetworkControllerImpl networkController, SubscriptionInfo info,  
  4.         SubscriptionDefaults defaults, Looper receiverLooper) {  
  5.     super("MobileSignalController(" + info.getSubscriptionId() + ")", context,  
  6.             NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,  
  7.             networkController);  
  8.     mNetworkToIconLookup = new SparseArray<>();  
  9.     mConfig = config;  
  10.     mPhone = phone;  
  11.     mDefaults = defaults;  
  12.     mSubscriptionInfo = info;  
  13.     mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(),  
  14.             receiverLooper);  
  15.     mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);  
  16.     mNetworkNameDefault = getStringIfExists(  
  17.             com.android.internal.R.string.lockscreen_carrier_default);  
  18.     mIsDataSignalControlEnabled = mContext.getResources()  
  19.             .getBoolean(R.bool.config_data_signal_control);  
  20.     if (mIsDataSignalControlEnabled) {  
  21.         mDataEnabledSettingObserver =  
  22.                 new DataEnabledSettingObserver(new Handler(), context);  
  23.         mLastState.isForbidden = mCurrentState.isForbidden =  
  24.               !(isMobileDataEnabled(mSubscriptionInfo.getSubscriptionId()));  
  25.     }  
  26.     if (config.readIconsFromXml) {  
  27.         TelephonyIcons.readIconsFromXml(context);  
  28.         mDefaultIcons = !mConfig.showAtLeast3G ? TelephonyIcons.G : TelephonyIcons.THREE_G;  
  29.     } else {  
  30.         mapIconSets();  
  31.     }  
  32.   
  33.     if (carrier != null && (CarrierAppUtils.CARRIER.TELEPHONY_CARRIER_ONE  
  34.              == carrier)) {  
  35.         mStyle = context.getResources().getInteger(R.integer.status_bar_style_extended);  
  36.     } else {  
  37.         mStyle = context.getResources().getInteger(R.integer.status_bar_style);  
  38.     }  
  39.   
  40.     String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()  
  41.             : mNetworkNameDefault;  
  42.     mLastState.networkName = mCurrentState.networkName = networkName;  
  43.     mLastState.networkNameData = mCurrentState.networkNameData = networkName;  
  44.     mLastState.enabled = mCurrentState.enabled = hasMobileData;  
  45.     mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;  
  46.     // Get initial data sim state.  
  47.     updateDataSim();  
  48. }  
1. Mobile Phone StateListener is used to monitor signal strength, mobile data links, etc. updateTelephony() method is called to update current state to set network type, icon, signal strength, etc. when signal strength and mobile data connection are detected to change. Then notifyListeners IfNecessary () method is called to call notifyListeners() method, and setMobileDataIndica in SignalClusterView.java is called through CallbackHandler object. The tors () method completes the refresh display of icons.
2. mapIconSets() is used to set the Icon map set of network type.
3. After this construction method is executed, it will return to the setCurrentSubscriptions() method of NetworkController Impl. Java and execute the controller.registerListener() statement to register the MobilePhoneStateListener listener for each MobileSignalController object.


Then call mCallbackHandler.setSubs() to pass the subscription information set of the sim card to the setSubs() method of SignalClusterView.java. First remove the previous mPhoneStatus information and mMobile Signal Group view, and then call the inflatePhoneState() method.

  1. @Override  
  2. public void setSubs(List<SubscriptionInfo> subs) {  
  3.     if (hasCorrectSubs(subs)) {  
  4.         return;  
  5.     }  
  6.     // Clear out all old subIds.  
  7.     mPhoneStates.clear();  
  8.     if (mMobileSignalGroup != null) {  
  9.         mMobileSignalGroup.removeAllViews();  
  10.     }  
  11.     final int n = subs.size();  
  12.     boolean imsOverWiFi = false;  
  13.     for (int i = 0; i < n; i++) {  
  14.         inflatePhoneState(subs.get(i).getSubscriptionId());  
  15.         imsOverWiFi |= getImsOverWifiStatus(subs.get(i).getSubscriptionId());  
  16.     }  
  17.     mImsOverWifi = imsOverWiFi;  
  18.     if (isAttachedToWindow()) {  
  19.         applyIconTint();  
  20.     }  
  21. }  
Call the inflatePhoneState() method to add state and view again.

  1. private PhoneState inflatePhoneState(int subId) {  
  2.     PhoneState state = new PhoneState(subId, mContext);  
  3.     if (mMobileSignalGroup != null) {  
  4.         mMobileSignalGroup.addView(state.mMobileGroup);  
  5.     }  
  6.     mPhoneStates.add(state);  
  7.     return state;  
  8. }  

Then go back to the setSubs() method and call the applyIconTint() method to set some Icon colors.

  1. private void applyIconTint() {  
  2.     setTint(mVpn, mIconTint);  
  3.     setTint(mAirplane, mIconTint);  
  4.     applyDarkIntensity(mDarkIntensity, mNoSims, mNoSimsDark);  
  5.     applyDarkIntensity(mDarkIntensity, mWifi, mWifiDark);  
  6.     applyDarkIntensity(mDarkIntensity, mEthernet, mEthernetDark);  
  7.     for (int i = 0; i < mPhoneStates.size(); i++) {  
  8.         mPhoneStates.get(i).setIconTint(mIconTint, mDarkIntensity);  
  9.     }  
  10. }  
Continue back to the setCurrentSubscriptions() method of NetworkController Impl. java, and then call notify AllListeners () method to notify mWifiSignalController(wifi), mEthernet SignalController (ethernet) and all mobile SignalController (mobile phone signal) to execute their respective fyListeners () methods;

  1. notifyAllListeners();  
  2.     /** 
  3.      * Forces update of all callbacks on both SignalClusters and 
  4.      * NetworkSignalChangedCallbacks. 
  5.      */  
  6.     private void notifyAllListeners() {  
  7.         notifyListeners();  
  8.         for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {  
  9.             mobileSignalController.notifyListeners();  
  10.         }  
  11.         mWifiSignalController.notifyListeners();  
  12.         mEthernetSignalController.notifyListeners();  
  13.     }  
The notifyListeners() method of Mobile SignalController. Java is mainly used to set the display Icon image attributes of the current sim card attributes, and then call the setMobile Data Indicators () method in SignalClusterView.java through the CallbackHandler object.

  1. @Override  
  2. public void notifyListeners() {  
  3.     if (mConfig.readIconsFromXml) {  
  4.         generateIconGroup();  
  5.     }  
  6.     MobileIconGroup icons = getIcons();  
  7.   
  8.     String contentDescription = getStringIfExists(getContentDescription());  
  9.     String dataContentDescription = getStringIfExists(icons.mDataContentDescription);  
  10.   
  11.     // Show icon in QS when we are connected or need to show roaming.  
  12.     boolean showDataIcon = false;  
  13.     if (mContext.getResources().getBoolean(R.bool.show_roaming_and_network_icons)) {  
  14.         showDataIcon = mCurrentState.dataConnected;  
  15.     } else {  
  16.         showDataIcon = mCurrentState.dataConnected  
  17.                 || (mCurrentState.iconGroup == TelephonyIcons.ROAMING || isRoaming());  
  18.     }  
  19.     IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,  
  20.             getCurrentIconId(), contentDescription);  
  21.   
  22.     int qsTypeIcon = 0;  
  23.     IconState qsIcon = null;  
  24.     String description = null;  
  25.     // Only send data sim callbacks to QS.  
  26.     if (mCurrentState.dataSim) {  
  27.         qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;  
  28.         qsIcon = new IconState(mCurrentState.enabled  
  29.                 && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);  
  30.         description = mCurrentState.isEmergency ? null : mCurrentState.networkName;  
  31.     }  
  32.     boolean activityIn = mCurrentState.dataConnected  
  33.                     && !mCurrentState.carrierNetworkChangeMode  
  34.                     && mCurrentState.activityIn;  
  35.     boolean activityOut = mCurrentState.dataConnected  
  36.                     && !mCurrentState.carrierNetworkChangeMode  
  37.                     && mCurrentState.activityOut;  
  38.     if (!mContext.getResources().getBoolean(R.bool.show_roaming_and_network_icons)) {  
  39.         showDataIcon &= mCurrentState.isDefault  
  40.                 || (mCurrentState.iconGroup == TelephonyIcons.ROAMING || isRoaming());  
  41.     }  
  42.     showDataIcon &= (mStyle == STATUS_BAR_STYLE_ANDROID_DEFAULT  
  43.             || mStyle == STATUS_BAR_STYLE_EXTENDED);  
  44.     int typeIcon = showDataIcon ? icons.mDataType : 0;  
  45.     int dataActivityId = showMobileActivity() ? 0 : icons.mActivityId;  
  46.     int mobileActivityId = showMobileActivity() ? icons.mActivityId : 0;  
  47.     int dataNetworkTypeInRoamingId = 0;  
  48.     if (mStyle == STATUS_BAR_STYLE_EXTENDED && isRoaming()) {  
  49.         dataNetworkTypeInRoamingId = mCurrentState.dataConnected ? typeIcon : 0;  
  50.         typeIcon = TelephonyIcons.ROAMING_ICON;  
  51.         qsTypeIcon = mCurrentState.dataConnected ? qsTypeIcon : 0;  
  52.     }  
  53.     mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,  
  54.             activityIn, activityOut, dataActivityId, mobileActivityId,  
  55.             icons.mStackedDataIcon, icons.mStackedVoiceIcon,  
  56.             dataContentDescription, description, icons.mIsWide,  
  57.             mSubscriptionInfo.getSubscriptionId(), getImsIconId(),  
  58.             isImsRegisteredInWifi(), dataNetworkTypeInRoamingId,  
  59.             getEmbmsIconId());  
  60.   
  61.     mCallbackHandler.post(new Runnable() {  
  62.         @Override  
  63.         public void run() {  
  64.             mNetworkController.updateNetworkLabelView();  
  65.         }  
  66.     });  
  67. }  
Call the setMobile Data Indicators () method in SignalClusterView.java to refresh the status of the current PhoneState object, and finally call the apply() method to refresh the Icon icon on the interface.
  1. @Override  
  2. public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,  
  3.         int qsType, boolean activityIn, boolean activityOut, int dataActivityId,  
  4.         int mobileActivityId, int stackedDataId, int stackedVoiceId,  
  5.         String typeContentDescription, String description, boolean isWide, int subId) {  
  6.     PhoneState state = getState(subId);  
  7.     if (state == null) {  
  8.         return;  
  9.     }  
  10.     state.mMobileVisible = statusIcon.visible && !mBlockMobile;  
  11.     state.mMobileStrengthId = statusIcon.icon;  
  12.     state.mMobileTypeId = statusType;  
  13.     state.mMobileDescription = statusIcon.contentDescription;  
  14.     state.mMobileTypeDescription = typeContentDescription;  
  15.     state.mIsMobileTypeIconWide = statusType != 0 && isWide;  
  16.     state.mDataActivityId = dataActivityId;  
  17.     state.mMobileActivityId = mobileActivityId;  
  18.     state.mStackedDataId = stackedDataId;  
  19.     state.mStackedVoiceId = stackedVoiceId;  
  20.   
  21.     apply();  
  22. }  
Perhaps in the course of the above operation, the network connection state has changed, and all of them finally go back to the NetworkController Impl. Java class to continue pushConnectivityToSignals() method to push the current network connection state to all the SignalControllers object controllers.


Signal bar summary:
1. The layout is loaded by PhoneStatusBar.java's makeStatusBarView() method. Because in Android system, the signal bar (status bar, status bar under lock screen interface and the quick setting area of drop-down notification bar) is used in three places, the three references are status_bar.xml, keyguard_status_bar.xml, status_bar_expanded_header.xml, instantiate three objects, and bind two controls for each SignalClusterView.java object in this method. Objects, NetworkController Impl. java, SecurityController Impl. java;
2. Network Controller Impl. Java object is mainly responsible for data control class as signal bar, inherited from Broadcast Receiver, responsible for monitoring wifi, SIM card status, service state, flight mode, etc.
SecurityController Impl. Java object is mainly responsible for the data control class of the signal bar when the user switches, and is responsible for monitoring the network state change callback when the user switches.
3. NetworkController Impl. Java links itself to SignalClusterView.java through CallbackHandler.java. In the middle, it controls communication between NetworkController Impl. Java and SignalClusterView.java by calling SignalClusterView.java in the object of CallbackHandler.java.
On the other hand, SignalClusterView.java implements the communication function by directly implementing the interface of SecurityController.java. In SecurityController Impl. java, SignalClusterView.java notifies SignalClusterView.java to do the corresponding operation by directly calling back onStateChanged().
4. Network Controller Impl. Java is inherited from Broadcast Receiver. It monitors SIM card events by monitoring system broadcasting and so on. When the SIM card is inserted, the subscription information set of the current SIM card is retrieved, and then the set is traversed to set up a MobileSignalController.java for subscription information.
5. Mobile SignalController. Java class mainly implements PhoneStateListener interface to monitor service state, signal strength, call status, mobile data connection status, and set corresponding display icons. These status and icon display properties are then passed to the SignalClusterView.java object through CallbackHandler.java.
6. SignalClusterView.java completes the final interface refresh by calling apply() method and application () method of internal PhoneState class.

Posted by NiteCloak on Mon, 01 Apr 2019 11:48:32 -0700