基于Android6.0的RIL框架层模块分析

本文与另外一篇分析RIL底层模块的文章是姐妹篇:基于Android6.0的RIL底层模块分析

根据手机网络制式的不同,通常系统中会扩展Phone.java这个类,扩展成GSMPhone和CDMAPhone。这个类主要是抽象整个手机来处理通信过程中与其他模块的交互。我们以GSMPhone为例,分析来电流程如何从底层传递到上层。该分析主要基于代码,所以会比较啰嗦。

以GSMPhone为例,在PhoneFactory类中有实例化该类的方法:


public static Phone getGsmPhone(int phoneId) {
     Phone phone = TelephonyPluginDelegate.getInstance().makeGSMPhone(sContext,sCommandsInterfaces[phoneId], sPhoneNotifier, phoneId);
     return phone;

}

这个phone的mCi其实使用sCommandInterfaces第phoneId个元素进行初始化。这个数组是为了支持多卡而设置。

sCommandInterfaces的初始化是:

sCommandsInterfaces = new RIL[numPhones];

所以可以知道其实mCi的真实类型就是RIL类。

GSMPhone会构造一个GsmCallTracker,而在GsmCallTracker中就会在构造函数中调用:


mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);

其实就是用GsmCallTracker来监听mCi上的电话状态改变EVENT_CALL_STATE_CHANGE啊。注意这个mCi是CommandInterfaces类型(当然实际是RIL类型,这样大家知道在哪里去找实现函数了)。我们理解模块流程,最好从更高层的抽象角度去考虑,深入到细节是你了解运行机制之后才进行的,否则容易迷失在细节中。通过查找RIL相关联的类(比如它继承的类和实现的接口),在BaseCommands里面找到实现函数:


public void registerForCallStateChanged(Handler h, int what, Object obj) {
        Registrant r = new Registrant (h, what, obj);
        mCallStateRegistrants.add(r);
}

看看它搞啥了。将传入的GsmCallTracker实例,响应的事件EVENT_CALL_STATE_CHANGE,以及传入的obj(null)包装成了一个Registrant,并且加入列表mCallStateRegistrants中了。注意传入的参数:


handler:实际传入的是GsmCallTracker类型,这个类也是handler的子类

what:EVENT_CALL_STATE_CHANGE,需要监听的事件类型

在稍微看看Registrant代码,发现就是包装了一下三个传入参数,并且在需要的时候触发事件的发送。mCallStateRegistrants是protected类型,所以可以在其子类RIL里面访问。在processUnsolicited&RIL.java里面确实针对这个做了处理:


//RIL.java
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
          mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
           break;
//RegistrantList.java
private synchronized void internalNotifyRegistrants (Object result, Throwable exception)
    {
       for (int i = 0, s = registrants.size(); i < s ; i++) {
            Registrant  r = (Registrant) registrants.get(i);
            r.internalNotifyRegistrant(result, exception);
       }
    }

是监听到了“RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED”事件,才进行了处理。至于这个事件的发出,涉及到了native层的rild,所以暂不在此提及。

其实就是把这个new AsyncResult(null, null, null)发送到mCallStateRegistrants中每个Registrant中去,并且用实例化Registrant时的handler来处理该AsyncResult。也就是返回到了GsmCallTracker中,注意返回信息的msg.what就是实例化该Registrant时候的what参数,针对来电就是EVENT_CALL_STATE_CHANGE。这个会触发:


//handleMessage&GsmCallTracker.java
case EVENT_CALL_STATE_CHANGE:
           pollCallsWhenSafe();
            break;
//CallTracker.java
protected void pollCallsWhenSafe() {
        if (checkNoOperationsPending()) {
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
            mCi.getCurrentCalls(mLastRelevantPoll);
        }
    }

也就是将一个mLastRelevantPoll.what = EVENT_POLL_CALL_RESULT的message传入getCurrentCalls函数。


//RIL.java
public void getCurrentCalls (Message result) {
        RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
        send(rr);
    }

下面来看看RILRequest这个类,非常有意思,它是一个链表实现,应该是作为一个pool的作用。也就是所有的request是放在一个池子里面进行管理(也就是链表,池子比较形象)。需要的时候就obtain一个。


static RILRequest obtain(int request, Message result) {
        RILRequest rr = null;
        synchronized(sPoolSync) {
            if (sPool != null) {
                rr = sPool;
                sPool = rr.mNext;
                rr.mNext = null;
                sPoolSize--;
            }
        }
        if (rr == null) {
            rr = new RILRequest();
        }
        rr.mSerial = sNextSerial.getAndIncrement();//依次递增,request的id。类似数据库里面的默认第一个键值_id
        rr.mRequest = request;//请求内容,就是RIL_REQUEST_GET_CURRENT_CALLS
        rr.mResult = result;
        rr.mParcel = Parcel.obtain();//一个序列化的数据,如下所见,保存request内容和request在池中的id
        if (result != null && result.getTarget() == null) {
            throw new NullPointerException("Message target must not be null");
        }
        // first elements in any RIL Parcel
        rr.mParcel.writeInt(request);
        rr.mParcel.writeInt(rr.mSerial);
        return rr;
    }

所以通过注释,看起来RILRequest就是容纳用户请求的一个池子。有些朋友可能要问了上面的getCurrentCalls函数直接用send(rr)把整个RILRequest全部发送出去了这是什么情况。记得rr里面还带有mSerial这个值的,这个值就可以定位到是哪个RILRequest被发送了。

send(rr)函数将RILRequest发送到RILSender的处理逻辑里面,由handleMessage进行处理。


case EVENT_SEND:
    try {
        LocalSocket s;
        s = mSocket;
        synchronized (mRequestList) {
            mRequestList.append(rr.mSerial, rr);//将request添加到一个列表中
        }
        byte[] data;
        data = rr.mParcel.marshall();//序列化mParcel里面的内容,注意里面包含request类型和request在池中的id
        rr.mParcel.recycle();
        rr.mParcel = null;//release resource
        // parcel length in big endian
        dataLength[0] = dataLength[1] = 0;
        dataLength[2] = (byte)((data.length >> 8) & 0xff);
        dataLength[3] = (byte)((data.length) & 0xff);
        s.getOutputStream().write(dataLength);//将数据长度和数据内容发送到mSocket里面,其实就是rild这个socket
        s.getOutputStream().write(data);

    }

还记得我们分析rild的native层的时候,提到的rild的main函数吗?最后会调用RIL_register函数,在这个函数最后会调用:


memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));
    /* Initialize socket1 parameters */
    s_ril_param_socket = {
                        RIL_SOCKET_1,             /* socket_id */
                        -1,                       /* fdListen */
                        -1,                       /* fdCommand */

                        PHONE_PROCESS,            /* processName */
                        &s_commands_event,        /* commands_event */
                        &s_listen_event,          /* listen_event */
                        processCommandsCallback,  /* processCommandsCallback */
                        NULL                      /* p_rs */

                        };
