1dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten/* 2dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * Copyright (C) 2012 The Android Open Source Project 3dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * 4dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * you may not use this file except in compliance with the License. 6dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * You may obtain a copy of the License at 7dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * 8dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * 10dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * See the License for the specific language governing permissions and 14dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten * limitations under the License. 15dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten */ 16dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 17dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten#ifndef ANDROID_AUDIO_STATE_QUEUE_H 18dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten#define ANDROID_AUDIO_STATE_QUEUE_H 19dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 20f39b560952d3706a7ff47ef0d82c1a836daeea42Hans Boehm#include <stdatomic.h> 21f39b560952d3706a7ff47ef0d82c1a836daeea42Hans Boehm 222188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// The state queue template class was originally driven by this use case / requirements: 232188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// There are two threads: a fast mixer, and a normal mixer, and they share state. 242188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// The interesting part of the shared state is a set of active fast tracks, 252188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// and the output HAL configuration (buffer size in frames, sample rate, etc.). 262188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// Fast mixer thread: 272188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// periodic with typical period < 10 ms 282188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// FIFO/RR scheduling policy and a low fixed priority 292188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// ok to block for bounded time using nanosleep() to achieve desired period 302188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// must not block on condition wait, mutex lock, atomic operation spin, I/O, etc. 312188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// under typical operations of mixing, writing, or adding/removing tracks 322188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// ok to block for unbounded time when the output HAL configuration changes, 332188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// and this may result in an audible artifact 342188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// needs read-only access to a recent stable state, 352188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// but not necessarily the most current one 36fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten// only allocate and free memory when configuration changes 37fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten// avoid conventional logging, as this is a form of I/O and could block 38fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten// defer computation to other threads when feasible; for example 39fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten// cycle times are collected by fast mixer thread but the floating-point 40fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten// statistical calculations on these cycle times are computed by normal mixer 41fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten// these requirements also apply to callouts such as AudioBufferProvider and VolumeProvider 422188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// Normal mixer thread: 43fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten// periodic with typical period ~20 ms 442188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// SCHED_OTHER scheduling policy and nice priority == urgent audio 452188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// ok to block, but prefer to avoid as much as possible 462188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// needs read/write access to state 472188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// The normal mixer may need to temporarily suspend the fast mixer thread during mode changes. 482188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// It will do this using the state -- one of the fields tells the fast mixer to idle. 492188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten 502188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// Additional requirements: 512188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// - observer must always be able to poll for and view the latest pushed state; it must never be 522188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// blocked from seeing that state 532188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// - observer does not need to see every state in sequence; it is OK for it to skip states 542188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// [see below for more on this] 552188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// - mutator must always be able to read/modify a state, it must never be blocked from reading or 562188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// modifying state 572188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// - reduce memcpy where possible 582188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// - work well if the observer runs more frequently than the mutator, 592188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// as is the case with fast mixer/normal mixer. 602188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// It is not a requirement to work well if the roles were reversed, 612188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// and the mutator were to run more frequently than the observer. 622188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// In this case, the mutator could get blocked waiting for a slot to fill up for 632188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// it to work with. This could be solved somewhat by increasing the depth of the queue, but it would 642188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// still limit the mutator to a finite number of changes before it would block. A future 652188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// possibility, not implemented here, would be to allow the mutator to safely overwrite an already 662188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// pushed state. This could be done by the mutator overwriting mNext, but then being prepared to 672188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// read an mAck which is actually for the earlier mNext (since there is a race). 682188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten 692188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// Solution: 702188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// Let's call the fast mixer thread the "observer" and normal mixer thread the "mutator". 712188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// We assume there is only a single observer and a single mutator; this is critical. 722188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// Each state is of type <T>, and should contain only POD (Plain Old Data) and raw pointers, as 732188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// memcpy() may be used to copy state, and the destructors are run in unpredictable order. 742188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// The states in chronological order are: previous, current, next, and mutating: 752188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// previous read-only, observer can compare vs. current to see the subset that changed 762188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// current read-only, this is the primary state for observer 772188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// next read-only, when observer is ready to accept a new state it will shift it in: 782188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// previous = current 792188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// current = next 802188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// and the slot formerly used by previous is now available to the mutator. 812188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// mutating invisible to observer, read/write to mutator 822188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// Initialization is tricky, especially for the observer. If the observer starts execution 832188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// before the mutator, there are no previous, current, or next states. And even if the observer 842188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// starts execution after the mutator, there is a next state but no previous or current states. 852188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// To solve this, we'll have the observer idle until there is a next state, 862188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// and it will have to deal with the case where there is no previous state. 872188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// The states are stored in a shared FIFO queue represented using a circular array. 882188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// The observer polls for mutations, and receives a new state pointer after a 892188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// a mutation is pushed onto the queue. To the observer, the state pointers are 902188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// effectively in random order, that is the observer should not do address 912188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// arithmetic on the state pointers. However to the mutator, the state pointers 922188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten// are in a definite circular order. 932188bc912a56d9bc577fcec7bf2208f49455e744Glenn Kasten 945b17c0b5b418c340d3e5201a72ee8c88c1755355Glenn Kasten#include "Configuration.h" 955b17c0b5b418c340d3e5201a72ee8c88c1755355Glenn Kasten 96dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kastennamespace android { 97dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 98399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten#ifdef STATE_QUEUE_DUMP 99399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten// The StateQueueObserverDump and StateQueueMutatorDump keep 100399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten// a cache of StateQueue statistics that can be logged by dumpsys. 101399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten// Each individual native word-sized field is accessed atomically. But the 102399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten// overall structure is non-atomic, that is there may be an inconsistency between fields. 103399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten// No barriers or locks are used for either writing or reading. 104399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten// Only POD types are permitted, and the contents shouldn't be trusted (i.e. do range checks). 105399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten// It has a different lifetime than the StateQueue, and so it can't be a member of StateQueue. 106399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten 107399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kastenstruct StateQueueObserverDump { 108399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten StateQueueObserverDump() : mStateChanges(0) { } 109399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten /*virtual*/ ~StateQueueObserverDump() { } 110399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten unsigned mStateChanges; // incremented each time poll() detects a state change 111399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten void dump(int fd); 112399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten}; 113399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten 114399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kastenstruct StateQueueMutatorDump { 115399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten StateQueueMutatorDump() : mPushDirty(0), mPushAck(0), mBlockedSequence(0) { } 116399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten /*virtual*/ ~StateQueueMutatorDump() { } 117399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten unsigned mPushDirty; // incremented each time push() is called with a dirty state 118399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten unsigned mPushAck; // incremented each time push(BLOCK_UNTIL_ACKED) is called 119399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten unsigned mBlockedSequence; // incremented before and after each time that push() 120399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten // blocks for more than one PUSH_BLOCK_ACK_NS; 121399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten // if odd, then mutator is currently blocked inside push() 122399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten void dump(int fd); 123399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten}; 124399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten#endif 125399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten 126dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten// manages a FIFO queue of states 127dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kastentemplate<typename T> class StateQueue { 128dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 129dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kastenpublic: 130dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten StateQueue(); 131dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten virtual ~StateQueue(); 132dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 133dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Observer APIs 134dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 135dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Poll for a state change. Returns a pointer to a read-only state, 136dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // or NULL if the state has not been initialized yet. 137dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // If a new state has not pushed by mutator since the previous poll, 138dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // then the returned pointer will be unchanged. 139dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // The previous state pointer is guaranteed to still be valid; 140dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // this allows the observer to diff the previous and new states. 141dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten const T* poll(); 142dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 143dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Mutator APIs 144dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 145dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Begin a mutation. Returns a pointer to a read/write state, except the 146dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // first time it is called the state is write-only and _must_ be initialized. 147dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Mutations cannot be nested. 148dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // If the state is dirty and has not been pushed onto the state queue yet, then 149dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // this new mutation will be squashed together with the previous one. 150dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten T* begin(); 151dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 152dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // End the current mutation and indicate whether caller modified the state. 153dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // If didModify is true, then the state is marked dirty (in need of pushing). 154dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // There is no rollback option because modifications are done in place. 155dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Does not automatically push the new state onto the state queue. 156dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten void end(bool didModify = true); 157dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 158dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Push a new state, if any, out to the observer via the state queue. 159dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // For BLOCK_NEVER, returns: 160dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // true if not dirty, or dirty and pushed successfully 161dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // false if dirty and not pushed because that would block; remains dirty 162dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // For BLOCK_UNTIL_PUSHED and BLOCK_UNTIL_ACKED, always returns true. 163dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // No-op if there are no pending modifications (not dirty), except 164dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // for BLOCK_UNTIL_ACKED it will wait until a prior push has been acknowledged. 165dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Must not be called in the middle of a mutation. 166dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten enum block_t { 167dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten BLOCK_NEVER, // do not block 168dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten BLOCK_UNTIL_PUSHED, // block until there's a slot available for the push 169dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten BLOCK_UNTIL_ACKED, // also block until the push is acknowledged by the observer 170dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten }; 171dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten bool push(block_t block = BLOCK_NEVER); 172dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 173dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // Return whether the current state is dirty (modified and not pushed). 174dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten bool isDirty() const { return mIsDirty; } 175dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 176399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten#ifdef STATE_QUEUE_DUMP 177399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten // Register location of observer dump area 178399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten void setObserverDump(StateQueueObserverDump *dump) 179399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten { mObserverDump = dump != NULL ? dump : &mObserverDummyDump; } 180399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten 181399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten // Register location of mutator dump area 182399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten void setMutatorDump(StateQueueMutatorDump *dump) 183399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten { mMutatorDump = dump != NULL ? dump : &mMutatorDummyDump; } 184399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten#endif 185399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten 186dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kastenprivate: 1877f5d335f7b4caecd0dfb8f1085f352f1d2da5d2eGlenn Kasten static const unsigned kN = 4; // values < 4 are not supported by this code 188dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten T mStates[kN]; // written by mutator, read by observer 189dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 190dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // "volatile" is meaningless with SMP, but here it indicates that we're using atomic ops 191f39b560952d3706a7ff47ef0d82c1a836daeea42Hans Boehm atomic_uintptr_t mNext; // written by mutator to advance next, read by observer 192dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten volatile const T* mAck; // written by observer to acknowledge advance of next, read by mutator 193dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 194dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // only used by observer 195dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten const T* mCurrent; // most recent value returned by poll() 196dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 197dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten // only used by mutator 198dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten T* mMutating; // where updates by mutator are done in place 199dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten const T* mExpecting; // what the mutator expects mAck to be set to 200dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten bool mInMutation; // whether we're currently in the middle of a mutation 201dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten bool mIsDirty; // whether mutating state has been modified since last push 202dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten bool mIsInitialized; // whether mutating state has been initialized yet 203dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 204399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten#ifdef STATE_QUEUE_DUMP 205399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten StateQueueObserverDump mObserverDummyDump; // default area for observer dump if not set 206399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten StateQueueObserverDump* mObserverDump; // pointer to active observer dump, always non-NULL 207399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten StateQueueMutatorDump mMutatorDummyDump; // default area for mutator dump if not set 208399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten StateQueueMutatorDump* mMutatorDump; // pointer to active mutator dump, always non-NULL 209399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten#endif 210399930859a75d806ce0ef124ac22025ae4ef0549Glenn Kasten 211dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten}; // class StateQueue 212dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 213dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten} // namespace android 214dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten 215dc998c809e084b617990b281e2ed5271830cc2e0Glenn Kasten#endif // ANDROID_AUDIO_STATE_QUEUE_H 216