1. 程式人生 > >Android8.0 Rild守護程序

Android8.0 Rild守護程序

電話是一種開放的通訊渠道,任何人都可以隨時向任何電話號碼致電或者傳送簡訊,因此 Android 使用者需要能夠輕鬆遮蔽騷擾電話和簡訊。在 Android N 推出之前,Android 使用者只能依靠下載的應用來限制來自騷擾電話號碼的來電和簡訊。但是,由於沒有適當的 API 來遮蔽來電和簡訊,這些應用大部分要麼達不到預期效果,要麼使用者體驗不佳。

在這裡插入圖片描述

一些製造商可能會提供他們自己的開箱即用型遮蔽解決方案,但是如果使用者更換裝置,由於缺乏互用性,他們的遮蔽列表可能會完全丟失。最後,即便使用者採用了提供此類功能的撥號應用和簡訊客戶端,他們可能仍需在每個應用中執行遮蔽操作,才能有效遮蔽來電和簡訊。Android 7.0 版本引入了 BlockedNumberProvider 內容提供程式,該程式可以儲存使用者指定的無法通過電話通訊(通話、簡訊、彩信)與他們聯絡的電話號碼列表。系統會參考遮蔽列表中的號碼,限制來自這些號碼的來電和簡訊。Android 7.0 不僅會顯示遮蔽號碼列表,還可讓使用者新增和刪除號碼。

1. 啟動Rild後臺程序

hardware\ril\rild\rild.c

int main(int argc, char **argv) {
    // vendor ril lib path either passed in as -l parameter, or read from rild.libpath property
    const char *rilLibPath = NULL;
    // ril arguments either passed in as -- parameter, or read from rild.libargs property
    char
**rilArgv; //廠商ril庫控制代碼 void *dlHandle; //廠商ril庫回撥 const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **); // Pointer to sap init function in vendor ril RIL_RadioFunctions *(*rilUimInit)(const struct RIL_Env *, int, char **); const char *err_str = NULL; // functions returned by ril init function in vendor ril
const RIL_RadioFunctions *funcs; ...... //打開廠商庫 dlHandle = dlopen(rilLibPath, RTLD_NOW); //啟動事件迴圈 RIL_startEventLoop(); //呼叫系統庫 rilInit =(const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init"); rilUimInit =(RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_SAP_Init"); //初始化rilInit funcs = rilInit(&s_rilEnv, argc, rilArgv); //註冊回撥函式 RIL_register(funcs); //註冊套接 if (rilUimInit) { RIL_register_socket(rilUimInit, RIL_SAP_SOCKET, argc, rilArgv); } done: ..... rilc_thread_pool(); ..... }

2. 啟動事件迴圈

hardware\ril\libril\ril.cpp

extern "C" void
RIL_startEventLoop(void) {
    ......
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    //啟動執行緒,執行 eventLoop
    int result = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
    while (s_started == 0) {
        pthread_cond_wait(&s_startupCond, &s_startupMutex);
    }
    ......

hardware\ril\libril\ril.cpp

static void *
eventLoop(void *param) {
    int ret;
    int filedes[2];
    //初始化事件連結串列
    ril_event_init();
    //建立管道
    ret = pipe(filedes);
    //讀寫喚醒描述符
    s_fdWakeupRead = filedes[0];
    s_fdWakeupWrite = filedes[1];
    //執行
    fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
    //設定事件描述符和事件處理函式
    ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
                processWakeupCallback, NULL);
    rilEventAddWakeup (&s_wakeupfd_event);
    //開始ril事件迴圈
    ril_event_loop();
    ......

    return NULL;
}

hardware\ril\libril\ril_event.cpp

void ril_event_init()
{
    MUTEX_INIT();
    FD_ZERO(&readFds);
    init_list(&timer_list); //初始化事件連結串列
    init_list(&pending_list);
    memset(watch_table, 0, sizeof(watch_table));
}

static void init_list(struct ril_event * list)
{
    memset(list, 0, sizeof(struct ril_event));
    list->next = list;
    list->prev = list;
    list->fd = -1; //儲存檔案描述符
}

hardware\ril\libril\ril_event.cpp

void ril_event_loop()
{
    int n;
    fd_set rfds;
    struct timeval tv;
    struct timeval * ptv;


    for (;;) {
        ......
        n = select(nfds, &rfds, NULL, NULL, ptv); //開始select
        ......
        // Check for timeouts
        processTimeouts();
        // Check for read-ready
        processReadReadies(&rfds, n);
        // Fire away
        firePending();
    }
}

static void processReadReadies(fd_set * rfds, int n)
{
    for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {
        struct ril_event * rev = watch_table[i];
        if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
            addToList(rev, &pending_list); //新增到掛起列表
            if (rev->persist == false) {
                removeWatch(rev, i); //從描述符觀察表中移除
            }
            n--;
        }
    }
}

