diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp index 6f69110d50..0e5169c9e0 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp @@ -623,6 +623,7 @@ Return DrmPlugin::getSecurityLevel(const hidl_vec& sessionId, return Void(); } + Mutex::Autolock lock(mSecurityLevelLock); std::map, SecurityLevel>::iterator itr = mSecurityLevel.find(sid); if (itr == mSecurityLevel.end()) { @@ -653,6 +654,7 @@ Return DrmPlugin::setSecurityLevel(const hidl_vec& sessionId, return Status::ERROR_DRM_SESSION_NOT_OPENED; } + Mutex::Autolock lock(mSecurityLevelLock); std::map, SecurityLevel>::iterator itr = mSecurityLevel.find(sid); if (itr != mSecurityLevel.end()) { diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h index 894985bd1b..e957cee194 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h @@ -398,7 +398,8 @@ struct DrmPlugin : public IDrmPlugin { std::map mStringProperties; std::map > mByteArrayProperties; std::map > mReleaseKeysMap; - std::map, SecurityLevel> mSecurityLevel; + std::map, SecurityLevel> mSecurityLevel + GUARDED_BY(mSecurityLevelLock); sp mListener; sp mListenerV1_2; SessionLibrary *mSessionLibrary; @@ -419,6 +420,7 @@ struct DrmPlugin : public IDrmPlugin { DeviceFiles mFileHandle GUARDED_BY(mFileHandleLock); Mutex mFileHandleLock; Mutex mSecureStopLock; + Mutex mSecurityLevelLock; CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin); }; diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.cpp b/media/codec2/components/mp3/C2SoftMp3Dec.cpp index 5ba7e3d78f..3984f62278 100644 --- a/media/codec2/components/mp3/C2SoftMp3Dec.cpp +++ b/media/codec2/components/mp3/C2SoftMp3Dec.cpp @@ -405,7 +405,7 @@ void C2SoftMP3::process( mConfig->inputBufferCurrentLength = (inSize - inPos); mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; - mConfig->outputFrameSize = (calOutSize - outSize); + mConfig->outputFrameSize = (calOutSize - outSize) / sizeof(int16_t); mConfig->pOutputBuffer = reinterpret_cast (wView.data() + outSize); ERROR_CODE decoderErr; diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp index 6d27a0212d..9410ce93fc 100644 --- a/media/codec2/vndk/C2AllocatorIon.cpp +++ b/media/codec2/vndk/C2AllocatorIon.cpp @@ -202,6 +202,7 @@ class C2AllocationIon::Impl { c2_status_t err = mapInternal(mapSize, mapOffset, alignmentBytes, prot, flags, &(map.addr), addr); if (map.addr) { + std::lock_guard guard(mMutexMappings); mMappings.push_back(map); } return err; @@ -212,22 +213,26 @@ class C2AllocationIon::Impl { ALOGD("tried to unmap unmapped buffer"); return C2_NOT_FOUND; } - for (auto it = mMappings.begin(); it != mMappings.end(); ++it) { - if (addr != (uint8_t *)it->addr + it->alignmentBytes || - size + it->alignmentBytes != it->size) { - continue; + { // Scope for the lock_guard of mMutexMappings. + std::lock_guard guard(mMutexMappings); + for (auto it = mMappings.begin(); it != mMappings.end(); ++it) { + if (addr != (uint8_t *)it->addr + it->alignmentBytes || + size + it->alignmentBytes != it->size) { + continue; + } + int err = munmap(it->addr, it->size); + if (err != 0) { + ALOGD("munmap failed"); + return c2_map_errno(errno); + } + if (fence) { + *fence = C2Fence(); // not using fences + } + (void)mMappings.erase(it); + ALOGV("successfully unmapped: addr=%p size=%zu fd=%d", addr, size, + mHandle.bufferFd()); + return C2_OK; } - int err = munmap(it->addr, it->size); - if (err != 0) { - ALOGD("munmap failed"); - return c2_map_errno(errno); - } - if (fence) { - *fence = C2Fence(); // not using fences - } - (void)mMappings.erase(it); - ALOGV("successfully unmapped: addr=%p size=%zu fd=%d", addr, size, mHandle.bufferFd()); - return C2_OK; } ALOGD("unmap failed to find specified map"); return C2_BAD_VALUE; @@ -236,6 +241,7 @@ class C2AllocationIon::Impl { virtual ~Impl() { if (!mMappings.empty()) { ALOGD("Dangling mappings!"); + std::lock_guard guard(mMutexMappings); for (const Mapping &map : mMappings) { (void)munmap(map.addr, map.size); } @@ -315,6 +321,7 @@ class C2AllocationIon::Impl { size_t size; }; std::list mMappings; + std::mutex mMutexMappings; }; class C2AllocationIon::ImplV2 : public C2AllocationIon::Impl { diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp old mode 100755 new mode 100644 index a976a2b12a..78e3f00b44 --- a/media/extractors/mp4/MPEG4Extractor.cpp +++ b/media/extractors/mp4/MPEG4Extractor.cpp @@ -146,6 +146,7 @@ static const size_t kMaxPcmFrameSize = 8192; MediaBufferHelper *mBuffer; + size_t mSrcBufferSize; uint8_t *mSrcBuffer; bool mIsHeif; @@ -4572,7 +4573,7 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( if (len2 == 0) { return ERROR_MALFORMED; } - if (offset >= csd_size || csd[offset] != 0x01) { + if (offset + len1 > csd_size || csd[offset] != 0x01) { return ERROR_MALFORMED; } // formerly kKeyVorbisInfo @@ -4882,6 +4883,7 @@ MPEG4Source::MPEG4Source( mNALLengthSize(0), mStarted(false), mBuffer(NULL), + mSrcBufferSize(0), mSrcBuffer(NULL), mIsHeif(itemTable != NULL), mItemTable(itemTable), @@ -5060,6 +5062,7 @@ media_status_t MPEG4Source::start() { // file probably specified a bad max size return AMEDIA_ERROR_MALFORMED; } + mSrcBufferSize = max_size; mStarted = true; @@ -5076,6 +5079,7 @@ media_status_t MPEG4Source::stop() { mBuffer = NULL; } + mSrcBufferSize = 0; delete[] mSrcBuffer; mSrcBuffer = NULL; @@ -6242,13 +6246,20 @@ media_status_t MPEG4Source::read( // Whole NAL units are returned but each fragment is prefixed by // the start code (0x00 00 00 01). ssize_t num_bytes_read = 0; - num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); + bool mSrcBufferFitsDataToRead = size <= mSrcBufferSize; + if (mSrcBufferFitsDataToRead) { + num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); + } else { + // We are trying to read a sample larger than the expected max sample size. + // Fall through and let the failure be handled by the following if. + android_errorWriteLog(0x534e4554, "188893559"); + } if (num_bytes_read < (ssize_t)size) { mBuffer->release(); mBuffer = NULL; - return AMEDIA_ERROR_IO; + return mSrcBufferFitsDataToRead ? AMEDIA_ERROR_IO : AMEDIA_ERROR_MALFORMED; } uint8_t *dstData = (uint8_t *)mBuffer->data(); diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp index 273d91ccde..4a96e7b093 100644 --- a/media/libheif/HeifDecoderImpl.cpp +++ b/media/libheif/HeifDecoderImpl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -421,7 +422,13 @@ bool HeifDecoderImpl::reinit(HeifFrameInfo* frameInfo) { initFrameInfo(&mSequenceInfo, videoFrame); - mSequenceLength = atoi(mRetriever->extractMetadata(METADATA_KEY_VIDEO_FRAME_COUNT)); + const char* frameCount = mRetriever->extractMetadata(METADATA_KEY_VIDEO_FRAME_COUNT); + if (frameCount == nullptr) { + android_errorWriteWithInfoLog(0x534e4554, "215002587", -1, NULL, 0); + ALOGD("No valid sequence information in metadata"); + return false; + } + mSequenceLength = atoi(frameCount); if (defaultInfo == nullptr) { defaultInfo = &mSequenceInfo; diff --git a/media/libmediametrics/include/media/MediaMetricsItem.h b/media/libmediametrics/include/media/MediaMetricsItem.h index 303343f91c..7ce75ed4f7 100644 --- a/media/libmediametrics/include/media/MediaMetricsItem.h +++ b/media/libmediametrics/include/media/MediaMetricsItem.h @@ -27,6 +27,7 @@ #include #include +#include #include #include // nsecs_t @@ -466,16 +467,16 @@ class BaseItem { template <> // static status_t extract(std::string *val, const char **bufferpptr, const char *bufferptrmax) { const char *ptr = *bufferpptr; - while (*ptr != 0) { + do { if (ptr >= bufferptrmax) { ALOGE("%s: buffer exceeded", __func__); + android_errorWriteLog(0x534e4554, "204445255"); return BAD_VALUE; } - ++ptr; - } - const size_t size = (ptr - *bufferpptr) + 1; + } while (*ptr++ != 0); + // ptr is terminator+1, == bufferptrmax if we finished entire buffer *val = *bufferpptr; - *bufferpptr += size; + *bufferpptr = ptr; return NO_ERROR; } template <> // static diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 553f59a41f..8283187c80 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -720,6 +720,8 @@ MediaCodec::MediaCodec( }; } + // we want an empty metrics record for any early getMetrics() call + // this should be the *only* initMediametrics() call that's not on the Looper thread initMediametrics(); } @@ -728,8 +730,17 @@ MediaCodec::~MediaCodec() { mResourceManagerProxy->removeClient(); flushMediametrics(); + + // clean any saved metrics info we stored as part of configure() + if (mConfigureMsg != nullptr) { + mediametrics_handle_t metricsHandle; + if (mConfigureMsg->findInt64("metrics", &metricsHandle)) { + mediametrics_delete(metricsHandle); + } + } } +// except for in constructor, called from the looper thread (and therefore mutexed) void MediaCodec::initMediametrics() { if (mMetricsHandle == 0) { mMetricsHandle = mediametrics_create(kCodecKeyName); @@ -759,11 +770,12 @@ void MediaCodec::initMediametrics() { } void MediaCodec::updateMediametrics() { - ALOGV("MediaCodec::updateMediametrics"); if (mMetricsHandle == 0) { return; } + Mutex::Autolock _lock(mMetricsLock); + if (mLatencyHist.getCount() != 0 ) { mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax()); mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin()); @@ -798,6 +810,8 @@ void MediaCodec::updateMediametrics() { #endif } +// called to update info being passed back via getMetrics(), which is a +// unique copy for that call, no concurrent access worries. void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) { ALOGD("MediaCodec::updateEphemeralMediametrics()"); @@ -837,7 +851,13 @@ void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) { } void MediaCodec::flushMediametrics() { + ALOGD("flushMediametrics"); + + // update does its own mutex locking updateMediametrics(); + + // ensure mutex while we do our own work + Mutex::Autolock _lock(mMetricsLock); if (mMetricsHandle != 0) { if (mediametrics_count(mMetricsHandle) > 0) { mediametrics_selfRecord(mMetricsHandle); @@ -1220,6 +1240,8 @@ status_t MediaCodec::init(const AString &name) { } msg->setString("name", name); + // initial naming setup covers the period before the first call to ::configure(). + // after that, we manage this through ::configure() and the setup message. if (mMetricsHandle != 0) { mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str()); mediametrics_setCString(mMetricsHandle, kCodecMode, @@ -1279,18 +1301,24 @@ status_t MediaCodec::configure( const sp &descrambler, uint32_t flags) { sp msg = new AMessage(kWhatConfigure, this); + mediametrics_handle_t nextMetricsHandle = mediametrics_create(kCodecKeyName); - if (mMetricsHandle != 0) { + if (nextMetricsHandle != 0) { int32_t profile = 0; if (format->findInt32("profile", &profile)) { - mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile); + mediametrics_setInt32(nextMetricsHandle, kCodecProfile, profile); } int32_t level = 0; if (format->findInt32("level", &level)) { - mediametrics_setInt32(mMetricsHandle, kCodecLevel, level); + mediametrics_setInt32(nextMetricsHandle, kCodecLevel, level); } - mediametrics_setInt32(mMetricsHandle, kCodecEncoder, + mediametrics_setInt32(nextMetricsHandle, kCodecEncoder, (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0); + + // moved here from ::init() + mediametrics_setCString(nextMetricsHandle, kCodecCodec, mInitName.c_str()); + mediametrics_setCString(nextMetricsHandle, kCodecMode, + mIsVideo ? kCodecModeVideo : kCodecModeAudio); } if (mIsVideo) { @@ -1300,17 +1328,17 @@ status_t MediaCodec::configure( mRotationDegrees = 0; } - if (mMetricsHandle != 0) { - mediametrics_setInt32(mMetricsHandle, kCodecWidth, mVideoWidth); - mediametrics_setInt32(mMetricsHandle, kCodecHeight, mVideoHeight); - mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees); + if (nextMetricsHandle != 0) { + mediametrics_setInt32(nextMetricsHandle, kCodecWidth, mVideoWidth); + mediametrics_setInt32(nextMetricsHandle, kCodecHeight, mVideoHeight); + mediametrics_setInt32(nextMetricsHandle, kCodecRotation, mRotationDegrees); int32_t maxWidth = 0; if (format->findInt32("max-width", &maxWidth)) { - mediametrics_setInt32(mMetricsHandle, kCodecMaxWidth, maxWidth); + mediametrics_setInt32(nextMetricsHandle, kCodecMaxWidth, maxWidth); } int32_t maxHeight = 0; if (format->findInt32("max-height", &maxHeight)) { - mediametrics_setInt32(mMetricsHandle, kCodecMaxHeight, maxHeight); + mediametrics_setInt32(nextMetricsHandle, kCodecMaxHeight, maxHeight); } } @@ -1334,13 +1362,23 @@ status_t MediaCodec::configure( } else { msg->setPointer("descrambler", descrambler.get()); } - if (mMetricsHandle != 0) { - mediametrics_setInt32(mMetricsHandle, kCodecCrypto, 1); + if (nextMetricsHandle != 0) { + mediametrics_setInt32(nextMetricsHandle, kCodecCrypto, 1); } } else if (mFlags & kFlagIsSecure) { ALOGW("Crypto or descrambler should be given for secure codec"); } + if (mConfigureMsg != nullptr) { + // if re-configuring, we have one of these from before. + // Recover the space before we discard the old mConfigureMsg + mediametrics_handle_t metricsHandle; + if (mConfigureMsg->findInt64("metrics", &metricsHandle)) { + mediametrics_delete(metricsHandle); + } + } + msg->setInt64("metrics", nextMetricsHandle); + // save msg for reset mConfigureMsg = msg; @@ -1851,24 +1889,42 @@ status_t MediaCodec::getCodecInfo(sp *codecInfo) const { return OK; } +// this is the user-callable entry point status_t MediaCodec::getMetrics(mediametrics_handle_t &reply) { reply = 0; - // shouldn't happen, but be safe - if (mMetricsHandle == 0) { - return UNKNOWN_ERROR; + sp msg = new AMessage(kWhatGetMetrics, this); + sp response; + status_t err; + if ((err = PostAndAwaitResponse(msg, &response)) != OK) { + return err; } - // update any in-flight data that's not carried within the record - updateMediametrics(); + CHECK(response->findInt64("metrics", &reply)); - // send it back to the caller. - reply = mediametrics_dup(mMetricsHandle); + return OK; +} - updateEphemeralMediametrics(reply); +// runs on the looper thread (for mutex purposes) +void MediaCodec::onGetMetrics(const sp& msg) { - return OK; + mediametrics_handle_t results = 0; + + sp replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mMetricsHandle != 0) { + updateMediametrics(); + results = mediametrics_dup(mMetricsHandle); + updateEphemeralMediametrics(results); + } else { + results = mediametrics_dup(mMetricsHandle); + } + + sp response = new AMessage; + response->setInt64("metrics", results); + response->postReply(replyID); } status_t MediaCodec::getInputBuffers(Vector > *buffers) const { @@ -2813,6 +2869,13 @@ void MediaCodec::onMessageReceived(const sp &msg) { break; } + case kWhatGetMetrics: + { + onGetMetrics(msg); + break; + } + + case kWhatConfigure: { if (mState != INITIALIZED) { @@ -2833,6 +2896,18 @@ void MediaCodec::onMessageReceived(const sp &msg) { sp format; CHECK(msg->findMessage("format", &format)); + // start with a copy of the passed metrics info for use in this run + mediametrics_handle_t handle; + CHECK(msg->findInt64("metrics", &handle)); + if (handle != 0) { + if (mMetricsHandle != 0) { + flushMediametrics(); + } + mMetricsHandle = mediametrics_dup(handle); + // and set some additional metrics values + initMediametrics(); + } + int32_t push; if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) { mFlags |= kFlagPushBlankBuffersOnShutdown; diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp index c6385079dd..7c4855ba35 100644 --- a/media/libstagefright/NuMediaExtractor.cpp +++ b/media/libstagefright/NuMediaExtractor.cpp @@ -627,9 +627,11 @@ status_t NuMediaExtractor::appendVorbisNumPageSamples( numPageSamples = -1; } + // insert, including accounting for the space used. memcpy((uint8_t *)buffer->data() + mbuf->range_length(), &numPageSamples, sizeof(numPageSamples)); + buffer->setRange(buffer->offset(), buffer->size() + sizeof(numPageSamples)); uint32_t type; const void *data; @@ -678,6 +680,8 @@ status_t NuMediaExtractor::readSampleData(const sp &buffer) { ssize_t minIndex = fetchAllTrackSamples(); + buffer->setRange(0, 0); // start with an empty buffer + if (minIndex < 0) { return ERROR_END_OF_STREAM; } @@ -693,25 +697,25 @@ status_t NuMediaExtractor::readSampleData(const sp &buffer) { sampleSize += sizeof(int32_t); } + // capacity() is ok since we cleared out the buffer if (buffer->capacity() < sampleSize) { return -ENOMEM; } + const size_t srclen = it->mBuffer->range_length(); const uint8_t *src = (const uint8_t *)it->mBuffer->data() + it->mBuffer->range_offset(); - memcpy((uint8_t *)buffer->data(), src, it->mBuffer->range_length()); + memcpy((uint8_t *)buffer->data(), src, srclen); + buffer->setRange(0, srclen); status_t err = OK; if (info->mTrackFlags & kIsVorbis) { + // adjusts range when it inserts the extra bits err = appendVorbisNumPageSamples(it->mBuffer, buffer); } - if (err == OK) { - buffer->setRange(0, sampleSize); - } - return err; } diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp index 771dfeabf5..55aa86b8cb 100644 --- a/media/libstagefright/SimpleDecodingSource.cpp +++ b/media/libstagefright/SimpleDecodingSource.cpp @@ -318,18 +318,23 @@ status_t SimpleDecodingSource::doRead( } size_t cpLen = min(in_buf->range_length(), in_buffer->capacity()); memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(), - cpLen ); + cpLen); if (mIsVorbis) { int32_t numPageSamples; if (!in_buf->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) { numPageSamples = -1; } - memcpy(in_buffer->base() + cpLen, &numPageSamples, sizeof(numPageSamples)); + if (cpLen + sizeof(numPageSamples) <= in_buffer->capacity()) { + memcpy(in_buffer->base() + cpLen, &numPageSamples, sizeof(numPageSamples)); + cpLen += sizeof(numPageSamples); + } else { + ALOGW("Didn't have enough space to copy kKeyValidSamples"); + } } res = mCodec->queueInputBuffer( - in_ix, 0 /* offset */, in_buf->range_length() + (mIsVorbis ? 4 : 0), + in_ix, 0 /* offset */, cpLen, timestampUs, 0 /* flags */); if (res != OK) { ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix); diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h index 7614ba5e6b..24f148e717 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodec.h +++ b/media/libstagefright/include/media/stagefright/MediaCodec.h @@ -328,6 +328,7 @@ struct MediaCodec : public AHandler { kWhatSetNotification = 'setN', kWhatDrmReleaseCrypto = 'rDrm', kWhatCheckBatteryStats = 'chkB', + kWhatGetMetrics = 'getM', }; enum { @@ -373,6 +374,7 @@ struct MediaCodec : public AHandler { sp mSurface; SoftwareRenderer *mSoftRenderer; + Mutex mMetricsLock; mediametrics_handle_t mMetricsHandle = 0; nsecs_t mLifetimeStartNs = 0; void initMediametrics(); @@ -380,6 +382,8 @@ struct MediaCodec : public AHandler { void flushMediametrics(); void updateEphemeralMediametrics(mediametrics_handle_t item); void updateLowLatency(const sp &msg); + void onGetMetrics(const sp& msg); + sp mOutputFormat; sp mInputFormat; diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp index 2c2d11d45b..3fec9edf65 100644 --- a/media/libstagefright/timedtext/TextDescriptions.cpp +++ b/media/libstagefright/timedtext/TextDescriptions.cpp @@ -466,6 +466,10 @@ status_t TextDescriptions::extract3GPPGlobalDescriptions( if (subChunkType == FOURCC('f', 't', 'a', 'b')) { + if(subChunkSize < 8) { + return OK; + } + tmpData += 8; size_t subChunkRemaining = subChunkSize - 8; diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index bfd5f7f59a..1eb8874af1 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 4431486a0a..96ab1f59e2 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -8925,6 +8925,12 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, if (isOutput()) { ret = AudioSystem::startOutput(portId); } else { + { + // Add the track record before starting input so that the silent status for the + // client can be cached. + Mutex::Autolock _l(mLock); + setClientSilencedState_l(portId, false /*silenced*/); + } ret = AudioSystem::startInput(portId); } @@ -8943,6 +8949,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, } else { mHalStream->stop(); } + eraseClientSilencedState_l(portId); return PERMISSION_DENIED; } @@ -8951,6 +8958,9 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, mChannelMask, mSessionId, isOutput(), client.clientUid, client.clientPid, IPCThreadState::self()->getCallingPid(), portId); + if (!isOutput()) { + track->setSilenced_l(isClientSilenced_l(portId)); + } if (isOutput()) { // force volume update when a new track is added @@ -9007,6 +9017,7 @@ status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle) } mActiveTracks.remove(track); + eraseClientSilencedState_l(track->portId()); mLock.unlock(); if (isOutput()) { @@ -9786,6 +9797,7 @@ void AudioFlinger::MmapCaptureThread::setRecordSilenced(audio_port_handle_t port broadcast_l(); } } + setClientSilencedIfExists_l(portId, silenced); } void AudioFlinger::MmapCaptureThread::toAudioPortConfig(struct audio_port_config *config) diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index b8356d3a23..21ab59353d 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -1847,6 +1847,26 @@ class MmapThread : public ThreadBase virtual void setRecordSilenced(audio_port_handle_t portId __unused, bool silenced __unused) {} + void setClientSilencedState_l(audio_port_handle_t portId, bool silenced) { + mClientSilencedStates[portId] = silenced; + } + + size_t eraseClientSilencedState_l(audio_port_handle_t portId) { + return mClientSilencedStates.erase(portId); + } + + bool isClientSilenced_l(audio_port_handle_t portId) const { + const auto it = mClientSilencedStates.find(portId); + return it != mClientSilencedStates.end() ? it->second : false; + } + + void setClientSilencedIfExists_l(audio_port_handle_t portId, bool silenced) { + const auto it = mClientSilencedStates.find(portId); + if (it != mClientSilencedStates.end()) { + it->second = silenced; + } + } + protected: void dumpInternals_l(int fd, const Vector& args) override; void dumpTracks_l(int fd, const Vector& args) override; @@ -1866,6 +1886,7 @@ class MmapThread : public ThreadBase AudioHwDevice* const mAudioHwDev; ActiveTracks mActiveTracks; float mHalVolFloat; + std::map mClientSilencedStates; int32_t mNoCallbackWarningCount; static constexpr int32_t kMaxNoCallbackWarnings = 5;