startListen(RIL_SOCKET_1, &s_ril_param_socket);

这个callbacks会用来初始化s_callbacks,而这个RIL_RadioFunctions类型的callbacks是调用rilInit之后返回的值。也既是调用三方的ril库文件,通过初始化返回的callbacks参数作为值来初始化rild层的s_callbacks参数(记住在reference-ril.c里面也有一个s_callbacks变量,但是为static类型,仅在该文件里面才有效)。

所以这个startlisten函数是在指定socket(RIL_SOCKET_1)上进行监听。看看该函数内部实现:


//Ril.cpp

static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_listen_p) {
    fdListen = android_get_control_socket(socket_name);//在init.rc里面找同名的socket
    ret = listen(fdListen, 4);
    socket_listen_p->fdListen = fdListen;
    /* note: non-persistent so we can accept only one connection at a time */
    ril_event_set (socket_listen_p->listen_event, fdListen, false,listenCallback, socket_listen_p);
    rilEventAddWakeup (socket_listen_p->listen_event);
}

可以看到针对这个fdListen(其实就是rild这个socket的文件描述符,也就是监听rild这个socket)被放到socket_listen-p(其实就是s_ril_param_socket)里面的listen_event这个ril_event中了。

注意,之前我们就在初始化native层的rild的时候就启动了一个ril_event_loop为函数主体的线程。它会监听rild这个套接字,当监听到数据的时候就会在ril_event_loop这个函数里面触发select这个函数,因为rild这个套接字已经放入了readFds这个FD_SET集合了。检测到之后就会触发

// Check for timeouts
        processTimeouts();
        // Check for read-ready
        processReadReadies(&rfds, n);
        // Fire away
        firePending();

所以最后调用的firePending,会直接遍历pending_list列表的每个event,并且调用ev->func(ev->fd, 0, ev->param)直接处理自己。ev->param这个参数实际上是在调用ril_event_set (socket_listen_p->listen_event, fdListen, false, listenCallback, socket_listen_p);时最后一个参数。也就是socket_listen_p,也即是s_ril_param_socket.

在这里监听到这个socket上的变化之后会调用listenCallback来处理。

static void listenCallback (int fd, short flags, void *param) {
    SocketListenParam *p_info = (SocketListenParam *)param;
    fdCommand = accept(fd, (sockaddr *) &peeraddr, &socklen);//注意这里的accept函数,接收了套接字rild上面的事件
    if(NULL == sapSocket) {
        p_info->fdCommand = fdCommand;
        p_rs = record_stream_new(p_info->fdCommand, MAX_COMMAND_BYTES);
        p_info->p_rs = p_rs;
        ril_event_set (p_info->commands_event, p_info->fdCommand, 1, p_info->processCommandsCallback, p_info);
        rilEventAddWakeup (p_info->commands_event);
        onNewCommandConnect(p_info->socket_id);
    }

}

接收到之后,又将这个fdCommand放入到了readFds里面,进行监听。且触发的是p_info(也即是s_ril_param_socket)的响应函数,就是processCommandsCallback函数。


static void processCommandsCallback(int fd, short flags, void *param) {
    for (;;) {
        /* loop until EAGAIN/EINTR, end of stream, or other error */
        ret = record_stream_get_next(p_rs, &p_record, &recordlen);
        processCommandBuffer(p_record, recordlen, p_info->socket_id);
    }
    if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
        rilEventAddWakeup(&s_listen_event);
        onCommandsSocketClosed(p_info->socket_id);
    }
}

注意,for循环里面会循环读取p_rs里面的数据,并且将读取出来的p_record传递到processCommandBuffer函数进行处理。


static int processCommandBuffer(void *buffer, size_t buflen, RIL_SOCKET_ID socket_id) {
    RequestInfo *pRI;
    /* pendingRequestsHook refer to &s_pendingRequests */
    RequestInfo**    pendingRequestsHook = &s_pendingRequests;
    p.setData((uint8_t *) buffer, buflen);
    // status checked at end
//注意这个序列化参数的读取顺序跟下面的写入顺序是对应的,所以这个token也就是mSerial了

    status = p.readInt32(&request);
    status = p.readInt32 (&token);
    pRI->token = token;
    pRI->pCI = &(s_commands[request]);
    pRI->socket_id = socket_id;
    pRI->p_next = *pendingRequestsHook;
    *pendingRequestsHook = pRI;
/*    sLastDispatchedToken = token; */
    pRI->pCI->dispatchFunction(p, pRI);
    return 0;
}

//ril.java--RILRequest--obtain
static RILRequest obtain(int request, Message result) {
        // first elements in any RIL Parcel
        rr.mParcel.writeInt(request);
        rr.mParcel.writeInt(rr.mSerial);
    }

对于当前的RIL_REQUEST_GET_CURRENT_CALLS来说,这个常量值在下面定义:

RILConstants.java:211: int RIL_REQUEST_GET_CURRENT_CALLS = 9;

所以pRI->pCI = &(s_commands[9]);,找到Ril_commands.h中对应id的值为:

{RIL_REQUEST_GET_CURRENT_CALLS, dispatchVoid, responseCallList},

所以我们知道后面调用的pRI->pCI->dispatchFunction(p, pRI);是调用哪个函数了。

static void dispatchVoid (Parcel& p, RequestInfo *pRI) {
    CALL_ONREQUEST(pRI->pCI->requestNumber, NULL, 0, pRI, pRI->socket_id);
}
等价于:
s_callbacks.onRequest(pRI->pCI->requestNumber, NULL, 0, pRI, pRI->socket_id)

所以跳转到reference-ril.c里面去了,会执行onRequest方法里面的如下分支:


case RIL_REQUEST_GET_CURRENT_CALLS:
            requestGetCurrentCalls(data, datalen, t);
            break;
//Reference-ril.c
static void requestGetCurrentCalls(void *data __unused, size_t datalen __unused, RIL_Token t)
{
    ATResponse *p_response;
    ATLine *p_cur;
    RIL_Call *p_calls;
    err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
    for (countValidCalls = 0, p_cur = p_response->p_intermediates
            ; p_cur != NULL
            ; p_cur = p_cur->p_next
    ) {
        err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
        countValidCalls++;
    }
    RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls, countValidCalls * sizeof (RIL_Call *));
    at_response_free(p_response);
    RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
}

其实就是通过at_send_command_multiline向modem发送AT命令,并且将结果存储在p_response中。后续会对将其中的内容解析出来,放入pp_calls里面。最后会调用RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls, countValidCalls * sizeof (RIL_Call *))。所以,发送RIL_REQUEST_GET_CURRENT_CALLS命令之后,从modem用AT命令查询到的结果pp_calls就被RIL_onRequestComplete函数返回了。


