拨出电话流程:

1 在系统源码这个路径下/packages/apps/Phone/src/com/android/phone/DialtactsActivity.java

contacts的androidmanifest.xml android:process="android.process.acore"说明此应用程序运行在acore进程中。DialtactsActivity的intent-filter的action属性设置为main,catelog属性设置为launcher,所以此activity能出现, 首先启动的就是这个activity在主菜单中,并且是点击此应用程序的第一个界面。dialtactsactivity包含四个tab,分别由TwelveKeyDialer、RecentCallsListActivity,两个activity-alias DialtactsContactsEntryActivity和DialtactsFavoritesEntryActivity分别表示联系人和收藏tab,但是正真的联系人列表和收藏是由ContactsListActivity负责。

2

进入TwelveKeyDialer OnClick方法,按住的按钮id为: R.id.digits,执行

placecall()

Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,

Uri.fromParts("tel", number, null));

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);

3、

intert.ACTION_CALL_PRIVILEGED实际字符串为android.intent.action.CALL_PRIVILEGED,通过查找知道了packegs/phone下面的androidmanifest.xml中PrivilegedOutgoingCallBroadcaster activity-alias设置了intent-filter,所以需要找到其targetactivity为OutgoingCallBroadcaster。所以进入OutgoingCallBroadcaster的

onCreate()

//如果为紧急号码马上启动intent.setClass(this, InCallScreen.class); startActivity(intent);

Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);

if (number != null) broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);

broadcastIntent.putExtra(EXTRA_ALREADY_CALLED, callNow);

broadcastIntent.putExtra(EXTRA_ORIGINAL_URI, intent.getData().toString());

if (LOGV) Log.v(TAG, "Broadcasting intent " + broadcastIntent + ".");

sendOrderedBroadcast(broadcastIntent, PERMISSION, null, null,

Activity.RESULT_OK, number, null);

4、Intent.ACTION_NEW_OUTGOING_CALL实际字符串为android.intent.action.NEW_OUTGOING_CALL,通过查找知道了packegs/phone

下面的androidmanifest.xml中OutgoingCallReceiver Receiver接收此intent消息。找到OutgoingCallReceiver,执行

onReceive()函数

Intent newIntent = new Intent(Intent.ACTION_CALL, uri);

newIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);

newIntent.setClass(context, InCallScreen.class);

newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

5、请求拨号的java部分流程

onCreate(第一次)/onNewIntent(非第一次)

internalResolveIntent

placeCall(intent);

PhoneUtils.placeCall(mPhone, number, intent.getData());

phone.dial(number);

mCT.dial(newDialString);

dial(dialString, CommandsInterface.CLIR_DEFAULT);

cm.dial(pendingMO.address, clirMode, obtainCompleteMessage());//obtainCompleteMessage(EVENT_OPERATION_COMPLETE);

send(rr);

msg = mSender.obtainMessage(EVENT_SEND, rr);

acquireWakeLock();

msg.sendToTarget();

RILSender.handleMessage()

case EVENT_SEND:

...

s.getOutputStream().write(dataLength);

s.getOutputStream().write(data);//从这里流程跑到下面ril.cpp中监听部份

6、请求拨号的c/c++部分流程

6.1、初始化事件循环,启动串口监听,注册socket监听。

rild.c->main()

(1)、RIL_startEventLoop

//建立事件循环线程

ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);

//注册进程唤醒事件回调

ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,

processWakeupCallback, NULL);

rilEventAddWakeup (&s_wakeupfd_event);

//建立事件循环

ril_event_loop

for (;;) {

...

n = select(nfds, &rfds, NULL, NULL, ptv);

// Check for timeouts

processTimeouts();

// Check for read-ready

processReadReadies(&rfds, n);

// Fire away

firePending();

}

(2)、funcs = rilInit(&s_rilEnv, argc, rilArgv);//实际是通过动态加载动态库的方式执行reference-ril.c中的RIL_Init

//单独启动一个线程读取串口数据

ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);

fd = open (s_device_path, O_RDWR);

ret = at_open(fd, onUnsolicited);

ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);

RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);

在initializeCallback中执行的程序:

setRadioState (RADIO_STATE_OFF);

at_handshake();

/* note: we don't check errors here. Everything important will

be handled in onATTimeout and onATReaderClosed */

/*  atchannel is tolerant of echo but it must */

/*  have verbose result codes */

at_send_command("ATE0Q0V1", NULL);

/*  No auto-answer */

at_send_command("ATS0=0", NULL);

...

//注册rild socket端口事件监听到事件循环中

(3)、RIL_register(funcs);

s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);

ret = listen(s_fdListen, 4);

ril_event_set (&s_listen_event, s_fdListen, false,

listenCallback, NULL);//将此端口加入事件select队列

rilEventAddWakeup (&s_listen_event);

如果rild socket端口有数据来了将执行listencallback函数

listencallback

//为此客户端连接创建新的监听句柄,s_fdListen继续监听其他客户端的连接。

s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);

ril_event_set (&s_commands_event, s_fdCommand, 1,

processCommandsCallback, p_rs);//将此端口加入事件select队列

rilEventAddWakeup (&s_commands_event);

6.2、socket监听,收到dial的socket请求

processCommandsCallback

//读数据到p_record中

ret = record_stream_get_next(p_rs, &p_record, &recordlen);

processCommandBuffer(p_record, recordlen);

p.setData((uint8_t *) buffer, buflen);

// status checked at end

status = p.readInt32(&request);

status = p.readInt32 (&token);//请求队列中的序号

pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));

pRI->token = token;

/*

包含#include "ril_commands.h"语句,结构体如下:

typedef struct {

int requestNumber;

void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI);

int(*responseFunction) (Parcel &p, void *response, size_t responselen);

} CommandInfo;

*/

pRI->pCI = &(s_commands[request]);

pRI->p_next = s_pendingRequests;

s_pendingRequests = pRI;

pRI->pCI->dispatchFunction(p, pRI);

//假设是接收了dial指令,pRI->PCI->dispatchFunction(p,pRI),调用dispatchDial (p,pRI)

dispatchDial (p,pRI)

s_callbacks.onRequest(pRI->pCI->requestNumber, &dial, sizeof(dial), pRI);

in reference-ril.c onRequest()

...

switch (request) {

case RIL_REQUEST_DIAL:

requestDial(data, datalen, t);

asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);

ret = at_send_command(cmd, NULL);

err = at_send_command_full (command, NO_RESULT, NULL, NULL, 0, pp_outResponse);

err = at_send_command_full_nolock(command, type, responsePrefix, smspdu,timeoutMsec, sponse);

err = writeline (command);

//此处等待,直到收到成功应答或失败的应答,如:ok,connect,error cme等

err = pthread_cond_wait(&s_commandcond, &s_commandmutex);

waiting....

waiting....

/* success or failure is ignored by the upper layer here.

it will call GET_CURRENT_CALLS and determine success that way */

RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);

p.writeInt32 (RESPONSE_SOLICITED);

p.writeInt32 (pRI->token);

errorOffset = p.dataPosition();

p.writeInt32 (e);

if (e == RIL_E_SUCCESS) {

/* process response on success */

ret = pRI->pCI->responseFunction(p, response, responselen);

if (ret != 0) {

p.setDataPosition(errorOffset);

p.writeInt32 (ret);

}

}

sendResponse(p);

sendResponseRaw(p.data(), p.dataSize());

blockingWrite(fd, (void *)&header, sizeof(header));

blockingWrite(fd, data, dataSize);

6.4、串口监听收到atd命令的应答"OK"或"no carrier"等

readerLoop()

line = readline();

processLine(line);

handleFinalResponse(line);

pthread_cond_signal(&s_commandcond);//至此,前面的等待结束,接着执行RIL_onRequestComplete函数

6.5、java层收到应答后的处理,以dial为例子.

ril.java->RILReceiver.run()

for(;;)

