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

Posted 古冥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,最后实现去电。

以上是关于android6.0 Phone源码分析之Phone适配过程的主要内容,如果未能解决你的问题,请参考以下文章

android6.0源码分析之Camera API2.0下的video流程分析

android6.0源码分析之Camera API2.0下的Capture流程分析

android6.0源码分析之Camera API2.0下的Capture流程分析

Camera API2.0的应用

Camera API2.0的应用

android6.0源码分析之蓝牙框架简介