Android 10.0 顶部状态栏体系图标表现分析

源代码 2024-9-15 13:42:47 84 0 来自 中国
学习条记:SystemUI StatusBar 手机信号相干图标的表现和更新流程分析
这里StatuBar的创建就不说了,前面已经说过了。
SystemUI中StatusBar的图标控制器实现类为StatusBarIconControllerImpl,其继承了StatusBarIconController的接口,用于跟踪全部图标的状态,并将对应的状态发送给注册的图标管理器(IconManagers)。当我们在StatusBar中获取到它的实例后,还会将它传给PhoneStatusBarPolicy和StatusBarSignalPolicy对象。PhoneStatusBarPolicy控制启动时装载哪些图标(蓝牙,定位等),而StatusBarSignalPolicy控制网络信号图标(移动网络,WiFi,以太网)的变革。
一起来看 StatuBar 的 start() 方法:
@Overridepublic void start() {        // 省略部门代码......    // 创建整个SystemUI视图并添加到WindowManager中    createAndAddWindows();//这个重点方法,创建相干的视图    // 省略部门代码......    // Lastly, call to the icon policy to install/update all the icons.    mIconPolicy.init();    mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);    // 省略部门代码......}这里的 mIconPolicy 就是 PhoneStatusBarPolicy对象,mSignalPolicy  就是 StatusBarSignalPolicy 对象。我们这里以 StatusBarSignalPolicy  为例去研究。
StatusBarSignalPolicy实现了NetworkControllerImpl.SignalCallback接口,SignalCallback接口界说在NetworkControllerImpl实现的接口NetworkController中。
// frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java    @Inject    public NetworkControllerImpl(Context context, @Background Looper bgLooper,            DeviceProvisionedController deviceProvisionedController,            BroadcastDispatcher broadcastDispatcher, ConnectivityManager connectivityManager,            TelephonyManager telephonyManager, WifiManager wifiManager,            NetworkScoreManager networkScoreManager) {        this(context, connectivityManager,                telephonyManager,                wifiManager,                networkScoreManager,                SubscriptionManager.from(context), Config.readConfig(context), bgLooper,                new CallbackHandler(),                new AccessPointControllerImpl(context),                new DataUsageController(context),                new SubscriptionDefaults(),                deviceProvisionedController,                broadcastDispatcher);        mReceiverHandler.post(mRegisterListeners);    }    private final Runnable mRegisterListeners = new Runnable() {        @Override        public void run() {            registerListeners();        }    };    void registerListeners() {        for (int i = 0; i < mMobileSignalControllers.size(); i++) {            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);            mobileSignalController.registerListener();        }        if (mSubscriptionListener == null) {            mSubscriptionListener = new SubListener();        }        mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);        mPhone.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);        // broadcasts        IntentFilter filter = new IntentFilter();        // wifi相干        // wifi信号强度广播        filter.addAction(WifiManager.RSSI_CHANGED_ACTION);        // wifi状态变革广播        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);        // wifi毗连状态改变        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);                // 移动网络相干        // SIM卡状态改变        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);        mContext.registerReceiver(this, filter, null, mReceiverHandler);        mListening = true;        // 省略部门代码......        // 4.更新移动网络控制器        updateMobileControllers();    }在NetworkControllerImpl 的构造方法里,最终会调用到:registerListeners() 方法举行广播的注册。
广播处置惩罚:
    @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:                // 省略部门代码......                break;            case Intent.ACTION_AIRPLANE_MODE_CHANGED:                 // 省略部门代码......                break;            case TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:                // We are using different subs now, we might be able to make calls.                 // 省略部门代码......                break;            case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:                // Notify every MobileSignalController so they can know whether they are the                // data sim or not.                // 省略部门代码......                break;            case Intent.ACTION_SIM_STATE_CHANGED:                // Avoid rebroadcast because SysUI is direct boot aware.                // 省略部门代码......                break;            case Intent.ACTION_SERVICE_STATE:                // 省略部门代码......                break;            case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:                // 省略部门代码......                break;            case ImsManager.ACTION_IMS_SERVICE_UP:            case ImsManager.ACTION_IMS_SERVICE_DOWN:                // 省略部门代码......                break;            case ACTION_HIGH_DEF_AUDIO_SUPPORT:                // 省略部门代码......                break;            case ACTION_MODEM_CHANGE:                // 省略部门代码......                break;            default:                int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,                        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 {                     // wifi状态图标处置惩罚                    // No sub id, must be for the wifi.                    mWifiSignalController.handleBroadcast(intent);                }                break;        }    }这里以 wifi状态图标处置惩罚 为例;接下来看WifiSignalController#handleBroadcast():
// frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java     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;        notifyListenersIfNecessary();    }在WifiSignalController#handleBroadcast()方法中,就两个实现,一个是获取 WiFi 的状态,一个是关照更新状态。
我们直接看关照SignalController# notifyListenersIfNecessary() :
// frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java     public void notifyListenersIfNecessary() {        if (isDirty()) {            saveLastState();    // 保持此时的状态            notifyListeners();    // 关照监听器        }    }    public final void notifyListeners() {        notifyListeners(mCallbackHandler);    }    public abstract void notifyListeners(SignalCallback callback);notifyListener()方法的实如今WifiSignalController类中:
// frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java    @Override    public void notifyListeners(SignalCallback callback) {        // only show wifi in the cluster if connected or if wifi-only        boolean visibleWhenEnabled = mContext.getResources().getBoolean(                R.bool.config_showWifiIndicatorWhenEnabled);        boolean wifiVisible = mCurrentState.enabled && (                (mCurrentState.connected && mCurrentState.inetCondition == 1)                        || !mHasMobileDataFeature || mWifiTracker.isDefaultNetwork                        || visibleWhenEnabled);        String wifiDesc = mCurrentState.connected ? mCurrentState.ssid : null;        boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;        String contentDescription = getTextIfExists(getContentDescription()).toString();        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,                mWifiTracker.isCaptivePortal ? R.drawable.ic_qs_wifi_disconnected                        : getQsCurrentIconId(), contentDescription);       // callback为 CallbackHandler对象        callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,                ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,                wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);    }可以看到,这里回调了StatusBarSignalPolicy#setWifiIndicators() 方法:
// frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/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);        }    }通过StatusBarIconController接口设置图标的套路都是一样的:

  • 获取图标名字
  • 监听变乱
  • 通过StatusBarIconControllerImpl相应的方法设置图标。
接下来再看StatusBarIconControllerImpl#setSignalIcon():
    /**     * 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);        }    }起首设置WiFi的状态信息,遍历mIconGroups分别实验StatusBarIconController接口中静态类IconManager中的onIconAdded()和onSetIconHolder()的回调。
IconManager用于将信息从StatusBarIconController转换为ViewGroup中的ImageViews(com.android.systemui.statusbar.AlphaOptimizedImageView)。
接着看IconManager中的onIconAdded()和onSetIconHolder()方法:这两个方法一个用于添加、一个用于更新。
public interface StatusBarIconController {    ....    public static class DarkIconManager extends IconManager {        ....        public DarkIconManager(LinearLayout linearLayout) {            // 将布局传入IconManager            super(linearLayout);            mIconHPadding = mContext.getResources().getDimensionPixelSize(                    R.dimen.status_bar_icon_padding);            mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);        }        ....        @Override        protected void onIconAdded(int index, String slot, boolean blocked,                                   StatusBarIconHolder holder) {            // 调用到父类的addHolder方法            StatusIconDisplayable view = addHolder(index, slot, blocked, holder);            ....        }    }        public static class IconManager implements DemoMode {        ....        protected final ViewGroup mGroup;        protected final Context mContext;        public IconManager(ViewGroup group) {            mGroup = group;            mContext = group.getContext();            mIconSize = mContext.getResources().getDimensionPixelSize(                    R.dimen.status_bar_height);            ....        }        ....        protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,                                                  StatusBarIconHolder holder) {            switch (holder.getType()) {                case TYPE_ICON:                    return addIcon(index, slot, blocked, holder.getIcon());                case TYPE_WIFI:                    return addSignalIcon(index, slot, holder.getWifiState());                case TYPE_MOBILE:                    return addMobileIcon(index, slot, holder.getMobileState());            }            return null;        }        @VisibleForTesting        protected StatusBarWifiView addSignalIcon(int index, String slot, WifiIconState state) {            // 创建一个StatusBarWifiView             StatusBarWifiView view = onCreateStatusBarWifiView(slot);            view.applyWifiState(state);            // 将view 添加进ViewGroup            mGroup.addView(view, index, onCreateLayoutParams());            if (mIsInDemoMode) {                mDemoStatusIcons.addDemoWifiView(state);            }            return view;        }        private StatusBarWifiView onCreateStatusBarWifiView(String slot) {            StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, slot);            return view;        }            ....        public void onSetIconHolder(int viewIndex, StatusBarIconHolder holder) {            switch (holder.getType()) {                case TYPE_ICON:                    onSetIcon(viewIndex, holder.getIcon());                    return;                case TYPE_WIFI:                    onSetSignalIcon(viewIndex, holder.getWifiState());                    return;                case TYPE_MOBILE:                    onSetMobileIcon(viewIndex, holder.getMobileState());                default:                    break;            }        }        public void onSetSignalIcon(int viewIndex, WifiIconState state) {            StatusBarWifiView wifiView = (StatusBarWifiView) mGroup.getChildAt(viewIndex);            if (wifiView != null) {                wifiView.applyWifiState(state);            }            if (mIsInDemoMode) {                mDemoStatusIcons.updateWifiState(state);            }        }        ....    }    }这里根据差异的StatusBarIconHolder范例,设置差异的网络Icon,上面列出了 Wifi 图标相干的方法。
SystemUI状态栏图标根据源码可大要分为三种:
  1. StatusBarIconView
  2. StatusBarWifiView
  3. StatusBarMobileView
这里告急以Wifi 相干图标(StatusBarWifiView)举行分析,添加Icon时起首会创建一个
StatusBarWifiView,然后调用StatusBarWifiView的applyWifiState更新其表现状态,末了将其加入到CollapsedStatusBarFragment中放置Icon的ViewGroup中,如许就完成了添加过程;
再来看看 CollapsedStatusBarFragment:
// SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.javapublic class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {    ....    private DarkIconManager mDarkIconManager;    ....    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,            Bundle savedInstanceState) {        return inflater.inflate(R.layout.status_bar, container, false);    }    @Override    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {        ....        // 这里可以看出status_bar布局中的statusIcons就是我们展示各种Icon的地域        mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));        mDarkIconManager.setShouldLog(true);        Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);        ....       }}增补:

  notifyListenersIfNecessary()在其父类SignalController中界说,
// SignalController.java    private final CallbackHandler mCallbackHandler;    public void notifyListenersIfNecessary() {        if (isDirty()) {            saveLastState();            notifyListeners();        }    }    // 在这里留意了,在这里的的参数是 CallbackHandler 的对象    public final void notifyListeners() {        notifyListeners(mCallbackHandler);    }// callback 则是 CallbackHandler 的对象。  public abstract void notifyListeners(SignalCallback callback);  CallbackHandler维护了全部须要监听的SignalCallback接口对象,我们的StatusBarSignalPolicy就实现了该接口。
  StatusBarSignalPolicy告急实验网络图标的革新动作,着实现了NetworkControllerImpl.SignalCallback接口,然后注册到NetworkController,其具体实现类NetworkControllerImpl会根据WIFI,SIM等状态广播来进一步派发给具体的Controller,比方WifiSignalController,每个Controller只与CallbackHandler交互,然后CallbackHandler继承转交给维护的SignalCallback接口的具体实现类,比方StatusBarSignalPolicy
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 22:33, Processed in 0.140814 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表