android通话流程浅析RIL层

拨出电话流程:

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

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

进入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.xmlPrivilegedOutgoingCallBroadcaster activity-alias设置了intent-filter,所以需要找到其targetactivityOutgoingCallBroadcaster。所以进入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);

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

 

下面的androidmanifest.xmlOutgoingCallReceiver 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.2socket监听,收到dialsocket请求

 

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.5java层收到应答后的处理,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();//dataLinkpppLink.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.javahandleMessage()

                  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();//设置dnsgw,我们的实现方式是在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、设置语音通路的路由

 

目前我们有两处处理:

 

aCallTracker.java中的

 

handlePollCalls()

 

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

 

 

 

bPhoneUtils.javasetAudioMode()函数

 

 

 

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.1NotificationMgr

 

==>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.2CallNotifier

 

==>PhoneApp.java

 

  onCreate()

 

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

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

电话通信相关的服务:

(1)、从ServiceManager得到的:

awifiService

bPhoneInterfaceManager

cPhoneSubInfo

dSimPhoneBookInterfaceManager

eSimSmsInterfaceManager

fTelephonyRegistry

gNetStatService

hConnectivityService

(2)、从ApplicationContext得到的:

aTelephonyManager


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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值