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
@VisibleForTestingNetworkControllerImpl(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;// telephonymPhone = telephonyManager;// wifimWifiManager = 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() {@Overridepublic void onMobileDataEnabled(boolean enabled) {mCallbackHandler.setMobileDataEnabled(enabled);notifyControllersMobileDataChanged();}});mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,mCallbackHandler, this, mWifiManager, trackerFactory,mReceiverHandler);
注册广播
@VisibleForTestingvoid 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);// broadcastsIntentFilter 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_ACTIONmReceiverHandler.post(mWifiSignalController::fetchInitialState);// Initial setup of mLastServiceState. Only run if there is no service state yet.// Each MobileSignalController will also get their correspondingmReceiverHandler.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);}
当收到广播时,更新图标
@Overridepublic 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 changeint 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;}}