1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "ALooper"
19*ec779b8eSAndroid Build Coastguard Worker
20*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker #include <sys/time.h>
25*ec779b8eSAndroid Build Coastguard Worker
26*ec779b8eSAndroid Build Coastguard Worker #include "ALooper.h"
27*ec779b8eSAndroid Build Coastguard Worker
28*ec779b8eSAndroid Build Coastguard Worker #include "AHandler.h"
29*ec779b8eSAndroid Build Coastguard Worker #include "ALooperRoster.h"
30*ec779b8eSAndroid Build Coastguard Worker #include "AMessage.h"
31*ec779b8eSAndroid Build Coastguard Worker
32*ec779b8eSAndroid Build Coastguard Worker namespace android {
33*ec779b8eSAndroid Build Coastguard Worker
34*ec779b8eSAndroid Build Coastguard Worker ALooperRoster gLooperRoster;
35*ec779b8eSAndroid Build Coastguard Worker
36*ec779b8eSAndroid Build Coastguard Worker struct ALooper::LooperThread : public Thread {
LooperThreadandroid::ALooper::LooperThread37*ec779b8eSAndroid Build Coastguard Worker LooperThread(ALooper *looper, bool canCallJava)
38*ec779b8eSAndroid Build Coastguard Worker : Thread(canCallJava),
39*ec779b8eSAndroid Build Coastguard Worker mLooper(looper),
40*ec779b8eSAndroid Build Coastguard Worker mThreadId(NULL) {
41*ec779b8eSAndroid Build Coastguard Worker }
42*ec779b8eSAndroid Build Coastguard Worker
readyToRunandroid::ALooper::LooperThread43*ec779b8eSAndroid Build Coastguard Worker virtual status_t readyToRun() {
44*ec779b8eSAndroid Build Coastguard Worker mThreadId = androidGetThreadId();
45*ec779b8eSAndroid Build Coastguard Worker
46*ec779b8eSAndroid Build Coastguard Worker return Thread::readyToRun();
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker
threadLoopandroid::ALooper::LooperThread49*ec779b8eSAndroid Build Coastguard Worker virtual bool threadLoop() {
50*ec779b8eSAndroid Build Coastguard Worker return mLooper->loop();
51*ec779b8eSAndroid Build Coastguard Worker }
52*ec779b8eSAndroid Build Coastguard Worker
isCurrentThreadandroid::ALooper::LooperThread53*ec779b8eSAndroid Build Coastguard Worker bool isCurrentThread() const {
54*ec779b8eSAndroid Build Coastguard Worker return mThreadId == androidGetThreadId();
55*ec779b8eSAndroid Build Coastguard Worker }
56*ec779b8eSAndroid Build Coastguard Worker
57*ec779b8eSAndroid Build Coastguard Worker protected:
~LooperThreadandroid::ALooper::LooperThread58*ec779b8eSAndroid Build Coastguard Worker virtual ~LooperThread() {}
59*ec779b8eSAndroid Build Coastguard Worker
60*ec779b8eSAndroid Build Coastguard Worker private:
61*ec779b8eSAndroid Build Coastguard Worker ALooper *mLooper;
62*ec779b8eSAndroid Build Coastguard Worker android_thread_id_t mThreadId;
63*ec779b8eSAndroid Build Coastguard Worker
64*ec779b8eSAndroid Build Coastguard Worker DISALLOW_EVIL_CONSTRUCTORS(LooperThread);
65*ec779b8eSAndroid Build Coastguard Worker };
66*ec779b8eSAndroid Build Coastguard Worker
67*ec779b8eSAndroid Build Coastguard Worker // static
GetNowUs()68*ec779b8eSAndroid Build Coastguard Worker int64_t ALooper::GetNowUs() {
69*ec779b8eSAndroid Build Coastguard Worker return systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
70*ec779b8eSAndroid Build Coastguard Worker }
71*ec779b8eSAndroid Build Coastguard Worker
getNowUs()72*ec779b8eSAndroid Build Coastguard Worker int64_t ALooper::getNowUs() {
73*ec779b8eSAndroid Build Coastguard Worker return GetNowUs();
74*ec779b8eSAndroid Build Coastguard Worker }
75*ec779b8eSAndroid Build Coastguard Worker
ALooper()76*ec779b8eSAndroid Build Coastguard Worker ALooper::ALooper()
77*ec779b8eSAndroid Build Coastguard Worker : mRunningLocally(false) {
78*ec779b8eSAndroid Build Coastguard Worker // clean up stale AHandlers. Doing it here instead of in the destructor avoids
79*ec779b8eSAndroid Build Coastguard Worker // the side effect of objects being deleted from the unregister function recursively.
80*ec779b8eSAndroid Build Coastguard Worker gLooperRoster.unregisterStaleHandlers();
81*ec779b8eSAndroid Build Coastguard Worker }
82*ec779b8eSAndroid Build Coastguard Worker
~ALooper()83*ec779b8eSAndroid Build Coastguard Worker ALooper::~ALooper() {
84*ec779b8eSAndroid Build Coastguard Worker stop();
85*ec779b8eSAndroid Build Coastguard Worker // stale AHandlers are now cleaned up in the constructor of the next ALooper to come along
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker
setName(const char * name)88*ec779b8eSAndroid Build Coastguard Worker void ALooper::setName(const char *name) {
89*ec779b8eSAndroid Build Coastguard Worker mName = name;
90*ec779b8eSAndroid Build Coastguard Worker }
91*ec779b8eSAndroid Build Coastguard Worker
registerHandler(const sp<AHandler> & handler)92*ec779b8eSAndroid Build Coastguard Worker ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {
93*ec779b8eSAndroid Build Coastguard Worker return gLooperRoster.registerHandler(this, handler);
94*ec779b8eSAndroid Build Coastguard Worker }
95*ec779b8eSAndroid Build Coastguard Worker
unregisterHandler(handler_id handlerID)96*ec779b8eSAndroid Build Coastguard Worker void ALooper::unregisterHandler(handler_id handlerID) {
97*ec779b8eSAndroid Build Coastguard Worker gLooperRoster.unregisterHandler(handlerID);
98*ec779b8eSAndroid Build Coastguard Worker }
99*ec779b8eSAndroid Build Coastguard Worker
start(bool runOnCallingThread,bool canCallJava,int32_t priority)100*ec779b8eSAndroid Build Coastguard Worker status_t ALooper::start(
101*ec779b8eSAndroid Build Coastguard Worker bool runOnCallingThread, bool canCallJava, int32_t priority) {
102*ec779b8eSAndroid Build Coastguard Worker if (runOnCallingThread) {
103*ec779b8eSAndroid Build Coastguard Worker {
104*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
105*ec779b8eSAndroid Build Coastguard Worker
106*ec779b8eSAndroid Build Coastguard Worker if (mThread != NULL || mRunningLocally) {
107*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
108*ec779b8eSAndroid Build Coastguard Worker }
109*ec779b8eSAndroid Build Coastguard Worker
110*ec779b8eSAndroid Build Coastguard Worker mRunningLocally = true;
111*ec779b8eSAndroid Build Coastguard Worker }
112*ec779b8eSAndroid Build Coastguard Worker
113*ec779b8eSAndroid Build Coastguard Worker do {
114*ec779b8eSAndroid Build Coastguard Worker } while (loop());
115*ec779b8eSAndroid Build Coastguard Worker
116*ec779b8eSAndroid Build Coastguard Worker return OK;
117*ec779b8eSAndroid Build Coastguard Worker }
118*ec779b8eSAndroid Build Coastguard Worker
119*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
120*ec779b8eSAndroid Build Coastguard Worker
121*ec779b8eSAndroid Build Coastguard Worker if (mThread != NULL || mRunningLocally) {
122*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker
125*ec779b8eSAndroid Build Coastguard Worker mThread = new LooperThread(this, canCallJava);
126*ec779b8eSAndroid Build Coastguard Worker
127*ec779b8eSAndroid Build Coastguard Worker status_t err = mThread->run(
128*ec779b8eSAndroid Build Coastguard Worker mName.empty() ? "ALooper" : mName.c_str(), priority);
129*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
130*ec779b8eSAndroid Build Coastguard Worker mThread.clear();
131*ec779b8eSAndroid Build Coastguard Worker }
132*ec779b8eSAndroid Build Coastguard Worker
133*ec779b8eSAndroid Build Coastguard Worker return err;
134*ec779b8eSAndroid Build Coastguard Worker }
135*ec779b8eSAndroid Build Coastguard Worker
stop()136*ec779b8eSAndroid Build Coastguard Worker status_t ALooper::stop() {
137*ec779b8eSAndroid Build Coastguard Worker sp<LooperThread> thread;
138*ec779b8eSAndroid Build Coastguard Worker bool runningLocally;
139*ec779b8eSAndroid Build Coastguard Worker
140*ec779b8eSAndroid Build Coastguard Worker {
141*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
142*ec779b8eSAndroid Build Coastguard Worker
143*ec779b8eSAndroid Build Coastguard Worker thread = mThread;
144*ec779b8eSAndroid Build Coastguard Worker runningLocally = mRunningLocally;
145*ec779b8eSAndroid Build Coastguard Worker mThread.clear();
146*ec779b8eSAndroid Build Coastguard Worker mRunningLocally = false;
147*ec779b8eSAndroid Build Coastguard Worker }
148*ec779b8eSAndroid Build Coastguard Worker
149*ec779b8eSAndroid Build Coastguard Worker if (thread == NULL && !runningLocally) {
150*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
151*ec779b8eSAndroid Build Coastguard Worker }
152*ec779b8eSAndroid Build Coastguard Worker
153*ec779b8eSAndroid Build Coastguard Worker if (thread != NULL) {
154*ec779b8eSAndroid Build Coastguard Worker thread->requestExit();
155*ec779b8eSAndroid Build Coastguard Worker }
156*ec779b8eSAndroid Build Coastguard Worker
157*ec779b8eSAndroid Build Coastguard Worker mQueueChangedCondition.signal();
158*ec779b8eSAndroid Build Coastguard Worker {
159*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mRepliesLock);
160*ec779b8eSAndroid Build Coastguard Worker mRepliesCondition.broadcast();
161*ec779b8eSAndroid Build Coastguard Worker }
162*ec779b8eSAndroid Build Coastguard Worker
163*ec779b8eSAndroid Build Coastguard Worker if (!runningLocally && !thread->isCurrentThread()) {
164*ec779b8eSAndroid Build Coastguard Worker // If not running locally and this thread _is_ the looper thread,
165*ec779b8eSAndroid Build Coastguard Worker // the loop() function will return and never be called again.
166*ec779b8eSAndroid Build Coastguard Worker thread->requestExitAndWait();
167*ec779b8eSAndroid Build Coastguard Worker }
168*ec779b8eSAndroid Build Coastguard Worker
169*ec779b8eSAndroid Build Coastguard Worker return OK;
170*ec779b8eSAndroid Build Coastguard Worker }
171*ec779b8eSAndroid Build Coastguard Worker
post(const sp<AMessage> & msg,int64_t delayUs)172*ec779b8eSAndroid Build Coastguard Worker void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {
173*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
174*ec779b8eSAndroid Build Coastguard Worker
175*ec779b8eSAndroid Build Coastguard Worker int64_t whenUs;
176*ec779b8eSAndroid Build Coastguard Worker if (delayUs > 0) {
177*ec779b8eSAndroid Build Coastguard Worker int64_t nowUs = getNowUs();
178*ec779b8eSAndroid Build Coastguard Worker whenUs = (delayUs > INT64_MAX - nowUs ? INT64_MAX : nowUs + delayUs);
179*ec779b8eSAndroid Build Coastguard Worker
180*ec779b8eSAndroid Build Coastguard Worker } else {
181*ec779b8eSAndroid Build Coastguard Worker whenUs = getNowUs();
182*ec779b8eSAndroid Build Coastguard Worker }
183*ec779b8eSAndroid Build Coastguard Worker
184*ec779b8eSAndroid Build Coastguard Worker List<Event>::iterator it = mEventQueue.begin();
185*ec779b8eSAndroid Build Coastguard Worker while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) {
186*ec779b8eSAndroid Build Coastguard Worker ++it;
187*ec779b8eSAndroid Build Coastguard Worker }
188*ec779b8eSAndroid Build Coastguard Worker
189*ec779b8eSAndroid Build Coastguard Worker Event event;
190*ec779b8eSAndroid Build Coastguard Worker event.mWhenUs = whenUs;
191*ec779b8eSAndroid Build Coastguard Worker event.mMessage = msg;
192*ec779b8eSAndroid Build Coastguard Worker event.mToken = nullptr;
193*ec779b8eSAndroid Build Coastguard Worker
194*ec779b8eSAndroid Build Coastguard Worker if (it == mEventQueue.begin()) {
195*ec779b8eSAndroid Build Coastguard Worker mQueueChangedCondition.signal();
196*ec779b8eSAndroid Build Coastguard Worker }
197*ec779b8eSAndroid Build Coastguard Worker
198*ec779b8eSAndroid Build Coastguard Worker mEventQueue.insert(it, event);
199*ec779b8eSAndroid Build Coastguard Worker }
200*ec779b8eSAndroid Build Coastguard Worker
postUnique(const sp<AMessage> & msg,const sp<RefBase> & token,int64_t delayUs)201*ec779b8eSAndroid Build Coastguard Worker status_t ALooper::postUnique(const sp<AMessage> &msg, const sp<RefBase> &token, int64_t delayUs) {
202*ec779b8eSAndroid Build Coastguard Worker if (token == nullptr) {
203*ec779b8eSAndroid Build Coastguard Worker return -EINVAL;
204*ec779b8eSAndroid Build Coastguard Worker }
205*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
206*ec779b8eSAndroid Build Coastguard Worker
207*ec779b8eSAndroid Build Coastguard Worker int64_t whenUs;
208*ec779b8eSAndroid Build Coastguard Worker if (delayUs > 0) {
209*ec779b8eSAndroid Build Coastguard Worker int64_t nowUs = getNowUs();
210*ec779b8eSAndroid Build Coastguard Worker whenUs = (delayUs > INT64_MAX - nowUs ? INT64_MAX : nowUs + delayUs);
211*ec779b8eSAndroid Build Coastguard Worker } else {
212*ec779b8eSAndroid Build Coastguard Worker whenUs = getNowUs();
213*ec779b8eSAndroid Build Coastguard Worker }
214*ec779b8eSAndroid Build Coastguard Worker
215*ec779b8eSAndroid Build Coastguard Worker // We only need to wake the loop up if we're rescheduling to the earliest event in the queue.
216*ec779b8eSAndroid Build Coastguard Worker // This needs to be checked now, before we reschedule the message, in case this message is
217*ec779b8eSAndroid Build Coastguard Worker // already at the beginning of the queue.
218*ec779b8eSAndroid Build Coastguard Worker bool shouldAwakeLoop = mEventQueue.empty() || whenUs < mEventQueue.begin()->mWhenUs;
219*ec779b8eSAndroid Build Coastguard Worker
220*ec779b8eSAndroid Build Coastguard Worker // Erase any previously-posted event with this token.
221*ec779b8eSAndroid Build Coastguard Worker for (auto i = mEventQueue.begin(); i != mEventQueue.end();) {
222*ec779b8eSAndroid Build Coastguard Worker if (i->mToken == token) {
223*ec779b8eSAndroid Build Coastguard Worker i = mEventQueue.erase(i);
224*ec779b8eSAndroid Build Coastguard Worker } else {
225*ec779b8eSAndroid Build Coastguard Worker ++i;
226*ec779b8eSAndroid Build Coastguard Worker }
227*ec779b8eSAndroid Build Coastguard Worker }
228*ec779b8eSAndroid Build Coastguard Worker
229*ec779b8eSAndroid Build Coastguard Worker // Find the insertion point for the rescheduled message.
230*ec779b8eSAndroid Build Coastguard Worker List<Event>::iterator i = mEventQueue.begin();
231*ec779b8eSAndroid Build Coastguard Worker while (i != mEventQueue.end() && i->mWhenUs <= whenUs) {
232*ec779b8eSAndroid Build Coastguard Worker ++i;
233*ec779b8eSAndroid Build Coastguard Worker }
234*ec779b8eSAndroid Build Coastguard Worker
235*ec779b8eSAndroid Build Coastguard Worker Event event;
236*ec779b8eSAndroid Build Coastguard Worker event.mWhenUs = whenUs;
237*ec779b8eSAndroid Build Coastguard Worker event.mMessage = msg;
238*ec779b8eSAndroid Build Coastguard Worker event.mToken = token;
239*ec779b8eSAndroid Build Coastguard Worker mEventQueue.insert(i, event);
240*ec779b8eSAndroid Build Coastguard Worker
241*ec779b8eSAndroid Build Coastguard Worker // If we rescheduled the event to be earlier than the first event, then we need to wake up the
242*ec779b8eSAndroid Build Coastguard Worker // looper earlier than it was previously scheduled to be woken up. Otherwise, it can sleep until
243*ec779b8eSAndroid Build Coastguard Worker // the previous wake-up time and then go to sleep again if needed.
244*ec779b8eSAndroid Build Coastguard Worker if (shouldAwakeLoop){
245*ec779b8eSAndroid Build Coastguard Worker mQueueChangedCondition.signal();
246*ec779b8eSAndroid Build Coastguard Worker }
247*ec779b8eSAndroid Build Coastguard Worker return OK;
248*ec779b8eSAndroid Build Coastguard Worker }
249*ec779b8eSAndroid Build Coastguard Worker
loop()250*ec779b8eSAndroid Build Coastguard Worker bool ALooper::loop() {
251*ec779b8eSAndroid Build Coastguard Worker
252*ec779b8eSAndroid Build Coastguard Worker Event event;
253*ec779b8eSAndroid Build Coastguard Worker
254*ec779b8eSAndroid Build Coastguard Worker {
255*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
256*ec779b8eSAndroid Build Coastguard Worker if (mThread == NULL && !mRunningLocally) {
257*ec779b8eSAndroid Build Coastguard Worker return false;
258*ec779b8eSAndroid Build Coastguard Worker }
259*ec779b8eSAndroid Build Coastguard Worker if (mEventQueue.empty()) {
260*ec779b8eSAndroid Build Coastguard Worker mQueueChangedCondition.wait(mLock);
261*ec779b8eSAndroid Build Coastguard Worker return true;
262*ec779b8eSAndroid Build Coastguard Worker }
263*ec779b8eSAndroid Build Coastguard Worker int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
264*ec779b8eSAndroid Build Coastguard Worker int64_t nowUs = getNowUs();
265*ec779b8eSAndroid Build Coastguard Worker
266*ec779b8eSAndroid Build Coastguard Worker if (whenUs > nowUs) {
267*ec779b8eSAndroid Build Coastguard Worker int64_t delayUs = whenUs - nowUs;
268*ec779b8eSAndroid Build Coastguard Worker if (delayUs > INT64_MAX / 1000) {
269*ec779b8eSAndroid Build Coastguard Worker delayUs = INT64_MAX / 1000;
270*ec779b8eSAndroid Build Coastguard Worker }
271*ec779b8eSAndroid Build Coastguard Worker mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);
272*ec779b8eSAndroid Build Coastguard Worker
273*ec779b8eSAndroid Build Coastguard Worker return true;
274*ec779b8eSAndroid Build Coastguard Worker }
275*ec779b8eSAndroid Build Coastguard Worker
276*ec779b8eSAndroid Build Coastguard Worker event = *mEventQueue.begin();
277*ec779b8eSAndroid Build Coastguard Worker mEventQueue.erase(mEventQueue.begin());
278*ec779b8eSAndroid Build Coastguard Worker }
279*ec779b8eSAndroid Build Coastguard Worker
280*ec779b8eSAndroid Build Coastguard Worker event.mMessage->deliver();
281*ec779b8eSAndroid Build Coastguard Worker
282*ec779b8eSAndroid Build Coastguard Worker // NOTE: It's important to note that at this point our "ALooper" object
283*ec779b8eSAndroid Build Coastguard Worker // may no longer exist (its final reference may have gone away while
284*ec779b8eSAndroid Build Coastguard Worker // delivering the message). We have made sure, however, that loop()
285*ec779b8eSAndroid Build Coastguard Worker // won't be called again.
286*ec779b8eSAndroid Build Coastguard Worker
287*ec779b8eSAndroid Build Coastguard Worker return true;
288*ec779b8eSAndroid Build Coastguard Worker }
289*ec779b8eSAndroid Build Coastguard Worker
290*ec779b8eSAndroid Build Coastguard Worker // to be called by AMessage::postAndAwaitResponse only
createReplyToken()291*ec779b8eSAndroid Build Coastguard Worker sp<AReplyToken> ALooper::createReplyToken() {
292*ec779b8eSAndroid Build Coastguard Worker return new AReplyToken(this);
293*ec779b8eSAndroid Build Coastguard Worker }
294*ec779b8eSAndroid Build Coastguard Worker
295*ec779b8eSAndroid Build Coastguard Worker // to be called by AMessage::postAndAwaitResponse only
awaitResponse(const sp<AReplyToken> & replyToken,sp<AMessage> * response)296*ec779b8eSAndroid Build Coastguard Worker status_t ALooper::awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response) {
297*ec779b8eSAndroid Build Coastguard Worker // return status in case we want to handle an interrupted wait
298*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mRepliesLock);
299*ec779b8eSAndroid Build Coastguard Worker CHECK(replyToken != NULL);
300*ec779b8eSAndroid Build Coastguard Worker while (!replyToken->retrieveReply(response)) {
301*ec779b8eSAndroid Build Coastguard Worker {
302*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
303*ec779b8eSAndroid Build Coastguard Worker if (mThread == NULL) {
304*ec779b8eSAndroid Build Coastguard Worker return -ENOENT;
305*ec779b8eSAndroid Build Coastguard Worker }
306*ec779b8eSAndroid Build Coastguard Worker }
307*ec779b8eSAndroid Build Coastguard Worker mRepliesCondition.wait(mRepliesLock);
308*ec779b8eSAndroid Build Coastguard Worker }
309*ec779b8eSAndroid Build Coastguard Worker return OK;
310*ec779b8eSAndroid Build Coastguard Worker }
311*ec779b8eSAndroid Build Coastguard Worker
postReply(const sp<AReplyToken> & replyToken,const sp<AMessage> & reply)312*ec779b8eSAndroid Build Coastguard Worker status_t ALooper::postReply(const sp<AReplyToken> &replyToken, const sp<AMessage> &reply) {
313*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mRepliesLock);
314*ec779b8eSAndroid Build Coastguard Worker status_t err = replyToken->setReply(reply);
315*ec779b8eSAndroid Build Coastguard Worker if (err == OK) {
316*ec779b8eSAndroid Build Coastguard Worker mRepliesCondition.broadcast();
317*ec779b8eSAndroid Build Coastguard Worker }
318*ec779b8eSAndroid Build Coastguard Worker return err;
319*ec779b8eSAndroid Build Coastguard Worker }
320*ec779b8eSAndroid Build Coastguard Worker
321*ec779b8eSAndroid Build Coastguard Worker } // namespace android
322