extern "C" void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) {
    pRI = (RequestInfo *)t;
    int fd = s_ril_param_socket.fdCommand;
    socket_id = pRI->socket_id;
    if (pRI->cancelled == 0) {
        Parcel p;
//注意这里写入的类型是RESPONSE_SOLICITED,该值在上层的RIL.java的解析函数processResponse里面会读取出来并进行处理的。
        p.writeInt32 (RESPONSE_SOLICITED);
        p.writeInt32 (pRI->token);
        p.writeInt32 (e);
        if (response != NULL) {
            // there is a response payload, no matter success or not.
            ret = pRI->pCI->responseFunction(p, response, responselen);
        }
        sendResponse(p, socket_id);
    }
}

还记得Ril_commands.h里面的数组吗?


{RIL_REQUEST_GET_CURRENT_CALLS, dispatchVoid, responseCallList},

pRI->pCI->responseFunction(p, response, responselen);这个函数对应的就是最后的responseCallList函数。该函数在Ril.cpp里面定义。

主要作用就是将response里面所有的电话信息都保存到序列化参数p里面,而这个参数最终会被sendResponse函数发送出去。


//ril.cpp
static int sendResponse (Parcel &p, RIL_SOCKET_ID socket_id) {
    return sendResponseRaw(p.data(), p.dataSize(), socket_id);
}

static int sendResponseRaw (const void *data, size_t dataSize, RIL_SOCKET_ID socket_id) {
    int fd = s_ril_param_socket.fdCommand;
    uint32_t header;
    header = htonl(dataSize);//主机数转换成无符号长整型的网络字节顺序,因为马上就要通过Socket传播了
    ret = blockingWrite(fd, (void *)&header, sizeof(header));
    ret = blockingWrite(fd, data, dataSize);
}

下面的blockingWrite就是将数据往fd句柄里面写入,代码如下:


static int blockingWrite(int fd, const void *buffer, size_t len) {
            written = write (fd, toWrite + writeOffset, len - writeOffset);
}

那这个地方的fd是哪里冒出来的呢?是否已经被绕晕了,不要怕,我也晕。但是凡事都有蛛丝马迹,需要的是耐心。我们追根溯源看看这个变量。最近的赋值,是在上一级的sendResponseRaw里面fd = s_ril_param_socket.fdCommand。而s_ril_param_socket是在RIL_register(这个函数大家应该很熟悉了吧,在ril.cpp里面,在rild.c的main函数里面被调用)里面,以引用传递的方式被传递给startListen函数了。而后,在startListen里面该变量被重命名为socket_listen_p,并被二人组加入到多路IO复用机制里面了。


//RIL_register
startListen(RIL_SOCKET_1, &s_ril_param_socket);
//startListen函数
ril_event_set (socket_listen_p->listen_event, fdListen, false, listenCallback, socket_listen_p);

所以当触发的时候,该参数作为param被传到响应函数listenCallback中了。

static void listenCallback (int fd, short flags, void *param) {
    SocketListenParam *p_info = (SocketListenParam *)param;
    fdCommand = accept(fd, (sockaddr *) &peeraddr, &socklen);
    if(NULL == sapSocket) {
        p_info->fdCommand = fdCommand;//注意这里的fdCommand是接受上层数据的socket
        p_info->p_rs = p_rs;
        ril_event_set (p_info->commands_event, p_info->fdCommand, 1, p_info->processCommandsCallback, p_info);
        rilEventAddWakeup (p_info->commands_event);
        onNewCommandConnect(p_info->socket_id);
    }
}

所以看到这里,大家就知道这个fd其实就是调用accept,响应上层传入的数据之后的socket。所以这blockwriting其实就是将从modem获取的数据写回到上层去。

我们再次回到上层。接受该消息的就是RIL.java里面的内部类RILReceiver,它是一个Runnable类。这个类在RIL的构造函数里面被初始化,并且被另起了一个线程来运行。


//RIL.java--RILReceiver--run
public void run() {
    String rilSocket = "rild";
    for (;;) {
        try {
            s = new LocalSocket();
            l = new LocalSocketAddress(rilSocket, LocalSocketAddress.Namespace.RESERVED);
            s.connect(l);
        }
        mSocket = s;
        try {
            InputStream is = mSocket.getInputStream();
            for (;;) {
                length = readRilMessage(is, buffer);
                p = Parcel.obtain();
                p.unmarshall(buffer, 0, length);
                p.setDataPosition(0);
                processResponse(p);
            } } }}

所以很明显可以看到,这个线程就是不停的从rild这个socket里面读取值,并且将读取出来的值序列化成parcel类型,最后用processResponse函数处理该值。


private void processResponse (Parcel p) {
    type = p.readInt();
    if (type == RESPONSE_UNSOLICITED) {
        processUnsolicited (p);
    } else if (type == RESPONSE_SOLICITED) {
        RILRequest rr = processSolicited (p);
    }
}

在RIL_onRequestComplete函数里面,type类型被定义为RESPONSE_SOLICITED。所以会触发下面一个分支。


private RILRequest processSolicited (Parcel p) {
    serial = p.readInt();
    error = p.readInt();
    RILRequest rr;
    rr = findAndRemoveRequestFromList(serial);
    Object ret = null;
    if (error == 0 || p.dataAvail() > 0) {
        // either command succeeds or command fails but with data payload
        try {switch (rr.mRequest) {
        case RIL_REQUEST_GET_CURRENT_CALLS: ret = responseCallList(p); break;
        }}
    }
    if (error == 0) {
        if (rr.mResult != null) {
            AsyncResult.forMessage(rr.mResult, ret, null);
            rr.mResult.sendToTarget();
        }
    }
}

我们来分析一下responseCallList函数:

private Object responseCallList(Parcel p) {
    ArrayList<DriverCall> response;
    DriverCall dc;
    num = p.readInt();
    response = new ArrayList<DriverCall>(num);
    for (int i = 0 ; i < num ; i++) {
        dc = new DriverCall();
        dc.state = DriverCall.stateFromCLCC(p.readInt());
        dc.index = p.readInt();
        response.add(dc);
    }
    Collections.sort(response);
    return response;
}

其实就是读取序列化参数p里面的数据,并且实例化为DriverCall对象,并放入response这个列表,且返回该列表。

下面分析如何处理response的代码:

 if (error == 0) {
        if (rr.mResult != null) {
            AsyncResult.forMessage(rr.mResult, ret, null);
            rr.mResult.sendToTarget();
        }
    }

