summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ytai Ben-Tsvi <ytai@google.com> 2022-04-06 15:53:38 -0700
committer Ytai Ben-Tsvi <ytai@google.com> 2022-04-11 11:55:20 -0700
commitf3e7be00588ea67dfaeb8be3847802d238a9a974 (patch)
tree2c2b41a45bbb4813430440ade0cbfea12fc176b6
parent64c62ca506e104885518a9bb7f48aaa9670ccfd5 (diff)
Wait for an abort event when stopping a model
Because the client callbacks from SoundTriggerMiddleware service are async, if a client quickly stops and starts a model, then receives a detection event for that model, it is impossible for it to tell whether the event corresponding to the previous or current session, and thus is unable to reason about the resulting state of the model. To mitigate that, we will always wait for an abort event when a model is stopped before any other operation is attempted. This way the model state stays synchronized. Bug: 191935600 Fixes: 226926627 Test: Manual verification of soundtrigger use-cases. Specifically, quick toggling of Assitant and Now Playing via Settings. Change-Id: Ia1b91e78aa6981a7b3612ae9213af1b37a333d00
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java47
1 files changed, 28 insertions, 19 deletions
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 3aa0ddd26e2d..b71669046ee9 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -395,20 +395,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
return STATUS_OK;
}
- int status = prepareForRecognition(modelData);
- if (status != STATUS_OK) {
- Slog.w(TAG, "startRecognition failed to prepare model for recognition");
- return status;
- }
- status = startRecognitionLocked(modelData,
+ return updateRecognitionLocked(modelData,
false /* Don't notify for synchronous calls */);
-
- // Initialize power save, call active state monitoring logic.
- if (status == STATUS_OK) {
- initializeDeviceStateListeners();
- }
-
- return status;
}
}
@@ -557,7 +545,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
- if (unloadModel && modelData.isModelLoaded()) {
+ if (unloadModel && (modelData.isModelLoaded() || modelData.isStopPending())) {
Slog.d(TAG, "Unloading previously loaded stale model.");
if (mModule == null) {
return STATUS_ERROR;
@@ -917,7 +905,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
Slog.w(TAG, "Recognition aborted");
MetricsLogger.count(mContext, "sth_recognition_aborted", 1);
ModelData modelData = getModelDataForLocked(event.soundModelHandle);
- if (modelData != null && modelData.isModelStarted()) {
+ if (modelData != null && (modelData.isModelStarted() || modelData.isStopPending())) {
modelData.setStopped();
try {
IRecognitionStatusCallback callback = modelData.getCallback();
@@ -929,6 +917,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
}
+ updateRecognitionLocked(modelData, true);
}
}
@@ -1008,16 +997,22 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
private int updateRecognitionLocked(ModelData model, boolean notifyClientOnError) {
boolean shouldStartModel = model.isRequested() && isRecognitionAllowedByDeviceState(model);
- if (shouldStartModel == model.isModelStarted()) {
+ if (shouldStartModel == model.isModelStarted() || model.isStopPending()) {
// No-op.
return STATUS_OK;
}
if (shouldStartModel) {
int status = prepareForRecognition(model);
if (status != STATUS_OK) {
+ Slog.w(TAG, "startRecognition failed to prepare model for recognition");
return status;
}
- return startRecognitionLocked(model, notifyClientOnError);
+ status = startRecognitionLocked(model, notifyClientOnError);
+ // Initialize power save, call active state monitoring logic.
+ if (status == STATUS_OK) {
+ initializeDeviceStateListeners();
+ }
+ return status;
} else {
return stopRecognitionLocked(model, notifyClientOnError);
}
@@ -1200,7 +1195,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
if (mModule == null) {
return;
}
- if (modelData.isModelStarted()) {
+ if (modelData.isStopPending()) {
+ // No need to wait for the stop to be confirmed.
+ modelData.setStopped();
+ } else if (modelData.isModelStarted()) {
Slog.d(TAG, "Stopping previously started dangling model " + modelData.getHandle());
if (mModule.stopRecognition(modelData.getHandle()) == STATUS_OK) {
modelData.setStopped();
@@ -1417,7 +1415,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
} else {
- modelData.setStopped();
+ modelData.setStopPending();
MetricsLogger.count(mContext, "sth_stop_recognition_success", 1);
// Notify of pause if needed.
if (notify) {
@@ -1472,6 +1470,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
// Started implies model was successfully loaded and start was called.
static final int MODEL_STARTED = 2;
+ // Model stop request has been sent. Waiting for an event to signal model being stopped.
+ static final int MODEL_STOP_PENDING = 3;
+
// One of MODEL_NOTLOADED, MODEL_LOADED, MODEL_STARTED (which implies loaded).
private int mModelState;
private UUID mModelId;
@@ -1549,6 +1550,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
return mModelState == MODEL_NOTLOADED;
}
+ synchronized boolean isStopPending() {
+ return mModelState == MODEL_STOP_PENDING;
+ }
+
synchronized void setStarted() {
mModelState = MODEL_STARTED;
}
@@ -1557,6 +1562,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
mModelState = MODEL_LOADED;
}
+ synchronized void setStopPending() {
+ mModelState = MODEL_STOP_PENDING;
+ }
+
synchronized void setLoaded() {
mModelState = MODEL_LOADED;
}