1 /* 2 * Copyright (C) 2012 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 // The watchdog thread runs periodically. It has two functions: 18 // (a) verify that adequate CPU time is available, and log 19 // as soon as possible when there appears to be a CPU shortage 20 // (b) monitor the other threads [not yet implemented] 21 22 #pragma once 23 24 #include <mutex> 25 #include <time.h> 26 #include <utils/Thread.h> 27 28 namespace android { 29 30 // Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys. 31 // The usual caveats about atomicity of information apply. 32 struct AudioWatchdogDump { 33 uint32_t mUnderruns = 0; // total number of underruns 34 uint32_t mLogs = 0; // total number of log messages 35 time_t mMostRecent = 0; // time of most recent log 36 void dump(int fd); // should only be called on a stable copy, not the original 37 }; 38 39 class AudioWatchdog : public Thread { 40 41 public: Thread(false)42 explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), 43 mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2) 44 { 45 // force an immediate log on first underrun 46 mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC; 47 mLogTs.tv_nsec = 0; 48 } 49 50 // Do not call Thread::requestExitAndWait() without first calling requestExit(). 51 // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough. 52 void requestExit() override; 53 54 // FIXME merge API and implementation with AudioTrackThread 55 void pause(); // suspend thread from execution at next loop boundary 56 void resume(); // allow thread to execute, if not requested to exit 57 58 // Where to store the dump, or NULL to not update 59 void setDump(AudioWatchdogDump* dump); 60 61 private: 62 bool threadLoop() override; 63 64 static constexpr int32_t MIN_TIME_BETWEEN_LOGS_SEC = 60; 65 const uint32_t mPeriodNs; // nominal period 66 const uint32_t mMaxCycleNs; // maximum allowed time of one cycle before declaring underrun 67 68 mutable std::mutex mLock; // Thread::mLock is private 69 std::condition_variable mCond; // Thread::mThreadExitedCondition is private 70 bool mPaused GUARDED_BY(mLock) = false; // whether thread is currently paused 71 bool mOldTsValid GUARDED_BY(mLock) = false; // whether mOldTs is valid 72 struct timespec mOldTs GUARDED_BY(mLock); // monotonic time when threadLoop last ran 73 struct timespec mLogTs GUARDED_BY(mLock); // time since last log (ctor init). 74 uint32_t mUnderruns GUARDED_BY(mLock) = 0; // total number of underruns 75 uint32_t mLogs GUARDED_BY(mLock) = 0; // total number of logs 76 77 // where to store the dump, always non-NULL 78 AudioWatchdogDump* mDump GUARDED_BY(mLock) = &mDummyDump; 79 AudioWatchdogDump mDummyDump; // default area for dump in case setDump() is not called 80 }; 81 82 } // namespace android 83 84