The problem is due to a too big difference between the buffer size used at the hardware interface and at the A2DP interface.
When no resampling occurs we don't notice problems but the timing is very tight. As soon as resampling is activated, the AudioTrack underruns.
This is because the AudioTrack buffers are not resized when moving the AudioTrack from hardware to A2DP output.
The AudioTrack buffers are calculated based on a hardware output buffer size of 3072 bytes. Which is much less than the A2DP output buffer size (10240).
The solution consists in creating new tracks with new buffers in AudioFlinger when the A2DP output is opened
instead of just transfering active tracks from hardware output mixer thread to the new A2DP output mixer thread.
To avoid synchronization issues between mixer threads and client processes, this is done by invalidating tracks
by setting a flag in their control block and having AudioTrack release the handle on this track (IAudioTrack)
and create a new IAudioTrack when this flag is detected next time obtainBuffer() or start() is executed.
AudioFlinger modifications:
- invalidate the tracks when setStreamOutput() is called
- make sure that notifications of output opening/closing and change of stream type to output mapping are sent synchronously to client process.
This is necessary so that AudioSystem has the new stream to output mapping when the AudioTrack detects the invalidate flag in the client process.
Previously their were sent when the corresponding thread loop was executed.
AudioTrack modifications:
- move frame count calculation and verification from set() to createTrack() so that is is updated every time a new IAudioTrack is created.
- detect track invalidate flag in obtainBuffer() and start() and create a new IAudioTrack.
AudioTrackShared modifications
- group all flags (out, flowControlFlag, forceReady...) into a single bit filed to save space.
Change-Id: I9ac26b6192230627d35084e1449640caaf7d56ee
Some variables and structure members should be renamed to reflect the fact that they contain the
number of channels in a track (channel count) or the actual channels used by a track (channel mask).
Especially member "channels" of track control block (struct audio_track_cblk_t) is actually the
number of channels (channels count).
Change-Id: I220c8dede9fc00c8a5693389e790073b6ed307b8
There is a bug in the way notification client list is managed when the client binder
interface dies that makes that the dead client is not removed from the list: the week
reference passed by binderDied() cannot be promoted and compared to the strong
references in the list.
The fix consists in creating a new NotificationClient class that implements the
binder DeathRecipient and holds a strong reference to the IAudioFlingerClient interface.
A new instance of this class is created for each cient and a strong reference to this
object is added to the notification client list maintained by AudioFlinger.
When binderDied() is called on this object, it is removed from the list preventing
AudioFlinger to notify this client for further io changes.
Also added code to disable LifeVibes effects when the client that has enabled the
enhancements dies.
Change-Id: Icedc4af171759e9ae9a575d82d44784b4e8267e8
Added getRenderPosition() API to IAudioFlinger to retreive number of audio frames
written by AudioFlinger to audio HAL and by DSP to DAC.
Added getRenderPosition() API to AudioHardwareInterface to retreive number of audio frames
written by DSP to DAC.
Exposed AudioTrack::getPosition() to AudioSink() to make it available to media player.
Removed excessive log in AudioHardwareGeneric.
Modified AudioService.getActiveStreamType() so that STREAM_VOICE_CALL is selected when a track using this stream
type is playing.
Chanded isMusicActive() for a more generic isStreamActive(stream) method in AudioSystem, IAudioFlinger and AudioFlinger.
Modified AudioFlinger duplicating output thread so that audio tracks are not mixed until both outputs (A2DP and hardware) have exited standby mode. This avoids to have one output far ahead of the other and audio frames dropped because the compensation mechanism cannot keep up.
Also calculate the maximum wait time in OutputTrack::write() based the on smallest frame count of all output threads instead of the frame count of the thread the OutputTrack is connected to. This avoids starving the thread with the smallest frame count by waiting too long on the other thread.
Since the frame count was reduced on hardware output to reduce latency the difference between A2DP and hardware outputs frame counts had become problematic.
Also increased the number of overflow buffers to cope with bigger timing differences among outputs.
Fixed AudioFlinger::openInput() broken in change ddb78e7753be03937ad57ce7c3c842c52bdad65e
so that an invalid IO handle (0) is returned in case of failure.
Applied the same correction to openOutput().
Modified RecordThread start procedure so that a failure occuring during the first read from audio input stream is detected and causes
the record start to fail.
Modified RecordThread stop procedure to make sure that audio input stream fd is closed before we exit the stop function.
Fixed AudioRecord JAVA and JNI implementation to take status of native AudioRecord::start() into account
and not change mRecordingState to RECORDSTATE_RECORDING if start fails.
This is a second attempt to fix the audio routed to earpiece syndrom.
The root cause identified this time is the crash of an application having an active AudioTrack playing on the VOICE_CALL stream type.
When this happens, the AudioTrack destructor is not called and the audio policy manager is not notified of the track stop.
Results a situation where the VOICE_CALL stream is considered as always in use by audio policy manager which makes that audio is routed to earpiece.
The fix consists in moving the track start/stop/close notification to audio policiy manager from AudioTrack to AudioFlinger Track objet.
The net result is that in the case of a client application crash, the AudioFlinger TrackHandle object (which implements the remote side of the IAudioTrack binder interface) destructor is called which in turn destroys the Track object and we can notify the audio policy manager of the track stop and removal.
The same modification is made for AudioRecord although no bug related to record has been reported yet.
Also fixed a potential problem if record stop is called while the record thread is exiting.
This change goes with a kernel driver change that reduces the audio buffer size from 4800 bytes (~27ms) to 3072 bytes (~17ms).
- The AudioFlinger modifcations in change 0bca68cfff161abbc992fec82dc7c88079dd1a36 have been removed: the short sleep period was counter productive when the AudioTrack is using the call back thread as it causes to many preemptions.
- AudioFlinger mixer thread now detects long standby exit time and in this case anticipates start by writing 0s as soon as a track is enabled even if not ready for mixing.
- AudioTrack::start() is modified to start call back thread before starting the IAudioTrack so that thread startup time is masked by IAudioTrack start and mixer thread wakeup time.
Added setVoiceVolume() method to AudioSystem, AudioFlinger, IAudioFlinger, AudioPolicyService.
Removed call to AudioHardwareInterface::setVoiceVolume() from AudioFlinger::setStreamVolume().
This change is a complement to the main fix in kernel driver for the same issue (partner change #1250).
It removes clicks sometimes heard after the end of the tones while audio flinger is sending 0s to the audio output stream.
The problem was that the sleep time between two writes was more than the duration of one audio output stream buffer which could cause some underrun.
Also fixed a recent regression in ToneGenerator that made that the end of previous tone was repeated at the beginning of current one under certain timing circumstances when the maximum tone duration was specified.
The fix consists in locking AudioFlinger::mLock mutex in the TrackBase destructor before clearing the strong pointer to the shared memory client. The mutex is not locked in removeclient() any more which implies that we must make sure that the Client destructor is always called from the TrackBase destructor or that we hold the mLock mutex before calling deleting the Client.
The problem comes from the fact that when the duplicated output is closed after BT headset disconnection, the OUTPUT_CLOSED notification is not sent to AudioSystem. Then the mapping between notification stream and duplicated output cached in AudioSystem is not cleared and next time a notification is played, the duplicated output is selected and the createTrack() request is refused by AudioFlinger as the selected output doesn't exist.
The notification is ignored by AudioFlinger because when it is sent by the terminating playback thread, the thread has already been removed from the playback thread list.
The fix consists in sending the notification in closeOutput() and not when exiting the playback thread.
The same fix is applied to record threads.
This is because the AudioFlinger duplicating thread is closed while the output tracks are still active. This cause the output tracks objects to be destroyed at a time where they can be in use by the destination output mixer.
The fix consists in adding the OutputTrack to the track list (mTracks) of its destination thread so that a strong reference is help during the mixer processed and the track is detroyed only when safe by destination thread.
Also added detection of problems when creating the output track (e.g. no more tracks in mixer). In this case the output track is not added to output track list of duplicating thread.
The BT headset detection now makes the difference between car kits and headsets, which can be used by audio policy manager.
The headset connection is also detected earlier, that is when the headset is connected and not when the SCO socket is connected as it was the case before. This allows the audio policy manager to suspend A2DP output while ringing if a SCO headset is connected.
The function checkForNewParameters_l() is called with the ThreadBase mutex mLock locked. In the case where the parameter change implies
an audio parameter modification (e.g. sampling rate) the function sendConfigEvent() is called which tries to lock mLock creating a deadlock.
The fix consists in creating a function equivalent to sendConfigEvent() that must be called with mLock locked and does not lock mLock.
Also added the possibility to have more than one set parameter request pending.
Use integers instead of void* as input/output handles at IAudioFlinger and IAudioPolicyService interfaces.
AudioFlinger maintains an always increasing count of opened inputs or outputs as unique ID.
Initial commit for review.
Integrated comments after patch set 1 review.
Fixed lockup in AudioFlinger::ThreadBase::exit()
Fixed lockup when playing tone with AudioPlocyService startTone()
This change is the first part of a fix for issue 1846343, :
- Added new enum values for input sources in AudioRecord and MediaRecorder for voice uplink, downlink and uplink+downlink sources.
- renamed streamType to inputSource in all native functions handling audio record.
A second change is required in opencore author driver and android audio input to completely fix the issue.
AudioTrack, AudioRecord:
- remove useless mAudioFlinger member of AudioTrack and AudioRecord.
- signal cblk.cv condition in stop() method to speed up stop completion.
- extend wait condition timeout in obtainBuffer() when waitCount is -1 to avoid waking up callback thread unnecessarily
AudioFlinger:
- remove some warnings in AudioFlinger.cpp.
- remove function AudioFlinger::MixerThread::removetrack_l() as its content is never executed.
- remove useless call to setMasterVolume in AudioFlinger::handleForcedSpeakerRoute().
- Offset VOICE_CALL stream volume to reflect actual volume that is never 0 in hardware (this fix has been made in the open source): 0.01 + v * 0.99.
AudioSystem.java:
- correct typo in comment
IAudioflinger, IAudioFlingerClient:
- make AudioFlinger binder interfaces used for callbacks ONEWAY.
AudioHardwareInterface:
- correct routeStrings[] table in AudioHardwareInteface.cpp