Android c++层 Handler分析和使用

1. C++层的Looper分析

文件:

platform/system/core/include/utils/Looper.h
platform/system/core/libutils/Looper.cpp

  • 前面的文章 Android Looper与Message 中最后
    可以看到,Java层的MessageQueue的等待/唤醒机制其实是由底层的Looper
    中对epoll进行操作来实现的。
  • 其实在同一个逻辑流程中, 也对C++层的Message做了通知处理。
    (C++中的Looper对Java层MessageQueue的影响就只有等待唤醒机制,没有其他的逻辑影响)

1. C++层的Handler: MessageHandler

  1. MessageHandler
//system/core/include/utils/Looper.h
/**
 * Interface for a Looper message handler.
 *
 * The Looper holds a strong reference to the message handler whenever it has
 * a message to deliver to it.  Make sure to call Looper::removeMessages
 * to remove any pending messages destined for the handler so that the handler
 * can be destroyed.
 */
class MessageHandler : public virtual RefBase {
protected:
    virtual ~MessageHandler() { }

public:
    /**
     * Handles a message.
     */
    virtual void handleMessage(const Message& message) = 0;
};
  1. Message
/**
 * A message that can be posted to a Looper.
 */
struct Message {
    Message() : what(0) { }
    Message(int what) : what(what) { }

    /* The message type. (interpretation is left up to the handler) */
    int what;
};

2. C++ Messagehandler的使用

Messagehandler在使用上其实也很简单:

//1. 导入Looper.h
#include <utils/Looper.h>

//2. 获取当前线程的Looper对象:
sp<Looper> looper = Looper::getForThread();

//3. 发送Message到当前线程的Looper队列中,等待回调:
mHandler = new MHandler();
msg = new Message(1/*what*/);
 looper ->sendMessage(delay, mHandler/*MessageHandler*/, msg/*Message*/);

//-------------------------------------------------------
//mHandler
class MHandler: public MessageHandler {
public:
  virtual void handleMessage(const Message& message) override;
}

 void MHandler::handleMessage(const Message& message) {
     //最后会调用到这里
 }

3. Looper::sendMessage 流程

  1. 将事件封装入队
void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    sendMessageAtTime(now, handler, message);
}

void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
        const Message& message) {
#if DEBUG_CALLBACKS
    ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", handler=%p, what=%d",
            this, uptime, handler.get(), message.what);
#endif

    size_t i = 0;
    { // acquire lock
        AutoMutex _l(mLock);

        size_t messageCount = mMessageEnvelopes.size();
        while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
            i += 1; //按照嗲用时间进行排序,计算要插入的位置
        }

        //将Handler和Message封装成MessageEnvelope对象, 然后插入到mMessageEnvelopes队列中;
        MessageEnvelope messageEnvelope(uptime, handler, message);
        mMessageEnvelopes.insertAt(messageEnvelope, i, 1);

        // Optimization: If the Looper is currently sending a message, then we can skip
        // the call to wake() because the next thing the Looper will do after processing
        // messages is to decide when the next wakeup time should be.  In fact, it does
        // not even matter whether this code is running on the Looper thread.
        if (mSendingMessage) {
            return;
        }
    } // release lock

    // Wake the poll loop only when we enqueue a new message at the head.
    if (i == 0) {
        wake();
    }
}
  1. pollOnce之后,进行对Handler和Message的处理:
int Looper::pollInner(int timeoutMillis) {
    ...
//-----------------1. 对Java层MQ阻塞事件和addFd函数添加的fd中的事件进行处理---------------------------------------------------------
	for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeEventFd) { //mWakeEventFd 用来解除Java层MQ的阻塞状态;
            if (epollEvents & EPOLLIN) {
                awoken();
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
            }
        } else {
            //这里是将addFd中的Request事件封装为Resonse事件, 并添加Response事件,即对addFd函数添加的fd中的事件响应;
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
                pushResponse(events, mRequests.valueAt(requestIndex)); //添加Request的Response事件
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
                        "no longer registered.", epollEvents, fd);
            }
        }
    }
Done: ;

//----------------------2. 对C++层Handler(MessageHandler)事件进行处理-----------------------------------------------

    // Invoke pending message callbacks.
    mNextMessageUptime = LLONG_MAX;
    while (mMessageEnvelopes.size() != 0) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);//取出队列中的MessageEnvelope
        if (messageEnvelope.uptime <= now) { //已经到达运行时间
            { // 获取Handler和Message
                sp<MessageHandler> handler = messageEnvelope.handler;
                Message message = messageEnvelope.message;
                //移除队列中的首位MessageEnvelope项
                mMessageEnvelopes.removeAt(0);
                mSendingMessage = true;
                mLock.unlock();

#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
                ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
                        this, handler.get(), message.what);
#endif
                //回调handleMessage方法;
                handler->handleMessage(message);
            } // release handler

            mLock.lock();
            mSendingMessage = false;
            result = POLL_CALLBACK;
        } else {
            // The last message left at the head of the queue determines the next wakeup time.
            mNextMessageUptime = messageEnvelope.uptime;
            break;
        }
    }
}
 // Release lock.
    mLock.unlock();

