1. TelephonyRegistryAOSP中的路径为:frameworks\base\services\core\java\com\android\server,它是作为安卓电话子系统中所有状态监听回调的集中管理的地方,应用对电话相关状态的监听主要注册在这里。它继承自ITelephonyRegistry.Stub,作为系统服务,在SystemServer.java中创建,并加入ServiceManager
    1. public static void main(String[] args){
    2. new SystemServer().run();
    3. }
    4. //在run()方法中,调用startOtherServices()
    5. //startOtherServices()中
    6. private void startOtherServices(){
    7. ...
    8. telephonyRegistry = new TelephonyRegistry(
    9. context, new TelephonyRegistry.ConfigurationProvider());
    10. ServiceManager.addService("telephony.registry", telephonyRegistry);
    11. ...
    12. }

    下面进入TelephonyRegistry的源码中查看,里面一大堆记录各种状态的数组,数组的长度取决于激活的卡的数量,

    1. private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
    2. private final ArrayList<Record> mRecords = new ArrayList<Record>();
    3. private int mNumPhones;
    4. private int[] mCallState;
    5. private String[] mCallIncomingNumber;
    6. private ServiceState[] mServiceState;
    7. private int[] mVoiceActivationState;
    8. private int[] mDataActivationState;
    9. private boolean[] mUserMobileDataState;
    10. private TelephonyDisplayInfo[] mTelephonyDisplayInfos;
    11. private SignalStrength[] mSignalStrength;
    12. private boolean[] mMessageWaiting;
    13. private boolean[] mCallForwarding;
    14. private int[] mDataActivity;
    15. // Connection state of default APN type data (i.e. internet) of phones
    16. private int[] mDataConnectionState;
    17. private CellIdentity[] mCellIdentity;
    18. private int[] mDataConnectionNetworkType;
    19. private ArrayList<List<CellInfo>> mCellInfo = null;
    20. private Map<Integer, List<EmergencyNumber>> mEmergencyNumberList;
    21. private EmergencyNumber[] mOutgoingSmsEmergencyNumber;
    22. private EmergencyNumber[] mOutgoingCallEmergencyNumber;
    23. private CallQuality[] mCallQuality;
    24. private CallAttributes[] mCallAttributes;

    其中最关键的就是mRecords,它是对客户端Binder注册进来的回调的实例的封装:

    1. private Record add(IBinder binder, int callingUid, int callingPid, boolean doesLimitApply) {
    2. Record r;
    3. synchronized (mRecords) {
    4. final int N = mRecords.size();
    5. // While iterating through the records, keep track of how many we have from this pid.
    6. int numRecordsForPid = 0;
    7. for (int i = 0; i < N; i++) {
    8. r = mRecords.get(i);
    9. if (binder == r.binder) {
    10. // Already existed.
    11. return r;
    12. }
    13. if (r.callerPid == callingPid) {
    14. numRecordsForPid++;
    15. }
    16. }
    17. // If we've exceeded the limit for registrations, log an error and quit.
    18. int registrationLimit = mConfigurationProvider.getRegistrationLimit();
    19. if (doesLimitApply
    20. && registrationLimit >= 1
    21. && numRecordsForPid >= registrationLimit) {
    22. String errorMsg = "Pid " + callingPid + " has exceeded the number of permissible"
    23. + " registered listeners. Ignoring request to add.";
    24. loge(errorMsg);
    25. if (mConfigurationProvider
    26. .isRegistrationLimitEnabledInPlatformCompat(callingUid)) {
    27. throw new IllegalStateException(errorMsg);
    28. }
    29. } else if (doesLimitApply && numRecordsForPid
    30. >= PhoneStateListener.DEFAULT_PER_PID_REGISTRATION_LIMIT / 2) {
    31. // Log the warning independently of the dynamically set limit -- apps shouldn't be
    32. // doing this regardless of whether we're throwing them an exception for it.
    33. Rlog.w(TAG, "Pid " + callingPid + " has exceeded half the number of permissible"
    34. + " registered listeners. Now at " + numRecordsForPid);
    35. }
    36. r = new Record();
    37. r.binder = binder;
    38. r.deathRecipient = new TelephonyRegistryDeathRecipient(binder);
    39. try {
    40. binder.linkToDeath(r.deathRecipient, 0);
    41. } catch (RemoteException e) {
    42. if (VDBG) log("LinkToDeath remote exception sending to r=" + r + " e=" + e);
    43. // Binder already died. Return null.
    44. return null;
    45. }
    46. mRecords.add(r);
    47. if (DBG) log("add new record");
    48. }
    49. return r;
    50. }

    在addOnSubscriptionsChangedListener中会被调用,而在各个notifyXXX方法中,会遍历该mRecords,调用对应的回调方法。

    1. public void notifyCallState(int phoneId, int subId, int state, String incomingNumber) {
    2. if (!checkNotifyPermission("notifyCallState()")) {
    3. return;
    4. }
    5. if (VDBG) {
    6. log("notifyCallState: subId=" + subId
    7. + " state=" + state + " incomingNumber=" + incomingNumber);
    8. }
    9. synchronized (mRecords) {
    10. if (validatePhoneId(phoneId)) {
    11. mCallState[phoneId] = state;
    12. mCallIncomingNumber[phoneId] = incomingNumber;
    13. for (Record r : mRecords) {
    14. if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
    15. (r.subId == subId) &&
    16. (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
    17. try {
    18. String incomingNumberOrEmpty = getCallIncomingNumber(r, phoneId);
    19. r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
    20. } catch (RemoteException ex) {
    21. mRemoveList.add(r.binder);
    22. }
    23. }
    24. }
    25. }
    26. handleRemoveListLocked();
    27. }
    28. broadcastCallStateChanged(state, incomingNumber, phoneId, subId);
    29. }

    通过代码搜索,发现TelephonyRegistry只在SystemServer中使用了,所以其他任何形式的访问必须通过其对应的客户端代理来进行访问。ITelephonyRegistry的客户端在TelephonyRegistryManager中:

    1. public class TelephonyRegistryManager{
    2. private static ITelephonyRegistry sRegistry;
    3. public TelephonyRegistryManager(@NonNull Context context) {
    4. mContext = context;
    5. if (sRegistry == null) {
    6. sRegistry = ITelephonyRegistry.Stub.asInterface(
    7. ServiceManager.getService("telephony.registry"));
    8. }
    9. }
    10. }

    TelephonyRegistryManager中的许多方法都是对sRegistry调用的封装,例如提供给应用添加监听的方法:

    1. public void listenForSubscriber(int subId, @NonNull String pkg, @NonNull String featureId,
    2. @NonNull PhoneStateListener listener, int events, boolean notifyNow) {
    3. try {
    4. // subId from PhoneStateListener is deprecated Q on forward, use the subId from
    5. // TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q.
    6. if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
    7. // Since mSubId in PhoneStateListener is deprecated from Q on forward, this is
    8. // the only place to set mSubId and its for "informational" only.
    9. listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
    10. ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
    11. } else if (listener.mSubId != null) {
    12. subId = listener.mSubId;
    13. }
    14. sRegistry.listenForSubscriber(
    15. subId, pkg, featureId, listener.callback, events, notifyNow);
    16. } catch (RemoteException e) {
    17. throw e.rethrowFromSystemServer();
    18. }
    19. }

    该方法在TelephonyManager中的listen()方法中被调用。

    1. public class TelephonyManager{
    2. public void listen(PhoneStateListener listener, int events) {
    3. if (mContext == null) return;
    4. boolean notifyNow = (getITelephony() != null);
    5. TelephonyRegistryManager telephonyRegistry =
    6. (TelephonyRegistryManager)
    7. mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
    8. if (telephonyRegistry != null) {
    9. telephonyRegistry.listenForSubscriber(mSubId, getOpPackageName(), getAttributionTag(),
    10. listener, events, notifyNow);
    11. } else {
    12. Rlog.w(TAG, "telephony registry not ready.");
    13. }
    14. }
    15. }

    为啥可以调用mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE)来获取TelephonyRegistryManger的实例呢?原来在SystemServiceRegistry中,TelephonyRegistryManager类被注册为SystemService了:

    1. static{
    2. registerService(Context.TELEPHONY_REGISTRY_SERVICE, TelephonyRegistryManager.class,
    3. new CachedServiceFetcher<TelephonyRegistryManager>() {
    4. @Override
    5. public TelephonyRegistryManager createService(ContextImpl ctx) {
    6. return new TelephonyRegistryManager(ctx);
    7. }});
    8. }

    继续搜索TelephonyRegistryManager的使用,发现在DefaultPhoneNotifier中,TelephonyRegistryManager作为私有成员变量使用,而且DefaultPhoneNotifier中的各种notifyXXX方法都是对TelephonyRegistryManager的方法的封装:

    1. public class DefaultPhoneNotifier implements PhoneNotifier {
    2. private TelephonyRegistryManager mTelephonyRegistryMgr;
    3. //在构造方法中通过context.getSystemService()实例化
    4. public DefaultPhoneNotifier(Context context) {
    5. mTelephonyRegistryMgr = (TelephonyRegistryManager) context.getSystemService(
    6. Context.TELEPHONY_REGISTRY_SERVICE);
    7. }
    8. @Override
    9. public void notifyPhoneState(Phone sender) {
    10. Call ringingCall = sender.getRingingCall();
    11. int subId = sender.getSubId();
    12. int phoneId = sender.getPhoneId();
    13. String incomingNumber = "";
    14. if (ringingCall != null && ringingCall.getEarliestConnection() != null) {
    15. incomingNumber = ringingCall.getEarliestConnection().getAddress();
    16. }
    17. mTelephonyRegistryMgr.notifyCallStateChanged(subId, phoneId,
    18. PhoneConstantConversions.convertCallState(sender.getState()), incomingNumber);
    19. }
    20. @Override
    21. public void notifyServiceState(Phone sender) {
    22. ServiceState ss = sender.getServiceState();
    23. int phoneId = sender.getPhoneId();
    24. int subId = sender.getSubId();
    25. Rlog.d(LOG_TAG, "notifyServiceState: mRegistryMgr=" + mTelephonyRegistryMgr + " ss="
    26. + ss + " sender=" + sender + " phondId=" + phoneId + " subId=" + subId);
    27. if (ss == null) {
    28. ss = new ServiceState();
    29. ss.setStateOutOfService();
    30. }
    31. mTelephonyRegistryMgr.notifyServiceStateChanged(subId, phoneId, ss);
    32. }
    33. @Override
    34. public void notifySignalStrength(Phone sender) {
    35. int phoneId = sender.getPhoneId();
    36. int subId = sender.getSubId();
    37. if (DBG) {
    38. // too chatty to log constantly
    39. Rlog.d(LOG_TAG, "notifySignalStrength: mRegistryMgr=" + mTelephonyRegistryMgr
    40. + " ss=" + sender.getSignalStrength() + " sender=" + sender);
    41. }
    42. mTelephonyRegistryMgr.notifySignalStrengthChanged(subId, phoneId,
    43. sender.getSignalStrength());
    44. }
    45. }

    继续追踪DefaultPhoneNotifier的使用,发现在PhoneFactory中,作为静态成员变量:

    1. class PhoneFactory{
    2. static private PhoneNorifier sPhoneNotifier;
    3. public static void makeDefaultPhone(Context context) {
    4. ···
    5. sPhoneNotifier = new DefaultPhoneNotifier(context)
    6. ···
    7. }
    8. private static Phone createPhone(Context context, int phoneId) {
    9. int phoneType = TelephonyManager.getPhoneType(RILConstants.PREFERRED_NETWORK_MODE);
    10. Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " phoneId = " + phoneId);
    11. // We always use PHONE_TYPE_CDMA_LTE now.
    12. if (phoneType == PHONE_TYPE_CDMA) phoneType = PHONE_TYPE_CDMA_LTE;
    13. TelephonyComponentFactory injectedComponentFactory =
    14. TelephonyComponentFactory.getInstance().inject(GsmCdmaPhone.class.getName());
    15. return injectedComponentFactory.makePhone(context,
    16. sCommandsInterfaces[phoneId], sPhoneNotifier, phoneId, phoneType,
    17. TelephonyComponentFactory.getInstance());
    18. }
    19. public static SipPhone makeSipPhone(String sipUri) {
    20. return SipPhoneFactory.makePhone(sipUri, sContext, sPhoneNotifier);
    21. }
    22. }

    发现DefaultPhoneNotifier主要用于构造Phone对象时,作为参数传进去。那就进Phone的源码里看看:

    1. class Phone{
    2. @UnsupportedAppUsage
    3. protected PhoneNotifier mNotifier;
    4. }

    原来Phone类里,有个PhoneNotifier类型的protected成员变量。,我们再看看 mNotifier在Phone类中如何使用的:

    1. class Phone{
    2. public void notifyPhoneStateChanged() {
    3. mNotifier.notifyPhoneState(this);
    4. }
    5. public void notifyDisconnect(Connection cn) {
    6. mDisconnectRegistrants.notifyResult(cn);
    7. mNotifier.notifyDisconnectCause(this, cn.getDisconnectCause(),
    8. cn.getPreciseDisconnectCause());
    9. }
    10. public void notifyLocationChanged(CellIdentity cellIdentity) {
    11. mNotifier.notifyCellLocation(this, cellIdentity);
    12. }
    13. ...
    14. }

    就此一切就都明朗了,应用通过实现PhoneStateListener接口,调用TelephonyManager的listen()方法,将回调监听添加到TelephonyRegistry系统服务中,然后,各个Phone实例通过调用内部mNotifier的各种notifyXXX方法,来实现Telephony状态的上报,再回调到各个添加了监听的应用中。