SystemUI系列文章

Android8.1 MTK平台 SystemUI源码分析之 Notification流程

Android8.1 MTK平台 SystemUI源码分析之 电池时钟刷新

Android 8.1平台SystemUI 导航栏加载流程解析

一、从布局说起

前面的文章分析过,网络信号栏这块属于 system_icon_area,里面包含蓝牙、wifi、VPN、网卡、SIM卡网络类型、

数据流量符号、SIM卡信号格、电池、时钟。

先来看下 system_icon_area 对应的布局文件 system_icons.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/system_icons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"> <com.android.keyguard.AlphaOptimizedLinearLayout
android:id="@+id/statusIcons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal"/> <include layout="@layout/signal_cluster_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/signal_cluster_margin_start"/> <com.android.systemui.BatteryMeterView
android:id="@+id/battery"
android:layout_height="match_parent"
android:layout_width="0dp"
/>
</LinearLayout>

看到里面的 signal_cluster_view.xml 正是我们要找的信号栏布局文件,内容有点多,下面只截取我们关心的

vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout\signal_cluster_view.xml

<com.android.systemui.statusbar.SignalClusterView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/signal_cluster"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingEnd="@dimen/signal_cluster_battery_padding"
>
... vpn ... 网卡 ... wifi 手机信号栏
<LinearLayout
android:id="@+id/mobile_signal_group"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
</LinearLayout> 未插入SIM卡
<FrameLayout
android:id="@+id/no_sims_combo"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:contentDescription="@string/accessibility_no_sims">
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="?attr/lightIconTheme"
android:id="@+id/no_sims"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/stat_sys_no_sims"
/>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="?attr/darkIconTheme"
android:id="@+id/no_sims_dark"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/stat_sys_no_sims"
android:alpha="0.0"
/>
</FrameLayout>
<View
android:id="@+id/wifi_airplane_spacer"
android:layout_width="@dimen/status_bar_airplane_spacer_width"
android:layout_height="4dp"
android:visibility="gone"
/> 飞行模式
<ImageView
android:id="@+id/airplane"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
</com.android.systemui.statusbar.SignalClusterView>

可以看到最外层是自定义 SignalClusterView,xml里包含了 vpn、网卡、wifi、手机信号栏、未插入SIM卡、飞行模式对应的 view,那么接下来看下 SignalClusterView 代码

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\SignalClusterView.java

public class SignalClusterView extends LinearLayout implements NetworkControllerImpl.SignalCallback, SecurityController.SecurityControllerCallback, Tunable,DarkReceiver 

public SignalClusterView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); Resources res = getResources();
mMobileSignalGroupEndPadding =
res.getDimensionPixelSize(R.dimen.mobile_signal_group_end_padding);
mMobileDataIconStartPadding =
res.getDimensionPixelSize(R.dimen.mobile_data_icon_start_padding);
mWideTypeIconStartPadding = res.getDimensionPixelSize(R.dimen.wide_type_icon_start_padding);
mSecondaryTelephonyPadding = res.getDimensionPixelSize(R.dimen.secondary_telephony_padding);
mEndPadding = res.getDimensionPixelSize(R.dimen.signal_cluster_battery_padding);
mEndPaddingNothingVisible = res.getDimensionPixelSize(
R.dimen.no_signal_cluster_battery_padding); TypedValue typedValue = new TypedValue();
res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
mIconScaleFactor = typedValue.getFloat();
//网络相关控制器
mNetworkController = Dependency.get(NetworkController.class);
//安全相关控制器
mSecurityController = Dependency.get(SecurityController.class);
updateActivityEnabled(); /// M: Add for Plugin feature @ {
mStatusBarExt = OpSystemUICustomizationFactoryBase.getOpFactory(context)
.makeSystemUIStatusBar(context);
/// @ }
mIsWfcEnable = SystemProperties.get("persist.mtk_wfc_support").equals("1");
}

看到 SignalClusterView 继承自 LinearLayout,实现了 NetworkController、SecurityController(这俩类控制图标的刷新逻辑)

构造方法中通过 Dependency.get() 实例化 NetworkController、SecurityController这俩核心

类,跟进 Dependent 类中大概看了下 get()方法,其实就是通过单例模式来进行管理,里面维护了一

个数据类型为 ArrayMap 的 DependencyProvider 集合对象,通过 put和 get 来存取。

接着回到 SignalClusterView 中看下控件都是怎么初始化的?

 @Override
protected void onFinishInflate() {
super.onFinishInflate(); mVpn = findViewById(R.id.vpn);
mEthernetGroup = findViewById(R.id.ethernet_combo);
mEthernet = findViewById(R.id.ethernet);
mEthernetDark = findViewById(R.id.ethernet_dark);
mWifiGroup = findViewById(R.id.wifi_combo);
mWifi = findViewById(R.id.wifi_signal);
mWifiDark = findViewById(R.id.wifi_signal_dark);
mWifiActivityIn = findViewById(R.id.wifi_in);
mWifiActivityOut= findViewById(R.id.wifi_out);
mAirplane = findViewById(R.id.airplane);
mNoSims = findViewById(R.id.no_sims);
mNoSimsDark = findViewById(R.id.no_sims_dark);
mNoSimsCombo = findViewById(R.id.no_sims_combo);
mWifiAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
mWifiSignalSpacer = findViewById(R.id.wifi_signal_spacer);
mMobileSignalGroup = findViewById(R.id.mobile_signal_group); maybeScaleVpnAndNoSimsIcons();
}

这里初始化了一堆刚刚布局文件里的控件,onFinishInflate() 在 xml 布局文件被加载完成后就会调

用,我们看到布局文件中都没有给控件设置对应的 background icon,而且有的 visibility 为