//--------------------------3. 对addFd函数中request注册的回调进行处理(Response事件处理)---------------------------------------------------
    // Invoke all response callbacks.
    for (size_t i = 0; i < mResponses.size(); i++) {
        //取出每个Response对象
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == POLL_CALLBACK) {
            //获取回调需要的参数
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;

            ...
            
            //回调handleEvent方法;
            int callbackResult = response.request.callback->handleEvent(fd, events, data);
            if (callbackResult == 0) {
                removeFd(fd, response.request.seq);
            }
            //清除CallBack
            response.request.callback.clear();
            result = POLL_CALLBACK;
        }
    }

4. addFd函数

addFd函数,在调用时, 传入一个需要添加的fd到对应Looper的epoll事件监听池中,对fd中感兴趣的事件进行监听,监听的结果会返回到传入的监听器中,见上面代码中分析的第三点;

  1. addFd时需要传入的CallBack监听器:
///system/core/include/utils/Looper.h
/**
 * A looper callback.
 */
class LooperCallback : public virtual RefBase {
protected:
    virtual ~LooperCallback() { }

public:
    /**
     * Handles a poll event for the given file descriptor.
     * It is given the file descriptor it is associated with,
     * a bitmask of the poll events that were triggered (typically EVENT_INPUT),
     * and the data pointer that was originally supplied.
     *
     * Implementations should return 1 to continue receiving callbacks, or 0
     * to have this file descriptor and callback unregistered from the looper.
     */
    virtual int handleEvent(int fd, int events, void* data) = 0;
};
  1. SimpleLooperCallback

SimpleLooperCallback 时对LooperCallback的简单封装, 目的主要是为了addFd的一个重载,用于函数式调用

/**
 * Wraps a Looper_callbackFunc function pointer.
 */
class SimpleLooperCallback : public LooperCallback {
protected:
    virtual ~SimpleLooperCallback();

public:
    SimpleLooperCallback(Looper_callbackFunc callback);
    virtual int handleEvent(int fd, int events, void* data);

private:
    Looper_callbackFunc mCallback;
};
  1. addFd函数:
int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
    return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data); //SimpleLooperCallback即用于该重载, 为了简单化callBack的传入类型, 之间穿入一个函数指针;
}

//最终调用的这一个addFd
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
    if (!callback.get()) {
        if (! mAllowNonCallbacks) {
            ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
            return -1;
        }

        if (ident < 0) {
            ALOGE("Invalid attempt to set NULL callback with ident < 0.");
            return -1;
        }
    } else {
        ident = POLL_CALLBACK;
    }

    { // acquire lock
        AutoMutex _l(mLock);

        //构造Request对象
        Request request;
        request.fd = fd;
        request.ident = ident;
        request.events = events;
        request.seq = mNextRequestSeq++;
        request.callback = callback;
        request.data = data;
        
        if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1

        struct epoll_event eventItem;
        request.initEventItem(&eventItem);
        ssize_t requestIndex = mRequests.indexOfKey(fd);
      
        //处理对fd事件的监听, 并将其加入到epoll事件池中;
        if (requestIndex < 0) {
            //如果不存在,则做添加操作
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
            if (epollResult < 0) {
                ALOGE("Error adding epoll events for fd %d: %s", fd, strerror(errno));
                return -1;
            }
            mRequests.add(fd, request);
        } else {
            //如果已经存在,则做修改操作
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
            if (epollResult < 0) {
                if (errno == ENOENT) {
                   /*...*/
                   //修改失败,则做添加操作
                    epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
                    if (epollResult < 0) {
                        ALOGE("Error modifying or adding epoll events for fd %d: %s",
                                fd, strerror(errno));
                        return -1;
                    }
                    scheduleEpollRebuildLocked();
                } else {
                    ALOGE("Error modifying epoll events for fd %d: %s", fd, strerror(errno));
                    return -1;
                }
            }
            //更新Request;
            mRequests.replaceValueAt(requestIndex, request);
        }
    } // release lock
    return 1;
}

5. 代码使用案例

1. MessageHandler
#include "looper/Looper.h"
#include <string>
#include <thread>
#include <cstring>

using namespace android;

static bool isQuit = false;

