android 电话接听流程解析

Andriod通话处理流程


一、总览
1、从java端发送at命令的处理流程。
2、unsolicited 消息从modem上报到java的流程。
3、猫相关的各种状态的监听和通知机制。
4、通话相关的图标变换的工作原理。
5、gprs拨号上网的通路原理。
6、通话相关的语音通路切换原理、震动接口。
7、通话相关的notification服务。
8、通话相关的各种server。

第一部分:从java端发送at命令的处理流程。

拨出电话流程:

1、contacts的androidmanifest.xml android:process="android.process.acore"说明此应用程序运行在acore进程中。
DialtactsActivity的intent-filter的action属性设置为main,catelog属性设置为launcher,所以此activity能出现在主菜单中,并且是点击此应用程序的第一个界面。dialtactsactivity包含四个tab,分别由TwelveKeyDialer,RecentCallsListActivity,两个activity-alias DialtactsContactsEntryActivity和DialtactsFavoritesEntryActivity分别

表示联系人和收藏tab,但是正真的联系人列表和收藏是由ContactsListActivity负责。

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

java代码:

  1. placecall()
  2. Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
  3. Uri.fromParts("tel", number, null));
  4. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  5. 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);

java代码:
  1. Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
  2. if (number != null) broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
  3. broadcastIntent.putExtra(EXTRA_ALREADY_CALLED, callNow);
  4. broadcastIntent.putExtra(EXTRA_ORIGINAL_URI, intent.getData().toString());
  5. if (LOGV) Log.v(TAG, "Broadcasting intent " + broadcastIntent + ".");
  6. sendOrderedBroadcast(broadcastIntent, PERMISSION, null, null,
  7. 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()函数

java代码:
  1. Intent newIntent = new Intent(Intent.ACTION_CALL, uri);
  2. newIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
  3. newIntent.setClass(context, InCallScreen.class);
  4. newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

复制代码

5、请求拨号的java部分流程
onCreate(第一次)/onNewIntent(非第一次)

java代码:
  1. internalResolveIntent
  2. placeCall(intent);
  3. PhoneUtils.placeCall(mPhone, number, intent.getData());
  4. phone.dial(number);
  5. mCT.dial(newDialString);
  6. dial(dialString, CommandsInterface.CLIR_DEFAULT);
  7. cm.dial(pendingMO.address, clirMode, obtainCompleteMessage());//obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
  8. send(rr);
  9. msg = mSender.obtainMessage(EVENT_SEND, rr);
  10. acquireWakeLock();
  11. msg.sendToTarget();
  12. RILSender.handleMessage()
  13. case EVENT_SEND:
  14. ... s.getOutputStream().write(dataLength);
  15. s.getOutputStream().write(data);//从这里流程跑到下面ril.cpp中监听部份

复制代码

6、请求拨号的c/c++部分流程
6.1、初始化事件循环,启动串口监听,注册socket监听。
rild.c->main()
(1)、RIL_startEventLoop

java代码:
  1. //建立事件循环线程
  2. ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
  3. //注册进程唤醒事件回调
  4. ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
  5. processWakeupCallback, NULL);
  6. rilEventAddWakeup (&s_wakeupfd_event);
  7. //建立事件循环
  8. ril_event_loop
  9. for (;;) {
  10. ...
  11. n = select(nfds, &rfds, NULL, NULL, ptv);
  12. // Check for timeouts
  13. processTimeouts();
  14. // Check for read-ready
  15. processReadReadies(&rfds, n);
  16. // Fire away
  17. firePending();
  18. }
//

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

java代码:


  1. //单独启动一个线程读取串口数据
  2. ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
  3. fd = open (s_device_path, O_RDWR);
  4. ret = at_open(fd, onUnsolicited);
  5. ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
  6. RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);


  7. //在initializeCallback中执行的程序:
  8. setRadioState (RADIO_STATE_OFF);
  9. at_handshake();
  10. /* note: we don't check errors here. Everything important will
  11. be handled in onATTimeout and onATReaderClosed */
  12. /* atchannel is tolerant of echo but it must */
  13. /* have verbose result codes */
  14. at_send_command("ATE0Q0V1", NULL);
  15. /* No auto-answer */
  16. at_send_command("ATS0=0", NULL);
  17. ...
  18. //注册rild socket端口事件监听到事件循环中
