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 #ifndef AUDIO_WATCHDOG_H 23 #define AUDIO_WATCHDOG_H 24 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 { AudioWatchdogDumpAudioWatchdogDump33 AudioWatchdogDump() : mUnderruns(0), mLogs(0), mMostRecent(0) { } ~AudioWatchdogDumpAudioWatchdogDump34 /*virtual*/ ~AudioWatchdogDump() { } 35 uint32_t mUnderruns; // total number of underruns 36 uint32_t mLogs; // total number of log messages 37 time_t mMostRecent; // time of most recent log 38 void dump(int fd); // should only be called on a stable copy, not the original 39 }; 40 41 class AudioWatchdog : public Thread { 42 43 public: Thread(false)44 explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), mPaused(false), 45 mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2), 46 // mOldTs 47 // mLogTs initialized below 48 mOldTsValid(false), mUnderruns(0), mLogs(0), mDump(&mDummyDump) 49 { 50 #define MIN_TIME_BETWEEN_LOGS_SEC 60 51 // force an immediate log on first underrun 52 mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC; 53 mLogTs.tv_nsec = 0; 54 } ~AudioWatchdog()55 virtual ~AudioWatchdog() { } 56 57 // Do not call Thread::requestExitAndWait() without first calling requestExit(). 58 // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough. 59 virtual void requestExit(); 60 61 // FIXME merge API and implementation with AudioTrackThread 62 void pause(); // suspend thread from execution at next loop boundary 63 void resume(); // allow thread to execute, if not requested to exit 64 65 // Where to store the dump, or NULL to not update 66 void setDump(AudioWatchdogDump* dump); 67 68 private: 69 virtual bool threadLoop(); 70 71 Mutex mMyLock; // Thread::mLock is private 72 Condition mMyCond; // Thread::mThreadExitedCondition is private 73 bool mPaused; // whether thread is currently paused 74 75 uint32_t mPeriodNs; // nominal period 76 uint32_t mMaxCycleNs; // maximum allowed time of one cycle before declaring underrun 77 struct timespec mOldTs; // monotonic time when threadLoop last ran 78 struct timespec mLogTs; // time since last log 79 bool mOldTsValid; // whether mOldTs is valid 80 uint32_t mUnderruns; // total number of underruns 81 uint32_t mLogs; // total number of logs 82 AudioWatchdogDump* mDump; // where to store the dump, always non-NULL 83 AudioWatchdogDump mDummyDump; // default area for dump in case setDump() is not called 84 }; 85 86 } // namespace android 87 88 #endif // AUDIO_WATCHDOG_H 89