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

Commit 539340fe authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Support for posting messages and synchronously waiting for a response."

parents dae908a3 e6882574
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;