Android通话过程分析.docx

上传人:b****8 文档编号:11074257 上传时间:2023-02-24 格式:DOCX 页数:20 大小:40.16KB
下载 相关 举报
Android通话过程分析.docx_第1页
第1页 / 共20页
Android通话过程分析.docx_第2页
第2页 / 共20页
Android通话过程分析.docx_第3页
第3页 / 共20页
Android通话过程分析.docx_第4页
第4页 / 共20页
Android通话过程分析.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

Android通话过程分析.docx

《Android通话过程分析.docx》由会员分享,可在线阅读,更多相关《Android通话过程分析.docx(20页珍藏版)》请在冰豆网上搜索。

Android通话过程分析.docx

Android通话过程分析

Android 通话过程分析

本文档主要对 android 平台下的 call 的实现做详细分析。

Call 处理的五大核心分别是:

Call,Phone,

CallTracker,DriverCall,Connection

1.Call

Call 是 Call 应用中的最基本的单位,其主要是用来管理 Connection 的。

Call 中非常重要

的是其状态,Call 中共有九种状态:

IDLE, ACTIVE, HOLDING, DIALING, ALERTING, INCOMING, WAITING, DISCONNECTED,

DISCONNECTING;

对 call 的处理实际上是对状态转换上的处理。

对这九中状态所对应的含义和 call 此时的

现状要很熟。

Call 的继承关系图:

Call

+hangup()

+hangupAllCalls()

+getConnections()

 

GsmCall

#connections

+attach()

+attachFake()

+detach()

+isFull() :

 bool

+clearDisconnected()

CdmaCall

#connections

+attach()

+attachFake()

+detach()

+isFull() :

 bool

+clearDisconnected()

Call 是一个抽象类,从图中可知,实际操作是在其子类 GsmCall 和 CdmaCall。

GsmCall 中,有个成员变量:

connections,这个变量是用来管理 Call 中的 connection 的,

一个 Call 最大允许有 5 个 connections:

static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call

2.Phone

Phone 不仅是 call 的处理核心,而且是整个 Telephony 处理的核心。

Phone 是一个最基

本的概念,用来控制 Phone 系统相关(即无线相关的)模块的处理:

simcard,call,message,datacall 等。

Phone 的继承关系如下:

<<接口>>

Phone

 

PhoneBase

#mPhoneId :

 int

 

GsmPhone

Hander

+handleMessage()

 

PhoneProxy

-mActivePhone :

 Phone

 

CdmaPhone

#GsmCallTracker mCT

+dial()

+rejectCall()

+acceptCall()

+switchHoldingAndActive()

#CdmaCallTracker mCT

+dial()

+rejectCall()

+acceptCall()

+switchHoldingAndActive()

在 Phone 的继承关系中可知,Phone 只是一个接口,它被 PhoneBase 和 PhoneProxy 实

现,而 PhoneBase 是抽象类,它被 GsmPhone 和 CdmaPhone 继承。

所以有此可知

Phone 分为两类:

GsmPhone 和 CdmaPhone。

PhoneBase 还有另外一个继承关系:

继承自 Handler。

这就说明 GsmPhone 和

CdmaPhone 其实都是一个 Handler。

所以 PhoneBase 的子类是可以进行事件处理的。

 

3.Connection

Connection 用来处理一个真正的通话通路,包含通话过程中 call 的数据,包括号码、通

话时间、MT 还是 MO、是第几路通话、挂断原因等信息。

Connection 类关系图:

Connection

 

GsmConnectionCdmaConnection

 

CallTracker

 

GsmConnection 中有个成员变量:

GsmCallparent,这个成员变量是用来表示该

connection 是属于哪个 Call 的。

由变量名(parent)可以看出 Call 与 Connection 的关系:

父与子的关系,一个 Call 可以有多个 Connection(3gpp 中规定最多 5 个),但一个

Connection 只能属于一个 Call。

所以一个 Connection 必定要依附于一个 Call。

Connection 是怎样依附于一个 Call 的呢?

从 Connection 的构造方法中就可以知道:

a.GsmConnection (Context context, DriverCall dc, GsmCallTracker ct, int index)

这个构造方法是在 MT 的时候使用的,因为它有一个 DriverCall 的参数。

它通过

parentFromDCState 方法来获得对应的 parent(Call)且通过

parent.attach(this, dc);把 connection 加入到 Call 的 Connections 变量

进行管理。

b.GsmConnection (Context context, String dialString, GsmCallTracker ct, GsmCall parent)

这个构造方法是在 MO 的时候使用的,它会传入一个指定的 parent(Call)且通过

parent.attachFake(this,GsmCall.State.DIALING);调用把 Connection 加入到 Call 的

Connections 变量进行管理。

从上面知道 Connection 调用了 Call 的 2 个重要的方法:

Attach 和 attachFake。