复制代码

(3)、RIL_register(funcs);

java代码:
  1. s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);
  2. ret = listen(s_fdListen, 4);
  3. ril_event_set (&s_listen_event, s_fdListen, false,
  4. listenCallback, NULL);//将此端口加入事件select队列
  5. rilEventAddWakeup (&s_listen_event);
  6. //如果rild socket端口有数据来了将执行listencallback函数
  7. listencallback
  8. //为此客户端连接创建新的监听句柄,s_fdListen继续监听其他客户端的连接。
  9. s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);
  10. ril_event_set (&s_commands_event, s_fdCommand, 1,
  11. processCommandsCallback, p_rs);//将此端口加入事件select队列
  12. rilEventAddWakeup (&s_commands_event);

复制代码

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

java代码:
  1. processCommandsCallback
  2. //读数据到p_record中
  3. ret = record_stream_get_next(p_rs, &p_record, &recordlen);
  4. processCommandBuffer(p_record, recordlen);
  5. p.setData((uint8_t *) buffer, buflen);
  6. // status checked at end
  7. status = p.readInt32(&request);
  8. status = p.readInt32 (&token);//请求队列中的序号
  9. pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));
  10. pRI->token = token;
  11. /*
  12. 包含#include "ril_commands.h"语句,结构体如下:
  13. typedef struct {
  14. int requestNumber;
  15. void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI);
  16. int(*responseFunction) (Parcel &p, void *response, size_t responselen);
  17. } CommandInfo;
  18. */
  19. pRI->pCI = &(s_commands[request]);
  20. pRI->p_next = s_pendingRequests;
  21. s_pendingRequests = pRI;
  22. pRI->pCI->dispatchFunction(p, pRI);
  23. //假设是接收了dial指令,pRI->PCI->dispatchFunction(p,pRI),调用dispatchDial (p,pRI)
  24. dispatchDial (p,pRI)
  25. s_callbacks.onRequest(pRI->pCI->requestNumber, &dial, sizeof(dial), pRI);
  26. in reference-ril.c onRequest()
  27. ...
  28. switch (request) {
  29. case RIL_REQUEST_DIAL:
  30. requestDial(data, datalen, t);
  31. asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
  32. ret = at_send_command(cmd, NULL);
  33. err = at_send_command_full (command, NO_RESULT, NULL, NULL, 0, pp_outResponse);
  34. err = at_send_command_full_nolock(command, type, responsePrefix, smspdu,timeoutMsec, sponse);
  35. err = writeline (command);
  36. //此处等待,直到收到成功应答或失败的应答,如:ok,connect,error cme等
  37. err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
  38. waiting....
  39. waiting....
  40. /* success or failure is ignored by the upper layer here.it will call GET_CURRENT_CALLS and determine success that way */
  41. RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  42. p.writeInt32 (RESPONSE_SOLICITED);
  43. p.writeInt32 (pRI->token);
  44. errorOffset = p.dataPosition();
  45. p.writeInt32 (e);
  46. if (e == RIL_E_SUCCESS) {
  47. /* process response on success */
  48. ret = pRI->pCI->responseFunction(p, response, responselen);
  49. if (ret != 0) {
  50. p.setDataPosition(errorOffset);
  51. p.writeInt32 (ret);
  52. }
  53. }
  54. sendResponse(p);
  55. sendResponseRaw(p.data(), p.dataSize());
  56. blockingWrite(fd, (void *)&header, sizeof(header));
  57. blockingWrite(fd, data, dataSize);

复制代码

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

java代码:
  1. readerLoop()
  2. line = readline();
  3. processLine(line);
  4. handleFinalResponse(line);
  5. pthread_cond_signal(&s_commandcond);//至此,前面的等待结束,接着执行RIL_onRequestComplete函数

复制代码

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

java代码:
  1. ril.java->RILReceiver.run()
  2. for(;;)
  3. {
  4. ...
  5. length = readRilMessage(is, buffer);
  6. p = Parcel.obtain();
  7. p.unmarshall(buffer, 0, length);
  8. p.setDataPosition(0);
  9. processResponse(p);
  10. type = p.readInt();
  11. if (type == RESPONSE_SOLICITED) {
  12. processSolicited (p);
  13. serial = p.readInt();
  14. rr = findAndRemoveRequestFromList(serial);
  15. rr.mResult.sendToTarget();
  16. ......
  17. }
  18. CallTracker.java->handleMessage (Message msg)
  19. switch (msg.what) {
  20. case EVENT_OPERATION_COMPLETE:
  21. ar = (AsyncResult)msg.obj;
  22. operationComplete();
  23. cm.getCurrentCalls(lastRelevantPoll);
///

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

java代码:

  1. readerLoop()
  2. line = readline();
  3. processLine(line);
  4. handleUnsolicited(line);
  5. if (s_unsolHandler != NULL) {
  6. s_unsolHandler (line1, line2);//实际执行的是void onUnsolicited (const char *s, const char *sms_pdu)
  7. if (strStartsWith(s,"+CRING:")
  8. || strStartsWith(s,"RING")
  9. || strStartsWith(s,"NO CARRIER")
  10. || strStartsWith(s,"+CCWA")
  11. )
  12. RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
  13. p.writeInt32 (RESPONSE_UNSOLICITED);
  14. p.writeInt32 (unsolResponse);
  15. ret = s_unsolResponses[unsolResponseIndex].responseFunction(p, data, datalen);
  16. ret = sendResponse(p);
  17. sendResponseRaw(p.data(), p.dataSize());
  18. ret = blockingWrite(fd, (void *)&header, sizeof(header));
  19. blockingWrite(fd, data, dataSize);
复制代码

java部份

java代码:
  1. ril.java->RILReceiver.run()
  2. for(;;){

  3. length = readRilMessage(is, buffer);
  4. p = Parcel.obtain();
  5. p.unmarshall(buffer, 0, length);
  6. p.setDataPosition(0);
  7. processResponse(p);
  8. processUnsolicited (p);
  9. response = p.readInt();
  10. switch(response) {
  11. ...
  12. case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break;
  13. ...
  14. }
  15. switch(response) {
  16. case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
  17. if (RILJ_LOGD) unsljLog(response);
  18. mCallStateRegistrants
  19. .notifyRegistrants(new AsyncResult(null, null, null));
  20. ...
  21. }

复制代码

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

a、注册监听部分

java代码:
  1. ==>SystemServer.java
  2. init2()
  3. Thread thr = new ServerThread();
  4. thr.setName("android.server.ServerThread");
  5. thr.start();
  6. ServerThread.run() com.android.server.status.StatusBarPolicy.installIcons(context, statusBar);
  7. sInstance = new StatusBarPolicy(context, service);
  8. // phone_signal
  9. mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
  10. mPhoneData = IconData.makeIcon("phone_signal",
  11. null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
  12. mPhoneIcon = service.addIcon(mPhoneData, null);
  13. // register for phone state notifications.
  14. ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE)).listen(mPhoneStateListener,
  15. PhoneStateListener.LISTEN_SERVICE_STATE
  16. | PhoneStateListener.LISTEN_SIGNAL_STRENGTH
  17. | PhoneStateListener.LISTEN_CALL_STATE
  18. | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
  19. | PhoneStateListener.LISTEN_DATA_ACTIVITY);
  20. //实际是调用的是TelephonyRegistry.listen,此listen函数会将Iphonestatelistener添加到对应的的handler数组中,到时来了事件会轮询回调。
  21. // data_connection
  22. mDataData = IconData.makeIcon("data_connection", null, com.android.internal.R.drawable.stat_sys_data_connected_g, 0, 0);
  23. mDataIcon = service.addIcon(mDataData, null);
  24. service.setIconVisibility(mDataIcon, false);

  25. b、事件通知部分
  26. ==>PhoneFactory.java
  27. makeDefaultPhones()
  28. sPhoneNotifier = new DefaultPhoneNotifier();
  29. useNewRIL(context);
  30. phone = new GSMPhone(context, new RIL(context), sPhoneNotifier);
  31. for example
  32. ==>DataConnectionTracker.java
  33. notifyDefaultData(String reason)
  34. phone.notifyDataConnection(reason);
  35. mNotifier.notifyDataConnection(this, reason);
  36. ==>DefaultPhoneNotifier.java
  37. mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
  38. "telephony.registry"));
  39. mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),
  40. sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),
  41. sender.getInterfaceName(null));
