相关源码:
\frameworks\base\packages\SystemUI\src\com\android\systemui\Dependency.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\StatusBarSignalPolicy.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\CollapsedStatusBarFragment.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\StatusBarIconController.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\StatusBarIconControllerImpl.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\NetworkController.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\WifiSignalController.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\SignalController.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\NetworkControllerImpl.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\WifiIcons.java
在文章中《Android P SystemUI之StatusBar UI布局status_bar.xml解析》讲到,wifi,蓝牙等系统图标的UI是在system_icons.xml中。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/system_icons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.android.systemui.statusbar.phone.StatusIconContainer
android:id="@+id/statusIcons"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:paddingEnd="@dimen/signal_cluster_battery_padding"
android:gravity="center_vertical"
android:orientation="horizontal"/>
<com.android.systemui.BatteryMeterView
android:id="@+id/battery"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:clipToPadding="false"
android:clipChildren="false" />
</LinearLayout>
关键点:android:id="@+id/statusIcons",我需要查看是哪里加载了statusIcons。
private DarkIconManager mDarkIconManager;
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mStatusBar = (PhoneStatusBarView) view;
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
mStatusBar.go(savedInstanceState.getInt(EXTRA_PANEL_STATE));
}
mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
mDarkIconManager.setShouldLog(true);
Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
mClockView = mStatusBar.findViewById(R.id.clock);
showSystemIconArea(false);
showClock(false);
initEmergencyCryptkeeperText();
initOperatorName();
}
关键点1: mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
关键点2:Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
这里创建了一个DarkIconManager,添加了statusIcons的view,并且添加到StatusBarIconController中。
StatusBarIconController是一个接口,并且包含一个DarkIconManager的内部类,
Dependency也是在SystemBars中启动的,执行如下:
@Override
public void start() {
//省略一部分代码
//...
mProviders.put(StatusBarIconController.class, () ->
new StatusBarIconControllerImpl(mContext));
//省略一部分代码
//...
}
我们只关心StatusBarIconController这一块,实现的是StatusBarIconControllerImpl。
private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
@Override
public void addIconGroup(IconManager group) {
mIconGroups.add(group);
List<Slot> allSlots = getSlots();
for (int i = 0; i < allSlots.size(); i++) {
Slot slot = allSlots.get(i);
List<StatusBarIconHolder> holders = slot.getHolderListInViewOrder();
boolean blocked = mIconBlacklist.contains(slot.getName());
for (StatusBarIconHolder holder : holders) {
int tag = holder.getTag();
int viewIndex = getViewIndex(getSlotIndex(slot.getName()), holder.getTag());
group.onIconAdded(viewIndex, slot.getName(), blocked, holder);
}
}
}
/**
* Signal icons need to be handled differently, because they can be
* composite views
*/
@Override
public void setSignalIcon(String slot, WifiIconState state) {
int index = getSlotIndex(slot);
if (state == null) {
removeIcon(index, 0);
return;
}
StatusBarIconHolder holder = getIcon(index, 0);
if (holder == null) {
holder = StatusBarIconHolder.fromWifiIconState(state);
setIcon(index, holder);
} else {
holder.setWifiState(state);
handleSet(index, holder);
}
}
@Override
public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
boolean isNew = getIcon(index, holder.getTag()) == null;
super.setIcon(index, holder);
if (isNew) {
addSystemIcon(index, holder);
} else {
handleSet(index, holder);
}
}
private void addSystemIcon(int index, StatusBarIconHolder holder) {
String slot = getSlotName(index);
int viewIndex = getViewIndex(index, holder.getTag());
boolean blocked = mIconBlacklist.contains(slot);
mIconLogger.onIconVisibility(getSlotName(index), holder.isVisible());
mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));
}
通过setSignalIcon设置系统图标,包括Wifi,蓝牙等。
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description, boolean isTransient,
String statusLabel) {
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;
}
private void updateWifiIconWithState(WifiIconState state) {
if (state.visible && state.resId > 0) {
mIconController.setSignalIcon(mSlotWifi, state);
mIconController.setIconVisibility(mSlotWifi, true);
} else {
mIconController.setIconVisibility(mSlotWifi, false);
}
}
setWifiIndicators()收到wifi状态变化后执行,调用updateWifiIconWithState()更新图标。
注册Wifi监听回调的地方:
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_);
mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
mIconController = iconController;
mNetworkController = Dependency.get(NetworkController.class);
mSecurityController = Dependency.get(SecurityController.class);
//注册wifi状态回调
mNetworkController.addCallback(this);
mSecurityController.addCallback(this);
}
NetworkController包含了接口SignalCallback
@Override
public void notifyListeners(SignalCallback callback) {
// only show wifi in the cluster if connected or if wifi-only
boolean wifiVisible = 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.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
}
回调执行了setWifiIndicators,去更新wifi状态。
NetworkControllerImpl实现了接口NetworkController,并且保存了StatusBarSignalPolicy的回调对象,监听了wifi状态变化。
NetworkControllerImpl继承了BroadcastReceiver,在onReceive中接收广播。
onReceive()监听了各种状态的变化。
@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:
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);
}
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);
}
break;
}
}
关注点: mWifiSignalController.handleBroadcast(intent);
Wifi图标显示在WifiIcons定义如下:
public class WifiIcons {
static final int[][] WIFI_SIGNAL_STRENGTH = {
{ R.drawable.stat_sys_wifi_signal_0,
R.drawable.stat_sys_wifi_signal_1,
R.drawable.stat_sys_wifi_signal_2,
R.drawable.stat_sys_wifi_signal_3,
R.drawable.stat_sys_wifi_signal_4 },
{ R.drawable.stat_sys_wifi_signal_0_fully,
R.drawable.stat_sys_wifi_signal_1_fully,
R.drawable.stat_sys_wifi_signal_2_fully,
R.drawable.stat_sys_wifi_signal_3_fully,
R.drawable.stat_sys_wifi_signal_4_fully }
};
public static final int[][] QS_WIFI_SIGNAL_STRENGTH = {
{ R.drawable.ic_qs_wifi_0,
R.drawable.ic_qs_wifi_1,
R.drawable.ic_qs_wifi_2,
R.drawable.ic_qs_wifi_3,
R.drawable.ic_qs_wifi_4 },
{ R.drawable.ic_qs_wifi_full_0,
R.drawable.ic_qs_wifi_full_1,
R.drawable.ic_qs_wifi_full_2,
R.drawable.ic_qs_wifi_full_3,
R.drawable.ic_qs_wifi_full_4 }
};
static final int QS_WIFI_NO_NETWORK = R.drawable.ic_qs_wifi_no_network;
static final int WIFI_NO_NETWORK = R.drawable.stat_sys_wifi_signal_null;
static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
}
整理一下wifi信号发生的整个流程:
NetworkControllerImpl–>WifiSignalController–>SignalController–>WifiSignalController–>StatusBarSignalPolicy–>StatusBarIconController–>StatusBarIconControllerImpl–>CollapsedStatusBarFragment–>system_icons.xml
其中WifiSignalController