Merge "Fix ProCameraTests to pass on Wolfie, disabling failing tests" into jb-mr2-dev
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 5cfe5bc..34bae29 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -264,12 +264,16 @@
status_t pushBlankBuffersToNativeWindow();
- // Returns true iff all buffers on the given port have status OWNED_BY_US.
+ // Returns true iff all buffers on the given port have status
+ // OWNED_BY_US or OWNED_BY_NATIVE_WINDOW.
bool allYourBuffersAreBelongToUs(OMX_U32 portIndex);
bool allYourBuffersAreBelongToUs();
+ void waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
+
size_t countBuffersOwnedByComponent(OMX_U32 portIndex) const;
+ size_t countBuffersOwnedByNativeWindow() const;
void deferMessage(const sp<AMessage> &msg);
void processDeferredMessages();
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
index bb01467..ee5e4e2 100644
--- a/include/media/stagefright/MediaErrors.h
+++ b/include/media/stagefright/MediaErrors.h
@@ -54,6 +54,8 @@
ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5,
ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6,
ERROR_DRM_TAMPER_DETECTED = DRM_ERROR_BASE - 7,
+ ERROR_DRM_NOT_PROVISIONED = DRM_ERROR_BASE - 8,
+ ERROR_DRM_DEVICE_REVOKED = DRM_ERROR_BASE - 9,
ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500,
ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999,
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ee49033..6d952c3 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -960,6 +960,19 @@
err = setupVideoDecoder(mime, width, height);
}
}
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+ int32_t numChannels, sampleRate;
+ if (!msg->findInt32("channel-count", &numChannels)
+ || !msg->findInt32("sample-rate", &sampleRate)) {
+ // Since we did not always check for these, leave them optional
+ // and have the decoder figure it all out.
+ err = OK;
+ } else {
+ err = setupRawAudioFormat(
+ encoder ? kPortIndexInput : kPortIndexOutput,
+ sampleRate,
+ numChannels);
+ }
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
int32_t numChannels, sampleRate;
if (!msg->findInt32("channel-count", &numChannels)
@@ -2122,6 +2135,42 @@
return n;
}
+size_t ACodec::countBuffersOwnedByNativeWindow() const {
+ size_t n = 0;
+
+ for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
+ const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
+
+ if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+ ++n;
+ }
+ }
+
+ return n;
+}
+
+void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
+ if (mNativeWindow == NULL) {
+ return;
+ }
+
+ int minUndequeuedBufs = 0;
+ status_t err = mNativeWindow->query(
+ mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &minUndequeuedBufs);
+
+ if (err != OK) {
+ ALOGE("[%s] NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
+ mComponentName.c_str(), strerror(-err), -err);
+
+ minUndequeuedBufs = 0;
+ }
+
+ while (countBuffersOwnedByNativeWindow() > (size_t)minUndequeuedBufs
+ && dequeueBufferFromNativeWindow() != NULL) {
+ }
+}
+
bool ACodec::allYourBuffersAreBelongToUs(
OMX_U32 portIndex) {
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
@@ -4164,6 +4213,10 @@
if (mFlushComplete[kPortIndexInput]
&& mFlushComplete[kPortIndexOutput]
&& mCodec->allYourBuffersAreBelongToUs()) {
+ // We now own all buffers except possibly those still queued with
+ // the native window for rendering. Let's get those back as well.
+ mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
+
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", ACodec::kWhatFlushCompleted);
notify->post();
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 3503aaf..145869e 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -83,7 +83,7 @@
uint8_t mCryptoKey[16]; // passed in from extractor
uint32_t mCurrentAuxInfoType;
uint32_t mCurrentAuxInfoTypeParameter;
- uint32_t mCurrentDefaultSampleInfoSize;
+ int32_t mCurrentDefaultSampleInfoSize;
uint32_t mCurrentSampleInfoCount;
uint32_t mCurrentSampleInfoAllocSize;
uint8_t* mCurrentSampleInfoSizes;
@@ -320,6 +320,21 @@
}
}
+static bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
+ // AMR NB audio is always mono, 8kHz
+ *channels = 1;
+ *rate = 8000;
+ return true;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
+ // AMR WB audio is always mono, 16kHz
+ *channels = 1;
+ *rate = 16000;
+ return true;
+ }
+ return false;
+}
+
MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
: mSidxDuration(0),
mMoofOffset(0),
@@ -443,6 +458,14 @@
return track->meta;
}
+static void MakeFourCCString(uint32_t x, char *s) {
+ s[0] = x >> 24;
+ s[1] = (x >> 16) & 0xff;
+ s[2] = (x >> 8) & 0xff;
+ s[3] = x & 0xff;
+ s[4] = '\0';
+}
+
status_t MPEG4Extractor::readMetaData() {
if (mInitCheck != NO_INIT) {
return mInitCheck;
@@ -673,14 +696,6 @@
return UNKNOWN_ERROR; // Return a dummy error.
}
-static void MakeFourCCString(uint32_t x, char *s) {
- s[0] = x >> 24;
- s[1] = (x >> 16) & 0xff;
- s[2] = (x >> 8) & 0xff;
- s[3] = x & 0xff;
- s[4] = '\0';
-}
-
struct PathAdder {
PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
: mPath(path) {
@@ -891,13 +906,19 @@
case FOURCC('f', 'r', 'm', 'a'):
{
- int32_t original_fourcc;
+ uint32_t original_fourcc;
if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
return ERROR_IO;
}
original_fourcc = ntohl(original_fourcc);
ALOGV("read original format: %d", original_fourcc);
mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
+ uint32_t num_channels = 0;
+ uint32_t sample_rate = 0;
+ if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
+ mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
+ mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+ }
*offset += chunk_size;
break;
}
@@ -1134,6 +1155,7 @@
}
case FOURCC('m', 'p', '4', 'a'):
+ case FOURCC('e', 'n', 'c', 'a'):
case FOURCC('s', 'a', 'm', 'r'):
case FOURCC('s', 'a', 'w', 'b'):
{
@@ -1149,29 +1171,18 @@
}
uint16_t data_ref_index = U16_AT(&buffer[6]);
- uint16_t num_channels = U16_AT(&buffer[16]);
+ uint32_t num_channels = U16_AT(&buffer[16]);
uint16_t sample_size = U16_AT(&buffer[18]);
uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
- if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
- FourCC2MIME(chunk_type))) {
- // AMR NB audio is always mono, 8kHz
- num_channels = 1;
- sample_rate = 8000;
- } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
- FourCC2MIME(chunk_type))) {
- // AMR WB audio is always mono, 16kHz
- num_channels = 1;
- sample_rate = 16000;
+ if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
+ // if the chunk type is enca, we'll get the type from the sinf/frma box later
+ mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+ AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
}
-
-#if 0
- printf("*** coding='%s' %d channels, size %d, rate %d\n",
+ ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
chunk, num_channels, sample_size, sample_rate);
-#endif
-
- mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
@@ -2297,6 +2308,7 @@
mSrcBuffer(NULL) {
mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
+ mDefaultIVSize = 0;
mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
uint32_t keytype;
const void *key;
@@ -2544,13 +2556,17 @@
if (!mDataSource->getUInt32(offset, &smplcnt)) {
return ERROR_MALFORMED;
}
+ mCurrentSampleInfoCount = smplcnt;
offset += 4;
+ if (mCurrentDefaultSampleInfoSize != 0) {
+ ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
+ return OK;
+ }
if (smplcnt > mCurrentSampleInfoAllocSize) {
mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
mCurrentSampleInfoAllocSize = smplcnt;
}
- mCurrentSampleInfoCount = smplcnt;
mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
return OK;
@@ -2608,7 +2624,8 @@
drmoffset += mCurrentMoofOffset;
int ivlength;
CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
- int foo = 1;
+
+ // read CencSampleAuxiliaryDataFormats
for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
Sample *smpl = &mCurrentSamples.editItemAt(i);
@@ -2619,24 +2636,33 @@
drmoffset += ivlength;
- uint16_t numsubsamples;
- if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
- return ERROR_IO;
+ int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
+ if (smplinfosize == 0) {
+ smplinfosize = mCurrentSampleInfoSizes[i];
}
- drmoffset += 2;
- for (size_t j = 0; j < numsubsamples; j++) {
- uint16_t numclear;
- uint32_t numencrypted;
- if (!mDataSource->getUInt16(drmoffset, &numclear)) {
+ if (smplinfosize > ivlength) {
+ uint16_t numsubsamples;
+ if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
return ERROR_IO;
}
drmoffset += 2;
- if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
- return ERROR_IO;
+ for (size_t j = 0; j < numsubsamples; j++) {
+ uint16_t numclear;
+ uint32_t numencrypted;
+ if (!mDataSource->getUInt16(drmoffset, &numclear)) {
+ return ERROR_IO;
+ }
+ drmoffset += 2;
+ if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
+ return ERROR_IO;
+ }
+ drmoffset += 4;
+ smpl->clearsizes.add(numclear);
+ smpl->encryptedsizes.add(numencrypted);
}
- drmoffset += 4;
- smpl->clearsizes.add(numclear);
- smpl->encryptedsizes.add(numencrypted);
+ } else {
+ smpl->clearsizes.add(0);
+ smpl->encryptedsizes.add(smpl->size);
}
}
@@ -3293,6 +3319,21 @@
}
}
+ const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
+ const sp<MetaData> bufmeta = mBuffer->meta_data();
+ bufmeta->clear();
+ if (smpl->encryptedsizes.size()) {
+ // store clear/encrypted lengths in metadata
+ bufmeta->setData(kKeyPlainSizes, 0,
+ smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
+ bufmeta->setData(kKeyEncryptedSizes, 0,
+ smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
+ bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
+ bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
+ bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
+ bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
+ }
+
if (!mIsAVC || mWantsNALFragments) {
if (newBuffer) {
ssize_t num_bytes_read =
@@ -3308,7 +3349,6 @@
CHECK(mBuffer != NULL);
mBuffer->set_range(0, size);
- mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
@@ -3432,7 +3472,6 @@
mBuffer->set_range(0, dstOffset);
}
- mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
@@ -3445,20 +3484,6 @@
mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
}
- const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
- if (smpl->encryptedsizes.size()) {
- // store clear/encrypted lengths in metadata
- sp<MetaData> bufmeta = mBuffer->meta_data();
- bufmeta->setData(kKeyPlainSizes, 0,
- smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
- bufmeta->setData(kKeyEncryptedSizes, 0,
- smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
- bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
- bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
- bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
- bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
- }
-
++mCurrentSampleIndex;
*out = mBuffer;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 0d89c0f..e4e95d2 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -534,6 +534,20 @@
// the shutdown complete notification.
sendErrorReponse = false;
+
+ if (omxError == OMX_ErrorResourcesLost
+ && internalError == DEAD_OBJECT) {
+ // MediaServer died, there definitely won't
+ // be a shutdown complete notification after
+ // all.
+
+ // note that we're directly going from
+ // STOPPING->UNINITIALIZED, instead of the
+ // usual STOPPING->INITIALIZED state.
+ setState(UNINITIALIZED);
+
+ (new AMessage)->postReply(mReplyID);
+ }
break;
}
@@ -1013,8 +1027,16 @@
if (mState != INITIALIZED
&& mState != CONFIGURED && mState != STARTED) {
+ // We may be in "UNINITIALIZED" state already without the
+ // client being aware of this if media server died while
+ // we were being stopped. The client would assume that
+ // after stop() returned, it would be safe to call release()
+ // and it should be in this case, no harm to allow a release()
+ // if we're already uninitialized.
sp<AMessage> response = new AMessage;
- response->setInt32("err", INVALID_OPERATION);
+ response->setInt32(
+ "err",
+ mState == UNINITIALIZED ? OK : INVALID_OPERATION);
response->postReply(replyID);
break;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 6c0779d..9d349a1 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -522,6 +522,17 @@
CODEC_LOGE("setAACFormat() failed (err = %d)", err);
return err;
}
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_MPEG, mMIME)) {
+ int32_t numChannels, sampleRate;
+ if (meta->findInt32(kKeyChannelCount, &numChannels)
+ && meta->findInt32(kKeySampleRate, &sampleRate)) {
+ // Since we did not always check for these, leave them optional
+ // and have the decoder figure it all out.
+ setRawAudioFormat(
+ mIsEncoder ? kPortIndexInput : kPortIndexOutput,
+ sampleRate,
+ numChannels);
+ }
} else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
|| !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
// These are PCM-like formats with a fixed sample rate but
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index cf81c16..cf50dc9 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -586,9 +586,12 @@
}
void SoftAAC2::drainDecoder() {
- short buf [2048];
- aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
- aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
+ // a buffer big enough for 6 channels of decoded HE-AAC
+ short buf [2048*6];
+ aacDecoder_DecodeFrame(mAACDecoder,
+ buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
+ aacDecoder_DecodeFrame(mAACDecoder,
+ buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
mDecoderHasData = false;
}
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 849be87..9f25536 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -166,6 +166,21 @@
return OMX_ErrorNone;
}
+ case OMX_IndexParamAudioPcm:
+ {
+ const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (const OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ mNumChannels = pcmParams->nChannels;
+ mSamplingRate = pcmParams->nSamplingRate;
+
+ return OMX_ErrorNone;
+ }
+
default:
return SimpleSoftOMXComponent::internalSetParameter(index, params);
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 971875f..e7d5e74 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -299,7 +299,9 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex %s failed", name);
+ if (enable) {
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
+ }
return StatusFromOMXError(err);
}
@@ -378,9 +380,8 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- if (enable) {
- ALOGE("OMX_GetExtensionIndex %s failed", name);
- }
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
+
return StatusFromOMXError(err);
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b3de526..87eb6aa 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -143,6 +143,7 @@
mMode(AUDIO_MODE_INVALID),
mBtNrecIsOff(false)
{
+ getpid_cached = getpid();
char value[PROPERTY_VALUE_MAX];
bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
if (doLog) {
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 6a58852..d15bd04 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -21,8 +21,9 @@
namespace android {
-// This optimization assumes mediaserver process doesn't fork, which it doesn't
-const pid_t getpid_cached = getpid();
+// Not valid until initialized by AudioFlinger constructor. It would have to be
+// re-initialized if the process containing AudioFlinger service forks (which it doesn't).
+pid_t getpid_cached;
bool recordingAllowed() {
if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index f77ec5b..80cecba 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -18,7 +18,7 @@
namespace android {
-extern const pid_t getpid_cached;
+extern pid_t getpid_cached;
bool recordingAllowed();
bool settingsAllowed();
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index f60749d..683fdf3 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -60,7 +60,9 @@
static const String16 sDump("android.permission.DUMP");
if (!(IPCThreadState::self()->getCallingUid() == AID_MEDIA ||
PermissionCache::checkCallingPermission(sDump))) {
- fdprintf(fd, "Permission denied.\n");
+ fdprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n",
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
return NO_ERROR;
}