Merge "ACodec: process deferred messages when entering Loaded state." into lmp-dev
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 28e5c56..d77ddaf 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -217,6 +217,8 @@
bool mCreateInputBuffersSuspended;
+ bool mTunneled;
+
status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode);
status_t allocateBuffersOnPort(OMX_U32 portIndex);
status_t freeBuffersOnPort(OMX_U32 portIndex);
diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h
index 5dd425b..5193d00 100644
--- a/include/private/media/VideoFrame.h
+++ b/include/private/media/VideoFrame.h
@@ -63,8 +63,11 @@
uint32_t mDisplayWidth;
uint32_t mDisplayHeight;
uint32_t mSize; // Number of bytes in mData
+ int32_t mRotationAngle; // rotation angle, clockwise, should be multiple of 90
+ // mData should be 64 bit aligned to prevent additional padding
uint8_t* mData; // Actual binary data
- int32_t mRotationAngle; // rotation angle, clockwise
+ // pad structure so it's the same size on 64 bit and 32 bit
+ char mPadding[8 - sizeof(mData)];
};
}; // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index e3beba5..8e0704f 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -2244,6 +2244,9 @@
return true;
}
}
+ if (exitPending()) {
+ return false;
+ }
nsecs_t ns = mReceiver.processAudioBuffer();
switch (ns) {
case 0:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 17190fb..cadd691 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1172,6 +1172,7 @@
client.interface(),
(mVideoEncoder == VIDEO_ENCODER_H263 ? MEDIA_MIMETYPE_VIDEO_H263 :
mVideoEncoder == VIDEO_ENCODER_MPEG_4_SP ? MEDIA_MIMETYPE_VIDEO_MPEG4 :
+ mVideoEncoder == VIDEO_ENCODER_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 :
mVideoEncoder == VIDEO_ENCODER_H264 ? MEDIA_MIMETYPE_VIDEO_AVC : ""),
false /* decoder */, true /* hwCodec */, &codecs);
*supportsCameraSourceMetaDataMode = codecs.size() > 0;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 53eec91..1c73995 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -174,6 +174,7 @@
mNumFramesDropped(0ll),
mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
mStarted(false) {
+ clearFlushComplete();
}
NuPlayer::~NuPlayer() {
@@ -333,25 +334,6 @@
msg->post();
}
-// static
-bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
- switch (state) {
- case FLUSHING_DECODER:
- if (needShutdown != NULL) {
- *needShutdown = false;
- }
- return true;
-
- case FLUSHING_DECODER_SHUTDOWN:
- if (needShutdown != NULL) {
- *needShutdown = true;
- }
- return true;
-
- default:
- return false;
- }
-}
void NuPlayer::writeTrackInfo(
Parcel* reply, const sp<AMessage> format) const {
@@ -773,38 +755,9 @@
mRenderer->queueEOS(audio, err);
} else if (what == Decoder::kWhatFlushCompleted) {
- bool needShutdown;
-
- if (audio) {
- CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
- mFlushingAudio = FLUSHED;
- } else {
- CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
- mFlushingVideo = FLUSHED;
-
- mVideoLateByUs = 0;
- }
-
ALOGV("decoder %s flush completed", audio ? "audio" : "video");
- if (needShutdown) {
- ALOGV("initiating %s decoder shutdown",
- audio ? "audio" : "video");
-
- // Widevine source reads must stop before releasing the video decoder.
- if (!audio && mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
- mSource->stop();
- }
-
- getDecoder(audio)->initiateShutdown();
-
- if (audio) {
- mFlushingAudio = SHUTTING_DOWN_DECODER;
- } else {
- mFlushingVideo = SHUTTING_DOWN_DECODER;
- }
- }
-
+ handleFlushComplete(audio, true /* isDecoder */);
finishFlushIfPossible();
} else if (what == Decoder::kWhatOutputFormatChanged) {
sp<AMessage> format;
@@ -957,6 +910,8 @@
CHECK(msg->findInt32("audio", &audio));
ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
+ handleFlushComplete(audio, false /* isDecoder */);
+ finishFlushIfPossible();
} else if (what == Renderer::kWhatVideoRenderingStart) {
notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
} else if (what == Renderer::kWhatMediaRenderingStart) {
@@ -1084,6 +1039,50 @@
return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
}
+void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) {
+ // We wait for both the decoder flush and the renderer flush to complete
+ // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state.
+
+ mFlushComplete[audio][isDecoder] = true;
+ if (!mFlushComplete[audio][!isDecoder]) {
+ return;
+ }
+
+ FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo;
+ switch (*state) {
+ case FLUSHING_DECODER:
+ {
+ *state = FLUSHED;
+
+ if (!audio) {
+ mVideoLateByUs = 0;
+ }
+ break;
+ }
+
+ case FLUSHING_DECODER_SHUTDOWN:
+ {
+ *state = SHUTTING_DOWN_DECODER;
+
+ ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
+ if (!audio) {
+ mVideoLateByUs = 0;
+ // Widevine source reads must stop before releasing the video decoder.
+ if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
+ mSource->stop();
+ }
+ }
+ getDecoder(audio)->initiateShutdown();
+ break;
+ }
+
+ default:
+ // decoder flush completes only occur in a flushing state.
+ LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state);
+ break;
+ }
+}
+
void NuPlayer::finishFlushIfPossible() {
if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED
&& mFlushingAudio != SHUT_DOWN) {
@@ -1116,6 +1115,8 @@
mFlushingAudio = NONE;
mFlushingVideo = NONE;
+ clearFlushComplete();
+
processDeferredActions();
}
@@ -1720,6 +1721,8 @@
FlushStatus newStatus =
needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
+ mFlushComplete[audio][false /* isDecoder */] = false;
+ mFlushComplete[audio][true /* isDecoder */] = false;
if (audio) {
ALOGE_IF(mFlushingAudio != NONE,
"audio flushDecoder() is called in state %d", mFlushingAudio);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 8157733..1b9a756 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -164,6 +164,9 @@
// notion of time has changed.
bool mTimeDiscontinuityPending;
+ // Status of flush responses from the decoder and renderer.
+ bool mFlushComplete[2][2];
+
// Used by feedDecoderInputData to aggregate small buffers into
// one large buffer.
sp<ABuffer> mPendingAudioAccessUnit;
@@ -187,6 +190,13 @@
return audio ? mAudioDecoder : mVideoDecoder;
}
+ inline void clearFlushComplete() {
+ mFlushComplete[0][0] = false;
+ mFlushComplete[0][1] = false;
+ mFlushComplete[1][0] = false;
+ mFlushComplete[1][1] = false;
+ }
+
void openAudioSink(const sp<AMessage> &format, bool offloadOnly);
void closeAudioSink();
@@ -201,6 +211,7 @@
void notifyListener(int msg, int ext1, int ext2, const Parcel *in = NULL);
+ void handleFlushComplete(bool audio, bool isDecoder);
void finishFlushIfPossible();
bool audioDecoderStillNeeded();
@@ -209,8 +220,6 @@
bool audio, bool needShutdown, const sp<AMessage> &newFormat = NULL);
void updateDecoderFormatWithoutFlush(bool audio, const sp<AMessage> &format);
- static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);
-
void postScanSources();
void schedulePollDuration();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 1a01d52..c57955d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -582,7 +582,7 @@
}
void NuPlayerDriver::notifyResetComplete() {
- ALOGI("notifyResetComplete(%p)", this);
+ ALOGD("notifyResetComplete(%p)", this);
Mutex::Autolock autoLock(mLock);
CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index d6bf1de..e5c64f6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -72,6 +72,7 @@
mHasVideo(false),
mSyncQueues(false),
mPaused(false),
+ mPauseStartedTimeRealUs(-1),
mVideoSampleReceived(false),
mVideoRenderingStarted(false),
mVideoRenderingStartGeneration(0),
@@ -574,7 +575,9 @@
if (!mHasAudio) {
mAnchorTimeMediaUs = mediaTimeUs;
mAnchorTimeRealUs = nowUs;
- notifyPosition();
+ if (!mPaused || mVideoSampleReceived) {
+ notifyPosition();
+ }
}
realTimeUs = nowUs;
} else {
@@ -645,6 +648,10 @@
}
} else {
mVideoLateByUs = 0ll;
+ if (!mHasAudio && !mVideoSampleReceived) {
+ mAnchorTimeMediaUs = -1;
+ mAnchorTimeRealUs = -1;
+ }
}
entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
@@ -830,6 +837,9 @@
{
Mutex::Autolock autoLock(mLock);
syncQueuesDone_l();
+ if (!mHasAudio) {
+ mPauseStartedTimeRealUs = -1;
+ }
}
ALOGV("flushing %s", audio ? "audio" : "video");
@@ -980,6 +990,9 @@
++mVideoQueueGeneration;
prepareForMediaRenderingStart();
mPaused = true;
+ if (!mHasAudio) {
+ mPauseStartedTimeRealUs = ALooper::GetNowUs();
+ }
}
mDrainAudioQueuePending = false;
@@ -1008,6 +1021,10 @@
Mutex::Autolock autoLock(mLock);
mPaused = false;
+ if (!mHasAudio && mPauseStartedTimeRealUs != -1) {
+ mAnchorTimeRealUs += ALooper::GetNowUs() - mPauseStartedTimeRealUs;
+ mPauseStartedTimeRealUs = -1;
+ }
if (!mAudioQueue.empty()) {
postDrainAudioQueue_l();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 4237902..d27c238 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -130,6 +130,7 @@
bool mSyncQueues;
bool mPaused;
+ int64_t mPauseStartedTimeRealUs;
bool mVideoSampleReceived;
bool mVideoRenderingStarted;
int32_t mVideoRenderingStartGeneration;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b14efd7..b8d5c7b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -421,7 +421,8 @@
mMaxPtsGapUs(-1ll),
mTimePerFrameUs(-1ll),
mTimePerCaptureUs(-1ll),
- mCreateInputBuffersSuspended(false) {
+ mCreateInputBuffersSuspended(false),
+ mTunneled(false) {
mUninitializedState = new UninitializedState(this);
mLoadedState = new LoadedState(this);
mLoadedToIdleState = new LoadedToIdleState(this);
@@ -697,6 +698,21 @@
return err;
}
+ // Exits here for tunneled video playback codecs -- i.e. skips native window
+ // buffer allocation step as this is managed by the tunneled OMX omponent
+ // itself and explicitly sets def.nBufferCountActual to 0.
+ if (mTunneled) {
+ ALOGV("Tunneled Playback: skipping native window buffer allocation.");
+ def.nBufferCountActual = 0;
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ *minUndequeuedBuffers = 0;
+ *bufferCount = 0;
+ *bufferSize = 0;
+ return err;
+ }
+
*minUndequeuedBuffers = 0;
err = mNativeWindow->query(
mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
@@ -904,6 +920,13 @@
ANativeWindowBuffer *buf;
int fenceFd = -1;
CHECK(mNativeWindow.get() != NULL);
+
+ if (mTunneled) {
+ ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
+ " video playback mode mode!");
+ return NULL;
+ }
+
if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
ALOGE("dequeueBuffer failed.");
return NULL;
@@ -1245,6 +1268,7 @@
if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
tunneled != 0) {
ALOGI("Configuring TUNNELED video playback.");
+ mTunneled = true;
int32_t audioHwSync = 0;
if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
@@ -1259,6 +1283,9 @@
inputFormat->setInt32("adaptive-playback", true);
} else {
+ ALOGV("Configuring CPU controlled video playback.");
+ mTunneled = false;
+
// Always try to enable dynamic output buffers on native surface
err = mOMX->storeMetaDataInBuffers(
mNode, kPortIndexOutput, OMX_TRUE);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b568063..5f55484 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -780,7 +780,9 @@
// STOPPING->UNINITIALIZED, instead of the
// usual STOPPING->INITIALIZED state.
setState(UNINITIALIZED);
-
+ if (mState == RELEASING) {
+ mComponentName.clear();
+ }
(new AMessage)->postReply(mReplyID);
}
break;
@@ -1046,7 +1048,9 @@
}
if (mFlags & kFlagIsAsync) {
- onInputBufferAvailable();
+ if (!mHaveInputSurface) {
+ onInputBufferAvailable();
+ }
} else if (mFlags & kFlagDequeueInputPending) {
CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
@@ -1130,6 +1134,7 @@
} else {
CHECK_EQ(mState, RELEASING);
setState(UNINITIALIZED);
+ mComponentName.clear();
}
(new AMessage)->postReply(mReplyID);
@@ -1339,12 +1344,12 @@
// 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.
- // Similarly stopping a stopped MediaCodec should be benign.
sp<AMessage> response = new AMessage;
- response->setInt32(
- "err",
- mState == targetState ? OK : INVALID_OPERATION);
-
+ status_t err = mState == targetState ? OK : INVALID_OPERATION;
+ response->setInt32("err", err);
+ if (err == OK && targetState == UNINITIALIZED) {
+ mComponentName.clear();
+ }
response->postReply(replyID);
break;
}
@@ -1353,6 +1358,9 @@
// It's dead, Jim. Don't expect initiateShutdown to yield
// any useful results now...
setState(UNINITIALIZED);
+ if (targetState == UNINITIALIZED) {
+ mComponentName.clear();
+ }
(new AMessage)->postReply(replyID);
break;
}
@@ -1745,8 +1753,6 @@
// return any straggling buffers, e.g. if we got here on an error
returnBuffersToCodec();
- mComponentName.clear();
-
// The component is gone, mediaserver's probably back up already
// but should definitely be back up should we try to instantiate
// another component.. and the cycle continues.
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 1b6eac4..40925fd 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -654,6 +654,7 @@
inHeader->nOffset += inBufferUsedLength;
AAC_DECODER_ERROR decoderErr;
+ int numLoops = 0;
do {
if (outputDelayRingBufferSpaceLeft() <
(mStreamInfo->frameSize * mStreamInfo->numChannels)) {
@@ -661,20 +662,19 @@
break;
}
- int numconsumed = mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes;
+ int numConsumed = mStreamInfo->numTotalBytes;
decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
tmpOutBuffer,
2048 * MAX_CHANNEL_COUNT,
0 /* flags */);
- numconsumed = (mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes) - numconsumed;
- if (numconsumed != 0) {
- mDecodedSizes.add(numconsumed);
- }
+ numConsumed = mStreamInfo->numTotalBytes - numConsumed;
+ numLoops++;
if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
break;
}
+ mDecodedSizes.add(numConsumed);
if (decoderErr != AAC_DEC_OK) {
ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
@@ -716,6 +716,15 @@
aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
+ // After an error, replace the last entry in mBufferSizes with the sum of the
+ // last <numLoops> entries from mDecodedSizes to resynchronize the in/out lists.
+ mBufferSizes.pop();
+ int n = 0;
+ for (int i = 0; i < numLoops; i++) {
+ n += mDecodedSizes.itemAt(mDecodedSizes.size() - numLoops + i);
+ }
+ mBufferSizes.add(n);
+
// fall through
}
diff --git a/services/audiopolicy/AudioPolicyClientImplLegacy.cpp b/services/audiopolicy/AudioPolicyClientImplLegacy.cpp
index 9639096..97719da 100644
--- a/services/audiopolicy/AudioPolicyClientImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyClientImplLegacy.cpp
@@ -96,7 +96,7 @@
*pFormat = config.format;
*pChannelMask = config.channel_mask;
if (offloadInfo != NULL) {
- *offloadInfo = config.offload_info;
+ *((audio_offload_info_t *)offloadInfo) = config.offload_info;
}
}
return output;
diff --git a/services/audiopolicy/AudioPolicyEffects.cpp b/services/audiopolicy/AudioPolicyEffects.cpp
index c45acd0..3c1c042 100644
--- a/services/audiopolicy/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/AudioPolicyEffects.cpp
@@ -87,6 +87,7 @@
audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
+ Mutex::Autolock _l(mLock);
ssize_t index = mInputSources.indexOfKey(aliasSource);
if (index < 0) {
ALOGV("addInputEffects(): no processing needs to be attached to this source");
@@ -122,7 +123,7 @@
ALOGV("addInputEffects(): added Fx %s on source: %d", effect->mName, (int32_t)aliasSource);
inputDesc->mEffects.add(fx);
}
- setProcessorEnabled(inputDesc, true);
+ inputDesc->setProcessorEnabled(true);
return status;
}
@@ -132,6 +133,7 @@
{
status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
ssize_t index = mInputs.indexOfKey(input);
if (index < 0) {
return status;
@@ -140,7 +142,7 @@
inputDesc->mRefCount--;
ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, inputDesc->mRefCount);
if (inputDesc->mRefCount == 0) {
- setProcessorEnabled(inputDesc, false);
+ inputDesc->setProcessorEnabled(false);
delete inputDesc;
mInputs.removeItemsAt(index);
ALOGV("releaseInputEffects(): all effects released");
@@ -154,6 +156,7 @@
{
status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
size_t index;
for (index = 0; index < mInputs.size(); index++) {
if (mInputs.valueAt(index)->mSessionId == audioSession) {
@@ -186,6 +189,7 @@
{
status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
size_t index;
for (index = 0; index < mOutputSessions.size(); index++) {
if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
@@ -218,6 +222,7 @@
{
status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
// create audio processors according to stream
ssize_t index = mOutputStreams.indexOfKey(stream);
if (index < 0) {
@@ -254,7 +259,7 @@
procDesc->mEffects.add(fx);
}
- setProcessorEnabled(procDesc, true);
+ procDesc->setProcessorEnabled(true);
return status;
}
@@ -267,6 +272,7 @@
(void) output; // argument not used for now
(void) stream; // argument not used for now
+ Mutex::Autolock _l(mLock);
ssize_t index = mOutputSessions.indexOfKey(audioSession);
if (index < 0) {
ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
@@ -277,7 +283,7 @@
procDesc->mRefCount--;
ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d", audioSession, procDesc->mRefCount);
if (procDesc->mRefCount == 0) {
- setProcessorEnabled(procDesc, false);
+ procDesc->setProcessorEnabled(false);
procDesc->mEffects.clear();
delete procDesc;
mOutputSessions.removeItemsAt(index);
@@ -288,11 +294,10 @@
}
-void AudioPolicyEffects::setProcessorEnabled(const EffectVector *effectVector, bool enabled)
+void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
{
- const Vector<sp<AudioEffect> > &fxVector = effectVector->mEffects;
- for (size_t i = 0; i < fxVector.size(); i++) {
- fxVector.itemAt(i)->setEnabled(enabled);
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ mEffects.itemAt(i)->setEnabled(enabled);
}
}
@@ -313,7 +318,7 @@
// returns the audio_source_t enum corresponding to the input source name or
// AUDIO_SOURCE_CNT is no match found
-audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
+/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
{
int i;
for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
diff --git a/services/audiopolicy/AudioPolicyEffects.h b/services/audiopolicy/AudioPolicyEffects.h
index dbe0d0e..6b0d538 100644
--- a/services/audiopolicy/AudioPolicyEffects.h
+++ b/services/audiopolicy/AudioPolicyEffects.h
@@ -45,6 +45,10 @@
AudioPolicyEffects();
virtual ~AudioPolicyEffects();
+ // NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService
+ // main mutex (mLock) held as they will indirectly call back into AudioPolicyService when
+ // managing audio effects.
+
// Return a list of effect descriptors for default input effects
// associated with audioSession
status_t queryDefaultInputEffects(int audioSession,
@@ -133,6 +137,10 @@
public:
EffectVector(int session) : mSessionId(session), mRefCount(0) {}
/*virtual*/ ~EffectVector() {}
+
+ // Enable or disable all effects in effect vector
+ void setProcessorEnabled(bool enabled);
+
const int mSessionId;
// AudioPolicyManager keeps mLock, no need for lock on reference count here
int mRefCount;
@@ -141,14 +149,11 @@
static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
- audio_source_t inputSourceNameToEnum(const char *name);
+ static audio_source_t inputSourceNameToEnum(const char *name);
static const char *kStreamNames[AUDIO_STREAM_CNT+1]; //+1 required as streams start from -1
audio_stream_type_t streamNameToEnum(const char *name);
- // Enable or disable all effects in effect vector
- void setProcessorEnabled(const EffectVector *effectVector, bool enabled);
-
// Parse audio_effects.conf
status_t loadAudioEffectConfig(const char *path);
@@ -173,6 +178,8 @@
size_t *curSize,
size_t *totSize);
+ // protects access to mInputSources, mInputs, mOutputStreams, mOutputSessions
+ Mutex mLock;
// Automatic input effects are configured per audio_source_t
KeyedVector< audio_source_t, EffectDescVector* > mInputSources;
// Automatic input effects are unique for audio_io_handle_t
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
index b212ca6..6cd0ac8 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
@@ -162,14 +162,19 @@
return NO_INIT;
}
ALOGV("startOutput()");
- Mutex::Autolock _l(mLock);
-
- // create audio processors according to stream
- status_t status = mAudioPolicyEffects->addOutputSessionEffects(output, stream, session);
- if (status != NO_ERROR && status != ALREADY_EXISTS) {
- ALOGW("Failed to add effects on session %d", session);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ audioPolicyEffects = mAudioPolicyEffects;
}
-
+ if (audioPolicyEffects != 0) {
+ // create audio processors according to stream
+ status_t status = audioPolicyEffects->addOutputSessionEffects(output, stream, session);
+ if (status != NO_ERROR && status != ALREADY_EXISTS) {
+ ALOGW("Failed to add effects on session %d", session);
+ }
+ }
+ Mutex::Autolock _l(mLock);
return mAudioPolicyManager->startOutput(output, stream, session);
}
@@ -190,14 +195,19 @@
int session)
{
ALOGV("doStopOutput from tid %d", gettid());
- Mutex::Autolock _l(mLock);
-
- // release audio processors from the stream
- status_t status = mAudioPolicyEffects->releaseOutputSessionEffects(output, stream, session);
- if (status != NO_ERROR && status != ALREADY_EXISTS) {
- ALOGW("Failed to release effects on session %d", session);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ audioPolicyEffects = mAudioPolicyEffects;
}
-
+ if (audioPolicyEffects != 0) {
+ // release audio processors from the stream
+ status_t status = audioPolicyEffects->releaseOutputSessionEffects(output, stream, session);
+ if (status != NO_ERROR && status != ALREADY_EXISTS) {
+ ALOGW("Failed to release effects on session %d", session);
+ }
+ }
+ Mutex::Autolock _l(mLock);
return mAudioPolicyManager->stopOutput(output, stream, session);
}
@@ -235,23 +245,26 @@
if ((inputSource == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) {
return 0;
}
-
- Mutex::Autolock _l(mLock);
- // the audio_in_acoustics_t parameter is ignored by get_input()
- audio_io_handle_t input = mAudioPolicyManager->getInput(inputSource, samplingRate,
- format, channelMask,
- (audio_session_t)audioSession, flags);
-
+ audio_io_handle_t input;
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ // the audio_in_acoustics_t parameter is ignored by get_input()
+ input = mAudioPolicyManager->getInput(inputSource, samplingRate,
+ format, channelMask,
+ (audio_session_t)audioSession, flags);
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
if (input == 0) {
return input;
}
-
- // create audio pre processors according to input source
- status_t status = mAudioPolicyEffects->addInputEffects(input, inputSource, audioSession);
- if (status != NO_ERROR && status != ALREADY_EXISTS) {
- ALOGW("Failed to add effects on input %d", input);
+ if (audioPolicyEffects != 0) {
+ // create audio pre processors according to input source
+ status_t status = audioPolicyEffects->addInputEffects(input, inputSource, audioSession);
+ if (status != NO_ERROR && status != ALREADY_EXISTS) {
+ ALOGW("Failed to add effects on input %d", input);
+ }
}
-
return input;
}
@@ -283,13 +296,18 @@
if (mAudioPolicyManager == NULL) {
return;
}
- Mutex::Autolock _l(mLock);
- mAudioPolicyManager->releaseInput(input, session);
-
- // release audio processors from the input
- status_t status = mAudioPolicyEffects->releaseInputEffects(input);
- if(status != NO_ERROR) {
- ALOGW("Failed to release effects on input %d", input);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ mAudioPolicyManager->releaseInput(input, session);
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+ if (audioPolicyEffects != 0) {
+ // release audio processors from the input
+ status_t status = audioPolicyEffects->releaseInputEffects(input);
+ if(status != NO_ERROR) {
+ ALOGW("Failed to release effects on input %d", input);
+ }
}
}
@@ -437,9 +455,16 @@
*count = 0;
return NO_INIT;
}
- Mutex::Autolock _l(mLock);
-
- return mAudioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+ if (audioPolicyEffects == 0) {
+ *count = 0;
+ return NO_INIT;
+ }
+ return audioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count);
}
bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
index 1e40bc3..e1e81e1 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
@@ -24,6 +24,7 @@
#include <system/audio.h>
#include <system/audio_policy.h>
#include <hardware/audio_policy.h>
+#include <media/AudioPolicyHelper.h>
namespace android {
@@ -150,14 +151,20 @@
return NO_INIT;
}
ALOGV("startOutput()");
- Mutex::Autolock _l(mLock);
-
// create audio processors according to stream
- status_t status = mAudioPolicyEffects->addOutputSessionEffects(output, stream, session);
- if (status != NO_ERROR && status != ALREADY_EXISTS) {
- ALOGW("Failed to add effects on session %d", session);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+ if (audioPolicyEffects != 0) {
+ status_t status = audioPolicyEffects->addOutputSessionEffects(output, stream, session);
+ if (status != NO_ERROR && status != ALREADY_EXISTS) {
+ ALOGW("Failed to add effects on session %d", session);
+ }
}
+ Mutex::Autolock _l(mLock);
return mpAudioPolicy->start_output(mpAudioPolicy, output, stream, session);
}
@@ -178,14 +185,19 @@
int session)
{
ALOGV("doStopOutput from tid %d", gettid());
- Mutex::Autolock _l(mLock);
-
// release audio processors from the stream
- status_t status = mAudioPolicyEffects->releaseOutputSessionEffects(output, stream, session);
- if (status != NO_ERROR && status != ALREADY_EXISTS) {
- ALOGW("Failed to release effects on session %d", session);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ audioPolicyEffects = mAudioPolicyEffects;
}
-
+ if (audioPolicyEffects != 0) {
+ status_t status = audioPolicyEffects->releaseOutputSessionEffects(output, stream, session);
+ if (status != NO_ERROR && status != ALREADY_EXISTS) {
+ ALOGW("Failed to release effects on session %d", session);
+ }
+ }
+ Mutex::Autolock _l(mLock);
return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session);
}
@@ -224,21 +236,26 @@
return 0;
}
- Mutex::Autolock _l(mLock);
- // the audio_in_acoustics_t parameter is ignored by get_input()
- audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
- format, channelMask, (audio_in_acoustics_t) 0);
-
+ audio_io_handle_t input;
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ // the audio_in_acoustics_t parameter is ignored by get_input()
+ input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
+ format, channelMask, (audio_in_acoustics_t) 0);
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
if (input == 0) {
return input;
}
- // create audio pre processors according to input source
- status_t status = mAudioPolicyEffects->addInputEffects(input, inputSource, audioSession);
- if (status != NO_ERROR && status != ALREADY_EXISTS) {
- ALOGW("Failed to add effects on input %d", input);
+ if (audioPolicyEffects != 0) {
+ // create audio pre processors according to input source
+ status_t status = audioPolicyEffects->addInputEffects(input, inputSource, audioSession);
+ if (status != NO_ERROR && status != ALREADY_EXISTS) {
+ ALOGW("Failed to add effects on input %d", input);
+ }
}
-
return input;
}
@@ -270,13 +287,19 @@
if (mpAudioPolicy == NULL) {
return;
}
- Mutex::Autolock _l(mLock);
- mpAudioPolicy->release_input(mpAudioPolicy, input);
- // release audio processors from the input
- status_t status = mAudioPolicyEffects->releaseInputEffects(input);
- if(status != NO_ERROR) {
- ALOGW("Failed to release effects on input %d", input);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ mpAudioPolicy->release_input(mpAudioPolicy, input);
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+ if (audioPolicyEffects != 0) {
+ // release audio processors from the input
+ status_t status = audioPolicyEffects->releaseInputEffects(input);
+ if(status != NO_ERROR) {
+ ALOGW("Failed to release effects on input %d", input);
+ }
}
}
@@ -437,9 +460,16 @@
*count = 0;
return NO_INIT;
}
- Mutex::Autolock _l(mLock);
-
- return mAudioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+ if (audioPolicyEffects == 0) {
+ *count = 0;
+ return NO_INIT;
+ }
+ return audioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count);
}
bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
@@ -496,7 +526,7 @@
return INVALID_OPERATION;
}
-audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr __unused,
+audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
uint32_t samplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index 647cda4..06a7e84 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -61,56 +61,65 @@
: BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
{
+}
+
+void AudioPolicyService::onFirstRef()
+{
char value[PROPERTY_VALUE_MAX];
const struct hw_module_t *module;
int forced_val;
int rc;
- Mutex::Autolock _l(mLock);
+ {
+ Mutex::Autolock _l(mLock);
- // start tone playback thread
- mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
- // start audio commands thread
- mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
- // start output activity command thread
- mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
+ // start tone playback thread
+ mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
+ // start audio commands thread
+ mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
+ // start output activity command thread
+ mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
#ifdef USE_LEGACY_AUDIO_POLICY
- ALOGI("AudioPolicyService CSTOR in legacy mode");
+ ALOGI("AudioPolicyService CSTOR in legacy mode");
- /* instantiate the audio policy manager */
- rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
- if (rc) {
- return;
- }
- rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
- ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
- if (rc) {
- return;
- }
+ /* instantiate the audio policy manager */
+ rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
+ if (rc) {
+ return;
+ }
+ rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
+ ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
+ if (rc) {
+ return;
+ }
- rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
- &mpAudioPolicy);
- ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
- if (rc) {
- return;
- }
+ rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
+ &mpAudioPolicy);
+ ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
+ if (rc) {
+ return;
+ }
- rc = mpAudioPolicy->init_check(mpAudioPolicy);
- ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
- if (rc) {
- return;
- }
- ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
+ rc = mpAudioPolicy->init_check(mpAudioPolicy);
+ ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
+ if (rc) {
+ return;
+ }
+ ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
#else
- ALOGI("AudioPolicyService CSTOR in new mode");
+ ALOGI("AudioPolicyService CSTOR in new mode");
- mAudioPolicyClient = new AudioPolicyClient(this);
- mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
+ mAudioPolicyClient = new AudioPolicyClient(this);
+ mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
#endif
-
+ }
// load audio processing modules
- mAudioPolicyEffects = new AudioPolicyEffects();
+ sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
+ {
+ Mutex::Autolock _l(mLock);
+ mAudioPolicyEffects = audioPolicyEffects;
+ }
}
AudioPolicyService::~AudioPolicyService()
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 2cea40b..4e68ab1 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -134,6 +134,9 @@
// IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
+ // RefBase
+ virtual void onFirstRef();
+
//
// Helpers for the struct audio_policy_service_ops implementation.
// This is used by the audio policy manager for certain operations that