int main() {

    class TestHandler : public  MessageHandler {
        void handleMessage(const Message& message) {
            printf("handleMessage ###: %d\n", message.what);
        };
    };


    std::shared_ptr<TestHandler> handler;
    std::shared_ptr<Looper> looper;

    std::thread thread([=](std::shared_ptr<Looper>* looper,
                           std::shared_ptr<TestHandler>* handler){
        *looper = Looper::getForThread();
        if (*looper == nullptr) {
            *handler = std::make_shared<TestHandler>();
            if (*looper == nullptr) {
                *looper = Looper::prepare(0);
            }

            printf("looper= %p\n", looper->get());
        }

        (*looper)->sendMessage(*handler, Message(1));

        while (!isQuit){
            printf("pollOnce\n");
            (*looper)->pollOnce(-1);
        }

    }, &looper, &handler);



    while (true) {
        if (isQuit) {
            if (looper->isPolling()) {
                looper->wake();
            }

            break;
        }

        if (looper) {
            looper->sendMessage(handler, Message(1));
            sleep(1);
        }

    }
}

2. FD监听
#include "looper/Looper.h"
#include <string>
#include <thread>
#include <cstring>

using namespace android;

static bool isQuit = false;

int main() {

    int fds[2];
//    int ret = pipe(fds);
//    if (ret == -1) {
//        strerror(errno);
//        exit(1);
//    }

    int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
    if (ret == -1) {
        strerror(errno);
        exit(1);
    }


    pid_t pid = fork();

    if (pid == 0) {
        //子进程, 关闭write fd, 监听receive fd
        close(fds[0]);

        //创建looper
        std::shared_ptr<Looper> looper = Looper::getForThread();
        if (looper == nullptr) {
            looper = Looper::prepare(0);
        }

        //创建FD监听的looper callback
        class MyCallback : public LooperCallback {
            int handleEvent(int fd, int events, void* data) {
                printf("[%d]handleEvent, fd=%d\n", getpid(), fd);

                if (events & Looper::EVENT_INPUT) {
                    printf("[%d]EVENT_INPUT\n", getpid());


                    //读取内容......
                    char buf[256];
                    ::recv(fd, buf, 256, 0);
                    //read(fd, buf, 256);
                    printf("[%d]receive: %s\n", getpid(), buf);

                    if (strncmp("exit", buf, 4) == 0) {
                        printf("[%d]EXIT!!!\n", getpid());
                        isQuit = true;
                    }

                } else if (events & Looper::EVENT_OUTPUT) {
                    printf("[%d]EVENT_OUTPUT\n", getpid());

                } else if (events & Looper::EVENT_ERROR) {
                    printf("[%d]EVENT_ERROR\n", getpid());

                } else if (events & Looper::EVENT_HANGUP) {
                    printf("[%d]EVENT_HANGUP\n", getpid());

                } else {
                    printf("[%d]else....\n", getpid());
                }

            }
        };


        //监听read fd
        auto callback = std::make_shared<MyCallback>();
        looper->addFd(fds[1], Looper::POLL_CALLBACK,
                      Looper::EVENT_INPUT/*|Looper::EVENT_OUTPUT*/,
                      callback, NULL);


        //loop
        while (!isQuit){
            printf("[%d]pollOnce\n", getpid());
            looper->pollOnce(-1);
            printf("pollOnce 222\n");
        }

        close(fds[1]);
    } else if (pid > 0){
        //主进程, 关闭read fd
        close(fds[1]);

        int count = 0;
        while (true) {
            if (isQuit) {
                break;
            }



            const char *buf = std::to_string(count++).c_str();
            //printf("[%d]: fd= %d, Send: %s\n", getpid(), fds[0], buf);

            ::send(fds[0], buf, 10, 0);
            //write(fds[0], buf, 10);

            usleep(10);

            if (count >= 10000) {
                printf("[%d]: wait....\n", getpid());
                char exitBuf[6] = "exit\n";
                ::send(fds[0], exitBuf, 10, 0);
                //sleep(100);

                isQuit = true;
            }

        }

        close(fds[0]);
    }
}


2. 总结:

  1. 逻辑相关:
    Looper中的事件队列机制, 集成了两种事件处理监听机制:
  1. addFd: 对添加的文件描述符中的(写入/写出)事件仅从监听处理;
  2. MessageHandler: C++层的Handler机制;

2.非逻辑相关:

  • Looper中的mWakeEventFd只是对Java层MQ的阻塞/唤醒机制做控制,而不影响Java MQ的逻辑。
  • Java MQ只是借助了该Looper进行阻塞实现。Looper中的mWakeEventFd只是对Java层MQ的阻塞/唤醒机制做控制,而不影响- - – Java MQ的逻辑。
  • Java MQ只是借助了该Looper进行阻塞实现。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值