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 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); 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); sp<ALooper> findLooper(ALooper::handler_id handlerID);
private: private:
@@ -45,6 +50,12 @@ private:
Mutex mLock; Mutex mLock;
KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers; KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
ALooper::handler_id mNextHandlerID; 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); DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster);
}; };

View File

@@ -72,6 +72,17 @@ struct AMessage : public RefBase {
void post(int64_t delayUs = 0); 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". // 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 // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
// their refcount incremented. // their refcount incremented.

View File

@@ -27,7 +27,8 @@
namespace android { namespace android {
ALooperRoster::ALooperRoster() ALooperRoster::ALooperRoster()
: mNextHandlerID(1) { : mNextHandlerID(1),
mNextReplyID(1) {
} }
ALooper::handler_id ALooperRoster::registerHandler( ALooper::handler_id ALooperRoster::registerHandler(
@@ -70,15 +71,19 @@ void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
mHandlers.removeItemsAt(index); mHandlers.removeItemsAt(index);
} }
void ALooperRoster::postMessage( status_t ALooperRoster::postMessage(
const sp<AMessage> &msg, int64_t delayUs) { const sp<AMessage> &msg, int64_t delayUs) {
Mutex::Autolock autoLock(mLock); 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()); ssize_t index = mHandlers.indexOfKey(msg->target());
if (index < 0) { if (index < 0) {
LOGW("failed to post message. Target handler not registered."); LOGW("failed to post message. Target handler not registered.");
return; return -ENOENT;
} }
const HandlerInfo &info = mHandlers.valueAt(index); const HandlerInfo &info = mHandlers.valueAt(index);
@@ -91,10 +96,12 @@ void ALooperRoster::postMessage(
msg->target()); msg->target());
mHandlers.removeItemsAt(index); mHandlers.removeItemsAt(index);
return; return -ENOENT;
} }
looper->post(msg, delayUs); looper->post(msg, delayUs);
return OK;
} }
void ALooperRoster::deliverMessage(const sp<AMessage> &msg) { void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
@@ -145,4 +152,38 @@ sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
return looper; 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 } // namespace android

View File

@@ -27,6 +27,8 @@
namespace android { namespace android {
extern ALooperRoster gLooperRoster;
AMessage::AMessage(uint32_t what, ALooper::handler_id target) AMessage::AMessage(uint32_t what, ALooper::handler_id target)
: mWhat(what), : mWhat(what),
mTarget(target), mTarget(target),
@@ -227,11 +229,30 @@ bool AMessage::findRect(
} }
void AMessage::post(int64_t delayUs) { void AMessage::post(int64_t delayUs) {
extern ALooperRoster gLooperRoster;
gLooperRoster.postMessage(this, delayUs); 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> AMessage::dup() const {
sp<AMessage> msg = new AMessage(mWhat, mTarget); sp<AMessage> msg = new AMessage(mWhat, mTarget);
msg->mNumItems = mNumItems; msg->mNumItems = mNumItems;