两个方法都是把一个 connection 加入到 Call 的 Connections 成员变量中进行管理的。

Call 中还有一个方法 detach(GsmConnectionconn),这个方法是用来把 connection

从 Call 中移除的。

其中还有一个方法:

/*package*/booleanupdate(DriverCalldc)。

这个是用来更新

connection 的。

4.DriverCall

是与 ril 层通信时的一个中间处理类,主要用来接收到 ril 的 call 数据后转到到 java 层上

来。

DriverCall 中包含了协议中规定的有关 call 的相关参数,具体如下:

public int index; //Connection Index for use with, eg, AT+CHLD

public boolean isMT; //是 incoming 还是 outgoing

public State state; //connection state。

public boolean isMpty;// nonzero if is mpty call。

public String number;// Remote party number

public int TOA; //type of address, eg 145 = intl

public boolean isVoice;// nonzero if this is is a voice call

public boolean isVoicePrivacy;// nonzero if CDMA voice privacy mode is active

public int als;// ALS line indicator if available (0 = line 1)

public int numberPresentation;// 0=Allowed, 1=Restricted, 2=Not Specified/Unknown

3=Payphone

public String name;// Remote party name

public int namePresentation;// 0=Allowed, 1=Restricted, 2=Not Specified/Unknown

3=Payphone

5.CallTracker

CallTracker 的类关系图:

 

GsmConnection

Handler

 

CallTracker

#pendingOperations :

 int

#needsPoll :

 bool

-Message lastRelevantPoll

 

<<接口>>

CommandsInterface

GsmPhone

 

GsmCall

GsmCallTracker

#ringingCall :

 GsmCall

#foregroundCall :

 GsmCall

#backgroundCall :

 GsmCall

#connections[] :

 GsmConnection

CdmaCallTracker

#ringingCall :

 CdmaCall

#foregroundCall :

 CdmaCall

#backgroundCall :

 CdmaCall

#connections[] :

 CdmaConnection

CdmaPhone

 

CdmaCall

 

CdmaConnection

 

从上图中可以看到,CallTracker 在本质上是一个 Handler。

CallTracker 是一个抽象类,所以其实际的操作对象是其子类:

GSMCallTracker 和

CdmaCallTracker。

下面以 GSMCallTracker 为例介绍 CallTracker 的相关处理,CdmaCallTracker 处理基本与

之相同。

GSMCallTracker 是 Android 的通话管理层。

GSMCallTracker 建立了 ConnectionList 来管

理现行的通话连接,并向上层提供电话调用接口。

1) Connections

Connections 是 GSMCallTracker 用来维护所有的通话的列表,最大可维护 7 路通话。

static final int MAX_CONNECTIONS = 7;// only 7 connections allowed in GSM

2) ringingCall、foregroundCall、backgroundCall

一个手机系统只允许 3 个 Call 同时存在,即 ring call、active call 和 held call,所以

GSMCallTracker 用 ringingCall、foregroundCall、backgroundCall 来管理。

ringingCall:

用来管理 INCOMING 和 WAITING 的通话

foregroundCall:

用来管理 DAILING、ALERTING、ACTIVE 的通话

backgroundCall:

用来管理 HOLD 的通话

那么,ringingCall、foregroundCall、backgroundCall 是如何来管理对应的 call 和

connection 的呢?

前面已经讲过了 Call 和 Connection 及它们之间的关系,其实系统

中的 Call 是已经存在的,就是上面的 3 个,其实主要的是对于一个 connection,它

需要依附于那个 call,由 connection 的构造方法知:

1) 在从 RIL 获取的 Calls 列表的时候,通过 parentFromDCState 来获取相应的

Call:

private GsmCall

parentFromDCState (DriverCall.State state) {

switch (state) {

case ACTIVE:

case DIALING:

case ALERTING:

return owner.foregroundCall;

//break;

case HOLDING:

return owner.backgroundCall;

//break;

case INCOMING:

case WAITING:

return owner.ringingCall;

//break;

default:

throw new RuntimeException("illegal call state:

 " +

state);

}

}

2) 在其他情况下,一般根据上面的状态直接传入对应的 call。

3) GsmCallTracker 中的事件处理机制

Call 的事件处理基本上是请求应答模式,具体如下(以 dail 为例,其他类同):

 

其中涉及到 3 个变量的处理:

protected int pendingOperations;

protected boolean needsPoll;

protected Message lastRelevantPoll;

pendingOperations:

顾名思义,这个变量是在发生请求的时候会++,在处理应答

的时候会--。

needsPoll:

该变量是用来配合pendingOperations处理是否需要从RIL获取当前

calls列表,并更新connections列表。

lastRelevantPoll:

在发送RIL_REQUEST_GET_CURRENT_CALLS的时候记录最近

一次请求的message,在response的时候只对最近一次请求的response做出响应,

更新connections列表。

