Revert "Wait for an abort event when stopping a model"
This reverts commit 6e2eb81ac4.
The original commit fixed b/223922855, which resulted from fixing
b/191935600, but created another.
Blocking the stop() call until the event confirming the stop arrives is
a bad idea, since:
- We have to give up the lock when waiting for the event, and thus lose
the atomicity of some of the operations. b/226926627 is an example of
this.
- It turns out some of the forward calls happen from the main thread's
looper, which is also used for callbacks, and we risk deadlocks.
A follow-up commit will address the fix in a better way.
Bug: 191935600
Bug: 226926627
Bug: 223922855
Test: See next commit in the chain.
Change-Id: I2b9987ae93803d3b4f72a1df56c88e284bed43c5
This commit is contained in:
@@ -84,9 +84,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
|
||||
private static final int INVALID_VALUE = Integer.MIN_VALUE;
|
||||
|
||||
/** Maximum time to wait for a model stop confirmation before giving up. */
|
||||
private static final long STOP_TIMEOUT_MS = 5000;
|
||||
|
||||
/** The {@link ModuleProperties} for the system, or null if none exists. */
|
||||
final ModuleProperties mModuleProperties;
|
||||
|
||||
@@ -834,7 +831,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
}
|
||||
|
||||
if (!event.recognitionStillActive) {
|
||||
model.setStoppedLocked();
|
||||
model.setStopped();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -921,7 +918,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
MetricsLogger.count(mContext, "sth_recognition_aborted", 1);
|
||||
ModelData modelData = getModelDataForLocked(event.soundModelHandle);
|
||||
if (modelData != null && modelData.isModelStarted()) {
|
||||
modelData.setStoppedLocked();
|
||||
modelData.setStopped();
|
||||
try {
|
||||
IRecognitionStatusCallback callback = modelData.getCallback();
|
||||
if (callback != null) {
|
||||
@@ -978,7 +975,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
}
|
||||
|
||||
if (!event.recognitionStillActive) {
|
||||
modelData.setStoppedLocked();
|
||||
modelData.setStopped();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1206,7 +1203,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
if (modelData.isModelStarted()) {
|
||||
Slog.d(TAG, "Stopping previously started dangling model " + modelData.getHandle());
|
||||
if (mModule.stopRecognition(modelData.getHandle()) == STATUS_OK) {
|
||||
modelData.setStoppedLocked();
|
||||
modelData.setStopped();
|
||||
modelData.setRequested(false);
|
||||
} else {
|
||||
Slog.e(TAG, "Failed to stop model " + modelData.getHandle());
|
||||
@@ -1255,7 +1252,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
|
||||
ModelData modelData = mModelDataMap.get(modelId);
|
||||
if (modelData == null) {
|
||||
modelData = createGenericModelData(modelId);
|
||||
modelData = ModelData.createGenericModelData(modelId);
|
||||
mModelDataMap.put(modelId, modelData);
|
||||
} else if (!modelData.isGenericModel()) {
|
||||
Slog.e(TAG, "UUID already used for non-generic model.");
|
||||
@@ -1287,7 +1284,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
mKeyphraseUuidMap.remove(keyphraseId);
|
||||
mModelDataMap.remove(modelId);
|
||||
mKeyphraseUuidMap.put(keyphraseId, modelId);
|
||||
ModelData modelData = createKeyphraseModelData(modelId);
|
||||
ModelData modelData = ModelData.createKeyphraseModelData(modelId);
|
||||
mModelDataMap.put(modelId, modelData);
|
||||
return modelData;
|
||||
}
|
||||
@@ -1419,26 +1416,18 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
Slog.w(TAG, "RemoteException in onError", e);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Wait for model to be stopped.
|
||||
try {
|
||||
modelData.waitStoppedLocked(STOP_TIMEOUT_MS);
|
||||
} catch (InterruptedException e) {
|
||||
Slog.e(TAG, "Didn't receive model stop callback");
|
||||
return SoundTrigger.STATUS_ERROR;
|
||||
}
|
||||
|
||||
MetricsLogger.count(mContext, "sth_stop_recognition_success", 1);
|
||||
// Notify of pause if needed.
|
||||
if (notify) {
|
||||
try {
|
||||
callback.onRecognitionPaused();
|
||||
} catch (DeadObjectException e) {
|
||||
forceStopAndUnloadModelLocked(modelData, e);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
|
||||
} else {
|
||||
modelData.setStopped();
|
||||
MetricsLogger.count(mContext, "sth_stop_recognition_success", 1);
|
||||
// Notify of pause if needed.
|
||||
if (notify) {
|
||||
try {
|
||||
callback.onRecognitionPaused();
|
||||
} catch (DeadObjectException e) {
|
||||
forceStopAndUnloadModelLocked(modelData, e);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DBG) {
|
||||
@@ -1473,7 +1462,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
|
||||
// This class encapsulates the callbacks, state, handles and any other information that
|
||||
// represents a model.
|
||||
private class ModelData {
|
||||
private static class ModelData {
|
||||
// Model not loaded (and hence not started).
|
||||
static final int MODEL_NOTLOADED = 0;
|
||||
|
||||
@@ -1530,9 +1519,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
mModelType = modelType;
|
||||
}
|
||||
|
||||
static ModelData createKeyphraseModelData(UUID modelId) {
|
||||
return new ModelData(modelId, SoundModel.TYPE_KEYPHRASE);
|
||||
}
|
||||
|
||||
static ModelData createGenericModelData(UUID modelId) {
|
||||
return new ModelData(modelId, SoundModel.TYPE_GENERIC_SOUND);
|
||||
}
|
||||
|
||||
// Note that most of the functionality in this Java class will not work for
|
||||
// SoundModel.TYPE_UNKNOWN nevertheless we have it since lower layers support it.
|
||||
ModelData createModelDataOfUnknownType(UUID modelId) {
|
||||
static ModelData createModelDataOfUnknownType(UUID modelId) {
|
||||
return new ModelData(modelId, SoundModel.TYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
@@ -1556,20 +1553,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
mModelState = MODEL_STARTED;
|
||||
}
|
||||
|
||||
synchronized void setStoppedLocked() {
|
||||
synchronized void setStopped() {
|
||||
mModelState = MODEL_LOADED;
|
||||
mLock.notifyAll();
|
||||
}
|
||||
|
||||
void waitStoppedLocked(long timeoutMs) throws InterruptedException {
|
||||
long deadline = System.currentTimeMillis() + timeoutMs;
|
||||
while (mModelState == MODEL_STARTED) {
|
||||
long waitTime = deadline - System.currentTimeMillis();
|
||||
if (waitTime <= 0) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
mLock.wait(waitTime);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void setLoaded() {
|
||||
@@ -1589,7 +1574,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
mRecognitionConfig = null;
|
||||
mRequested = false;
|
||||
mCallback = null;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized void clearCallback() {
|
||||
@@ -1694,12 +1678,4 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
return "Model type: " + type + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
ModelData createKeyphraseModelData(UUID modelId) {
|
||||
return new ModelData(modelId, SoundModel.TYPE_KEYPHRASE);
|
||||
}
|
||||
|
||||
ModelData createGenericModelData(UUID modelId) {
|
||||
return new ModelData(modelId, SoundModel.TYPE_GENERIC_SOUND);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user