在android 2.2 上开发GC双模手机的考虑---RIL电话管理的设计

在android 智能OS上做双模产品,在目前市场情况看还是有一定市场份额,以下从技术分析设计角度,对双模的android 手机的设计做一个阐述;

目前android 的操作系统对GSM的支持比较好,对于CDMA EVDO的支持还是有不少需要修改和调整的地方,下面先给出几个大的方向,然后再按专题方式展开讨论;

                                        总体

(1)电话管理部分需要修改,考虑如何兼容CDMA EVDO的content,call,call long,应用层的phone 部分代码需要修改,ril层需要修改,modem的AT命令需要事项;

 

(2)手机上网部分需要修改;主要是在RIL层以及AT命令层;PPP以及应用层可以借用android 原生态;但是APN部分需要修改;

 

(3)MMS彩信部分需要修改,AT命令,PPP,以及APN修改情况和手机上网相同,MMS的报文格式需要按照CDMA MMS协议进行解析处理,一般放在RIL 层进行GSM和CDMA EVDO之间的转换;

 

(4)UTK部分需要修改;

 

(5)lancher 需要修改,涵盖PIN PUK 待机等处理

 

(6)CC/CB/手机设置CDMA部分需要考虑支持CDMA EVDO部分;

 

                                      下面按照电话管理处理

 

                                     电话管理部分---打电话

第一部分:从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);

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值