OSDN Git Service

Merge "Fix bug 4082512 IAE "pointerIndex out of range" while zooming over flashplayer...
[android-x86/frameworks-native.git] / services / surfaceflinger / MessageQueue.cpp
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdint.h>
18 #include <errno.h>
19 #include <sys/types.h>
20
21 #include <utils/threads.h>
22 #include <utils/Timers.h>
23 #include <utils/Log.h>
24 #include <binder/IPCThreadState.h>
25
26 #include "MessageQueue.h"
27
28 namespace android {
29
30 // ---------------------------------------------------------------------------
31
32 void MessageList::insert(const sp<MessageBase>& node) 
33 {
34     LIST::iterator cur(mList.begin());
35     LIST::iterator end(mList.end());
36     while (cur != end) {
37         if (*node < **cur) {
38             mList.insert(cur, node);
39             return;
40         }
41         ++cur;
42     }
43     mList.insert(++end, node);
44 }
45
46 void MessageList::remove(MessageList::LIST::iterator pos) 
47 {
48     mList.erase(pos);
49 }
50
51 // ---------------------------------------------------------------------------
52
53 MessageQueue::MessageQueue()
54     : mInvalidate(false)
55 {
56     mInvalidateMessage = new MessageBase(INVALIDATE);
57 }
58
59 MessageQueue::~MessageQueue()
60 {
61 }
62
63 sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout)
64 {
65     sp<MessageBase> result;
66
67     bool again;
68     do {
69         const nsecs_t timeoutTime = systemTime() + timeout;
70         while (true) {
71             Mutex::Autolock _l(mLock);
72             nsecs_t now = systemTime();
73             nsecs_t nextEventTime = -1;
74
75             LIST::iterator cur(mMessages.begin());
76             if (cur != mMessages.end()) {
77                 result = *cur;
78             }
79             
80             if (result != 0) {
81                 if (result->when <= now) {
82                     // there is a message to deliver
83                     mMessages.remove(cur);
84                     break;
85                 }
86                 nextEventTime = result->when;
87                 result = 0;
88             }
89
90             // see if we have an invalidate message
91             if (mInvalidate) {
92                 mInvalidate = false;
93                 mInvalidateMessage->when = now;
94                 result = mInvalidateMessage;
95                 break;
96             }
97
98             if (timeout >= 0) {
99                 if (timeoutTime < now) {
100                     // we timed-out, return a NULL message
101                     result = 0;
102                     break;
103                 }
104                 if (nextEventTime > 0) {
105                     if (nextEventTime > timeoutTime) {
106                         nextEventTime = timeoutTime;
107                     }
108                 } else {
109                     nextEventTime = timeoutTime;
110                 }
111             }
112
113             if (nextEventTime >= 0) {
114                 //LOGD("nextEventTime = %lld ms", nextEventTime);
115                 if (nextEventTime > 0) {
116                     // we're about to wait, flush the binder command buffer
117                     IPCThreadState::self()->flushCommands();
118                     const nsecs_t reltime = nextEventTime - systemTime();
119                     if (reltime > 0) {
120                         mCondition.waitRelative(mLock, reltime);
121                     }
122                 }
123             } else {
124                 //LOGD("going to wait");
125                 // we're about to wait, flush the binder command buffer
126                 IPCThreadState::self()->flushCommands();
127                 mCondition.wait(mLock);
128             }
129         } 
130         // here we're not holding the lock anymore
131
132         if (result == 0)
133             break;
134
135         again = result->handler();
136         if (again) {
137             // the message has been processed. release our reference to it
138             // without holding the lock.
139             result->notify();
140             result = 0;
141         }
142         
143     } while (again);
144
145     return result;
146 }
147
148 status_t MessageQueue::postMessage(
149         const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
150 {
151     return queueMessage(message, relTime, flags);
152 }
153
154 status_t MessageQueue::invalidate() {
155     Mutex::Autolock _l(mLock);
156     mInvalidate = true;
157     mCondition.signal();
158     return NO_ERROR;
159 }
160
161 status_t MessageQueue::queueMessage(
162         const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
163 {
164     Mutex::Autolock _l(mLock);
165     message->when = systemTime() + relTime;
166     mMessages.insert(message);
167     
168     //LOGD("MessageQueue::queueMessage time = %lld ms", message->when);
169     //dumpLocked(message);
170
171     mCondition.signal();
172     return NO_ERROR;
173 }
174
175 void MessageQueue::dump(const sp<MessageBase>& message)
176 {
177     Mutex::Autolock _l(mLock);
178     dumpLocked(message);
179 }
180
181 void MessageQueue::dumpLocked(const sp<MessageBase>& message)
182 {
183     LIST::const_iterator cur(mMessages.begin());
184     LIST::const_iterator end(mMessages.end());
185     int c = 0;
186     while (cur != end) {
187         const char tick = (*cur == message) ? '>' : ' ';
188         LOGD("%c %d: msg{.what=%08x, when=%lld}",
189                 tick, c, (*cur)->what, (*cur)->when);
190         ++cur;
191         c++;
192     }
193 }
194
195 // ---------------------------------------------------------------------------
196
197 }; // namespace android