gone,那么信号栏图标是如何设置对应的icon和显示的呢?

二、SignalCluterView 详解

SignalCluterView 中调用频率很高的方法 apply() 就是幕后黑手,通过该方法控制一系列图标的更

新, 然而 SignalCallback 的如下每个回调最终都调用 apply()

1、setWifiIndicators() wifi开关状态、流量上下行

2、setMobileDataIndicators() 手机网络类型、信号强度、流量上下行、volte图标

3、setSubs() SIM卡识别结束

4、setNoSims() 未插入SIM卡状态

5、setEthernetIndicators() 网卡状态

6、setIsAirplaneMode() 飞行模式是否打开

7、setMobileDataEnabled() SIM卡数据流量是否开启

1、apply()

private void apply() {
if (mWifiGroup == null) return; //vpn图标
if (mVpnVisible) {
if (mLastVpnIconId != mVpnIconId) {
setIconForView(mVpn, mVpnIconId);
mLastVpnIconId = mVpnIconId;
}
mIconLogger.onIconShown(SLOT_VPN);
mVpn.setVisibility(View.VISIBLE);
} else {
mIconLogger.onIconHidden(SLOT_VPN);
mVpn.setVisibility(View.GONE);
}
if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE")); //网卡图标
if (mEthernetVisible) {
if (mLastEthernetIconId != mEthernetIconId) {
setIconForView(mEthernet, mEthernetIconId);
setIconForView(mEthernetDark, mEthernetIconId);
mLastEthernetIconId = mEthernetIconId;
}
mEthernetGroup.setContentDescription(mEthernetDescription);
mIconLogger.onIconShown(SLOT_ETHERNET);
mEthernetGroup.setVisibility(View.VISIBLE);
} else {
mIconLogger.onIconHidden(SLOT_ETHERNET);
mEthernetGroup.setVisibility(View.GONE);
} if (DEBUG) Log.d(TAG,
String.format("ethernet: %s",
(mEthernetVisible ? "VISIBLE" : "GONE")));
//wifi图标
if (mWifiVisible) {
if (mWifiStrengthId != mLastWifiStrengthId) {
setIconForView(mWifi, mWifiStrengthId);
setIconForView(mWifiDark, mWifiStrengthId);
mLastWifiStrengthId = mWifiStrengthId;
}
mIconLogger.onIconShown(SLOT_WIFI);
mWifiGroup.setContentDescription(mWifiDescription);
mWifiGroup.setVisibility(View.VISIBLE);
} else {
mIconLogger.onIconHidden(SLOT_WIFI);
mWifiGroup.setVisibility(View.GONE);
} if (DEBUG) Log.d(TAG,
String.format("wifi: %s sig=%d",
(mWifiVisible ? "VISIBLE" : "GONE"),
mWifiStrengthId));
//wifi数据上下行图标
mWifiActivityIn.setVisibility(mWifiIn ? View.VISIBLE : View.GONE);
mWifiActivityOut.setVisibility(mWifiOut ? View.VISIBLE : View.GONE); boolean anyMobileVisible = false;
/// M: Support for [Network Type on Statusbar]
/// A spacer is set between networktype and WIFI icon @ {
if (FeatureOptions.MTK_CTA_SET) {
anyMobileVisible = true;
}
/// @ }
//SIM 卡组图标
int firstMobileTypeId = 0;
for (PhoneState state : mPhoneStates) {
//PhoneState中的另一个apply()方法,对应网络类型、信号格等
if (state.apply(anyMobileVisible)) {
if (!anyMobileVisible) {
firstMobileTypeId = state.mMobileTypeId;
anyMobileVisible = true;
}
}
}
if (anyMobileVisible) {
mIconLogger.onIconShown(SLOT_MOBILE);
} else {
mIconLogger.onIconHidden(SLOT_MOBILE);
}
//飞行模式图标
if (mIsAirplaneMode) {
if (mLastAirplaneIconId != mAirplaneIconId) {
setIconForView(mAirplane, mAirplaneIconId);
mLastAirplaneIconId = mAirplaneIconId;
}
mAirplane.setContentDescription(mAirplaneContentDescription);
mIconLogger.onIconShown(SLOT_AIRPLANE);
mAirplane.setVisibility(VISIBLE);
} else {
mIconLogger.onIconHidden(SLOT_AIRPLANE);
mAirplane.setVisibility(View.GONE);
}
//wifi和飞行模式间隔
if (mIsAirplaneMode && mWifiVisible) {
mWifiAirplaneSpacer.setVisibility(View.VISIBLE);
} else {
mWifiAirplaneSpacer.setVisibility(View.GONE);
} if (((anyMobileVisible && firstMobileTypeId != 0) || mNoSimsVisible) && mWifiVisible) {
mWifiSignalSpacer.setVisibility(View.VISIBLE);
} else {
mWifiSignalSpacer.setVisibility(View.GONE);
}
//未插入SIM卡图标组
if (mNoSimsVisible) {
mIconLogger.onIconShown(SLOT_MOBILE);
mNoSimsCombo.setVisibility(View.VISIBLE);
if (!Objects.equals(mSimDetected, mNoSimsCombo.getTag())) {
mNoSimsCombo.setTag(mSimDetected);
/// M:alps03596830 Don't show lack of signal when airplane mode is on.
if (mSimDetected && !mIsAirplaneMode) {
SignalDrawable d = new SignalDrawable(mNoSims.getContext());
d.setDarkIntensity(0);
mNoSims.setImageDrawable(d);
mNoSims.setImageLevel(SignalDrawable.getEmptyState(4)); SignalDrawable dark = new SignalDrawable(mNoSims.getContext());
dark.setDarkIntensity(1);
mNoSimsDark.setImageDrawable(dark);
mNoSimsDark.setImageLevel(SignalDrawable.getEmptyState(4));
} else {
mNoSims.setImageResource(R.drawable.stat_sys_no_sims);
mNoSimsDark.setImageResource(R.drawable.stat_sys_no_sims);
}
}
} else {
mIconLogger.onIconHidden(SLOT_MOBILE);
mNoSimsCombo.setVisibility(View.GONE);
} /// M: Add for Plugin feature @ {
mStatusBarExt.setCustomizedNoSimsVisible(mNoSimsVisible);
mStatusBarExt.setCustomizedAirplaneView(mNoSimsCombo, mIsAirplaneMode);
/// @ } boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
|| anyMobileVisible || mVpnVisible || mEthernetVisible;
setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
}