///

第四部分:gprs拨号上网的通路原理。
上层java程序调用gprs流程:

java代码:

  1. =>PhoneApp.java
  2. onCreate()
  3. PhoneFactory.makeDefaultPhones(this);
  4. phone = new GSMPhone(context, new SimulatedCommands(), sPhoneNotifier);
  5. mDataConnection = new DataConnectionTracker (this);
  6. createAllPdpList();//建立缺省pdpconnection
  7. pdp = new PdpConnection(phone);
  8. dataLink = new PppLink(phone.mDataConnection);
  9. dataLink.setOnLinkChange(this, EVENT_LINK_STATE_CHANGED, null);
  10. //某个条件触发执行
  11. trySetupData(String reason)
  12. setupData(reason);
  13. pdp = findFreePdp();
  14. Message msg = obtainMessage();
  15. msg.what = EVENT_DATA_SETUP_COMPLETE;
  16. msg.obj = reason;
  17. pdp.connect(apn, msg);
  18. phone.mCM.setupDefaultPDP(apn.apn, apn.user, apn.password,
  19. obtainMessage(EVENT_SETUP_PDP_DONE));
  20. //收到EVENT_SETUP_PDP_DONE消息
  21. =>pdpconnection.java
  22. handleMessage()
  23. case EVENT_SETUP_PDP_DONE:
  24. dataLink.connect();//dataLink是pppLink.java
  25. SystemService.start(SERVICE_PPPD_GPRS);//启动pppd_grps服务
  26. poll.what = EVENT_POLL_DATA_CONNECTION;
  27. sendMessageDelayed(poll, POLL_SYSFS_MILLIS);//启动轮询,看是否成功连接gprscheckPPP()//每隔5秒轮询,看是否连接成功,或断开
  28. //如果已经连接
  29. mLinkChangeRegistrant.notifyResult(LinkState.LINK_UP);
  30. //执行到pdpconnection.handleMessage()
  31. case EVENT_LINK_STATE_CHANGED
  32. onLinkStateChanged(ls);
  33. case LINK_UP:
  34. notifySuccess(onConnectCompleted);
  35. onCompleted.sendToTarget();
  36. //执行dataConnectionTracker.java的handleMessage()
  37. case EVENT_DATA_SETUP_COMPLETE
  38. notifyDefaultData(reason);
  39. setupDnsProperties();
  40. setState(State.CONNECTED);
  41. phone.notifyDataConnection(reason);
  42. startNetStatPoll();
  43. 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++部分代码的角度分析