上面的3个变量主要是用来判断是否需要发送RIL_REQUEST_GET_CURRENT_CALLS请

求来从RIL获取当前的calls列表,并更新connections列表。

 

if (pendingOperations == 0 && needsPoll) {

lastRelevantPoll= obtainMessage(EVENT_POLL_CALLS_RESULT);

cm.getCurrentCalls(lastRelevantPoll);

 

4) GsmCallTracker 的核心处理方法----更新 connections 列表处理方法

protected void handlePollCalls(AsyncResult ar)的处理分析

handlePollCalls(AsyncResult ar) {

List polledCalls;

if(DBG_POLL) log(">handlePollCalls");

if (ar.exception == null) {

//没有异常,取得calllists列表

polledCalls = (List)ar.result;

} else if (isCommandExceptionRadioNotAvailable(ar.exception)) {

//如果radio是RADIO_NOT_AVAILABLE,则挂断所有的calls,这里的意思是所有

的DriverCall是null。

polledCalls = new ArrayList();

} else {

//其他的异常的话,推迟POLL_DELAY_MSEC = 250后再发送

//RIL_REQUEST_GET_CURRENT_CALLS去获取DriverCall列表。

pollCallsAfterDelay();

return;

}

Connection newRinging = null; //or waiting

boolean hasNonHangupStateChanged = false;// Any change besides

// a dropped connection

boolean needsPollDelay = false;

boolean unknownConnectionAppeared = false;

//遍历DriverCall和Connections,根据不同情况做相应处理。

for (int i = 0, curDC = 0, dcSize = polledCalls.size()

; i < connections.length; i++) {

GsmConnection conn = connections[i];

DriverCall dc = null;

// polledCall list is sparse

if (curDC < dcSize) {

dc = (DriverCall) polledCalls.get(curDC);

//此处说明connections数组的index+1就是callId,也即dc.index。

if (dc.index == i+1) {

curDC++;

} else {

dc = null;

}

}

 

if (conn == null && dc !

= null) {

 

} else if (conn !

= null && dc == null) {

 

} else if (conn !

= null && dc !

= null && !

pareTo(dc))

{

} else if (conn !

= null && dc !

= null) {

//此处表明connection和dc是同一个call,随后根据dc来更新connection。

}

if (REPEAT_POLLING) {}

}

if (pendingMO !

= null) {

 

droppedDuringPoll.add(pendingMO);

pendingMO = null;

hangupPendingMO = false;

}

if (newRinging !

= null) {

//表示是一个MT call,需要通知用户。

phone.notifyNewRingingConnection(newRinging);

}

// clear the "local hangup" and "missed/rejected call"

// cases from the "dropped during poll" list

// These cases need no "last call fail" reason

for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) {

GsmConnection conn = droppedDuringPoll.get(i);

if (conn.isIncoming() && conn.getConnectTime() == 0) {

// Missed or rejected call

Connection.DisconnectCause cause;

if (conn.cause == Connection.DisconnectCause.LOCAL) {

cause = Connection.DisconnectCause.INCOMING_REJECTED;

} else {

cause = Connection.DisconnectCause.INCOMING_MISSED;

}

droppedDuringPoll.remove(i);

conn.onDisconnect(cause);

} else if (conn.cause == Connection.DisconnectCause.LOCAL) {

// Local hangup

droppedDuringPoll.remove(i);

conn.onDisconnect(Connection.DisconnectCause.LOCAL);

} else if (conn.cause ==

Connection.DisconnectCause.INVALID_NUMBER) {

droppedDuringPoll.remove(i);

 

}

}

// Any non-local disconnects:

 determine cause

if (droppedDuringPoll.size() > 0) {

//本地挂断都是DisconnectCause.LOCAL,此处表明是对方或网络端的挂断,具

体//挂断原因需要从RIL处获得。

cm.getLastCallFailCause(

 

}

if (needsPollDelay) {

pollCallsAfterDelay();

}

// Cases when we can no longer keep disconnected Connection's

// with their previous calls

// 1) the phone has started to ring

// 2) A Call/Connection object has changed state...

//we may have switched or held or answered (but not hung up)

if (newRinging !

= null || hasNonHangupStateChanged) {

internalClearDisconnected();

}

更新Phone的状态。

updatePhoneState();

if (unknownConnectionAppeared) {

phone.notifyUnknownConnection();

}

if (hasNonHangupStateChanged || newRinging !

= null) {

//通知用户callstatechange。

phone.notifyPreciseCallStateChanged();

}

if(DBG_POLL) log("

//dumpState();

}

Call 处理中的内部接口就是 PhoneUtils,它提供的主要接口如下:

setAudioControlState(int)

answerCall(Phone)

hangup(Phone)

hangupRingingCall(Phone)

hangupActiveCall(Phone)

hangupHoldingCall(Phone)

hangupRingingAndActive(Phone)

hangupAllC

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 经济学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1