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 198