xref: /aosp_15_r20/frameworks/av/media/module/foundation/ALooper.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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