1. 状态栏信号图标
1.1 WIFI信号显示
WIFI信号在状态栏的显示如下图所示
当WiFi状态为关闭时,状态栏不会有任何显示。当WiFi状态打开时,会如上图所示,左侧表示有可用WiFi,右侧表示当前WiFi打开但未连接。
当WiFi状态连接时,会如上图所示,显示信号连接强度和数据连接状态。
1.2 图标更新流程框架
如图所示,WiFi图标的显示流程主要是通过监听系统的WiFi状态,然后通知UI去实时的刷新图标资源。NetworkControllerImpl.java 继承 BroadcastReceiver 监听系统WiFi状态的变化。
2. WIFI图标更新流介绍
2.1 重要类
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\NetworkControllerImpl.java
定义相关函数,继承BroadcastReceiver监听系统广播,动态注册广播接收器。是状态栏WiFi图标更新的核心类。
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\WifiIcons.java
定义了 Wifi 信号更新所需的图标资源。
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\WifiSignalController.java
2.2 WIFI图标更新流程
(1)WifiNetworkController实例化,在NetworkControllerImpl.java进行实例化
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\NetworkControllerImpl.java
@VisibleForTesting NetworkControllerImpl(Context context, ConnectivityManager connectivityManager, TelephonyManager telephonyManager, TelephonyListenerManager telephonyListenerManager, WifiManager wifiManager, SubscriptionManager subManager, Config config, Looper bgLooper, Executor bgExecutor, CallbackHandler callbackHandler, AccessPointControllerImpl accessPointController, StatusBarPipelineFlags statusBarPipelineFlags, DataUsageController dataUsageController, SubscriptionDefaults defaultsHandler, DeviceProvisionedController deviceProvisionedController, BroadcastDispatcher broadcastDispatcher, UserTracker userTracker, DemoModeController demoModeController, CarrierConfigTracker carrierConfigTracker, WifiStatusTrackerFactory trackerFactory, MobileSignalControllerFactory mobileFactory, @Main Handler handler, DumpManager dumpManager, LogBuffer logBuffer ) { mContext = context; mTelephonyListenerManager = telephonyListenerManager; mConfig = config; mMainHandler = handler; mReceiverHandler = new Handler(bgLooper); mBgLooper = bgLooper; mBgExecutor = bgExecutor; mCallbackHandler = callbackHandler; mStatusBarPipelineFlags = statusBarPipelineFlags; mDataSaverController = new DataSaverControllerImpl(context); mBroadcastDispatcher = broadcastDispatcher; mMobileFactory = mobileFactory; mSubscriptionManager = subManager; mSubDefaults = defaultsHandler; mConnectivityManager = connectivityManager; mHasMobileDataFeature = telephonyManager.isDataCapable(); mDemoModeController = demoModeController; mCarrierConfigTracker = carrierConfigTracker; mDumpManager = dumpManager; mLogBuffer = logBuffer; // telephony mPhone = telephonyManager; // wifi mWifiManager = wifiManager; mLocale = mContext.getResources().getConfiguration().locale; mAccessPoints = accessPointController; mDataUsageController = dataUsageController; mDataUsageController.setNetworkController(this); // TODO: Find a way to move this into DataUsageController. mDataUsageController.setCallback(new DataUsageController.Callback() { @Override public void onMobileDataEnabled(boolean enabled) { mCallbackHandler.setMobileDataEnabled(enabled); notifyControllersMobileDataChanged(); } }); mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature, mCallbackHandler, this, mWifiManager, trackerFactory, mReceiverHandler);
注册广播
@VisibleForTesting void registerListeners() { for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); mobileSignalController.registerListener(); } if (mSubscriptionListener == null) { mSubscriptionListener = new SubListener(mBgLooper); } mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener); // broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(Intent.ACTION_SERVICE_STATE); filter.addAction(Intent.ACTION_SIM_STATE_CHANGED); filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED); filter.addAction(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); mListening = true; // Initial setup of connectivity. Handled as if we had received a sticky broadcast of // ConnectivityManager.CONNECTIVITY_ACTION. mReceiverHandler.post(this::updateConnectivity); // Initial setup of WifiSignalController. Handled as if we had received a sticky broadcast // of WifiManager.WIFI_STATE_CHANGED_ACTION or WifiManager.NETWORK_STATE_CHANGED_ACTION mReceiverHandler.post(mWifiSignalController::fetchInitialState); // Initial setup of mLastServiceState. Only run if there is no service state yet. // Each MobileSignalController will also get their corresponding mReceiverHandler.post(() -> { if (mLastServiceState == null) { mLastServiceState = mPhone.getServiceState(); if (mMobileSignalControllers.size() == 0) { recalculateEmergency(); } } }); updateMobileControllers(); // Initial setup of emergency information. Handled as if we had received a sticky broadcast // of TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED. mReceiverHandler.post(this::recalculateEmergency); }
当收到广播时,更新图标
@Override public void onReceive(Context context, Intent intent) { if (true) { Log.d(TAG, "onReceive: intent=" + intent); } final String action = intent.getAction(); mLogBuffer.log( TAG, LogLevel.INFO, logMessage -> { logMessage.setStr1(action); return Unit.INSTANCE; }, logMessage -> String.format( Locale.US, "Received broadcast with action \"%s\"", logMessage.getStr1())); switch (action) { case ConnectivityManager.CONNECTIVITY_ACTION: updateConnectivity(); break; case Intent.ACTION_AIRPLANE_MODE_CHANGED: refreshLocale(); updateAirplaneMode(false); break; case TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED: // We are using different subs now, we might be able to make calls. recalculateEmergency(); break; case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED: // Notify every MobileSignalController so they can know whether they are the // data sim or not. for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController controller = mMobileSignalControllers.valueAt(i); controller.handleBroadcast(intent); } mConfig = Config.readConfig(mContext); mReceiverHandler.post(this::handleConfigurationChanged); break; case TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED: { // Notify the relevant MobileSignalController of the change int subId = intent.getIntExtra( TelephonyManager.EXTRA_SUBSCRIPTION_ID, INVALID_SUBSCRIPTION_ID ); if (SubscriptionManager.isValidSubscriptionId(subId)) { if (mMobileSignalControllers.indexOfKey(subId) >= 0) { mMobileSignalControllers.get(subId).handleBroadcast(intent); } } } break; case Intent.ACTION_SIM_STATE_CHANGED: // Avoid rebroadcast because SysUI is direct boot aware. if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) { break; } // Might have different subscriptions now. updateMobileControllers(); break; case Intent.ACTION_SERVICE_STATE: mLastServiceState = ServiceState.newFromBundle(intent.getExtras()); if (mMobileSignalControllers.size() == 0) { // If none of the subscriptions are active, we might need to recalculate // emergency state. recalculateEmergency(); } break; case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED: mConfig = Config.readConfig(mContext); mReceiverHandler.post(this::handleConfigurationChanged); break; case Settings.Panel.ACTION_INTERNET_CONNECTIVITY: mMainHandler.post(() -> mInternetDialogFactory.create(true, mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi(), null /* view */)); break; default: int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, INVALID_SUBSCRIPTION_ID); if (SubscriptionManager.isValidSubscriptionId(subId)) { if (mMobileSignalControllers.indexOfKey(subId) >= 0) { mMobileSignalControllers.get(subId).handleBroadcast(intent); } else { // Can't find this subscription... We must be out of date. updateMobileControllers(); } } else { // No sub id, must be for the wifi. mWifiSignalController.handleBroadcast(intent); } break; } }