diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2016-03-18 02:08:46 +0100 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2016-03-18 02:08:46 +0100 |
commit | 185e2110a53feb7720d91b6f8366ad27402f21cc (patch) | |
tree | a265317b5846eec34d7c87b494ede81857e6c2d3 | |
parent | d4590dda7776ec99e4e879c47b3372a5f4b13dcd (diff) | |
parent | 8c2e9d8867ccaba1a617f133b37103e2ac77e871 (diff) | |
download | frameworks_av-185e2110a53feb7720d91b6f8366ad27402f21cc.zip frameworks_av-185e2110a53feb7720d91b6f8366ad27402f21cc.tar.gz frameworks_av-185e2110a53feb7720d91b6f8366ad27402f21cc.tar.bz2 |
Merge branch 'cm-13.0' of https://github.com/CyanogenMod/android_frameworks_av into replicant-6.0
Signed-off-by: Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de>
44 files changed, 557 insertions, 109 deletions
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h index feed402..5a82bae 100644 --- a/include/media/AudioPolicy.h +++ b/include/media/AudioPolicy.h @@ -42,6 +42,7 @@ namespace android { // AudioSystem's implementation of the AudioPolicyClient interface // keep in sync with AudioSystem.java #define DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE 0 +#define AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE 10 #define MIX_STATE_DISABLED -1 #define MIX_STATE_IDLE 0 diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 26a0bb2..35b06ba 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -31,6 +31,8 @@ namespace android { typedef void (*audio_error_callback)(status_t err); typedef void (*dynamic_policy_callback)(int event, String8 regId, int val); +typedef void (*effect_session_callback)(int event, + audio_stream_type_t stream, audio_unique_id_t sessionId, bool added); class IAudioFlinger; class IAudioPolicyService; @@ -92,6 +94,7 @@ public: static void setErrorCallback(audio_error_callback cb); static void setDynPolicyCallback(dynamic_policy_callback cb); + static status_t setEffectSessionCallback(effect_session_callback cb); // helper function to obtain AudioFlinger service handle static const sp<IAudioFlinger> get_audio_flinger(); @@ -419,6 +422,9 @@ private: virtual void onAudioPortListUpdate(); virtual void onAudioPatchListUpdate(); virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); + virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, + bool added); private: Mutex mLock; @@ -438,6 +444,7 @@ private: static sp<IAudioFlinger> gAudioFlinger; static audio_error_callback gAudioErrorCallback; static dynamic_policy_callback gDynPolicyCallback; + static effect_session_callback gEffectSessionCallback; static size_t gInBuffSize; // previous parameters for recording buffer size queries diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 6b93f6f..3a7bd68 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -165,6 +165,8 @@ public: const audio_attributes_t *attributes, audio_io_handle_t *handle) = 0; virtual status_t stopAudioSource(audio_io_handle_t handle) = 0; + + virtual status_t setEffectSessionCallbacksEnabled(bool enabled) = 0; }; diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h index a7f2cc3..3bdeb5a 100644 --- a/include/media/IAudioPolicyServiceClient.h +++ b/include/media/IAudioPolicyServiceClient.h @@ -37,6 +37,10 @@ public: virtual void onAudioPatchListUpdate() = 0; // Notifies a change in the mixing state of a specific mix in a dynamic audio policy virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0; + // Notifies when a default effect set is attached to a session/stream + virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, + bool added) = 0; }; diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index cbc2ba6..0ac13b9 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -148,6 +148,7 @@ protected: kFlagIsSecure = 1, kFlagPushBlankBuffersToNativeWindowOnShutdown = 2, kFlagIsGrallocUsageProtected = 4, + kFlagPushBlankBuffersToNativeWindowOnSwitch = 1 << 7, }; enum { diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h index de5ddd3..d627fec 100644 --- a/include/media/stagefright/DataSource.h +++ b/include/media/stagefright/DataSource.h @@ -27,10 +27,10 @@ #include <utils/RefBase.h> #include <utils/threads.h> #include <drm/DrmManagerClient.h> +#include <media/stagefright/foundation/AMessage.h> namespace android { -struct AMessage; struct AString; class IDataSource; struct IMediaHTTPService; @@ -57,7 +57,7 @@ public: static sp<DataSource> CreateMediaHTTP(const sp<IMediaHTTPService> &httpService); static sp<DataSource> CreateFromIDataSource(const sp<IDataSource> &source); - DataSource() {} + DataSource() : mMeta(new AMessage) {} virtual status_t initCheck() const = 0; @@ -108,10 +108,14 @@ public: virtual String8 getMIMEType() const; + virtual sp<AMessage> meta() { return mMeta; } + protected: virtual ~DataSource() {} private: + sp<AMessage> mMeta; + static Mutex gSnifferMutex; static List<SnifferFunc> gSniffers; static List<SnifferFunc> gExtraSniffers; diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp index e01c414..f0afd39 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -3104,7 +3104,10 @@ int Effect_command(effect_handle_t self, //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM start"); effect_param_t *p = (effect_param_t *)pCmdData; - + if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { + android_errorWriteLog(0x534e4554, "26347509"); + return -EINVAL; + } if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL || replySize == NULL || diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp index a48a4e3..4dc8b45 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -1956,7 +1956,10 @@ int Reverb_command(effect_handle_t self, //ALOGV("\tReverb_command cmdCode Case: " // "EFFECT_CMD_GET_PARAM start"); effect_param_t *p = (effect_param_t *)pCmdData; - + if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { + android_errorWriteLog(0x534e4554, "26347509"); + return -EINVAL; + } if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL || replySize == NULL || diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 9d645f0..10ec495 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -37,7 +37,7 @@ sp<IAudioFlinger> AudioSystem::gAudioFlinger; sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL; - +effect_session_callback AudioSystem::gEffectSessionCallback = NULL; // establish binder interface to AudioFlinger service const sp<IAudioFlinger> AudioSystem::get_audio_flinger() @@ -652,6 +652,21 @@ status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( gDynPolicyCallback = cb; } +/*static*/ status_t AudioSystem::setEffectSessionCallback(effect_session_callback cb) +{ + const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + + Mutex::Autolock _l(gLock); + gEffectSessionCallback = cb; + + status_t status = aps->setEffectSessionCallbacksEnabled(cb != NULL); + if (status != OK) { + gEffectSessionCallback = NULL; + } + return status; +} + // client singleton for AudioPolicyService binder interface // protected by gLockAPS sp<IAudioPolicyService> AudioSystem::gAudioPolicyService; @@ -1223,6 +1238,21 @@ void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate( } } +void AudioSystem::AudioPolicyServiceClient::onOutputSessionEffectsUpdate( + audio_stream_type_t stream, audio_unique_id_t sessionId, bool added) +{ + ALOGV("AudioPolicyServiceClient::onOutputSessionEffectsUpdate(%d, %d, %d)", stream, sessionId, added); + effect_session_callback cb = NULL; + { + Mutex::Autolock _l(AudioSystem::gLock); + cb = gEffectSessionCallback; + } + + if (cb != NULL) { + cb(AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE, stream, sessionId, added); + } +} + void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused) { { diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 76b5924..6ff8149 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -74,6 +74,7 @@ enum { START_AUDIO_SOURCE, STOP_AUDIO_SOURCE, SET_AUDIO_PORT_CALLBACK_ENABLED, + SET_EFFECT_SESSION_CALLBACK_ENABLED, }; #define MAX_ITEMS_PER_LIST 1024 @@ -655,6 +656,18 @@ public: remote()->transact(SET_AUDIO_PORT_CALLBACK_ENABLED, data, &reply); } + virtual status_t setEffectSessionCallbacksEnabled(bool enabled) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(enabled ? 1 : 0); + status_t status = remote()->transact(SET_EFFECT_SESSION_CALLBACK_ENABLED, data, &reply); + if (status != NO_ERROR) { + return status; + } + return (status_t)reply.readInt32(); + } + virtual status_t acquireSoundTriggerSession(audio_session_t *session, audio_io_handle_t *ioHandle, audio_devices_t *device) @@ -1238,6 +1251,13 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case SET_EFFECT_SESSION_CALLBACK_ENABLED: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + status_t status = setEffectSessionCallbacksEnabled(data.readInt32() == 1); + reply->writeInt32(status); + return NO_ERROR; + } break; + case ACQUIRE_SOUNDTRIGGER_SESSION: { CHECK_INTERFACE(IAudioPolicyService, data, reply); sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>( diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp index 65cc7d6..d6207ce 100644 --- a/media/libmedia/IAudioPolicyServiceClient.cpp +++ b/media/libmedia/IAudioPolicyServiceClient.cpp @@ -30,7 +30,8 @@ namespace android { enum { PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION, PATCH_LIST_UPDATE, - MIX_STATE_UPDATE + MIX_STATE_UPDATE, + OUTPUT_SESSION_EFFECTS_UPDATE }; class BpAudioPolicyServiceClient : public BpInterface<IAudioPolicyServiceClient> @@ -63,6 +64,17 @@ public: data.writeInt32(state); remote()->transact(MIX_STATE_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); } + + void onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, bool added) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor()); + data.writeInt32(stream); + data.writeInt32(sessionId); + data.writeInt32(added ? 1 : 0); + remote()->transact(OUTPUT_SESSION_EFFECTS_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient"); @@ -90,6 +102,14 @@ status_t BnAudioPolicyServiceClient::onTransact( onDynamicPolicyMixStateUpdate(regId, state); return NO_ERROR; } + case OUTPUT_SESSION_EFFECTS_UPDATE: { + CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply); + audio_stream_type_t stream = static_cast<audio_stream_type_t>(data.readInt32()); + audio_unique_id_t sessionId = static_cast<audio_unique_id_t>(data.readInt32()); + bool added = data.readInt32() > 0; + onOutputSessionEffectsUpdate(stream, sessionId, added); + return NO_ERROR; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index da5bb9a..1e911c2 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1936,8 +1936,13 @@ void MediaPlayerService::AudioOutput::pause() void MediaPlayerService::AudioOutput::close() { ALOGV("close"); - Mutex::Autolock lock(mLock); - close_l(); + sp<AudioTrack> track; + { + Mutex::Autolock lock(mLock); + track = mTrack; + close_l(); // clears mTrack + } + // destruction of the track occurs outside of mutex. } void MediaPlayerService::AudioOutput::setVolume(float left, float right) diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index c4c5741..d182a68 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -963,6 +963,30 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() { } } + // If using QCOM extension (Camera 1 HAL) for slow motion recording + // mCaptureFpsEnable and mCaptureFps will not be set via setCaptureRate + // We need to query from AVUtil, in order to support slow motion audio recording + if (mVideoSourceNode != NULL) { + int hfrRatio = AVUtils::get()->HFRUtils().getHFRRatio(mVideoSourceNode->getFormat()); + if (hfrRatio != 1) { + // Upscale the sample rate for slow motion recording. + // Fail audio source creation if source sample rate is too high, as it could + // cause out-of-memory due to large input buffer size. And audio recording + // probably doesn't make sense in the scenario, since the slow-down factor + // is probably huge (eg. mSampleRate=48K, hfrRatio=240, mFrameRate=1). + const static int32_t SAMPLE_RATE_HZ_MAX = 192000; + sourceSampleRate = + (mSampleRate * hfrRatio + mFrameRate / 2) / mFrameRate; + if (sourceSampleRate < mSampleRate || sourceSampleRate > SAMPLE_RATE_HZ_MAX) { + ALOGE("source sample rate out of range! " + "(mSampleRate %d, hfrRatio %d, mFrameRate %d", + mSampleRate, hfrRatio, mFrameRate); + return NULL; + } + } + } + + sp<AudioSource> audioSource = AVFactory::get()->createAudioSource( mAudioSource, mOpPackageName, @@ -2044,10 +2068,16 @@ status_t StagefrightRecorder::setSourcePause(bool pause) { } } if (mAudioEncoderOMX != NULL) { - err = mAudioEncoderOMX->pause(); - if (err != OK) { - ALOGE("OMX AudioEncoder pause failed"); - return err; + if (mAudioEncoderOMX != mAudioSourceNode) { + err = mAudioEncoderOMX->pause(); + if (err != OK) { + ALOGE("OMX AudioEncoder pause failed"); + return err; + } + } else { + // If AudioSource is the same as MediaSource(as in LPCM), + // bypass omx encoder pause() call. + ALOGV("OMX AudioEncoder->pause() bypassed"); } } if (mVideoSourceNode != NULL) { @@ -2087,10 +2117,16 @@ status_t StagefrightRecorder::setSourcePause(bool pause) { } } if (mAudioEncoderOMX != NULL) { - err = mAudioEncoderOMX->start(); - if (err != OK) { - ALOGE("OMX AudioEncoder start failed"); - return err; + if (mAudioEncoderOMX != mAudioSourceNode) { + err = mAudioEncoderOMX->start(); + if (err != OK) { + ALOGE("OMX AudioEncoder start failed"); + return err; + } + } else { + // If AudioSource is the same as MediaSource(as in LPCM), + // bypass omx encoder start() call. + ALOGV("OMX AudioEncoder->start() bypassed"); } } } diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk index fbb1276..ff2a202 100644 --- a/media/libmediaplayerservice/nuplayer/Android.mk +++ b/media/libmediaplayerservice/nuplayer/Android.mk @@ -38,6 +38,10 @@ ifeq ($(TARGET_BOARD_PLATFORM),msm8974) LOCAL_CFLAGS += -DTARGET_8974 endif +ifeq ($(TARGET_NUPLAYER_CANNOT_SET_SURFACE_WITHOUT_A_FLUSH),true) +LOCAL_CFLAGS += -DCANNOT_SET_SURFACE_WITHOUT_A_FLUSH +endif + LOCAL_CLANG := true LOCAL_MODULE:= libstagefright_nuplayer diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index c87208c..1835101 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -660,7 +660,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { // When mStarted is true, mSource must have been set. if (mSource == NULL || !mStarted || mSource->getFormat(false /* audio */) == NULL // NOTE: mVideoDecoder's mSurface is always non-null - || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK)) { +#ifndef CANNOT_SET_SURFACE_WITHOUT_A_FLUSH + || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK) +#endif + ) { performSetSurface(surface); break; } @@ -932,10 +935,21 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { audio ? "audio" : "video", formatChange); if (formatChange) { - mDeferredActions.push_back( - new FlushDecoderAction( + int32_t seamlessChange = 0; + if (msg->findInt32("video-seamlessChange", &seamlessChange) && seamlessChange) { + ALOGE("video decoder seamlessChange in smooth streaming mode, " + "flush the video decoder"); + mDeferredActions.push_back( + new FlushDecoderAction(FLUSH_CMD_NONE, FLUSH_CMD_FLUSH)); + mDeferredActions.push_back(new ResumeDecoderAction(false)); + processDeferredActions(); + break; + } else { + mDeferredActions.push_back( + new FlushDecoderAction( audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE, audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN)); + } } mDeferredActions.push_back( diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index c505096..a18e1da 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -73,6 +73,7 @@ NuPlayer::Decoder::Decoder( mIsSecure(false), mFormatChangePending(false), mTimeChangePending(false), + mVideoFormatChangeDoFlushOnly(false), mResumePending(false), mComponentName("decoder") { mCodecLooper = new ALooper; @@ -243,6 +244,7 @@ void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) { mFormatChangePending = false; mTimeChangePending = false; + mVideoFormatChangeDoFlushOnly = false; ++mBufferGeneration; @@ -759,9 +761,20 @@ status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) { mTimeChangePending = true; err = ERROR_END_OF_STREAM; } else if (seamlessFormatChange) { - // reuse existing decoder and don't flush - rememberCodecSpecificData(newFormat); - continue; + if (!mIsAudio && + newFormat != NULL && + newFormat->contains("prefer-adaptive-playback")) { + ALOGV("in smooth streaming mode, " + "do video flush in video seamless format change"); + mFormatChangePending = true; + mVideoFormatChangeDoFlushOnly = true; + err = ERROR_END_OF_STREAM; + } else { + // reuse existing decoder and don't flush + rememberCodecSpecificData(newFormat); + continue; + } + } else { // This stream is unaffected by the discontinuity return -EWOULDBLOCK; @@ -989,10 +1002,14 @@ void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) { sp<AMessage> msg = mNotify->dup(); msg->setInt32("what", kWhatInputDiscontinuity); msg->setInt32("formatChange", mFormatChangePending); + if (mVideoFormatChangeDoFlushOnly) { + msg->setInt32("video-seamlessChange", mVideoFormatChangeDoFlushOnly); + } msg->post(); mFormatChangePending = false; mTimeChangePending = false; + mVideoFormatChangeDoFlushOnly = false; } bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange( diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h index 6e2b9d0..1fbefda 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h @@ -95,6 +95,7 @@ protected: bool mIsSecure; bool mFormatChangePending; bool mTimeChangePending; + bool mVideoFormatChangeDoFlushOnly; bool mResumePending; AString mComponentName; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 4807b65..b83d6c6 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -767,7 +767,8 @@ status_t ACodec::handleSetSurface(const sp<Surface> &surface) { } // push blank buffers to previous window if requested - if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) { + if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown || + mFlags & kFlagPushBlankBuffersToNativeWindowOnSwitch) { pushBlankBuffersToNativeWindow(mNativeWindow.get()); } @@ -925,10 +926,24 @@ status_t ACodec::setupNativeWindowSizeFormatAndUsage( #endif ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage); + int32_t width = 0, height = 0; + int32_t isAdaptivePlayback = 0; + + if (mInputFormat->findInt32("adaptive-playback", &isAdaptivePlayback) + && isAdaptivePlayback + && mInputFormat->findInt32("max-width", &width) + && mInputFormat->findInt32("max-height", &height)) { + width = max(width, (int32_t)def.format.video.nFrameWidth); + height = max(height, (int32_t)def.format.video.nFrameHeight); + ALOGV("Adaptive playback width = %d, height = %d", width, height); + } else { + width = def.format.video.nFrameWidth; + height = def.format.video.nFrameHeight; + } err = setNativeWindowSizeFormatAndUsage( nativeWindow, - def.format.video.nFrameWidth, - def.format.video.nFrameHeight, + width, + height, #ifdef USE_SAMSUNG_COLORFORMAT eNativeColorFormat, #else @@ -1969,6 +1984,12 @@ status_t ACodec::configureCodec( && push != 0) { mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; } + + int32_t val; + if (msg->findInt32("push-blank-buffers-on-switch", &val) + && val != 0) { + mFlags |= kFlagPushBlankBuffersToNativeWindowOnSwitch; + } } int32_t rotationDegrees; @@ -6760,6 +6781,11 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent( mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput); } + /* Clear the RenderQueue in which queued GraphicBuffers hold the + * actual buffer references in order to free them early. + */ + mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); + if (err == OK) { err = mCodec->allocateBuffersOnPort(kPortIndexOutput); ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index b833f9e..34f0649 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -38,7 +38,6 @@ #include <media/IMediaHTTPConnection.h> #include <media/IMediaHTTPService.h> #include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/DataURISource.h> #include <media/stagefright/FileSource.h> diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index c928495..c7c238e 100755 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -3325,11 +3325,13 @@ MPEG4Source::MPEG4Source( const uint8_t *ptr = (const uint8_t *)data; - CHECK(size >= 7); - CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 - - // The number of bytes used to encode the length of a NAL unit. - mNALLengthSize = 1 + (ptr[4] & 3); + if (size < 7 || ptr[0] != 1) { + ALOGE("Invalid AVCC atom, size %zu, configurationVersion: %d", + size, ptr[0]); + } else { + // The number of bytes used to encode the length of a NAL unit. + mNALLengthSize = 1 + (ptr[4] & 3); + } } else if (mIsHEVC) { uint32_t type; const void *data; @@ -4573,7 +4575,15 @@ status_t MPEG4Source::fragmentedRead( continue; } - CHECK(dstOffset + 4 <= mBuffer->size()); + if (dstOffset > SIZE_MAX - 4 || + dstOffset + 4 > SIZE_MAX - nalLength || + dstOffset + 4 + nalLength > mBuffer->size()) { + ALOGE("b/26365349 : %zu %zu", dstOffset, mBuffer->size()); + android_errorWriteLog(0x534e4554, "26365349"); + mBuffer->release(); + mBuffer = NULL; + return ERROR_MALFORMED; + } dstData[dstOffset++] = 0; dstData[dstOffset++] = 0; diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp index 3dc549e..08200c1 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp @@ -56,7 +56,8 @@ SoftVorbis::SoftVorbis( mNumFramesLeftOnPage(-1), mSawInputEos(false), mSignalledOutputEos(false), - mOutputPortSettingsChange(NONE) { + mOutputPortSettingsChange(NONE), + mSignalledError(false) { initPorts(); CHECK_EQ(initDecoder(), (status_t)OK); } @@ -251,10 +252,21 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) { return; } + if (mSignalledError) { + return; + } + if (portIndex == 0 && mInputBufferCount < 2) { BufferInfo *info = *inQueue.begin(); OMX_BUFFERHEADERTYPE *header = info->mHeader; + if (!header || !header->pBuffer) { + ALOGE("b/25727575 has happened. report error"); + notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); + mSignalledError = true; + return; + } + const uint8_t *data = header->pBuffer + header->nOffset; size_t size = header->nFilledLen; diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h index 1d00816..7decc5a 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h @@ -68,6 +68,8 @@ private: AWAITING_ENABLED } mOutputPortSettingsChange; + bool mSignalledError; + void initPorts(); status_t initDecoder(); bool isConfigured() const; diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index c1fa240..b2463e7 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -224,18 +224,19 @@ MatroskaSource::MatroskaSource( mIsAudio = !strncasecmp("audio/", mime, 6); if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { - mType = AVC; - uint32_t dummy; const uint8_t *avcc; size_t avccSize; CHECK(meta->findData( kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)); - CHECK_GE(avccSize, 5u); - - mNALSizeLen = 1 + (avcc[4] & 3); - ALOGV("mNALSizeLen = %zu", mNALSizeLen); + if (avccSize < 7) { + ALOGW("Invalid AVCC atom in track, size %zu", avccSize); + } else { + mNALSizeLen = 1 + (avcc[4] & 3); + ALOGV("mNALSizeLen = %zu", mNALSizeLen); + mType = AVC; + } } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) { mType = HEVC; diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 1f60924..c3ee6c2 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -1630,6 +1630,7 @@ void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& dprintf(fd, " Mixer buffer: %p\n", mMixerBuffer); dprintf(fd, " Effect buffer: %p\n", mEffectBuffer); dprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask); + dprintf(fd, " Standby delay ns=%lld\n", (long long)mStandbyDelayNs); AudioStreamOut *output = mOutput; audio_output_flags_t flags = output != NULL ? output->flags : AUDIO_OUTPUT_FLAG_NONE; String8 flagsAsString = outputFlagsToString(flags); @@ -2542,7 +2543,8 @@ The derived values that are cached: - mSinkBufferSize from frame count * frame size - mActiveSleepTimeUs from activeSleepTimeUs() - mIdleSleepTimeUs from idleSleepTimeUs() - - mStandbyDelayNs from mActiveSleepTimeUs (DIRECT only) + - mStandbyDelayNs from mActiveSleepTimeUs (DIRECT only) or forced to at least + kDefaultStandbyTimeInNsecs when connected to an A2DP device. - maxPeriod from frame count and sample rate (MIXER only) The parameters that affect these derived values are: @@ -2561,6 +2563,15 @@ void AudioFlinger::PlaybackThread::cacheParameters_l() mSinkBufferSize = mNormalFrameCount * mFrameSize; mActiveSleepTimeUs = activeSleepTimeUs(); mIdleSleepTimeUs = idleSleepTimeUs(); + + // make sure standby delay is not too short when connected to an A2DP sink to avoid + // truncating audio when going to standby. + mStandbyDelayNs = AudioFlinger::mStandbyTimeInNsecs; + if ((mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) { + if (mStandbyDelayNs < kDefaultStandbyTimeInNsecs) { + mStandbyDelayNs = kDefaultStandbyTimeInNsecs; + } + } } void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType) @@ -4319,6 +4330,7 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa status_t& status) { bool reconfig = false; + bool a2dpDeviceChanged = false; status = NO_ERROR; @@ -4398,6 +4410,8 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa // forward device change to effects that have requested to be // aware of attached audio device. if (value != AUDIO_DEVICE_NONE) { + a2dpDeviceChanged = + (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != (value & AUDIO_DEVICE_OUT_ALL_A2DP); mOutDevice = value; for (size_t i = 0; i < mEffectChains.size(); i++) { mEffectChains[i]->setDevice_l(mOutDevice); @@ -4441,7 +4455,7 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED); } - return reconfig; + return reconfig || a2dpDeviceChanged; } @@ -4877,6 +4891,7 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& key status_t& status) { bool reconfig = false; + bool a2dpDeviceChanged = false; status = NO_ERROR; @@ -4887,6 +4902,8 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& key // forward device change to effects that have requested to be // aware of attached audio device. if (value != AUDIO_DEVICE_NONE) { + a2dpDeviceChanged = + (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != (value & AUDIO_DEVICE_OUT_ALL_A2DP); mOutDevice = value; for (size_t i = 0; i < mEffectChains.size(); i++) { mEffectChains[i]->setDevice_l(mOutDevice); @@ -4919,7 +4936,7 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& key } } - return reconfig; + return reconfig || a2dpDeviceChanged; } uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk index 5b38e1c..69fc0e8 100644 --- a/services/audiopolicy/Android.mk +++ b/services/audiopolicy/Android.mk @@ -40,6 +40,10 @@ LOCAL_SHARED_LIBRARIES += \ libaudiopolicymanager endif +ifeq ($(BOARD_HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB),true) + LOCAL_CFLAGS += -DHAVE_PRE_KITKAT_AUDIO_POLICY_BLOB +endif + LOCAL_STATIC_LIBRARIES := \ libmedia_helper \ libaudiopolicycomponents diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index c1e7bc0..a5edc14 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -331,6 +331,9 @@ public: virtual audio_unique_id_t newAudioUniqueId() = 0; virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0; + + virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, bool added) = 0; }; extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface); diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 50b5087..13499ae 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -88,20 +88,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device, } ALOGV("setDeviceConnectionState() connecting device %x", device); -#ifdef LEGACY_ALSA_AUDIO - if (device & AUDIO_DEVICE_OUT_ALL_A2DP) { - AudioParameter param; - param.add(String8("a2dp_connected"), String8("true")); - mpClientInterface->setParameters(0, param.toString()); - } - - if (device & AUDIO_DEVICE_OUT_USB_ACCESSORY) { - AudioParameter param; - param.add(String8("usb_connected"), String8("true")); - mpClientInterface->setParameters(0, param.toString()); - } -#endif - // register new device as available index = mAvailableOutputDevices.add(devDesc); if (index >= 0) { @@ -153,20 +139,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device, // remove device from available output devices mAvailableOutputDevices.remove(devDesc); -#ifdef LEGACY_ALSA_AUDIO - if (device & AUDIO_DEVICE_OUT_ALL_A2DP) { - AudioParameter param; - param.add(String8("a2dp_connected"), String8("false")); - mpClientInterface->setParameters(0, param.toString()); - } - - if (device & AUDIO_DEVICE_OUT_USB_ACCESSORY) { - AudioParameter param; - param.add(String8("usb_connected"), String8("true")); - mpClientInterface->setParameters(0, param.toString()); - } -#endif - checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress); // Propagate device availability to Engine @@ -333,11 +305,7 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs if(!hasPrimaryOutput()) { return; } -#ifdef LEGACY_ALSA_AUDIO - audio_devices_t txDevice = getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_CALL); -#else audio_devices_t txDevice = getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION); -#endif ALOGV("updateCallRouting device rxDevice %08x txDevice %08x", rxDevice, txDevice); // release existing RX patch if any @@ -1423,22 +1391,6 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, } else { *inputType = API_INPUT_LEGACY; } -#ifdef LEGACY_ALSA_AUDIO - // adapt channel selection to input source - switch (inputSource) { - case AUDIO_SOURCE_VOICE_UPLINK: - channelMask |= AUDIO_CHANNEL_IN_VOICE_UPLINK; - break; - case AUDIO_SOURCE_VOICE_DOWNLINK: - channelMask |= AUDIO_CHANNEL_IN_VOICE_DNLINK; - break; - case AUDIO_SOURCE_VOICE_CALL: - channelMask |= AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK; - break; - default: - break; - } -#endif if (inputSource == AUDIO_SOURCE_HOTWORD) { ssize_t index = mSoundTriggerSessions.indexOfKey(session); if (index >= 0) { @@ -3947,13 +3899,11 @@ void AudioPolicyManager::checkOutputForAllStrategies() void AudioPolicyManager::checkA2dpSuspend() { -#ifndef LEGACY_ALSA_AUDIO audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput(); if (a2dpOutput == 0) { mA2dpSuspended = false; return; } -#endif bool isScoConnected = ((mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET & @@ -3978,9 +3928,7 @@ void AudioPolicyManager::checkA2dpSuspend() ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) && (mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) { -#ifndef LEGACY_ALSA_AUDIO mpClientInterface->restoreOutput(a2dpOutput); -#endif mA2dpSuspended = false; } } else { @@ -3990,9 +3938,7 @@ void AudioPolicyManager::checkA2dpSuspend() ((mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) || (mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) { -#ifndef LEGACY_ALSA_AUDIO mpClientInterface->suspendOutput(a2dpOutput); -#endif mA2dpSuspended = true; } } diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp index 489a9be..d71daa4 100644 --- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp @@ -219,6 +219,12 @@ void AudioPolicyService::AudioPolicyClient::onDynamicPolicyMixStateUpdate( mAudioPolicyService->onDynamicPolicyMixStateUpdate(regId, state); } +void AudioPolicyService::AudioPolicyClient::onOutputSessionEffectsUpdate( + audio_stream_type_t stream, audio_unique_id_t sessionId, bool added) +{ + mAudioPolicyService->onOutputSessionEffectsUpdate(stream, sessionId, added); +} + audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId() { return AudioSystem::newAudioUniqueId(); diff --git a/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp index a79f8ae..36c85f1 100644 --- a/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp +++ b/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp @@ -125,8 +125,13 @@ audio_io_handle_t aps_open_output_on_module(void *service __unused, audio_output_flags_t flags, const audio_offload_info_t *offloadInfo) { +#ifdef HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB + return open_output(module, pDevices, pSamplingRate, pFormat, pChannelMask, + pLatencyMs, flags, NULL); +#else return open_output(module, pDevices, pSamplingRate, pFormat, pChannelMask, pLatencyMs, flags, offloadInfo); +#endif } audio_io_handle_t aps_open_dup_output(void *service __unused, diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp index 26857b1..f2d7f6f 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.cpp +++ b/services/audiopolicy/service/AudioPolicyEffects.cpp @@ -28,6 +28,7 @@ #include <utils/Vector.h> #include <utils/SortedVector.h> #include <cutils/config_utils.h> +#include "AudioPolicyService.h" #include "AudioPolicyEffects.h" #include "ServiceUtilities.h" @@ -37,7 +38,8 @@ namespace android { // AudioPolicyEffects Implementation // ---------------------------------------------------------------------------- -AudioPolicyEffects::AudioPolicyEffects() +AudioPolicyEffects::AudioPolicyEffects(AudioPolicyService *audioPolicyService) : + mAudioPolicyService(audioPolicyService) { // load automatic audio effect modules if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE2, R_OK) == 0) { @@ -244,6 +246,8 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output, if (idx < 0) { procDesc = new EffectVector(audioSession); mOutputSessions.add(audioSession, procDesc); + + mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, true); } else { // EffectVector is existing and we just need to increase ref count procDesc = mOutputSessions.valueAt(idx); @@ -291,15 +295,49 @@ status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t outpu } EffectVector *procDesc = mOutputSessions.valueAt(index); + + // just in case it already has a death wish + if (procDesc->mRefCount == 0) { + return NO_ERROR; + } + procDesc->mRefCount--; ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d", audioSession, procDesc->mRefCount); + + if (procDesc->mRefCount == 0) { + mAudioPolicyService->releaseOutputSessionEffectsDelayed( + output, stream, audioSession, 10000); + } + + return status; +} + +status_t AudioPolicyEffects::doReleaseOutputSessionEffects(audio_io_handle_t output, + audio_stream_type_t stream, + int audioSession) +{ + status_t status = NO_ERROR; + (void) output; // argument not used for now + + Mutex::Autolock _l(mLock); + ssize_t index = mOutputSessions.indexOfKey(audioSession); + if (index < 0) { + ALOGV("doReleaseOutputSessionEffects: no output processing was attached to this stream"); + return NO_ERROR; + } + + EffectVector *procDesc = mOutputSessions.valueAt(index); + ALOGV("doReleaseOutputSessionEffects(): session: %d, refCount: %d", + audioSession, procDesc->mRefCount); + if (procDesc->mRefCount == 0) { procDesc->setProcessorEnabled(false); procDesc->mEffects.clear(); delete procDesc; mOutputSessions.removeItemsAt(index); - ALOGV("releaseOutputSessionEffects(): output processing released from session: %d", + mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, false); + ALOGV("doReleaseOutputSessionEffects(): output processing released from session: %d", audioSession); } return status; diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h index 3845050..7988515 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.h +++ b/services/audiopolicy/service/AudioPolicyEffects.h @@ -31,6 +31,8 @@ namespace android { +class AudioPolicyService; + // ---------------------------------------------------------------------------- // AudioPolicyEffects class @@ -44,7 +46,7 @@ public: // The constructor will parse audio_effects.conf // First it will look whether vendor specific file exists, // otherwise it will parse the system default file. - AudioPolicyEffects(); + AudioPolicyEffects(AudioPolicyService *audioPolicyService); virtual ~AudioPolicyEffects(); // NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService @@ -84,6 +86,12 @@ public: audio_stream_type_t stream, int audioSession); + // For deferred release + status_t doReleaseOutputSessionEffects(audio_io_handle_t output, + audio_stream_type_t stream, + int audioSession); + + private: // class to store the description of an effects and its parameters @@ -192,6 +200,8 @@ private: KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams; // Automatic output effects are unique for audiosession ID KeyedVector< int32_t, EffectVector* > mOutputSessions; + + AudioPolicyService *mAudioPolicyService; }; }; // namespace android diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp index f76b5c8..318c6d2 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp @@ -275,6 +275,11 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, return BAD_VALUE; } +#ifdef HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB + if (inputSource == AUDIO_SOURCE_HOTWORD) + inputSource = AUDIO_SOURCE_VOICE_RECOGNITION; +#endif + sp<AudioPolicyEffects>audioPolicyEffects; { Mutex::Autolock _l(mLock); @@ -524,6 +529,9 @@ status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession, bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info) { +#ifdef HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB + return false; +#else if (mpAudioPolicy == NULL) { ALOGV("mpAudioPolicy == NULL"); return false; @@ -535,6 +543,7 @@ bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info) } return mpAudioPolicy->is_offload_supported(mpAudioPolicy, &info); +#endif } status_t AudioPolicyService::listAudioPorts(audio_port_role_t role __unused, diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 12cca65..58cfe37 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -116,7 +116,7 @@ void AudioPolicyService::onFirstRef() #endif } // load audio processing modules - sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(); + sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(this); { Mutex::Autolock _l(mLock); mAudioPolicyEffects = audioPolicyEffects; @@ -177,6 +177,23 @@ void AudioPolicyService::setAudioPortCallbacksEnabled(bool enabled) mNotificationClients.valueFor(uid)->setAudioPortCallbacksEnabled(enabled); } +status_t AudioPolicyService::setEffectSessionCallbacksEnabled(bool enabled) +{ + Mutex::Autolock _l(mNotificationClientsLock); + + uid_t uid = IPCThreadState::self()->getCallingUid(); + if (mNotificationClients.indexOfKey(uid) < 0) { + return NO_INIT; + } + if (!modifyAudioRoutingAllowed()) { + ALOGE("setEffectSessionCallbacksEnabled requires MODIFY_AUDIO_ROUTING"); + return PERMISSION_DENIED; + } + mNotificationClients.valueFor(uid)->setEffectSessionCallbacksEnabled(enabled); + return OK; +} + + // removeNotificationClient() is called when the client process dies. void AudioPolicyService::removeNotificationClient(uid_t uid) { @@ -254,11 +271,31 @@ status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_co return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs); } +void AudioPolicyService::onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, + bool added) +{ + ALOGV("AudioPolicyService::onOutputSessionEffectsUpdate(%d, %d, %d)", + stream, sessionId, added); + mOutputCommandThread->effectSessionUpdateCommand(stream, sessionId, added); +} + +void AudioPolicyService::doOnOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, + bool added) +{ + Mutex::Autolock _l(mNotificationClientsLock); + for (size_t i = 0; i < mNotificationClients.size(); i++) { + mNotificationClients.valueAt(i)->onOutputSessionEffectsUpdate(stream, sessionId, added); + } +} + AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service, const sp<IAudioPolicyServiceClient>& client, uid_t uid) : mService(service), mUid(uid), mAudioPolicyServiceClient(client), - mAudioPortCallbacksEnabled(false) + mAudioPortCallbacksEnabled(false), + mEffectSessionCallbacksEnabled(false) { } @@ -289,6 +326,14 @@ void AudioPolicyService::NotificationClient::onAudioPatchListUpdate() } } +void AudioPolicyService::NotificationClient::onOutputSessionEffectsUpdate( + audio_stream_type_t stream, audio_unique_id_t sessionId, bool added) +{ + if (mAudioPolicyServiceClient != 0 && mEffectSessionCallbacksEnabled) { + mAudioPolicyServiceClient->onOutputSessionEffectsUpdate(stream, sessionId, added); + } +} + void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate( String8 regId, int32_t state) { @@ -302,12 +347,23 @@ void AudioPolicyService::NotificationClient::setAudioPortCallbacksEnabled(bool e mAudioPortCallbacksEnabled = enabled; } +void AudioPolicyService::NotificationClient::setEffectSessionCallbacksEnabled(bool enabled) +{ + mEffectSessionCallbacksEnabled = enabled; +} void AudioPolicyService::binderDied(const wp<IBinder>& who) { ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(), IPCThreadState::self()->getCallingPid()); } +void AudioPolicyService::releaseOutputSessionEffectsDelayed( + audio_io_handle_t output, audio_stream_type_t stream, + audio_unique_id_t sessionId, int delayMs) +{ + mAudioCommandThread->releaseOutputSessionEffectsCommand(output, stream, sessionId, delayMs); +} + static bool tryLock(Mutex& mutex) { bool locked = false; @@ -579,6 +635,35 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() svc->doOnDynamicPolicyMixStateUpdate(data->mRegId, data->mState); mLock.lock(); } break; + case EFFECT_SESSION_UPDATE: { + EffectSessionUpdateData *data = + (EffectSessionUpdateData *)command->mParam.get(); + ALOGV("AudioCommandThread() processing effect session update %d %d %d", + data->mStream, data->mSessionId, data->mAdded); + svc = mService.promote(); + if (svc == 0) { + break; + } + mLock.unlock(); + svc->doOnOutputSessionEffectsUpdate(data->mStream, data->mSessionId, data->mAdded); + mLock.lock(); + } break; + case RELEASE_OUTPUT_SESSION_EFFECTS: { + ReleaseOutputSessionEffectsData *data = + (ReleaseOutputSessionEffectsData *)command->mParam.get(); + ALOGV("AudioCommandThread() processing release output session effects %d %d %d", + data->mOutput, data->mStream, data->mSessionId); + svc = mService.promote(); + if (svc == 0) { + break; + } + mLock.unlock(); + svc->mAudioPolicyEffects->doReleaseOutputSessionEffects( + data->mOutput, data->mStream, data->mSessionId); + mLock.lock(); + } break; + + default: ALOGW("AudioCommandThread() unknown command %d", command->mCommand); } @@ -851,6 +936,38 @@ void AudioPolicyService::AudioCommandThread::dynamicPolicyMixStateUpdateCommand( sendCommand(command); } +void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand( + audio_stream_type_t stream, audio_unique_id_t sessionId, bool added) +{ + sp<AudioCommand> command = new AudioCommand(); + command->mCommand = EFFECT_SESSION_UPDATE; + EffectSessionUpdateData *data = new EffectSessionUpdateData(); + data->mStream = stream; + data->mSessionId = sessionId; + data->mAdded = added; + command->mParam = data; + ALOGV("AudioCommandThread() sending effect session update (id=%d) for stream %d (added=%d)", + stream, sessionId, added); + sendCommand(command); +} + +void AudioPolicyService::AudioCommandThread::releaseOutputSessionEffectsCommand( + audio_io_handle_t output, audio_stream_type_t stream, + audio_unique_id_t sessionId, int delayMs) +{ + sp<AudioCommand> command = new AudioCommand(); + command->mCommand = RELEASE_OUTPUT_SESSION_EFFECTS; + ReleaseOutputSessionEffectsData *data = new ReleaseOutputSessionEffectsData(); + data->mOutput = output; + data->mStream = stream; + data->mSessionId = sessionId; + command->mParam = data; + ALOGV("AudioCommandThread() sending release output session effects (id=%d) for stream %d", + sessionId, stream); + sendCommand(command, delayMs); +} + + status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs) { { diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index d11294b..9b17a26 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -202,6 +202,8 @@ public: audio_io_handle_t *handle); virtual status_t stopAudioSource(audio_io_handle_t handle); + virtual status_t setEffectSessionCallbacksEnabled(bool enabled); + status_t doStartOutput(audio_io_handle_t output, audio_stream_type_t stream, audio_session_t session); @@ -229,6 +231,15 @@ public: void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state); + void onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, bool added); + void doOnOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, bool added); + void releaseOutputSessionEffectsDelayed(audio_io_handle_t output, + audio_stream_type_t stream, + audio_unique_id_t sessionId, + int delayMs); + private: AudioPolicyService() ANDROID_API; virtual ~AudioPolicyService(); @@ -260,7 +271,9 @@ private: UPDATE_AUDIOPORT_LIST, UPDATE_AUDIOPATCH_LIST, SET_AUDIOPORT_CONFIG, - DYN_POLICY_MIX_STATE_UPDATE + DYN_POLICY_MIX_STATE_UPDATE, + EFFECT_SESSION_UPDATE, + RELEASE_OUTPUT_SESSION_EFFECTS, }; AudioCommandThread (String8 name, const wp<AudioPolicyService>& service); @@ -303,6 +316,12 @@ private: int delayMs); void dynamicPolicyMixStateUpdateCommand(String8 regId, int32_t state); void insertCommand_l(AudioCommand *command, int delayMs = 0); + void effectSessionUpdateCommand(audio_stream_type_t stream, + audio_unique_id_t sessionId, bool added); + void releaseOutputSessionEffectsCommand(audio_io_handle_t output, + audio_stream_type_t stream, + audio_unique_id_t sessionId, + int delayMs = 0); private: class AudioCommandData; @@ -399,6 +418,20 @@ private: int32_t mState; }; + class EffectSessionUpdateData : public AudioCommandData { + public: + audio_stream_type_t mStream; + audio_unique_id_t mSessionId; + bool mAdded; + }; + + class ReleaseOutputSessionEffectsData : public AudioCommandData { + public: + audio_io_handle_t mOutput; + audio_stream_type_t mStream; + audio_unique_id_t mSessionId; + }; + Mutex mLock; Condition mWaitWorkCV; Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands @@ -508,6 +541,9 @@ private: virtual audio_unique_id_t newAudioUniqueId(); + virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, bool added); + private: AudioPolicyService *mAudioPolicyService; }; @@ -524,7 +560,9 @@ private: void onAudioPatchListUpdate(); void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); void setAudioPortCallbacksEnabled(bool enabled); - + void setEffectSessionCallbacksEnabled(bool enabled); + void onOutputSessionEffectsUpdate(audio_stream_type_t stream, + audio_unique_id_t sessionId, bool added); // IBinder::DeathRecipient virtual void binderDied(const wp<IBinder>& who); @@ -536,6 +574,7 @@ private: const uid_t mUid; const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient; bool mAudioPortCallbacksEnabled; + bool mEffectSessionCallbacksEnabled; }; // Internal dump utilities. diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 3deb396..a560b93 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -153,6 +153,7 @@ void CameraService::onFirstRef() ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err)); logServiceError("Could not load camera HAL module", err); mNumberOfCameras = 0; + mNumberOfNormalCameras = 0; return; } @@ -1944,6 +1945,14 @@ void CameraService::BasicClient::disconnect() { mClientPid = 0; } +status_t CameraService::BasicClient::dump(int, const Vector<String16>&) { + // No dumping of clients directly over Binder, + // must go through CameraService::dump + android_errorWriteWithInfoLog(SN_EVENT_LOG_ID, "26265403", + IPCThreadState::self()->getCallingUid(), NULL, 0); + return OK; +} + String16 CameraService::BasicClient::getPackageName() const { return mClientPackageName; } @@ -2396,7 +2405,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) { String8(client->getPackageName()).string()); write(fd, result.string(), result.size()); - client->dump(fd, args); + client->dumpClient(fd, args); } if (stateLocked) mCameraStatesLock.unlock(); diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index ce026b9..ee4c3f9 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -91,6 +91,9 @@ public: // Default number of messages to store in eviction log static const size_t DEFAULT_EVENT_LOG_LENGTH = 100; + // Event log ID + static const int SN_EVENT_LOG_ID = 0x534e4554; + // Implementation of BinderService<T> static char const* getServiceName() { return "media.camera"; } @@ -205,7 +208,10 @@ public: return mRemoteBinder; } - virtual status_t dump(int fd, const Vector<String16>& args) = 0; + // Disallows dumping over binder interface + virtual status_t dump(int fd, const Vector<String16>& args); + // Internal dump method to be called by CameraService + virtual status_t dumpClient(int fd, const Vector<String16>& args) = 0; // Return the package name for this client virtual String16 getPackageName() const; diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index 1821636..96266ed 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -163,6 +163,10 @@ Camera2Client::~Camera2Client() { } status_t Camera2Client::dump(int fd, const Vector<String16>& args) { + return BasicClient::dump(fd, args); +} + +status_t Camera2Client::dumpClient(int fd, const Vector<String16>& args) { String8 result; result.appendFormat("Client2[%d] (%p) PID: %d, dump:\n", mCameraId, (getRemoteCallback() != NULL ? diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h index d50bf63..7e7a284 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.h +++ b/services/camera/libcameraservice/api1/Camera2Client.h @@ -100,6 +100,8 @@ public: virtual status_t dump(int fd, const Vector<String16>& args); + virtual status_t dumpClient(int fd, const Vector<String16>& args); + /** * Interface used by CameraDeviceBase */ diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp index af0d680..55555fd 100644 --- a/services/camera/libcameraservice/api1/CameraClient.cpp +++ b/services/camera/libcameraservice/api1/CameraClient.cpp @@ -111,6 +111,10 @@ CameraClient::~CameraClient() { } status_t CameraClient::dump(int fd, const Vector<String16>& args) { + return BasicClient::dump(fd, args); +} + +status_t CameraClient::dumpClient(int fd, const Vector<String16>& args) { const size_t SIZE = 256; char buffer[SIZE]; diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h index 9d2d02f..d2cb64a 100644 --- a/services/camera/libcameraservice/api1/CameraClient.h +++ b/services/camera/libcameraservice/api1/CameraClient.h @@ -70,7 +70,9 @@ public: status_t initialize(CameraModule *module); - status_t dump(int fd, const Vector<String16>& args); + virtual status_t dump(int fd, const Vector<String16>& args); + + virtual status_t dumpClient(int fd, const Vector<String16>& args); private: diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index 0c531c3..bd9fea3 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -787,8 +787,11 @@ status_t CameraDeviceClient::tearDown(int streamId) { return res; } - status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) { + return BasicClient::dump(fd, args); +} + +status_t CameraDeviceClient::dumpClient(int fd, const Vector<String16>& args) { String8 result; result.appendFormat("CameraDeviceClient[%d] (%p) dump:\n", mCameraId, diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h index d1e692c..b1d1762 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.h +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h @@ -135,6 +135,8 @@ public: virtual status_t dump(int fd, const Vector<String16>& args); + virtual status_t dumpClient(int fd, const Vector<String16>& args); + /** * Device listener interface */ diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp index 5732f80..c7de56a 100644 --- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp +++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp @@ -124,7 +124,7 @@ Camera2ClientBase<TClientBase>::~Camera2ClientBase() { } template <typename TClientBase> -status_t Camera2ClientBase<TClientBase>::dump(int fd, +status_t Camera2ClientBase<TClientBase>::dumpClient(int fd, const Vector<String16>& args) { String8 result; result.appendFormat("Camera2ClientBase[%d] (%p) PID: %d, dump:\n", diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h index 220c5ad..4568af0 100644 --- a/services/camera/libcameraservice/common/Camera2ClientBase.h +++ b/services/camera/libcameraservice/common/Camera2ClientBase.h @@ -57,7 +57,7 @@ public: virtual ~Camera2ClientBase(); virtual status_t initialize(CameraModule *module); - virtual status_t dump(int fd, const Vector<String16>& args); + virtual status_t dumpClient(int fd, const Vector<String16>& args); /** * CameraDeviceBase::NotificationListener implementation |