Android10 SystemUI状态栏网络图标流程分析

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

各位看客老爷,记得关注奥

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值