是将一个消息发送给它的target进行处理。注意在函数调用中,rr.mResult.obj被赋值为了这个AsyncResult了。一个消息必包含一个message.what和messag.target(也就是handle)。那我们看看这个消息是怎么来的,其实这个rr是通过serial这个rr的id号在列表中找到的,上面我们也提到过这个id号,它是用来标识唯一的RilRequest的。至于这个rr怎么来的,大家看看下面的代码就知道了。


//CallTracker.java
protected void pollCallsWhenSafe() {
        if (checkNoOperationsPending()) {
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
            mCi.getCurrentCalls(mLastRelevantPoll);
        }
    }

//RIL.java

public void getCurrentCalls (Message result) {
        RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
//将这个rr放入列表中了,这个列表用mSerial唯一标识了它的id,这个mSerial也会被传入底层一直到从底层返回,同样也包含了这个mSerial。所以这个是伴随这个RILRequest的整个声明周期的。
        send(rr);
    }

所以我们知道,这个message的target是CallTracker类或子类,而what参数为EVENT_POLL_CALLS_RESULT。

在实际代码中,以GsmPhone为例,target就换成了GsmCallTracker了。

//GsmCallTracker--handleMessage
case EVENT_POLL_CALLS_RESULT:
                ar = (AsyncResult)msg.obj;
                if (msg == mLastRelevantPoll) {
                    handlePollCalls((AsyncResult)msg.obj);
                }

注意这个msg.obj实际上在AsyncResult.forMessage(rr.mResult, ret, null)中被赋值为了一个AsyncResult了。


rr.mResult.obj = new AsyncResult(rr.mResult.obj/*userObj*/, ret/*result*/, null/*exception*/);

这个ret就是通过rild这个套接字从native层接收到的结果解析成数据,并且放入ArrayList response。所以这个ret就是很多DriverCall组成的列表啊。

我们下面看看handlePollCalls函数,看他是如何处理返回结果的。


//GsmCallTracker
protected synchronized void handlePollCalls(AsyncResult ar) {
    if (ar.exception == null) {
        polledCalls = (List)ar.result;//注意这里的赋值
    }
    Connection newRinging = null; //or waiting
    for (int i = 0, curDC = 0, dcSize = polledCalls.size(); i < mConnections.length; i++) {
        GsmConnection conn = mConnections[i];
        // polledCall list is sparse

        if (curDC < dcSize) {
            dc = (DriverCall) polledCalls.get(curDC);
        }
        if (conn == null && dc != null) {
            // Connection appeared in CLCC response that we don‘t know about
// 注意这里是判断是否是MO,也就是拨出电话
            if (mPendingMO != null && mPendingMO.compareTo(dc)) {
                // It‘s our pending mobile originating call
            } else {//这就是拨入电话的响应逻辑了。
                mConnections[i] = new GsmConnection(mPhone, dc, this, i);//注意这里初始化的GsmConnection
                Connection hoConnection = getHoConnection(dc);
        if (hoConnection != null) {//这个是针对SRVCC这种类型的电话,所以也不是
// Single Radio Voice Call Continuity (SRVCC) completed                    mConnections[i].migrateFrom(hoConnection);
// Updating connect time for silent redial cases (ex: Calls are transferred
// from DIALING/ALERTING/INCOMING/WAITING to ACTIVE)
                } else if ( mConnections[i].getCall() == mRingingCall ) { // it‘s a ringing call,就是这里了
                    newRinging = mConnections[i];
                } }
            hasNonHangupStateChanged = true; } }
    if (newRinging != null) {
        mPhone.notifyNewRingingConnection(newRinging);
    }
    updatePhoneState();
    if (hasNonHangupStateChanged || newRinging != null || hasAnyCallDisconnected) {
        mPhone.notifyPreciseCallStateChanged();
    }
}

看看mPhone.notifyNewRingConnection(newRinging)函数,就是在这里通知的。这个mPhone其实就是在GsmPhone的构造函数里面实例化GsmCallTracker的时候传入的。最后辗转调用的是GsmPhone的父类里面的函数。这个有点类似模板方法了哈,把部分逻辑过程放在父类里面实现,它所有的子类都公用这段逻辑。


//PhoneBase.java
public void notifyNewRingingConnectionP(Connection cn) {
        if (!mIsVoiceCapable)
            return;
        AsyncResult ar = new AsyncResult(null/*userObj*/, cn/*result,其实就是mConnections[i] = new GsmConnection(mPhone, dc, this, i)*/, null/*exception*/);        mNewRingingConnectionRegistrants.notifyRegistrants(ar);
    }

//AsyncResult.java
public /*synchronized*/ void notifyRegistrants(AsyncResult ar)
    {        internalNotifyRegistrants(ar.result, ar.exception);    }
private synchronized void internalNotifyRegistrants (Object result, Throwable exception)
    {
       for (int i = 0, s = registrants.size(); i < s ; i++) {
            Registrant  r = (Registrant) registrants.get(i);
            r.internalNotifyRegistrant(result, exception);
       }}

等价为:
r.internalNotifyRegistrant(mConnections[i] = new GsmConnection(mPhone, dc, this, i),  null);

其实就是调用在列表中的每个Registrant来处理从底层传回来的结果。这个很像观察者模式吧,哈哈,把所有的观察者放在一个列表,等事件来的时候,一一通知。

所以这样来看看这些Registrant是在哪里放入PhoneBase里面这个mNewRingingConnectionRegistrants列表的。经过查找,找到下面的地方。


//CallManager.java-->registerForPhoneStates
//这个handler为CallManagerHandler类型。说明从modem返回的值会被该类处理。类型以及在这里指定了

phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION,mRegistrantidentifier);

//CallManager.java-->CallManagerHandler
case EVENT_NEW_RINGING_CONNECTION:
    Connection c = (Connection) ((AsyncResult) msg.obj).result;
    int subId = c.getCall().getPhone().getSubId();
    if (getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall(subId)) {
//当前是否有正在拨打的电话,或者是否有另外一个正在呼入的电话

    } else {        mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
    }

看起来并不像是这个地方处理,所以扩大到全项目搜索代码,最后在packages目录下的PstnIncomingCallNotifier.java中找到。(这个名字签名的Pstn不知道到底啥意思)


//从类开头的注释也可以看出来,该类确实用来负责处理拨入的电话PstnIncomingCallNotifier.java

/**
 * Listens to incoming-call events from the associated phone object and notifies Telecom upon each
 * occurence. One instance of these exists for each of the telephony-based call services.
 */
final class PstnIncomingCallNotifier {
private void registerForNotifications() {
        Phone newPhone = mPhoneProxy.getActivePhone();

            if (newPhone != null) {
                mPhoneBase = newPhone;             mPhoneBase.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null);            } } }

而这个mHandler对EVENT_NEW_RINGING_CONNECTION的处理为:
case EVENT_NEW_RINGING_CONNECTION:
    handleNewRingingConnection((AsyncResult) msg.obj);
    break;