{

...

length = readRilMessage(is, buffer);

p = Parcel.obtain();

p.unmarshall(buffer, 0, length);

p.setDataPosition(0);

processResponse(p);

type = p.readInt();

if (type == RESPONSE_SOLICITED) {

processSolicited (p);

serial = p.readInt();

rr = findAndRemoveRequestFromList(serial);

rr.mResult.sendToTarget();

......

}

CallTracker.java->handleMessage (Message msg)

switch (msg.what) {

case EVENT_OPERATION_COMPLETE:

ar = (AsyncResult)msg.obj;

operationComplete();

cm.getCurrentCalls(lastRelevantPoll);

第二部分:unsolicited 消息从modem上报到java的流程。

c++部份

readerLoop()

line = readline();

processLine(line);

handleUnsolicited(line);

if (s_unsolHandler != NULL) {

s_unsolHandler (line1, line2);//实际执行的是void onUnsolicited (const char *s, const char *sms_pdu)

if (strStartsWith(s,"+CRING:")

|| strStartsWith(s,"RING")

|| strStartsWith(s,"NO CARRIER")

|| strStartsWith(s,"+CCWA")

)

RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);

p.writeInt32 (RESPONSE_UNSOLICITED);

p.writeInt32 (unsolResponse);

ret = s_unsolResponses[unsolResponseIndex].responseFunction(p, data, datalen);

ret = sendResponse(p);

sendResponseRaw(p.data(), p.dataSize());

ret = blockingWrite(fd, (void *)&header, sizeof(header));

blockingWrite(fd, data, dataSize);

java部份

ril.java->RILReceiver.run()

for(;;)

{

...

length = readRilMessage(is, buffer);

p = Parcel.obtain();

p.unmarshall(buffer, 0, length);

p.setDataPosition(0);

processResponse(p);

processUnsolicited (p);

response = p.readInt();

switch(response) {

...

case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret =  responseVoid(p); break;

...

}

switch(response) {

case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:

if (RILJ_LOGD) unsljLog(response);

mCallStateRegistrants

.notifyRegistrants(new AsyncResult(null, null, null));

...

}

第三部分、第四部分:猫相关的各种状态的监听和通知机制/通话相关的图标变换的工作原理。

网络状态,edge,gprs图标的处理

a、注册监听部分

==>SystemServer.java

init2()

Thread thr = new ServerThread();

thr.setName("android.server.ServerThread");

thr.start();

ServerThread.run()

com.android.server.status.StatusBarPolicy.installIcons(context, statusBar);

sInstance = new StatusBarPolicy(context, service);

// phone_signal

mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

mPhoneData = IconData.makeIcon("phone_signal",

null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);

mPhoneIcon = service.addIcon(mPhoneData, null);

// register for phone state notifications.

((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))

.listen(mPhoneStateListener,

PhoneStateListener.LISTEN_SERVICE_STATE

| PhoneStateListener.LISTEN_SIGNAL_STRENGTH

| PhoneStateListener.LISTEN_CALL_STATE

| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE

| PhoneStateListener.LISTEN_DATA_ACTIVITY);

//实际是调用的是TelephonyRegistry.listen,此listen函数会将Iphonestatelistener添加到对应的的handler数组中,到时来了事件会轮询回调。

// data_connection

mDataData = IconData.makeIcon("data_connection",

null, com.android.internal.R.drawable.stat_sys_data_connected_g, 0, 0);

mDataIcon = service.addIcon(mDataData, null);

service.setIconVisibility(mDataIcon, false);

b、事件通知部分

==>PhoneFactory.java

makeDefaultPhones()

sPhoneNotifier = new DefaultPhoneNotifier();

useNewRIL(context);

phone = new GSMPhone(context, new RIL(context), sPhoneNotifier);

for example

==>DataConnectionTracker.java

notifyDefaultData(String reason)

phone.notifyDataConnection(reason);

mNotifier.notifyDataConnection(this, reason);

==>DefaultPhoneNotifier.java

mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(

"telephony.registry"));

mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),

sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),

sender.getInterfaceName(null));

第五部分:gprs拨号上网的通路原理。

上层java程序调用gprs流程:

=>PhoneApp.java

onCreate()

PhoneFactory.makeDefaultPhones(this);

