diff options
author | Joonas Kylmälä <joonas.kylmala@iki.fi> | 2018-08-27 13:35:19 -0400 |
---|---|---|
committer | Joonas Kylmälä <joonas.kylmala@iki.fi> | 2018-08-27 13:35:19 -0400 |
commit | e5bc488f110fd7cb70b7a78c3449476679236277 (patch) | |
tree | 978d47c3905fbdfc7e76b98e51dd4ebd73f4152d | |
parent | 6cf6309d48f3d97b6f0cd43843917664e42c32dc (diff) | |
parent | dc3b246bb1422b805937343e65b513d246952eb6 (diff) | |
download | frameworks_av-e5bc488f110fd7cb70b7a78c3449476679236277.tar.gz frameworks_av-e5bc488f110fd7cb70b7a78c3449476679236277.tar.bz2 frameworks_av-e5bc488f110fd7cb70b7a78c3449476679236277.zip |
Merge remote-tracking branch 'lineageos/cm-13.0' into replicant-6.0replicant-6.0-aug-2018
34 files changed, 390 insertions, 159 deletions
diff --git a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp index 01f8d65702..f7106b275e 100644 --- a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp +++ b/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp @@ -36,6 +36,11 @@ android::status_t AesCtrDecryptor::decrypt(const android::Vector<uint8_t>& key, uint8_t previousEncryptedCounter[kBlockSize]; memset(previousEncryptedCounter, 0, kBlockSize); + if (key.size() != kBlockSize || (sizeof(Iv) / sizeof(uint8_t)) != kBlockSize) { + android_errorWriteLog(0x534e4554, "63982768"); + return android::ERROR_DRM_DECRYPT; + } + size_t offset = 0; AES_KEY opensslKey; AES_set_encrypt_key(key.array(), kBlockBitCount, &opensslKey); diff --git a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h index b416266ddf..edb84458a7 100644 --- a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h +++ b/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h @@ -18,6 +18,7 @@ #define CLEARKEY_AES_CTR_DECRYPTOR_H_ #include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/MediaErrors.h> #include <Utils.h> #include <utils/Errors.h> #include <utils/Vector.h> diff --git a/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp b/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp index 039e40226b..5db8290a91 100644 --- a/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp +++ b/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp @@ -34,7 +34,7 @@ class AesCtrDecryptorTest : public ::testing::Test { uint8_t* destination, const SubSample* subSamples, size_t numSubSamples, size_t* bytesDecryptedOut) { Vector<uint8_t> keyVector; - keyVector.appendArray(key, kBlockSize); + keyVector.appendArray(key, sizeof(key) / sizeof(uint8_t)); AesCtrDecryptor decryptor; return decryptor.decrypt(keyVector, iv, source, destination, subSamples, @@ -57,6 +57,67 @@ class AesCtrDecryptorTest : public ::testing::Test { } }; +TEST_F(AesCtrDecryptorTest, DecryptsWithEmptyKey) { + const size_t kTotalSize = 64; + const size_t kNumSubsamples = 1; + + // Test vectors from NIST-800-38A + Iv iv = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + + uint8_t source[kTotalSize] = { 0 }; + uint8_t destination[kTotalSize] = { 0 }; + SubSample subSamples[kNumSubsamples] = { + {0, 64} + }; + + size_t bytesDecrypted = 0; + Vector<uint8_t> keyVector; + keyVector.clear(); + + AesCtrDecryptor decryptor; + ASSERT_EQ(android::ERROR_DRM_DECRYPT, decryptor.decrypt(keyVector, iv, + &source[0], &destination[0], + &subSamples[0], kNumSubsamples, &bytesDecrypted)); + ASSERT_EQ(0u, bytesDecrypted); +} + +TEST_F(AesCtrDecryptorTest, DecryptsWithKeyTooLong) { + const size_t kTotalSize = 64; + const size_t kNumSubsamples = 1; + + // Test vectors from NIST-800-38A + uint8_t key[kBlockSize * 2] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + + Iv iv = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + + uint8_t source[kTotalSize] = { 0 }; + uint8_t destination[kTotalSize] = { 0 }; + SubSample subSamples[kNumSubsamples] = { + {0, 64} + }; + + size_t bytesDecrypted = 0; + Vector<uint8_t> keyVector; + keyVector.appendArray(key, sizeof(key) / sizeof(uint8_t)); + + AesCtrDecryptor decryptor; + ASSERT_EQ(android::ERROR_DRM_DECRYPT, decryptor.decrypt(keyVector, iv, + &source[0], &destination[0], + &subSamples[0], kNumSubsamples, &bytesDecrypted)); + ASSERT_EQ(0u, bytesDecrypted); +} + TEST_F(AesCtrDecryptorTest, DecryptsContiguousEncryptedBlock) { const size_t kTotalSize = 64; const size_t kNumSubsamples = 1; diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 1df91ee140..9441861635 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -180,6 +180,10 @@ public: const Parcel& data, Parcel* reply, uint32_t flags = 0); +private: + void sanetizeAudioAttributes(audio_attributes_t* attr); + status_t sanitizeEffectDescriptor(effect_descriptor_t* desc); + status_t sanitizeAudioPortConfig(struct audio_port_config* config); }; // ---------------------------------------------------------------------------- diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 4810b7eef4..875c6b685c 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -65,14 +65,17 @@ enum player_type { // duration below which we do not allow deep audio buffering #define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000 -// callback mechanism for passing messages to MediaPlayer object -typedef void (*notify_callback_f)(void* cookie, - int msg, int ext1, int ext2, const Parcel *obj); - // abstract base class - use MediaPlayerInterface class MediaPlayerBase : public RefBase { public: + // callback mechanism for passing messages to MediaPlayer object + class Listener : public RefBase { + public: + virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) = 0; + virtual ~Listener() {} + }; + // AudioSink: abstraction layer for audio output class AudioSink : public RefBase { public: @@ -144,7 +147,7 @@ public: virtual String8 getParameters(const String8& /* keys */) { return String8::empty(); } }; - MediaPlayerBase() : mCookie(0), mNotify(0) {} + MediaPlayerBase() {} virtual ~MediaPlayerBase() {} virtual status_t initCheck() = 0; virtual bool hardwareOutput() = 0; @@ -245,22 +248,22 @@ public: }; void setNotifyCallback( - void* cookie, notify_callback_f notifyFunc) { + const sp<Listener> &listener) { Mutex::Autolock autoLock(mNotifyLock); - mCookie = cookie; mNotify = notifyFunc; + mListener = listener; } void sendEvent(int msg, int ext1=0, int ext2=0, const Parcel *obj=NULL) { - notify_callback_f notifyCB; - void* cookie; + sp<Listener> listener; { Mutex::Autolock autoLock(mNotifyLock); - notifyCB = mNotify; - cookie = mCookie; + listener = mListener; } - if (notifyCB) notifyCB(cookie, msg, ext1, ext2, obj); + if (listener != NULL) { + listener->notify(msg, ext1, ext2, obj); + } } virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const { @@ -279,8 +282,7 @@ private: friend class MediaPlayerService; Mutex mNotifyLock; - void* mCookie; - notify_callback_f mNotify; + sp<Listener> mListener; }; // Implement this class for media players that use the AudioFlinger software mixer diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp index 19892ddac3..80c8a3878f 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -1768,6 +1768,10 @@ int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue, in if (param != REVERB_PARAM_PRESET) { return -EINVAL; } + if (vsize < (int)sizeof(uint16_t)) { + android_errorWriteLog(0x534e4554, "67647856"); + return -EINVAL; + } uint16_t preset = *(uint16_t *)pValue; ALOGV("set REVERB_PARAM_PRESET, preset %d", preset); diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index abae614645..7a80bad7e9 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -863,7 +863,7 @@ status_t BnAudioPolicyService::onTransact( audio_output_flags_t flags = static_cast <audio_output_flags_t>(data.readInt32()); bool hasOffloadInfo = data.readInt32() != 0; - audio_offload_info_t offloadInfo; + audio_offload_info_t offloadInfo = {}; if (hasOffloadInfo) { data.read(&offloadInfo, sizeof(audio_offload_info_t)); } @@ -879,10 +879,11 @@ status_t BnAudioPolicyService::onTransact( case GET_OUTPUT_FOR_ATTR: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - audio_attributes_t attr; + audio_attributes_t attr = {}; bool hasAttributes = data.readInt32() != 0; if (hasAttributes) { data.read(&attr, sizeof(audio_attributes_t)); + sanetizeAudioAttributes(&attr); } audio_session_t session = (audio_session_t)data.readInt32(); audio_stream_type_t stream = AUDIO_STREAM_DEFAULT; @@ -948,8 +949,9 @@ status_t BnAudioPolicyService::onTransact( case GET_INPUT_FOR_ATTR: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - audio_attributes_t attr; + audio_attributes_t attr = {}; data.read(&attr, sizeof(audio_attributes_t)); + sanetizeAudioAttributes(&attr); audio_session_t session = (audio_session_t)data.readInt32(); uid_t uid = (uid_t)data.readInt32(); uint32_t samplingRate = data.readInt32(); @@ -1044,8 +1046,11 @@ status_t BnAudioPolicyService::onTransact( case GET_OUTPUT_FOR_EFFECT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - effect_descriptor_t desc; - data.read(&desc, sizeof(effect_descriptor_t)); + effect_descriptor_t desc = {}; + if (data.read(&desc, sizeof(desc)) != NO_ERROR) { + android_errorWriteLog(0x534e4554, "73126106"); + } + (void)sanitizeEffectDescriptor(&desc); audio_io_handle_t output = getOutputForEffect(&desc); reply->writeInt32(static_cast <int>(output)); return NO_ERROR; @@ -1053,8 +1058,11 @@ status_t BnAudioPolicyService::onTransact( case REGISTER_EFFECT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - effect_descriptor_t desc; - data.read(&desc, sizeof(effect_descriptor_t)); + effect_descriptor_t desc = {}; + if (data.read(&desc, sizeof(desc)) != NO_ERROR) { + android_errorWriteLog(0x534e4554, "73126106"); + } + (void)sanitizeEffectDescriptor(&desc); audio_io_handle_t io = data.readInt32(); uint32_t strategy = data.readInt32(); int session = data.readInt32(); @@ -1113,7 +1121,7 @@ status_t BnAudioPolicyService::onTransact( count = AudioEffect::kMaxPreProcessing; } uint32_t retCount = count; - effect_descriptor_t *descriptors = new effect_descriptor_t[count]; + 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) { @@ -1132,7 +1140,7 @@ status_t BnAudioPolicyService::onTransact( case IS_OFFLOAD_SUPPORTED: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - audio_offload_info_t info; + audio_offload_info_t info = {}; data.read(&info, sizeof(audio_offload_info_t)); bool isSupported = isOffloadSupported(info); reply->writeInt32(isSupported); @@ -1187,7 +1195,7 @@ status_t BnAudioPolicyService::onTransact( case CREATE_AUDIO_PATCH: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - struct audio_patch patch; + struct audio_patch patch = {}; data.read(&patch, sizeof(struct audio_patch)); audio_patch_handle_t handle = {}; if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) { @@ -1203,7 +1211,7 @@ status_t BnAudioPolicyService::onTransact( case RELEASE_AUDIO_PATCH: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - audio_patch_handle_t handle; + audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE; data.read(&handle, sizeof(audio_patch_handle_t)); status_t status = releaseAudioPatch(handle); reply->writeInt32(status); @@ -1242,8 +1250,9 @@ status_t BnAudioPolicyService::onTransact( case SET_AUDIO_PORT_CONFIG: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - struct audio_port_config config; + struct audio_port_config config = {}; data.read(&config, sizeof(struct audio_port_config)); + (void)sanitizeAudioPortConfig(&config); status_t status = setAudioPortConfig(&config); reply->writeInt32(status); return NO_ERROR; @@ -1334,10 +1343,12 @@ status_t BnAudioPolicyService::onTransact( case START_AUDIO_SOURCE: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - struct audio_port_config source; + struct audio_port_config source = {}; data.read(&source, sizeof(struct audio_port_config)); - audio_attributes_t attributes; + (void)sanitizeAudioPortConfig(&source); + audio_attributes_t attributes = {}; data.read(&attributes, sizeof(audio_attributes_t)); + sanetizeAudioAttributes(&attributes); audio_io_handle_t handle = {}; status_t status = startAudioSource(&source, &attributes, &handle); reply->writeInt32(status); @@ -1358,6 +1369,44 @@ status_t BnAudioPolicyService::onTransact( } } +/** returns true if string overflow was prevented by zero termination */ +template <size_t size> +static bool preventStringOverflow(char (&s)[size]) { + if (strnlen(s, size) < size) return false; + s[size - 1] = '\0'; + return true; +} + +void BnAudioPolicyService::sanetizeAudioAttributes(audio_attributes_t* attr) +{ + const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE; + if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) { + android_errorWriteLog(0x534e4554, "68953950"); // SafetyNet logging + } + attr->tags[tagsMaxSize - 1] = '\0'; +} + +/** returns BAD_VALUE if sanitization was required. */ +status_t BnAudioPolicyService::sanitizeEffectDescriptor(effect_descriptor_t* desc) +{ + if (preventStringOverflow(desc->name) + | /* always */ preventStringOverflow(desc->implementor)) { + android_errorWriteLog(0x534e4554, "73126106"); // SafetyNet logging + return BAD_VALUE; + } + return NO_ERROR; +} + +/** returns BAD_VALUE if sanitization was required. */ +status_t BnAudioPolicyService::sanitizeAudioPortConfig(struct audio_port_config* config) +{ + if (config->type == AUDIO_PORT_TYPE_DEVICE && + preventStringOverflow(config->ext.device.address)) { + return BAD_VALUE; + } + return NO_ERROR; +} + // ---------------------------------------------------------------------------- } // namespace android diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp index 6f6530bfe2..637770ddb5 100644 --- a/media/libmedia/IDrm.cpp +++ b/media/libmedia/IDrm.cpp @@ -572,8 +572,13 @@ IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm"); void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const { uint32_t size = data.readInt32(); - vector.insertAt((size_t)0, size); - data.read(vector.editArray(), size); + if (vector.insertAt((size_t)0, size) < 0) { + vector.clear(); + } + if (data.read(vector.editArray(), size) != NO_ERROR) { + vector.clear(); + android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0); + } } void BnDrm::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const { diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp index f0afc5a0fb..598e306de2 100644 --- a/media/libmediaplayerservice/MediaPlayerFactory.cpp +++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp @@ -128,8 +128,7 @@ player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, sp<MediaPlayerBase> MediaPlayerFactory::createPlayer( player_type playerType, - void* cookie, - notify_callback_f notifyFunc, + const sp<MediaPlayerBase::Listener> &listener, pid_t pid) { sp<MediaPlayerBase> p; IFactory* factory; @@ -154,7 +153,7 @@ sp<MediaPlayerBase> MediaPlayerFactory::createPlayer( init_result = p->initCheck(); if (init_result == NO_ERROR) { - p->setNotifyCallback(cookie, notifyFunc); + p->setNotifyCallback(listener); } else { ALOGE("Failed to create player object of type %d, initCheck failed" " (res = %d)", playerType, init_result); diff --git a/media/libmediaplayerservice/MediaPlayerFactory.h b/media/libmediaplayerservice/MediaPlayerFactory.h index e22a56fe6e..e88700cf58 100644 --- a/media/libmediaplayerservice/MediaPlayerFactory.h +++ b/media/libmediaplayerservice/MediaPlayerFactory.h @@ -65,8 +65,7 @@ class MediaPlayerFactory { const sp<DataSource> &source); static sp<MediaPlayerBase> createPlayer(player_type playerType, - void* cookie, - notify_callback_f notifyFunc, + const sp<MediaPlayerBase::Listener> &listener, pid_t pid); static void registerBuiltinFactories(); diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index a2ec69182e..d4a5847b41 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -604,10 +604,11 @@ MediaPlayerService::Client::Client( mUID = uid; mRetransmitEndpointValid = false; mAudioAttributes = NULL; + mListener = new Listener(this); #if CALLBACK_ANTAGONIZER ALOGD("create Antagonizer"); - mAntagonizer = new Antagonizer(notify, this); + mAntagonizer = new Antagonizer(mListener); #endif } @@ -643,7 +644,7 @@ void MediaPlayerService::Client::disconnect() // and reset the player. We assume the player will serialize // access to itself if necessary. if (p != 0) { - p->setNotifyCallback(0, 0); + p->setNotifyCallback(0); #if CALLBACK_ANTAGONIZER ALOGD("kill Antagonizer"); mAntagonizer->kill(); @@ -665,7 +666,7 @@ sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerT p.clear(); } if (p == NULL) { - p = MediaPlayerFactory::createPlayer(playerType, this, notify, mPid); + p = MediaPlayerFactory::createPlayer(playerType, mListener, mPid); } if (p != NULL) { @@ -1271,29 +1272,25 @@ status_t MediaPlayerService::Client::getRetransmitEndpoint( } void MediaPlayerService::Client::notify( - void* cookie, int msg, int ext1, int ext2, const Parcel *obj) + int msg, int ext1, int ext2, const Parcel *obj) { - Client* client = static_cast<Client*>(cookie); - if (client == NULL) { - return; - } sp<IMediaPlayerClient> c; { - Mutex::Autolock l(client->mLock); - c = client->mClient; - if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) { - if (client->mAudioOutput != NULL) - client->mAudioOutput->switchToNextOutput(); + Mutex::Autolock l(mLock); + c = mClient; + if (msg == MEDIA_PLAYBACK_COMPLETE && mNextClient != NULL) { + if (mAudioOutput != NULL) + mAudioOutput->switchToNextOutput(); ALOGD("gapless:current track played back"); ALOGD("gapless:try to do a gapless switch to next track"); status_t ret; - ret = client->mNextClient->start(); + ret = mNextClient->start(); if (ret == NO_ERROR) { - client->mNextClient->mClient->notify(MEDIA_INFO, + mNextClient->mClient->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj); } else { - client->mClient->notify(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN , 0, obj); + mClient->notify(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN , 0, obj); ALOGW("gapless:start playback for next track failed"); } } @@ -1303,17 +1300,17 @@ void MediaPlayerService::Client::notify( MEDIA_INFO_METADATA_UPDATE == ext1) { const media::Metadata::Type metadata_type = ext2; - if(client->shouldDropMetadata(metadata_type)) { + if(shouldDropMetadata(metadata_type)) { return; } // Update the list of metadata that have changed. getMetadata // also access mMetadataUpdated and clears it. - client->addNewMetadataUpdate(metadata_type); + addNewMetadataUpdate(metadata_type); } if (c != NULL) { - ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2); + ALOGV("[%d] notify (%d, %d, %d)", mConnId, msg, ext1, ext2); c->notify(msg, ext1, ext2, obj); } } @@ -1361,8 +1358,8 @@ status_t MediaPlayerService::Client::resume() #if CALLBACK_ANTAGONIZER const int Antagonizer::interval = 10000; // 10 msecs -Antagonizer::Antagonizer(notify_callback_f cb, void* client) : - mExit(false), mActive(false), mClient(client), mCb(cb) +Antagonizer::Antagonizer(const sp<MediaPlayerBase::Listener> &listener) : + mExit(false), mActive(false), mListener(listener) { createThread(callbackThread, this); } @@ -1382,7 +1379,7 @@ int Antagonizer::callbackThread(void* user) while (!p->mExit) { if (p->mActive) { ALOGV("send event"); - p->mCb(p->mClient, 0, 0, 0); + p->mListener->notify(0, 0, 0, 0); } usleep(interval); } diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 2bd7ec5c75..6e97b3892b 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -49,7 +49,7 @@ class MediaRecorderClient; #if CALLBACK_ANTAGONIZER class Antagonizer { public: - Antagonizer(notify_callback_f cb, void* client); + Antagonizer(const sp<MediaPlayerBase::Listener> &listener); void start() { mActive = true; } void stop() { mActive = false; } void kill(); @@ -57,12 +57,11 @@ private: static const int interval; Antagonizer(); static int callbackThread(void* cookie); - Mutex mLock; - Condition mCondition; - bool mExit; - bool mActive; - void* mClient; - notify_callback_f mCb; + Mutex mLock; + Condition mCondition; + bool mExit; + bool mActive; + sp<MediaPlayerBase::Listener> mListener; }; #endif @@ -205,7 +204,6 @@ class MediaPlayerService : public BnMediaPlayerService }; // AudioOutput - public: static void instantiate(); @@ -327,8 +325,7 @@ private: void setDataSource_post(const sp<MediaPlayerBase>& p, status_t status); - static void notify(void* cookie, int msg, - int ext1, int ext2, const Parcel *obj); + void notify(int msg, int ext1, int ext2, const Parcel *obj); pid_t pid() const { return mPid; } virtual status_t dump(int fd, const Vector<String16>& args); @@ -370,23 +367,38 @@ private: status_t setAudioAttributes_l(const Parcel &request); - mutable Mutex mLock; - sp<MediaPlayerBase> mPlayer; - sp<MediaPlayerService> mService; - sp<IMediaPlayerClient> mClient; - sp<AudioOutput> mAudioOutput; - pid_t mPid; - status_t mStatus; - bool mLoop; - int32_t mConnId; - int mAudioSessionId; - audio_attributes_t * mAudioAttributes; - uid_t mUID; - sp<ANativeWindow> mConnectedWindow; - sp<IBinder> mConnectedWindowBinder; - struct sockaddr_in mRetransmitEndpoint; - bool mRetransmitEndpointValid; - sp<Client> mNextClient; + class Listener : public MediaPlayerBase::Listener { + public: + Listener(const wp<Client> &client) : mClient(client) {} + virtual ~Listener() {} + virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) { + sp<Client> client = mClient.promote(); + if (client != NULL) { + client->notify(msg, ext1, ext2, obj); + } + } + private: + wp<Client> mClient; + }; + + mutable Mutex mLock; + sp<MediaPlayerBase> mPlayer; + sp<MediaPlayerService> mService; + sp<IMediaPlayerClient> mClient; + sp<AudioOutput> mAudioOutput; + pid_t mPid; + status_t mStatus; + bool mLoop; + int32_t mConnId; + int mAudioSessionId; + audio_attributes_t * mAudioAttributes; + uid_t mUID; + sp<ANativeWindow> mConnectedWindow; + sp<IBinder> mConnectedWindowBinder; + struct sockaddr_in mRetransmitEndpoint; + bool mRetransmitEndpointValid; + sp<Client> mNextClient; + sp<MediaPlayerBase::Listener> mListener; // Metadata filters. media::Metadata::Filter mMetadataAllow; // protected by mLock @@ -399,7 +411,7 @@ private: media::Metadata::Filter mMetadataUpdated; // protected by mLock #if CALLBACK_ANTAGONIZER - Antagonizer* mAntagonizer; + Antagonizer* mAntagonizer; #endif }; // Client diff --git a/media/libstagefright/AACExtractor.cpp b/media/libstagefright/AACExtractor.cpp index 2115eb4929..87538b589e 100644 --- a/media/libstagefright/AACExtractor.cpp +++ b/media/libstagefright/AACExtractor.cpp @@ -306,6 +306,10 @@ status_t AACSource::read( if (options && options->getSeekTo(&seekTimeUs, &mode)) { if (mFrameDurationUs > 0) { int64_t seekFrame = seekTimeUs / mFrameDurationUs; + if (seekFrame < 0 || seekFrame >= (int64_t)mOffsetVector.size()) { + android_errorWriteLog(0x534e4554, "70239507"); + return ERROR_MALFORMED; + } mCurrentTimeUs = seekFrame * mFrameDurationUs; mOffset = mOffsetVector.itemAt(seekFrame); diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 9e37ed32c0..3ed2251bc7 100755 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -1580,6 +1580,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { // ratio. Use compression ratio of 1. max_size = width * height * 3 / 2; } + // HACK: allow 10% overhead + // TODO: read sample size from traf atom for fragmented MPEG4. + max_size += max_size / 10; mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size); } diff --git a/media/libstagefright/VideoFrameScheduler.cpp b/media/libstagefright/VideoFrameScheduler.cpp index c17faf32d8..b2d12f4da9 100644 --- a/media/libstagefright/VideoFrameScheduler.cpp +++ b/media/libstagefright/VideoFrameScheduler.cpp @@ -129,6 +129,11 @@ bool VideoFrameScheduler::PLL::fit( numSamplesToUse = mNumSamples; } + if ((period >> kPrecision) == 0 ) { + ALOGW("Period is 0, or after including precision is 0 - would cause div0, returning"); + return false; + } + int64_t sumX = 0; int64_t sumXX = 0; int64_t sumXY = 0; diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp index bf014ba6af..19556cc2cf 100644 --- a/media/libstagefright/avc_utils.cpp +++ b/media/libstagefright/avc_utils.cpp @@ -304,7 +304,7 @@ static sp<ABuffer> FindNAL(const uint8_t *data, size_t size, unsigned nalType) { const uint8_t *nalStart; size_t nalSize; while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { - if ((nalStart[0] & 0x1f) == nalType) { + if (nalSize > 0 && (nalStart[0] & 0x1f) == nalType) { sp<ABuffer> buffer = new ABuffer(nalSize); memcpy(buffer->data(), nalStart, nalSize); return buffer; diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp index 2130ccf856..2ca0e37b6a 100644 --- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp +++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp @@ -317,10 +317,6 @@ status_t SoftAVC::initDecoder() { status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op); - mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle; - mCodecCtx->pv_fxns = dec_fxns; - mCodecCtx->u4_size = sizeof(iv_obj_t); - if (status != IV_SUCCESS) { ALOGE("Error in create: 0x%x", s_create_op.s_ivd_create_op_t.u4_error_code); @@ -328,6 +324,10 @@ status_t SoftAVC::initDecoder() { mCodecCtx = NULL; return UNKNOWN_ERROR; } + + mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle; + mCodecCtx->pv_fxns = dec_fxns; + mCodecCtx->u4_size = sizeof(iv_obj_t); } /* Reset the plugin state */ @@ -545,7 +545,7 @@ void SoftAVC::onQueueFilled(OMX_U32 portIndex) { notifyEmptyBufferDone(inHeader); if (!(inHeader->nFlags & OMX_BUFFERFLAG_EOS)) { - continue; + return; } mReceivedEOS = true; diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp index 07d12453b0..8a8d84fe16 100644 --- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp +++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp @@ -1134,6 +1134,12 @@ OMX_ERRORTYPE SoftAVC::setEncodeArgs( ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat; source = NULL; if ((inputBufferHeader != NULL) && inputBufferHeader->nFilledLen) { + OMX_ERRORTYPE error = validateInputBuffer(inputBufferHeader); + if (error != OMX_ErrorNone) { + ALOGE("b/69065651"); + android_errorWriteLog(0x534e4554, "69065651"); + return error; + } source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset; if (mInputDataIsMeta) { diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp index 1dac86804b..98fafbc9c3 100644 --- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp +++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp @@ -278,10 +278,6 @@ status_t SoftHEVC::initDecoder() { status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op); - mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle; - mCodecCtx->pv_fxns = dec_fxns; - mCodecCtx->u4_size = sizeof(iv_obj_t); - if (status != IV_SUCCESS) { ALOGE("Error in create: 0x%x", s_create_op.s_ivd_create_op_t.u4_error_code); @@ -289,6 +285,10 @@ status_t SoftHEVC::initDecoder() { mCodecCtx = NULL; return UNKNOWN_ERROR; } + + mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle; + mCodecCtx->pv_fxns = dec_fxns; + mCodecCtx->u4_size = sizeof(iv_obj_t); } /* Reset the plugin state */ diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp index f7192b1c0f..7202f982eb 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp +++ b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp @@ -560,7 +560,7 @@ int PV_VlcDecMCBPC_com_inter_H263(BitstreamDecVideo *stream) BitstreamShow13Bits(stream, &code); - if (code == 0) + if (code < 8) { return VLC_CODE_ERROR; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index 800238685e..fe98438a59 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -442,6 +442,14 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { } if (inHeader->nFilledLen > 0) { + OMX_ERRORTYPE error = validateInputBuffer(inHeader); + if (error != OMX_ErrorNone) { + ALOGE("b/69065651"); + android_errorWriteLog(0x534e4554, "69065651"); + mSignalledError = true; + notify(OMX_EventError, error, 0, 0); + return; + } const uint8_t *inputData = NULL; if (mInputDataIsMeta) { inputData = diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp index d443b7ccfe..bc5fd79526 100644 --- a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp +++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp @@ -184,7 +184,7 @@ ERROR_CODE pvmp3_decode_header(tmp3Bits *inputStream, info->emphasis = (temp << 30) >> 30; /* 2 */ - if (!info->bitrate_index || info->sampling_frequency == 3) + if (!info->bitrate_index || info->bitrate_index == 15 || info->sampling_frequency == 3) { err = UNSUPPORTED_FREE_BITRATE; } diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index 26c0fca559..fabe2e9654 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -726,6 +726,13 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) { return; } + OMX_ERRORTYPE error = validateInputBuffer(inputBufferHeader); + if (error != OMX_ErrorNone) { + ALOGE("b/27569635"); + android_errorWriteLog(0x534e4554, "27569635"); + notify(OMX_EventError, error, 0, 0); + return; + } const uint8_t *source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset; @@ -741,14 +748,6 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) { return; } } else { - if (inputBufferHeader->nFilledLen < frameSize) { - android_errorWriteLog(0x534e4554, "27569635"); - notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); - return; - } else if (inputBufferHeader->nFilledLen > frameSize) { - ALOGW("Input buffer contains too many pixels"); - } - if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { ConvertYUV420SemiPlanarToYUV420Planar( source, mConversionBuffer, mWidth, mHeight); diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp index ff2bb272ed..7b5e7d5920 100644 --- a/media/libstagefright/httplive/M3UParser.cpp +++ b/media/libstagefright/httplive/M3UParser.cpp @@ -655,10 +655,13 @@ status_t M3UParser::parse(const void *_data, size_t size) { } if (!line.startsWith("#")) { + if (itemMeta == NULL) { + ALOGV("itemMeta == NULL"); + return ERROR_MALFORMED; + } if (!mIsVariantPlaylist) { int64_t durationUs; - if (itemMeta == NULL - || !itemMeta->findInt64("durationUs", &durationUs)) { + if (!itemMeta->findInt64("durationUs", &durationUs)) { return ERROR_MALFORMED; } itemMeta->setInt32("discontinuity-sequence", @@ -887,6 +890,9 @@ status_t M3UParser::parseStreamInf( } } + if (meta->get() == NULL) { + return ERROR_MALFORMED; + } return OK; } diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp index fee13eac66..d97d444bd6 100644 --- a/media/libstagefright/id3/ID3.cpp +++ b/media/libstagefright/id3/ID3.cpp @@ -328,12 +328,25 @@ struct id3_header { } void ID3::removeUnsynchronization() { - for (size_t i = 0; i + 1 < mSize; ++i) { - if (mData[i] == 0xff && mData[i + 1] == 0x00) { - memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2); - --mSize; + + // This file has "unsynchronization", so we have to replace occurrences + // of 0xff 0x00 with just 0xff in order to get the real data. + + size_t writeOffset = 1; + for (size_t readOffset = 1; readOffset < mSize; ++readOffset) { + if (mData[readOffset - 1] == 0xff && mData[readOffset] == 0x00) { + continue; } + // Only move data if there's actually something to move. + // This handles the special case of the data being only [0xff, 0x00] + // which should be converted to just 0xff if unsynchronization is on. + mData[writeOffset++] = mData[readOffset]; + } + + if (writeOffset < mSize) { + mSize = writeOffset; } + } static void WriteSyncsafeInteger(uint8_t *dst, size_t x) { @@ -392,7 +405,12 @@ bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) { --mSize; --dataSize; } - mData[writeOffset++] = mData[readOffset++]; + if (i + 1 < dataSize) { + // Only move data if there's actually something to move. + // This handles the special case of the data being only [0xff, 0x00] + // which should be converted to just 0xff if unsynchronization is on. + mData[writeOffset++] = mData[readOffset++]; + } } // move the remaining data following this frame if (readOffset <= oldSize) { diff --git a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h index b43635deba..02555a2f34 100644 --- a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h +++ b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h @@ -68,6 +68,8 @@ protected: virtual OMX_ERRORTYPE getExtensionIndex(const char *name, OMX_INDEXTYPE *index); + OMX_ERRORTYPE validateInputBuffer(const OMX_BUFFERHEADERTYPE *inputBufferHeader); + enum { kInputPortIndex = 0, kOutputPortIndex = 1, diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp index 7359e8bb1f..0542792278 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.cpp +++ b/media/libstagefright/mpeg2ts/ESQueue.cpp @@ -1178,7 +1178,9 @@ static ssize_t getNextChunkSize( const uint8_t *data, size_t size) { static const char kStartCode[] = "\x00\x00\x01"; - if (size < 3) { + // per ISO/IEC 14496-2 6.2.1, a chunk has a 3-byte prefix + 1-byte start code + // we need at least <prefix><start><next prefix> to successfully scan + if (size < 3 + 1 + 3) { return -EAGAIN; } @@ -1186,7 +1188,7 @@ static ssize_t getNextChunkSize( return -EAGAIN; } - size_t offset = 3; + size_t offset = 4; while (offset + 2 < size) { if (!memcmp(&data[offset], kStartCode, 3)) { return offset; @@ -1237,6 +1239,9 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEG4Video() { state = EXPECT_VISUAL_OBJECT_START; } else { discard = true; + offset += chunkSize; + ALOGW("b/74114680, advance to next chunk"); + android_errorWriteLog(0x534e4554, "74114680"); } break; } diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk index d16d5df120..d2e6937151 100644 --- a/media/libstagefright/omx/Android.mk +++ b/media/libstagefright/omx/Android.mk @@ -36,6 +36,10 @@ ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER)),true) endif endif +ifeq ($(BOARD_SKIP_CVE_2017_13154),true) +LOCAL_CFLAGS += -DSKIP_CVE_2017_13154 +endif + LOCAL_MODULE:= libstagefright_omx LOCAL_CFLAGS += -Werror -Wall LOCAL_CLANG := true diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 04d0b258aa..6f1ba9b6bb 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -378,6 +378,10 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) { break; } +#ifndef SKIP_CVE_2017_13154 + Mutex::Autolock _l(mLock); +#endif + ALOGV("[%x:%s] calling destroyComponentInstance", mNodeID, mName); OMX_ERRORTYPE err = master->destroyComponentInstance( static_cast<OMX_COMPONENTTYPE *>(mHandle)); diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp index dc3ed393fa..a8d54bcdb6 100644 --- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp +++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp @@ -637,4 +637,17 @@ OMX_ERRORTYPE SoftVideoEncoderOMXComponent::getExtensionIndex( return SimpleSoftOMXComponent::getExtensionIndex(name, index); } +OMX_ERRORTYPE SoftVideoEncoderOMXComponent::validateInputBuffer( + const OMX_BUFFERHEADERTYPE *inputBufferHeader) { + size_t frameSize = mInputDataIsMeta ? + max(sizeof(VideoNativeMetadata), sizeof(VideoGrallocMetadata)) + : mWidth * mHeight * 3 / 2; + if (inputBufferHeader->nFilledLen < frameSize) { + return OMX_ErrorUndefined; + } else if (inputBufferHeader->nFilledLen > frameSize) { + ALOGW("Input buffer contains more data than expected."); + } + return OMX_ErrorNone; +} + } // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp index 4e24f19daa..169a599033 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp @@ -827,6 +827,7 @@ AudioPortConfig::AudioPortConfig() mSamplingRate = 0; mChannelMask = AUDIO_CHANNEL_NONE; mFormat = AUDIO_FORMAT_INVALID; + memset(&mGain, 0, sizeof(struct audio_gain_config)); mGain.index = -1; } diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 45b3bb0972..7957af33bc 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -692,6 +692,7 @@ status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session audio_io_handle_t *ioHandle, audio_devices_t *device) { + Mutex::Autolock _l(mLock); if (mAudioPolicyManager == NULL) { return NO_INIT; } @@ -701,6 +702,7 @@ status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session) { + Mutex::Autolock _l(mLock); if (mAudioPolicyManager == NULL) { return NO_INIT; } diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp index a45d5f6ab8..4e54b919e7 100644 --- a/services/soundtrigger/SoundTriggerHwService.cpp +++ b/services/soundtrigger/SoundTriggerHwService.cpp @@ -528,6 +528,8 @@ void SoundTriggerHwService::Module::detach() { if (!captureHotwordAllowed()) { return; } + Vector<audio_session_t> releasedSessions; + { AutoMutex lock(mLock); for (size_t i = 0; i < mModels.size(); i++) { @@ -537,9 +539,16 @@ void SoundTriggerHwService::Module::detach() { mHwDevice->stop_recognition(mHwDevice, model->mHandle); } mHwDevice->unload_sound_model(mHwDevice, model->mHandle); + releasedSessions.add(model->mCaptureSession); } mModels.clear(); } + + for (size_t i = 0; i < releasedSessions.size(); i++) { + // do not call AudioSystem methods with mLock held + AudioSystem::releaseSoundTriggerSession(releasedSessions[i]); + } + if (mClient != 0) { IInterface::asBinder(mClient)->unlinkToDeath(this); } @@ -581,37 +590,43 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM return BAD_VALUE; } - AutoMutex lock(mLock); - - if (mModels.size() >= mDescriptor.properties.max_sound_models) { - if (mModels.size() == 0) { - return INVALID_OPERATION; - } - ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one", - mDescriptor.properties.max_sound_models); - unloadSoundModel_l(mModels.valueAt(0)->mHandle); - } - - status_t status = mHwDevice->load_sound_model(mHwDevice, - sound_model, - SoundTriggerHwService::soundModelCallback, - this, - handle); - if (status != NO_ERROR) { - return status; - } audio_session_t session; audio_io_handle_t ioHandle; audio_devices_t device; - - status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device); + // do not call AudioSystem methods with mLock held + status_t status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device); if (status != NO_ERROR) { return status; } - sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); - mModels.replaceValueFor(*handle, model); + { + AutoMutex lock(mLock); + + if (mModels.size() >= mDescriptor.properties.max_sound_models) { + ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded", + mDescriptor.properties.max_sound_models); + status = INVALID_OPERATION; + goto exit; + } + status_t status = mHwDevice->load_sound_model(mHwDevice, + sound_model, + SoundTriggerHwService::soundModelCallback, + this, + handle); + if (status != NO_ERROR) { + goto exit; + } + + sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); + mModels.replaceValueFor(*handle, model); + } + +exit: + if (status != NO_ERROR) { + // do not call AudioSystem methods with mLock held + AudioSystem::releaseSoundTriggerSession(session); + } return status; } @@ -621,25 +636,26 @@ status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t ha if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } + status_t status; + audio_session_t session; - AutoMutex lock(mLock); - return unloadSoundModel_l(handle); -} - -status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle) -{ - ssize_t index = mModels.indexOfKey(handle); - if (index < 0) { - return BAD_VALUE; - } - sp<Model> model = mModels.valueAt(index); - mModels.removeItem(handle); - if (model->mState == Model::STATE_ACTIVE) { - mHwDevice->stop_recognition(mHwDevice, model->mHandle); - model->mState = Model::STATE_IDLE; - } - AudioSystem::releaseSoundTriggerSession(model->mCaptureSession); - return mHwDevice->unload_sound_model(mHwDevice, handle); + { + AutoMutex lock(mLock); + ssize_t index = mModels.indexOfKey(handle); + if (index < 0) { + return BAD_VALUE; + } + sp<Model> model = mModels.valueAt(index); + mModels.removeItem(handle); + if (model->mState == Model::STATE_ACTIVE) { + mHwDevice->stop_recognition(mHwDevice, model->mHandle); + model->mState = Model::STATE_IDLE; + } + status = mHwDevice->unload_sound_model(mHwDevice, handle); + session = model->mCaptureSession; + } + AudioSystem::releaseSoundTriggerSession(session); + return status; } status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle, diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h index 2619a5fb49..d05dacdb7f 100644 --- a/services/soundtrigger/SoundTriggerHwService.h +++ b/services/soundtrigger/SoundTriggerHwService.h @@ -141,9 +141,6 @@ public: private: - status_t unloadSoundModel_l(sound_model_handle_t handle); - - Mutex mLock; wp<SoundTriggerHwService> mService; struct sound_trigger_hw_device* mHwDevice; |