android通话过程RIL层详细分析(代码)

来源:互联网 发布:闪电网络货币代码 编辑:程序博客网 时间:2024/04/17 00:54

拨出电话流程:

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

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

2

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

placecall()

Intent intent = newIntent(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.xmlPrivilegedOutgoingCallBroadcasteractivity-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++部分流程(APPA层RIL_java进入RIL 层)


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();


    


    


    


    at_send_command("ATE0Q0V1", NULL);


    


    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;




  


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




        


        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) {


          


          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""nocarrier"


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);//实际执行的是voidonUnsolicited (const char *s, const char *sms_pdu)


      if (strStartsWith(s,"+CRING:")


          ||strStartsWith(s,"RING")


          || strStartsWith(s,"NOCARRIER")


          ||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) {


          caseRIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:


          if (RILJ_LOGD)unsljLog(response);




          mCallStateRegistrants


              .notifyRegistrants(newAsyncResult(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 = newPppLink(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()

            caseEVENT_DATA_SETUP_COMPLETE

              notifyDefaultData(reason);

              setupDnsProperties();

              setState(State.CONNECTED);

              phone.notifyDataConnection(reason);

              startNetStatPoll();

                resetPollStats();

                1、读取发送出去的包数和接受到的包数

                2、如果发送的数据包且没有收到应答包数n大于等于看门狗追踪的限定包数。

                2.1、开始轮询pdpcontext 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 javalayer.

              p.writeInt32(RESPONSE_SOLICITED);

              p.writeInt32 (pRI->token);//theserial No  in the request list.

              errorOffset =p.dataPosition();

              p.writeInt32 (e);

              if (e == RIL_E_SUCCESS) {

                

                ret =pRI->pCI->responseFunction(p, response, responselen);


                

                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()

              caseEVENT_LINK_STATE_CHANGED:

              DataLink.LinkStatels  = (DataLink.LinkState) ar.result;

              onLinkStateChanged(ls);

                case LINK_UP:

                  notifySuccess(onConnectCompleted);

                  AsyncResult.forMessage(onCompleted);

                  onCompleted.sendToTarget();


                  =>DataConnectionTracker.java

                    handleMessage()

                    caseEVENT_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 VendorSpecific AudioHardware");


              hw = createAudioHardware();


              return newAudioHardwareMarvell();






      return af->setMode(mode);


        AudioHardwareLittle.cpp==>setMode(mode)


          doRouting();


            enable_incall_headphone()//orothers...


            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得到的:

TelephonyManager


未完,待续。。

原创粉丝点击