通过上面的代码发现 apply 控制了 VPN、网卡、wifi、飞行模式、未插入SIM 这几种图标的显示和隐

藏,我们看到里面有另外一个 state.apply(anyMobileVisible) 用来控制 SIM卡相关的图标,接下

来看下都有哪些图标呢?

2、内部类 PhoneState

PhoneState 是 SignalClusterView 中一个内部类,控制volte、网络类型、数据是否打开、信号格

数、漫游等图标

private class PhoneState {
//SIM卡id
private final int mSubId;
//SIM卡组是否可见
private boolean mMobileVisible = false;
//信号格数图标、数据流量是否打开图标(关闭是X,打开是网络类型小图标4G/3G)
private int mMobileStrengthId = 0, mMobileTypeId = 0;
///M: Add for [Network Type and volte on Statusbar]
//网络类型图标
private int mNetworkIcon = 0;
//volte图标
private int mVolteIcon = 0; private int mLastMobileStrengthId = -1;
private int mLastMobileTypeId = -1;
private boolean mIsMobileTypeIconWide;
//网络类型描述,运营商类型,或只能拨打紧急号码
private String mMobileDescription, mMobileTypeDescription; //整个PhoneState根本局,SIM信号栏组
private ViewGroup mMobileGroup;
//信号格控件、流量图标控件、是否漫游控件
private ImageView mMobile, mMobileDark, mMobileType, mMobileRoaming;
public boolean mRoaming;
//手机流量上下行控件
private ImageView mMobileActivityIn;
private ImageView mMobileActivityOut; public boolean mActivityIn;
public boolean mActivityOut;
/// M: Add for new features @ {
// Add for [Network Type and volte on Statusbar]
//网络类型控件
private ImageView mNetworkType;
//volte控件
private ImageView mVolteType;
private boolean mIsWfcCase;
/// @ } /// M: Add for plugin features. @ {
private boolean mDataActivityIn, mDataActivityOut;
private ISystemUIStatusBarExt mPhoneStateExt;
/// @ } public PhoneState(int subId, Context context) {
//加载 mobile_signal_group_ext 布局文件
ViewGroup root = (ViewGroup) LayoutInflater.from(context)
.inflate(R.layout.mobile_signal_group_ext, null); /// M: Add data group for plugin feature. @ {
mPhoneStateExt = OpSystemUICustomizationFactoryBase.getOpFactory(context)
.makeSystemUIStatusBar(context);
mPhoneStateExt.addCustomizedView(subId, context, root);
/// @ } setViews(root);
mSubId = subId;
} //控件初始化
public void setViews(ViewGroup root) {
mMobileGroup = root;
mMobile = root.findViewById(R.id.mobile_signal);
mMobileDark = root.findViewById(R.id.mobile_signal_dark);
mMobileType = root.findViewById(R.id.mobile_type);
///M: Add for [Network Type and volte on Statusbar]
mNetworkType = (ImageView) root.findViewById(R.id.network_type);
mVolteType = (ImageView) root.findViewById(R.id.volte_indicator_ext);
mMobileRoaming = root.findViewById(R.id.mobile_roaming);
mMobileActivityIn = root.findViewById(R.id.mobile_in);
mMobileActivityOut = root.findViewById(R.id.mobile_out); // TODO: Remove the 2 instances because now the drawable can handle darkness.
mMobile.setImageDrawable(new SignalDrawable(mMobile.getContext()));
SignalDrawable drawable = new SignalDrawable(mMobileDark.getContext());
drawable.setDarkIntensity(1);
mMobileDark.setImageDrawable(drawable);
} public boolean apply(boolean isSecondaryIcon) {
Log.e(TAG, "apply() mMobileVisible = " + mMobileVisible
+ ", mIsAirplaneMode = " + mIsAirplaneMode
+ ", mIsWfcEnable = " + mIsWfcEnable
+ ", mIsWfcCase = " + mIsWfcCase
+ ", mVolteIcon = " + mVolteIcon);
if (mMobileVisible && !mIsAirplaneMode) {
Log.e(TAG, "apply() into this code 1.. mMobileStrengthId=="+mMobileStrengthId);
//设置信号格数
if (mLastMobileStrengthId != mMobileStrengthId) {
mMobile.getDrawable().setLevel(mMobileStrengthId);
mMobileDark.getDrawable().setLevel(mMobileStrengthId); mLastMobileStrengthId = mMobileStrengthId;
} //设置流量是否打开
if (mLastMobileTypeId != mMobileTypeId) {
if (!mPhoneStateExt.disableHostFunction()) {
mMobileType.setImageResource(mMobileTypeId);
}
mLastMobileTypeId = mMobileTypeId;
} mMobileGroup.setContentDescription(mMobileTypeDescription
+ " " + mMobileDescription);
mMobileGroup.setVisibility(View.VISIBLE);
showViewInWfcCase();
} else {
if (mIsAirplaneMode && (mIsWfcEnable && mVolteIcon != 0)) {
Log.e(TAG, "apply() into this code 2..");
/// M:Bug fix for show vowifi icon in flight mode
mMobileGroup.setVisibility(View.VISIBLE);
hideViewInWfcCase();
} else {
Log.e(TAG, "apply() into this code 3..");
if (DEBUG) {
Log.d(TAG, "setVisibility as GONE, this = " + this
+ ", mMobileVisible = " + mMobileVisible
+ ", mIsAirplaneMode = " + mIsAirplaneMode
+ ", mIsWfcEnable = " + mIsWfcEnable
+ ", mVolteIcon = " + mVolteIcon);
}
mMobileGroup.setVisibility(View.GONE);
}
} /// M: Set all added or customised view. @ {
//更新网络类型和volte图标
setCustomizeViewProperty();
/// @ } // When this isn't next to wifi, give it some extra padding between the signals.
mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0,
0, 0, 0);
mMobile.setPaddingRelative(
mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
0, 0, 0);
mMobileDark.setPaddingRelative(
mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
0, 0, 0); if (true) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d",
(mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId)); Log.e(TAG, "mActivityIn="+mActivityIn+" mActivityOut="+mActivityOut);
if(!mIsWfcCase) {
//更新流量是否打开可见性
mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE :View.GONE);
//漫游图标
mMobileRoaming.setVisibility(mRoaming ? View.VISIBLE : View.GONE);
//流量上下行图标
mMobileActivityIn.setVisibility(mActivityIn ? View.VISIBLE : View.GONE);
mMobileActivityOut.setVisibility(mActivityOut ? View.VISIBLE : View.GONE);
} /// M: Add for support plugin featurs. @ {
//可通过op01/2/3等加载SystemUI,从6.0延伸来的
setCustomizedOpViews();
/// @ } return mMobileVisible;
} ......
}

