android6.0 Phone源码分析之Phone适配过程
2016-02-26 13:41
489 查看
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,最后实现去电。
相关文章推荐
- Android Launcher抽屉类SlidingDrawer的使用!
- Android常用名令集锦
- <转>Android 文件夹访问路径~
- AndroidStudio使用注意事项
- Android 文件导入导出命令
- Android SQLite数据存储的通用设计
- 怎样编写Android界面使你的代码易于重构和维护(有demo示例)
- Android广播机制
- Android开源项目集合
- Android View的事件分发机制(一):View
- Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)(转载)
- Android LayoutInflater(布局填充器)的详解
- Android仿美团团购详情页下拉图片放大效果,简单可直接用在项目中
- Android单元測试之JUnit
- Android各版本代号、版本号、API/NDK级别、发布时间及市场份额
- Loading data for Android 5.0
- Android include标签 放置的顺序问题
- Android之多种Bitmap效果
- EnevtBus 发布、订阅消息--android
- Android之混淆心得与亲身体验