From b933e2cf539e7c6fc224fb3e450f2fe23914910f Mon Sep 17 00:00:00 2001 From: Ytai Ben-Tsvi Date: Tue, 14 Apr 2020 11:51:55 -0700 Subject: Make SoundTriggerHw2Enforcer thread-safe Since this class may be accessed from two separate execution contexts (forward calls and callbacks), make sure we avoid data races when accessing mModelStates. Fixes: 154002405 Test: Manual verification of sound-trigger functionality. Change-Id: I817a4d1b2861de8bc7ce364e39f36dd07863d307 --- .../SoundTriggerHw2Enforcer.java | 56 ++++++++++++++-------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java index 870d909fbbcc..a18b690f08cd 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java +++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java @@ -33,7 +33,7 @@ import java.util.Map; * This is not necessarily a strict enforcement for the HAL contract, but a place to add checks for * common HAL malfunctions, to help track them and assist in debugging. * - * The class is not thread-safe. + * The class is thread-safe. */ public class SoundTriggerHw2Enforcer implements ISoundTriggerHw2 { static final String TAG = "SoundTriggerHw2Enforcer"; @@ -55,7 +55,9 @@ public class SoundTriggerHw2Enforcer implements ISoundTriggerHw2 { public int loadSoundModel(ISoundTriggerHw.SoundModel soundModel, Callback callback, int cookie) { int handle = mUnderlying.loadSoundModel(soundModel, new CallbackEnforcer(callback), cookie); - mModelStates.put(handle, false); + synchronized (mModelStates) { + mModelStates.put(handle, false); + } return handle; } @@ -64,27 +66,35 @@ public class SoundTriggerHw2Enforcer implements ISoundTriggerHw2 { int cookie) { int handle = mUnderlying.loadPhraseSoundModel(soundModel, new CallbackEnforcer(callback), cookie); - mModelStates.put(handle, false); + synchronized (mModelStates) { + mModelStates.put(handle, false); + } return handle; } @Override public void unloadSoundModel(int modelHandle) { mUnderlying.unloadSoundModel(modelHandle); - mModelStates.remove(modelHandle); + synchronized (mModelStates) { + mModelStates.remove(modelHandle); + } } @Override public void stopRecognition(int modelHandle) { mUnderlying.stopRecognition(modelHandle); - mModelStates.replace(modelHandle, false); + synchronized (mModelStates) { + mModelStates.replace(modelHandle, false); + } } @Override public void stopAllRecognitions() { mUnderlying.stopAllRecognitions(); - for (Map.Entry entry : mModelStates.entrySet()) { - entry.setValue(false); + synchronized (mModelStates) { + for (Map.Entry entry : mModelStates.entrySet()) { + entry.setValue(false); + } } } @@ -92,7 +102,9 @@ public class SoundTriggerHw2Enforcer implements ISoundTriggerHw2 { public void startRecognition(int modelHandle, RecognitionConfig config, Callback callback, int cookie) { mUnderlying.startRecognition(modelHandle, config, new CallbackEnforcer(callback), cookie); - mModelStates.replace(modelHandle, true); + synchronized (mModelStates) { + mModelStates.replace(modelHandle, true); + } } @Override @@ -142,12 +154,14 @@ public class SoundTriggerHw2Enforcer implements ISoundTriggerHw2 { public void recognitionCallback(ISoundTriggerHwCallback.RecognitionEvent event, int cookie) { int model = event.header.model; - if (!mModelStates.getOrDefault(model, false)) { - Log.wtfStack(TAG, "Unexpected recognition event for model: " + model); - } - if (event.header.status - != android.media.soundtrigger_middleware.RecognitionStatus.FORCED) { - mModelStates.replace(model, false); + synchronized (mModelStates) { + if (!mModelStates.getOrDefault(model, false)) { + Log.wtfStack(TAG, "Unexpected recognition event for model: " + model); + } + if (event.header.status + != android.media.soundtrigger_middleware.RecognitionStatus.FORCED) { + mModelStates.replace(model, false); + } } mUnderlying.recognitionCallback(event, cookie); } @@ -156,12 +170,14 @@ public class SoundTriggerHw2Enforcer implements ISoundTriggerHw2 { public void phraseRecognitionCallback(ISoundTriggerHwCallback.PhraseRecognitionEvent event, int cookie) { int model = event.common.header.model; - if (!mModelStates.getOrDefault(model, false)) { - Log.wtfStack(TAG, "Unexpected recognition event for model: " + model); - } - if (event.common.header.status - != android.media.soundtrigger_middleware.RecognitionStatus.FORCED) { - mModelStates.replace(model, false); + synchronized (mModelStates) { + if (!mModelStates.getOrDefault(model, false)) { + Log.wtfStack(TAG, "Unexpected recognition event for model: " + model); + } + if (event.common.header.status + != android.media.soundtrigger_middleware.RecognitionStatus.FORCED) { + mModelStates.replace(model, false); + } } mUnderlying.phraseRecognitionCallback(event, cookie); } -- cgit v1.2.3-59-g8ed1b