From 72e3f39146fce4686bd96f11057c051bea376dfb Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 20 May 2015 14:43:50 -0700 Subject: audio flinger: do not call JAVA services until system is ready Wait for system ready indication form AudioService before enabling calls to scheduling service or power manager. Bug: 11520969. Change-Id: I221927394f4a08fd86c9d457e55dd0e07949f0cf --- include/media/AudioSystem.h | 3 ++ include/media/IAudioFlinger.h | 3 ++ media/libmedia/AudioSystem.cpp | 7 +++ media/libmedia/IAudioFlinger.cpp | 14 +++++- services/audioflinger/AudioFlinger.cpp | 34 +++++++++++--- services/audioflinger/AudioFlinger.h | 4 ++ services/audioflinger/Threads.cpp | 83 ++++++++++++++++++++-------------- services/audioflinger/Threads.h | 31 +++++++++---- 8 files changed, 128 insertions(+), 51 deletions(-) diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 3241e9c..26cffa6 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -158,6 +158,9 @@ public: // or no HW sync source is used. static audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId); + // Indicate JAVA services are ready (scheduling, power management ...) + static status_t systemReady(); + // Events used to synchronize actions between audio sessions. // For instance SYNC_EVENT_PRESENTATION_COMPLETE can be used to delay recording start until // playback is complete on another audio session. diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index 3f7fd09..5051aff 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -243,6 +243,9 @@ public: /* Get the HW synchronization source used for an audio session */ virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) = 0; + + /* Indicate JAVA services are ready (scheduling, power management ...) */ + virtual status_t systemReady() = 0; }; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 4c2e77b..6c2c226 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -423,6 +423,13 @@ audio_hw_sync_t AudioSystem::getAudioHwSyncForSession(audio_session_t sessionId) return af->getAudioHwSyncForSession(sessionId); } +status_t AudioSystem::systemReady() +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return NO_INIT; + return af->systemReady(); +} + // --------------------------------------------------------------------------- diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index d722fe9..a3f014b 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -80,7 +80,8 @@ enum { RELEASE_AUDIO_PATCH, LIST_AUDIO_PATCHES, SET_AUDIO_PORT_CONFIG, - GET_AUDIO_HW_SYNC + GET_AUDIO_HW_SYNC, + SYSTEM_READY }; #define MAX_ITEMS_PER_LIST 1024 @@ -903,6 +904,12 @@ public: } return (audio_hw_sync_t)reply.readInt32(); } + virtual status_t systemReady() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + return remote()->transact(SYSTEM_READY, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -1396,6 +1403,11 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32(getAudioHwSyncForSession((audio_session_t)data.readInt32())); return NO_ERROR; } break; + case SYSTEM_READY: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + systemReady(); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 93b1642..52fce34 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -181,7 +181,8 @@ AudioFlinger::AudioFlinger() mIsLowRamDevice(true), mIsDeviceTypeKnown(false), mGlobalEffectEnableTime(0), - mPrimaryOutputSampleRate(0) + mPrimaryOutputSampleRate(0), + mSystemReady(false) { getpid_cached = getpid(); char value[PROPERTY_VALUE_MAX]; @@ -1722,6 +1723,26 @@ audio_hw_sync_t AudioFlinger::getAudioHwSyncForSession(audio_session_t sessionId return (audio_hw_sync_t)value; } +status_t AudioFlinger::systemReady() +{ + Mutex::Autolock _l(mLock); + ALOGI("%s", __FUNCTION__); + if (mSystemReady) { + ALOGW("%s called twice", __FUNCTION__); + return NO_ERROR; + } + mSystemReady = true; + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + ThreadBase *thread = (ThreadBase *)mPlaybackThreads.valueAt(i).get(); + thread->systemReady(); + } + for (size_t i = 0; i < mRecordThreads.size(); i++) { + ThreadBase *thread = (ThreadBase *)mRecordThreads.valueAt(i).get(); + thread->systemReady(); + } + return NO_ERROR; +} + // setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId) { @@ -1794,15 +1815,15 @@ sp AudioFlinger::openOutput_l(audio_module_handle_ PlaybackThread *thread; if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { - thread = new OffloadThread(this, outputStream, *output, devices); + thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread); } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || !isValidPcmSinkFormat(config->format) || !isValidPcmSinkChannelMask(config->channel_mask)) { - thread = new DirectOutputThread(this, outputStream, *output, devices); + thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created direct output: ID %d thread %p", *output, thread); } else { - thread = new MixerThread(this, outputStream, *output, devices); + thread = new MixerThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created mixer output: ID %d thread %p", *output, thread); } mPlaybackThreads.add(*output, thread); @@ -1873,7 +1894,7 @@ audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1, } audio_io_handle_t id = nextUniqueId(); - DuplicatingThread *thread = new DuplicatingThread(this, thread1, id); + DuplicatingThread *thread = new DuplicatingThread(this, thread1, id, mSystemReady); thread->addOutputTrack(thread2); mPlaybackThreads.add(id, thread); // notify client processes of the new output creation @@ -2120,7 +2141,8 @@ sp AudioFlinger::openInput_l(audio_module_handle_t m inputStream, *input, primaryOutputDevice_l(), - devices + devices, + mSystemReady #ifdef TEE_SINK , teeSink #endif diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 51b2610..73590ae 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -257,6 +257,9 @@ public: /* Get the HW synchronization source used for an audio session */ virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId); + /* Indicate JAVA services are ready (scheduling, power management ...) */ + virtual status_t systemReady(); + virtual status_t onTransact( uint32_t code, const Parcel& data, @@ -752,6 +755,7 @@ private: uint32_t mPrimaryOutputSampleRate; // sample rate of the primary output, or zero if none // protected by mHardwareLock + bool mSystemReady; }; #undef INCLUDING_FROM_AUDIOFLINGER_H diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 594ed05..1ed4e18 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -487,7 +487,7 @@ const char *sourceToString(audio_source_t source) } AudioFlinger::ThreadBase::ThreadBase(const sp& audioFlinger, audio_io_handle_t id, - audio_devices_t outDevice, audio_devices_t inDevice, type_t type) + audio_devices_t outDevice, audio_devices_t inDevice, type_t type, bool systemReady) : Thread(false /*canCallJava*/), mType(type), mAudioFlinger(audioFlinger), @@ -498,7 +498,8 @@ AudioFlinger::ThreadBase::ThreadBase(const sp& audioFlinger, audio mStandby(false), mOutDevice(outDevice), mInDevice(inDevice), mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), // mName will be set by concrete (non-virtual) subclass - mDeathRecipient(new PMDeathRecipient(this)) + mDeathRecipient(new PMDeathRecipient(this)), + mSystemReady(systemReady) { memset(&mPatch, 0, sizeof(struct audio_patch)); } @@ -567,6 +568,11 @@ status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp& event) { status_t status = NO_ERROR; + if (event->mRequiresSystemReady && !mSystemReady) { + event->mWaitStatus = false; + mPendingConfigEvents.add(event); + return status; + } mConfigEvents.add(event); ALOGV("sendConfigEvent_l() num events %d event %d", mConfigEvents.size(), event->mType); mWaitWorkCV.signal(); @@ -598,6 +604,12 @@ void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event) sendConfigEvent_l(configEvent); } +void AudioFlinger::ThreadBase::sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio) +{ + Mutex::Autolock _l(mLock); + sendPrioConfigEvent_l(pid, tid, prio); +} + // sendPrioConfigEvent_l() must be called with ThreadBase::mLock held void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio) { @@ -880,8 +892,7 @@ void AudioFlinger::ThreadBase::updateWakeLockUids(const SortedVector &uids) } void AudioFlinger::ThreadBase::getPowerManager_l() { - - if (mPowerManager == 0) { + if (mSystemReady && mPowerManager == 0) { // use checkService() to avoid blocking if power service is not up yet sp binder = defaultServiceManager()->checkService(String16("power")); @@ -895,7 +906,6 @@ void AudioFlinger::ThreadBase::getPowerManager_l() { } void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector &uids) { - getPowerManager_l(); if (mWakeLockToken == NULL) { ALOGE("no wake lock to update!"); @@ -1337,6 +1347,20 @@ void AudioFlinger::ThreadBase::getAudioPortConfig(struct audio_port_config *conf AUDIO_PORT_CONFIG_FORMAT; } +void AudioFlinger::ThreadBase::systemReady() +{ + Mutex::Autolock _l(mLock); + if (mSystemReady) { + return; + } + mSystemReady = true; + + for (size_t i = 0; i < mPendingConfigEvents.size(); i++) { + sendConfigEvent_l(mPendingConfigEvents.editItemAt(i)); + } + mPendingConfigEvents.clear(); +} + // ---------------------------------------------------------------------------- // Playback @@ -1346,8 +1370,9 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp& audioFlinge AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, - type_t type) - : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type), + type_t type, + bool systemReady) + : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady), mNormalFrameCount(0), mSinkBuffer(NULL), mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision), mMixerBuffer(NULL), @@ -3118,8 +3143,8 @@ void AudioFlinger::PlaybackThread::getAudioPortConfig(struct audio_port_config * // ---------------------------------------------------------------------------- AudioFlinger::MixerThread::MixerThread(const sp& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, audio_devices_t device, type_t type) - : PlaybackThread(audioFlinger, output, id, device, type), + audio_io_handle_t id, audio_devices_t device, bool systemReady, type_t type) + : PlaybackThread(audioFlinger, output, id, device, type, systemReady), // mAudioMixer below // mFastMixer below mFastMixerFutex(0) @@ -3252,11 +3277,7 @@ AudioFlinger::MixerThread::MixerThread(const sp& audioFlinger, Aud // start the fast mixer mFastMixer->run("FastMixer", PRIORITY_URGENT_AUDIO); pid_t tid = mFastMixer->getTid(); - int err = requestPriority(getpid_cached, tid, kPriorityFastMixer); - if (err != 0) { - ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", - kPriorityFastMixer, getpid_cached, tid, err); - } + sendPrioConfigEvent(getpid_cached, tid, kPriorityFastMixer); #ifdef AUDIO_WATCHDOG // create and start the watchdog @@ -3264,11 +3285,7 @@ AudioFlinger::MixerThread::MixerThread(const sp& audioFlinger, Aud mAudioWatchdog->setDump(&mAudioWatchdogDump); mAudioWatchdog->run("AudioWatchdog", PRIORITY_URGENT_AUDIO); tid = mAudioWatchdog->getTid(); - err = requestPriority(getpid_cached, tid, kPriorityFastMixer); - if (err != 0) { - ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", - kPriorityFastMixer, getpid_cached, tid, err); - } + sendPrioConfigEvent(getpid_cached, tid, kPriorityFastMixer); #endif } @@ -4294,16 +4311,16 @@ void AudioFlinger::MixerThread::cacheParameters_l() // ---------------------------------------------------------------------------- AudioFlinger::DirectOutputThread::DirectOutputThread(const sp& audioFlinger, - AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device) - : PlaybackThread(audioFlinger, output, id, device, DIRECT) + AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady) + : PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady) // mLeftVolFloat, mRightVolFloat { } AudioFlinger::DirectOutputThread::DirectOutputThread(const sp& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, - ThreadBase::type_t type) - : PlaybackThread(audioFlinger, output, id, device, type) + ThreadBase::type_t type, bool systemReady) + : PlaybackThread(audioFlinger, output, id, device, type, systemReady) // mLeftVolFloat, mRightVolFloat { } @@ -4832,8 +4849,8 @@ void AudioFlinger::AsyncCallbackThread::resetDraining() // ---------------------------------------------------------------------------- AudioFlinger::OffloadThread::OffloadThread(const sp& audioFlinger, - AudioStreamOut* output, audio_io_handle_t id, uint32_t device) - : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD), + AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady) + : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady), mPausedBytesRemaining(0) { //FIXME: mStandby should be set to true by ThreadBase constructor @@ -5110,9 +5127,9 @@ void AudioFlinger::OffloadThread::onAddNewTrack_l() // ---------------------------------------------------------------------------- AudioFlinger::DuplicatingThread::DuplicatingThread(const sp& audioFlinger, - AudioFlinger::MixerThread* mainThread, audio_io_handle_t id) + AudioFlinger::MixerThread* mainThread, audio_io_handle_t id, bool systemReady) : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->outDevice(), - DUPLICATING), + systemReady, DUPLICATING), mWaitTimeMs(UINT_MAX) { addOutputTrack(mainThread); @@ -5292,12 +5309,13 @@ AudioFlinger::RecordThread::RecordThread(const sp& audioFlinger, AudioStreamIn *input, audio_io_handle_t id, audio_devices_t outDevice, - audio_devices_t inDevice + audio_devices_t inDevice, + bool systemReady #ifdef TEE_SINK , const sp& teeSink #endif ) : - ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD), + ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady), mInput(input), mActiveTracksGen(0), mRsmpInBuffer(NULL), // mRsmpInFrames and mRsmpInFramesP2 are set by readInputParameters_l() mRsmpInRear(0) @@ -5416,12 +5434,7 @@ AudioFlinger::RecordThread::RecordThread(const sp& audioFlinger, // start the fast capture mFastCapture->run("FastCapture", ANDROID_PRIORITY_URGENT_AUDIO); pid_t tid = mFastCapture->getTid(); - int err = requestPriority(getpid_cached, tid, kPriorityFastMixer); - if (err != 0) { - ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", - kPriorityFastCapture, getpid_cached, tid, err); - } - + sendPrioConfigEvent(getpid_cached, tid, kPriorityFastMixer); #ifdef AUDIO_WATCHDOG // FIXME #endif diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 37bacae..aa20525 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -35,7 +35,8 @@ public: static const char *threadTypeToString(type_t type); ThreadBase(const sp& audioFlinger, audio_io_handle_t id, - audio_devices_t outDevice, audio_devices_t inDevice, type_t type); + audio_devices_t outDevice, audio_devices_t inDevice, type_t type, + bool systemReady); virtual ~ThreadBase(); virtual status_t readyToRun(); @@ -92,10 +93,13 @@ public: Condition mCond; // condition for status return status_t mStatus; // status communicated to sender bool mWaitStatus; // true if sender is waiting for status + bool mRequiresSystemReady; // true if must wait for system ready to enter event queue sp mData; // event specific parameter data protected: - ConfigEvent(int type) : mType(type), mStatus(NO_ERROR), mWaitStatus(false), mData(NULL) {} + ConfigEvent(int type, bool requiresSystemReady = false) : + mType(type), mStatus(NO_ERROR), mWaitStatus(false), + mRequiresSystemReady(requiresSystemReady), mData(NULL) {} }; class IoConfigEventData : public ConfigEventData { @@ -136,7 +140,7 @@ public: class PrioConfigEvent : public ConfigEvent { public: PrioConfigEvent(pid_t pid, pid_t tid, int32_t prio) : - ConfigEvent(CFG_EVENT_PRIO) { + ConfigEvent(CFG_EVENT_PRIO, true) { mData = new PrioConfigEventData(pid, tid, prio); } virtual ~PrioConfigEvent() {} @@ -258,6 +262,7 @@ public: status_t sendConfigEvent_l(sp& event); void sendIoConfigEvent(audio_io_config_event event); void sendIoConfigEvent_l(audio_io_config_event event); + void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio); void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio); status_t sendSetParameterConfigEvent_l(const String8& keyValuePair); status_t sendCreateAudioPatchConfigEvent(const struct audio_patch *patch, @@ -359,6 +364,8 @@ public: virtual sp pipeMemory() const { return 0; } + void systemReady(); + mutable Mutex mLock; protected: @@ -418,6 +425,7 @@ protected: size_t mBufferSize; // HAL buffer size for read() or write() Vector< sp > mConfigEvents; + Vector< sp > mPendingConfigEvents; // events awaiting system ready // These fields are written and read by thread itself without lock or barrier, // and read by other threads without lock or barrier via standby(), outDevice() @@ -445,6 +453,7 @@ protected: mSuspendedSessions; static const size_t kLogSize = 4 * 1024; sp mNBLogWriter; + bool mSystemReady; }; // --- PlaybackThread --- @@ -470,7 +479,7 @@ public: static const int8_t kMaxTrackRetriesOffload = 20; PlaybackThread(const sp& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, audio_devices_t device, type_t type); + audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady); virtual ~PlaybackThread(); void dump(int fd, const Vector& args); @@ -842,6 +851,7 @@ public: AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, + bool systemReady, type_t type = MIXER); virtual ~MixerThread(); @@ -903,7 +913,7 @@ class DirectOutputThread : public PlaybackThread { public: DirectOutputThread(const sp& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, audio_devices_t device); + audio_io_handle_t id, audio_devices_t device, bool systemReady); virtual ~DirectOutputThread(); // Thread virtuals @@ -933,7 +943,8 @@ protected: float mRightVolFloat; DirectOutputThread(const sp& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, uint32_t device, ThreadBase::type_t type); + audio_io_handle_t id, uint32_t device, ThreadBase::type_t type, + bool systemReady); void processVolume_l(Track *track, bool lastTrack); // prepareTracks_l() tells threadLoop_mix() the name of the single active track @@ -946,7 +957,7 @@ class OffloadThread : public DirectOutputThread { public: OffloadThread(const sp& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, uint32_t device); + audio_io_handle_t id, uint32_t device, bool systemReady); virtual ~OffloadThread() {}; virtual void flushHw_l(); @@ -1001,7 +1012,7 @@ private: class DuplicatingThread : public MixerThread { public: DuplicatingThread(const sp& audioFlinger, MixerThread* mainThread, - audio_io_handle_t id); + audio_io_handle_t id, bool systemReady); virtual ~DuplicatingThread(); // Thread virtuals @@ -1177,7 +1188,8 @@ public: AudioStreamIn *input, audio_io_handle_t id, audio_devices_t outDevice, - audio_devices_t inDevice + audio_devices_t inDevice, + bool systemReady #ifdef TEE_SINK , const sp& teeSink #endif @@ -1294,6 +1306,7 @@ private: // one-time initialization, no locks required sp mFastCapture; // non-0 if there is also // a fast capture + // FIXME audio watchdog thread // contents are not guaranteed to be consistent, no locks required -- cgit v1.1