phone = new GSMPhone(context, new SimulatedCommands(), sPhoneNotifier);

mDataConnection = new DataConnectionTracker (this);

createAllPdpList();//建立缺省pdpconnection

pdp = new PdpConnection(phone);

dataLink = new PppLink(phone.mDataConnection);

dataLink.setOnLinkChange(this, EVENT_LINK_STATE_CHANGED, null);

//某个条件触发执行

trySetupData(String reason)

setupData(reason);

pdp = findFreePdp();

Message msg = obtainMessage();

msg.what = EVENT_DATA_SETUP_COMPLETE;

msg.obj = reason;

pdp.connect(apn, msg);

phone.mCM.setupDefaultPDP(apn.apn, apn.user, apn.password,

obtainMessage(EVENT_SETUP_PDP_DONE));

//收到EVENT_SETUP_PDP_DONE消息

=>pdpconnection.java

handleMessage()

case EVENT_SETUP_PDP_DONE:

dataLink.connect();//dataLink是pppLink.java

SystemService.start(SERVICE_PPPD_GPRS);//启动pppd_grps服务

poll.what = EVENT_POLL_DATA_CONNECTION;

sendMessageDelayed(poll, POLL_SYSFS_MILLIS);//启动轮询,看是否成功连接gprs

checkPPP()//每隔5秒轮询,看是否连接成功,或断开

//如果已经连接

mLinkChangeRegistrant.notifyResult(LinkState.LINK_UP);

//执行到pdpconnection.handleMessage()

case EVENT_LINK_STATE_CHANGED

onLinkStateChanged(ls);

case LINK_UP:

notifySuccess(onConnectCompleted);

onCompleted.sendToTarget();

//执行dataConnectionTracker.java的handleMessage()

case EVENT_DATA_SETUP_COMPLETE

notifyDefaultData(reason);

setupDnsProperties();

setState(State.CONNECTED);

phone.notifyDataConnection(reason);

startNetStatPoll();

resetPollStats();

1、读取发送出去的包数和接受到的包数

2、如果发送的数据包且没有收到应答包数n大于等于看门狗追踪的限定包数。

2.1、开始轮询pdp context list,尝试恢复网络连接

2.2、如果轮询24次后还没有联通网络则停止网络状态轮询,进行一次ping实验。

2.2.1、如果ping成功则,重新进行网络状态轮询,否则发送EVENT_START_RECOVERY事件。

// reset reconnect timer

nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;

着重c++部分代码的角度分析

=>DataConnectionTracker.java

trySetupData(String reason)

setupData(reason);

=>PdpConnection.java

pdp.connect(apn, msg);

=>RIL.JAVA

phone.mCM.setupDefaultPDP(apn.apn, apn.user, apn.password,

obtainMessage(EVENT_SETUP_PDP_DONE));

send(rr);

//send socket to RIL

//enter c++ layer

=>ril.cpp

processCommandsCallback (int fd, short flags, void *param)

processCommandBuffer(p_record, recordlen);

status = p.readInt32(&request);

pRI->pCI = &(s_commands[request]);

pRI->pCI->dispatchFunction(p, pRI);

dispatchStrings();

s_callbacks.onRequest(pRI->pCI->requestNumber, pStrings, datalen, pRI);

=>reference-ril.c

onRequest();

requestSetupDefaultPDP(data, datalen, t);

err = write_at_to_data_channel("ATD*99***1#",1);

//after a while.get "connect" from data channel,so need to send socket message to java layer.

p.writeInt32 (RESPONSE_SOLICITED);

p.writeInt32 (pRI->token);//the serial No  in the request list.

errorOffset = p.dataPosition();

p.writeInt32 (e);

if (e == RIL_E_SUCCESS) {

/* process response on success */

ret = pRI->pCI->responseFunction(p, response, responselen);

/* if an error occurred, rewind and mark it */

if (ret != 0) {

p.setDataPosition(errorOffset);

p.writeInt32 (ret);

}

}

sendResponse(p);

sendResponseRaw(p.data(), p.dataSize());

