421ddc014b
This change fixes the stability problems experienced when using a bluetooth headset supporting both A2DP and SCO. Problems occur when starting the video chat at which time the A2DP output is being stopped to start SCO. At that time, active AudioTracks are invalidated by AudioFlinger so that a new AudioTrack binder interface can be recreated by the client process on the new mixer thread with correct parameters. The problem was that the process to restore the binder interface was not protected against concurrent requests which caused 2 binder interfaces to be created sometimes. This could lead to permanent client deadlock if one of the client threads was waiting for a condition of the first created binder interface while the second one was created (as the AudioFlinger would only signal conditions on the last one created). This concurrent request situation is more likely to happen when a client uses the JAVA AudioTrack as the JNI implementation uses simultaneously the native AudioTrack callback and write push mechanisms. By doing so, the code that checks if the binder interface should be restored (in obtainBuffer()) is much more likely to be called concurrently from two different threads. The fix consists in protecting the critical binder interface restore phase with a flag in the AudioTrack control block. The first thread acting upon the binder interface restore request will raise the flag and the second thread will just wait for a condition to be signaled when the restore process is complete. Also protected all accesses to the AudioTrack control block by a mutex to prevent access while the track is being destroyed and restored. If a mutex cannot be held (e.g because we call a callback function), acquire a strong reference on the IAudioTrack to prevent its destruction while the cblk is being accessed. Modified AudioTrack JNI to use GetByteArrayElements() instead of GetPrimitiveArrayCritical() when writing audio buffers. Entering a critical section would cause the JNI to abort if a mediaserver crash occurs during a write due to the AudioSystem callback being called during the critical section when media server process restarts. Anyway with current JNI implementation, either versions do not copy data most of the times and the criticial version does not guaranty no data copy. The same modifications have been made to AudioRecord. Change-Id: Idc5aa711a04c3eee180cdd03f44fe17f3c4dcb52
109 lines
4.5 KiB
C++
109 lines
4.5 KiB
C++
/*
|
|
* Copyright (C) 2007 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef ANDROID_AUDIO_TRACK_SHARED_H
|
|
#define ANDROID_AUDIO_TRACK_SHARED_H
|
|
|
|
#include <stdint.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <utils/threads.h>
|
|
|
|
namespace android {
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#define THREAD_PRIORITY_AUDIO_CLIENT (ANDROID_PRIORITY_AUDIO)
|
|
// Maximum cumulated timeout milliseconds before restarting audioflinger thread
|
|
#define MAX_STARTUP_TIMEOUT_MS 3000 // Longer timeout period at startup to cope with A2DP init time
|
|
#define MAX_RUN_TIMEOUT_MS 1000
|
|
#define WAIT_PERIOD_MS 10
|
|
#define RESTORE_TIMEOUT_MS 5000 // Maximum waiting time for a track to be restored
|
|
|
|
#define CBLK_UNDERRUN_MSK 0x0001
|
|
#define CBLK_UNDERRUN_ON 0x0001 // underrun (out) or overrrun (in) indication
|
|
#define CBLK_UNDERRUN_OFF 0x0000 // no underrun
|
|
#define CBLK_DIRECTION_MSK 0x0002
|
|
#define CBLK_DIRECTION_OUT 0x0002 // this cblk is for an AudioTrack
|
|
#define CBLK_DIRECTION_IN 0x0000 // this cblk is for an AudioRecord
|
|
#define CBLK_FORCEREADY_MSK 0x0004
|
|
#define CBLK_FORCEREADY_ON 0x0004 // track is considered ready immediately by AudioFlinger
|
|
#define CBLK_FORCEREADY_OFF 0x0000 // track is ready when buffer full
|
|
#define CBLK_INVALID_MSK 0x0008
|
|
#define CBLK_INVALID_ON 0x0008 // track buffer is invalidated by AudioFlinger:
|
|
#define CBLK_INVALID_OFF 0x0000 // must be re-created
|
|
#define CBLK_DISABLED_MSK 0x0010
|
|
#define CBLK_DISABLED_ON 0x0010 // track disabled by AudioFlinger due to underrun:
|
|
#define CBLK_DISABLED_OFF 0x0000 // must be re-started
|
|
#define CBLK_RESTORING_MSK 0x0020
|
|
#define CBLK_RESTORING_ON 0x0020 // track is being restored after invalidation
|
|
#define CBLK_RESTORING_OFF 0x0000 // by AudioFlinger
|
|
#define CBLK_RESTORED_MSK 0x0040
|
|
#define CBLK_RESTORED_ON 0x0040 // track has been restored after invalidation
|
|
#define CBLK_RESTORED_OFF 0x0040 // by AudioFlinger
|
|
|
|
struct audio_track_cblk_t
|
|
{
|
|
|
|
// The data members are grouped so that members accessed frequently and in the same context
|
|
// are in the same line of data cache.
|
|
Mutex lock;
|
|
Condition cv;
|
|
volatile uint32_t user;
|
|
volatile uint32_t server;
|
|
uint32_t userBase;
|
|
uint32_t serverBase;
|
|
void* buffers;
|
|
uint32_t frameCount;
|
|
// Cache line boundary
|
|
uint32_t loopStart;
|
|
uint32_t loopEnd;
|
|
int loopCount;
|
|
volatile union {
|
|
uint16_t volume[2];
|
|
uint32_t volumeLR;
|
|
};
|
|
uint32_t sampleRate;
|
|
// NOTE: audio_track_cblk_t::frameSize is not equal to AudioTrack::frameSize() for
|
|
// 8 bit PCM data: in this case, mCblk->frameSize is based on a sample size of
|
|
// 16 bit because data is converted to 16 bit before being stored in buffer
|
|
|
|
uint8_t frameSize;
|
|
uint8_t channelCount;
|
|
uint16_t flags;
|
|
|
|
uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
|
|
uint16_t waitTimeMs; // Cumulated wait time
|
|
|
|
uint16_t sendLevel;
|
|
uint16_t reserved;
|
|
// Cache line boundary (32 bytes)
|
|
audio_track_cblk_t();
|
|
uint32_t stepUser(uint32_t frameCount);
|
|
bool stepServer(uint32_t frameCount);
|
|
void* buffer(uint32_t offset) const;
|
|
uint32_t framesAvailable();
|
|
uint32_t framesAvailable_l();
|
|
uint32_t framesReady();
|
|
};
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
}; // namespace android
|
|
|
|
#endif // ANDROID_AUDIO_TRACK_SHARED_H
|