blob: dab5d4f336b8571ecaa2e86ea750017459a715ee [file] [log] [blame]
Eric Laurent3528c932018-02-23 17:17:22 -08001/*
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
20namespace android {
21
22/* static */
23sp<TimeCheck::TimeCheckThread> TimeCheck::getTimeCheckThread()
24{
25 static sp<TimeCheck::TimeCheckThread> sTimeCheckThread = new TimeCheck::TimeCheckThread();
26 return sTimeCheckThread;
27}
28
29TimeCheck::TimeCheck(const char *tag, uint32_t timeoutMs)
30 : mEndTimeNs(getTimeCheckThread()->startMonitoring(tag, timeoutMs))
31{
32}
33
34TimeCheck::~TimeCheck() {
35 getTimeCheckThread()->stopMonitoring(mEndTimeNs);
36}
37
38TimeCheck::TimeCheckThread::~TimeCheckThread()
39{
40 AutoMutex _l(mMutex);
41 requestExit();
42 mMonitorRequests.clear();
43 mCond.signal();
44}
45
46nsecs_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
55void TimeCheck::TimeCheckThread::stopMonitoring(nsecs_t endTimeNs) {
56 Mutex::Autolock _l(mMutex);
57 mMonitorRequests.removeItem(endTimeNs);
58 mCond.signal();
59}
60
61bool 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