//handleNewRingingConnection
private void handleNewRingingConnection(AsyncResult asyncResult) {
    Log.d(this, "handleNewRingingConnection");
    Connection connection = (Connection) asyncResult.result;
    if (connection != null) {
        Call call = connection.getCall();
        // Final verification of the ringing state before sending the intent to Telecom.
        if (call != null && call.getState().isRinging()) {
            sendIncomingCallIntent(connection);
        }
    }
}

/**
 * Sends the incoming call intent to telecom.
 */
private void sendIncomingCallIntent(Connection connection) {
    Bundle extras = null;
    if (connection.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED && !TextUtils.isEmpty(connection.getAddress())) {
        extras = new Bundle();
        Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);        extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri);
    }    //将通话connection的地址打包进extras。注意这个ID,EXTRA_INCOMING_CALL_ADDRESS

TelecomManager.from(mPhoneProxy.getContext()).addNewIncomingCall(PhoneUtils.makePstnPhoneAccountHandle(mPhoneProxy), extras);

//PhoneUtils.makePstnPhoneAccountHandle的返回值类似等价于下面代码

PhoneUtils.makePstnPhoneAccoutnHandle(mPhoneProxy) = new PhoneAccountHandle(TelephonyConnectionService, mPhoneProxy.getSubId())

}

所以该结果被传到TelecomManager里面去了。


((TelecomManager) mPhoneProxy.getContext().getSystemService(Context.TELECOM_SERVICE)).addNewIncomingCall( PhoneAccountHandle, extras);
//TelecomManager.java
public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
    try {        if (isServiceConnected()) {            getTelecomService().addNewIncomingCall(phoneAccount, extras == null ? new Bundle() : extras);

        }}}

这个addNewIncomingCall函数最终调用的是TelecomServiceImpl.java类里面的。其实这些方法是在该类的变量:private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub()下面实现的。

//TelecomServiceImpl.java
@Override
public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
    synchronized (mLock) {
        Log.i(this, "Adding new incoming call with phoneAccountHandle %s", phoneAccountHandle);
        if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
            try {
                Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);

                intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,phoneAccountHandle);                intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
                if (extras != null) {                    intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);}
                CallIntentProcessor.processIncomingCallIntent(mCallsManager, intent);}}}}

其实就是将传进来的参数打包成Intent,然后通过CallIntentProcessor.processIncomingCallIntent处理掉。


//CallIntentProcessor.java
static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
    PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
    Bundle clientExtras = null;
    if (intent.hasExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS)) {
        clientExtras = intent.getBundleExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS);
    }    callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);

}

上文的callsManager是在TelecomServiceImpl的构造函数里面赋值的。而该变量实际是在TelecomSystem.java的构造函数里面赋值的:


//TelecomSystem.java
public TelecomSystem(
            Context context,MissedCallNotifier missedCallNotifier,CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory, HeadsetMediaButtonFactory headsetMediaButtonFactory,ProximitySensorManagerFactory proximitySensorManagerFactory,InCallWakeLockControllerFactory inCallWakeLockControllerFactory,
            ViceNotifier vicenotifier) {
                mCallsManager = new CallsManager(mContext,mLock,mContactsAsyncHelper,callerInfoAsyncQueryFactory,mMissedCallNotifier,mPhoneAccountRegistrar,headsetMediaButtonFactory,proximitySensorManagerFactory,inCallWakeLockControllerFactory,mViceNotifier);
}

注意,CallsManager里面有好多参数都是TelecomSystem实例化的实例化的时候传进来的值。这个TelecomSystem是在TelcomService里面进行实例化的,你看到这个实例化的时候一定会大吃一惊!


//TelecomService.java
new TelecomSystem(context,
    new MissedCallNotifierImpl(context.getApplicationContext()),
    new CallerInfoAsyncQueryFactory() {//注意这个数据库查询类,UI上显示的来电人都是通过这个在数据库中匹配的
        @Override
        public CallerInfoAsyncQuery startQuery(int token, Context context, String number,                CallerInfoAsyncQuery.OnQueryCompleteListener listener, Object cookie) {
            Log.i(TelecomSystem.getInstance(), "CallerInfoAsyncQuery.startQuery number=%s cookie=%s",
                    Log.pii(number), cookie);
            return CallerInfoAsyncQuery.startQuery(token, context, number, listener, cookie);
        }
    },

    new HeadsetMediaButtonFactory() {
        @Override
        public HeadsetMediaButton create(Context context, CallsManager callsManager, TelecomSystem.SyncRoot lock) {
            return new HeadsetMediaButton(context, callsManager, lock);
        }
    },
    new ProximitySensorManagerFactory() {
        @Override
        public ProximitySensorManager create(Context context, CallsManager callsManager) {
            return new ProximitySensorManager(context, callsManager);
        }
    },
    new InCallWakeLockControllerFactory() {
        @Override
        public InCallWakeLockController create(Context context, CallsManager callsManager) {
            return new InCallWakeLockController(context, callsManager);
        }
    },
    new ViceNotifier() {
        @Override
        public ViceNotificationImpl create(Context context, CallsManager callsManager) {
            return new ViceNotificationImpl(context.getApplicationContext(), callsManager);

        }

    })

这里面定义了一堆匿名内部类,部分内容被传至CallsManager类(注意这里是CallsManager而不是CallManager)。至此,我们总算知道了实例化这个CallsManager实例时,里面存放的到底是些什么内容了。所以我们再回到上面的:


//CallIntentProcessor.java
callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
//CallsManager.java
void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
    Uri handle = extras.getParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS);
    Call call = new Call(mContext,this,mLock,mConnectionServiceRepository,
            mContactsAsyncHelper,mCallerInfoAsyncQueryFactory,
            handle,//其实这个就是地址或者来电号码。从Connection里面获取的,见之前的代码
            null /* gatewayInfo */,null /* connectionManagerPhoneAccount */,
            phoneAccountHandle,true /* isIncoming */,false /* isConference */);
    call.setIntentExtras(extras);
    call.addListener(this);
    call.startCreateConnection(mPhoneAccountRegistrar);
}

//packages\services\telecomm\src\com\android\server\telecom\Call.java
void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
        mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,  phoneAccountRegistrar, mContext);/*mRepository-- CallsManager.java
mConnectionServiceRepository =new ConnectionServiceRepository(mPhoneAccountRegistrar, mContext, mLock, this);*/
        mCreateConnectionProcessor.process();

    }