ret = blockingWrite(fd, (void *)&header, sizeof(header));

blockingWrite(fd, data, dataSize);

=>RIL.JAVA

RILReceiver.run();

length = readRilMessage(is, buffer);

p = Parcel.obtain();

p.unmarshall(buffer, 0, length);

p.setDataPosition(0);

processResponse(p);

processSolicited (p);

serial = p.readInt();

error = p.readInt();

rr = findAndRemoveRequestFromList(serial);

ret =  responseStrings(p);

if (rr.mResult != null) {

AsyncResult.forMessage(rr.mResult, ret, null);

rr.mResult.sendToTarget();

}

=>pdpConnection.java

handleMessage()

case EVENT_SETUP_PDP_DONE:

...

dataLink.connect();

=>pppLink.java

SystemProperties.set(PROPERTY_PPPD_EXIT_CODE, "");

SystemService.start(SERVICE_PPPD_GPRS);//启动pppd_grps服务

poll.what = EVENT_POLL_DATA_CONNECTION;

sendMessageDelayed(poll, POLL_SYSFS_MILLIS);

dataConnection.state = State.CONNECTING;

handleMessage()

case EVENT_POLL_DATA_CONNECTION

checkPPP();

if (ArrayUtils.equals(mCheckPPPBuffer, UP_ASCII_STRING, UP_ASCII_STRING.length)

|| ArrayUtils.equals(mCheckPPPBuffer, UNKNOWN_ASCII_STRING,

UNKNOWN_ASCII_STRING.length)

&& dataConnection.state == State.CONNECTING)

if (mLinkChangeRegistrant != null) {

mLinkChangeRegistrant.notifyResult(LinkState.LINK_UP);

=>pdpConnection.java

handleMessage()

case EVENT_LINK_STATE_CHANGED:

DataLink.LinkState ls  = (DataLink.LinkState) ar.result;

onLinkStateChanged(ls);

case LINK_UP:

notifySuccess(onConnectCompleted);

AsyncResult.forMessage(onCompleted);

onCompleted.sendToTarget();

=>DataConnectionTracker.java

handleMessage()

case EVENT_DATA_SETUP_COMPLETE:

...

SystemProperties.set("gsm.defaultpdpcontext.active", "true");

notifyDefaultData(reason);

setupDnsProperties();//设置dns,gw,我们的实现方式是在pppd中设置的,不用pppd拨号的适用。

setState(State.CONNECTED);

phone.notifyDataConnection(reason);

mNotifier.notifyDataConnection(this, reason);

=>DefaultPhoneNotifier.java

//mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(

"telephony.registry"));构造函数中初始化了mRegistry

mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),

sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),

sender.getInterfaceName(null));

startNetStatPoll();

}

第六部分:通话相关的语音通路切换原理、震动接口

6、语音通路

6.1、设置语音通路的路由

目前我们有两处处理:

a、CallTracker.java中的

handlePollCalls()

检测到+clcc返回的电话列表中有状态为DriverCall.State.ALERTING(表示拨打电话后,对方已经振铃),此时需要设置语音通路为MODE_IN_CALL

b、PhoneUtils.java中setAudioMode()函数

c、调用通路分析

AudioManager audioManager = (AudioManager) context.getSystemService

(Context.AUDIO_SERVICE);

audioManager.setMode(mode);

AudioManager.setMode(mode);

AudioService.setMode(mode);

AudioSystem.setMode(mode);(native function)

android_media_AudioSystem.cpp==>android_media_AudioSystem_setMode()

AudioSystem.cpp==>setMode()

const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();

binder = sm->getService(String16("media.audio_flinger"));

...

gAudioFlinger = interface_cast<IAudioFlinger>(binder);

...

return gAudioFlinger;

通过查找“media.audio_flinger”发现AudioFlinger.cpp==>instantiate()//Main_mediaserver.cpp中被实例化。

defaultServiceManager()->addService(String16("media.audio_flinger"), new AudioFlinger());

mAudioHardware = AudioHardwareInterface::create();

LOGV("Creating Vendor Specific AudioHardware");

hw = createAudioHardware();

