(M)SIM卡开机流程分析之DefaultPhoneNotifier类分析

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方法中调用的,这个具体数据,后续继续分析~

你可能感兴趣的:(SIM卡开机流程分析)