Merge "Support for posting messages and synchronously waiting for a response."
This commit is contained in:
committed by
Android (Google) Code Review
commit
539340fe2c
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user