SIM卡开机流程,之前我们已经了解由PhoneFactory类的makeDefaultPhone方法中开始,在这个方法中,新建了一个DefaultPhoneNotifier对象
sPhoneNotifier = new DefaultPhoneNotifier();
那么,先看看google对DefaultPhoneNotifier类的介绍
/**
* broadcast intents
*/
public class DefaultPhoneNotifier implements PhoneNotifier {
......
}
从这个介绍中可以看到这个类的主要工作就是向外发送广播消息,那么,就来看看它是如何来完成其工作的
/*package*/
protected DefaultPhoneNotifier() {
mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
}
构造方法中,仅仅创建了一个对象,这个对象是什么?ITelephonyRegistry,我们可知,实现ITelephonyRegistry的是TelephonyRegistry类,也就是说,其实是新建了一个TelephonyRegister对象
遍观DefaultPhoneNotifier类,发现其都是notify一族的方法,那么我们就直接选取一个方法来看看,其究竟是如何来实现发送广播消息的
@Override
public void notifyDataConnection(Phone sender, String reason, String apnType,
PhoneConstants.DataState state) {
doNotifyDataConnection(sender, reason, apnType, state);
}
private void doNotifyDataConnection(Phone sender, String reason, String apnType,
PhoneConstants.DataState state) {
int subId = sender.getSubId();
long dds = SubscriptionManager.getDefaultDataSubId();
if (DBG) log("subId = " + subId + ", DDS = " + dds);
// TODO
// use apnType as the key to which connection we're talking about.
// pass apnType back up to fetch particular for this one.
TelephonyManager telephony = TelephonyManager.getDefault();
LinkProperties linkProperties = null;
NetworkCapabilities networkCapabilities = null;
boolean roaming = false;
if (state == PhoneConstants.DataState.CONNECTED) {
linkProperties = sender.getLinkProperties(apnType);
networkCapabilities = sender.getNetworkCapabilities(apnType);
}
ServiceState ss = sender.getServiceState();
if (ss != null) roaming = ss.getDataRoaming();
try {
if (mRegistry != null) {
mRegistry.notifyDataConnectionForSubscriber(subId,
convertDataState(state),
sender.isDataConnectivityPossible(apnType), reason,
sender.getActiveApnHost(apnType),
apnType,
linkProperties,
networkCapabilities,
((telephony!=null) ? telephony.getDataNetworkType(subId) :
TelephonyManager.NETWORK_TYPE_UNKNOWN),
roaming);
}
} catch (RemoteException ex) {
// system process is dead
}
}
notifyDataConnection方法,从名称上看,应该是发送数据连接的广播的,那么如何发送的呢?我们来看看notifyDataConnection方法的各个参数
1)第一个参数Phone sender,Phone对象,Phone类是一个接口类,从PhoneFactory的makeDefaultPhone方法的下文,我们知道在M平台中,完整实现Phone接口的只有GSMPhone类和CDMALTEPhone两类,此处我们以GSMPhone来分析
2)第四个参数PhoneConstants.DataState state,是一个枚举类型
接下来看看,doNotifyDataConnection方法中做了哪些操作
1)获取subId
2)通过Phone对象获取一些数据
3)调用TelephonyRegistry对象的notifyDataConnectionForSubscriber方法
那么,接下来我们进入TelephonyRegistry对象的notifyDataConnectionForSubscriber方法看看,其究竟做了哪些操作
public void notifyDataConnectionForSubscriber(int subId, int state,
boolean isDataConnectivityPossible, String reason, String apn, String apnType,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int networkType, boolean roaming) {
if (!checkNotifyPermission("notifyDataConnection()" )) {
return;
}
......
synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId);
if (validatePhoneId(phoneId)) {
......
boolean modified = false;
if (state == TelephonyManager.DATA_CONNECTED) {
if (!mConnectedApns[phoneId].contains(apnType)
&& !apnType.equals(PhoneConstants.APN_TYPE_IMS)) {
mConnectedApns[phoneId].add(apnType);
if (mDataConnectionState[phoneId] != state) {
mDataConnectionState[phoneId] = state;
modified = true;
}
}
} else {
if (mConnectedApns[phoneId].remove(apnType)) {
if (mConnectedApns[phoneId].isEmpty()) {
mDataConnectionState[phoneId] = state;
modified = true;
} else {
// leave mDataConnectionState as is and
// send out the new status for the APN in question.
}
}
}
mDataConnectionPossible[phoneId] = isDataConnectivityPossible;
mDataConnectionReason[phoneId] = reason;
mDataConnectionLinkProperties[phoneId] = linkProperties;
mDataConnectionNetworkCapabilities[phoneId] = networkCapabilities;
if (mDataConnectionNetworkType[phoneId] != networkType) {
mDataConnectionNetworkType[phoneId] = networkType;
// need to tell registered listeners about the new network type
modified = true;
}
if (modified) {
......
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) && idMatch(r.subId, subId, phoneId)) {
try {
......
r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
mDataConnectionNetworkType[phoneId]);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
}
}
handleRemoveListLocked();
}
mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
apnType, apn, reason, linkProperties, "");
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
try {
r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
}
}
}
handleRemoveListLocked();
}
broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
apnType, linkProperties, networkCapabilities, roaming, subId);
broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason,
linkProperties, "");
}
从上述的方法代码中可以看到,其主要是做了
1)判断是否拥有android.Manifest.permission.MODIFY_PHONE_STATE权限,若有,则继续,若无,则返回
2)判断为有效的卡槽,则根据传输过来的一些数据,给当前卡槽对应赋值,并在数据网络类型有变化的时候,调用相匹配的Record对象中的callback参数的onDataConnectionStateChanged方法,通知更新
3)发送TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED和TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED广播,通知更新
接下来,我们看看这个地方的Record是什么东西?我们从目前位置往上追踪,确认mRecords中的数据来源
遍观全类,我们看到,其是在listen方法中添加Record数据的,而listen方法,从全局搜索来看,是在TelephonyManager的listen方法中调用的,这个具体数据,后续继续分析~