//CreateConnectionProcessor.java
void process() {
    mAttemptRecords = new ArrayList<>();
    if (mCall.getTargetPhoneAccount() != null) {
        mAttemptRecords.add(new CallAttemptRecord(mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
    }
    adjustAttemptsForConnectionManager();
    adjustAttemptsForEmergency();
    mAttemptRecordIterator = mAttemptRecords.iterator();
    attemptNextPhoneAccount();
}

我们先看看CreateConnectionProcessor的简介:

这个类创建一个Connection,这个connection用来放置拨出的电话,或者附着到一个呼入电话上。在两种方式中,这个类会循环编译一系列Connection Services,直到有下列情况发生:

  1. 一个connection services返回一个最新创建的connection,因为有一个call被显示给了用户
  2. 一个connection service取消了处理进程,call就abort中断了。

因为可以看到上面的 程序中有一个明显的迭代器,所以看看最后一个函数是否对迭代器的数据进行了处理:

//CreateConnectionProcessor.java
private void attemptNextPhoneAccount() {
    CallAttemptRecord attempt = null;
    if (mAttemptRecordIterator.hasNext()) {
        attempt = mAttemptRecordIterator.next();
    }

    if (mResponse != null && attempt != null) {
        PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
        ConnectionServiceWrapper service = mRepository.getService(phoneAccount.getComponentName(), phoneAccount.getUserHandle());
        if (service == null) {} else {            mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
            mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
            mCall.setConnectionService(service);
            setTimeoutIfNeeded(service, attempt);
            service.createConnection(mCall, new Response(service));
        }}}

//ConnectionServiceWrapper.java
void createConnection(final Call call, final CreateConnectionResponse response) {
    BindCallback callback = new BindCallback() {注意,这个callback就是在下面连接服务成功时候,会触发自己的onSuccess函数};
    mBinder.bind(callback, call);
}

//ServiceBinder.java
void bind(BindCallback callback, Call call) {
        mCallbacks.add(callback);
        if (mServiceConnection == null) {
            Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
            ServiceConnection connection = new ServiceBinderConnection(call);
            Log.event(call, Log.Events.BIND_CS, mComponentName);
            final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
            final boolean isBound;
            if (mUserHandle != null) {
                isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,mUserHandle);
            }}}}

其实这个serviceIntent触发的是”android.telecom.ConnectionService”这个Action,在package/Service/Telephony/AndroidManifest.xml里面可以找到对应的service为TelephonyConnectionService。这个mComponentName的值就没有找到在什么地方了。连接成功之后,就会触发connection的onServiceConnected函数了。


//ServiceBinder&ServiceBinderConnection
public void onServiceConnected(ComponentName componentName, IBinder binder) {
    synchronized (mLock) {
        mServiceConnection = this;
        setBinder(binder);
        handleSuccessfulConnection();
    }}

    private void handleSuccessfulConnection() {
        for (BindCallback callback : mCallbacks) {
            callback.onSuccess();
        } }

这个callback就是在上面createConnection函数中创建的内部类如下:


//ConnectionServiceWrapper.java--createConnection
BindCallback callback = new BindCallback() {
            public void onSuccess()

{
    String callId = mCallIdMapper.getCallId(call);
    mPendingResponses.put(callId, response);
    GatewayInfo gatewayInfo = call.getGatewayInfo();
    Bundle extras = call.getIntentExtras();
    if (gatewayInfo != null && gatewayInfo.getGatewayProviderPackageName() != null &&
            gatewayInfo.getOriginalAddress() != null) {
        extras = (Bundle) extras.clone();        extras.putString(TelecomManager.GATEWAY_PROVIDER_PACKAGE,gatewayInfo.getGatewayProviderPackageName());        extras.putParcelable(TelecomManager.GATEWAY_ORIGINAL_ADDRESS,gatewayInfo.getOriginalAddress());
    }
    try {        mServiceInterface.createConnection(call.getConnectionManagerPhoneAccount(),callId,
                new ConnectionRequest(call.getTargetPhoneAccount(),call.getHandle(),extras,call.getVideoState()),
                call.isIncoming(),
                call.isUnknown());
    }

}};

其实这个mServiceInterface就是绑定ConnectionService的时候反回来的一个IBinder,所以这个引用就是调用的ConnectionService.createConnection了。


//ConnectionService---createConnection
private void createConnection(final PhoneAccountHandle callManagerAccount,final String callId,
        final ConnectionRequest request,boolean isIncoming,boolean isUnknown) {
    Connection connection = onCreateIncomingConnection(callManagerAccount, request);
    Uri address = connection.getAddress();    mAdapter.handleCreateConnectionComplete(callId,request,new ParcelableConnection());

}

这个调用会遍历mAdapter里面的每个IConnectionServiceAdapter,并且执行

adapter.handleCreateConnectionComplete(id, request, connection);

而这个mAdapter是通过调用addAdapter函数进行填充的。而这个函数在ConnectionService唯一调用的地方是在mHandler里面,处理MSG_ADD_CONNECTION_SERVICE_ADAPTER消息的时候。注意这个mHandler和mAdapter都是private的,也就是都是仅限这个类内部访问。这个消息是在mBinder的addConnectionServiceAdapter函数里面触发的。

在ConnectionServiceWrapper里面的setServiceInterface里面会调用


//ConnectionServiceWrapper,setServiceInterface
mServiceInterface = IConnectionService.Stub.asInterface(binder);
addConnectionServiceAdapter(mAdapter);
private void addConnectionServiceAdapter(IConnectionServiceAdapter adapter) {
        if (isServiceValid("addConnectionServiceAdapter")) {                mServiceInterface.addConnectionServiceAdapter(adapter);
        }}

这个adapter函数实际定义在:


//ConnectionServiceWrapper.java
final class ConnectionServiceWrapper extends ServiceBinder {
    private final class Adapter extends IConnectionServiceAdapter.Stub {

其实是一个内部类。所以在ConnectionService—createConnection里面调用adapter.handleCreateConnectionComplete(id, request, connection)实际调用的是这个内部类的对应函数。


//ConnectionServiceWrapper.java---Adapter---handleCreateConnectionComplete
public void handleCreateConnectionComplete(String callId,ConnectionRequest request,ParcelableConnection connection) {
    if (mCallIdMapper.isValidCallId(callId))         ConnectionServiceWrapper.this.handleCreateConnectionComplete(callId, request, connection);
}

private void handleCreateConnectionComplete(String callId,ConnectionRequest request,ParcelableConnection connection) {
    if (connection.getState() == Connection.STATE_DISCONNECTED) {
    } else {
        // Successful connection
        if (mPendingResponses.containsKey(callId)) {            mPendingResponses.remove(callId).handleCreateConnectionSuccess(mCallIdMapper, connection);

        }}}

而通过搜索,发现在call.java里面有对函数handleCreateConnectionSuccess的实现。

public void handleCreateConnectionSuccess(CallIdMapper idMapper, ParcelableConnection connection) {
    setTargetPhoneAccount(connection.getPhoneAccount());
    setHandle(connection.getHandle(), connection.getHandlePresentation());
//设置显示呼叫者名字    setCallerDisplayName(connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());    setConnectionCapabilities(connection.getConnectionCapabilities());
    setVideoProvider(connection.getVideoProvider());
    setVideoState(connection.getVideoState());    setRingbackRequested(connection.isRingbackRequested());
    setIsVoipAudioMode(connection.getIsVoipAudioMode());
    setStatusHints(connection.getStatusHints());
    setExtras(connection.getExtras());

    if (mIsUnknown) {
    } else if (mIsIncoming) {
        // We do not handle incoming calls immediately when they are verified by the connection
        // service. We allow the caller-info-query code to execute first so that we can read the
        // direct-to-voicemail property before deciding if we want to show the incoming call to
        // the user or if we want to reject the call.
        mDirectToVoicemailQueryPending = true;
        // Timeout the direct-to-voicemail lookup execution so that we dont wait too long before
        // showing the user the incoming call screen.
        mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis(
                mContext.getContentResolver()));
    } else {
        for (Listener l : mListeners) {            l.onSuccessfulOutgoingCall(this,getStateFromConnectionState(connection.getState()));
        }
    }
}

请注意看if (mIsIncoming)这个分支里面的注释。当我们正在被连接服务(connection service)验证的时候,我们并不立即处理呼入电话。我们允许来电信息查询代码首先执行,这样我们就可以读取是否转到语音邮箱的属性,这样我们可以决定我们是否将来电显示给用户还是直接拒绝。

我们在看看这个作为mDirectToVoicemailRunnable

//Call.java
private final Runnable mDirectToVoicemailRunnable = new Runnable() {
        public void run() {
            synchronized (mLock) {
                processDirectToVoicemail();
            }}};

private void processDirectToVoicemail() {
    if (mDirectToVoicemailQueryPending) {
        if (mCallerInfo != null && mCallerInfo.shouldSendToVoicemail) {
   setState(CallState.RINGING, "directing to voicemail");
            reject(false, null);
        } else {
            for (Listener l : mListeners) {
                l.onSuccessfulIncomingCall(this);
            }
        }
        mDirectToVoicemailQueryPending = false;
    }
}

会调用mListeners的onSuccessfulIncomingCall函数。


//CallsManager.java
public void onSuccessfulIncomingCall(Call incomingCall) {
    setCallState(incomingCall, CallState.RINGING, "successful incoming call");
    if (hasMaximumRingingCalls(incomingCall.getTargetPhoneAccount().getId()) || hasMaximumDialingCalls() ) {
        incomingCall.reject(false, null);
        // since the call was not added to the list of calls, we have to call the missed
        // call notifier and the call logger manually.        mMissedCallNotifier.showMissedCallNotification(incomingCall);
        mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE);
    } else {        if(TelephonyManager.getDefault().getMultiSimConfiguration()== TelephonyManager.MultiSimVariants.DSDA) {
            incomingCall.mIsActiveSub = true;
        }
        addCall(incomingCall);        setActiveSubscription(incomingCall.getTargetPhoneAccount().getId());
    }}

private void addCall(Call call) {
    call.addListener(this);
    mCalls.add(call);
    // TODO: Update mForegroundCall prior to invoking
    // onCallAdded for calls which immediately take the foreground (like the first call).
    for (CallsManagerListener listener : mListeners) {
        listener.onCallAdded(call);
    }
    updateCallsManagerState();
}

在CallsManagerListener里面,调用里面的onCallAdded如下:

//InCallController.java这个类实现了CallsManagerListenerBase这个类,所以看看这个的onCallAdded
    public void onCallAdded(Call call) {
        if (!isBoundToServices()) {//在成功绑定了服务之后,这个函数返回值应该就是true了,所以应该走另外一个分支
            bindToServices(call);
        } else {
            Log.i(this, "onCallAdded: %s", call);
            // Track the call if we don‘t already know about it.
            addCall(call);
            for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
           ComponentName componentName = entry.getKey();
          IInCallService inCallService = entry.getValue();
          ParcelableCall parcelableCall = toParcelableCall(call, true /* includeVideoProvider */);
                try {
                    inCallService.addCall(parcelableCall);
                } catch (RemoteException ignored) {
                }}}}

这个会调用InCallService的addCall函数。

//InCallService.java
public void addCall(ParcelableCall call) {    mHandler.obtainMessage(MSG_ADD_CALL,call).sendToTarget();
}

case MSG_SET_IN_CALL_ADAPTER:
      mPhone = new Phone(newInCallAdapter((IInCallAdapter) msg.obj));
      mPhone.addListener(mPhoneListener);
      onPhoneCreated(mPhone);
      break;
case MSG_ADD_CALL:
     mPhone.internalAddCall((ParcelableCall) msg.obj);
     break;

//Phone.java
final void internalAddCall(ParcelableCall parcelableCall) {
    Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,parcelableCall.getState(), parcelableCall.isActive());
    mCallByTelecomCallId.put(parcelableCall.getId(), call);
    mCalls.add(call);
    checkCallTree(parcelableCall);    call.internalUpdate(parcelableCall,mCallByTelecomCallId);
    fireCallAdded(call);

 }

注意最后的这个inCallService.addCall(parcelableCall),实际触发了一个消息机制。同时注意,还有一个MSG_SET_IN_CALL_ADAPTER消息会触发将mPhoneListener加入到Phone的监听者列表里面。最终该消息会触发 mPhone.internalAddCall。我们看看这个最后的调用函数fireCallAdded(call):

//Phone.java
private void fireCallAdded(Call call) {
        for (Listener listener : mListeners) {
            listener.onCallAdded(this, call);
        }
    }

上面我们也提到了,另外一个消息MSG_SET_IN_CALL_ADAPTER,会将一个监听者mPhoneListener加入到Phone的监听列表里面,所以这个循环遍历列表的行为会触发这个mPhoneListener。


//InCallService.java
private Phone.Listener mPhoneListener = new Phone.Listener() {
    public void onAudioStateChanged(Phone phone, AudioState audioState) {}
    public void onCallAudioStateChanged(Phone phone, CallAudioState callAudioState) {        InCallService.this.onCallAudioStateChanged(callAudioState);};
    public void onBringToForeground(Phone phone, boolean showDialpad) {        InCallService.this.onBringToForeground(showDialpad);}
    public void onCallAdded(Phone phone, Call call) {
        InCallService.this.onCallAdded(call);}
    public void onCallRemoved(Phone phone, Call call) {
        InCallService.this.onCallRemoved(call);}
    public void onCanAddCallChanged(Phone phone, boolean canAddCall) {        InCallService.this.onCanAddCallChanged(canAddCall);}
};

