Chinaunix首页 | 论坛 | 博客
  • 博客访问: 86184
  • 博文数量: 21
  • 博客积分: 766
  • 博客等级: 军士长
  • 技术积分: 185
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-29 10:27
文章分类

全部博文(21)

文章存档

2012年(5)

2010年(10)

2009年(6)

我的朋友

分类: LINUX

2010-05-18 15:29:37

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);//启动轮询,看是否成功连接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& af = AudioSystem::get_audio_flinger();
 
             binder = sm->getService(String16("media.audio_flinger"));
 
             ...
 
             gAudioFlinger = interface_cast(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
 
 
 
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Yangcg/archive/2009/10/28/4738848.aspx
阅读(1467) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~