13528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent/*
23528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * Copyright (C) 2018 The Android Open Source Project
33528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent *
43528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
53528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * you may not use this file except in compliance with the License.
63528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * You may obtain a copy of the License at
73528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent *
83528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
93528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent *
103528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * Unless required by applicable law or agreed to in writing, software
113528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
123528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * See the License for the specific language governing permissions and
143528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent * limitations under the License.
153528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent */
163528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
173528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
183528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent#include <media/TimeCheck.h>
193528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
203528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurentnamespace android {
213528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
223528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent/* static */
233528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurentsp<TimeCheck::TimeCheckThread> TimeCheck::getTimeCheckThread()
243528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent{
253528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    static sp<TimeCheck::TimeCheckThread> sTimeCheckThread = new TimeCheck::TimeCheckThread();
263528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    return sTimeCheckThread;
273528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent}
283528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
293528c9330f481f236f16753cb0846c7d6ddcc7eeEric LaurentTimeCheck::TimeCheck(const char *tag, uint32_t timeoutMs)
303528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    : mEndTimeNs(getTimeCheckThread()->startMonitoring(tag, timeoutMs))
313528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent{
323528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent}
333528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
343528c9330f481f236f16753cb0846c7d6ddcc7eeEric LaurentTimeCheck::~TimeCheck() {
353528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    getTimeCheckThread()->stopMonitoring(mEndTimeNs);
363528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent}
373528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
383528c9330f481f236f16753cb0846c7d6ddcc7eeEric LaurentTimeCheck::TimeCheckThread::~TimeCheckThread()
393528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent{
403528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    AutoMutex _l(mMutex);
413528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    requestExit();
423528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    mMonitorRequests.clear();
433528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    mCond.signal();
443528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent}
453528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
463528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurentnsecs_t TimeCheck::TimeCheckThread::startMonitoring(const char *tag, uint32_t timeoutMs) {
473528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    Mutex::Autolock _l(mMutex);
483528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    nsecs_t endTimeNs = systemTime() + milliseconds(timeoutMs);
493528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    for (; mMonitorRequests.indexOfKey(endTimeNs) >= 0; ++endTimeNs);
503528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    mMonitorRequests.add(endTimeNs, tag);
513528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    mCond.signal();
523528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    return endTimeNs;
533528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent}
543528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
553528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurentvoid TimeCheck::TimeCheckThread::stopMonitoring(nsecs_t endTimeNs) {
563528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    Mutex::Autolock _l(mMutex);
573528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    mMonitorRequests.removeItem(endTimeNs);
583528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    mCond.signal();
593528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent}
603528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
613528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurentbool TimeCheck::TimeCheckThread::threadLoop()
623528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent{
633528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    status_t status = TIMED_OUT;
643528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    const char *tag;
653528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    {
663528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        AutoMutex _l(mMutex);
673528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
683528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        if (exitPending()) {
693528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent            return false;
703528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        }
713528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
723528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        nsecs_t endTimeNs = INT64_MAX;
733528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        // KeyedVector mMonitorRequests is ordered so take first entry as next timeout
743528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        if (mMonitorRequests.size() != 0) {
753528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent            endTimeNs = mMonitorRequests.keyAt(0);
763528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent            tag = mMonitorRequests.valueAt(0);
773528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        }
783528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
793528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        const nsecs_t waitTimeNs = endTimeNs - systemTime();
803528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        if (waitTimeNs > 0) {
813528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent            status = mCond.waitRelative(mMutex, waitTimeNs);
823528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent        }
833528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    }
843528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "TimeCheck timeout for %s", tag);
853528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent    return true;
863528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent}
873528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent
883528c9330f481f236f16753cb0846c7d6ddcc7eeEric Laurent}; // namespace android
89