diff options
Diffstat (limited to 'media/libmedia')
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 76 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 59 | ||||
-rw-r--r-- | media/libmedia/AudioTrackShared.cpp | 27 | ||||
-rw-r--r-- | media/libmedia/IAudioPolicyService.cpp | 15 | ||||
-rw-r--r-- | media/libmedia/ICrypto.cpp | 22 | ||||
-rw-r--r-- | media/libmedia/IDrm.cpp | 43 | ||||
-rw-r--r-- | media/libmedia/Visualizer.cpp | 19 |
7 files changed, 172 insertions, 89 deletions
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index dda3657..fce4389 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -32,6 +32,8 @@ namespace android { // client singleton for AudioFlinger binder interface Mutex AudioSystem::gLock; +Mutex AudioSystem::gLockAPS; +Mutex AudioSystem::gLockAPC; sp<IAudioFlinger> AudioSystem::gAudioFlinger; sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; @@ -70,9 +72,9 @@ const sp<IAudioFlinger>& AudioSystem::get_audio_flinger() } binder->linkToDeath(gAudioFlingerClient); gAudioFlinger = interface_cast<IAudioFlinger>(binder); + LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0); gAudioFlinger->registerClient(gAudioFlingerClient); } - ALOGE_IF(gAudioFlinger==0, "no AudioFlinger!?"); return gAudioFlinger; } @@ -245,19 +247,6 @@ status_t AudioSystem::getOutputSamplingRate(uint32_t* samplingRate, audio_stream return getSamplingRate(output, samplingRate); } -status_t AudioSystem::getOutputSamplingRateForAttr(uint32_t* samplingRate, - const audio_attributes_t *attr) -{ - if (attr == NULL) { - return BAD_VALUE; - } - audio_io_handle_t output = getOutputForAttr(attr); - if (output == 0) { - return PERMISSION_DENIED; - } - return getSamplingRate(output, samplingRate); -} - status_t AudioSystem::getSamplingRate(audio_io_handle_t output, uint32_t* samplingRate) { @@ -543,22 +532,8 @@ void AudioSystem::setErrorCallback(audio_error_callback cb) gAudioErrorCallback = cb; } - -bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType) -{ - switch (streamType) { - case AUDIO_STREAM_MUSIC: - case AUDIO_STREAM_VOICE_CALL: - case AUDIO_STREAM_BLUETOOTH_SCO: - case AUDIO_STREAM_SYSTEM: - return true; - default: - return false; - } -} - - // client singleton for AudioPolicyService binder interface +// protected by gLockAPS sp<IAudioPolicyService> AudioSystem::gAudioPolicyService; sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient; @@ -566,7 +541,7 @@ sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient // establish binder interface to AudioPolicy service const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service() { - gLock.lock(); + Mutex::Autolock _l(gLockAPS); if (gAudioPolicyService == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; @@ -582,15 +557,10 @@ const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service() } binder->linkToDeath(gAudioPolicyServiceClient); gAudioPolicyService = interface_cast<IAudioPolicyService>(binder); - gLock.unlock(); - // Registering the client takes the AudioPolicyService lock. - // Don't hold the AudioSystem lock at the same time. + LOG_ALWAYS_FATAL_IF(gAudioPolicyService == 0); gAudioPolicyService->registerClient(gAudioPolicyServiceClient); - } else { - // There exists a benign race condition where gAudioPolicyService - // is set, but gAudioPolicyServiceClient is not yet registered. - gLock.unlock(); } + return gAudioPolicyService; } @@ -856,9 +826,18 @@ status_t AudioSystem::setLowRamDevice(bool isLowRamDevice) void AudioSystem::clearAudioConfigCache() { - Mutex::Autolock _l(gLock); + // called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances ALOGV("clearAudioConfigCache()"); - gOutputs.clear(); + { + Mutex::Autolock _l(gLock); + gOutputs.clear(); + gAudioFlinger.clear(); + } + { + Mutex::Autolock _l(gLockAPS); + gAudioPolicyService.clear(); + } + // Do not clear gAudioPortCallback } bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info) @@ -920,7 +899,7 @@ status_t AudioSystem::setAudioPortConfig(const struct audio_port_config *config) void AudioSystem::setAudioPortCallback(sp<AudioPortCallback> callBack) { - Mutex::Autolock _l(gLock); + Mutex::Autolock _l(gLockAPC); gAudioPortCallback = callBack; } @@ -952,18 +931,23 @@ audio_mode_t AudioSystem::getPhoneState() void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused) { - Mutex::Autolock _l(gLock); - if (gAudioPortCallback != 0) { - gAudioPortCallback->onServiceDied(); + { + Mutex::Autolock _l(gLockAPC); + if (gAudioPortCallback != 0) { + gAudioPortCallback->onServiceDied(); + } + } + { + Mutex::Autolock _l(gLockAPS); + AudioSystem::gAudioPolicyService.clear(); } - AudioSystem::gAudioPolicyService.clear(); ALOGW("AudioPolicyService server died!"); } void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate() { - Mutex::Autolock _l(gLock); + Mutex::Autolock _l(gLockAPC); if (gAudioPortCallback != 0) { gAudioPortCallback->onAudioPortListUpdate(); } @@ -971,7 +955,7 @@ void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate() void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate() { - Mutex::Autolock _l(gLock); + Mutex::Autolock _l(gLockAPC); if (gAudioPortCallback != 0) { gAudioPortCallback->onAudioPatchListUpdate(); } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 5379809..b45a420 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -278,7 +278,9 @@ status_t AudioTrack::set( } // handle default values first. - if (streamType == AUDIO_STREAM_DEFAULT) { + // TODO once AudioPolicyManager fully supports audio_attributes_t, + // remove stream "text-to-speech" redirect + if ((streamType == AUDIO_STREAM_DEFAULT) || (streamType == AUDIO_STREAM_TTS)) { streamType = AUDIO_STREAM_MUSIC; } @@ -302,17 +304,6 @@ status_t AudioTrack::set( mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags); } - status_t status; - if (sampleRate == 0) { - status = AudioSystem::getOutputSamplingRateForAttr(&sampleRate, &mAttributes); - if (status != NO_ERROR) { - ALOGE("Could not get output sample rate for stream type %d; status %d", - mStreamType, status); - return status; - } - } - mSampleRate = sampleRate; - // these below should probably come from the audioFlinger too... if (format == AUDIO_FORMAT_DEFAULT) { format = AUDIO_FORMAT_PCM_16_BIT; @@ -371,6 +362,12 @@ status_t AudioTrack::set( // so no need to check for specific PCM formats here } + // sampling rate must be specified for direct outputs + if (sampleRate == 0 && (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) { + return BAD_VALUE; + } + mSampleRate = sampleRate; + // Make copy of input parameter offloadInfo so that in the future: // (a) createTrack_l doesn't need it as an input parameter // (b) we can support re-creation of offloaded tracks @@ -411,7 +408,7 @@ status_t AudioTrack::set( } // create the IAudioTrack - status = createTrack_l(); + status_t status = createTrack_l(); if (status != NO_ERROR) { if (mAudioTrackThread != 0) { @@ -678,15 +675,18 @@ status_t AudioTrack::setSampleRate(uint32_t rate) return INVALID_OPERATION; } + AutoMutex lock(mLock); + if (mOutput == AUDIO_IO_HANDLE_NONE) { + return NO_INIT; + } uint32_t afSamplingRate; - if (AudioSystem::getOutputSamplingRateForAttr(&afSamplingRate, &mAttributes) != NO_ERROR) { + if (AudioSystem::getSamplingRate(mOutput, &afSamplingRate) != NO_ERROR) { return NO_INIT; } if (rate == 0 || rate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) { return BAD_VALUE; } - AutoMutex lock(mLock); mSampleRate = rate; mProxy->setSampleRate(rate); @@ -961,7 +961,9 @@ status_t AudioTrack::createTrack_l() ALOGE("getSamplingRate(output=%d) status %d", output, status); goto release; } - + if (mSampleRate == 0) { + mSampleRate = afSampleRate; + } // Client decides whether the track is TIMED (see below), but can only express a preference // for FAST. Server will perform additional tests. if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) && !(( @@ -1826,7 +1828,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) status_t result; // refresh the audio configuration cache in this process to make sure we get new - // output parameters in createTrack_l() + // output parameters and new IAudioFlinger in createTrack_l() AudioSystem::clearAudioConfigCache(); if (isOffloadedOrDirect_l()) { @@ -2124,17 +2126,30 @@ void AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) { mStreamType = AUDIO_STREAM_BLUETOOTH_SCO; return; } + // TODO once AudioPolicyManager fully supports audio_attributes_t, + // remove stream remap, the flag will be enough + if ((aa.flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) { + mStreamType = AUDIO_STREAM_TTS; + return; + } // usage to stream type mapping switch (aa.usage) { - case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: { // TODO once AudioPolicyManager fully supports audio_attributes_t, - // remove stream change based on phone state - if (AudioSystem::getPhoneState() == AUDIO_MODE_RINGTONE) { + // remove stream change based on stream activity + bool active; + status_t status = AudioSystem::isStreamActive(AUDIO_STREAM_RING, &active, 0); + if (status == NO_ERROR && active == true) { mStreamType = AUDIO_STREAM_RING; break; } - /// FALL THROUGH + status = AudioSystem::isStreamActive(AUDIO_STREAM_ALARM, &active, 0); + if (status == NO_ERROR && active == true) { + mStreamType = AUDIO_STREAM_ALARM; + break; + } + } /// FALL THROUGH case AUDIO_USAGE_MEDIA: case AUDIO_USAGE_GAME: case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: @@ -2174,7 +2189,7 @@ void AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) { bool AudioTrack::isValidAttributes(const audio_attributes_t *paa) { // has flags that map to a strategy? - if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO)) != 0) { + if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) { return true; } diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index eec025e..561cb24 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -348,7 +348,13 @@ size_t ClientProxy::getFramesFilled() { void AudioTrackClientProxy::flush() { - mCblk->u.mStreaming.mFlush++; + // This works for mFrameCountP2 <= 2^30 + size_t increment = mFrameCountP2 << 1; + size_t mask = increment - 1; + audio_track_cblk_t* cblk = mCblk; + int32_t newFlush = (cblk->u.mStreaming.mRear & mask) | + ((cblk->u.mStreaming.mFlush & ~mask) + increment); + android_atomic_release_store(newFlush, &cblk->u.mStreaming.mFlush); } bool AudioTrackClientProxy::clearStreamEndDone() { @@ -536,17 +542,27 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); front = cblk->u.mStreaming.mFront; if (flush != mFlush) { - mFlush = flush; // effectively obtain then release whatever is in the buffer - android_atomic_release_store(rear, &cblk->u.mStreaming.mFront); - if (front != rear) { + size_t mask = (mFrameCountP2 << 1) - 1; + int32_t newFront = (front & ~mask) | (flush & mask); + ssize_t filled = rear - newFront; + // Rather than shutting down on a corrupt flush, just treat it as a full flush + if (!(0 <= filled && (size_t) filled <= mFrameCount)) { + ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, filled %d=%#x", + mFlush, flush, front, rear, mask, newFront, filled, filled); + newFront = rear; + } + mFlush = flush; + android_atomic_release_store(newFront, &cblk->u.mStreaming.mFront); + // There is no danger from a false positive, so err on the side of caution + if (true /*front != newFront*/) { int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); if (!(old & CBLK_FUTEX_WAKE)) { (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } } - front = rear; + front = newFront; } } else { front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront); @@ -668,6 +684,7 @@ size_t AudioTrackServerProxy::framesReady() int32_t flush = cblk->u.mStreaming.mFlush; if (flush != mFlush) { + // FIXME should return an accurate value, but over-estimate is better than under-estimate return mFrameCount; } // the acquire might not be necessary since not doing a subsequent read diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 99fd525..9349662 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -23,6 +23,7 @@ #include <binder/Parcel.h> +#include <media/AudioEffect.h> #include <media/IAudioPolicyService.h> #include <system/audio.h> @@ -704,8 +705,8 @@ status_t BnAudioPolicyService::onTransact( case GET_OUTPUT_FOR_ATTR: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - audio_attributes_t *attr = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t)); - data.read(attr, sizeof(audio_attributes_t)); + audio_attributes_t attr; + data.read(&attr, sizeof(audio_attributes_t)); uint32_t samplingRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); @@ -716,7 +717,7 @@ status_t BnAudioPolicyService::onTransact( if (hasOffloadInfo) { data.read(&offloadInfo, sizeof(audio_offload_info_t)); } - audio_io_handle_t output = getOutputForAttr(attr, + audio_io_handle_t output = getOutputForAttr(&attr, samplingRate, format, channelMask, @@ -916,16 +917,18 @@ status_t BnAudioPolicyService::onTransact( CHECK_INTERFACE(IAudioPolicyService, data, reply); int audioSession = data.readInt32(); uint32_t count = data.readInt32(); + if (count > AudioEffect::kMaxPreProcessing) { + count = AudioEffect::kMaxPreProcessing; + } uint32_t retCount = count; - effect_descriptor_t *descriptors = - (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)]; + effect_descriptor_t *descriptors = new effect_descriptor_t[count]; status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount); reply->writeInt32(status); if (status != NO_ERROR && status != NO_MEMORY) { retCount = 0; } reply->writeInt32(retCount); - if (retCount) { + if (retCount != 0) { if (retCount < count) { count = retCount; } diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp index 0d5f990..c26c5bf 100644 --- a/media/libmedia/ICrypto.cpp +++ b/media/libmedia/ICrypto.cpp @@ -33,6 +33,7 @@ enum { DESTROY_PLUGIN, REQUIRES_SECURE_COMPONENT, DECRYPT, + NOTIFY_RESOLUTION, }; struct BpCrypto : public BpInterface<ICrypto> { @@ -149,6 +150,15 @@ struct BpCrypto : public BpInterface<ICrypto> { return result; } + virtual void notifyResolution( + uint32_t width, uint32_t height) { + Parcel data, reply; + data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); + data.writeInt32(width); + data.writeInt32(height); + remote()->transact(NOTIFY_RESOLUTION, data, &reply); + } + private: DISALLOW_EVIL_CONSTRUCTORS(BpCrypto); }; @@ -290,10 +300,20 @@ status_t BnCrypto::onTransact( return OK; } + case NOTIFY_RESOLUTION: + { + CHECK_INTERFACE(ICrypto, data, reply); + + int32_t width = data.readInt32(); + int32_t height = data.readInt32(); + notifyResolution(width, height); + + return OK; + } + default: return BBinder::onTransact(code, data, reply, flags); } } } // namespace android - diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp index 0efdce8..b08fa82 100644 --- a/media/libmedia/IDrm.cpp +++ b/media/libmedia/IDrm.cpp @@ -54,7 +54,9 @@ enum { SIGN_RSA, VERIFY, SET_LISTENER, - UNPROVISION_DEVICE + UNPROVISION_DEVICE, + GET_SECURE_STOP, + RELEASE_ALL_SECURE_STOPS }; struct BpDrm : public BpInterface<IDrm> { @@ -255,6 +257,17 @@ struct BpDrm : public BpInterface<IDrm> { return reply.readInt32(); } + virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, ssid); + remote()->transact(GET_SECURE_STOP, data, &reply); + + readVector(reply, secureStop); + return reply.readInt32(); + } + virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); @@ -265,6 +278,15 @@ struct BpDrm : public BpInterface<IDrm> { return reply.readInt32(); } + virtual status_t releaseAllSecureStops() { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + remote()->transact(RELEASE_ALL_SECURE_STOPS, data, &reply); + + return reply.readInt32(); + } + virtual status_t getPropertyString(String8 const &name, String8 &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); @@ -655,6 +677,17 @@ status_t BnDrm::onTransact( return OK; } + case GET_SECURE_STOP: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector<uint8_t> ssid, secureStop; + readVector(data, ssid); + status_t result = getSecureStop(ssid, secureStop); + writeVector(reply, secureStop); + reply->writeInt32(result); + return OK; + } + case RELEASE_SECURE_STOPS: { CHECK_INTERFACE(IDrm, data, reply); @@ -664,6 +697,13 @@ status_t BnDrm::onTransact( return OK; } + case RELEASE_ALL_SECURE_STOPS: + { + CHECK_INTERFACE(IDrm, data, reply); + reply->writeInt32(releaseAllSecureStops()); + return OK; + } + case GET_PROPERTY_STRING: { CHECK_INTERFACE(IDrm, data, reply); @@ -809,4 +849,3 @@ status_t BnDrm::onTransact( } } // namespace android - diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp index c146b8d..f91e3e4 100644 --- a/media/libmedia/Visualizer.cpp +++ b/media/libmedia/Visualizer.cpp @@ -52,6 +52,13 @@ Visualizer::Visualizer (int32_t priority, Visualizer::~Visualizer() { + ALOGV("Visualizer::~Visualizer()"); + if (mCaptureThread != NULL) { + mCaptureThread->requestExitAndWait(); + mCaptureThread.clear(); + } + mCaptureCallBack = NULL; + mCaptureFlags = 0; } status_t Visualizer::setEnabled(bool enabled) @@ -102,20 +109,18 @@ status_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t return INVALID_OPERATION; } - sp<CaptureThread> t = mCaptureThread; - if (t != 0) { - t->mLock.lock(); + if (mCaptureThread != 0) { + mCaptureLock.unlock(); + mCaptureThread->requestExitAndWait(); + mCaptureLock.lock(); } + mCaptureThread.clear(); mCaptureCallBack = cbk; mCaptureCbkUser = user; mCaptureFlags = flags; mCaptureRate = rate; - if (t != 0) { - t->mLock.unlock(); - } - if (cbk != NULL) { mCaptureThread = new CaptureThread(*this, rate, ((flags & CAPTURE_CALL_JAVA) != 0)); } |