PhoneState 中的成员变量较多,我在代码里都已经加了注释了,就不细说了。加载的布局文件为

vendor\mediatek\proprietary\packages\apps\SystemUI\res_ext\layout\mobile_signal_group_ext.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- Support [Network Type on Statusbar] The layout to wrap original
mobile_signal_group and add image view for show network Type -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
<ImageView
android:id="@+id/volte_indicator_ext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
/>
<ImageView
android:id="@+id/network_type"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone"
/>
<include layout="@layout/mobile_signal_group"/> </LinearLayout>

布局文件中对应了 volte 和当前网络类型大图标, 再包含了 mobile_signal_group,里面就是上面提到的各种控件

vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout\mobile_signal_group.xml

3、state.apply(anyMobileVisible) 调用流程

通过上面的分析可以总结下 信号栏的调用流程

NetworkControllerImpl.java 中注册了SIM卡状态改变广播(ACTION_SIM_STATE_CHANGED),当收

到广播通知后调用到 notifyAllListeners()

通知所有的监听,mobileSignalController、mWifiSignalController、

mEthernetSignalController,分别对应手机信号显示、wifi信号、网卡显示通知

我们看到 mobileSignalController 中的回调 notifyListeners(SignalCallback callback),

在进行一系列的赋值操作后,最终回调到

SignalClusterView 中的 setMobileDataIndicators(),给 PhoneState 的成员变量赋值,

最后通过 apply()进行更新

4、PhoneState创建

通过刚刚对 PhoneState 类的介绍,发现通过构造方法 PhoneState(int subId, Context context) 可获取 PhoneState 对象

搜索当前文件找到在 inflatePhoneState(int subId) 中实例化 PhoneState

@Override
public void setSubs(List<SubscriptionInfo> subs) {
if (DEBUG) {
Log.d(TAG, "setSubs, this = " + this + ", size = " + subs.size()
+ ", subs = " + subs);
}
if (hasCorrectSubs(subs)) {//判断SIM卡是否改变
if (DEBUG) {
Log.d(TAG, "setSubs, hasCorrectSubs and return");
}
return;
}
mPhoneStates.clear();
if (mMobileSignalGroup != null) {
mMobileSignalGroup.removeAllViews();//移除手机信号组中的所有view
}
final int n = subs.size();//SIM卡数量
Log.d(TAG, "setSubs-clear subsize:" + subs.size() + "mStes" + mPhoneStates + ":" + this);
for (int i = 0; i < n; i++) {
inflatePhoneState(subs.get(i).getSubscriptionId());
}
if (isAttachedToWindow()) {
applyIconTint();//图标根据背景色动态变化
}
} private PhoneState inflatePhoneState(int subId) {
PhoneState state = new PhoneState(subId, mContext);
if (mMobileSignalGroup != null) {
mMobileSignalGroup.addView(state.mMobileGroup);//添加view到手机信号组中
}
Log.d(TAG, "inflatePhoneState add subId:" + subId + ",state" + state + ":" + this);
mPhoneStates.add(state);//存储PhoneState 对象,方便快速修改状态
return state;
}

当SIM卡插入识别后将回调 setSubs(),先判断SIM卡是否改变,有效则移除 mobileGroup 中已添加

所有view,遍历SIM卡数量,通过 subId 创建 PhoneState,并将对应的view添加到 mobileGroup 中。

然后将 PhoneState对象存储到集合中,方便快速修改状态

这里简单说下 subId subid对应卡,slotid对应卡槽

slotid或者phoneid是指卡槽,双卡机器的卡槽1值为0,卡槽2值为1,依次类推

subid的值从1开始,每插入一个新卡,subId的值就会加1。

插入双卡后数据库中就会有subid值为1和2的两个数据条目,

拔卡插卡交换卡槽后,数据库并不会增加新项,只有插入一张新的sim卡才会增加一条id为3的数据条目

详细的介绍请看这篇 subId、slotId

5、SIM卡插入后更新图标流程

PhoneState 创建成功了并存到集合中,当收到 setMobileDataIndicators()回调后