static void firePending()
{
    struct ril_event * ev = pending_list.next;
    while (ev != &pending_list) {
        struct ril_event * next = ev->next;
        removeFromList(ev);
        ev->func(ev->fd, 0, ev->param); //執行函式 processWakeupCallback
        ev = next;
    }
}

hardware\ril\libril\ril.cpp

static void processWakeupCallback(int fd, short flags, void *param) {
    char buff[16];
    int ret;
    //迴圈從套接端讀取
    do {
        ret = read(s_fdWakeupRead, &buff, sizeof(buff));
    } while (ret > 0 || (ret < 0 && errno == EINTR));
}

hardware\ril\libril\ril.cpp

static void rilEventAddWakeup(struct ril_event *ev) {
    ril_event_add(ev);
    triggerEvLoop();
}

hardware\ril\libril\ril_event.cpp

void ril_event_add(struct ril_event * ev)
{
    for (int i = 0; i < MAX_FD_EVENTS; i++) {
        if (watch_table[i] == NULL) {
            watch_table[i] = ev; //加入事件觀察表中
            ev->index = i; //加索引
            FD_SET(ev->fd, &readFds);
            if (ev->fd >= nfds) nfds = ev->fd+1;
            break;
        }
    }
}

hardware\ril\libril\ril.cpp

static void triggerEvLoop() {
    int ret;
    if (!pthread_equal(pthread_self(), s_tid_dispatch)) {
          //迴圈觸發喚醒事件迴圈
         do {
            ret = write (s_fdWakeupWrite, " ", 1);
         } while (ret < 0 && errno == EINTR);
    }
}

3. 啟動RIL庫

hardware\ril\reference-ril\reference-ril.c

const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
    ......
    //啟動執行緒,開始主迴圈
    ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL); 
    ......
    return &s_callbacks; //返回操作結構體
}

//函式回撥結構表
static const RIL_RadioFunctions s_callbacks = {
    RIL_VERSION,
    onRequest,
    currentState,
    onSupports,
    onCancel,
    getVersion
};

hardware\ril\reference-ril\reference-ril.c
開始開啟BP(基帶處理器)

static void *
mainLoop(void *param __unused)
{
    int fd;
    int ret;
    at_set_on_reader_closed(onATReaderClosed);
    at_set_on_timeout(onATTimeout);
    for (;;) {
        fd = -1;
        while  (fd < 0) {
            if (isInEmulator()) {
                fd = qemu_pipe_open("pipe:qemud:gsm"); //模擬
            } else if (s_port > 0) {
                fd = socket_network_client("localhost", s_port, SOCK_STREAM); //網路
            } else if (s_device_socket) { //本地
                fd = socket_local_client(s_device_path,
                                         ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
                                         SOCK_STREAM);
            } else if (s_device_path != NULL) {
                fd = open (s_device_path, O_RDWR); //開啟基帶處理器
                if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
                    /* disable echo on serial ports */
                    struct termios  ios;
                    tcgetattr( fd, &ios );
                    ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
                    tcsetattr( fd, TCSANOW, &ios );
                }
            }
            ......
        }

        s_closed = 0;
        ret = at_open(fd, onUnsolicited); // 開始基帶處理通訊,出入檔案描述符,回撥處理函式
        RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
        ......
    }
}

4. 未經請求的AT通訊

