diff options
Diffstat (limited to 'services/audioflinger')
-rw-r--r-- | services/audioflinger/Android.mk | 13 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 2 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 107 | ||||
-rw-r--r-- | services/audioflinger/Threads.h | 3 | ||||
-rw-r--r-- | services/audioflinger/Tracks.cpp | 17 | ||||
-rw-r--r-- | services/audioflinger/tests/Android.mk | 23 |
6 files changed, 126 insertions, 39 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index 697fb37..f3290c6 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -23,6 +23,12 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) +# Clang++ aborts on AudioMixer.cpp, +# b/18373866, "do not know how to split this operator." +ifeq ($(filter $(TARGET_ARCH),arm arm64),$(TARGET_ARCH)) + LOCAL_CLANG := false +endif + LOCAL_SRC_FILES:= \ AudioFlinger.cpp \ Threads.cpp \ @@ -68,13 +74,6 @@ LOCAL_SRC_FILES += FastCapture.cpp FastCaptureState.cpp LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"' -# Define ANDROID_SMP appropriately. Used to get inline tracing fast-path. -ifeq ($(TARGET_CPU_SMP),true) - LOCAL_CFLAGS += -DANDROID_SMP=1 -else - LOCAL_CFLAGS += -DANDROID_SMP=0 -endif - LOCAL_CFLAGS += -fvisibility=hidden include $(BUILD_SHARED_LIBRARY) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 115b60c..a17a49e 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1191,7 +1191,7 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) mNotificationClients.add(pid, notificationClient); - sp<IBinder> binder = client->asBinder(); + sp<IBinder> binder = IInterface::asBinder(client); binder->linkToDeath(notificationClient); clientAdded = true; } diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 6b9da83..aef1844 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -314,6 +314,64 @@ void CpuStats::sample(const String8 &title // ThreadBase // ---------------------------------------------------------------------------- +// static +const char *AudioFlinger::ThreadBase::threadTypeToString(AudioFlinger::ThreadBase::type_t type) +{ + switch (type) { + case MIXER: + return "MIXER"; + case DIRECT: + return "DIRECT"; + case DUPLICATING: + return "DUPLICATING"; + case RECORD: + return "RECORD"; + case OFFLOAD: + return "OFFLOAD"; + default: + return "unknown"; + } +} + +static String8 outputFlagsToString(audio_output_flags_t flags) +{ + static const struct mapping { + audio_output_flags_t mFlag; + const char * mString; + } mappings[] = { + AUDIO_OUTPUT_FLAG_DIRECT, "DIRECT", + AUDIO_OUTPUT_FLAG_PRIMARY, "PRIMARY", + AUDIO_OUTPUT_FLAG_FAST, "FAST", + AUDIO_OUTPUT_FLAG_DEEP_BUFFER, "DEEP_BUFFER", + AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, "COMPRESS_OFFLOAAD", + AUDIO_OUTPUT_FLAG_NON_BLOCKING, "NON_BLOCKING", + AUDIO_OUTPUT_FLAG_HW_AV_SYNC, "HW_AV_SYNC", + AUDIO_OUTPUT_FLAG_NONE, "NONE", // must be last + }; + String8 result; + audio_output_flags_t allFlags = AUDIO_OUTPUT_FLAG_NONE; + const mapping *entry; + for (entry = mappings; entry->mFlag != AUDIO_OUTPUT_FLAG_NONE; entry++) { + allFlags = (audio_output_flags_t) (allFlags | entry->mFlag); + if (flags & entry->mFlag) { + if (!result.isEmpty()) { + result.append("|"); + } + result.append(entry->mString); + } + } + if (flags & ~allFlags) { + if (!result.isEmpty()) { + result.append("|"); + } + result.appendFormat("0x%X", flags & ~allFlags); + } + if (result.isEmpty()) { + result.append(entry->mString); + } + return result; +} + AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, audio_devices_t outDevice, audio_devices_t inDevice, type_t type) : Thread(false /*canCallJava*/), @@ -338,7 +396,7 @@ AudioFlinger::ThreadBase::~ThreadBase() // do not lock the mutex in destructor releaseWakeLock_l(); if (mPowerManager != 0) { - sp<IBinder> binder = mPowerManager->asBinder(); + sp<IBinder> binder = IInterface::asBinder(mPowerManager); binder->unlinkToDeath(mDeathRecipient); } } @@ -577,20 +635,21 @@ void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args __u bool locked = AudioFlinger::dumpTryLock(mLock); if (!locked) { - dprintf(fd, "thread %p maybe dead locked\n", this); + dprintf(fd, "thread %p may be deadlocked\n", this); } 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, " Sample rate: %u Hz\n", mSampleRate); dprintf(fd, " HAL frame count: %zu\n", mFrameCount); + dprintf(fd, " HAL format: 0x%x (%s)\n", mHALFormat, formatToString(mHALFormat)); 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, + dprintf(fd, " Channel count: %u\n", mChannelCount); + dprintf(fd, " Channel mask: 0x%08x (%s)\n", mChannelMask, channelMaskToString(mChannelMask, mType != RECORD).string()); - dprintf(fd, " Format: 0x%x (%s)\n", mHALFormat, formatToString(mHALFormat)); - dprintf(fd, " Frame size: %zu\n", mFrameSize); + dprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat)); + dprintf(fd, " Frame size: %zu bytes\n", mFrameSize); dprintf(fd, " Pending config events:"); size_t numConfig = mConfigEvents.size(); if (numConfig) { @@ -1317,7 +1376,7 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args) { - dprintf(fd, "\nOutput thread %p:\n", this); + dprintf(fd, "\nOutput thread %p type %d (%s):\n", this, type(), threadTypeToString(type())); 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); @@ -1328,6 +1387,10 @@ void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& dprintf(fd, " Mixer buffer: %p\n", mMixerBuffer); dprintf(fd, " Effect buffer: %p\n", mEffectBuffer); dprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask); + AudioStreamOut *output = mOutput; + audio_output_flags_t flags = output != NULL ? output->flags : AUDIO_OUTPUT_FLAG_NONE; + String8 flagsAsString = outputFlagsToString(flags); + dprintf(fd, " AudioStreamOut: %p flags %#x (%s)\n", output, flags, flagsAsString.string()); dumpBase(fd, args); } @@ -2620,7 +2683,9 @@ bool AudioFlinger::PlaybackThread::threadLoop() } } else { + ATRACE_BEGIN("sleep"); usleep(sleepTime); + ATRACE_END(); } } @@ -2820,6 +2885,7 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud NBAIO_Format format = mOutputSink->format(); NBAIO_Format origformat = format; // adjust format to match that of the Fast Mixer + ALOGV("format changed from %d to %d", format.mFormat, fastMixerFormat); format.mFormat = fastMixerFormat; format.mFrameSize = audio_bytes_per_sample(format.mFormat) * format.mChannelCount; @@ -3383,6 +3449,23 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac } size_t framesReady = track->framesReady(); + if (ATRACE_ENABLED()) { + // I wish we had formatted trace names + char traceName[16]; + strcpy(traceName, "nRdy"); + int name = track->name(); + if (AudioMixer::TRACK0 <= name && + name < (int) (AudioMixer::TRACK0 + AudioMixer::MAX_NUM_TRACKS)) { + name -= AudioMixer::TRACK0; + traceName[4] = (name / 10) + '0'; + traceName[5] = (name % 10) + '0'; + } else { + traceName[4] = '?'; + traceName[5] = '?'; + } + traceName[6] = '\0'; + ATRACE_INT(traceName, framesReady); + } if ((framesReady >= minFrames) && track->isReady() && !track->isPaused() && !track->isTerminated()) { @@ -4661,7 +4744,11 @@ void AudioFlinger::DuplicatingThread::threadLoop_mix() if (outputsReady(outputTracks)) { mAudioMixer->process(AudioBufferProvider::kInvalidPTS); } else { - memset(mSinkBuffer, 0, mSinkBufferSize); + if (mMixerBufferValid) { + memset(mMixerBuffer, 0, mMixerBufferSize); + } else { + memset(mSinkBuffer, 0, mSinkBufferSize); + } } sleepTime = 0; writeFrames = mNormalFrameCount; @@ -5029,7 +5116,9 @@ reacquire_wakelock: // sleep with mutex unlocked if (sleepUs > 0) { + ATRACE_BEGIN("sleep"); usleep(sleepUs); + ATRACE_END(); sleepUs = 0; } diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index bb9aa18..bcdb0e5 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -32,6 +32,8 @@ public: OFFLOAD // Thread class is OffloadThread }; + static const char *threadTypeToString(type_t type); + ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, audio_devices_t outDevice, audio_devices_t inDevice, type_t type); virtual ~ThreadBase(); @@ -406,6 +408,7 @@ protected: audio_channel_mask_t mChannelMask; uint32_t mChannelCount; size_t mFrameSize; + // not HAL frame size, this is for output sink (to pipe to fast mixer) audio_format_t mFormat; // Source format for Recording and // Sink format for Playback. // Sink format may be different than diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 7d8d4c8..6ce2d42 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -611,15 +611,16 @@ status_t AudioFlinger::PlaybackThread::Track::getNextBuffer( // ExtendedAudioBufferProvider interface -// Note that framesReady() takes a mutex on the control block using tryLock(). -// This could result in priority inversion if framesReady() is called by the normal mixer, -// as the normal mixer thread runs at lower -// priority than the client's callback thread: there is a short window within framesReady() -// during which the normal mixer could be preempted, and the client callback would block. -// Another problem can occur if framesReady() is called by the fast mixer: -// the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer. -// FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue. +// framesReady() may return an approximation of the number of frames if called +// from a different thread than the one calling Proxy->obtainBuffer() and +// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the +// AudioTrackServerProxy so be especially careful calling with FastTracks. size_t AudioFlinger::PlaybackThread::Track::framesReady() const { + if (mSharedBuffer != 0 && (isStopped() || isStopping())) { + // Static tracks return zero frames immediately upon stopping (for FastTracks). + // The remainder of the buffer is not drained. + return 0; + } return mAudioTrackServerProxy->framesReady(); } diff --git a/services/audioflinger/tests/Android.mk b/services/audioflinger/tests/Android.mk index 7bba05b..8604ef5 100644 --- a/services/audioflinger/tests/Android.mk +++ b/services/audioflinger/tests/Android.mk @@ -10,19 +10,10 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libutils \ libcutils \ - libstlport \ libaudioutils \ libaudioresampler -LOCAL_STATIC_LIBRARIES := \ - libgtest \ - libgtest_main - LOCAL_C_INCLUDES := \ - bionic \ - bionic/libstdc++/include \ - external/gtest/include \ - external/stlport/stlport \ $(call include-path-for, audio-utils) \ frameworks/av/services/audioflinger @@ -32,21 +23,24 @@ LOCAL_SRC_FILES := \ LOCAL_MODULE := resampler_tests LOCAL_MODULE_TAGS := tests -include $(BUILD_EXECUTABLE) +include $(BUILD_NATIVE_TEST) # # audio mixer test tool # include $(CLEAR_VARS) +# Clang++ aborts on AudioMixer.cpp, +# b/18373866, "do not know how to split this operator." +ifeq ($(filter $(TARGET_ARCH),arm arm64),$(TARGET_ARCH)) + LOCAL_CLANG := false +endif + LOCAL_SRC_FILES:= \ test-mixer.cpp \ ../AudioMixer.cpp.arm \ LOCAL_C_INCLUDES := \ - bionic \ - bionic/libstdc++/include \ - external/stlport/stlport \ $(call include-path-for, audio-effects) \ $(call include-path-for, audio-utils) \ frameworks/av/services/audioflinger @@ -55,7 +49,6 @@ LOCAL_STATIC_LIBRARIES := \ libsndfile LOCAL_SHARED_LIBRARIES := \ - libstlport \ libeffects \ libnbaio \ libcommon_time_client \ @@ -70,4 +63,6 @@ LOCAL_MODULE:= test-mixer LOCAL_MODULE_TAGS := optional +LOCAL_CXX_STL := libc++ + include $(BUILD_EXECUTABLE) |