您的位置:首页 > 移动开发 > Android开发

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

2011-10-17 19:06 459 查看
 

拨出电话流程:

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

contacts的androidmanifest.xmlandroid:process="android.process.acore"说明此应用程序运行在acore进程中。DialtactsActivity的intent-filter的action属性设置为main,catelog属性设置为launcher,所以此activity能出现, 首先启动的就是这个activity在主菜单中,并且是点击此应用程序的第一个界面。dialtactsactivity包含四个tab,分别由TwelveKeyDialer、RecentCallsListActivity,两个activity-aliasDialtactsContactsEntryActivity和DialtactsFavoritesEntryActivity分别表示联系人和收藏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.xml中PrivilegedOutgoingCallBroadcasteractivity-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++部分流程(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.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;

   

   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.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);//实际执行的是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();//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()

                  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();//设置dns,gw,我们的实现方式是在pppd中设置的,不用pppd拨号的适用。

                                  setState(State.CONNECTED);

                                  phone.notifyDataConnection(reason);

                                       mNotifier.notifyDataConnection(this,reason);

                                       =>DefaultPhoneNotifier.java

                                         //mRegistry =ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(

                   "telephony.registry"));构造函数中初始化了mRegistry

                                         mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),

                                             sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),

                                             sender.getInterfaceName(null));

                                  startNetStatPoll();   

                }

第六部分:通话相关的语音通路切换原理、震动接口

6、语音通路

6.1、设置语音通路的路由

目前我们有两处处理:

a、CallTracker.java中的

handlePollCalls()

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

b、PhoneUtils.java中setAudioMode()函数

c、调用通路分析

AudioManager audioManager = (AudioManager)context.getSystemService

  (Context.AUDIO_SERVICE);

audioManager.setMode(mode);

  AudioManager.setMode(mode);

    AudioService.setMode(mode);

      AudioSystem.setMode(mode);(native function)

        android_media_AudioSystem.cpp==>android_media_AudioSystem_setMode()

        AudioSystem.cpp==>setMode()

          const sp<IAudioFlinger>& af =AudioSystem::get_audio_flinger();

            binder =sm->getService(String16("media.audio_flinger"));

            ...

            gAudioFlinger = interface_cast<IAudioFlinger>(binder);

            ...

            return gAudioFlinger;

                          通过查找“media.audio_flinger”发现AudioFlinger.cpp==>instantiate()//Main_mediaserver.cpp中被实例化。

               defaultServiceManager()->addService(String16("media.audio_flinger"),new AudioFlinger());

                  mAudioHardware =AudioHardwareInterface::create();

                    LOGV("Creating 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.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得到的:

TelephonyManager

未完,待续。。

转自:
http://bbs.apkplace.com/thread-30-1-1.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息