java代码:

  1. =>DataConnectionTracker.java
  2. trySetupData(String reason)
  3. setupData(reason);
  4. =>PdpConnection.java
  5. pdp.connect(apn, msg);
  6. =>RIL.JAVA
  7. phone.mCM.setupDefaultPDP(apn.apn, apn.user, apn.password,
  8. obtainMessage(EVENT_SETUP_PDP_DONE));
  9. send(rr);
  10. //send socket to RIL
  11. //enter c++ layer
  12. =>ril.cpp
  13. processCommandsCallback (int fd, short flags, void *param)
  14. processCommandBuffer(p_record, recordlen);
  15. status = p.readInt32(&request);
  16. pRI->pCI = &(s_commands[request]);
  17. pRI->pCI->dispatchFunction(p, pRI);
  18. dispatchStrings();
  19. s_callbacks.onRequest(pRI->pCI->requestNumber, pStrings, datalen, pRI);
  20. =>reference-ril.c
  21. onRequest();
  22. requestSetupDefaultPDP(data, datalen, t);
  23. err = write_at_to_data_channel("ATD*99***1#",1);
  24. //after a while.get "connect" from data channel,so need to send socket message to java layer.
  25. p.writeInt32 (RESPONSE_SOLICITED);
  26. p.writeInt32 (pRI->token);//the serial No in the request list.
  27. errorOffset = p.dataPosition();
  28. p.writeInt32 (e);
  29. if (e == RIL_E_SUCCESS) {
  30. /* process response on success */
  31. ret = pRI->pCI->responseFunction(p, response, responselen);
  32. /* if an error occurred, rewind and mark it */
  33. if (ret != 0) {
  34. p.setDataPosition(errorOffset);
  35. p.writeInt32 (ret);
  36. }
  37. }
  38. sendResponse(p);
  39. sendResponseRaw(p.data(), p.dataSize());
  40. ret = blockingWrite(fd, (void *)&header, sizeof(header));
  41. blockingWrite(fd, data, dataSize);
  42. =>RIL.JAVA
  43. RILReceiver.run();
  44. length = readRilMessage(is, buffer);
  45. p = Parcel.obtain();
  46. p.unmarshall(buffer, 0, length);
  47. p.setDataPosition(0);
  48. processResponse(p);
  49. processSolicited (p);
  50. serial = p.readInt();
  51. error = p.readInt();
  52. rr = findAndRemoveRequestFromList(serial);
  53. ret = responseStrings(p);
  54. if (rr.mResult != null) {
  55. AsyncResult.forMessage(rr.mResult, ret, null);
  56. rr.mResult.sendToTarget();
  57. }
  58. =>pdpConnection.java
  59. handleMessage()
  60. case EVENT_SETUP_PDP_DONE:
  61. ...
  62. dataLink.connect();
  63. =>pppLink.java
  64. SystemProperties.set(PROPERTY_PPPD_EXIT_CODE, "");
  65. SystemService.start(SERVICE_PPPD_GPRS);//启动pppd_grps服务
  66. poll.what = EVENT_POLL_DATA_CONNECTION;
  67. sendMessageDelayed(poll, POLL_SYSFS_MILLIS);
  68. dataConnection.state = State.CONNECTING;
  69. handleMessage()
  70. case EVENT_POLL_DATA_CONNECTION
  71. checkPPP();
  72. if (ArrayUtils.equals(mCheckPPPBuffer, UP_ASCII_STRING, UP_ASCII_STRING.length)
  73. || ArrayUtils.equals(mCheckPPPBuffer, UNKNOWN_ASCII_STRING,
  74. UNKNOWN_ASCII_STRING.length) && dataConnection.state == State.CONNECTING)
  75. if (mLinkChangeRegistrant != null) {
  76. mLinkChangeRegistrant.notifyResult(LinkState.LINK_UP);
  77. =>pdpConnection.java
  78. handleMessage()
  79. case EVENT_LINK_STATE_CHANGED:
  80. DataLink.LinkState ls = (DataLink.LinkState) ar.result;
  81. onLinkStateChanged(ls);
  82. case LINK_UP:
  83. notifySuccess(onConnectCompleted);
  84. AsyncResult.forMessage(onCompleted);
  85. onCompleted.sendToTarget();
  86. =>DataConnectionTracker.java
  87. handleMessage()
  88. case EVENT_DATA_SETUP_COMPLETE:
  89. ... SystemProperties.set("gsm.defaultpdpcontext.active", "true");
  90. notifyDefaultData(reason);
  91. setupDnsProperties();
  92. //设置dns,gw,我们的实现方式是在pppd中设置的,不用pppd拨号的适用。
  93. setState(State.CONNECTED);
  94. phone.notifyDataConnection(reason);
  95. mNotifier.notifyDataConnection(this, reason);
  96. =>DefaultPhoneNotifier.java
  97. //mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
  98. "telephony.registry"));构造函数中初始化了mRegistry mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()), sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),
  99. sender.getInterfaceName(null));
  100. startNetStatPoll();
  101. }
