1 /* 2 * Copyright (C) 2018 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 18 #include <media/TimeCheck.h> 19 20 namespace android { 21 22 /* static */ 23 sp<TimeCheck::TimeCheckThread> TimeCheck::getTimeCheckThread() 24 { 25 static sp<TimeCheck::TimeCheckThread> sTimeCheckThread = new TimeCheck::TimeCheckThread(); 26 return sTimeCheckThread; 27 } 28 29 TimeCheck::TimeCheck(const char *tag, uint32_t timeoutMs) 30 : mEndTimeNs(getTimeCheckThread()->startMonitoring(tag, timeoutMs)) 31 { 32 } 33 34 TimeCheck::~TimeCheck() { 35 getTimeCheckThread()->stopMonitoring(mEndTimeNs); 36 } 37 38 TimeCheck::TimeCheckThread::~TimeCheckThread() 39 { 40 AutoMutex _l(mMutex); 41 requestExit(); 42 mMonitorRequests.clear(); 43 mCond.signal(); 44 } 45 46 nsecs_t TimeCheck::TimeCheckThread::startMonitoring(const char *tag, uint32_t timeoutMs) { 47 Mutex::Autolock _l(mMutex); 48 nsecs_t endTimeNs = systemTime() + milliseconds(timeoutMs); 49 for (; mMonitorRequests.indexOfKey(endTimeNs) >= 0; ++endTimeNs); 50 mMonitorRequests.add(endTimeNs, tag); 51 mCond.signal(); 52 return endTimeNs; 53 } 54 55 void TimeCheck::TimeCheckThread::stopMonitoring(nsecs_t endTimeNs) { 56 Mutex::Autolock _l(mMutex); 57 mMonitorRequests.removeItem(endTimeNs); 58 mCond.signal(); 59 } 60 61 bool TimeCheck::TimeCheckThread::threadLoop() 62 { 63 status_t status = TIMED_OUT; 64 const char *tag; 65 { 66 AutoMutex _l(mMutex); 67 68 if (exitPending()) { 69 return false; 70 } 71 72 nsecs_t endTimeNs = INT64_MAX; 73 // KeyedVector mMonitorRequests is ordered so take first entry as next timeout 74 if (mMonitorRequests.size() != 0) { 75 endTimeNs = mMonitorRequests.keyAt(0); 76 tag = mMonitorRequests.valueAt(0); 77 } 78 79 const nsecs_t waitTimeNs = endTimeNs - systemTime(); 80 if (waitTimeNs > 0) { 81 status = mCond.waitRelative(mMutex, waitTimeNs); 82 } 83 } 84 LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "TimeCheck timeout for %s", tag); 85 return true; 86 } 87 88 }; // namespace android 89