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
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
89