//

第五部分:通话相关的语音通路切换原理、震动接口
5、语音通路
5.1、设置语音通路的路由
目前我们有两处处理:

a、CallTracker.java中的handlePollCalls()检测到+clcc返回的电话列表中有状态为DriverCall.State.ALERTING(表示拨打电话后,对方已经振铃),此时需要设置语音通路为MODE_IN_CALL
b、PhoneUtils.java中setAudioMode()函数
c、调用通路分析

java代码:

  1. AudioManager audioManager = (AudioManager) context.getSystemService
  2. (Context.AUDIO_SERVICE);
  3. audioManager.setMode(mode);
  4. AudioManager.setMode(mode);
  5. AudioService.setMode(mode);
  6. AudioSystem.setMode(mode);(native function)
  7. android_media_AudioSystem.cpp==>android_media_AudioSystem_setMode()
  8. AudioSystem.cpp==>setMode()
  9. const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
  10. binder = sm->getService(String16("media.audio_flinger"));
  11. ...
  12. gAudioFlinger = interface_cast<IAudioFlinger>(binder);
  13. ...
  14. return gAudioFlinger;
复制代码

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

java代码:
  1. defaultServiceManager()->addService(String16("media.audio_flinger"), new AudioFlinger());
  2. mAudioHardware = AudioHardwareInterface::create();
  3. LOGV("Creating Vendor Specific AudioHardware");
  4. hw = createAudioHardware();
  5. return new AudioHardwareMarvell();
  6. return af->setMode(mode);
  7. AudioHardwareLittle.cpp==>setMode(mode)
  8. doRouting();
  9. enable_incall_headphone()//or others...
  10. system("alsactl -f /etc/alsactl/asound.state_none restore");
  11. system("alsactl -f /etc/alsactl/asound.state_headset_r_s restore");

