android6.0 Phone源码分析之Phone适配过程

android6.0 Phone源码分析之Phone适配过程

分析过Phone源码的人知道,在Phone去电过程中会调用到phone.dial()方法,而此处的Phone可以为GSMPhone或者CDMALTEPhone。对于Phone的适配,android采用了工厂模式。本文主要分析Phone的适配过程,重要的类主要有PhoneApp, PhoneFactory,PhoneGlobals等。


1.Phone进程的初始化

在android系统中,有许多永久存在的应用,它们对应的设置是androidmanifest.xml文件的persistent属性,若属性值为true,则此应用为永久性应用,系统开机启动时会自动加载。此外,若应用因某种原因退出,系统会再次自动启动此应用。而在Phone应用中的PhoneApp类在androidmanifest.xml中的persistent属性为true。

<application android:name="PhoneApp"
             android:persistent="true"
             android:label="@string/phoneAppLabel"
             android:icon="@mipmap/ic_launcher_phone"
             android:allowBackup="false"
             android:supportsRtl="true"
             android:usesCleartextTraffic="true">
             <provider android:name="IccProvider"

分析PhoneApp类:

@Override
public void onCreate() {
       if (UserHandle.myUserId() == 0) {
       // We are running as the primary user, so should bring up 
       // the global phone state.
       mPhoneGlobals = new PhoneGlobals(this);
       mPhoneGlobals.onCreate();

       mTelephonyGlobals = new TelephonyGlobals(this);
       mTelephonyGlobals.onCreate();
 }

在PhoneApp类启动后,会在onCreate()中初始化PhoneGlobals和TelephonyGlobals两个类。PhoneGlobals类用来初始化phone,以及获取phone,而TelephonyGlobals类主要用来处理PSTN呼叫,它是5.0新添加的类,先分析PhoneGlobals。

2.PhoneGlobals类分析

public void onCreate() {
       ...
       if (mCM == null) {
            // Initialize the telephony framework
            PhoneFactory.makeDefaultPhones(this);

            // Start TelephonyDebugService After the default 
            // phone is created.
            Intent intent = new Intent(this,
                          TelephonyDebugService.class);
            startService(intent);
            //获取CallManager实例
            mCM = CallManager.getInstance();
            for (Phone phone : PhoneFactory.getPhones()) {
                //将phone注册到CallManager中
                mCM.registerPhone(phone);
            }
            ...
            // Create the CallController singleton, which is the 
            //interface to the telephony layer for user-initiated 
            //telephony functionality(like making outgoing calls)
            //初始化callController
            callController = CallController.init(this,           
                           callLogger, callGatewayManager);
            ...
 }

由以上代码可知,PhoneGlobals类先通过PhoneFactory初始化Phone,然后将所有的Phone注册到CallManager,此时就可以通过PhoneFactory的getPhone(int phoneId)方法,通过phoneId来获取相应的Phone.接着先分析makeDefaultPhones()方法。

public static void makeDefaultPhone(Context context) {
       ...
       //获取Phone的sim数量
       int numPhones =  
           TelephonyManager.getDefault().getPhoneCount();
       ...
       //循环对所有的Sim卡进行Phone类型的初始化
       for (int i = 0; i < numPhones; i++) {
           PhoneBase phone = null;
           //获取Phone的类型
           int phoneType =TelephonyManager
                         .getPhoneType(networkModes[i]);
           if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
               //初始化为GSM模式
               phone = new GSMPhone(context,
                   sCommandsInterfaces[i],sPhoneNotifier, i);
               phone.startMonitoringImsService();
            } else if (phoneType ==                          
                      PhoneConstants.PHONE_TYPE_CDMA) {
                //初始化为CMDALTE模式
                phone = new CDMALTEPhone(context,
                      sCommandsInterfaces[i], sPhoneNotifier, i);
                phone.startMonitoringImsService();
            }
            //生成Phone代理,并放入PhoneFactory的工厂
            sProxyPhones[i] = new PhoneProxy(phone);
        }
        //将PhoneFactory的所有Phone代码交给ProxyController管理
        mProxyController = ProxyController.getInstance(context, 
             sProxyPhones,mUiccController, sCommandsInterfaces);
        ...
 }

首先获取Phone中sim卡的数量,然后分别对对应的Sim卡进行Phone的初始化,可以初始化为GSMPhone和CDMALTEPhone两种。接着将其加入到PhoneFactory的ProxyPhones数组中进行,最后再将其交给ProxyController进行控制管理,至此,Phone的准备工作已经结束。

3.Phone适配

在去电过程(MO)中,会调用onCreateOutgoingConnection()创建去电Connection

@Override
public Connection onCreateOutgoingConnection(
       PhoneAccountHandle connectionManagerPhoneAccount,
            final ConnectionRequest request) {
       //根据请求获取tel
       Uri handle = request.getAddress();
       ...
       //获取PhoneAccount的类型
       String scheme = handle.getScheme();
       ...
       //获取Phone
       final Phone phone = getPhoneForAccount(
                           request.getAccountHandle(), false);
       ...
       //创建连接
       final TelephonyConnection connection =
                createConnectionFor(phone, null, true /* isOutgoing */, request.getAccountHandle());
       ...
       //设置tel
       connection.setAddress(handle, 
                  PhoneConstants.PRESENTATION_ALLOWED);
       //初始化
       connection.setInitializing();
       connection.setVideoState(request.getVideoState());
       if (useEmergencyCallHelper) {//紧急号码
           ...
       }else{//非紧急号码,根据初始化好的connection创建连接
           placeOutgoingConnection(connection, phone, request);
       }
       return connection;
}

由以上代码可知,根据请求通过getPhoneForAccount()方法来获取Phone.

private Phone getPhoneForAccount(PhoneAccountHandle 
                           accountHandle, boolean isEmergency) {
    if (isEmergency) {//紧急号码
        return PhoneFactory.getDefaultPhone();
    }
    //获取subId
    int subId = PhoneUtils.
              getSubIdForPhoneAccountHandle(accountHandle);
    if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {//有效ID
        //获取phoneId
        int phoneId = SubscriptionController.
                    getInstance().getPhoneId(subId);
        //根据phoneId从PhoneFactory获取Phone
        return PhoneFactory.getPhone(phoneId);
    }
    return null;
}

首先通过PhoneUtils获取subId,然后再从SubscriptionController中获取相应的phoneId,最后再根据phoneId从PhoneFactory中获取phone.

public static int getSubIdForPhoneAccountHandle(
        PhoneAccountHandle handle) {
    if (handle != null && handle.getComponentName().
            equals(getPstnConnectionServiceName())) {
        Phone phone = getPhoneFromIccId(handle.getId());
        if (phone != null) {
            return phone.getSubId();
        }
    }
    return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}

接着分析getPhoneFromIccId()方法.

private static Phone getPhoneFromIccId(String iccId) {
    if (!TextUtils.isEmpty(iccId)) {
        for (Phone phone : PhoneFactory.getPhones()) {
            String phoneIccId = phone.getIccSerialNumber();
            if (iccId.equals(phoneIccId)) {
                return phone;
            }
        }
    }
    return null;
}

由代码可知,通过比较所有Phone与此Account的iccId来获取相应的phone.最后会通过得到的phone来创建相应的Connection,最后实现去电。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值