给 PhoneState 成员变量赋值,赋值结束通过apply()更新

还记得上面说过的 apply() 中更新SIM卡图标的逻辑吧,

遍历 mPhoneStates 集合,调用PhoneState的apply()将成员变量值设置给对应的控件

int firstMobileTypeId = 0;
for (PhoneState state : mPhoneStates) {
if (state.apply(anyMobileVisible)) {
if (!anyMobileVisible) {
firstMobileTypeId = state.mMobileTypeId;
anyMobileVisible = true;
}
}
}

那么 setMobileDataIndicators() 是从哪里回调过来的呢?

分析找到 MobileSignalController 中的 notifyListeners()

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\MobileSignalController.java

@Override
public void notifyListeners(SignalCallback callback) {
//获取资源ID组
MobileIconGroup icons = getIcons(); String contentDescription = getStringIfExists(getContentDescription());
String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
//移动数据是否开启
final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
&& mCurrentState.userSetup; /// M: Customize the signal strength icon id. @ {
//当前手机信号格数资源ID
int iconId = getCurrentIconId();
//用户可自定义的资源ID,该方法将目前的iconId原值赋给了iconID,如需定制可在此修改
iconId = mStatusBarExt.getCustomizeSignalStrengthIcon(
mSubscriptionInfo.getSubscriptionId(),
iconId,
mSignalStrength,
mDataNetType,
mServiceState);
/// @ } // Show icon in QS when we are connected or data is disabled.
//是否显示移动数据图标
boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
//是否显示 mobileGroup、信号格数、SIM卡信息描述
IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
iconId, contentDescription); int qsTypeIcon = 0;
IconState qsIcon = null;
String description = null;
// Only send data sim callbacks to QS.
if (mCurrentState.dataSim) {
qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
qsIcon = new IconState(mCurrentState.enabled
&& !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
//状态栏显示只能拨打紧急电话或当前的网络类型
description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
}
//数据下行
boolean activityIn = mCurrentState.dataConnected
&& !mCurrentState.carrierNetworkChangeMode
&& mCurrentState.activityIn;
//数据上行
boolean activityOut = mCurrentState.dataConnected
&& !mCurrentState.carrierNetworkChangeMode
&& mCurrentState.activityOut;
showDataIcon &= mCurrentState.isDefault || dataDisabled;
//移动数据类型资源ID,关闭是X,打开是小的网络类型4G/3G/2G
int typeIcon = showDataIcon ? icons.mDataType : 0; /// M: Add for lwa.
typeIcon = mCurrentState.lwaRegState == NetworkTypeUtils.LWA_STATE_CONNCTED
&& showDataIcon ? NetworkTypeUtils.LWA_ICON : typeIcon;
/** M: Support [Network Type on StatusBar], change the implement methods.
* Get the network icon base on service state.
* Add one more parameter for network type.
* @ { **/
//当前网络类型资源ID
int networkIcon = mCurrentState.networkIcon;
/// M: Support volte icon.Bug fix when airplane mode is on go to hide volte icon
//VOlTE资源ID
int volteIcon = mCurrentState.airplaneMode && !isImsOverWfc()
? 0 : mCurrentState.volteIcon; /// M: when data disabled, common show data icon as x, but op do not need show it @ {
mStatusBarExt.isDataDisabled(mSubscriptionInfo.getSubscriptionId(), dataDisabled);
/// @ } /// M: Customize the data type icon id. @ {
//可自定义移动数据类型资源ID(比如常见的上下箭头)
typeIcon = mStatusBarExt.getDataTypeIcon(
mSubscriptionInfo.getSubscriptionId(),
typeIcon,
mDataNetType,
mCurrentState.dataConnected ? TelephonyManager.DATA_CONNECTED :
TelephonyManager.DATA_DISCONNECTED,
mServiceState);
/// @ }
/// M: Customize the network type icon id. @ {
//可自定义网络类型资源ID
networkIcon = mStatusBarExt.getNetworkTypeIcon(
mSubscriptionInfo.getSubscriptionId(),
networkIcon,
mDataNetType,
mServiceState); callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, networkIcon, volteIcon,
qsTypeIcon,activityIn, activityOut, dataContentDescription, description,
icons.mIsWide, mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming); /// M: update plmn label @{
mNetworkController.refreshPlmnCarrierLabel();
/// @}
}

这个方法比较重要,上面写了简单的注释,接下来我们会详细看下每个资源ID都是如何获取的?

在这之前我们先介绍下几个重要的 Bean 类

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\SignalController.java

State

static class State {
boolean connected;
boolean enabled;
boolean activityIn;
boolean activityOut;
int level;
IconGroup iconGroup;
int inetCondition;
int rssi;
...
}

IconGroup

static class IconGroup {
final int[][] mSbIcons;
final int[][] mQsIcons;
final int[] mContentDesc;
final int mSbNullState;
final int mQsNullState;
final int mSbDiscState;
final int mQsDiscState;
final int mDiscContentDesc;
// For logging.
final String mName;
....
}

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\MobileSignalController.java

MobileState

static class MobileState extends SignalController.State {
String networkName;//当前网络类型
String networkNameData;//移动数据网络类型
boolean dataSim;
boolean dataConnected;//数据是否连接
boolean isEmergency;//是否是紧急电话模式
boolean airplaneMode;//是否是飞行模式
boolean carrierNetworkChangeMode;//SIM卡网络类型是否改变
boolean isDefault;
boolean userSetup;//是否是用户操作
boolean roaming;//是否漫游 /// M: Add for 4G+W
int lwaRegState = NetworkTypeUtils.LWA_STATE_UNKNOWN;
/// M: For network type big icon.
int networkIcon;//网络类型大图标资源ID
/// M: Add for data network type.
int dataNetType;//移动数据网络类型
/// M: Add for op network tower type.
int customizedState;//自定义状态
/// M: Add for op signal strength tower icon.
int customizedSignalStrengthIcon;//自定义信号格资源ID
/// M: Add for volte @{
int imsRegState = ServiceState.STATE_POWER_OFF;
int imsCap;
int volteIcon;//volte资源ID ......
}