复制代码

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

java代码:
  1. ==>Phone.app
  2. onCreate()
  3. ringer = new Ringer(phone);
  4. Vibrator mVibrator = new Vibrator();
  5. mService = IHardwareService.Stub.asInterface(ServiceManager.getService("hardware"));
  6. notifier = new CallNotifier(this, phone, ringer, mBtHandsfree);
  7. mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
  8. mPhone.registerForPhoneStateChanged(this, PHONE_STATE_CHANGED, null);
  9. mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);
  10. ...
  11. case PHONE_INCOMING_RING:
  12. mRinger.ring();
  13. mHardwareService.setAttentionLight(true);
  14. mVibratorThread.start();
  15. while (mContinueVibrating) {
  16. mVibrator.vibrate(VIBRATE_LENGTH);
  17. SystemClock.sleep(VIBRATE_LENGTH + PAUSE_LENGTH);
  18. }
  19. ...
  20. makeLooper();
  21. mRingHandler.sendEmptyMessage(PLAY_RING_ONCE);
  22. ...
  23. case PLAY_RING_ONCE:
  24. PhoneUtils.setAudioMode(mContext,AudioManager.MODE_RINGTONE);
  25. r.play();
  26. ...
  27. case PHONE_DISCONNECT:
  28. case PHONE_STATE_CHANGED:
  29. ...
  30. mRinger.stopRing();
  31. Message msg = mRingHandler.obtainMessage(STOP_RING);
  32. msg.obj = mRingtone;
  33. mRingHandler.sendMessage(msg);
  34. case STOP_RING:
  35. r.stop();
  36. getLooper().quit();
  37. ...mVibrator.cancel();

复制代码

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

java代码:
  1. sMe = new NotificationMgr(context);
  2. mNotificationMgr = (NotificationManager)
  3. context.getSystemService(Context.NOTIFICATION_SERVICE);
  4. mStatusBar = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE); //主要用于显示静音和
复制代码

speaker状态的图表(在状态条右边显示)
sMe.updateNotifications();//主要功能是:
1、查询是否有未读的未接听电话,并显示到状态栏图标,和通知列表
2、根据是否是电话状态,更新状态栏图表和通知列表(可能是激活,蓝牙,保持等)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值