blob: 4657530e741235f3d9d0555e26cb362a93640277 [file] [log] [blame]
Glenn Kastenc15d6652012-05-30 14:52:57 -07001/*
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
28namespace android {
29
30// Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys.
31// The usual caveats about atomicity of information apply.
32struct AudioWatchdogDump {
33 AudioWatchdogDump() : mUnderruns(0), mLogs(0), mMostRecent(0) { }
34 /*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
41class AudioWatchdog : public Thread {
42
43public:
44 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 }
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
68private:
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