I am trying to do some customization for Audio output on Android
platform. I am trying to use openmax backend to get a bunch of audio
data and flush it into AudioFlinger to playback. This works fine to get
audio output on speaker and wired headphone/headset. However, it fails
every often to bluetooth headset. Audio output switching from speaker to
bluetooth headset could not be done at all sometimes.
Here is how I do the test. When I have some music played back with
speaker, I will press "power" button on my bluetooth headset to enable
bluetooth A2DP connection(I have had bluetooth headset paired with my
phone). Audio will keep output to speaker. The switching fails.
I have an instance of AudioTrack in my openmax player and I am using
AudioTrack::write() to flush data to AudioFlinger. The
AudioTrack::write() function will be called in a thread my own player
crated. The write function is non-block and I just simply put it into
and infinite loop. I guess this problem casued by some asynchronous
callings between my player and AudioTrack or AudioFlinger, but I cannot
prove it. I got these log in NG cases:
=======================================================================
D/A2dpAudioInterface( 80): A2dpAudioStreamOut::set 80, 0, 0, 0
D/A2dpAudioInterface( 80): A2dpAudioStreamOut::openOutputStream A2dpOut returns NO_ERROR
D/A2dpAudioInterface( 80): setBluetoothEnabled 1
V/AudioFlinger( 80): openOutput() openOutputStream returned output 0x55230, SamplingRate 44100, Format 1, Channels c, status 0
V/AudioFlinger( 80): openOutput() created mixer output: ID 7 thread 0x42f50
V/AudioFlinger( 80): PlaybackThread::audioConfigChanged_l, thread 0x42f50, event 0, param 0
V/BluetoothEventManager( 276): Received android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED
D/CachedBluetoothDevice( 276): onProfileStateChanged: profile A2DP newProfileState 2
I/AudioFlinger( 80): AudioFlinger's thread 0x42f50 ready to run
V/AudioFlinger( 80): Audio hardware entering standby, mixer 0x42f50, mSuspended 0
V/AudioFlinger( 80): MixerThread 0x42f50 TID 649 going to sleep
V/AudioFlinger( 80): Track constructor name 4096, calling thread 117
V/AudioFlinger( 80): OutputTrack constructor mCblk 0x4b4d0, mBuffer 0x4b510, mCblk->buffers 0x4b510, mCblk->frameCount 7680, mCblk->sampleRate 44100, mCblk->channelCount 2 mBufferEnd 0x52d10
V/AudioFlinger( 80): addOutputTrack() track 0x54178, on thread 0x42f50
V/AudioFlinger( 80): Track constructor name 4098, calling thread 117
V/AudioFlinger( 80): OutputTrack constructor mCblk 0x56760, mBuffer 0x567a0, mCblk->buffers 0x567a0, mCblk->frameCount 7680,
mCblk->sampleRate 44100, mCblk->channelCount 2 mBufferEnd 0x5dfa0
V/AudioFlinger( 80): addOutputTrack() track 0x553d8, on thread 0x38918
V/AudioFlinger( 80): PlaybackThread::audioConfigChanged_l, thread 0x562f0, event 0, param 0
V/AudioFlinger( 80): setParameters(): io 7, keyvalue a2dp_sink_address=00:1F:82:2A:5F:F2, tid 111, calling tid 80
V/AudioFlinger( 80): ThreadBase::setParameters() a2dp_sink_address=00:1F:82:2A:5F:F2
D/A2DP ( 80): bluetooth_init
D/A2DP ( 80): finished bluetooth_init
I/AudioFlinger( 80): AudioFlinger's thread 0x562f0 ready to run
V/AudioFlinger( 80): MixerThread 0x42f50 TID 649 waking up
D/A2DP ( 80): set_command 1
D/A2DP ( 80): a2dp thread New state command signaled.
V/AudioFlinger( 80): stop(4096), calling thread 80
V/AudioFlinger( 80): stop(4098), calling thread 80
V/AudioFlinger( 80): DuplicatingThread 0x562f0 TID 650 going to sleep
V/AudioFlinger( 80): setStreamOutput() stream 0 to output 7
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 0, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x562f0, streamType 0, mTracks.size 0
V/AudioFlinger( 80): setStreamOutput() stream 6 to output 7
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 6, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x562f0, streamType 6, mTracks.size 0
V/AudioFlinger( 80): setStreamOutput() stream 2 to output 8
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 2, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x42f50, streamType 2, mTracks.size 1
V/AudioFlinger( 80): setStreamOutput() stream 4 to output 8
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 4, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x42f50, streamType 4, mTracks.size 1
V/AudioFlinger( 80): setStreamOutput() stream 5 to output 8
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 5, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x42f50, streamType 5, mTracks.size 1
V/AudioFlinger( 80): setStreamOutput() stream 7 to output 8
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 7, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x42f50, streamType 7, mTracks.size 1
V/AudioFlinger( 80): setStreamOutput() stream 1 to output 7
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 1, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x562f0, streamType 1, mTracks.size 0
V/AudioFlinger( 80): setStreamOutput() stream 3 to output 7
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 3, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x562f0, streamType 3, mTracks.size 0
V/AudioFlinger( 80): setStreamOutput() stream 9 to output 7
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 9, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x562f0, streamType 9, mTracks.size 0
V/AudioFlinger( 80): setStreamOutput() stream 8 to output 7
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x38918, streamType 8, mTracks.size 3
V/AudioFlinger( 80): MixerThread::invalidateTracks() mixer 0x562f0, streamType 8, mTracks.size 0
W/AudioTrack( 570): dead IAudioTrack, creating a new one from obtainBuffer()
V/AudioFlinger( 80): createTrack() sessionId: 6
V/AudioFlinger( 80): createTrack() lSessionId: 6
V/AudioFlinger( 80): Track constructor name 4099, calling thread 570
V/AudioFlinger( 80): setParameters(): io 0, keyvalue
A2dpSuspended=false, tid 114, calling tid 117
I/BluetoothDeviceProfileState( 117): Entering ACL Connected state with: 102
V/AudioFlinger( 80): start(4099), calling thread 570 session 6
V/AudioFlinger( 80): ? => ACTIVE (4099) on thread 0x56678
V/AudioFlinger( 80): mWaitWorkCV.broadcast
=======================================================================
Could you please explain how AudioFlinger handle such kind of switching?
How could my player communicate with AudioFlinger? Do I have to use
IBinder for it? Thank you!
/Adam