android去电流程,android 去电流程
开始看代码。
TwelveKeyDialer.java,既然要打电话,总要先输入号码才拨出,这个类就是拨号盘的界面,只是这个phone用到的类却是放在com.android.contacts包下,应该是出于代码结构的考虑吧。毕竟联系人、拨号盘、通话记录和收藏都是在一个Tab标签里的。这个界面没什么好说的,0-9数字键,P和W(也可能是*和#),P表示直接拨打带有分机号的号码(如2345-0000P1234)时会直接拨分机号,无需要再输入分机号码,而W拨号(如23450000W1234)则会有对话框提示你确认是否拨分机号,就这点区别。
按完电话号码点拨号键,接下来就开始去电流程了,离开TwelveKeyDialer.java前的代码,
voiddialButtonPressed(String ipPrefix) {
Log.d(TAG, "dialButtonPressed");
//注意这个action,只有从拨号盘拨出的才是Intent.ACTION_CALL_PRIVILEGED
//外部调用的是Intent.ACTION_CALL
Intent intent = newIntent(Intent.ACTION_CALL_PRIVILEGED);
//省略次要代码……
intent.setData(Uri.fromParts("tel", number,null));//拼一个电话的Uri,关键代码
StickyTabs.saveTab(this, getIntent());//与拨号无关
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
mDigits.getText().clear(); //清除输入
}
发出来的Intent谁来接收呢,是OutgoingCallBroadcaster.java类(其实拨打电话的方式很多,不一定是拨号盘拨号:可以从联系人拨号,可以是历史记录拨号等,无论是何种拨号,最后一定走向OutgoingCallBroadcaster.java),这是一个中间类,实际我们是看不到它的,这个类先判断号码是否为紧急号码,如果是紧急号码,启动InCallScree.java,并发送广播;如果不是,发送广播“Intent.ACTION_NEW_OUTGOING_CALL”由它的内部类OutgoingCallReceiver接收,从onReceiver()再到doReceiver(),会把action里的字符串统一替换成Intent.ACTION_CALL,启动InCallScreen.java,在这个类也可以做一些其它的业务逻辑判断(比如固定拨号,视频电话等),IncallScreen.java是电话应用的主界面,这个界面负责的东西比较多,所需要做的判断也不少,值得一提的是它重写finish()方法,当调用这个方法时它又把自己放回栈中,这样可提高下次启动的响应速度。
如果是第一次进入IncallScreen,会执行onCreate()
protectedvoidonCreate(Bundle icicle) {
Profiler.callScreenOnCreate();//获得通话界面被创建的时间。
…..省略代码...
setPhone(app.phone); // Sets mPhone
mCM = PhoneApp.getInstance().mCM;
mBluetoothHandsfree = app.getBluetoothHandsfree();//设置蓝牙
if(mBluetoothHandsfree !=null) {
mBluetoothHeadset = newBluetoothHeadset(this,null);
}
initInCallScreen(); //加载界面元素
…..省略代码...
registerForPhoneStates();//注册各种状态
if(icicle ==null) {
mInCallInitialStatus = internalResolveIntent(getIntent()); //这个是关键代码
} else{
mInCallInitialStatus = InCallInitStatus.SUCCESS;
}
mUseTouchLockOverlay = !app.proximitySensorModeEnabled();
Profiler.callScreenCreated();//记录通话界面创建完成后的时间
}
如果是第二次进入会执行onNewIntent()
protectedvoidonNewIntent(Intent intent) {
mInCallInitialStatus = internalResolveIntent(intent);//这个是关键代码
……去掉log代码
}
两个方法都会走到internalResolveIntent(intent),这里我们关心电话拨出的动作是怎么跑下去的,所以InCallScreen里的onResume()方法就不细看了,那里面有关于锁屏和蓝牙连接等逻辑判断。回来继续看internalResolveIntent()的代码。
InCallInitStatus internalResolveIntent(Intent intent) {
……省略很多代码… 传过来的action是Intent.ACTION_CALL,直接看重点
} elseif(action.equals(Intent.ACTION_CALL)
|| action.equals(Intent.ACTION_CALL_EMERGENCY)) {
app.setRestoreMuteOnInCallResume(false);
if(PhoneUtils.hasPhoneProviderExtras(intent)) {
InCallInitStatus status = placeCall(intent);//这是我们要找的
if(status == InCallInitStatus.SUCCESS) {
app.setBeginningCall(true);
}
returnstatus;
} }
(当我看到这篇文章的时候,也按照作者的思路看代码,发现代码不一样,本文的代码是gingerbread的代码,我看的是四核代码,版本应该是4.2的。四核的代码里internalResolveIntent()并没有执行InCallInitStatus status = placeCall(intent);//这是我们要找的 这句,看了注释,placeCall()方法在callcontroller.java里面,后续流程大致相同)
进入placeCall()方法后,会做一些关于是否紧急号码和OTA(Over-the-Air Technology空中下载技术,是通过移动通信(GSM或CDMA)的空中接口对SIM卡数据及应用进行远程管理的技术)的判断,不过我们更关心下面的代码。
if(null!= mProviderGatewayUri && !(isEmergencyNumber || isEmergencyIntent) &&
PhoneUtils.isRoutableViaGateway(number)) {
callStatus = PhoneUtils.placeCallVia(this, phone, number,
contactUri, mProviderGatewayUri);//多了个网关参数
} else{
callStatus = PhoneUtils.placeCall(phone, number, contactUri);//多数调用这里
}
后面switch分支会根据callStatus的值完成相应的功能或提示。到这里到代码就走到PhoneUtils.java里了,placeCall()是一个静态方法调用。里面最重要的代码是
Connection cn = PhoneApp.getInstance().mCM.dial(phone, number);
//也有可能看到下面的代码
Connection cn = phone.dial(number)//如果是这种,会先走到GsmCallTracker.java
顺便提下在这个方法里还会有setAudioMode(),关于音频通道和模式的设置就在这里,这里面的故事也不少,不过要先放放了。下面的代码已经在Framework层了,不管之前的代码在哪里dial,最后都会来到RIL.java。
publicvoiddial(String address,intclirMode, UUSInfo uusInfo, Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
rr.mp.writeString(address);
rr.mp.writeInt(clirMode);
rr.mp.writeInt(0);// UUS information is absent
if(uusInfo ==null) {
rr.mp.writeInt(0);// UUS information is absent
} else{
rr.mp.writeInt(1);// UUS information is present
rr.mp.writeInt(uusInfo.getType());
rr.mp.writeInt(uusInfo.getDcs());
rr.mp.writeByteArray(uusInfo.getUserData());
}
send(rr);
}
跟着RIL_REQUEST_DIAL这个TAG标志向下走来到Reference-ril.c找到相应的case分支,
caseRIL_REQUEST_DIAL:
requestDial(data, datalen, t);
staticvoidrequestDial(void*data, size_t datalen, RIL_Token t){
p_dial = (RIL_Dial *)data;
switch(p_dial->clir) {
case1: clir ="I";break;/*invocation*/
case2: clir ="i";break;/*suppression*/
default:
case0: clir ="";break;/*subscription default*/
}
asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
ret = at_send_command(cmd, NULL);
free(cmd);
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
}
到这里我们的电话基本上算是拨出去了,至于是否成功还要看返回结果,通常形式上的流程是这样的(下面只是很多可能中的一种,也是比较常见的一种),
===>>[SendAT] ATD15812345678//拨号,看到atd是不是会想到贝尔实验室和AT&T呢?
<<====[RecvAT] OK
<<====[RecvAT] +CLCC: 1,0,2,0,0,"15812345678",129,//主动上报clcc
===>>[SendAT] AT+CMUT=0, time=//设置话简静音关
<<====[RecvAT] OK, time=
===>>[SendAT] AT+CLCC //主动查询,
<<====[RecvAT] +CLCC: 1,0,2,0,0,"15812345678",129,//以这一次的clcc为准
这段代码描述这样一个事实,不管模块报上来CLCC数据如何,我们都会重新查询后再上报给应用层,上层收到消息后更新界面和维护Connection里每一路电话的状态。到这一步,去电的流程也算是基本走完了,后面还有些界面状态刷新的代码省略了,对于AT命令那一部分,具体实现要看芯片厂商,表现上不完全一致。
转自 http://blog.csdn.net/baimy1985/article/details/7853268
android去电流程,android 去电流程相关推荐
- Android监听来去电通话录音真正可实行方案,可获取电话接通时状态
最近 经过一段时间研究了Android来去电并且录音的研究,特此作为记录 首先监听来去电并且可以录音得有以下权限: //录音权限 <uses-permission android:name=&q ...
- Android 10.0 PackageManagerService(一)工作原理及启动流程-[Android取经之路]
摘要:PackageManagerService是Android系统核心服务之一,在Android中的非常重要,主要负责APK.jar包等的管理. 阅读本文大约需要花费50分钟. 文章的内容主要还是从 ...
- Android10.0应用进程创建过程以及Zygote的fork流程-[Android取经之路]
摘要:点击手机桌面图标,例如微信,它是如何启动的呢,让我们从系统源码级来一起分析. 阅读本文大约需要花费1小时. 文章的内容主要还是从源码进行分析,虽然又臭又长,但是如果想要学习Android系统源码 ...
- Android10.0系统启动之Launcher(桌面)启动流程-[Android取经之路]
摘要:上一节我们讲完了Android10.0的ActivityManagerService的启动流程,在AMS的最后启动了Launcher进程,今天我们就来看看Launcher的真正启动流程. 阅读本 ...
- Android 10.0 系统服务之ActivityMnagerService-AMS启动流程-[Android取经之路]
摘要:上一节我们讲完了SystemServer的启动过程,这一节接着上一节的步骤,来讲解ActivityManagerService的启动过程. ActivityManagerService简称AMS ...
- 【Android 逆向】Android 进程简介 ( Android 应用启动流程 )
文章目录 前言 一.Android 进程 二.Android 应用启动流程 前言 参考 [Android 逆向]Android 系统文件分析 ( /proc/pid 进程号对应进程目录 | oom_a ...
- 【字节码插桩】Android 打包流程 | Android 中的字节码操作方式 | AOP 面向切面编程 | APT 编译时技术
文章目录 一.Android 中的 Java 源码打包流程 1.Java 源码打包流程 2.字符串常量池 二.Android 中的字节码操作方式 一.Android 中的 Java 源码打包流程 Ja ...
- 【Android 启动过程】Android 应用启动流程 | Activity 启动流程
文章目录 一.Android 系统启动流程 二.Activity 启动流程 一.Android 系统启动流程 打开 Android 手机电源键后 , 先运行 BootLoader , 然后使用 Boo ...
- 【Android 安装包优化】APK 打包流程 ( 文件结构 | 打包流程 | 安装流程 | 安卓虚拟机 )
文章目录 一.APK 文件结构 二.APK 打包流程 三.APK 安装流程 四.安卓虚拟机 一.APK 文件结构 Android 应用的安装包时 以 " .apk " 为后缀的 A ...
- 【Android 应用开发】Android 工程修改包名流程 ( 修改 applicationId | 修改 package | 修改 R 资源引用 | 修改 BuildConfig 引用 )
文章目录 一. Android 工程修改包名流程 二. 修改 applicationId 三. 修改 package 包名 四. AndroidManifest.xml 清单文件组件 五. 修改 R ...
最新文章
- SQL*Plus 系统变量之15 - DESC[RIBE]
- MathType公式行距设置的方法
- htmlparser解析网页内容代码
- Linux驱动修炼之道-内存映射
- NN如何在表格数据中战胜GBDT类模型
- [Protobuf] Mac系统下安装配置及简单使用
- 我的20132014
- 1535C. Unstable String
- first network error, wait for 15 seconds
- java8 streamlist转化
- Java MD5加密工具类
- 判断对错html,js制作单选题,能判断对错
- 蔡勒(Zeller)公式及其推导:快速将任意日期转换为星期数
- 股票预测和股票分析就用FineBI!
- Python将npy文件转换为mat文件
- png怎么转换成jpg格式?如何转换照片格式为jpg?
- git获取ssh密钥
- 琴生不等式(Jensen Inequality)
- 必须了解的待人处事小技巧
- c语言数组子集,C语言实现数组所有子集
热门文章
- Oracle FAST_START_MTTR_TARGET参数的理解
- Flink CEP结合案例详解
- 行业寒冬:我们究竟还要学习哪些Android知识?赶紧收藏!
- android 应用程序入口,小米系统 应用入口之争的另一种思路
- 两个.c文件访问同一个全局变量的用法
- echarts format tooltip
- selenium的弹出框处理
- GoodSync文件同步工具,亲测可用。
- 山东大学类脑实验 五 HMAX 模型实现
- lol显示客户端无法与服务器通讯,lol客户端无法与登录队列怎么办 lol客户端无法与登录队列进行通讯解决办法...