Merge commit '62174d022b9018d92fc180a576bd12c13681c76e' into eclair-mr2-plus-aosp * commit '62174d022b9018d92fc180a576bd12c13681c76e': Log for issue 2203561.
This commit is contained in:
@@ -459,6 +459,61 @@ status_t AudioPolicyManagerGeneric::getStreamVolumeIndex(AudioSystem::stream_typ
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t AudioPolicyManagerGeneric::dump(int fd)
|
||||||
|
{
|
||||||
|
const size_t SIZE = 256;
|
||||||
|
char buffer[SIZE];
|
||||||
|
String8 result;
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
|
||||||
|
result.append(buffer);
|
||||||
|
write(fd, result.string(), result.size());
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "\nOutputs dump:\n");
|
||||||
|
write(fd, buffer, strlen(buffer));
|
||||||
|
for (size_t i = 0; i < mOutputs.size(); i++) {
|
||||||
|
snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
|
||||||
|
write(fd, buffer, strlen(buffer));
|
||||||
|
mOutputs.valueAt(i)->dump(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "\nInputs dump:\n");
|
||||||
|
write(fd, buffer, strlen(buffer));
|
||||||
|
for (size_t i = 0; i < mInputs.size(); i++) {
|
||||||
|
snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
|
||||||
|
write(fd, buffer, strlen(buffer));
|
||||||
|
mInputs.valueAt(i)->dump(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "\nStreams dump:\n");
|
||||||
|
write(fd, buffer, strlen(buffer));
|
||||||
|
snprintf(buffer, SIZE, " Stream Index Min Index Max Index Cur Mute Count Can be muted\n");
|
||||||
|
write(fd, buffer, strlen(buffer));
|
||||||
|
for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
|
||||||
|
snprintf(buffer, SIZE, " %02d", i);
|
||||||
|
mStreams[i].dump(buffer + 3, SIZE);
|
||||||
|
write(fd, buffer, strlen(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// AudioPolicyManagerGeneric
|
// AudioPolicyManagerGeneric
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -815,6 +870,35 @@ uint32_t AudioPolicyManagerGeneric::AudioOutputDescriptor::refCount()
|
|||||||
return refcount;
|
return refcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t AudioPolicyManagerGeneric::AudioOutputDescriptor::dump(int fd)
|
||||||
|
{
|
||||||
|
const size_t SIZE = 256;
|
||||||
|
char buffer[SIZE];
|
||||||
|
String8 result;
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Format: %d\n", mFormat);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Stream refCount\n");
|
||||||
|
result.append(buffer);
|
||||||
|
for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
|
||||||
|
snprintf(buffer, SIZE, " %02d %d\n", i, mRefCount[i]);
|
||||||
|
result.append(buffer);
|
||||||
|
}
|
||||||
|
write(fd, result.string(), result.size());
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// --- AudioInputDescriptor class implementation
|
// --- AudioInputDescriptor class implementation
|
||||||
|
|
||||||
AudioPolicyManagerGeneric::AudioInputDescriptor::AudioInputDescriptor()
|
AudioPolicyManagerGeneric::AudioInputDescriptor::AudioInputDescriptor()
|
||||||
@@ -823,4 +907,39 @@ AudioPolicyManagerGeneric::AudioInputDescriptor::AudioInputDescriptor()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t AudioPolicyManagerGeneric::AudioInputDescriptor::dump(int fd)
|
||||||
|
{
|
||||||
|
const size_t SIZE = 256;
|
||||||
|
char buffer[SIZE];
|
||||||
|
String8 result;
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Format: %d\n", mFormat);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
|
||||||
|
result.append(buffer);
|
||||||
|
write(fd, result.string(), result.size());
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- StreamDescriptor class implementation
|
||||||
|
|
||||||
|
void AudioPolicyManagerGeneric::StreamDescriptor::dump(char* buffer, size_t size)
|
||||||
|
{
|
||||||
|
snprintf(buffer, size, " %02d %02d %02d %02d %d\n",
|
||||||
|
mIndexMin,
|
||||||
|
mIndexMax,
|
||||||
|
mIndexCur,
|
||||||
|
mMuteCount,
|
||||||
|
mCanBeMuted);
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ public:
|
|||||||
virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
|
virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
|
||||||
virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
|
virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
|
||||||
|
|
||||||
|
virtual status_t dump(int fd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum routing_strategy {
|
enum routing_strategy {
|
||||||
@@ -93,6 +95,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
AudioOutputDescriptor();
|
AudioOutputDescriptor();
|
||||||
|
|
||||||
|
status_t dump(int fd);
|
||||||
|
|
||||||
uint32_t device();
|
uint32_t device();
|
||||||
void changeRefCount(AudioSystem::stream_type, int delta);
|
void changeRefCount(AudioSystem::stream_type, int delta);
|
||||||
@@ -115,6 +118,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
AudioInputDescriptor();
|
AudioInputDescriptor();
|
||||||
|
|
||||||
|
status_t dump(int fd);
|
||||||
|
|
||||||
uint32_t mSamplingRate; //
|
uint32_t mSamplingRate; //
|
||||||
uint32_t mFormat; // input configuration
|
uint32_t mFormat; // input configuration
|
||||||
uint32_t mChannels; //
|
uint32_t mChannels; //
|
||||||
@@ -130,6 +135,8 @@ private:
|
|||||||
StreamDescriptor()
|
StreamDescriptor()
|
||||||
: mIndexMin(0), mIndexMax(1), mIndexCur(1), mMuteCount(0), mCanBeMuted(true) {}
|
: mIndexMin(0), mIndexMax(1), mIndexCur(1), mMuteCount(0), mCanBeMuted(true) {}
|
||||||
|
|
||||||
|
void dump(char* buffer, size_t size);
|
||||||
|
|
||||||
int mIndexMin; // min volume index
|
int mIndexMin; // min volume index
|
||||||
int mIndexMax; // max volume index
|
int mIndexMax; // max volume index
|
||||||
int mIndexCur; // current volume index
|
int mIndexCur; // current volume index
|
||||||
|
|||||||
@@ -43,6 +43,12 @@
|
|||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
static const char* kDeadlockedString = "AudioPolicyService may be deadlocked\n";
|
||||||
|
static const char* kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
|
||||||
|
|
||||||
|
static const int kDumpLockRetries = 50;
|
||||||
|
static const int kDumpLockSleep = 20000;
|
||||||
|
|
||||||
static bool checkPermission() {
|
static bool checkPermission() {
|
||||||
#ifndef HAVE_ANDROID_OS
|
#ifndef HAVE_ANDROID_OS
|
||||||
return true;
|
return true;
|
||||||
@@ -335,17 +341,65 @@ void AudioPolicyService::binderDied(const wp<IBinder>& who) {
|
|||||||
LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
|
LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tryLock(Mutex& mutex)
|
||||||
|
{
|
||||||
|
bool locked = false;
|
||||||
|
for (int i = 0; i < kDumpLockRetries; ++i) {
|
||||||
|
if (mutex.tryLock() == NO_ERROR) {
|
||||||
|
locked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
usleep(kDumpLockSleep);
|
||||||
|
}
|
||||||
|
return locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AudioPolicyService::dumpInternals(int fd)
|
||||||
|
{
|
||||||
|
const size_t SIZE = 256;
|
||||||
|
char buffer[SIZE];
|
||||||
|
String8 result;
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
|
||||||
|
result.append(buffer);
|
||||||
|
|
||||||
|
write(fd, result.string(), result.size());
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
|
status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
|
||||||
{
|
{
|
||||||
if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
|
if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
|
||||||
dumpPermissionDenial(fd, args);
|
dumpPermissionDenial(fd);
|
||||||
} else {
|
} else {
|
||||||
|
bool locked = tryLock(mLock);
|
||||||
|
if (!locked) {
|
||||||
|
String8 result(kDeadlockedString);
|
||||||
|
write(fd, result.string(), result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpInternals(fd);
|
||||||
|
if (mAudioCommandThread != NULL) {
|
||||||
|
mAudioCommandThread->dump(fd);
|
||||||
|
}
|
||||||
|
if (mTonePlaybackThread != NULL) {
|
||||||
|
mTonePlaybackThread->dump(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mpPolicyManager) {
|
||||||
|
mpPolicyManager->dump(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locked) mLock.unlock();
|
||||||
}
|
}
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t AudioPolicyService::dumpPermissionDenial(int fd, const Vector<String16>& args)
|
status_t AudioPolicyService::dumpPermissionDenial(int fd)
|
||||||
{
|
{
|
||||||
const size_t SIZE = 256;
|
const size_t SIZE = 256;
|
||||||
char buffer[SIZE];
|
char buffer[SIZE];
|
||||||
@@ -609,6 +663,36 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t AudioPolicyService::AudioCommandThread::dump(int fd)
|
||||||
|
{
|
||||||
|
const size_t SIZE = 256;
|
||||||
|
char buffer[SIZE];
|
||||||
|
String8 result;
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
|
||||||
|
result.append(buffer);
|
||||||
|
write(fd, result.string(), result.size());
|
||||||
|
|
||||||
|
bool locked = tryLock(mLock);
|
||||||
|
if (!locked) {
|
||||||
|
String8 result2(kCmdDeadlockedString);
|
||||||
|
write(fd, result2.string(), result2.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "- Commands:\n");
|
||||||
|
result = String8(buffer);
|
||||||
|
result.append(" Command Time Status Wait pParam\n");
|
||||||
|
for (int i = 0; i < (int)mAudioCommands.size(); i++) {
|
||||||
|
mAudioCommands[i]->dump(buffer, SIZE);
|
||||||
|
result.append(buffer);
|
||||||
|
}
|
||||||
|
write(fd, result.string(), result.size());
|
||||||
|
|
||||||
|
if (locked) mLock.unlock();
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
|
void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
|
||||||
{
|
{
|
||||||
AudioCommand *command = new AudioCommand();
|
AudioCommand *command = new AudioCommand();
|
||||||
@@ -808,4 +892,15 @@ void AudioPolicyService::AudioCommandThread::exit()
|
|||||||
requestExitAndWait();
|
requestExitAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
|
||||||
|
{
|
||||||
|
snprintf(buffer, size, " %02d %06d.%03d %03d %01u %p\n",
|
||||||
|
mCommand,
|
||||||
|
(int)ns2s(mTime),
|
||||||
|
(int)ns2ms(mTime)%1000,
|
||||||
|
mStatus,
|
||||||
|
mWaitStatus,
|
||||||
|
mParam);
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ private:
|
|||||||
AudioPolicyService();
|
AudioPolicyService();
|
||||||
virtual ~AudioPolicyService();
|
virtual ~AudioPolicyService();
|
||||||
|
|
||||||
|
status_t dumpInternals(int fd);
|
||||||
|
|
||||||
// Thread used for tone playback and to send audio config commands to audio flinger
|
// Thread used for tone playback and to send audio config commands to audio flinger
|
||||||
// For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
|
// For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
|
||||||
// and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
|
// and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
|
||||||
@@ -133,6 +135,8 @@ private:
|
|||||||
AudioCommandThread ();
|
AudioCommandThread ();
|
||||||
virtual ~AudioCommandThread();
|
virtual ~AudioCommandThread();
|
||||||
|
|
||||||
|
status_t dump(int fd);
|
||||||
|
|
||||||
// Thread virtuals
|
// Thread virtuals
|
||||||
virtual void onFirstRef();
|
virtual void onFirstRef();
|
||||||
virtual bool threadLoop();
|
virtual bool threadLoop();
|
||||||
@@ -149,6 +153,8 @@ private:
|
|||||||
// descriptor for requested tone playback event
|
// descriptor for requested tone playback event
|
||||||
class AudioCommand {
|
class AudioCommand {
|
||||||
public:
|
public:
|
||||||
|
void dump(char* buffer, size_t size);
|
||||||
|
|
||||||
int mCommand; // START_TONE, STOP_TONE ...
|
int mCommand; // START_TONE, STOP_TONE ...
|
||||||
nsecs_t mTime; // time stamp
|
nsecs_t mTime; // time stamp
|
||||||
Condition mCond; // condition for status return
|
Condition mCond; // condition for status return
|
||||||
@@ -188,7 +194,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Internal dump utilities.
|
// Internal dump utilities.
|
||||||
status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
|
status_t dumpPermissionDenial(int fd);
|
||||||
|
|
||||||
|
|
||||||
Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing device
|
Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing device
|
||||||
|
|||||||
Reference in New Issue
Block a user