看看上面的,基本上设计到了各种通话属性的变化。而且都是转到InCallService里面进行处理。看看对于onCallAdded的处理。

InCallService里面的onCallAdded是一个空函数,所以会由它的子类来进行处理,它的子类是InCallServiceImpl.java。重点来了,这个子类中的实现为:


//InCallServiceImpl
public class  InCallServiceImpl extends InCallService{
public void onCallAdded(Call call) {
        CallList.getInstance().onCallAdded(call);
        InCallPresenter.getInstance().onCallAdded(call);
    }}

我们来看看CallList的onCallAdded函数:

//CallList.java
ublic void onCallAdded(android.telecom.Call telecommCall) {
        Call call = new Call(telecommCall);
        if (call.getState() == Call.State.INCOMING ||call.getState() == Call.State.CALL_WAITING) {
        onIncoming(call, call.getCannedSmsResponses());
        } else {
            onUpdate(call);
        } }

public void onIncoming(Call call, List<String> textMessages) {
    for (Listener listener : mListeners) {
        listener.onIncomingCall(call);
    }
}

上面讲到了一个细节,CallList实际将InCallPresenter实例保存在了listener列表里面。所以这个onIncoming会触发listener.onIncomingCall(call);这个listener则是InCallPresenter,所以最后调用的是如下:


//InCallPresenter.java
    public void onIncomingCall(Call call) {
        InCallState newState = startOrFinishUi(InCallState.INCOMING);
        InCallState oldState = mInCallState;
        mInCallState = newState;
        for (IncomingCallListener listener : mIncomingCallListeners) {
            listener.onIncomingCall(oldState, mInCallState, call);
        }

        if (InCallServiceImpl.isDsdaEnabled() && (mInCallActivity != null)) {
            mInCallActivity.updateDsdaTab();
        }
    }

注意,上面的startOrFinishUi是关键函数,涉及到显示来电接听的UI弹出流程。这个InCallPresenter很像Google提倡的MVP结构里面的Presenter啊!

综上,CallList的onCallAdded函数会触发来电信息的显示。最后发现,在InCallServiceImpl.java里面,在onCallAdded函数里面会触发CallList的对应函数,也就是会触发来电显示。

时间: 2024-11-08 04:32:46

基于Android6.0的RIL框架层模块分析的相关文章

基于Android系统应用层与框架层剖析View点击事件

基于Android操作系统的框架层和应用层,介绍了View的绘制.触摸事件的传递流程,分析了View与用户交互时被回调的相关框架层代码和应用层代码,研究了Android应用中事件处理的相关重要机制.通过具体代码详细剖析了在Android系统下用户和View交互过程中折射出的回调机制,回调方法在系统框架的详细执行过程,以及基于回调机制的经典事件处理模型. 1 引言 Android是一种基于Linux的自由及开放源代码的操作系统,目前基于Android平台的应用日趋广泛.Android应用程序大多基

html一个页面链接携带参数跳转另一个页面基于vue2.0的element框架

来给生活比个耶! 1.按钮 <el-button @click="albumList(scope.row.id)" size="mini" type="primary" size="small">相册列表</el-button> 2.js函数 albumList (id){ location.href=`album_list.html?id=`+id /*跳转页面传递id值*/ }, 3.钩子函数 加载

Android6.0来电号码电话薄名称匹配

本文将介绍系统接收到来电之后,如何在电话薄中进行匹配联系人的流程.分析将从另外一篇文章(基于Android6.0的RIL框架层模块分析)中提到的与本文内容相关的代码开始. //packages/service/***/Call.java public void handleCreateConnectionSuccess( CallIdMapper idMapper, ParcelableConnection connection) { setHandle(connection.getHandle

Android6.0执行时权限解析,RxPermissions的使用,自己封装一套权限框架

Android6.0执行时权限解析,RxPermissions的使用.自己封装一套权限框架 在Android6.0中,新添加了一个执行时的权限,我相信非常多人都已经知道了.预计也知道怎么用了,这篇博客非常easy.就是告诉大家怎样去申请执行时权限和RxPermission这个权限框架的使用.同一时候依据现有的技术封装思想,去封装一个自己可用的权限框架,好的,我们继续往下看 一.Android M 执行时权限介绍 关于Android M的更新变化,我就不啰嗦了,有兴趣的能够看下Android M更

基于 ASP.NET Core 2.0 WebAPI 后台框架搭建(0) - 目录概述

概述 博主自毕业后,进公司就一直是以ASP.NET MVC 5.0 + MySQL 进行项目开发,在项目也使用了很多常用功能,如 WCF.SignalR.微信公众号API.支付宝API.Dapper等等,前端是大杂烩,如:Bootstrap.AmazeUI.EasyUI.Light7.WeUI等等.其实对于我们公司的项目来说,技术栈虽说不庞大,但五脏俱全,而且基于这一套技术,开发速度有保证.但是,作为一个有梦想的程序猿,必须与时俱进,因此无意中接触了.Net Core 2.0.听说它是开源的?它

基于 ASP.NET Core 2.0 WebAPI 后台框架搭建(4) - EF Core CodeFirst 数据库创建

概述 在 基于 ASP.NET Core 2.0 WebAPI 后台框架搭建(2) - EF Core (MySQL) CodeFirst 数据库迁移与依赖注入 一文中,我们介绍如何快速以CodeFirst快速搭建数据库,这一章,我们来完善一下创建数据库中可以添加的验证与约束. 微软爸爸官方文档:Entity Framework Core 数据库操作 (1) 数据库迁移  add-migration [任一名称,须唯一] (2) 更新数据库  update-database (3) 删除数据库迁

Android6.0 Bitmap存储以及Parcel传输

如果想要对Android Bitmap进行更多的操作,理解好Bitmap的实现将会有非常大的帮助,另外Android在6.0中增加了asm存储图片.这篇文章就通过源码来分析Android6.0中的Bitmap.本文主要分析Java层与native层的Bitmap,以及Bitmap的储存和Parcel传输.源码基于6.0,所以会有一些新的特性. Bitmap存储方式以及包含的属性 计算机里面图片都是作为数组来存储的,而在Android中Bitmap也是一样.在Java层的Bitmap数组保存为mB

Java网络编程和NIO详解9:基于NIO的网络编程框架Netty

Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introduction/ netty是基于NIO实现的异步事件驱动的网络编程框架,学完NIO以后,应该看看netty的实现,netty框架涉及的内容特别多,这里只介绍netty的基本使用和实现原理,更多扩展的内容将在以后推出. 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎

SpringMVC学习第一天(基于Spring4.0)

简介:Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口.在很多方面优秀于Struts2支持REST风格的URL请求采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性 简单HelloWorld例子(基于Spring4.0)1. 八个基础jar包- commons-logging-1.1.3.jar– spring-aop-4.