return new AudioHardwareMarvell();

return af->setMode(mode);

AudioHardwareLittle.cpp==>setMode(mode)

doRouting();

enable_incall_headphone()//or others...

system("alsactl -f /etc/alsactl/asound.state_none restore");

system("alsactl -f /etc/alsactl/asound.state_headset_r_s restore");

6.2、来电播放振铃,挂断或接听停止振铃。

==>Phone.app

onCreate()

ringer = new Ringer(phone);

Vibrator mVibrator = new Vibrator();

mService = IHardwareService.Stub.asInterface(ServiceManager.getService("hardware"));

notifier = new CallNotifier(this, phone, ringer, mBtHandsfree);

mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);

mPhone.registerForPhoneStateChanged(this, PHONE_STATE_CHANGED, null);

mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);

...

case PHONE_INCOMING_RING:

mRinger.ring();

mHardwareService.setAttentionLight(true);

mVibratorThread.start();

while (mContinueVibrating) {

mVibrator.vibrate(VIBRATE_LENGTH);

SystemClock.sleep(VIBRATE_LENGTH + PAUSE_LENGTH);

}

...

makeLooper();

mRingHandler.sendEmptyMessage(PLAY_RING_ONCE);

...

case PLAY_RING_ONCE:

PhoneUtils.setAudioMode(mContext, AudioManager.MODE_RINGTONE);

r.play();

...

case PHONE_DISCONNECT:

case PHONE_STATE_CHANGED:

...

mRinger.stopRing();

Message msg = mRingHandler.obtainMessage(STOP_RING);

msg.obj = mRingtone;

mRingHandler.sendMessage(msg);

case STOP_RING:

r.stop();

getLooper().quit();

...

mVibrator.cancel();

第七部分:通话相关的notification服务

7、通话相关的notification服务。

7.1、NotificationMgr

==>PhoneApp.java

onCreate()

NotificationMgr.init(this)//NotificationMgr.java//此类主要负责电话通知的具体表现(通知和取消通知),未接图标、通话中、蓝牙激活中、保持中,静音、免提等。封装了简单的瞬间显示文本消息的功能。提供漫游数据连接禁止的通知封装和漫游数据连接允许时取消通知

sMe = new NotificationMgr(context);

mNotificationMgr = (NotificationManager)

context.getSystemService(Context.NOTIFICATION_SERVICE);

mStatusBar = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE); //主要用于显示静音和speaker状态的图表(在状态条右边显示)

sMe.updateNotifications();//主要功能是:

1、查询是否有未读的未接听电话,并显示到状态栏图标,和通知列表

2、根据是否是电话状态,更新状态栏图表和通知列表(可能是激活,蓝牙,保持等)

7.2、CallNotifier

==>PhoneApp.java

onCreate()

notifier = new CallNotifier(this, phone, ringer, mBtHandsfree);//此类主要是监听通话相关的事件,然后进行例如来电播放铃声,震动。挂断、接听停止振铃等(调用Ringer类实现此功能),根据不同的状态调用调用NotificationMgr进行具体的通知和取消通知。

第八部分: 通话相关的各种server

电话通信相关的服务:

(1)、从ServiceManager得到的:

a、wifiService

b、PhoneInterfaceManager

c、PhoneSubInfo

d、SimPhoneBookInterfaceManager

e、SimSmsInterfaceManager

f、TelephonyRegistry

g、NetStatService

h、ConnectivityService

(2)、从ApplicationContext得到的:

a、TelephonyManager

转载于:https://www.cnblogs.com/yuzaipiaofei/archive/2011/07/14/4124613.html

