1c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten/*
2c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * Copyright (C) 2012 The Android Open Source Project
3c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten *
4c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * you may not use this file except in compliance with the License.
6c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * You may obtain a copy of the License at
7c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten *
8c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten *
10c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * Unless required by applicable law or agreed to in writing, software
11c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * See the License for the specific language governing permissions and
14c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten * limitations under the License.
15c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten */
16c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
17c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten// The watchdog thread runs periodically.  It has two functions:
18c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten//   (a) verify that adequate CPU time is available, and log
19c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten//       as soon as possible when there appears to be a CPU shortage
20c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten//   (b) monitor the other threads [not yet implemented]
21c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
22c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten#ifndef AUDIO_WATCHDOG_H
23c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten#define AUDIO_WATCHDOG_H
24c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
25c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten#include <time.h>
26c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten#include <utils/Thread.h>
27c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
28c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kastennamespace android {
29c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
30c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten// Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys.
31c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten// The usual caveats about atomicity of information apply.
32c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kastenstruct AudioWatchdogDump {
33c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    AudioWatchdogDump() : mUnderruns(0), mLogs(0), mMostRecent(0) { }
34c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    /*virtual*/ ~AudioWatchdogDump() { }
35c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    uint32_t mUnderruns;    // total number of underruns
36c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    uint32_t mLogs;         // total number of log messages
37c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    time_t   mMostRecent;   // time of most recent log
38c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    void     dump(int fd);  // should only be called on a stable copy, not the original
39c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten};
40c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
41c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kastenclass AudioWatchdog : public Thread {
42c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
43c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kastenpublic:
44c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), mPaused(false),
45c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten            mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2),
46c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten            // mOldTs
47c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten            // mLogTs initialized below
48c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten            mOldTsValid(false), mUnderruns(0), mLogs(0), mDump(&mDummyDump)
49c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten        {
50c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten#define MIN_TIME_BETWEEN_LOGS_SEC 60
51c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten            // force an immediate log on first underrun
52c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten            mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
53c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten            mLogTs.tv_nsec = 0;
54c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten        }
55c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    virtual         ~AudioWatchdog() { }
56c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
57c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten     // Do not call Thread::requestExitAndWait() without first calling requestExit().
58c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
59c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    virtual void        requestExit();
60c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
61c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    // FIXME merge API and implementation with AudioTrackThread
62c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    void            pause();        // suspend thread from execution at next loop boundary
63c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    void            resume();       // allow thread to execute, if not requested to exit
64c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
65c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    // Where to store the dump, or NULL to not update
66c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    void            setDump(AudioWatchdogDump* dump);
67c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
68c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kastenprivate:
69c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    virtual bool    threadLoop();
70c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
71c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    Mutex           mMyLock;        // Thread::mLock is private
72c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    Condition       mMyCond;        // Thread::mThreadExitedCondition is private
73c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    bool            mPaused;        // whether thread is currently paused
74c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
75c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    uint32_t        mPeriodNs;      // nominal period
76c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    uint32_t        mMaxCycleNs;    // maximum allowed time of one cycle before declaring underrun
77c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    struct timespec mOldTs;         // monotonic time when threadLoop last ran
78c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    struct timespec mLogTs;         // time since last log
79c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    bool            mOldTsValid;    // whether mOldTs is valid
80c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    uint32_t        mUnderruns;     // total number of underruns
81c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    uint32_t        mLogs;          // total number of logs
82c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    AudioWatchdogDump*  mDump;      // where to store the dump, always non-NULL
83c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten    AudioWatchdogDump   mDummyDump; // default area for dump in case setDump() is not called
84c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten};
85c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
86c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten}   // namespace android
87c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten
88c15d6657a17d7cef91f800f40d11760e2e7340afGlenn Kasten#endif  // AUDIO_WATCHDOG_H
89