Log for issue 2203561.
Implemented AudioPolicyService dump().
Added detailed dump for AudioPolicyManageriGeneric when AudioPolicyService is dumped.
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/libs/audioflinger/AudioPolicyService.cpp
index f71c99c..9723697 100644
--- a/libs/audioflinger/AudioPolicyService.cpp
+++ b/libs/audioflinger/AudioPolicyService.cpp
@@ -43,6 +43,12 @@
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() {
#ifndef HAVE_ANDROID_OS
return true;
@@ -335,17 +341,65 @@
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)
{
if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- dumpPermissionDenial(fd, args);
+ dumpPermissionDenial(fd);
} 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;
}
-status_t AudioPolicyService::dumpPermissionDenial(int fd, const Vector<String16>& args)
+status_t AudioPolicyService::dumpPermissionDenial(int fd)
{
const size_t SIZE = 256;
char buffer[SIZE];
@@ -609,6 +663,36 @@
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)
{
AudioCommand *command = new AudioCommand();
@@ -808,4 +892,15 @@
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