MobileIconGroup

static class MobileIconGroup extends SignalController.IconGroup {
final int mDataContentDescription; // mContentDescriptionDataType
final int mDataType;//移动数据网络类型资源ID
final boolean mIsWide;
final int mQsDataType;//下拉快捷访问资源 ...
}

好了重要的Bean类介绍完了,接下来又要说一个重要的方法了 updateTelephony()

还是在 MobileSignalController.java 中

private final void updateTelephony() {
if (DEBUG && FeatureOptions.LOG_ENABLE) {
Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
+ " ss=" + mSignalStrength);
}
//连接状态,是否在服务中
mCurrentState.connected = hasService() && mSignalStrength != null;
handleIWLANNetwork();
if (mCurrentState.connected) {
//SIM 卡信号格数级别 0~4格
if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
mCurrentState.level = mSignalStrength.getCdmaLevel();
} else {
mCurrentState.level = mSignalStrength.getLevel();
}
/// M: Customize the signal strength level. @ {
//客户可自定义
mCurrentState.level = mStatusBarExt.getCustomizeSignalStrengthLevel(
mCurrentState.level, mSignalStrength, mServiceState);
/// @ }
}
//当前网络类型获取对应的图标组
if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
} else {
mCurrentState.iconGroup = mDefaultIcons;
}
/// M: Add for data network type.
//数据网络类型
mCurrentState.dataNetType = mDataNetType;
//数据状态
mCurrentState.dataConnected = mCurrentState.connected
&& mDataState == TelephonyManager.DATA_CONNECTED;
/// M: Add for op network tower type.
mCurrentState.customizedState = mStatusBarExt.getCustomizeCsState(mServiceState,
mCurrentState.customizedState);
/// M: Add for op signal strength tower icon.
mCurrentState.customizedSignalStrengthIcon = mStatusBarExt.getCustomizeSignalStrengthIcon(
mSubscriptionInfo.getSubscriptionId(),
mCurrentState.customizedSignalStrengthIcon,
mSignalStrength,
mDataNetType,
mServiceState); mCurrentState.roaming = isRoaming();
if (isCarrierNetworkChangeActive()) {
mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
} else if (isDataDisabled()) {//数据未打开,对应x
mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
}
if (isEmergencyOnly() != mCurrentState.isEmergency) {
mCurrentState.isEmergency = isEmergencyOnly();
mNetworkController.recalculateEmergency();
}
// Fill in the network name if we think we have it.
//当前网络运营商
if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
&& !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
}
/// M: For network type big icon. 网络类型大图标
mCurrentState.networkIcon =
NetworkTypeUtils.getNetworkTypeIcon(mServiceState, mConfig, hasService());
/// M: For volte type icon. volte图标
mCurrentState.volteIcon = getVolteIcon(); //通知更新,最终回调到notifyListeners()中
notifyListenersIfNecessary();
}

基本上获取资源ID的方法都在 updateTelephony()中了,那么都在那里调用了 updateTelephony()?

MobileSignalController中构造方法初始化了 MobilePhoneStateListener 分别监听了

mPhone.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE//服务状态改变,可用、不可用
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS//信号强度改变,用于获取dbm、asu
| PhoneStateListener.LISTEN_CALL_STATE//电话状态改变,空闲、来电、通话
| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE//数据网络连接状态,网络断开、正在连接中、已连接上
| PhoneStateListener.LISTEN_DATA_ACTIVITY//数据上下行状态
| PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);//网络状态发送改变 class MobilePhoneStateListener extends PhoneStateListener {
public MobilePhoneStateListener(int subId, Looper looper) {
super(subId, looper);
} @Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
...
updateTelephony();
} @Override
public void onServiceStateChanged(ServiceState state) {
...
updateTelephony();
} @Override
public void onDataConnectionStateChanged(int state, int networkType) {
...
updateTelephony();
} @Override
public void onDataActivity(int direction) {
...
setActivity(direction);
} @Override
public void onCarrierNetworkChange(boolean active) {
...
updateTelephony();
} /// M: Add for Plugin feature. @{
@Override
public void onCallStateChanged(int state, String incomingNumber) {
...
updateTelephony(); }
/// @}
};

LISTEN_SIGNAL_STRENGTHS、LISTEN_CALL_STATE、LISTEN_CARRIER_NETWORK_CHANGE

这三个监听应该是我们平常用较多的,好了说了这么久,接下来重要看获取资源ID的具体方法了

5.1、Vlote资源ID

mCurrentState.volteIcon = getVolteIcon();

private int getVolteIcon() {
int icon = 0;
if (isImsOverWfc()) {
boolean needShowWfcSysIcon = mStatusBarExt.needShowWfcIcon();
if (needShowWfcSysIcon) {
icon = NetworkTypeUtils.WFC_ICON;
}
} else if (isImsOverVoice() && isLteNetWork()) {
if (mCurrentState.imsRegState == ServiceState.STATE_IN_SERVICE) {
//volte可用
icon = NetworkTypeUtils.VOLTE_ICON;
} else if(FeatureOptions.MTK_CT_MIXED_VOLTE_SUPPORT &&
SIMHelper.isSecondaryCSIMForMixedVolte(mSubscriptionInfo.getSubscriptionId()) &&
mCurrentState.imsRegState == ServiceState.STATE_OUT_OF_SERVICE) {
if (DEBUG) {
Log.d(mTag, "set dis volte icon");
}//volte不可用
icon = NetworkTypeUtils.VOLTE_DIS_ICON;
}
}
/// M: add for disconnected volte feature. @{
mStatusBarExt.setImsRegInfo(mSubscriptionInfo.getSubscriptionId(),
mCurrentState.imsRegState, isImsOverWfc(), isImsOverVoice());
/// @}
return icon;
}

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\mediatek\systemui\statusbar\networktype\NetworkTypeUtils.java

