Andriod 通话处理流程

来源:互联网 发布:akb48知乎 编辑:程序博客网 时间:2024/05/22 08:09
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,执行 
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);//启动轮询,看是否成功连接gprscheckPPP()//每隔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 
原创粉丝点击