hardware\ril\reference-ril\atchannel.c

int at_open(int fd, ATUnsolHandler h)
{
    int ret;
    pthread_t tid;
    pthread_attr_t attr;

    s_fd = fd;
    s_unsolHandler = h; //回撥處理控制代碼
    s_readerClosed = 0;
    //開執行緒迴圈讀取
    ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
    ......
    return 0;
}

hardware\ril\reference-ril\atchannel.c
迴圈讀取基帶處理器的AT指令

static void *readerLoop(void *arg __unused)
{
    for (;;) {
        const char * line;

        line = readline(); //讀取AT命令

        if (line == NULL) {
            break;
        }

        if(isSMSUnsolicited(line)) { //是未經請求的回覆
            char *line1;
            const char *line2;

            // The scope of string returned by 'readline()' is valid only
            // till next call to 'readline()' hence making a copy of line
            // before calling readline again.
            line1 = strdup(line);
            line2 = readline();

            if (line2 == NULL) {
                free(line1);
                break;
            }

            if (s_unsolHandler != NULL) {
                s_unsolHandler (line1, line2); //回撥
            }
            free(line1);
        } else {
            processLine(line); //處理
        }
    }

    onReaderClosed();

    return NULL;
}

hardware\ril\reference-ril\atchannel.c
讀取AT命令列

static const char *readline()
{
    ssize_t count;

    char *p_read = NULL;
    char *p_eol = NULL;
    char *ret;

    /* this is a little odd. I use *s_ATBufferCur == 0 to
     * mean "buffer consumed completely". If it points to a character, than
     * the buffer continues until a \0
     */
    if (*s_ATBufferCur == '\0') {
        /* empty buffer */
        s_ATBufferCur = s_ATBuffer;
        *s_ATBufferCur = '\0';
        p_read = s_ATBuffer;
    } else {   /* *s_ATBufferCur != '\0' */
        /* there's data in the buffer from the last read */

        // skip over leading newlines
        while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
            s_ATBufferCur++;

        p_eol = findNextEOL(s_ATBufferCur);

        if (p_eol == NULL) {
            /* a partial line. move it up and prepare to read more */
            size_t len;

            len = strlen(s_ATBufferCur);

            memmove(s_ATBuffer, s_ATBufferCur, len + 1);
            p_read = s_ATBuffer + len;
            s_ATBufferCur = s_ATBuffer;
        }
        /* Otherwise, (p_eol !- NULL) there is a complete line  */
        /* that will be returned the while () loop below        */
    }

    while (p_eol == NULL) {
        if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) {
            RLOGE("ERROR: Input line exceeded buffer\n");
            /* ditch buffer and start over again */
            s_ATBufferCur = s_ATBuffer;
            *s_ATBufferCur = '\0';
            p_read = s_ATBuffer;
        }

        do {
            //迴圈讀取AT指令資料
            count = read(s_fd, p_read,
                            MAX_AT_RESPONSE - (p_read - s_ATBuffer));
        } while (count < 0 && errno == EINTR);

        if (count > 0) {
            AT_DUMP( "<< ", p_read, count );

            p_read[count] = '\0';

            // skip over leading newlines
            while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
                s_ATBufferCur++;

            p_eol = findNextEOL(s_ATBufferCur);
            p_read += count;
        } else if (count <= 0) {
            /* read error encountered or EOF reached */
            if(count == 0) {
                RLOGD("atchannel: EOF reached");
            } else {
                RLOGD("atchannel: read error %s", strerror(errno));
            }
            return NULL;
        }
    }

    /* a full line in the buffer. Place a \0 over the \r and return */

    ret = s_ATBufferCur;
    *p_eol = '\0';
    s_ATBufferCur = p_eol + 1; /* this will always be <= p_read,    */
                              /* and there will be a \0 at *p_read */

    RLOGD("AT< %s\n", ret);
    return ret;
}

hardware\ril\reference-ril\atchannel.c
處理命令列

static void processLine(const char *line)
{
    pthread_mutex_lock(&s_commandmutex);

    if (sp_response == NULL) {
        /* no command pending */
        handleUnsolicited