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

This commit is contained in:
Andreas Huber
2011-08-26 13:47:26 -07:00
committed by Android (Google) Code Review
4 changed files with 91 additions and 7 deletions

View File

@@ -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);
};

View File

@@ -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.

View File

@@ -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

View File

@@ -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;