diff options
Diffstat (limited to 'services/audioflinger')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 33 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 3 | ||||
-rw-r--r-- | services/audioflinger/AudioMixer.h | 4 | ||||
-rw-r--r-- | services/audioflinger/AudioWatchdog.cpp | 2 | ||||
-rw-r--r-- | services/audioflinger/Effects.h | 1 | ||||
-rw-r--r-- | services/audioflinger/FastMixer.cpp | 75 | ||||
-rw-r--r-- | services/audioflinger/FastMixer.h | 8 | ||||
-rw-r--r-- | services/audioflinger/FastMixerState.h | 6 | ||||
-rw-r--r-- | services/audioflinger/FastThread.cpp | 7 | ||||
-rw-r--r-- | services/audioflinger/PlaybackTracks.h | 2 | ||||
-rw-r--r-- | services/audioflinger/StateQueue.cpp | 4 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 127 | ||||
-rw-r--r-- | services/audioflinger/Threads.h | 2 | ||||
-rw-r--r-- | services/audioflinger/TrackBase.h | 9 | ||||
-rw-r--r-- | services/audioflinger/Tracks.cpp | 56 |
15 files changed, 193 insertions, 146 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 45e17f8..9bd0e9b 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -143,7 +143,7 @@ static int load_audio_interface(const char *if_name, audio_hw_device_t **dev) if (rc) { goto out; } - if ((*dev)->common.version != AUDIO_DEVICE_API_VERSION_CURRENT) { + if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) { ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version); rc = BAD_VALUE; goto out; @@ -427,7 +427,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) if (mLogMemoryDealer != 0) { sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log")); if (binder != 0) { - fdprintf(fd, "\nmedia.log:\n"); + dprintf(fd, "\nmedia.log:\n"); Vector<String16> args; binder->dump(fd, args); } @@ -635,8 +635,12 @@ sp<IAudioTrack> AudioFlinger::createTrack( if (lStatus != NO_ERROR) { // remove local strong reference to Client before deleting the Track so that the // Client destructor is called by the TrackBase destructor with mClientLock held - Mutex::Autolock _cl(mClientLock); - client.clear(); + // Don't hold mClientLock when releasing the reference on the track as the + // destructor will acquire it. + { + Mutex::Autolock _cl(mClientLock); + client.clear(); + } track.clear(); goto Exit; } @@ -1173,7 +1177,7 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) } // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the - // ThreadBase mutex and teh locknig order is ThreadBase::mLock then AudioFlinger::mClientLock. + // ThreadBase mutex and the locking order is ThreadBase::mLock then AudioFlinger::mClientLock. if (clientAdded) { // the config change is always sent from playback or record threads to avoid deadlock // with AudioSystem::gLock @@ -1419,8 +1423,12 @@ sp<IAudioRecord> AudioFlinger::openRecord( if (lStatus != NO_ERROR) { // remove local strong reference to Client before deleting the RecordTrack so that the // Client destructor is called by the TrackBase destructor with mClientLock held - Mutex::Autolock _cl(mClientLock); - client.clear(); + // Don't hold mClientLock when releasing the reference on the track as the + // destructor will acquire it. + { + Mutex::Autolock _cl(mClientLock); + client.clear(); + } recordTrack.clear(); goto Exit; } @@ -2380,6 +2388,11 @@ sp<IEffect> AudioFlinger::createEffect( if (handle != 0 && id != NULL) { *id = handle->id(); } + if (handle == 0) { + // remove local strong reference to Client with mClientLock held + Mutex::Autolock _cl(mClientLock); + client.clear(); + } } Exit: @@ -2590,7 +2603,7 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand } } else { if (fd >= 0) { - fdprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno)); + dprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno)); } } char teeTime[16]; @@ -2644,11 +2657,11 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand write(teeFd, &temp, sizeof(temp)); close(teeFd); if (fd >= 0) { - fdprintf(fd, "tee copied to %s\n", teePath); + dprintf(fd, "tee copied to %s\n", teePath); } } else { if (fd >= 0) { - fdprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno)); + dprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno)); } } } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index d69d6a2..d2ded9a 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -82,9 +82,6 @@ class ServerProxy; static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3); -#define MAX_GAIN 4096.0f -#define MAX_GAIN_INT 0x1000 - #define INCLUDING_FROM_AUDIOFLINGER_H class AudioFlinger : diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h index eca9848..573ba96 100644 --- a/services/audioflinger/AudioMixer.h +++ b/services/audioflinger/AudioMixer.h @@ -30,6 +30,9 @@ #include <system/audio.h> #include <media/nbaio/NBLog.h> +// FIXME This is actually unity gain, which might not be max in future, expressed in U.12 +#define MAX_GAIN_INT AudioMixer::UNITY_GAIN + namespace android { // ---------------------------------------------------------------------------- @@ -91,6 +94,7 @@ public: REMOVE = 0x4102, // Remove the sample rate converter on this track name; // the track is restored to the mix sample rate. // for target RAMP_VOLUME and VOLUME (8 channels max) + // FIXME use float for these 3 to improve the dynamic range VOLUME0 = 0x4200, VOLUME1 = 0x4201, AUXLEVEL = 0x4210, diff --git a/services/audioflinger/AudioWatchdog.cpp b/services/audioflinger/AudioWatchdog.cpp index 93d185e..877e776 100644 --- a/services/audioflinger/AudioWatchdog.cpp +++ b/services/audioflinger/AudioWatchdog.cpp @@ -34,7 +34,7 @@ void AudioWatchdogDump::dump(int fd) } else { strcpy(buf, "N/A\n"); } - fdprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s", + dprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s", mUnderruns, mLogs, buf); } diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h index ccc4825..4170fd4 100644 --- a/services/audioflinger/Effects.h +++ b/services/audioflinger/Effects.h @@ -270,6 +270,7 @@ public: sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor); sp<EffectModule> getEffectFromId_l(int id); sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type); + // FIXME use float to improve the dynamic range bool setVolume_l(uint32_t *left, uint32_t *right); void setDevice_l(audio_devices_t device); void setMode_l(audio_mode_t mode); diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp index f7cc8aa..f0ce902 100644 --- a/services/audioflinger/FastMixer.cpp +++ b/services/audioflinger/FastMixer.cpp @@ -26,7 +26,6 @@ #define ATRACE_TAG ATRACE_TAG_AUDIO #include "Configuration.h" -#include <sys/atomics.h> #include <time.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -256,9 +255,9 @@ void FastMixer::onStateChange() mixer->setBufferProvider(name, bufferProvider); if (fastTrack->mVolumeProvider == NULL) { mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, - (void *)0x1000); + (void *) MAX_GAIN_INT); mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, - (void *)0x1000); + (void *) MAX_GAIN_INT); } mixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::REMOVE, NULL); @@ -313,11 +312,13 @@ void FastMixer::onWork() int name = fastTrackNames[i]; ALOG_ASSERT(name >= 0); if (fastTrack->mVolumeProvider != NULL) { - uint32_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); + gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, - (void *)(uintptr_t)(vlr & 0xFFFF)); + (void *) (uintptr_t) + (float_from_gain(gain_minifloat_unpack_left(vlr)) * MAX_GAIN_INT)); mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, - (void *)(uintptr_t)(vlr >> 16)); + (void *) (uintptr_t) + (float_from_gain(gain_minifloat_unpack_right(vlr)) * MAX_GAIN_INT)); } // FIXME The current implementation of framesReady() for fast tracks // takes a tryLock, which can block @@ -464,7 +465,7 @@ static int compare_uint32_t(const void *pa, const void *pb) void FastMixerDumpState::dump(int fd) const { if (mCommand == FastMixerState::INITIAL) { - fdprintf(fd, " FastMixer not initialized\n"); + dprintf(fd, " FastMixer not initialized\n"); return; } #define COMMAND_MAX 32 @@ -498,10 +499,10 @@ void FastMixerDumpState::dump(int fd) const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) + (mMeasuredWarmupTs.tv_nsec / 1000000.0); double mixPeriodSec = (double) mFrameCount / (double) mSampleRate; - fdprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n" - " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n" - " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n" - " mixPeriod=%.2f ms\n", + dprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n" + " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n" + " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n" + " mixPeriod=%.2f ms\n", string, mWriteSequence, mFramesWritten, mNumTracks, mWriteErrors, mUnderruns, mOverruns, mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles, @@ -553,26 +554,26 @@ void FastMixerDumpState::dump(int fd) const #endif } if (n) { - fdprintf(fd, " Simple moving statistics over last %.1f seconds:\n", - wall.n() * mixPeriodSec); - fdprintf(fd, " wall clock time in ms per mix cycle:\n" - " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", - wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6, - wall.stddev()*1e-6); - fdprintf(fd, " raw CPU load in us per mix cycle:\n" - " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", - loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, - loadNs.stddev()*1e-3); + dprintf(fd, " Simple moving statistics over last %.1f seconds:\n", + wall.n() * mixPeriodSec); + dprintf(fd, " wall clock time in ms per mix cycle:\n" + " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", + wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6, + wall.stddev()*1e-6); + dprintf(fd, " raw CPU load in us per mix cycle:\n" + " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", + loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, + loadNs.stddev()*1e-3); } else { - fdprintf(fd, " No FastMixer statistics available currently\n"); + dprintf(fd, " No FastMixer statistics available currently\n"); } #ifdef CPU_FREQUENCY_STATISTICS - fdprintf(fd, " CPU clock frequency in MHz:\n" - " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", - kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); - fdprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n" - " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", - loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); + dprintf(fd, " CPU clock frequency in MHz:\n" + " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", + kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); + dprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n" + " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", + loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); #endif if (tail != NULL) { qsort(tail, n, sizeof(uint32_t), compare_uint32_t); @@ -583,12 +584,12 @@ void FastMixerDumpState::dump(int fd) const left.sample(tail[i]); right.sample(tail[n - (i + 1)]); } - fdprintf(fd, " Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n" - " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n" - " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", - left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6, - right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6, - right.stddev()*1e-6); + dprintf(fd, " Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n" + " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n" + " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", + left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6, + right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6, + right.stddev()*1e-6); delete[] tail; } #endif @@ -598,9 +599,9 @@ void FastMixerDumpState::dump(int fd) const // Instead we always display all tracks, with an indication // of whether we think the track is active. uint32_t trackMask = mTrackMask; - fdprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n", + dprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n", FastMixerState::kMaxFastTracks, trackMask); - fdprintf(fd, " Index Active Full Partial Empty Recent Ready\n"); + dprintf(fd, " Index Active Full Partial Empty Recent Ready\n"); for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) { bool isActive = trackMask & 1; const FastTrackDump *ftDump = &mTracks[i]; @@ -620,7 +621,7 @@ void FastMixerDumpState::dump(int fd) const mostRecent = "?"; break; } - fdprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no", + dprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no", (underruns.mBitFields.mFull) & UNDERRUN_MASK, (underruns.mBitFields.mPartial) & UNDERRUN_MASK, (underruns.mBitFields.mEmpty) & UNDERRUN_MASK, diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h index 981c1a7..db89ef4 100644 --- a/services/audioflinger/FastMixer.h +++ b/services/audioflinger/FastMixer.h @@ -17,13 +17,11 @@ #ifndef ANDROID_AUDIO_FAST_MIXER_H #define ANDROID_AUDIO_FAST_MIXER_H +#include <linux/futex.h> +#include <sys/syscall.h> #include <utils/Debug.h> -#if 1 // FIXME move to where used -extern "C" { -#include "../private/bionic_futex.h" -} -#endif #include "FastThread.h" +#include <utils/Thread.h> #include "StateQueue.h" #include "FastMixerState.h" #include "FastMixerDumpState.h" diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/FastMixerState.h index cb54ff1..661c9ca 100644 --- a/services/audioflinger/FastMixerState.h +++ b/services/audioflinger/FastMixerState.h @@ -17,6 +17,7 @@ #ifndef ANDROID_AUDIO_FAST_MIXER_STATE_H #define ANDROID_AUDIO_FAST_MIXER_STATE_H +#include <audio_utils/minifloat.h> #include <system/audio.h> #include <media/ExtendedAudioBufferProvider.h> #include <media/nbaio/NBAIO.h> @@ -29,9 +30,8 @@ struct FastMixerDumpState; class VolumeProvider { public: - // Return the track volume in U4_12 format: left in lower half, right in upper half. The - // provider implementation is responsible for validating that the return value is in range. - virtual uint32_t getVolumeLR() = 0; + // The provider implementation is responsible for validating that the return value is in range. + virtual gain_minifloat_packed_t getVolumeLR() = 0; protected: VolumeProvider() { } virtual ~VolumeProvider() { } diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp index 8a216b3..216dace 100644 --- a/services/audioflinger/FastThread.cpp +++ b/services/audioflinger/FastThread.cpp @@ -20,10 +20,9 @@ #define ATRACE_TAG ATRACE_TAG_AUDIO #include "Configuration.h" +#include <linux/futex.h> +#include <sys/syscall.h> #include <utils/Log.h> -extern "C" { -#include "../private/bionic_futex.h" -} #include <utils/Trace.h> #include "FastThread.h" @@ -157,7 +156,7 @@ bool FastThread::threadLoop() ALOG_ASSERT(coldFutexAddr != NULL); int32_t old = android_atomic_dec(coldFutexAddr); if (old <= 0) { - __futex_syscall4(coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL); + syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL); } int policy = sched_getscheduler(0); if (!(policy == SCHED_FIFO || policy == SCHED_RR)) { diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 08b1728..6f1f293 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -65,7 +65,7 @@ public: void signal(); // implement FastMixerState::VolumeProvider interface - virtual uint32_t getVolumeLR(); + virtual gain_minifloat_packed_t getVolumeLR(); virtual status_t setSyncEvent(const sp<SyncEvent>& event); diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp index 48399c0..7e01c9f 100644 --- a/services/audioflinger/StateQueue.cpp +++ b/services/audioflinger/StateQueue.cpp @@ -28,12 +28,12 @@ namespace android { #ifdef STATE_QUEUE_DUMP void StateQueueObserverDump::dump(int fd) { - fdprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges); + dprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges); } void StateQueueMutatorDump::dump(int fd) { - fdprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n", + dprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n", mPushDirty, mPushAck, mBlockedSequence); } #endif diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 0a18433..7843387 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -35,6 +35,7 @@ #include <audio_effects/effect_aec.h> #include <audio_utils/primitives.h> #include <audio_utils/format.h> +#include <audio_utils/minifloat.h> // NBAIO implementations #include <media/nbaio/AudioStreamOutSink.h> @@ -504,30 +505,30 @@ void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args __u bool locked = AudioFlinger::dumpTryLock(mLock); if (!locked) { - fdprintf(fd, "thread %p maybe dead locked\n", this); + dprintf(fd, "thread %p maybe dead locked\n", this); } - fdprintf(fd, " I/O handle: %d\n", mId); - fdprintf(fd, " TID: %d\n", getTid()); - fdprintf(fd, " Standby: %s\n", mStandby ? "yes" : "no"); - fdprintf(fd, " Sample rate: %u\n", mSampleRate); - fdprintf(fd, " HAL frame count: %zu\n", mFrameCount); - fdprintf(fd, " HAL buffer size: %u bytes\n", mBufferSize); - fdprintf(fd, " Channel Count: %u\n", mChannelCount); - fdprintf(fd, " Channel Mask: 0x%08x (%s)\n", mChannelMask, + dprintf(fd, " I/O handle: %d\n", mId); + dprintf(fd, " TID: %d\n", getTid()); + dprintf(fd, " Standby: %s\n", mStandby ? "yes" : "no"); + dprintf(fd, " Sample rate: %u\n", mSampleRate); + dprintf(fd, " HAL frame count: %zu\n", mFrameCount); + dprintf(fd, " HAL buffer size: %u bytes\n", mBufferSize); + dprintf(fd, " Channel Count: %u\n", mChannelCount); + dprintf(fd, " Channel Mask: 0x%08x (%s)\n", mChannelMask, channelMaskToString(mChannelMask, mType != RECORD).string()); - fdprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat)); - fdprintf(fd, " Frame size: %zu\n", mFrameSize); - fdprintf(fd, " Pending config events:"); + dprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat)); + dprintf(fd, " Frame size: %zu\n", mFrameSize); + dprintf(fd, " Pending config events:"); size_t numConfig = mConfigEvents.size(); if (numConfig) { for (size_t i = 0; i < numConfig; i++) { mConfigEvents[i]->dump(buffer, SIZE); - fdprintf(fd, "\n %s", buffer); + dprintf(fd, "\n %s", buffer); } - fdprintf(fd, "\n"); + dprintf(fd, "\n"); } else { - fdprintf(fd, " none\n"); + dprintf(fd, " none\n"); } if (locked) { @@ -1190,15 +1191,15 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar // These values are "raw"; they will wrap around. See prepareTracks_l() for a better way. FastTrackUnderruns underruns = getFastTrackUnderruns(0); - fdprintf(fd, " Normal mixer raw underrun counters: partial=%u empty=%u\n", + dprintf(fd, " Normal mixer raw underrun counters: partial=%u empty=%u\n", underruns.mBitFields.mPartial, underruns.mBitFields.mEmpty); size_t numtracks = mTracks.size(); size_t numactive = mActiveTracks.size(); - fdprintf(fd, " %d Tracks", numtracks); + dprintf(fd, " %d Tracks", numtracks); size_t numactiveseen = 0; if (numtracks) { - fdprintf(fd, " of which %d are active\n", numactive); + dprintf(fd, " of which %d are active\n", numactive); Track::appendDumpHeader(result); for (size_t i = 0; i < numtracks; ++i) { sp<Track> track = mTracks[i]; @@ -1230,22 +1231,21 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar } write(fd, result.string(), result.size()); - } void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args) { - fdprintf(fd, "\nOutput thread %p:\n", this); - fdprintf(fd, " Normal frame count: %zu\n", mNormalFrameCount); - fdprintf(fd, " Last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime)); - fdprintf(fd, " Total writes: %d\n", mNumWrites); - fdprintf(fd, " Delayed writes: %d\n", mNumDelayedWrites); - fdprintf(fd, " Blocked in write: %s\n", mInWrite ? "yes" : "no"); - fdprintf(fd, " Suspend count: %d\n", mSuspended); - fdprintf(fd, " Sink buffer : %p\n", mSinkBuffer); - fdprintf(fd, " Mixer buffer: %p\n", mMixerBuffer); - fdprintf(fd, " Effect buffer: %p\n", mEffectBuffer); - fdprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask); + dprintf(fd, "\nOutput thread %p:\n", this); + dprintf(fd, " Normal frame count: %zu\n", mNormalFrameCount); + dprintf(fd, " Last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime)); + dprintf(fd, " Total writes: %d\n", mNumWrites); + dprintf(fd, " Delayed writes: %d\n", mNumDelayedWrites); + dprintf(fd, " Blocked in write: %s\n", mInWrite ? "yes" : "no"); + dprintf(fd, " Suspend count: %d\n", mSuspended); + dprintf(fd, " Sink buffer : %p\n", mSinkBuffer); + dprintf(fd, " Mixer buffer: %p\n", mMixerBuffer); + dprintf(fd, " Effect buffer: %p\n", mEffectBuffer); + dprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask); dumpBase(fd, args); } @@ -2753,7 +2753,7 @@ AudioFlinger::MixerThread::~MixerThread() if (state->mCommand == FastMixerState::COLD_IDLE) { int32_t old = android_atomic_inc(&mFastMixerFutex); if (old == -1) { - (void) __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); + (void) syscall(__NR_futex, &mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); } } state->mCommand = FastMixerState::EXIT; @@ -2810,7 +2810,7 @@ ssize_t AudioFlinger::MixerThread::threadLoop_write() if (state->mCommand == FastMixerState::COLD_IDLE) { int32_t old = android_atomic_inc(&mFastMixerFutex); if (old == -1) { - (void) __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); + (void) syscall(__NR_futex, &mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); } #ifdef AUDIO_WATCHDOG if (mAudioWatchdog != 0) { @@ -3258,21 +3258,23 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac float typeVolume = mStreamTypes[track->streamType()].volume; float v = masterVolume * typeVolume; AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy; - uint32_t vlr = proxy->getVolumeLR(); - vl = vlr & 0xFFFF; - vr = vlr >> 16; + gain_minifloat_packed_t vlr = proxy->getVolumeLR(); + float vlf = float_from_gain(gain_minifloat_unpack_left(vlr)); + float vrf = float_from_gain(gain_minifloat_unpack_right(vlr)); // track volumes come from shared memory, so can't be trusted and must be clamped - if (vl > MAX_GAIN_INT) { - ALOGV("Track left volume out of range: %04X", vl); - vl = MAX_GAIN_INT; + if (vlf > GAIN_FLOAT_UNITY) { + ALOGV("Track left volume out of range: %.3g", vlf); + vlf = GAIN_FLOAT_UNITY; } - if (vr > MAX_GAIN_INT) { - ALOGV("Track right volume out of range: %04X", vr); - vr = MAX_GAIN_INT; + if (vrf > GAIN_FLOAT_UNITY) { + ALOGV("Track right volume out of range: %.3g", vrf); + vrf = GAIN_FLOAT_UNITY; } // now apply the master volume and stream type volume - vl = (uint32_t)(v * vl) << 12; - vr = (uint32_t)(v * vr) << 12; + // FIXME we're losing the wonderful dynamic range in the minifloat representation + float v8_24 = v * (MAX_GAIN_INT * MAX_GAIN_INT); + vl = (uint32_t) (v8_24 * vlf); + vr = (uint32_t) (v8_24 * vrf); // assuming master volume and stream type volume each go up to 1.0, // vl and vr are now in 8.24 format @@ -3299,6 +3301,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac track->mHasVolumeController = false; } + // FIXME Use float // Convert volumes from 8.24 to 4.12 format // This additional clamping is needed in case chain->setVolume_l() overshot vl = (vl + (1 << 11)) >> 12; @@ -3674,7 +3677,7 @@ void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& ar PlaybackThread::dumpInternals(fd, args); - fdprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames()); + dprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames()); // Make a non-atomic copy of fast mixer dump state so it won't change underneath us const FastMixerDumpState copy(mFastMixerDumpState); @@ -3755,13 +3758,17 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr float typeVolume = mStreamTypes[track->streamType()].volume; float v = mMasterVolume * typeVolume; AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy; - uint32_t vlr = proxy->getVolumeLR(); - float v_clamped = v * (vlr & 0xFFFF); - if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; - left = v_clamped/MAX_GAIN; - v_clamped = v * (vlr >> 16); - if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; - right = v_clamped/MAX_GAIN; + gain_minifloat_packed_t vlr = proxy->getVolumeLR(); + left = float_from_gain(gain_minifloat_unpack_left(vlr)); + if (left > GAIN_FLOAT_UNITY) { + left = GAIN_FLOAT_UNITY; + } + left *= v; + right = float_from_gain(gain_minifloat_unpack_right(vlr)); + if (right > GAIN_FLOAT_UNITY) { + right = GAIN_FLOAT_UNITY; + } + right *= v; } if (lastTrack) { @@ -4157,7 +4164,10 @@ void AudioFlinger::OffloadThread::threadLoop_exit() mMixerStatus = MIXER_DRAIN_ALL; threadLoop_drain(); } - mCallbackThread->exit(); + if (mUseAsyncWrite) { + ALOG_ASSERT(mCallbackThread != 0); + mCallbackThread->exit(); + } PlaybackThread::threadLoop_exit(); } @@ -5122,6 +5132,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe // to be at least 2 x the record thread frame count and cover audio hardware latency. // This is probably too conservative, but legacy application code may depend on it. // If you change this calculation, also review the start threshold which is related. + // FIXME It's not clear how input latency actually matters. Perhaps this should be 0. uint32_t latencyMs = 50; // FIXME mInput->stream->get_latency(mInput->stream); size_t mNormalFrameCount = 2048; // FIXME uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate); @@ -5354,12 +5365,12 @@ void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& args) { - fdprintf(fd, "\nInput thread %p:\n", this); + dprintf(fd, "\nInput thread %p:\n", this); if (mActiveTracks.size() > 0) { - fdprintf(fd, " Buffer size: %zu bytes\n", mBufferSize); + dprintf(fd, " Buffer size: %zu bytes\n", mBufferSize); } else { - fdprintf(fd, " No active record clients\n"); + dprintf(fd, " No active record clients\n"); } dumpBase(fd, args); @@ -5374,9 +5385,9 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args size_t numtracks = mTracks.size(); size_t numactive = mActiveTracks.size(); size_t numactiveseen = 0; - fdprintf(fd, " %d Tracks", numtracks); + dprintf(fd, " %d Tracks", numtracks); if (numtracks) { - fdprintf(fd, " of which %d are active\n", numactive); + dprintf(fd, " of which %d are active\n", numactive); RecordTrack::appendDumpHeader(result); for (size_t i = 0; i < numtracks ; ++i) { sp<RecordTrack> track = mTracks[i]; @@ -5390,7 +5401,7 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args } } } else { - fdprintf(fd, "\n"); + dprintf(fd, "\n"); } if (numactiveseen != numactive) { diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 1b01512..44008e5 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -301,6 +301,8 @@ public: // If a thread does not have such a heap, this method returns 0. virtual sp<MemoryDealer> readOnlyHeap() const { return 0; } + virtual sp<IMemory> pipeMemory() const { return 0; } + mutable Mutex mLock; protected: diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h index 5f13be3..4cba3fd 100644 --- a/services/audioflinger/TrackBase.h +++ b/services/audioflinger/TrackBase.h @@ -39,6 +39,13 @@ public: STARTING_2, // for RecordTrack only }; + // where to allocate the data buffer + enum alloc_type { + ALLOC_CBLK, // allocate immediately after control block + ALLOC_READONLY, // allocate from a separate read-only heap per thread + ALLOC_PIPE, // do not allocate; use the pipe buffer + }; + TrackBase(ThreadBase *thread, const sp<Client>& client, uint32_t sampleRate, @@ -50,7 +57,7 @@ public: int uid, IAudioFlinger::track_flags_t flags, bool isOut, - bool useReadOnlyHeap = false); + alloc_type alloc = ALLOC_CBLK); virtual ~TrackBase(); virtual status_t initCheck() const { return getCblk() != 0 ? NO_ERROR : NO_MEMORY; } diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 222ec53..7ddc71c 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -21,6 +21,7 @@ #include "Configuration.h" #include <math.h> +#include <sys/syscall.h> #include <utils/Log.h> #include <private/media/AudioTrackShared.h> @@ -34,6 +35,7 @@ #include <media/nbaio/Pipe.h> #include <media/nbaio/PipeReader.h> +#include <audio_utils/minifloat.h> // ---------------------------------------------------------------------------- @@ -71,7 +73,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( int clientUid, IAudioFlinger::track_flags_t flags, bool isOut, - bool useReadOnlyHeap) + alloc_type alloc) : RefBase(), mThread(thread), mClient(client), @@ -115,7 +117,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); size_t size = sizeof(audio_track_cblk_t); size_t bufferSize = (sharedBuffer == 0 ? roundup(frameCount) : frameCount) * mFrameSize; - if (sharedBuffer == 0 && !useReadOnlyHeap) { + if (sharedBuffer == 0 && alloc == ALLOC_CBLK) { size += bufferSize; } @@ -137,7 +139,8 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // construct the shared structure in-place. if (mCblk != NULL) { new(mCblk) audio_track_cblk_t(); - if (useReadOnlyHeap) { + switch (alloc) { + case ALLOC_READONLY: { const sp<MemoryDealer> roHeap(thread->readOnlyHeap()); if (roHeap == 0 || (mBufferMemory = roHeap->allocate(bufferSize)) == 0 || @@ -151,7 +154,17 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( return; } memset(mBuffer, 0, bufferSize); - } else { + } break; + case ALLOC_PIPE: + mBufferMemory = thread->pipeMemory(); + // mBuffer is the virtual address as seen from current process (mediaserver), + // and should normally be coming from mBufferMemory->pointer(). + // However in this case the TrackBase does not reference the buffer directly. + // It should references the buffer via the pipe. + // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL. + mBuffer = NULL; + break; + case ALLOC_CBLK: // clear all buffers if (sharedBuffer == 0) { mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); @@ -162,6 +175,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic #endif } + break; } #ifdef TEE_SINK @@ -461,7 +475,7 @@ void AudioFlinger::PlaybackThread::Track::destroy() void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool active) { - uint32_t vlr = mAudioTrackServerProxy->getVolumeLR(); + gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR(); if (isFastTrack()) { sprintf(buffer, " F %2d", mFastIndex); } else if (mName >= AudioMixer::TRACK0) { @@ -534,8 +548,8 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool a stateChar, mFillingUpStatus, mAudioTrackServerProxy->getSampleRate(), - 20.0 * log10((vlr & 0xFFFF) / 4096.0), - 20.0 * log10((vlr >> 16) / 4096.0), + 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))), + 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))), mCblk->mServer, mMainBuffer, mAuxBuffer, @@ -961,27 +975,27 @@ void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_ // implement VolumeBufferProvider interface -uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR() +gain_minifloat_packed_t AudioFlinger::PlaybackThread::Track::getVolumeLR() { // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs ALOG_ASSERT(isFastTrack() && (mCblk != NULL)); - uint32_t vlr = mAudioTrackServerProxy->getVolumeLR(); - uint32_t vl = vlr & 0xFFFF; - uint32_t vr = vlr >> 16; + gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR(); + float vl = float_from_gain(gain_minifloat_unpack_left(vlr)); + float vr = float_from_gain(gain_minifloat_unpack_right(vlr)); // track volumes come from shared memory, so can't be trusted and must be clamped - if (vl > MAX_GAIN_INT) { - vl = MAX_GAIN_INT; + if (vl > GAIN_FLOAT_UNITY) { + vl = GAIN_FLOAT_UNITY; } - if (vr > MAX_GAIN_INT) { - vr = MAX_GAIN_INT; + if (vr > GAIN_FLOAT_UNITY) { + vr = GAIN_FLOAT_UNITY; } // now apply the cached master volume and stream type volume; // this is trusted but lacks any synchronization or barrier so may be stale float v = mCachedVolume; vl *= v; vr *= v; - // re-combine into U4.16 - vlr = (vr << 16) | (vl & 0xFFFF); + // re-combine into packed minifloat + vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr)); // FIXME look at mute, pause, and stop flags return vlr; } @@ -1007,7 +1021,7 @@ void AudioFlinger::PlaybackThread::Track::invalidate() android_atomic_or(CBLK_INVALID, &cblk->mFlags); android_atomic_release_store(0x40000000, &cblk->mFutex); // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE - (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX); + (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX); mIsInvalid = true; } @@ -1592,7 +1606,7 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( // since client and server are in the same process, // the buffer has the same virtual address on both sides mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize); - mClientProxy->setVolumeLR((uint32_t(uint16_t(0x1000)) << 16) | uint16_t(0x1000)); + mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY); mClientProxy->setSendLevel(0.0); mClientProxy->setSampleRate(sampleRate); mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize, @@ -1840,7 +1854,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, flags, false /*isOut*/, - (flags & IAudioFlinger::TRACK_FAST) != 0 /*useReadOnlyHeap*/), + (flags & IAudioFlinger::TRACK_FAST) != 0 ? ALLOC_READONLY : ALLOC_CBLK), mOverflow(false), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpOutFrameCount(0), // See real initialization of mRsmpInFront at RecordThread::start() mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL) @@ -1936,7 +1950,7 @@ void AudioFlinger::RecordThread::RecordTrack::invalidate() android_atomic_or(CBLK_INVALID, &cblk->mFlags); android_atomic_release_store(0x40000000, &cblk->mFutex); // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE - (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX); + (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX); } |