`
zzbupt
  • 浏览: 84601 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android通信模块代码流程

阅读更多

        下面转载的这篇文章为开发android通信模块之必看,作者从代码的角度对Android的通信模块进行跟踪,可能有点长,但是对RIL初学者来说有很大的参考价值,所以自己收藏一下,以备以后查看。

 

一、总览

1、从java端发送at命令的处理流程。

2unsolicited 消息从modem上报到java的流程。

3、猫相关的各种状态的监听和通知机制。

4、通话相关的图标变换的工作原理。

5gprs拨号上网的通路原理。

6、通话相关的语音通路切换原理、震动接口。

7、通话相关的notification服务。

8、通话相关的各种server

 

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

拨出电话流程: 

 

1contactsandroidmanifest.xml android:process="android.process.acore"说明此应用程序运行在acore进程中。

DialtactsActivityintent-filteraction属性设置为maincatelog属性设置为launcher,所以此activity能出现

在主菜单中,并且是点击此应用程序的第一个界面。dialtactsactivity包含四个tab,分别由TwelveKeyDialer

RecentCallsListActivity,两个activity-alias DialtactsContactsEntryActivityDialtactsFavoritesEntryActivity分别

表示联系人和收藏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);

 

3intert.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();//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();//
设置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得到的:
a
wifiService
b
PhoneInterfaceManager
c
PhoneSubInfo
d
SimPhoneBookInterfaceManager
e
SimSmsInterfaceManager
f
TelephonyRegistry
g
NetStatService

原文地址 http://blog.csdn.net/Yangcg/archive/2009/10/28/4738848.aspxConnectivityService

(2)
、从ApplicationContext得到的:

a
TelephonyManager


h

分享到:
评论

相关推荐

    《Android系统源代码情景分析》

    《Android系统源代码情景分析》随书光盘内容(源代码) 目录如下: 第1篇 初识Android系统 第1章 准备知识 1.1 Linux内核参考书籍 1.2 Android应用程序参考书籍 1.3 下载、编译和运行Android源代码 ...

    Android系统源代码情景分析-罗升阳-源码

    《Android系统源代码情景分析》随书光盘内容(源代码) 目录如下: 第1篇 初识Android系统 第1章 准备知识 1.1 Linux内核参考书籍 1.2 Android应用程序参考书籍 1.3 下载、编译和运行Android源代码 1.3.1 下载...

    Android系统源代码情景分析光盘

    Android系统源代码情景分析光盘资料 目录 第1篇初识Android系统 第1章 准备知识................................................................ 2 1.1 Linux内核参考书籍......................................

    《Android应用开发揭秘》附带光盘代码.

    《Android应用开发揭秘》全部实例源代码,配合《Android应用开发揭秘》使用 前言  第一部分 准备篇  第1章 Android开发简介  1.1 Android基本概念  1.1.1 Android简介  1.1.2 Android的系统构架  1.1.3 ...

    Android代码-kotlin_tips

    Android模块化通信项目module-service-manager,支持模块间功能服务/View/Fragment的通信调用等,通过注解标示模块内需要暴露出来的服务和View,然后gradle插件会通过transform来hook编译过程,扫描出注解信息后再...

    Android驱动开发权威指南

    2.2 Android代码目录结构 2.3 Android开发环境搭建 第二篇 勿于浮砂筑高台——Linux驱动基础篇 第3章Linux内核综述 3.1 OS基本概念 3.1.1多用户系统 3.1.2用户和组 3.1.3进程 3.1.4 Linux单核架构 3.2 Linux内核综述...

    《Android Telephony原理解析与开发指南》_杨青平

    全书共10章,主要内容包括初识Android、搭建Android源代码编译调试环境、深入解析通话流程、详解Telecom、详解TeleService、Voice Call语音通话模型、ServiceState网络服务、Data Call移动数据业务、SMS & MMS业务...

    Android应用开发揭秘pdf高清版

    它还以迭代的方式重现了各种常用的Android应用和经典Android游戏的开发全过程,既可以以它们为范例进行实战演练,又可以将它们直接应用到实际开发中去。 目录 -------------------------------------------------...

    《Android嵌入式应用开发 (第2版)》

    《卓越工程师培养计划"十二五"规划教材:Android嵌入式应用开发》主要内容包括Android基础知识、Android应用程序开发的基本流程、Android应用程序开发的常用编程接口、常用控件及一些在应用程序中常用的模块和功能的...

    《Android应用开发揭秘》源码

     14.4.2 流程控制和线程  14.4.3 游戏对象与对象管理  14.4.4 图形引擎  14.4.5 物理引擎  14.4.6 事件模块  14.4.7 工具模块  14.4.8 脚本引擎、音效模块、网络模块  14.5 小结  第15章 优化技术  15.1 ...

    深入理解Android WiFi NFC和GPS卷(邓凡平).

    从通信专业知识和Android系统代码实现的角度,对Netd、Wi-Fi、NFC和GPS等模块的代码进行深入的剖析,旨在深刻揭示其实现原理和工作流程。其中涉及大量通信相关的专业知识,因此特意邀请全志和高通等著名芯片公司的...

    深入理解Android:卷I--详细书签版

    笔者根据研究Android代码的心得,在本书中尝试性地采用了精简流程、逐个击破的方法进 行讲解,希望这样做能帮助读者更快、更准确地把握各模块的工作流程及其本质。本书大部分章节中都专门撰写了“拓展思路”的内容...

    新版Android开发教程.rar

    将会支持 Google 可能发布的手机操作系统或者应用软件,共同开发名为 Android 的开放源代码的移动 系 统。 谷歌早在 2002 年就进入了移动领域,可是由于目前的手机操作系统企业和手机企业相对封闭,提高了 行业的...

    基于ARM Cortex-A8和Android 4.x的联动报警系统 (Android 、A8、Linux、驱动、NDK)

    掌握Android从应用开发,到系统移植,再到设备驱动开发的全套技术,无疑会极大的提升自己的职业竞争力和薪酬谢水平 ,本课程深入浅出,手敲全部实战项目代码,经历软硬件结合的嵌入式项目开发全部过程,而且课程中不...

    ARM Cortex-A8和Android 4.x联动报警系统

    掌握Android从应用开发,到系统移植,再到设备驱动开发的全套技术,无疑会极大的提升自己的职业竞争力和薪酬谢水平 ,本课程深入浅出,手敲全部实战项目代码,经历软硬件结合的嵌入式项目开发全部过程,而且课程中不...

    基于AndroidStudio实现的疾病预防疫苗接种预约app设计毕业源代码+文档说明+sql文件

    具体要求:对于预防接种app,主要有四个功能模块,登录注册,预约接种,在线咨询,我的信息,在能满足业务流程后,添加其他的功能模块,如侧滑栏显示更改密码,退出注销等。 系统要求: 1.登录注册:连接数据库,能...

    Android应用开发实战 (李宁) PDF扫描版

    实践部分以一个完整的大型案例(功能完善的微博客户端)贯穿始终,以迭代的方式详细演示和讲解了该案例的开发全过程,旨在帮助读者迅速理清android应用开发的完整流程和实现细节,同时,对开发过程中所涉及的理论...

    Android项目应用框架原理与程序设计.rar

    内容涵盖框架设计原则、架构模式、系统组件及通信机制等核心知识,结合实例引导读者逐步探索Android应用的构建过程。 资源特点: 1. 内容丰富:从基础概念到高级技术,全面覆盖Android应用框架的各个方面。 2. ...

Global site tag (gtag.js) - Google Analytics