public static final int VOLTE_ICON = R.drawable.stat_sys_volte;

5.2、网络类型大图标资源ID

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\mediatek\systemui\statusbar\networktype\NetworkTypeUtils.java

mCurrentState.networkIcon =
NetworkTypeUtils.getNetworkTypeIcon(mServiceState, mConfig, hasService()); public static int getNetworkTypeIcon(ServiceState serviceState, Config config,
boolean hasService) {
if (!hasService) {
// Not in service, no network type. 未注册成功,比如废卡、停机卡
return 0;
}
//通过 serviceState 获取当前注册的网络类型
int tempNetworkType = getNetworkType(serviceState); Integer iconId = sNetworkTypeIcons.get(tempNetworkType);
if (iconId == null) {
iconId = tempNetworkType == TelephonyManager.NETWORK_TYPE_UNKNOWN ? 0 :
config.showAtLeast3G ? R.drawable.stat_sys_network_type_3g :
R.drawable.stat_sys_network_type_g;
}
return iconId.intValue();
} private static int getNetworkType(ServiceState serviceState) {
int type = TelephonyManager.NETWORK_TYPE_UNKNOWN;
if (serviceState != null) {
type = serviceState.getDataNetworkType() != TelephonyManager.NETWORK_TYPE_UNKNOWN ?
serviceState.getDataNetworkType() : serviceState.getVoiceNetworkType();
}
return type;
} //网络类型-资源ID 4g/3g/2g/e/1x
static final Map<Integer, Integer> sNetworkTypeIcons = new HashMap<Integer, Integer>() {
{
// For CDMA 3G
put(TelephonyManager.NETWORK_TYPE_EVDO_0, R.drawable.stat_sys_network_type_3g);
put(TelephonyManager.NETWORK_TYPE_EVDO_A, R.drawable.stat_sys_network_type_3g);
put(TelephonyManager.NETWORK_TYPE_EVDO_B, R.drawable.stat_sys_network_type_3g);
put(TelephonyManager.NETWORK_TYPE_EHRPD, R.drawable.stat_sys_network_type_3g);
// For CDMA 1x
put(TelephonyManager.NETWORK_TYPE_CDMA, R.drawable.stat_sys_network_type_1x);
put(TelephonyManager.NETWORK_TYPE_1xRTT, R.drawable.stat_sys_network_type_1x);
// Edge
put(TelephonyManager.NETWORK_TYPE_EDGE, R.drawable.stat_sys_network_type_e);
// 3G
put(TelephonyManager.NETWORK_TYPE_UMTS, R.drawable.stat_sys_network_type_3g);
// For 4G
put(TelephonyManager.NETWORK_TYPE_LTE, R.drawable.stat_sys_network_type_4g);
// 3G
put(TelephonyManager.NETWORK_TYPE_HSDPA, R.drawable.stat_sys_network_type_3g);
put(TelephonyManager.NETWORK_TYPE_HSUPA, R.drawable.stat_sys_network_type_3g);
put(TelephonyManager.NETWORK_TYPE_HSPA, R.drawable.stat_sys_network_type_3g);
put(TelephonyManager.NETWORK_TYPE_HSPAP, R.drawable.stat_sys_network_type_3g);
put(TelephonyManager.NETWORK_TYPE_IWLAN, 0);
}
};

5.3、移动数据类型资源ID

//mNetworkToIconLookup 和上面的网络类型 Map有点类似,键都是网络类型,
//不同的是,这次的key是上面介绍过的 MobileIconGroup
if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
} else {
mCurrentState.iconGroup = mDefaultIcons;
} if (isCarrierNetworkChangeActive()) {
mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
} else if (isDataDisabled()) {
mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
}

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\TelephonyIcons.java

class TelephonyIcons {
//***** Data connection icons //状态栏快捷访问,其实和下面的差多不
static final int QS_DATA_G = R.drawable.ic_qs_signal_g;
static final int QS_DATA_3G = R.drawable.ic_qs_signal_3g;
static final int QS_DATA_E = R.drawable.ic_qs_signal_e;
static final int QS_DATA_H = R.drawable.ic_qs_signal_h;
static final int QS_DATA_1X = R.drawable.ic_qs_signal_1x;
static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g;
static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte;
static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus; static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode; //此处的图标为小图标,网络类型
static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus;
static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e;
static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus;
static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x; //流量未打开
static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled; ... static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
"DataDisabled",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
0, 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.accessibility_cell_data_off,
TelephonyIcons.ICON_DATA_DISABLED,//这个值对应的就是 移动数据类型资源ID
false,
TelephonyIcons.QS_ICON_DATA_DISABLED
); }

MobileIconGroup 的倒数第三个参数就是 移动数据类型资源ID

5.4、信号格数资源ID

if (mCurrentState.connected) {
if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
mCurrentState.level = mSignalStrength.getCdmaLevel();
} else {
mCurrentState.level = mSignalStrength.getLevel();
}
/// M: Customize the signal strength level. @ {
mCurrentState.level = mStatusBarExt.getCustomizeSignalStrengthLevel(
mCurrentState.level, mSignalStrength, mServiceState);
/// @ }
}

信号格数对应的是 SignalDrawable,通过 setLevel()来控制显示几格,其实以上的大部分资源ID都是

