包括 8.0 9.0 的流程和修改方式
一、 信号级别
二、 图片配置
三、android 8.0 代码中的修改 及 流程
四、android 9.0 的修改和 基本流程
包括部分修改signal out in 图片自定义
8.0
NetworkControllerImpl 中收到广播更新数据时,调用到 MobileSignalController 生成各种数据,
通过 MobileSignalController notifyListeners 方法将数据回调给mSignalCallbacks
通过 SignalClusterView 通过代码 mNetworkController.addCallback(this) 将自己添加到CallbackHandler中的 mSignalCallbacks 回调列表。
9.0
前面是一样的 MobileSignalController 调用到了"代理类" StatusBarSignalPolicy
StatusBarSignalPolicy 通过 mIconController.setMobileIcons 调用到了具体实现类 StatusBarIconControllerImpl
StatusBarIconControllerImpl
一、 信号级别
frameworks/base/telephony/java/android/telephony/SignalStrength.java
/** @hide */
private static final boolean mIsSignalFiveNumber = true;
/** @hide */
public static final int NUM_SIGNAL_STRENGTH_BINS = mIsSignalFiveNumber ? 6 : 5;
修改方式:查看好当前项目的level
二、 图片配置
2.1 图片配置加载类
SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
//level
static final int SIGNAL_LEVEL_NUM = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
//图片数组
static String[] mSignalStrengthArray, mSignalStrengthRoamingArray;
//读取xml图片配置
static void readIconsFromXml(Context context) {
if (isInitiated) {
log(TAG, "readIconsFromXml, already read!");
return;
}
mSignalStrengthArray = mRes.getStringArray(R.array.multi_signal_strength);
mSignalStrengthRoamingArray = mRes.getStringArray(
R.array.multi_signal_strength_roaming);
}
//更新 数据类型
static void updateDataType(int slot, int type, boolean showAtLeast3G,
boolean show4GforLte, boolean hspaDistinguishable, int inet) {
....
.....
....
}
//生成信号图标
static int getSignalStrengthIcon(int slot, int inet, int level, boolean roaming) {
log(TAG, "getSignalStrengthIcon: " + String.format(
"slot=%d, inetCondition=%d, level=%d, roaming=%b", slot, inet, level, roaming));
String[] signalStrengthArray, selectedTypeArray;
signalStrengthArray = mRes.getStringArray(mRes.getIdentifier(!roaming ?
mSignalStrengthArray[slot] : mSignalStrengthRoamingArray[slot], null, NS));
log(TAG, String.format("signalStrengthArray.length=%d", signalStrengthArray.length));
selectedTypeArray = mRes.getStringArray(mRes.getIdentifier(
signalStrengthArray[mSelectedSignalStreagthIndex[slot]], null, NS));
log(TAG, String.format("selectedTypeArray.length=%d", selectedTypeArray.length));
String[] inetArray = mRes.getStringArray(
mRes.getIdentifier(selectedTypeArray[inet], null, NS));
log(TAG, String.format("inetArray.length=%d", inetArray.length));
return mRes.getIdentifier(inetArray[level], null, NS);
}
2.2 图片配置
通过二中读取的 array名称,就找到了读取的配置数据
SystemUI/res/values/arrays.xml 对应的sim1 sim2的图
- array/telephony_siganl_strength_sim1
- array/telephony_siganl_strength_sim1
- array/telephony_siganl_strength_sim1
...
修改方式:
根据实际的数组中配置的图片名称替换下面的图片
stat_sys_signal_0_fully.png stat_sys_signal_0.png
stat_sys_signal_1_fully.png stat_sys_signal_1.png
stat_sys_signal_2_fully.png stat_sys_signal_2.png
stat_sys_signal_3_fully.png stat_sys_signal_3.png
stat_sys_signal_4_fully.png stat_sys_signal_4.png
stat_sys_signal_disable.png stat_sys_signal_null.png
三、android 8.0 代码中的修改 及 流程
3.1 SystemUI/res/values/config.xml
true -- 信号读取图片
加载view: SignalClusterView.java -> signal_cluster_view.xml
信号图片控制的主要逻辑 :MobileSignalController.java
3.2 8.0 基本流程:
状态栏,锁屏状态栏,下拉通知状态栏等都有信号网络的控制,
(1)StatusBar{
...
private NotificationMessagingUtil mMessagingUtil;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private UserSwitcherController mUserSwitcherController;
private NetworkController mNetworkController;
private KeyguardMonitorImpl mKeyguardMonitor
= (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
private BatteryController mBatteryController;
@Override
public void start() {
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
//生成网络控制器
mNetworkController = Dependency.get(NetworkController.class);
...
}
}
(2) 加载 NetworkController 的实现类 NetworkControllerImpl
NetworkControllerImpl是 作为信号栏数据控制类,负责监控 wifi, service state 飞行模式等。
public class NetworkControllerImpl extends BroadcastReceiver ....{
@VisibleForTesting
final WifiSignalController mWifiSignalController;
@VisibleForTesting
final EthernetSignalController mEthernetSignalController;
@VisibleForTesting
final SparseArray mMobileSignalControllers = new SparseArray<>();
// When no SIMs are around at setup, and one is added later, it seems to default to the first
// SIM for most actions. This may be null if there aren't any SIMs around.
private MobileSignalController mDefaultSignalController;
//添加对应subid的 MobileSignalControll 控制器
private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
null, 0, 0, "");
MobileSignalController controller = new MobileSignalController(mContext,
mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
mSubDefaults, mReceiverHandler.getLooper());
mMobileSignalControllers.put(id, controller);
controller.getState().userSetup = true;
return info;
}
//这个构造方法内部会先去调用一个另外的构造方法;
/**
* Construct this controller object and register for updates.
*/
public NetworkControllerImpl(Context context, Looper bgLooper,
DeviceProvisionedController deviceProvisionedController) {
this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
(WifiManager) context.getSystemService(Context.WIFI_SERVICE),
SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
new CallbackHandler(),
new AccessPointControllerImpl(context, bgLooper),
new DataUsageController(context),
new SubscriptionDefaults(),
deviceProvisionedController);
// 主要注册监听的地方
mReceiverHandler.post(mRegisterListeners);
}
@VisibleForTesting
NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
TelephonyManager telephonyManager, WifiManager wifiManager,
SubscriptionManager subManager, Config config, Looper bgLooper,
CallbackHandler callbackHandler,
AccessPointControllerImpl accessPointController,
DataUsageController dataUsageController,
SubscriptionDefaults defaultsHandler,
DeviceProvisionedController deviceProvisionedController) {
mContext = context;
mConfig = config;
mReceiverHandler = new Handler(bgLooper);
mCallbackHandler = callbackHandler;
mDataSaverController = new DataSaverControllerImpl(context);
mSubscriptionManager = subManager;
mSubDefaults = defaultsHandler;
mConnectivityManager = connectivityManager;
mHasMobileDataFeature = mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
// telephony
mPhone = telephonyManager;
// wifi
mWifiManager = wifiManager;
mLocale = mContext.getResources().getConfiguration().locale;
mAccessPoints = accessPointController;
mDataUsageController = dataUsageController;
mDataUsageController.setNetworkController(this);
// TODO: Find a way to move this into DataUsageController.
mDataUsageController.setCallback(new DataUsageController.Callback() {
@Override
public void onMobileDataEnabled(boolean enabled) {
mCallbackHandler.setMobileDataEnabled(enabled);
}
});
mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
mCallbackHandler, this);
mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
// AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
updateAirplaneMode(true /* force callback */);
mUserTracker = new CurrentUserTracker(mContext) {
@Override
public void onUserSwitched(int newUserId) {
NetworkControllerImpl.this.onUserSwitched(newUserId);
}
};
mUserTracker.startTracking();
deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
@Override
public void onUserSetupChanged() {
setUserSetupComplete(deviceProvisionedController.isUserSetup(
deviceProvisionedController.getCurrentUser()));
}
});
}
/**
* Used to register listeners from the BG Looper, this way the PhoneStateListeners that
* get created will also run on the BG Looper.
*/
private final Runnable mRegisterListeners = new Runnable() {
@Override
public void run() {
registerListeners();
}
};
private 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);
// broadcasts 这里就可以看到 有注册了 wifi,信号,数据流量 飞行模式,
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);
mContext.registerReceiver(this, filter, null, mReceiverHandler);
mListening = true;
updateMobileControllers();
}
//从 config.xml 中读取的网络的配置
@VisibleForTesting
static class Config {
boolean showAtLeast3G = false;
boolean alwaysShowCdmaRssi = false;
boolean show4gForLte = false;
boolean hideLtePlus = false;
boolean hspaDataDistinguishable;
boolean readIconsFromXml;
boolean showRsrpSignalLevelforLTE;
boolean inflateSignalStrengths = false;
static Config readConfig(Context context) {
Config config = new Config();
Resources res = context.getResources();
config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
config.alwaysShowCdmaRssi =
res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE);
config.hspaDataDistinguishable =
res.getBoolean(R.bool.config_hspa_data_distinguishable);
config.hideLtePlus = res.getBoolean(R.bool.config_hideLtePlus);
config.readIconsFromXml = res.getBoolean(R.bool.config_read_icons_from_xml);
config.showRsrpSignalLevelforLTE = res.getBoolean(R.bool.config_showRsrpSignalLevelforLTE);
config.inflateSignalStrengths = res.getBoolean(R.bool.config_inflateSignalStrength);
return config;
}
}
}
(3) 信号图片控制的主要逻辑类
public MobileSignalController(
....
//如果配置读取图片,则加载配置类
if (config.readIconsFromXml) {
TelephonyIcons.readIconsFromXml(context);
mDefaultIcons = !mConfig.showAtLeast3G ? TelephonyIcons.G : TelephonyIcons.THREE_G;
} else {
mapIconSets();
}
}
@Override
public int getCurrentIconId() {
if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {
return SignalDrawable.getCarrierChangeState(getNumLevels());
} else if (mCurrentState.connected) {
int level = mCurrentState.level;
if (mConfig.inflateSignalStrengths) {
level++;
}
if (mConfig.readIconsFromXml) {
//返回配置类的图片
return getIcons().mSingleSignalIcon;
} else {
return SignalDrawable.getState(level, getNumLevels(),
mCurrentState.inetCondition == 0);
}
} else if (mCurrentState.enabled) {
if (mConfig.readIconsFromXml) {
return getIcons().mSbDiscState;
} else {
return SignalDrawable.getEmptyState(getNumLevels());
}
} else {
return 0;
}
}
private int getSimSlotIndex() {
int slotId = -1;
if (mSubscriptionInfo != null) {
slotId = mSubscriptionInfo.getSimSlotIndex();
}
if (DEBUG) Log.d(mTag, "getSimSlotIndex, slotId: " + slotId);
return slotId;
}
//这个方法就生成 dataType, singleSignalIcon 的主要类了
private void generateIconGroup() {
final int level = mCurrentState.level;
final int voiceLevel = mCurrentState.voiceLevel;
final int inet = mCurrentState.inetCondition;
final boolean dataConnected = mCurrentState.dataConnected;
final boolean roaming = isRoaming();
final int voiceType = getVoiceNetworkType();
int dataType = getDataNetworkType();
if (dataType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
mServiceState.isUsingCarrierAggregation()) {
dataType = TelephonyManager.NETWORK_TYPE_LTE_CA;
}
int[] contentDesc = AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH;
int discContentDesc = AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0];
int dataContentDesc, dataTypeIcon, qsDataTypeIcon, dataActivityId;
int singleSignalIcon, stackedDataIcon = 0, stackedVoiceIcon = 0;
final int slotId = getSimSlotIndex();
if (slotId < 0 || slotId > mPhone.getPhoneCount()) {
Log.e(mTag, "generateIconGroup invalid slotId:" + slotId);
return;
}
if (DEBUG) Log.d(mTag, "generateIconGroup slot:" + slotId + " style:" + mStyle
+ " connected:" + mCurrentState.connected + " inetCondition:" + inet
+ " roaming:" + roaming + " level:" + level + " voiceLevel:" + voiceLevel
+ " dataConnected:" + dataConnected
+ " dataActivity:" + mCurrentState.dataActivity
+ " CS:" + voiceType
+ "/" + TelephonyManager.getNetworkTypeName(voiceType)
+ ", PS:" + dataType
+ "/" + TelephonyManager.getNetworkTypeName(dataType));
// Update data icon set
int chosenNetworkType = ((dataType == TelephonyManager.NETWORK_TYPE_UNKNOWN)
? voiceType : dataType);
TelephonyIcons.updateDataType(slotId, chosenNetworkType, mConfig.showAtLeast3G,
mConfig.show4gForLte, mConfig.hspaDataDistinguishable, inet);
// Update signal strength icons ---
singleSignalIcon = TelephonyIcons.getSignalStrengthIcon(slotId, inet, level, roaming);
if (DEBUG) {
Log.d(mTag, "singleSignalIcon:" + getResourceName(singleSignalIcon));
}
dataActivityId = (mCurrentState.dataConnected && slotId >= 0) ?
TelephonyIcons.getDataActivity(slotId, mCurrentState.dataActivity) : 0;
// Convert the icon to unstacked if necessary.
int unstackedSignalIcon = TelephonyIcons.convertMobileStrengthIcon(singleSignalIcon);
if (DEBUG) {
Log.d(mTag, "unstackedSignalIcon:" + getResourceName(unstackedSignalIcon));
}
if (singleSignalIcon != unstackedSignalIcon) {
stackedDataIcon = singleSignalIcon;
singleSignalIcon = unstackedSignalIcon;
}
int[] subId = SubscriptionManager.getSubId(getSimSlotIndex());
if (subId != null && subId.length >= 1) {
mDualBar = SubscriptionManager.getResourcesForSubId(mContext,
subId[0]).getBoolean(com.android.internal.R.bool.config_dual_bar);
}
if (DEBUG) {
Log.d(mTag, "mDualBar:" + mDualBar);
Log.d(mTag, "mStyle:" + mStyle);
}
if (mStyle == STATUS_BAR_STYLE_CDMA_1X_COMBINED
|| (mStyle == STATUS_BAR_STYLE_DATA_VOICE && mDualBar)) {
if (!roaming && showDataAndVoice()) {
stackedVoiceIcon = TelephonyIcons.getStackedVoiceIcon(voiceLevel);
} else if (roaming && dataActivityId != 0) {
// Remove data type indicator if already shown in data activity icon.
singleSignalIcon = TelephonyIcons.getRoamingSignalIconId(level, inet);
}
}
// Clear satcked data icon if no satcked voice icon.
if (stackedVoiceIcon == 0) stackedDataIcon = 0;
contentDesc = TelephonyIcons.getSignalStrengthDes(slotId);
int sbDiscState = TelephonyIcons.getSignalNullIcon(slotId);
if (DEBUG) {
Log.d(mTag, "singleSignalIcon=" + getResourceName(singleSignalIcon)
+ " dataActivityId=" + getResourceName(dataActivityId)
+ " stackedDataIcon=" + getResourceName(stackedDataIcon)
+ " stackedVoiceIcon=" + getResourceName(stackedVoiceIcon));
}
// Update data net type icons
if (dataType == TelephonyManager.NETWORK_TYPE_IWLAN) {
// wimax is a special 4g network not handled by telephony
dataTypeIcon = TelephonyIcons.ICON_4G;
qsDataTypeIcon = TelephonyIcons.ICON_4G;
dataContentDesc = R.string.accessibility_data_connection_4g;
} else {
dataTypeIcon = TelephonyIcons.getDataTypeIcon(slotId);
dataContentDesc = TelephonyIcons.getDataTypeDesc(slotId);
qsDataTypeIcon = TelephonyIcons.getQSDataTypeIcon(slotId);
}
if (DEBUG) {
Log.d(mTag, "updateDataNetType, dataTypeIcon=" + getResourceName(dataTypeIcon)
+ " qsDataTypeIcon=" + getResourceName(qsDataTypeIcon)
+ " dataContentDesc=" + dataContentDesc);
}
mCurrentState.iconGroup = new MobileIconGroup(
TelephonyManager.getNetworkTypeName(dataType),
null, null, contentDesc, 0, 0, sbDiscState, 0, discContentDesc,dataContentDesc, dataTypeIcon, false, qsDataTypeIcon,
singleSignalIcon, stackedDataIcon, stackedVoiceIcon, dataActivityId);
}
@Override
public void notifyListeners(SignalCallback callback) {
//8.0之前会在这里判断,如果是读取配置,则去生成对应图片
if (mConfig.readIconsFromXml) {
generateIconGroup();
}
.....
.....
//这里很重要的, 就是将数据回调给 CallbackHandler, CallbackHandler, 再
callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut, dataActivityId,
icons.mStackedDataIcon, icons.mStackedVoiceIcon,
dataContentDescription, description, icons.mIsWide,
mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
}
}
(4) MobileSignalController 回调到 CallbackHandler 回调到 SignalClusterView
class CallbackHandler{
@Override
public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon,
final int statusType, final int qsType,final boolean activityIn,
final boolean activityOut, final int dataActivityId,
final int stackedDataIcon, final int stackedVoiceIcon,
final String typeContentDescription,
final String description, final boolean isWide, final int subId, boolean roaming) {
post(new Runnable() {
@Override
public void run() {
for (SignalCallback signalCluster : mSignalCallbacks) {
//回调到了SignalClusterView
signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType,
activityIn, activityOut, dataActivityId,
stackedDataIcon, stackedVoiceIcon,
typeContentDescription, description, isWide,
subId, roaming);
}
}
});
}
}
SignalClusterView.java
public class SignalClusterView extends LinearLayout implements NetworkControllerImpl.SignalCallback,
SecurityController.SecurityControllerCallback, Tunable,DarkReceiver {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mVpnVisible = mSecurityController.isVpnEnabled();
mVpnIconId = currentVpnIconId(mSecurityController.isVpnBranded());
for (PhoneState state : mPhoneStates) {
if (state.mMobileGroup.getParent() == null) {
mMobileSignalGroup.addView(state.mMobileGroup);
}
}
int endPadding = mMobileSignalGroup.getChildCount() > 0 ? mMobileSignalGroupEndPadding : 0;
mMobileSignalGroup.setPaddingRelative(0, 0, endPadding, 0);
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
apply();
applyIconTint();
//在这里,将自己添加到了回调列表中
mNetworkController.addCallback(this);
mSecurityController.addCallback(this);
}
public void setMobileDataIndicators(...){
....
apply();
}
}
四、android 9.0 的修改和 基本流程
4.1
SystemUI/res/values/config.xml
true -- 信号读取图片
true -- 显示类型 4G 3G
信号栏图片的逻辑:MobileSignalController.java (9.0 代码变化较大)
//一、二修改的步骤一致。
//主要需要修改 MobileSignalController.java
//MobileSignalController.java 中将
MobileSignalController.java {
public MobileSignalController(
//9.0 没有了 TelephonyIcons的加载
//if (config.readIconsFromXml) {
// TelephonyIcons.readIconsFromXml(context);
// mDefaultIcons = !mConfig.showAtLeast3G ? TelephonyIcons.G : TelephonyIcons.THREE_G;
//} else {
mapIconSets();
...
}
//需要修改,这个方法返回的是 信号栏需要显示的图片ID,9.0中完全使用 SignalDrawable 来生成
@Override
public int getCurrentIconId() {
//9.0 可以自己添加
if (mConfig.readIconsFromXml) {
return getIcons().mSingleSignalIcon;
}
}
//信号状态发生变化的时候,会调用到这里,在这里,这里会生成当前很多的信息
@Override
public void notifyListeners(SignalCallback callback) {
//9.0 去掉了 generateIconGroup code 需要补充
//if (mConfig.readIconsFromXml) {
// generateIconGroup();
//}
// 在 generateIconGroup 中也不能生成 使用new 的代码了
// 需要将最后1个生成对象代码变成 mSingleSignalIcon 这个属性需要自己添加9.0 已经去掉了
// mCurrentState.iconGroup.mSingleSignalIcon = singleSignalIcon;
....
....
//从这里把 新的状态回调到, StatusBarSignalPolicy.java
callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut,volteIcon,
dataContentDescription, description, icons.mIsWide,
mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
}
}
信号栏界面view的修改 : StatusBarMobileView.java
StatusBarMobileView.java{
在初始化中添加流量图标
private void initViewState() {
//隐藏原生container
mInoutContainer.setVisibility(View.GONE);
//添加view
mInOut.setImageResource(getCardActivityId(mState.activityIn,mState.activityOut));
}
//更新状态
private void updateState(MobileIconState state) {
setContentDescription(state.contentDescription);
if (mState.visible != state.visible) {
mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
}
if (mState.strengthId != state.strengthId) {
//更改信号View图片显示方式
//mMobileDrawable.setLevel(state.strengthId);
mMobile.setImageResource(state.strengthId);
}
}
if (mState.typeId != state.typeId) {
if (state.typeId != 0) {
mMobileType.setContentDescription(state.typeContentDescription);
mMobileType.setImageResource(state.typeId);
//更新上下行图标
mInOut.setImageResource(getCardActivityId(mState.activityIn,mState.activityOut));
mMobileType.setVisibility(View.VISIBLE);
} else {
mMobileType.setVisibility(View.GONE);
}
}
mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
mMobileRoamingSpace.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
mOut.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
// mInoutContainer.setVisibility((state.activityIn || state.activityOut)
// ? View.VISIBLE : View.GONE);
// 隐藏原生的效果
// mInoutContainer.setVisibility(View.GONE);
}
@Override
public void onDarkChanged(Rect area, float darkIntensity, int tint) {
if (!isInArea(area, this)) {
return;
}
mMobileDrawable.setDarkIntensity(darkIntensity);
ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint));
mIn.setImageTintList(color);
mOut.setImageTintList(color);
mMobileType.setImageTintList(color);
mMobileRoaming.setImageTintList(color);
mDotView.setDecorColor(tint);
mDotView.setIconColor(tint, false);
//添加图标更改颜色
mInOut.setImageTintList(color);
mMobile.setImageTintList(color);
}
//添加流量图标的定义
private int getCardActivityId(boolean activityIn, boolean activityOut) {
int activityId;
if (activityIn && activityOut) {
activityId = R.drawable.stat_sys_signal_inout_auto_mirrored;
} else if (activityIn) {
activityId = R.drawable.stat_sys_signal_in_auto_mirrored;
} else if (activityOut) {
activityId = R.drawable.stat_sys_signal_out_auto_mirrored;
} else {
activityId = R.drawable.stat_sys_signal_no_auto_mirrored;
}
return activityId;
}
}
4.2 基本流程
前面的流程基本一致
MobileSignalController 调用到 StatusBarSignalPolicy.java
代理类
StatusBarSignalPolicy.java{
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,{
在此类中,就真正的进行的数据赋值
MobileIconState state = getState(subId);
state.visible = statusIcon.visible && !mBlockMobile;
state.strengthId = statusIcon.icon; -- 信号栏图片ID
state.typeId = statusType; -- 信号类型图片
state.contentDescription = statusIcon.contentDescription; --描述
state.typeContentDescription = typeContentDescription;
state.roaming = roaming; -- 漫游
state.activityIn = activityIn && mActivityEnabled; -- 数据进入
state.activityOut = activityOut && mActivityEnabled;
state.volteId = volteIcon;
// Always send a copy to maintain value type semantics
这里调用到拉具体实现类 StatusBarIconControllerImpl.java
mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates));
....
}
}
//具体控制实现类 XXXimpl.java
StatusBarIconControllerImpl.java {
@Override
public void setMobileIcons(String slot, List iconStates) {
Slot mobileSlot = getSlot(slot);
int slotIndex = getSlotIndex(slot);
for (MobileIconState state : iconStates) {
StatusBarIconHolder holder = mobileSlot.getHolderForTag(state.subId);
if (holder == null) {
holder = StatusBarIconHolder.fromMobileIconState(state);
setIcon(slotIndex, holder);
} else {
holder.setMobileState(state);
handleSet(slotIndex, holder);
}
}
}
@Override
public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
boolean isNew = getIcon(index, holder.getTag()) == null;
super.setIcon(index, holder);
if (isNew) {
addSystemIcon(index, holder);
} else {
handleSet(index, holder);
}
}
//如下 addSystemIcon 和 handleSet 会调用到 IconManager 中的方法进行实现,
//具体看下下面IconManager的部分代码
private void addSystemIcon(int index, StatusBarIconHolder holder) {
String slot = getSlotName(index);
int viewIndex = getViewIndex(index, holder.getTag());
boolean blocked = mIconBlacklist.contains(slot);
mIconLogger.onIconVisibility(getSlotName(index), holder.isVisible());
//for 循环添加 mIconGroups 中的数据
// onIconAdded 这个方法,就可以看到 IconManager 中的实现,会判断type进行add
mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));
}
private void handleSet(int index, StatusBarIconHolder holder) {
int viewIndex = getViewIndex(index, holder.getTag());
mIconLogger.onIconVisibility(getSlotName(index), holder.isVisible());
mIconGroups.forEach(l -> l.onSetIconHolder(viewIndex, holder));
}
//这个类也是很重要的, 这里保存了 mIconGroups
//QuickStatusBarHeader, CollapsedStatusBarFragment
//Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
@Override
public void addIconGroup(IconManager group) {
mIconGroups.add(group);
List allSlots = getSlots();
for (int i = 0; i < allSlots.size(); i++) {
Slot slot = allSlots.get(i);
List holders = slot.getHolderListInViewOrder();
boolean blocked = mIconBlacklist.contains(slot.getName());
for (StatusBarIconHolder holder : holders) {
int tag = holder.getTag();
int viewIndex = getViewIndex(getSlotIndex(slot.getName()), holder.getTag());
group.onIconAdded(viewIndex, slot.getName(), blocked, holder);
}
}
}
public interface StatusBarIconController {
//statuabr icon 黑名单,
public static final String ICON_BLACKLIST = "icon_blacklist";
//继承 iconManager, 然后去控制状态栏的颜色
public static class DarkIconManager extends IconManager { }
public static class TintedIconManager extends IconManager { }
内部类
Class IconManager{
//Turns info from StatusBarIconController into ImageViews in a ViewGroup.
public static class IconManager implements DemoMode {
protected void onIconAdded(int index, String slot, boolean blocked,
StatusBarIconHolder holder) {
addHolder(index, slot, blocked, holder);
}
//生成缓存类 viewHoler 类似listiew 的 viewHolder
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;
}
protected StatusBarIconView addIcon(int index, String slot, boolean blocked,StatusBarIcon icon) {
}
//生成wifi相关view
protected StatusBarWifiView addSignalIcon(int index, String slot, WifiIconState state) {
}
//生成信号栏等手机相关的view
protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) {
}
}
}
}