Android8.0 SystemUI 状态栏信号图标

Android 状态栏信号更新架构

状态栏上信号区域在电池图标的左侧包括 ,ethernet,wifi,sim,airplane等,该区域对应的View为SignalClusterView,其负责显示以上信号图标的显示

Android8.0 SystemUI 状态栏信号图标_第1张图片

图中红框部分就是SignalClusterView

SignalClusterView

// Intimately tied to the design of res/layout/signal_cluster_view.xml
public class SignalClusterView extends LinearLayout implements NetworkControllerImpl.SignalCallback,
        SecurityController.SecurityControllerCallback, Tunable,
        DarkReceiver {

其实现了NetworkControllerImpl.SignalCallback接口,根据名称可以看出信号图标更新的逻辑主要靠回调接口完成.

SignalCallback接口定义在NetworkControllerImpl实现的接口NetworkController中
NetworkController

public interface SignalCallback {
    // 设置wifi图标
    default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
            boolean activityIn, boolean activityOut, String description, boolean isTransient) {}

    default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
            int networkIcon, int volteType, int qsType, boolean activityIn, boolean activityOut,
            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) {}
}

根据每个方法的名称即可看出其具体作用,比如设置wifi图标,设置数据流量图标,设置是否为飞行模式等等.

那具体这些方法如何调用,我们便可从NetworkControllerImpl入手.
NetworkControllerImpl继承自BroadcastReceiver,猜想就是通过接受各个网络状态的广播然后去进行进一步更新状态,让我们一探究竟
其注册了如下广播

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

可以看出接受了关于网络信号相关的广播,收到广播会在onReceive()方法中处理
NetworkControllerImpl

@Override
public void onReceive(Context context, Intent intent) {
    if (CHATTY) {
        Log.d(TAG, "onReceive: intent=" + intent);
    }
    final String action = intent.getAction();
    if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
            action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
        updateConnectivity();
    } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
        refreshLocale();
        updateAirplaneMode(false);
    } ...
    } else {
        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.
			// 处理wifi状态改变
            mWifiSignalController.handleBroadcast(intent);
        }
    }
}

在开篇的图片中可以看到wifi图标本来包含上下行图标,但左侧还有独立的上下行图标,我们就以去掉左侧的上下行图标为例,如果wifi状态改变,则会走到上面代码的mWifiSignalController.handleBroadcast(intent);处

WifiSignalController

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); // 将intent中wifi状态交给wifiTracker
        mCurrentState.enabled = mWifiTracker.enabled;
        mCurrentState.connected = mWifiTracker.connected;
        mCurrentState.ssid = mWifiTracker.ssid;
        mCurrentState.rssi = mWifiTracker.rssi;
        mCurrentState.level = mWifiTracker.level;
		// 由父类进一步调用notifyListeners(mCallbackHandler);来交由具体子类完成 ,这里就是WifiSignalController了,该出代码不贴出了
        notifyListenersIfNecessary(); 
    }

	@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 ? mCurrentStateNetworkController.ssid : null;
        boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
        String contentDescription = getStringIfExists(getContentDescription());
        if (mCurrentState.inetCondition == 0) {
            contentDescription +=
                    ("," + mContext.getString(R.string.accessibility_quick_settings_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);
    }
}

notifyListeners中的callback是在创建WifiSignalController创建时传入的,WifiSignalController在NetworkControllerImpl构造方法中创建的,
该callback是直接new了一个CallbackHandler对象,其实现了SignalCallback

CallbackHandler

// 所有实现了SignalCallback并注册过来的集合
private final ArrayList<SignalCallback> mSignalCallbacks = new ArrayList<>();

@Override
public void setWifiIndicators(final boolean enabled, final IconState statusIcon,
        final IconState qsIcon, final boolean activityIn, final boolean activityOut,
        final String description, boolean isTransient) {
    post(new Runnable() {
        @Override
        public void run() {
            for (SignalCallback callback : mSignalCallbacks) {
				// 利用多态调用setWifiIndicators
                callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
                        description, isTransient);
            }
        }
    });
}

CallbackHandler维护了所有需要监听的SignalCallback接口对象,我们的SignalClusterView就实现了该接口。该类中持有NetWorkController对象

SignalClusterView

public SignalClusterView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
	...
    mNetworkController = Dependency.get(NetworkController.class); 
    updateActivityEnabled();
	...
}

所有Controller都由Dependency管理,SystemUI启动后就会调用子类的start方法,Dependency会维护所有的Controller对象,具体如下
Dependency

public class Dependency extends SystemUI {
	@Override
    public void start() {
        sDependency = this;
        ....
        mProviders.put(BluetoothController.class, () ->
                new BluetoothControllerImpl(mContext, getDependency(BG_LOOPER)));

        mProviders.put(LocationController.class, () ->
                new LocationControllerImpl(mContext, getDependency(BG_LOOPER)));

        mProviders.put(RotationLockController.class, () ->
                new RotationLockControllerImpl(mContext));
		// 将NetworkControllerImpl由mProviders管理,
        mProviders.put(NetworkController.class, () ->
                new NetworkControllerImpl(mContext, getDependency(BG_LOOPER),
                        getDependency(DeviceProvisionedController.class)));
		...
}

知道了CallbackHandler中callback来历,继续看callback.setWifiIndicators继续分析
SignalClusterView

public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
        boolean activityIn, boolean activityOut, String description, boolean isTransient) {
    mWifiVisible = statusIcon.visible && !mBlockWifi;
    mWifiStrengthId = statusIcon.icon;
    mWifiDescription = statusIcon.contentDescription;
	// activityIn标识是否为wifi下行
	// mActivityEnabled 是否支持图标显示
	// mWifiVisible wifi图标是否可见
    mWifiIn = activityIn && mActivityEnabled && mWifiVisible; 
    mWifiOut = activityOut && mActivityEnabled && mWifiVisible;
    apply();
}

如果要去掉wifi图标左侧上下行图标,mActivityEnabled改为不支持即可,其是在config中进行配置
vendor/mediatek/proprietary/packages/apps/SystemUI/res/values/config.xml


<bool name="config_showActivity">falsebool>

至此整个分析结束了,总结下

SignalClusterView是信号区域的View,其实现了NetworkControllerImpl.SignalCallback接口,然后注册到NetworkController,其具体实现类NetworkControllerImpl会根据WIFI,SIM等状态广播来进一步派发给具体的Controller,例如WifiSignalController,每个Controller只与CallbackHandler交互,然后CallbackHandler继续转交给维护的SignalCallback接口的具体实现类,例如SingalClusterView

你可能感兴趣的:(Android开发)