上一篇博客写了关于显示SignalClusterView的流程。
https://blog.csdn.net/csdnxialei/article/details/86570013
这一篇写关于SignalClusterView如何在控制和显示着信号相关信息。
SignalClusterView是显示各种信号栏图标view集合,它实现了多个接口。
public class SignalClusterView extends LinearLayout implements NetworkControllerImpl.SignalCallback,
SecurityController.SecurityControllerCallback, Tunable,
DarkReceiver
其中最重要的莫过于NetworkControllerImpl.SignalCallback这个接口了。
public interface SignalCallback {
default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description, boolean isTransient) {}
default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int networkIcon, int volteType, int qsType, boolean activityIn, boolean activityOut,
String typeContentDescription, String description, boolean isWide,
int subId,boolean roaming) {}
default void setSubs(List<SubscriptionInfo> subs) {}
default void setNoSims(boolean show, boolean simDetected) {}
default void setEthernetIndicators(IconState icon) {}
default void setIsAirplaneMode(IconState icon) {}
default void setMobileDataEnabled(boolean enabled) {}
}
SignalCallback这个接口,直接控制着信号栏view的显示问题。
其中setWifiIndicators,和setMobileDataIndicators就是控制显示wifi信息,和信号格网络状态的信息。
在SignalClusterView构造的时候
public SignalClusterView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
...
mNetworkController = Dependency.get(NetworkController.class);
mSecurityController = Dependency.get(SecurityController.class);
...
mNetworkController通过Dependency的服务来获取了NetworkController的实例。
然后在onAttachedToWindow的时候将SignalClusterView注册到了NetworkController.SignalCallback
@Override
protected void onAttachedToWindow() {
...
mNetworkController.addCallback(this);
mSecurityController.addCallback(this);
...
}
至此,SignalClusterView在显示到界面上以后,就开始接受mNetworkController的接口方法控制,
然而mNetworkController是个接口对象,所以谁继承了mNetworkController,谁就是实际控制SignalClusterView显示信号信息的幕后主使。
谁是幕后主使?
通过继承关系找到了NetworkControllerImpl。
public class NetworkControllerImpl extends BroadcastReceiver
implements NetworkController, DemoMode,
DataUsageController.NetworkNameProvider,ConfigurationChangedReceiver, Dumpable
看看NetworkControllerImpl
public void addCallback(SignalCallback cb) {
cb.setSubs(mCurrentSubscriptions);
cb.setIsAirplaneMode(new IconState(mAirplaneMode,TelephonyIcons.FLIGHT_MODE_ICON,
R.string.accessibility_airplane_mode, mContext));
mWifiSignalController.notifyListeners(cb);
mEthernetSignalController.notifyListeners(cb);
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController mobileSignalController =mMobileSignalControllers.valueAt(i);
mobileSignalController.notifyListeners(cb);
}
mCallbackHandler.setListening(cb, true);
cb.setNoSims(mHasNoSubs, mSimDetected);
}
在addCallback的时候,这个SignalCallback也就是前面的SignalClusterView。
虽然上面有 mobileSignalController.notifyListeners(cb);在后面也会出现,但是这只是第一次刷新,之后的刷新交给了另一个对象,
mCallbackHandler.setListening(cb, true);
CallbackHandler
private final CallbackHandler mCallbackHandler;
public void setListening(SignalCallback listener, boolean listening) {
if (DEBUG) {
Log.d(TAG, "setListening, listener = " + listener
+ ", listening = " + listening);
}
obtainMessage(MSG_ADD_REMOVE_SIGNAL, listening ? 1 : 0, 0, listener).sendToTarget();
}
setListening之后,就会由CallbackHandler来通知所有Listenner来更新显示。
而且CallbackHandler也是继承了SignalCallback
public class CallbackHandler extends Handler implements EmergencyListener, SignalCallback
@Override
public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon,
final int statusType, final int networkIcon, final int volteType,
final int qsType,final boolean activityIn,
final boolean activityOut, 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) {
///M: Support[Network Type and volte on StatusBar].
/// add more parameter networkIcon and volte.
signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType,
networkIcon, volteType, qsType, activityIn, activityOut,
typeContentDescription, description, isWide, subId, roaming);
}
}
});
}
在CallbackHandler的setMobileDataIndicators,去调用各个监听器的同一setMobileDataIndicators,
CallbackHandler实现了统一管理。
通过线索查找,我们发现,真正去通知CallbackHandler调用回调方法的是在MobileSignalController里。
@Override
public void notifyListeners(SignalCallback callback) {
...
callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, networkIcon, volteIcon,
qsTypeIcon,activityIn, activityOut, dataContentDescription, description,
icons.mIsWide, mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
...
}
而
public class MobileSignalController extends SignalController<
MobileSignalController.MobileState, MobileSignalController.MobileIconGroup>
MobileSignalController
MobileSignalController继承了SignalController,
在SignalController里
public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
mCurrentState.inetCondition = validatedTransports.get(mTransportType) ? 1 : 0;
notifyListenersIfNecessary();
}
public void notifyListenersIfNecessary() {
if (isDirty()) {
saveLastState();
notifyListeners();
}
}
public final void notifyListeners() {
notifyListeners(mCallbackHandler);
}
所以,SignalController的notifyListeners,是来自于updateConnectivity。
而反向查找,发现其实是这样的
NetworkControllerImpl
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
updateConnectivity();
}
private void updateConnectivity() {
...
pushConnectivityToSignals();
...
}
private void pushConnectivityToSignals() {
// We want to update all the icons, all at once, for any condition change
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
}
}
发现了一个既定事实,一切起源于NetworkControllerImpl的onReceive。
过程就是下面这个顺序
NetworkControllerImpl
MobileSignalController
CallbackHandler
SignalCallback
SignalClusterView
前面notifyListeners的时候获取了一些icon信息。
@Override
public void notifyListeners(SignalCallback callback) {
MobileIconGroup icons = getIcons();
。。。
int iconId = getCurrentIconId();
。。。
IconState statusIcon = new IconState(mCurrentState.enabled &&
!mCurrentState.airplaneMode,iconId, contentDescription);
。。。
qsIcon = new IconState(mCurrentState.enabled&&
!mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
。。。
int networkIcon = mCurrentState.networkIcon;
int volteIcon = mCurrentState.airplaneMode && !isImsOverWfc()
? 0 : mCurrentState.volteIcon;
。。。
callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, networkIcon, volteIcon,qsTypeIcon,)
。。。
}
MobilePhoneStateListener
这些信息的获取,来自于MobilePhoneStateListener
mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(),
MobilePhoneStateListener有这些重载方法,
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength)
@Override
public void onServiceStateChanged(ServiceState state)
@Override
public void onDataConnectionStateChanged(int state, int networkType)
@Override
public void onCarrierNetworkChange(boolean active)
@Override
public void onCallStateChanged(int state, String incomingNumber)
他们都调用了updateTelephony();
在updateTelephony里,MobileSignalController获取了所需要的关于信号强度,网络连接状态等信息。
最后也回到了
public void notifyListenersIfNecessary() {
if (isDirty()) {
saveLastState();
notifyListeners();
}
}
这和前面的NetworkControllerImpl有相同的地方,区别在于NetworkControllerImpl是用广播接收器更新的,而
MobilePhoneStateListener则是直接通过Telephony系统服务来更新,更新频率更频繁。
就这样,来自系统的信号状态信息汇集到MobileSignalController的notifyListeners里。
然后notifyListeners就最后走到了SignalClusterView的setMobileDataIndicators。
所有的信息都被加载到setMobileDataIndicators,然后就是把各个icon资源显示到状态栏里。
@Override
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;
/// @ }
apply();
}
显示流程与更新流程也到此结束。