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;
@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.java

StatusBarIconController是一个接口,并且包含一个DarkIconManager的内部类,

Dependency.java

Dependency也是在SystemBars中启动的,执行如下:

@Override
public void start() {
	//省略一部分代码
	//...
    mProviders.put(StatusBarIconController.class, () ->
            new StatusBarIconControllerImpl(mContext));
	//省略一部分代码
	//...
}

我们只关心StatusBarIconController这一块,实现的是StatusBarIconControllerImpl。

StatusBarIconControllerImpl.java

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,蓝牙等。

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_vpn);
    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

@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.java

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);

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

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunxiaolin2016

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值