Android 10 SystemUI网络图标刷新与显示
涉及文件目录:
android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
StatusBarSignalPolicy
public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallback,
SecurityController.SecurityControllerCallback, Tunable {}
其实现了NetworkControllerImpl.SignalCallback接口,根据名称可以看出信号图标更新的逻辑主要靠回调接口完成
NetworkController
SignalCallback接口定义在NetworkControllerImpl实现的接口NetworkController中
public interface SignalCallback {
default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description, boolean isTransient,
String statusLabel) {}
default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, int volteIcon,
String typeContentDescription, String description, boolean isWide,
int subId, boolean roaming) {}
default void setSubs(List<SubscriptionInfo> subs) {}
default void setNoSims(boolean show, boolean simDetected) {}
default void setEthernetIndicators(IconState icon) {}
default void setIsAirplaneMode(IconState icon) {}
default void setMobileDataEnabled(boolean enabled) {}
}
public interface EmergencyListener {
void setEmergencyCallsOnly(boolean emergencyOnly);
}
public static class IconState {
public final boolean visible;
public final int icon;
public final String contentDescription;
public IconState(boolean visible, int icon, String contentDescription) {
this.visible = visible;
this.icon = icon;
this.contentDescription = contentDescription;
}
public IconState(boolean visible, int icon, int contentDescription,
Context context) {
this(visible, icon, context.getString(contentDescription));
}
}
我们根据每个方法的名称即可看出其具体作用,比如设置wifi图标,设置Ethernet图标,设置Moblie数据流量图标,设置是否为飞行模式等等.
NetworkControllerImp实现了NetworkController部分接口。而NetworkControllerImpl主要根据intent广播来执行刷新图标的具体逻辑。
NetworkControllerImp
注册广播:
// broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
mContext.registerReceiver(this, filter, null, mReceiverHandler);
mListening = true
处理广播:
@Override
public void onReceive(Context context, Intent intent) {
if (CHATTY) {
Log.d(TAG, "onReceive: intent=" + intent);
}
final String action = intent.getAction();
switch (action) {
case ConnectivityManager.CONNECTIVITY_ACTION:
case ConnectivityManager.INET_CONDITION_ACTION: //Ethernet认证通过之后,会发送此广播
//Ethernet连接过程中图标<--->!,收到此广播之后,图标会更新为<--->
updateConnectivity();
break;
case Intent.ACTION_AIRPLANE_MODE_CHANGED: //飞行模式
refreshLocale();
updateAirplaneMode(false);
break;
case TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
// We are using different subs now, we might be able to make calls.
recalculateEmergency();
break;
case TelephonyIntents.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 TelephonyIntents.ACTION_SIM_STATE_CHANGED:
// Avoid rebroadcast because SysUI is direct boot aware.
if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
break;
}
// Might have different subscriptions now.
updateMobileControllers();
break;
case TelephonyIntents.ACTION_SERVICE_STATE_CHANGED:
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;
default:
int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
SubscriptionManager.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); //wifi状态图标处理
}
break;
}
}
从SystemUI状态栏显示的wifi图标来看,其左侧有上下行图标, 如果此时wifi状态发送改变,则会执行 mWifiSignalController.handleBroadcast(intent);
WifiSignalController
首先会将此intent消息交由wifitracker处理,之后会调用notifyListenersIfNecessary()。
public class WifiSignalController extends
SignalController<WifiSignalController.WifiState, SignalController.IconGroup>
/**
* Extract wifi state directly from broadcasts about changes in wifi state.
*/
public void handleBroadcast(Intent intent) {
mWifiTracker.handleBroadcast(intent);
mCurrentState.enabled = mWifiTracker.enabled;
mCurrentState.connected = mWifiTracker.connected;
mCurrentState.ssid = mWifiTracker.ssid;
mCurrentState.rssi = mWifiTracker.rssi;
mCurrentState.level = mWifiTracker.level;
mCurrentState.statusLabel = mWifiTracker.statusLabel;
mCurrentState.wifiGenerationVersion = mWifiTracker.wifiGeneration;
mCurrentState.isReady = (mWifiTracker.vhtMax8SpatialStreamsSupport
&& mWifiTracker.he8ssCapableAp);
updateIconGroup();
notifyListenersIfNecessary();//处理见SignalController,最终会执行如下方法块
}
@Override
public void notifyListeners(SignalCallback callback) {
// only show wifi in the cluster if connected or if wifi-only
boolean wifiVisible = !ethernetStatus() && mCurrentState.enabled
&& (mCurrentState.connected || !mHasMobileData);
String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
String contentDescription = getStringIfExists(getContentDescription());
if (mCurrentState.inetCondition == 0) {
contentDescription += ("," + mContext.getString(R.string.data_connection_no_internet));
}
IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
contentDescription);
//callback为CallbackHandler对象
callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
}
其中notifyListenersIfNecessary()在其父类SignalController中定义
SignalController
mCallbackHandler = callbackHandler; //SignalController构造时赋值
public void notifyListenersIfNecessary() {
if (isDirty()) {
saveLastState();
notifyListeners();
}
}
public final void notifyListeners() {
notifyListeners(mCallbackHandler);
}
/**
* Trigger callbacks based on current state. The callbacks should be completely
* based on current state, and only need to be called in the scenario where
* mCurrentState != mLastState.
*/
public abstract void notifyListeners(SignalCallback callback);
notifyListeners中的callback是在创建WifiSignalController创建时传入的,WifiSignalController在NetworkControllerImpl构造方法中创建的,
该callback是直接new了一个CallbackHandler对象,其实现了SignalCallback
CallbackHandler
//定义SignalCallback的对象集合
private final ArrayList<SignalCallback> mSignalCallbacks = new ArrayList<>();
//当调用setListening时,会将此callback对象添加到list列表中
public void setListening(SignalCallback listener, boolean listening) {
obtainMessage(MSG_ADD_REMOVE_SIGNAL, listening ? 1 : 0, 0, listener).sendToTarget();
}
//处理handler message
case MSG_ADD_REMOVE_SIGNAL:
if (msg.arg1 != 0) {
mSignalCallbacks.add((SignalCallback) msg.obj);
} else {
mSignalCallbacks.remove((SignalCallback) msg.obj);
}
break;
@Override
public void setWifiIndicators(final boolean enabled, final IconState statusIcon,
final IconState qsIcon, final boolean activityIn, final boolean activityOut,
final String description, boolean isTransient, String secondaryLabel) {
post(new Runnable() {
@Override
public void run() {
for (SignalCallback callback : mSignalCallbacks) {
callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
description, isTransient, secondaryLabel);
}
}
});
}
CallbackHandler维护了所有需要监听的SignalCallback接口对象,我们的StatusBarSignalPolicy就实现了该接口。该类中持有NetWorkController对象
StatusBarSignalPolicy
public StatusBarSignalPolicy(Context context, StatusBarIconController iconController) {
mContext = context;
mSlotAirplane = mContext.getString(com.android.internal.R.string.status_bar_airplane);
mSlotMobile = mContext.getString(com.android.internal.R.string.status_bar_mobile);
mSlotWifi = mContext.getString(com.android.internal.R.string.status_bar_wifi);
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
mIconController = iconController;
mNetworkController = Dependency.get(NetworkController.class);
mSecurityController = Dependency.get(SecurityController.class);
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
mNetworkController.addCallback(this);
mSecurityController.addCallback(this);
}
其中所有Controller都由Dependency管理,SystemUI启动后就会调用子类的start方法,Dependency会维护所有的Controller对象
Dependency
@Override
public void start() {
mProviders.put(NetworkController.class, mNetworkController::get);
最终会执行StatusBarSignalPolicy的setWifiIndicators方法执行图标的刷新动作
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description, boolean isTransient,
String statusLabel) {
// activityIn标识是否为wifi下行
// mActivityEnabled 是否支持图标显示
// mWifiVisible wifi图标是否可见
boolean visible = statusIcon.visible && !mBlockWifi;
boolean in = activityIn && mActivityEnabled && visible;
boolean out = activityOut && mActivityEnabled && visible;
WifiIconState newState = mWifiIconState.copy();
newState.visible = visible;
newState.resId = statusIcon.icon;
newState.activityIn = in;
newState.activityOut = out;
newState.slot = mSlotWifi;
newState.airplaneSpacerVisible = mIsAirplaneMode;
newState.contentDescription = statusIcon.contentDescription;
MobileIconState first = getFirstMobileState();
newState.signalSpacerVisible = first != null && first.typeId != 0;
updateWifiIconWithState(newState);
mWifiIconState = newState;
}
如果要去掉wifi图标左侧上下行图标,mActivityEnabled改为不支持即可,其是在config中进行配置
android/frameworks/base/packages/SystemUI/res/values/config.xml
<bool name="config_showActivity">true</bool> //true表示支持
总结
StatusBarSignalPolicy主要执行网络图标的刷新动作,其实现了NetworkControllerImpl.SignalCallback接口,然后注册到NetworkController,其具体实现类NetworkControllerImpl会根据WIFI,SIM等状态广播来进一步派发给具体的Controller,例如WifiSignalController,每个Controller只与CallbackHandler交互,然后CallbackHandler继续转交给维护的SignalCallback接口的具体实现类,例如StatusBarSignalPolicy
各位看客老爷,记得关注奥