Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6882574 authored by Andreas Huber's avatar Andreas Huber
Browse files

Support for posting messages and synchronously waiting for a response.

Change-Id: Id6c7a08c34fd5cb6c4632f78ece9e7898b29e52c
parent 1aabd124
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -31,9 +31,14 @@ struct ALooperRoster {

    void unregisterHandler(ALooper::handler_id handlerID);

    void postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
    status_t postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
    void deliverMessage(const sp<AMessage> &msg);

    status_t postAndAwaitResponse(
            const sp<AMessage> &msg, sp<AMessage> *response);

    void postReply(uint32_t replyID, const sp<AMessage> &reply);

    sp<ALooper> findLooper(ALooper::handler_id handlerID);

private:
@@ -45,6 +50,12 @@ private:
    Mutex mLock;
    KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
    ALooper::handler_id mNextHandlerID;
    uint32_t mNextReplyID;
    Condition mRepliesCondition;

    KeyedVector<uint32_t, sp<AMessage> > mReplies;

    status_t postMessage_l(const sp<AMessage> &msg, int64_t delayUs);

    DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster);
};
+11 −0
Original line number Diff line number Diff line
@@ -72,6 +72,17 @@ struct AMessage : public RefBase {

    void post(int64_t delayUs = 0);

    // Posts the message to its target and waits for a response (or error)
    // before returning.
    status_t postAndAwaitResponse(sp<AMessage> *response);

    // If this returns true, the sender of this message is synchronously
    // awaiting a response, the "replyID" can be used to send the response
    // via "postReply" below.
    bool senderAwaitsResponse(uint32_t *replyID) const;

    void postReply(uint32_t replyID);

    // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
    // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
    // their refcount incremented.
+45 −4
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@
namespace android {

ALooperRoster::ALooperRoster()
    : mNextHandlerID(1) {
    : mNextHandlerID(1),
      mNextReplyID(1) {
}

ALooper::handler_id ALooperRoster::registerHandler(
@@ -70,15 +71,19 @@ void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
    mHandlers.removeItemsAt(index);
}

void ALooperRoster::postMessage(
status_t ALooperRoster::postMessage(
        const sp<AMessage> &msg, int64_t delayUs) {
    Mutex::Autolock autoLock(mLock);
    return postMessage_l(msg, delayUs);
}

status_t ALooperRoster::postMessage_l(
        const sp<AMessage> &msg, int64_t delayUs) {
    ssize_t index = mHandlers.indexOfKey(msg->target());

    if (index < 0) {
        LOGW("failed to post message. Target handler not registered.");
        return;
        return -ENOENT;
    }

    const HandlerInfo &info = mHandlers.valueAt(index);
@@ -91,10 +96,12 @@ void ALooperRoster::postMessage(
             msg->target());

        mHandlers.removeItemsAt(index);
        return;
        return -ENOENT;
    }

    looper->post(msg, delayUs);

    return OK;
}

void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
@@ -145,4 +152,38 @@ sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
    return looper;
}

status_t ALooperRoster::postAndAwaitResponse(
        const sp<AMessage> &msg, sp<AMessage> *response) {
    Mutex::Autolock autoLock(mLock);

    uint32_t replyID = mNextReplyID++;

    msg->setInt32("replyID", replyID);

    status_t err = postMessage_l(msg, 0 /* delayUs */);

    if (err != OK) {
        response->clear();
        return err;
    }

    ssize_t index;
    while ((index = mReplies.indexOfKey(replyID)) < 0) {
        mRepliesCondition.wait(mLock);
    }

    *response = mReplies.valueAt(index);
    mReplies.removeItemsAt(index);

    return OK;
}

void ALooperRoster::postReply(uint32_t replyID, const sp<AMessage> &reply) {
    Mutex::Autolock autoLock(mLock);

    CHECK(mReplies.indexOfKey(replyID) < 0);
    mReplies.add(replyID, reply);
    mRepliesCondition.broadcast();
}

}  // namespace android
+23 −2
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@

namespace android {

extern ALooperRoster gLooperRoster;

AMessage::AMessage(uint32_t what, ALooper::handler_id target)
    : mWhat(what),
      mTarget(target),
@@ -227,11 +229,30 @@ bool AMessage::findRect(
}

void AMessage::post(int64_t delayUs) {
    extern ALooperRoster gLooperRoster;

    gLooperRoster.postMessage(this, delayUs);
}

status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
    return gLooperRoster.postAndAwaitResponse(this, response);
}

void AMessage::postReply(uint32_t replyID) {
    gLooperRoster.postReply(replyID, this);
}

bool AMessage::senderAwaitsResponse(uint32_t *replyID) const {
    int32_t tmp;
    bool found = findInt32("replyID", &tmp);

    if (!found) {
        return false;
    }

    *replyID = static_cast<uint32_t>(tmp);

    return true;
}

sp<AMessage> AMessage::dup() const {
    sp<AMessage> msg = new AMessage(mWhat, mTarget);
    msg->mNumItems = mNumItems;