197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten/* 297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * Copyright (C) 2012 The Android Open Source Project 397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * 497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * you may not use this file except in compliance with the License. 697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * You may obtain a copy of the License at 797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * 897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * 1097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * Unless required by applicable law or agreed to in writing, software 1197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 1297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * See the License for the specific language governing permissions and 1497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * limitations under the License. 1597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten */ 1697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 17a3d2628a22f2b3d682495044897a40ea1399a662Glenn Kasten// <IMPORTANT_WARNING> 18a3d2628a22f2b3d682495044897a40ea1399a662Glenn Kasten// Design rules for threadLoop() are given in the comments at section "Fast mixer thread" of 19a3d2628a22f2b3d682495044897a40ea1399a662Glenn Kasten// StateQueue.h. In particular, avoid library and system calls except at well-known points. 20a3d2628a22f2b3d682495044897a40ea1399a662Glenn Kasten// The design rules are only for threadLoop(), and don't apply to FastMixerDumpState methods. 21a3d2628a22f2b3d682495044897a40ea1399a662Glenn Kasten// </IMPORTANT_WARNING> 22a3d2628a22f2b3d682495044897a40ea1399a662Glenn Kasten 2397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#define LOG_TAG "FastMixer" 247f5d335f7b4caecd0dfb8f1085f352f1d2da5d2eGlenn Kasten//#define LOG_NDEBUG 0 2597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 26b3a8364eeea621ef63b983e4c1b0771f62069fe0Alex Ray#define ATRACE_TAG ATRACE_TAG_AUDIO 27371eb9756c32109ea572b91216b19bb623f6d3fdAlex Ray 28153b9fe667e6e78e0218ff0159353097428c7657Glenn Kasten#include "Configuration.h" 2997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <sys/atomics.h> 3097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <time.h> 3197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <utils/Log.h> 32d8e6fd35ec2b59ee7d873daf1f1d9d348221c7bcGlenn Kasten#include <utils/Trace.h> 3397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <system/audio.h> 3497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 3597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <cpustats/CentralTendencyStatistics.h> 360a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#ifdef CPU_FREQUENCY_STATISTICS 3742d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten#include <cpustats/ThreadCpuUsage.h> 3897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 390a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#endif 4097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include "AudioMixer.h" 4197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include "FastMixer.h" 4297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 4397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#define FAST_HOT_IDLE_NS 1000000L // 1 ms: time to sleep while hot idling 4497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#define FAST_DEFAULT_NS 999999999L // ~1 sec: default time to sleep 45eb15716b59020f342df62bce5b293f0603b94861Glenn Kasten#define MIN_WARMUP_CYCLES 2 // minimum number of loop cycles to wait for warmup 46288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten#define MAX_WARMUP_CYCLES 10 // maximum number of loop cycles to wait for warmup 4797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 487fc97ba08e2850f3f16db704b78ce78e3dbe1ff0Glenn Kasten#define FCC_2 2 // fixed channel count assumption 497fc97ba08e2850f3f16db704b78ce78e3dbe1ff0Glenn Kasten 5097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kastennamespace android { 5197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 5297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten// Fast mixer thread 5397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kastenbool FastMixer::threadLoop() 5497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten{ 5597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten static const FastMixerState initial; 5697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastMixerState *previous = &initial, *current = &initial; 5797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten FastMixerState preIdle; // copy of state before we went into idle 5897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten struct timespec oldTs = {0, 0}; 5997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten bool oldTsValid = false; 6097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long slopNs = 0; // accumulated time we've woken up too early (> 0) or too late (< 0) 6197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long sleepNs = -1; // -1: busy wait, 0: sched_yield, > 0: nanosleep 6297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int fastTrackNames[FastMixerState::kMaxFastTracks]; // handles used by mixer to identify tracks 6397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int generations[FastMixerState::kMaxFastTracks]; // last observed mFastTracks[i].mGeneration 6497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned i; 6597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten for (i = 0; i < FastMixerState::kMaxFastTracks; ++i) { 6697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTrackNames[i] = -1; 6797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten generations[i] = 0; 6897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 6997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten NBAIO_Sink *outputSink = NULL; 7097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int outputSinkGen = 0; 7197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten AudioMixer* mixer = NULL; 7297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten short *mixBuffer = NULL; 7397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten enum {UNDEFINED, MIXED, ZEROED} mixBufferState = UNDEFINED; 7497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten NBAIO_Format format = Format_Invalid; 7597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned sampleRate = 0; 7697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int fastTracksGen = 0; 7797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long periodNs = 0; // expected period; the time required to render one mix buffer 78288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten long underrunNs = 0; // underrun likely when write cycle is greater than this value 79288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten long overrunNs = 0; // overrun likely when write cycle is less than this value 80972af221ae7253e406e0e1ea853e56a3010ed6b1Glenn Kasten long forceNs = 0; // if overrun detected, force the write cycle to take this much time 81288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten long warmupNs = 0; // warmup complete when write cycle is greater than to this value 8297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten FastMixerDumpState dummyDumpState, *dumpState = &dummyDumpState; 8397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten bool ignoreNextOverrun = true; // used to ignore initial overrun and first after an underrun 8497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 8542d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten struct timespec oldLoad = {0, 0}; // previous value of clock_gettime(CLOCK_THREAD_CPUTIME_ID) 8642d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten bool oldLoadValid = false; // whether oldLoad is valid 8742d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten uint32_t bounds = 0; 884182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten bool full = false; // whether we have collected at least mSamplingN samples 890a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#ifdef CPU_FREQUENCY_STATISTICS 9042d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten ThreadCpuUsage tcu; // for reading the current CPU clock frequency in kHz 9197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 920a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#endif 9397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned coldGen = 0; // last observed mColdGen 94288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten bool isWarm = false; // true means ready to mix, false means wait for warmup before mixing 95288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten struct timespec measuredWarmupTs = {0, 0}; // how long did it take for warmup to complete 96288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten uint32_t warmupCycles = 0; // counter of number of loop cycles required to warmup 97fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten NBAIO_Sink* teeSink = NULL; // if non-NULL, then duplicate write() to this non-blocking sink 989e58b552f51b00b3b674102876bd6c77ef3da806Glenn Kasten NBLog::Writer dummyLogWriter, *logWriter = &dummyLogWriter; 99732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten uint32_t totalNativeFramesWritten = 0; // copied to dumpState->mFramesWritten 100732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten 101732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten // next 2 fields are valid only when timestampStatus == NO_ERROR 102732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten AudioTimestamp timestamp; 103732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten uint32_t nativeFramesWrittenButNotPresented = 0; // the = 0 is to silence the compiler 104732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten status_t timestampStatus = INVALID_OPERATION; 10597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 10697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten for (;;) { 10797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 10897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // either nanosleep, sched_yield, or busy wait 10997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (sleepNs >= 0) { 11097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (sleepNs > 0) { 11197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(sleepNs < 1000000000); 11297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const struct timespec req = {0, sleepNs}; 11397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten nanosleep(&req, NULL); 11497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 11597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sched_yield(); 11697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 11797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 11897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // default to long sleep for next cycle 11997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = FAST_DEFAULT_NS; 12097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 12197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // poll for state change 12297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastMixerState *next = mSQ.poll(); 12397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (next == NULL) { 12497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // continue to use the default initial state until a real state is available 12597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(current == &initial && previous == &initial); 12697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten next = current; 12797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 12897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 12997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten FastMixerState::Command command = next->mCommand; 13097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (next != current) { 13197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 13297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // As soon as possible of learning of a new dump area, start using it 13397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState = next->mDumpState != NULL ? next->mDumpState : &dummyDumpState; 134fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten teeSink = next->mTeeSink; 1359e58b552f51b00b3b674102876bd6c77ef3da806Glenn Kasten logWriter = next->mNBLogWriter != NULL ? next->mNBLogWriter : &dummyLogWriter; 136ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten if (mixer != NULL) { 137ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten mixer->setLog(logWriter); 138ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten } 13997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 14097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // We want to always have a valid reference to the previous (non-idle) state. 14197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // However, the state queue only guarantees access to current and previous states. 14297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // So when there is a transition from a non-idle state into an idle state, we make a 14397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // copy of the last known non-idle state so it is still available on return from idle. 14497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // The possible transitions are: 14597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // non-idle -> non-idle update previous from current in-place 14697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // non-idle -> idle update previous from copy of current 14797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // idle -> idle don't update previous 14897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // idle -> non-idle don't update previous 14997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (!(current->mCommand & FastMixerState::IDLE)) { 15097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (command & FastMixerState::IDLE) { 15197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten preIdle = *current; 15297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten current = &preIdle; 15397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten oldTsValid = false; 154153b9fe667e6e78e0218ff0159353097428c7657Glenn Kasten#ifdef FAST_MIXER_STATISTICS 15542d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten oldLoadValid = false; 156153b9fe667e6e78e0218ff0159353097428c7657Glenn Kasten#endif 15797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ignoreNextOverrun = true; 15897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 15997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten previous = current; 16097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 16197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten current = next; 16297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 16397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#if !LOG_NDEBUG 16497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten next = NULL; // not referenced again 16597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 16697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 16797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mCommand = command; 16897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 16997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten switch (command) { 17097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::INITIAL: 17197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::HOT_IDLE: 17297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = FAST_HOT_IDLE_NS; 17397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten continue; 17497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::COLD_IDLE: 17597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // only perform a cold idle command once 17621e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten // FIXME consider checking previous state and only perform if previous != COLD_IDLE 17797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (current->mColdGen != coldGen) { 17897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int32_t *coldFutexAddr = current->mColdFutexAddr; 17997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(coldFutexAddr != NULL); 18097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int32_t old = android_atomic_dec(coldFutexAddr); 18197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (old <= 0) { 18297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten __futex_syscall4(coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL); 18397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 184a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten int policy = sched_getscheduler(0); 185a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten if (!(policy == SCHED_FIFO || policy == SCHED_RR)) { 186a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten ALOGE("did not receive expected priority boost"); 187a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten } 188288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // This may be overly conservative; there could be times that the normal mixer 189288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // requests such a brief cold idle that it doesn't require resetting this flag. 190288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten isWarm = false; 191288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten measuredWarmupTs.tv_sec = 0; 192288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten measuredWarmupTs.tv_nsec = 0; 193288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten warmupCycles = 0; 19497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = -1; 19597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten coldGen = current->mColdGen; 196153b9fe667e6e78e0218ff0159353097428c7657Glenn Kasten#ifdef FAST_MIXER_STATISTICS 19742d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten bounds = 0; 19842d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten full = false; 199153b9fe667e6e78e0218ff0159353097428c7657Glenn Kasten#endif 20004a4ca4217e9b30342d5865024c340013d7184e8Glenn Kasten oldTsValid = !clock_gettime(CLOCK_MONOTONIC, &oldTs); 201732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten timestampStatus = INVALID_OPERATION; 20297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 20397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = FAST_HOT_IDLE_NS; 20497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 20597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten continue; 20697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::EXIT: 20797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten delete mixer; 20897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten delete[] mixBuffer; 20997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten return false; 21097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::MIX: 21197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::WRITE: 21297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::MIX_WRITE: 21397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 21497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten default: 21597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten LOG_FATAL("bad command %d", command); 21697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 21797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 21897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // there is a non-idle state available to us; did the state change? 21997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten size_t frameCount = current->mFrameCount; 22097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (current != previous) { 22197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 22297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // handle state change here, but since we want to diff the state, 22397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // we're prepared for previous == &initial the first time through 22497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned previousTrackMask; 22597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 22697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // check for change in output HAL configuration 22797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten NBAIO_Format previousFormat = format; 22897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (current->mOutputSinkGen != outputSinkGen) { 22997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten outputSink = current->mOutputSink; 23097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten outputSinkGen = current->mOutputSinkGen; 23197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (outputSink == NULL) { 23297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten format = Format_Invalid; 23397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sampleRate = 0; 23497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 23597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten format = outputSink->format(); 23697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sampleRate = Format_sampleRate(format); 2377fc97ba08e2850f3f16db704b78ce78e3dbe1ff0Glenn Kasten ALOG_ASSERT(Format_channelCount(format) == FCC_2); 23897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 23921e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten dumpState->mSampleRate = sampleRate; 24097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 24197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 24297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if ((format != previousFormat) || (frameCount != previous->mFrameCount)) { 24397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME to avoid priority inversion, don't delete here 24497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten delete mixer; 24597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer = NULL; 24697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten delete[] mixBuffer; 24797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBuffer = NULL; 24897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (frameCount > 0 && sampleRate > 0) { 24997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME new may block for unbounded time at internal mutex of the heap 25097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // implementation; it would be better to have normal mixer allocate for us 25197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // to avoid blocking here and to prevent possible priority inversion 25297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer = new AudioMixer(frameCount, sampleRate, FastMixerState::kMaxFastTracks); 2537fc97ba08e2850f3f16db704b78ce78e3dbe1ff0Glenn Kasten mixBuffer = new short[frameCount * FCC_2]; 25497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten periodNs = (frameCount * 1000000000LL) / sampleRate; // 1.00 25597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten underrunNs = (frameCount * 1750000000LL) / sampleRate; // 1.75 2560d27c65ddb5c968baa6db0c26e80f5c451bc52bcGlenn Kasten overrunNs = (frameCount * 500000000LL) / sampleRate; // 0.50 2570d27c65ddb5c968baa6db0c26e80f5c451bc52bcGlenn Kasten forceNs = (frameCount * 950000000LL) / sampleRate; // 0.95 258288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten warmupNs = (frameCount * 500000000LL) / sampleRate; // 0.50 25997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 26097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten periodNs = 0; 26197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten underrunNs = 0; 26297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten overrunNs = 0; 263972af221ae7253e406e0e1ea853e56a3010ed6b1Glenn Kasten forceNs = 0; 264972af221ae7253e406e0e1ea853e56a3010ed6b1Glenn Kasten warmupNs = 0; 26597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 26697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBufferState = UNDEFINED; 26797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#if !LOG_NDEBUG 26897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten for (i = 0; i < FastMixerState::kMaxFastTracks; ++i) { 26997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTrackNames[i] = -1; 27097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 27197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 27297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // we need to reconfigure all active tracks 27397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten previousTrackMask = 0; 27497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTracksGen = current->mFastTracksGen - 1; 27521e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten dumpState->mFrameCount = frameCount; 27697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 27797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten previousTrackMask = previous->mTrackMask; 27897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 27997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 28097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // check for change in active track set 28197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned currentTrackMask = current->mTrackMask; 2821295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten dumpState->mTrackMask = currentTrackMask; 28397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (current->mFastTracksGen != fastTracksGen) { 28497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(mixBuffer != NULL); 28597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int name; 28697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 28797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // process removed tracks first to avoid running out of track names 28897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned removedTracks = previousTrackMask & ~currentTrackMask; 28997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten while (removedTracks != 0) { 29097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten i = __builtin_ctz(removedTracks); 29197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten removedTracks &= ~(1 << i); 29297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastTrack* fastTrack = ¤t->mFastTracks[i]; 293288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten ALOG_ASSERT(fastTrack->mBufferProvider == NULL); 29497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (mixer != NULL) { 29597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten name = fastTrackNames[i]; 29697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(name >= 0); 29797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->deleteTrackName(name); 29897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 29997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#if !LOG_NDEBUG 30097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTrackNames[i] = -1; 30197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 302288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // don't reset track dump state, since other side is ignoring it 30397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten generations[i] = fastTrack->mGeneration; 30497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 30597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 30697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // now process added tracks 30797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned addedTracks = currentTrackMask & ~previousTrackMask; 30897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten while (addedTracks != 0) { 30997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten i = __builtin_ctz(addedTracks); 31097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten addedTracks &= ~(1 << i); 31197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastTrack* fastTrack = ¤t->mFastTracks[i]; 31297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider; 31397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(bufferProvider != NULL && fastTrackNames[i] == -1); 31497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (mixer != NULL) { 315fe3156ec6fd9fa57dde913fd8567530d095a6550Jean-Michel Trivi // calling getTrackName with default channel mask and a random invalid 316fe3156ec6fd9fa57dde913fd8567530d095a6550Jean-Michel Trivi // sessionId (no effects here) 317fe3156ec6fd9fa57dde913fd8567530d095a6550Jean-Michel Trivi name = mixer->getTrackName(AUDIO_CHANNEL_OUT_STEREO, -555); 31897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(name >= 0); 31997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTrackNames[i] = name; 32097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setBufferProvider(name, bufferProvider); 32197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER, 32297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *) mixBuffer); 32397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // newly allocated track names default to full scale volume 32421e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten if (fastTrack->mSampleRate != 0 && fastTrack->mSampleRate != sampleRate) { 32521e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::RESAMPLE, 32621e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten AudioMixer::SAMPLE_RATE, (void*) fastTrack->mSampleRate); 32721e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten } 32821e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, 32921e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten (void *) fastTrack->mChannelMask); 33097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->enable(name); 33197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 33297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten generations[i] = fastTrack->mGeneration; 33397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 33497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 335ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten // finally process (potentially) modified tracks; these use the same slot 33697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // but may have a different buffer provider or volume provider 33797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned modifiedTracks = currentTrackMask & previousTrackMask; 33897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten while (modifiedTracks != 0) { 33997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten i = __builtin_ctz(modifiedTracks); 34097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten modifiedTracks &= ~(1 << i); 34197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastTrack* fastTrack = ¤t->mFastTracks[i]; 34297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (fastTrack->mGeneration != generations[i]) { 343ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten // this track was actually modified 34497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider; 34597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(bufferProvider != NULL); 34697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (mixer != NULL) { 34797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten name = fastTrackNames[i]; 34897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(name >= 0); 34997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setBufferProvider(name, bufferProvider); 35097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (fastTrack->mVolumeProvider == NULL) { 35197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, 35297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *)0x1000); 35397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, 35497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *)0x1000); 35597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 35621e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten if (fastTrack->mSampleRate != 0 && 35721e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten fastTrack->mSampleRate != sampleRate) { 35821e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::RESAMPLE, 35921e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten AudioMixer::SAMPLE_RATE, (void*) fastTrack->mSampleRate); 36021e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten } else { 36121e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::RESAMPLE, 36221e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten AudioMixer::REMOVE, NULL); 36321e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten } 36421e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, 36521e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten (void *) fastTrack->mChannelMask); 36697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // already enabled 36797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 36897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten generations[i] = fastTrack->mGeneration; 36997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 37097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 37197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 37297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTracksGen = current->mFastTracksGen; 37397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 37497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mNumTracks = popcount(currentTrackMask); 37597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 37697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 37797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#if 1 // FIXME shouldn't need this 37897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // only process state change once 37997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten previous = current; 38097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 38197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 38297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 38397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // do work using current state here 384288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten if ((command & FastMixerState::MIX) && (mixer != NULL) && isWarm) { 38597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(mixBuffer != NULL); 386288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // for each track, update volume and check for underrun 387288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten unsigned currentTrackMask = current->mTrackMask; 388288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten while (currentTrackMask != 0) { 389288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten i = __builtin_ctz(currentTrackMask); 390288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten currentTrackMask &= ~(1 << i); 39197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastTrack* fastTrack = ¤t->mFastTracks[i]; 392732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten 393732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten // Refresh the per-track timestamp 394732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten if (timestampStatus == NO_ERROR) { 395732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten uint32_t trackFramesWrittenButNotPresented; 396732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten uint32_t trackSampleRate = fastTrack->mSampleRate; 397732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten // There is currently no sample rate conversion for fast tracks currently 398732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten if (trackSampleRate != 0 && trackSampleRate != sampleRate) { 399732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten trackFramesWrittenButNotPresented = 400732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten ((int64_t) nativeFramesWrittenButNotPresented * trackSampleRate) / 401732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten sampleRate; 402732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten } else { 403732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten trackFramesWrittenButNotPresented = nativeFramesWrittenButNotPresented; 404732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten } 405732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten uint32_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased(); 406732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten // Can't provide an AudioTimestamp before first frame presented, 407732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten // or during the brief 32-bit wraparound window 408732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten if (trackFramesWritten >= trackFramesWrittenButNotPresented) { 409732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten AudioTimestamp perTrackTimestamp; 410732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten perTrackTimestamp.mPosition = 411732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten trackFramesWritten - trackFramesWrittenButNotPresented; 412732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten perTrackTimestamp.mTime = timestamp.mTime; 413732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp); 414732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten } 415732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten } 416732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten 41797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int name = fastTrackNames[i]; 41897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(name >= 0); 41997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (fastTrack->mVolumeProvider != NULL) { 42097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten uint32_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); 42197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, 42297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *)(vlr & 0xFFFF)); 42397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, 42497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *)(vlr >> 16)); 42597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 426288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // FIXME The current implementation of framesReady() for fast tracks 427288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // takes a tryLock, which can block 428288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // up to 1 ms. If enough active tracks all blocked in sequence, this would result 429288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // in the overall fast mix cycle being delayed. Should use a non-blocking FIFO. 430288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten size_t framesReady = fastTrack->mBufferProvider->framesReady(); 431b3a8364eeea621ef63b983e4c1b0771f62069fe0Alex Ray if (ATRACE_ENABLED()) { 432b3a8364eeea621ef63b983e4c1b0771f62069fe0Alex Ray // I wish we had formatted trace names 433b3a8364eeea621ef63b983e4c1b0771f62069fe0Alex Ray char traceName[16]; 434c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten strcpy(traceName, "fRdy"); 435c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten traceName[4] = i + (i < 10 ? '0' : 'A' - 10); 436c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten traceName[5] = '\0'; 437b3a8364eeea621ef63b983e4c1b0771f62069fe0Alex Ray ATRACE_INT(traceName, framesReady); 438b3a8364eeea621ef63b983e4c1b0771f62069fe0Alex Ray } 439288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten FastTrackDump *ftDump = &dumpState->mTracks[i]; 44009474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten FastTrackUnderruns underruns = ftDump->mUnderruns; 441288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten if (framesReady < frameCount) { 442288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten if (framesReady == 0) { 44309474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten underruns.mBitFields.mEmpty++; 44409474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten underruns.mBitFields.mMostRecent = UNDERRUN_EMPTY; 445288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten mixer->disable(name); 446288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } else { 447288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // allow mixing partial buffer 44809474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten underruns.mBitFields.mPartial++; 44909474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten underruns.mBitFields.mMostRecent = UNDERRUN_PARTIAL; 450288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten mixer->enable(name); 451288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 45209474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten } else { 45309474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten underruns.mBitFields.mFull++; 45409474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten underruns.mBitFields.mMostRecent = UNDERRUN_FULL; 455288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten mixer->enable(name); 456288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 45709474df67278c0cd621b57c4aef1deaec4d8447fGlenn Kasten ftDump->mUnderruns = underruns; 4581295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten ftDump->mFramesReady = framesReady; 45997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 4602c3b2da3049627264b7c6b449a1622f002210f03John Grossman 4612c3b2da3049627264b7c6b449a1622f002210f03John Grossman int64_t pts; 4622c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (outputSink == NULL || (OK != outputSink->getNextWriteTimestamp(&pts))) 4632c3b2da3049627264b7c6b449a1622f002210f03John Grossman pts = AudioBufferProvider::kInvalidPTS; 4642c3b2da3049627264b7c6b449a1622f002210f03John Grossman 46597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // process() is CPU-bound 4662c3b2da3049627264b7c6b449a1622f002210f03John Grossman mixer->process(pts); 46797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBufferState = MIXED; 46897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else if (mixBufferState == MIXED) { 46997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBufferState = UNDEFINED; 47097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 471288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten bool attemptedWrite = false; 472288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten //bool didFullWrite = false; // dumpsys could display a count of partial writes 47397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if ((command & FastMixerState::WRITE) && (outputSink != NULL) && (mixBuffer != NULL)) { 47497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (mixBufferState == UNDEFINED) { 4757fc97ba08e2850f3f16db704b78ce78e3dbe1ff0Glenn Kasten memset(mixBuffer, 0, frameCount * FCC_2 * sizeof(short)); 47697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBufferState = ZEROED; 47797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 478fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten if (teeSink != NULL) { 479fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten (void) teeSink->write(mixBuffer, frameCount); 480fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten } 48197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME write() is non-blocking and lock-free for a properly implemented NBAIO sink, 48297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // but this code should be modified to handle both non-blocking and blocking sinks 48397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mWriteSequence++; 4842d590964aa58e137d17a43e095e6443dd0fe2e98Simon Wilson ATRACE_BEGIN("write"); 48597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ssize_t framesWritten = outputSink->write(mixBuffer, frameCount); 4862d590964aa58e137d17a43e095e6443dd0fe2e98Simon Wilson ATRACE_END(); 48797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mWriteSequence++; 48897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (framesWritten >= 0) { 489ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten ALOG_ASSERT((size_t) framesWritten <= frameCount); 490732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten totalNativeFramesWritten += framesWritten; 491732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten dumpState->mFramesWritten = totalNativeFramesWritten; 492288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten //if ((size_t) framesWritten == frameCount) { 493288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // didFullWrite = true; 494288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten //} 49597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 49697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mWriteErrors++; 49797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 498288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten attemptedWrite = true; 49997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME count # of writes blocked excessively, CPU usage, etc. for dump 500732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten 501732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten timestampStatus = outputSink->getTimestamp(timestamp); 502732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten if (timestampStatus == NO_ERROR) { 503732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten uint32_t totalNativeFramesPresented = timestamp.mPosition; 504732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten if (totalNativeFramesPresented <= totalNativeFramesWritten) { 505732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten nativeFramesWrittenButNotPresented = 506732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten totalNativeFramesWritten - totalNativeFramesPresented; 507732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten } else { 508732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten // HAL reported that more frames were presented than were written 509732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten timestampStatus = INVALID_OPERATION; 510732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten } 511732845c7e8d294bb1aaa4cd9687da62b51f1f6e6Glenn Kasten } 51297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 51397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 51497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // To be exactly periodic, compute the next sleep time based on current time. 51597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // This code doesn't have long-term stability when the sink is non-blocking. 51697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME To avoid drift, use the local audio clock or watch the sink's fill status. 51797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten struct timespec newTs; 51897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int rc = clock_gettime(CLOCK_MONOTONIC, &newTs); 51997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (rc == 0) { 520ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten //logWriter->logTimestamp(newTs); 52197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (oldTsValid) { 52297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten time_t sec = newTs.tv_sec - oldTs.tv_sec; 52397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long nsec = newTs.tv_nsec - oldTs.tv_nsec; 52480b3273cea8660fe8a5868d024d2788a1e083ffcGlenn Kasten ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0), 52580b3273cea8660fe8a5868d024d2788a1e083ffcGlenn Kasten "clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld", 52680b3273cea8660fe8a5868d024d2788a1e083ffcGlenn Kasten oldTs.tv_sec, oldTs.tv_nsec, newTs.tv_sec, newTs.tv_nsec); 52797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (nsec < 0) { 52897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten --sec; 52997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten nsec += 1000000000; 53097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 531288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // To avoid an initial underrun on fast tracks after exiting standby, 532288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // do not start pulling data from tracks and mixing until warmup is complete. 533288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // Warmup is considered complete after the earlier of: 534eb15716b59020f342df62bce5b293f0603b94861Glenn Kasten // MIN_WARMUP_CYCLES write() attempts and last one blocks for at least warmupNs 535288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // MAX_WARMUP_CYCLES write() attempts. 536288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten // This is overly conservative, but to get better accuracy requires a new HAL API. 537288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten if (!isWarm && attemptedWrite) { 538288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten measuredWarmupTs.tv_sec += sec; 539288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten measuredWarmupTs.tv_nsec += nsec; 540288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten if (measuredWarmupTs.tv_nsec >= 1000000000) { 541288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten measuredWarmupTs.tv_sec++; 542288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten measuredWarmupTs.tv_nsec -= 1000000000; 543288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 544288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten ++warmupCycles; 545eb15716b59020f342df62bce5b293f0603b94861Glenn Kasten if ((nsec > warmupNs && warmupCycles >= MIN_WARMUP_CYCLES) || 546288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten (warmupCycles >= MAX_WARMUP_CYCLES)) { 547288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten isWarm = true; 548288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten dumpState->mMeasuredWarmupTs = measuredWarmupTs; 549288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten dumpState->mWarmupCycles = warmupCycles; 550288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 551288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten } 552972af221ae7253e406e0e1ea853e56a3010ed6b1Glenn Kasten sleepNs = -1; 5533d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (isWarm) { 5543d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (sec > 0 || nsec > underrunNs) { 5553d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten ATRACE_NAME("underrun"); 55697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME only log occasionally 5573d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten ALOGV("underrun: time since last cycle %d.%03ld sec", 55897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (int) sec, nsec / 1000000L); 5593d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten dumpState->mUnderruns++; 5603d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten ignoreNextOverrun = true; 5613d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } else if (nsec < overrunNs) { 5623d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (ignoreNextOverrun) { 5633d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten ignoreNextOverrun = false; 5643d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } else { 5653d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // FIXME only log occasionally 5663d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten ALOGV("overrun: time since last cycle %d.%03ld sec", 5673d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten (int) sec, nsec / 1000000L); 5683d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten dumpState->mOverruns++; 5693d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } 5703d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // This forces a minimum cycle time. It: 5713d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // - compensates for an audio HAL with jitter due to sample rate conversion 5723d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // - works with a variable buffer depth audio HAL that never pulls at a 5733d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // rate < than overrunNs per buffer. 5743d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // - recovers from overrun immediately after underrun 5753d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // It doesn't work with a non-blocking audio HAL. 5763d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten sleepNs = forceNs - nsec; 5773d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } else { 5783d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten ignoreNextOverrun = false; 57997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 58097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 58197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 5823d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (isWarm) { 5833d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // advance the FIFO queue bounds 5844182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten size_t i = bounds & (dumpState->mSamplingN - 1); 5853d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten bounds = (bounds & 0xFFFF0000) | ((bounds + 1) & 0xFFFF); 5863d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (full) { 5873d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten bounds += 0x10000; 5884182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten } else if (!(bounds & (dumpState->mSamplingN - 1))) { 5893d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten full = true; 5903d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } 5913d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // compute the delta value of clock_gettime(CLOCK_MONOTONIC) 5923d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten uint32_t monotonicNs = nsec; 5933d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (sec > 0 && sec < 4) { 5943d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten monotonicNs += sec * 1000000000; 5953d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } 5963d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // compute raw CPU load = delta value of clock_gettime(CLOCK_THREAD_CPUTIME_ID) 5973d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten uint32_t loadNs = 0; 5983d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten struct timespec newLoad; 5993d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &newLoad); 6003d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (rc == 0) { 6013d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (oldLoadValid) { 6023d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten sec = newLoad.tv_sec - oldLoad.tv_sec; 6033d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten nsec = newLoad.tv_nsec - oldLoad.tv_nsec; 6043d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (nsec < 0) { 6053d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten --sec; 6063d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten nsec += 1000000000; 6073d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } 6083d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten loadNs = nsec; 6093d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten if (sec > 0 && sec < 4) { 6103d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten loadNs += sec * 1000000000; 6113d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } 6123d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } else { 6133d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // first time through the loop 6143d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten oldLoadValid = true; 61542d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten } 6163d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten oldLoad = newLoad; 61742d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten } 6180a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#ifdef CPU_FREQUENCY_STATISTICS 6193d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // get the absolute value of CPU clock frequency in kHz 6203d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten int cpuNum = sched_getcpu(); 6213d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten uint32_t kHz = tcu.getCpukHz(cpuNum); 6223d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten kHz = (kHz << 4) | (cpuNum & 0xF); 6230a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#endif 6243d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // save values in FIFO queues for dumpsys 6253d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // these stores #1, #2, #3 are not atomic with respect to each other, 6263d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // or with respect to store #4 below 6273d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten dumpState->mMonotonicNs[i] = monotonicNs; 6283d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten dumpState->mLoadNs[i] = loadNs; 6290a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#ifdef CPU_FREQUENCY_STATISTICS 6303d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten dumpState->mCpukHz[i] = kHz; 6310a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#endif 6323d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // this store #4 is not atomic with respect to stores #1, #2, #3 above, but 6333d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten // the newest open & oldest closed halves are atomic with respect to each other 6343d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten dumpState->mBounds = bounds; 6353d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten ATRACE_INT("cycle_ms", monotonicNs / 1000000); 6363d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten ATRACE_INT("load_us", loadNs / 1000); 6373d1982595cb9cb0856841f1f57fbdb4581189e99Glenn Kasten } 63897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 63997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 64097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // first time through the loop 64197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten oldTsValid = true; 64297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = periodNs; 64397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ignoreNextOverrun = true; 64497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 64597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten oldTs = newTs; 64697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 64797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // monotonic clock is broken 64897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten oldTsValid = false; 64997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = periodNs; 65097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 65197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 65242d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten 65397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } // for (;;) 65497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 65597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // never return 'true'; Thread::_threadLoop() locks mutex which can result in priority inversion 65697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} 65797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 6584182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn KastenFastMixerDumpState::FastMixerDumpState( 6594182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten#ifdef FAST_MIXER_STATISTICS 6604182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten uint32_t samplingN 6614182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten#endif 6624182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten ) : 66397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mCommand(FastMixerState::INITIAL), mWriteSequence(0), mFramesWritten(0), 66421e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mNumTracks(0), mWriteErrors(0), mUnderruns(0), mOverruns(0), 6651295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten mSampleRate(0), mFrameCount(0), /* mMeasuredWarmupTs({0, 0}), */ mWarmupCycles(0), 6661295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten mTrackMask(0) 66797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 6684182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten , mSamplingN(0), mBounds(0) 66997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 67097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten{ 671288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten mMeasuredWarmupTs.tv_sec = 0; 672288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten mMeasuredWarmupTs.tv_nsec = 0; 673153b9fe667e6e78e0218ff0159353097428c7657Glenn Kasten#ifdef FAST_MIXER_STATISTICS 6744182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten increaseSamplingN(samplingN); 6754182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten#endif 6764182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten} 6774182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten 6784182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten#ifdef FAST_MIXER_STATISTICS 6794182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kastenvoid FastMixerDumpState::increaseSamplingN(uint32_t samplingN) 6804182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten{ 6814182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) { 6824182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten return; 6834182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten } 6844182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten uint32_t additional = samplingN - mSamplingN; 68542d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten // sample arrays aren't accessed atomically with respect to the bounds, 68642d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten // so clearing reduces chance for dumpsys to read random uninitialized samples 6874182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional); 6884182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten memset(&mLoadNs[mSamplingN], 0, sizeof(mLoadNs[0]) * additional); 6890a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#ifdef CPU_FREQUENCY_STATISTICS 6904182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten memset(&mCpukHz[mSamplingN], 0, sizeof(mCpukHz[0]) * additional); 691153b9fe667e6e78e0218ff0159353097428c7657Glenn Kasten#endif 6924182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten mSamplingN = samplingN; 69397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} 6944182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten#endif 69597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 69697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn KastenFastMixerDumpState::~FastMixerDumpState() 69797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten{ 69897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} 69997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 7001ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten// helper function called by qsort() 7011ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kastenstatic int compare_uint32_t(const void *pa, const void *pb) 7021ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten{ 7031ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten uint32_t a = *(const uint32_t *)pa; 7041ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten uint32_t b = *(const uint32_t *)pb; 7051ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten if (a < b) { 7061ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten return -1; 7071ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten } else if (a > b) { 7081ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten return 1; 7091ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten } else { 7101ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten return 0; 7111ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten } 7121ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten} 7131ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten 7144182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kastenvoid FastMixerDumpState::dump(int fd) const 71597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten{ 716868c0abe9f26852c217bc201b337e72c68f829b8Glenn Kasten if (mCommand == FastMixerState::INITIAL) { 717868c0abe9f26852c217bc201b337e72c68f829b8Glenn Kasten fdprintf(fd, "FastMixer not initialized\n"); 718868c0abe9f26852c217bc201b337e72c68f829b8Glenn Kasten return; 719868c0abe9f26852c217bc201b337e72c68f829b8Glenn Kasten } 72097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#define COMMAND_MAX 32 72197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten char string[COMMAND_MAX]; 72297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten switch (mCommand) { 72397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::INITIAL: 72497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "INITIAL"); 72597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 72697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::HOT_IDLE: 72797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "HOT_IDLE"); 72897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 72997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::COLD_IDLE: 73097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "COLD_IDLE"); 73197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 73297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::EXIT: 73397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "EXIT"); 73497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 73597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::MIX: 73697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "MIX"); 73797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 73897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::WRITE: 73997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "WRITE"); 74097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 74197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::MIX_WRITE: 74297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "MIX_WRITE"); 74397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 74497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten default: 74597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten snprintf(string, COMMAND_MAX, "%d", mCommand); 74697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 74797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 74842d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) + 749288ed2103d96f3aabd7e6bea3c080ab6db164049Glenn Kasten (mMeasuredWarmupTs.tv_nsec / 1000000.0); 75042d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten double mixPeriodSec = (double) mFrameCount / (double) mSampleRate; 75197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fdprintf(fd, "FastMixer command=%s writeSequence=%u framesWritten=%u\n" 75221e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n" 75342d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten " sampleRate=%u frameCount=%u measuredWarmup=%.3g ms, warmupCycles=%u\n" 75442d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten " mixPeriod=%.2f ms\n", 75597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten string, mWriteSequence, mFramesWritten, 75621e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mNumTracks, mWriteErrors, mUnderruns, mOverruns, 75742d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles, 75842d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten mixPeriodSec * 1e3); 75997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 76042d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten // find the interval of valid samples 76142d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten uint32_t bounds = mBounds; 76242d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten uint32_t newestOpen = bounds & 0xFFFF; 76342d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten uint32_t oldestClosed = bounds >> 16; 76442d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten uint32_t n = (newestOpen - oldestClosed) & 0xFFFF; 7654182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten if (n > mSamplingN) { 76642d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten ALOGE("too many samples %u", n); 7674182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten n = mSamplingN; 76842d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten } 76942d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency, 77042d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten // and adjusted CPU load in MHz normalized for CPU clock frequency 7710a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten CentralTendencyStatistics wall, loadNs; 7720a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#ifdef CPU_FREQUENCY_STATISTICS 7730a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten CentralTendencyStatistics kHz, loadMHz; 77442d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten uint32_t previousCpukHz = 0; 7750a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#endif 7761ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten // Assuming a normal distribution for cycle times, three standard deviations on either side of 7771ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten // the mean account for 99.73% of the population. So if we take each tail to be 1/1000 of the 7781ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten // sample set, we get 99.8% combined, or close to three standard deviations. 7791ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten static const uint32_t kTailDenominator = 1000; 7801ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL; 78142d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten // loop over all the samples 7821ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten for (uint32_t j = 0; j < n; ++j) { 7834182c4e2a07e2441fcd5c22eaff0ddfe7f826f61Glenn Kasten size_t i = oldestClosed++ & (mSamplingN - 1); 78442d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten uint32_t wallNs = mMonotonicNs[i]; 7851ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten if (tail != NULL) { 7861ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten tail[j] = wallNs; 7871ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten } 78842d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten wall.sample(wallNs); 78942d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten uint32_t sampleLoadNs = mLoadNs[i]; 79042d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten loadNs.sample(sampleLoadNs); 7910a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#ifdef CPU_FREQUENCY_STATISTICS 7920a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten uint32_t sampleCpukHz = mCpukHz[i]; 793c059bd4246c1b3944965be921e5b334d51cd236cGlenn Kasten // skip bad kHz samples 794c059bd4246c1b3944965be921e5b334d51cd236cGlenn Kasten if ((sampleCpukHz & ~0xF) != 0) { 795c059bd4246c1b3944965be921e5b334d51cd236cGlenn Kasten kHz.sample(sampleCpukHz >> 4); 796c059bd4246c1b3944965be921e5b334d51cd236cGlenn Kasten if (sampleCpukHz == previousCpukHz) { 797c059bd4246c1b3944965be921e5b334d51cd236cGlenn Kasten double megacycles = (double) sampleLoadNs * (double) (sampleCpukHz >> 4) * 1e-12; 798c059bd4246c1b3944965be921e5b334d51cd236cGlenn Kasten double adjMHz = megacycles / mixPeriodSec; // _not_ wallNs * 1e9 799c059bd4246c1b3944965be921e5b334d51cd236cGlenn Kasten loadMHz.sample(adjMHz); 800c059bd4246c1b3944965be921e5b334d51cd236cGlenn Kasten } 80142d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten } 80242d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten previousCpukHz = sampleCpukHz; 8030a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#endif 80442d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten } 80542d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten fdprintf(fd, "Simple moving statistics over last %.1f seconds:\n", wall.n() * mixPeriodSec); 80642d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten fdprintf(fd, " wall clock time in ms per mix cycle:\n" 80742d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", 80842d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6, wall.stddev()*1e-6); 80942d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten fdprintf(fd, " raw CPU load in us per mix cycle:\n" 81042d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", 81142d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, 81242d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten loadNs.stddev()*1e-3); 8130a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#ifdef CPU_FREQUENCY_STATISTICS 81442d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten fdprintf(fd, " CPU clock frequency in MHz:\n" 81542d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", 81642d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); 81742d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten fdprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n" 81842d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", 81942d45cfd0c3d62357a6549c62f535e4d4fe08d91Glenn Kasten loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); 82097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 8211ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten if (tail != NULL) { 8221ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten qsort(tail, n, sizeof(uint32_t), compare_uint32_t); 8231ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten // assume same number of tail samples on each side, left and right 8241ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten uint32_t count = n / kTailDenominator; 8251ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten CentralTendencyStatistics left, right; 8261ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten for (uint32_t i = 0; i < count; ++i) { 8271ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten left.sample(tail[i]); 8281ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten right.sample(tail[n - (i + 1)]); 8291ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten } 8301ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten fdprintf(fd, "Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n" 8311ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n" 8321ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", 8331ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6, 8341ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6, 8351ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten right.stddev()*1e-6); 8361ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten delete[] tail; 8371ab212cf5cfa5b88c801840e11e3191cd10f48e4Glenn Kasten } 8380a14c4ce1a41bc09eb7855fa531a3af629a69139Glenn Kasten#endif 8391295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten // The active track mask and track states are updated non-atomically. 8401295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten // So if we relied on isActive to decide whether to display, 8411295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten // then we might display an obsolete track or omit an active track. 8421295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten // Instead we always display all tracks, with an indication 8431295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten // of whether we think the track is active. 8441295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten uint32_t trackMask = mTrackMask; 8451295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten fdprintf(fd, "Fast tracks: kMaxFastTracks=%u activeMask=%#x\n", 8461295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten FastMixerState::kMaxFastTracks, trackMask); 8471295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten fdprintf(fd, "Index Active Full Partial Empty Recent Ready\n"); 8481295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) { 8491295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten bool isActive = trackMask & 1; 8501295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten const FastTrackDump *ftDump = &mTracks[i]; 8511295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten const FastTrackUnderruns& underruns = ftDump->mUnderruns; 8521295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten const char *mostRecent; 8531295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten switch (underruns.mBitFields.mMostRecent) { 8541295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten case UNDERRUN_FULL: 8551295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten mostRecent = "full"; 8561295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten break; 8571295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten case UNDERRUN_PARTIAL: 8581295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten mostRecent = "partial"; 8591295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten break; 8601295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten case UNDERRUN_EMPTY: 8611295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten mostRecent = "empty"; 8621295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten break; 8631295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten default: 8641295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten mostRecent = "?"; 8651295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten break; 8661295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten } 8671295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten fdprintf(fd, "%5u %6s %4u %7u %5u %7s %5u\n", i, isActive ? "yes" : "no", 8681295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten (underruns.mBitFields.mFull) & UNDERRUN_MASK, 8691295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten (underruns.mBitFields.mPartial) & UNDERRUN_MASK, 8701295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten (underruns.mBitFields.mEmpty) & UNDERRUN_MASK, 8711295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten mostRecent, ftDump->mFramesReady); 8721295bb4dcff7b29c75cd23746816df12a871d72cGlenn Kasten } 87397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} 87497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 87597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} // namespace android 876