通过 Vector 标签绘制而来的,里面都是一堆 path,开始看可能会觉得很迷糊,可以把xml文件拷贝到

AS中进行预览,再学上一些基础语法就可对简单的图形进行自定义修改。比方说6.0的信号格数是通过

vector 绘制的,格与格之间是有间隔,而8.1是通过 SignalDrawable绘制,是一个填满的三角形



修改前样式



修改后样式

来看下 mSignalStrength.getLevel() 方法

frameworks/base/telephony/java/android/telephony/SignalStrength.java

    public int getLevel() {
int level = 0;
if (isGsm) { //移动或联通卡
level = getLteLevel(); //首先获取4G信号格
if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { //未获取到
level = getTdScdmaLevel(); //获取移动或联通的3G信号格
if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {//仍然未获取
level = getGsmLevel(); //获取移动或联通的2G信号格
}
}
} else {//电信
int cdmaLevel = getCdmaLevel(); //获取电信2G信号格
int evdoLevel = getEvdoLevel(); //获取电信3G信号格
if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
/* We don't know evdo, use cdma */
level = cdmaLevel;
} else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
/* We don't know cdma, use evdo */
level = evdoLevel;
} else {
/* We know both, use the lowest level */
level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
}
}
if (DBG) log("getLevel=" + level);
return level;
}

在此介绍下手机是几模的配置:GSM是移动和联通公用的band;LTE从编码方式上分为TDD和FDD,从频段上分有各种不同的band

移动:GSM、TDSCDMA、LTE(TDD)

联通:GSM、WCDMA、LTE(FDD)

电信:CDMA、EVDO、LTE(FDD)

因此如果手机支持GSM、WCDMA、TDSCDMA、TDD-LTE、FDD-LTE 这是五模;加上 CDMA、EVDO 就是七模

5.5、漫游资源ID R.drawable.stat_sys_roaming

大写的R

三、总结

信号栏的定制还是很容易的,只要理清楚了控件和对应的回调逻辑,加上日志打印,就能搞定你想要的效果。

四、相关资源

这里附上我定制使用的drawable文件

drawable.zip

Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新的更多相关文章

  1. Android8.1 SystemUI源码分析之 电池时钟刷新

    SystemUI源码分析相关文章 Android8.1 SystemUI源码分析之 Notification流程 分析之前再贴一下 StatusBar 相关类图 电池图标刷新 从上篇的分析得到电池图标 ...

  2. Android8.1 SystemUI源码分析之 Notification流程

    代码流程 1.先看UI显示,StatuBar加载 CollapsedStatusBarFragment 替换 status_bar_container(状态栏通知显示区域) SystemUI\src\ ...

  3. Windows平台下源码分析工具

    最近这段时间在阅读 RTKLIB的源代码,目前是将 pntpos.c文件的部分看完了,准备写一份文档记录下这些代码的用处.处理过程.理论公式来源.注意事项,自己还没有弄明白的地方.目前的想法是把每一个 ...

  4. 分布式调度平台XXL-JOB源码分析-调度中心

    架构图 上图是我们要进行源码分析的2.1版本的整体架构图.其分为两大块,调度中心和执行器,本文先分析调度中心,也就是xxl-job-admin这个包的代码. 关键bean 在application.p ...

  5. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  6. 分布式调度平台XXL-JOB源码分析-执行器端

    上一篇文章已经说到调度中心端如何进行任务管理及调度,本文将分析执行器端是如何接收到任务调度请求,然后执行业务代码的. XxlJobExecutorApplication为我们执行器的启动项,其中有个X ...

  7. 分布式调度平台XXL-JOB源码分析-时序图

    整体流程 初始化 任务调度 任务执行 任务回调 注册心跳

  8. trinitycore 魔兽服务器源码分析(二) 网络

    书接上文 继续分析Socket.h SocketMgr.h template<class T>class Socket : public std::enable_shared_from_t ...

  9. libevent2源码分析之三:信号的初始化流程

    libevent2对信号的响应也进行了封装,使之与socket操作一样对外提供统一的接口.这里的信号一般指linux的信号.由于信号与socket相关的编程接口有较大的不同,因此在内部实现也有一些区别 ...

随机推荐

  1. shell 替换文本中的某个符号为换行符

    替换后为: 0.06774 脚本: :%s/,"/\r/g

  2. MySql数据基础之数据表操作

    MySql数据库中主要利用多个数据表进行数据的存储,我们可以将数据表理解成一个Excel表格,Excel表格的第一列可以将它看为id列,主要任务是数据表中数据的唯一标识,不能重复.不能为空.如果将数据 ...

  3. 定时器注解 @Scheduled 使用

    试列代码: @Component @Slf4j //配置文件注入注解 @PropertySource("classpath:/**.properties") public clas ...

  4. RabbitMQ的三大交换器

    pom文件都是相同的 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  5. go学习第三天、数据类型

    基本数据类型 bool string int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr byte // alias ...

  6. HDU 1520 Anniversity party

    There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The Un ...

  7. python3导入子模块

    基础知识 参考资料1上有一句话Regular packages are traditional packages as they existed in Python 3.2 and earlier. ...

  8. python爬虫--爬虫与反爬

    爬虫与反爬 爬虫:自动获取网站数据的程序,关键是批量的获取. 反爬虫:使用技术手段防止爬虫程序的方法 误伤:反爬技术将普通用户识别为爬虫,从而限制其访问,如果误伤过高,反爬效果再好也不能使用(例如封i ...

  9. JS中原始值和引用值分析

    JS中变量中两种类型的值:原始值,引用值 原始值是存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置. var x = 1; //1就是一个原始值,变量x中存放的就是原始 ...

  10. Linux远程目录挂载

    原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/ad99ab1d-1 ...