Android P SystemUI之StatusBar Wifi图标更新逻辑
相关源码:
\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中。
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。
CollapsedStatusBarFragment.java
private DarkIconManager mDarkIconManager;@Overridepublic 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.java
StatusBarIconController是一个接口,并且包含一个DarkIconManager的内部类,
Dependency.java
Dependency也是在SystemBars中启动的,执行如下:
@Overridepublic void start() {//省略一部分代码//... mProviders.put(StatusBarIconController.class, () -> new StatusBarIconControllerImpl(mContext));//省略一部分代码//...}
我们只关心StatusBarIconController这一块,实现的是StatusBarIconControllerImpl。
StatusBarIconControllerImpl.java
private final ArrayList<IconManager> mIconGroups = new ArrayList<>();@Overridepublic 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 */@Overridepublic 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); }}@Overridepublic 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,蓝牙等。
StatusBarSignalPolicy.java
@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,java
NetworkController包含了接口SignalCallback
WifiSignalController.java
@Overridepublic 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.java
NetworkControllerImpl实现了接口NetworkController,并且保存了StatusBarSignalPolicy的回调对象,监听了wifi状态变化。
NetworkControllerImpl继承了BroadcastReceiver,在onReceive中接收广播。
onReceive()监听了各种状态的变化。
@Overridepublic 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);
WifiIcons.java
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
更多相关文章
- android 获取以太网的连接状态
- android 判断网络连接状态
- 各Android版本WifiStateMachine状态机
- android 蓝牙打印程序源代码
- 如何修改 Android 状态栏高度?
- Android菜鸟的成长笔记(15)—— Android中的状态保存探究(下)
- Android 蓝牙开发(整理大全)
- android 实现根据receiver的注册状态 进行register或unregister
- Android去掉状态栏和标题栏的两种方式