android通话流程浅析RIL层相关推荐

  1. Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析

    本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处 本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. ...

  2. android 电话 流程,android电话系统和ril分析(1)————概述和电话系统流程

    前段时间接触GSM模块,基于android源码实现打电话.这里把我自己的从最初的无知整体读懂实现过程,mark下来,其中引用很多网上各位达人的帖子,中间会附上链接,非常感谢他们的share自己的开发经 ...

  3. Android 6.0 Phone 多方通话流程

    写在前面的话 本文主要分析Voice Call多方通话的流程,分析GSM和CDMA在多方通话不同的地方,研究的代码是Android 6.0的,目前只关注framework层. 1. 多方通话的概念 下 ...

  4. 智能电话会议系统(11)---Android 6.0 Phone 多方通话流程

    Android 6.0 Phone 多方通话流程 写在前面的话 本文主要分析Voice Call多方通话的流程,分析GSM和CDMA在多方通话不同的地方,研究的代码是Android 6.0的,目前只关 ...

  5. android 短信ril移植,将Android平台的RIL层移植到基于LINUX的通用平台的研究与实现...

    摘要:本文通过对Android RIL层代码分析,将android RIL层功能在纯LINUX平台上实现,完全脱离了Android系统.为基于LINUX的通用平台实现一套成熟的RIL层代码,并开发出相 ...

  6. Android 5.1 Lollipop Phone工作流程浅析(十三)__InCallActivity启动Performance浅析

    前置文章: < Android 4.4 Kitkat Phone工作流程浅析(一)__概要和学习计划> <Android 4.4 Kitkat Phone工作流程浅析(二)__UI结 ...

  7. RIL层代码分析--拨号整个流程

    拨出电话流程: 1 在系统源码这个路径下/packages/apps/Phone/src/com/android/phone/DialtactsActivity.java contacts的andro ...

  8. Android R WiFi热点流程浅析

    Android R WiFi热点流程浅析 Android上的WiFi SoftAp功能是用户常用的功能之一,它能让我们分享手机的网络给其他设备使用. 那Android系统是如何实现SoftAp的呢,这 ...

  9. Android存储设备(U盘,SD卡)状态监测(《Android 2.3 SD卡挂载流程浅析1234567)

    我们是以DV6300-T的平台来做测试的,发现有2种方式来检测android中external media(包括SD卡,USB)的状态. 一种是使用StorageListener监听,还有一种是使用广 ...

最新文章

  1. Java 锁粗化与循环
  2. 使用 bcp 指定数据文件中的前缀长度
  3. linux tee 命令 输出的同时写入文件
  4. boost::math模块使用拉普拉斯(与正态比较)分布的示例的测试程序
  5. android 标准字体,文字规范标准(IOS/Android)
  6. python中str是什么函数_python str函数怎么用
  7. C++实现线段树(lazy-tag方法)-区间修改,区间查询
  8. 【Lucy-Richardson去卷积】迭代加速算法
  9. Cause: java.sql.SQLException: Could not retrieve transation read-only status server
  10. 结束下面sql块_oracle: PL/SQL基本结构,语法,变量
  11. 设计模式_07_单例模式
  12. Dubbo服务治理(一):限流策略
  13. 社区口碑营销案例分析
  14. Linux进程管理(redhat 8.0)
  15. OpenWRT/Linux多WAN带宽叠加使用iptables标记策略路由负载均衡
  16. 上门洗车APP --- Android客户端开发 前言及业务简介
  17. 双重差分模型能做固定效应吗_双重差分法的平行趋势假定
  18. qgc地面站飞行模式
  19. MYSQL UNION 同列类型不同时的处理方法
  20. 2021年西式面点师(初级)考试题库及西式面点师(初级)考试试卷

热门文章

  1. IPMP 认证考试知识点
  2. 自己动手写Docker系列 -- 5.4实现进入容器的namespace,exec命令
  3. 大工20春计算机文化基础在线测试2,大工20春《计算机文化基础》在线测试2
  4. Is It A Tree?(hdu1325)
  5. MATLAB信号处理之连续时间系统的时域分析
  6. Spring Boot 分页插件PageHelper
  7. html js轮播图无白链接,JavaScript:100%原生js实现左右切换的轮播图(无延迟加载)...
  8. python弱类型好处_JavaScript弱类型语言的优缺点有哪些
  9. linux日志报multipath,linux device mapper multipath 驱动的路径聚合
  10. 三十二楼层选几层最好_买房子选几层最好?网友:我是按这个公式来计算黄金楼层,你咋看?...