本文主要是讲SystemUI手机信号在状态栏上的加载过程,从结构树和处理逻辑上分析。
一、结构树:
以上就是整个界面显示的xml加载流程,后面会逐个源码贴出来。
1. 先看staus_bar.xml
<com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<include layout="@layout/system_icons" /> 加载system_icons.xml
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:singleLine="true"
android:paddingStart="@dimen/status_bar_clock_starting_padding"
android:paddingEnd="@dimen/status_bar_clock_end_padding"
android:gravity="center_vertical|start"
/>
</com.android.keyguard.AlphaOptimizedLinearLayout>
</LinearLayout>
2.system_icon.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="wrap_content"
/>
</LinearLayout>
这是父类是一个linearLayout 水平布局,从代码中不仅仅加载了信号图标区域(signal_cluster_view)还加载了电量显示图标(BatterMeterView),从现象看到与代码是一致的,电量图标一直在信号图标的右侧。
3.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"
>
<ImageView
android:id="@+id/vpn"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingEnd="6dp"
android:src="@drawable/stat_sys_vpn_ic"
android:tint="@color/background_protect_secondary"
android:contentDescription="@string/accessibility_vpn_on"
/>
<FrameLayout
android:id="@+id/ethernet_combo"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="?attr/lightIconTheme"
android:id="@+id/ethernet"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="?attr/darkIconTheme"
android:id="@+id/ethernet_dark"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:alpha="0.0"
/>
</FrameLayout>
<FrameLayout
android:layout_height="17dp"
android:layout_width="wrap_content">
<ImageView
android:id="@+id/wifi_in"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/ic_activity_down"
android:visibility="gone"
android:paddingEnd="2dp"
/>
<ImageView
android:id="@+id/wifi_out"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/ic_activity_up"
android:paddingEnd="2dp"
android:visibility="gone"
/>
</FrameLayout>
<FrameLayout
android:id="@+id/wifi_combo"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="?attr/lightIconTheme"
android:id="@+id/wifi_signal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="?attr/darkIconTheme"
android:id="@+id/wifi_signal_dark"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:alpha="0.0"
/>
<ImageView
android:id="@+id/wifi_inout"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
</FrameLayout>
<View
android:id="@+id/wifi_signal_spacer"
android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
android:layout_height="4dp"
android:visibility="gone"
/>
<ViewStub
android:id="@+id/connected_device_signals_stub"
android:layout="@layout/connected_device_signal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/mobile_signal_group"
android:layout_height="wrap_content"
android:layout_width="wrap_content" 此处是手机信号图标显示的父布局。
>
</LinearLayout>
<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,SignalClusterView是一个继承LinearLayout的ViewGroup,这个xml布局不仅仅包含了手机信号图标还有wifi以及飞行模式等。有朋友会问,从这个xml文件中我没看到mobile_signal_group_ext.xml的任何信息,那么mobile_signal_group_ext.xml是怎么被添加到手机信号图标树中呢?答案是通过代码的方式加载,在SignalClusterView.java 中有这么一段代码:
public PhoneState(int subId, Context context) {
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;
}
4.mobile_signal_group_ext.xml
<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>
5.mobile_signal_group.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/mobile_combo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<FrameLayout
android:layout_height="17dp"
android:layout_width="wrap_content">
<ImageView
android:id="@+id/mobile_in"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/ic_activity_down"
android:visibility="gone"
android:paddingEnd="2dp"
/>
<ImageView
android:id="@+id/mobile_out"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/ic_activity_up"
android:paddingEnd="2dp"
android:visibility="gone"
/>
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.android.systemui.statusbar.AnimatedImageView
android:theme="@style/DualToneLightTheme"
android:id="@+id/mobile_signal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
systemui:hasOverlappingRendering="false"
/>
<com.android.systemui.statusbar.AnimatedImageView
android:theme="@style/DualToneDarkTheme"
android:id="@+id/mobile_signal_dark"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:alpha="0.0"
systemui:hasOverlappingRendering="false"
/>
<ImageView
android:id="@+id/mobile_type"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
<ImageView
android:id="@+id/mobile_roaming"
android:layout_width="wrap_content"
android:layout_height="17dp"
android:paddingStart="22dp"
android:paddingTop="1.5dp"
android:paddingBottom="3dp"
android:scaleType="fitCenter"
android:src="@drawable/stat_sys_roaming"
android:contentDescription="@string/accessibility_data_connection_roaming"
android:visibility="gone" />
</FrameLayout>
</LinearLayout>
这两个xml布局都比较简单,其中对应的具体图标如下图
至此结构树的分析到此。
二、处理逻辑:
其实从网上能收到很多资料关于手机信号图标的信息,NetworkControllerImpl.java是手机信号处理逻辑类,这个类继承了BroadcastReceiver.java ,因此手机信号变化是监听一些信号广播来做修改的。之前提到的SignalClusterView.java则是信号显示类。那么这两个类是如何联系在一起的呢?答案是通过NetworkControllerImpl.SignalCallback,NetworkControllerImpl.SignalCallback是一个接口。
SignalClusterView.java继承NetworkControllerImpl.SignalCallback,并且向NetworkControllerImpl.java注册接口信息,NetworkControllerImpl.java根据信号广播回调NetworkControllerImpl.SignalCallback。
public class SignalClusterView extends LinearLayout implements NetworkControllerImpl.SignalCallback,
SecurityController.SecurityControllerCallback, Tunable,
DarkReceiver {
public void setForceBlockWifi() {
mForceBlockWifi = true;
mBlockWifi = true;
if (isAttachedToWindow()) {
// Re-register to get new callbacks.
mNetworkController.removeCallback(this);
mNetworkController.addCallback(this);
}
}
mNetWorkController 就是NetworkControllerImpl.Java实例,这个实例在SystemUI体系中被统一保存在Dependency.java中,有兴趣的朋友可以自己阅读相关的源码。下图是两者的关系。
后面我们捋一捋信号变化的逻辑部分,NetworkControllerImpl.java既然是一个BroadcastReceiver,那肯定会涉及到广播的注册和监听。
1.下面是广播的注册部分,代码比较简单。其中的MobileSignalController 是一个单独对手机信号逻辑处理类。
private void registerListeners() {
Log.e(TAG, "registerListeners-----------------------------");
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
StringBuilder st=new StringBuilder();
mobileSignalController.mCurrentState.toString(st);
Log.e(TAG, "registerListeners------- mNetworkNameDefault"+mobileSignalController.mNetworkNameDefault+" i ="+i+" st="+st.toString());
mobileSignalController.registerListener();
}
if (mSubscriptionListener == null) {
mSubscriptionListener = new SubListener();
}
mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
// 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);
/// M: Add mtk
addCustomizedAction(filter);
mContext.registerReceiver(this, filter, null, mReceiverHandler);
mListening = true;
updateMobileControllers();
}
所有有关SIM的监听最终会调用MobileSignalController.Java -->notifyListeners(SignalCallback callback)。但是信号强弱的变化则是由MobileSignalController.Java -->MobilePhoneStateListener的一个接口监听回调实现的,MobilePhoneStateListener通过向TelephonyManager.Java注册,最终还是会调用MobileSignalController.Java -->notifyListeners(SignalCallback callback)来实现信号的显示,相关的代码逻辑自行研究。
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 if (action.equals(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED)) {
// We are using different subs now, we might be able to make calls.
recalculateEmergency();
} else if (action.equals(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);
}
} else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
// Might have different subscriptions now.
updateMobileControllers();
/// M: Support "subinfo record update". @{
} else if (action.equals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED)) {
/// M: update plmn label @{
refreshPlmnCarrierLabel();
/// @}
updateMobileControllersEx(intent);
/// @}
} else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
/// M:[ALPS02809725]Always save ecc state not only no sim
/// M: [ALPS02614114] Check all phone's emergency state when no sims @{
if (mLastServiceState != null) {
int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY,
PhoneConstants.SIM_ID_1);
mEmergencyPhone[phoneId] = mLastServiceState.isEmergencyOnly();
if (DEBUG) {
Log.d(TAG, "Service State changed...phoneId: " + phoneId
+ " ,isEmergencyOnly: " + mEmergencyPhone[phoneId]);
}
if (mMobileSignalControllers.size() == 0) {
// If none of the subscriptions are active, we might need to recalculate
// emergency state.
recalculateEmergency();
}
// @}
}
} else if (action.equals(NetworkTypeUtils.LWA_STATE_CHANGE_ACTION)) {
/// M: Add for 4G+W
handleLwaAction(intent);
}
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.
mWifiSignalController.handleBroadcast(intent);
}
}
}
注释:
网络连接成功:ConnectivityManager.CONNECTIVITY_ACTION) ------- 能够上网
网络变化 ConnectivityManager.INET_CONDITION_ACTION -------- 能够上网
默认SIM变化:TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED -------- 相对于双卡手机,默认数据的SIM变化
默认SIM数据变化:TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED-----相对于双卡手机,默认数据的SIM变化
SIM状态变化:TelephonyIntents.ACTION_SIM_STATE_CHANGED----相对于双卡手机,默认数据的SIM变化
SIM数据变化:TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED
Phone service 变化:TelephonyIntents.ACTION_SERVICE_STATE_CHANGED
SIM正在打开数据:Telephony.SPN_STRINGS_UPDATED
SIM服务变化:TelephonyIntents.ACTION_SERVICE_STATE_CHANGED ----所有跟SIM相关的变化都会发送这个广播
3. MobileSignalController.Java -->notifyListeners(SignalCallback callback)
public void notifyListeners(SignalCallback callback) {
MobileIconGroup icons = getIcons();
Log.d(mTag, "mCurrentState.inetCondition " + mCurrentState.inetCondition + "mCurrentState.level"
+ mCurrentState.level);
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. @ {
int iconId = getCurrentIconId();
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;//modify xiao
IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
iconId, contentDescription);
Log.d(mTag, "notifyListeners: contentDescription=" + contentDescription+" dataContentDescription=" + dataContentDescription+
" dataDisabled=" + dataDisabled+" iconId=" + iconId+" showDataIcon=" + showDataIcon
+" mCurrentState.dataSim:"+mCurrentState.dataSim);
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;
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.
* @ { **/
int networkIcon = mCurrentState.networkIcon;
/// M: Support volte icon.Bug fix when airplane mode is on go to hide volte icon
int volteIcon = mCurrentState.airplaneMode && !isWfcEnable()
? 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. @ {
typeIcon = mStatusBarExt.getDataTypeIcon(
mSubscriptionInfo.getSubscriptionId(),
typeIcon,
mDataNetType,
mCurrentState.dataConnected ? TelephonyManager.DATA_CONNECTED :
TelephonyManager.DATA_DISCONNECTED,
mServiceState);
/// @ }
/// M: Customize the network type icon 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();
/// @}
}
1. typeIcon就是我们之前在分析控制树中有一张图片所显示4G ,networkIcon 3G,qsIcon是三角形图标,最终是调用SignalDrawable,SignalDrawable的主要工作就是根据信号强弱来画三角形图标。 SignalStrength表示信号等级,是通过MobilePhoneStateListener接口得到的。
2. typeIcon保存和获取会用到一个类TelephonyIcons.java,这个类保存了所有要显示信号类型。MobileSignalController-->mapIconSets() :根据信号类型加载不同的图标,就是我们在有的时候看到是3G,有时候显示的是4G。根据信号类型是如何获取得到的呢?答案是MobilePhoneStateListener 接口中onServiceStateChanged方法有这么一段代码
if (state != null) {
mDataNetType = state.getDataNetworkType();
3. networkIcon 保存和获取会用到一个类NetworkTypeUtils.java,这个类保存了所有要显示的网络类型图标,根据不同的ServiceState 和config来加载对应的网络类型图标。而ServiceState是依据MobilePhoneStateListener接口获取,config是根据SystemUI下面的Config.xml来配置的。NetworkControllerImpl.Java会加载相关的配置。
public static int getNetworkTypeIcon(ServiceState serviceState, Config config,
4.SignalClusterView.java最终依据callback.setMobileDataIndicators所传递的信息,对不同的View设置VISIBLE和GONE,以及图片的加载。
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int networkType, int volteIcon, int qsType, boolean activityIn, boolean activityOut,
String typeContentDescription, String description, boolean isWide, int subId,
boolean roaming) {
PhoneState state = getState(subId);
if (state == null) {
return;
}
state.mMobileVisible = statusIcon.visible && !mBlockMobile;
state.mMobileStrengthId = statusIcon.icon;
state.mMobileTypeId = statusType;
state.mMobileDescription = statusIcon.contentDescription;
state.mMobileTypeDescription = typeContentDescription;
state.mIsMobileTypeIconWide = statusType != 0 && isWide;
/// M: for big network icon and volte icon.
state.mNetworkIcon = networkType;
state.mVolteIcon = volteIcon;
state.mRoaming = roaming;
state.mActivityIn = activityIn && mActivityEnabled;
state.mActivityOut = activityOut && mActivityEnabled;
/// M: Add for plugin features. @ {
state.mDataActivityIn = activityIn;
state.mDataActivityOut = activityOut;
/// @ }
Log.d(TAG, "setMobileDataIndicators description:"+description+" typeContentDescription="+typeContentDescription);
apply();
}
至此手机信号图标的控制加载流程讲述完毕,本文只是讲了大体的流程,其中详情,可以自行阅读。