| Glenn Kasten | 97b5d0d | 2012-03-23 18:54:19 -0700 | [diff] [blame] | 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 | #ifndef ANDROID_AUDIO_FAST_MIXER_H | 
|  | 18 | #define ANDROID_AUDIO_FAST_MIXER_H | 
|  | 19 |  | 
| Glenn Kasten | 09474df | 2012-05-10 14:48:07 -0700 | [diff] [blame] | 20 | #include <utils/Debug.h> | 
| Glenn Kasten | 97b5d0d | 2012-03-23 18:54:19 -0700 | [diff] [blame] | 21 | #include <utils/Thread.h> | 
|  | 22 | extern "C" { | 
|  | 23 | #include "../private/bionic_futex.h" | 
|  | 24 | } | 
|  | 25 | #include "StateQueue.h" | 
|  | 26 | #include "FastMixerState.h" | 
|  | 27 |  | 
|  | 28 | namespace android { | 
|  | 29 |  | 
|  | 30 | typedef StateQueue<FastMixerState> FastMixerStateQueue; | 
|  | 31 |  | 
|  | 32 | class FastMixer : public Thread { | 
|  | 33 |  | 
|  | 34 | public: | 
|  | 35 | FastMixer() : Thread(false /*canCallJava*/) { } | 
|  | 36 | virtual ~FastMixer() { } | 
|  | 37 |  | 
|  | 38 | FastMixerStateQueue* sq() { return &mSQ; } | 
|  | 39 |  | 
|  | 40 | private: | 
|  | 41 | virtual bool                threadLoop(); | 
|  | 42 | FastMixerStateQueue mSQ; | 
|  | 43 |  | 
|  | 44 | };  // class FastMixer | 
|  | 45 |  | 
| Glenn Kasten | 09474df | 2012-05-10 14:48:07 -0700 | [diff] [blame] | 46 | // Describes the underrun status for a single "pull" attempt | 
|  | 47 | enum FastTrackUnderrunStatus { | 
|  | 48 | UNDERRUN_FULL,      // framesReady() is full frame count, no underrun | 
|  | 49 | UNDERRUN_PARTIAL,   // framesReady() is non-zero but < full frame count, partial underrun | 
|  | 50 | UNDERRUN_EMPTY,     // framesReady() is zero, total underrun | 
|  | 51 | }; | 
|  | 52 |  | 
|  | 53 | // Underrun counters are not reset to zero for new tracks or if track generation changes. | 
|  | 54 | // This packed representation is used to keep the information atomic. | 
|  | 55 | union FastTrackUnderruns { | 
|  | 56 | FastTrackUnderruns() { mAtomic = 0; | 
|  | 57 | COMPILE_TIME_ASSERT_FUNCTION_SCOPE(sizeof(FastTrackUnderruns) == sizeof(uint32_t)); } | 
|  | 58 | FastTrackUnderruns(const FastTrackUnderruns& copyFrom) : mAtomic(copyFrom.mAtomic) { } | 
|  | 59 | FastTrackUnderruns& operator=(const FastTrackUnderruns& rhs) | 
|  | 60 | { if (this != &rhs) mAtomic = rhs.mAtomic; return *this; } | 
|  | 61 | struct { | 
|  | 62 | #define UNDERRUN_BITS 10 | 
|  | 63 | #define UNDERRUN_MASK ((1 << UNDERRUN_BITS) - 1) | 
|  | 64 | uint32_t mFull    : UNDERRUN_BITS; // framesReady() is full frame count | 
|  | 65 | uint32_t mPartial : UNDERRUN_BITS; // framesReady() is non-zero but < full frame count | 
|  | 66 | uint32_t mEmpty   : UNDERRUN_BITS; // framesReady() is zero | 
|  | 67 | FastTrackUnderrunStatus mMostRecent : 2;    // status of most recent framesReady() | 
|  | 68 | }        mBitFields; | 
|  | 69 | private: | 
|  | 70 | uint32_t mAtomic; | 
|  | 71 | }; | 
|  | 72 |  | 
| Glenn Kasten | 288ed21 | 2012-04-25 17:52:27 -0700 | [diff] [blame] | 73 | // Represents the dump state of a fast track | 
|  | 74 | struct FastTrackDump { | 
| Glenn Kasten | 1295bb4d | 2012-05-31 07:43:43 -0700 | [diff] [blame] | 75 | FastTrackDump() : mFramesReady(0) { } | 
| Glenn Kasten | 288ed21 | 2012-04-25 17:52:27 -0700 | [diff] [blame] | 76 | /*virtual*/ ~FastTrackDump() { } | 
| Glenn Kasten | 09474df | 2012-05-10 14:48:07 -0700 | [diff] [blame] | 77 | FastTrackUnderruns mUnderruns; | 
| Glenn Kasten | 1295bb4d | 2012-05-31 07:43:43 -0700 | [diff] [blame] | 78 | size_t mFramesReady;        // most recent value only; no long-term statistics kept | 
| Glenn Kasten | 288ed21 | 2012-04-25 17:52:27 -0700 | [diff] [blame] | 79 | }; | 
|  | 80 |  | 
| Glenn Kasten | 97b5d0d | 2012-03-23 18:54:19 -0700 | [diff] [blame] | 81 | // The FastMixerDumpState keeps a cache of FastMixer statistics that can be logged by dumpsys. | 
| Glenn Kasten | 288ed21 | 2012-04-25 17:52:27 -0700 | [diff] [blame] | 82 | // Each individual native word-sized field is accessed atomically.  But the | 
|  | 83 | // overall structure is non-atomic, that is there may be an inconsistency between fields. | 
|  | 84 | // No barriers or locks are used for either writing or reading. | 
|  | 85 | // Only POD types are permitted, and the contents shouldn't be trusted (i.e. do range checks). | 
| Glenn Kasten | 97b5d0d | 2012-03-23 18:54:19 -0700 | [diff] [blame] | 86 | // It has a different lifetime than the FastMixer, and so it can't be a member of FastMixer. | 
|  | 87 | struct FastMixerDumpState { | 
|  | 88 | FastMixerDumpState(); | 
|  | 89 | /*virtual*/ ~FastMixerDumpState(); | 
|  | 90 |  | 
| Glenn Kasten | 42d45cf | 2012-05-02 10:34:47 -0700 | [diff] [blame] | 91 | void dump(int fd);          // should only be called on a stable copy, not the original | 
| Glenn Kasten | 97b5d0d | 2012-03-23 18:54:19 -0700 | [diff] [blame] | 92 |  | 
|  | 93 | FastMixerState::Command mCommand;   // current command | 
|  | 94 | uint32_t mWriteSequence;    // incremented before and after each write() | 
|  | 95 | uint32_t mFramesWritten;    // total number of frames written successfully | 
|  | 96 | uint32_t mNumTracks;        // total number of active fast tracks | 
|  | 97 | uint32_t mWriteErrors;      // total number of write() errors | 
|  | 98 | uint32_t mUnderruns;        // total number of underruns | 
|  | 99 | uint32_t mOverruns;         // total number of overruns | 
| Glenn Kasten | 21e8c50 | 2012-04-12 09:39:42 -0700 | [diff] [blame] | 100 | uint32_t mSampleRate; | 
|  | 101 | size_t   mFrameCount; | 
| Glenn Kasten | 288ed21 | 2012-04-25 17:52:27 -0700 | [diff] [blame] | 102 | struct timespec mMeasuredWarmupTs;  // measured warmup time | 
|  | 103 | uint32_t mWarmupCycles;     // number of loop cycles required to warmup | 
| Glenn Kasten | 1295bb4d | 2012-05-31 07:43:43 -0700 | [diff] [blame] | 104 | uint32_t mTrackMask;        // mask of active tracks | 
| Glenn Kasten | 288ed21 | 2012-04-25 17:52:27 -0700 | [diff] [blame] | 105 | FastTrackDump   mTracks[FastMixerState::kMaxFastTracks]; | 
| Glenn Kasten | 42d45cf | 2012-05-02 10:34:47 -0700 | [diff] [blame] | 106 |  | 
| Glenn Kasten | 97b5d0d | 2012-03-23 18:54:19 -0700 | [diff] [blame] | 107 | #ifdef FAST_MIXER_STATISTICS | 
| Glenn Kasten | 42d45cf | 2012-05-02 10:34:47 -0700 | [diff] [blame] | 108 | // Recently collected samples of per-cycle monotonic time, thread CPU time, and CPU frequency. | 
|  | 109 | // kSamplingN is the size of the sampling frame, and must be a power of 2 <= 0x8000. | 
| Glenn Kasten | 0d35f78 | 2013-03-11 10:58:50 -0700 | [diff] [blame] | 110 | static const uint32_t kSamplingN = 0x8000; | 
| Glenn Kasten | 42d45cf | 2012-05-02 10:34:47 -0700 | [diff] [blame] | 111 | // The bounds define the interval of valid samples, and are represented as follows: | 
|  | 112 | //      newest open (excluded) endpoint   = lower 16 bits of bounds, modulo N | 
|  | 113 | //      oldest closed (included) endpoint = upper 16 bits of bounds, modulo N | 
|  | 114 | // Number of valid samples is newest - oldest. | 
|  | 115 | uint32_t mBounds;                   // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz | 
|  | 116 | // The elements in the *Ns arrays are in units of nanoseconds <= 3999999999. | 
|  | 117 | uint32_t mMonotonicNs[kSamplingN];  // delta monotonic (wall clock) time | 
|  | 118 | uint32_t mLoadNs[kSamplingN];       // delta CPU load in time | 
| Glenn Kasten | 0a14c4c | 2012-06-13 14:58:49 -0700 | [diff] [blame] | 119 | #ifdef CPU_FREQUENCY_STATISTICS | 
| Glenn Kasten | 42d45cf | 2012-05-02 10:34:47 -0700 | [diff] [blame] | 120 | uint32_t mCpukHz[kSamplingN];       // absolute CPU clock frequency in kHz, bits 0-3 are CPU# | 
| Glenn Kasten | 97b5d0d | 2012-03-23 18:54:19 -0700 | [diff] [blame] | 121 | #endif | 
| Glenn Kasten | 0a14c4c | 2012-06-13 14:58:49 -0700 | [diff] [blame] | 122 | #endif | 
| Glenn Kasten | 97b5d0d | 2012-03-23 18:54:19 -0700 | [diff] [blame] | 123 | }; | 
|  | 124 |  | 
|  | 125 | }   // namespace android | 
|  | 126 |  | 
|  | 127 | #endif  // ANDROID_AUDIO_FAST_MIXER_H |