summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java39
1 files changed, 32 insertions, 7 deletions
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index 09035cd1d165..15c9ba923d3a 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -37,6 +37,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.util.Preconditions;
@@ -829,17 +830,41 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public void binderDied() {
// This is called whenever our client process dies.
+ SparseArray<ModelState.Activity> cachedMap =
+ new SparseArray<ModelState.Activity>();
synchronized (SoundTriggerMiddlewareValidation.this) {
- try {
- // Gracefully stop all active recognitions and unload the models.
+ // Copy the relevant state under the lock, so we can call back without
+ // holding a lock. This exposes us to a potential race, but the client is
+ // dead so we don't expect one.
+ // TODO(240613068) A more resilient fix for this.
for (Map.Entry<Integer, ModelState> entry :
mLoadedModels.entrySet()) {
- if (entry.getValue().activityState == ModelState.Activity.ACTIVE) {
- mDelegate.stopRecognition(entry.getKey());
- }
- mDelegate.unloadModel(entry.getKey());
+ cachedMap.put(entry.getKey(), entry.getValue().activityState);
+ }
+ }
+ try {
+ // Gracefully stop all active recognitions and unload the models.
+ for (int i = 0; i < cachedMap.size(); i++) {
+ if (cachedMap.valueAt(i) == ModelState.Activity.ACTIVE) {
+ mDelegate.stopRecognition(cachedMap.keyAt(i));
}
- // Detach.
+ mDelegate.unloadModel(cachedMap.keyAt(i));
+ }
+ } catch (Exception e) {
+ throw handleException(e);
+ }
+ synchronized (SoundTriggerMiddlewareValidation.this) {
+ // Check if state updated unexpectedly to log race conditions.
+ for (Map.Entry<Integer, ModelState> entry : mLoadedModels.entrySet()) {
+ if (cachedMap.get(entry.getKey()) != entry.getValue().activityState) {
+ Log.e(TAG, "Unexpected state update in binderDied. Race occurred!");
+ }
+ }
+ if (mLoadedModels.size() != cachedMap.size()) {
+ Log.e(TAG, "Unexpected state update in binderDied. Race occurred!");
+ }
+ try {
+ // Detach
detachInternal();
} catch (Exception e) {
throw handleException(e);