Merge changes from topics "presubmit-am-41e144351270485b94f495fc32653e46", "presubmit-am-d52b531f305c4668b1dfe4f906403ae6" into tm-dev
* changes: Wait for an abort event when stopping a model Revert "Wait for an abort event when stopping a model"
This commit is contained in:
committed by
Android (Google) Code Review
commit
36e2df5b5f
@@ -84,9 +84,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
|
|
||||||
private static final int INVALID_VALUE = Integer.MIN_VALUE;
|
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. */
|
/** The {@link ModuleProperties} for the system, or null if none exists. */
|
||||||
final ModuleProperties mModuleProperties;
|
final ModuleProperties mModuleProperties;
|
||||||
|
|
||||||
@@ -398,20 +395,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int status = prepareForRecognition(modelData);
|
return updateRecognitionLocked(modelData,
|
||||||
if (status != STATUS_OK) {
|
|
||||||
Slog.w(TAG, "startRecognition failed to prepare model for recognition");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
status = startRecognitionLocked(modelData,
|
|
||||||
false /* Don't notify for synchronous calls */);
|
false /* Don't notify for synchronous calls */);
|
||||||
|
|
||||||
// Initialize power save, call active state monitoring logic.
|
|
||||||
if (status == STATUS_OK) {
|
|
||||||
initializeDeviceStateListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,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.");
|
Slog.d(TAG, "Unloading previously loaded stale model.");
|
||||||
if (mModule == null) {
|
if (mModule == null) {
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
@@ -834,7 +819,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!event.recognitionStillActive) {
|
if (!event.recognitionStillActive) {
|
||||||
model.setStoppedLocked();
|
model.setStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -920,8 +905,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
Slog.w(TAG, "Recognition aborted");
|
Slog.w(TAG, "Recognition aborted");
|
||||||
MetricsLogger.count(mContext, "sth_recognition_aborted", 1);
|
MetricsLogger.count(mContext, "sth_recognition_aborted", 1);
|
||||||
ModelData modelData = getModelDataForLocked(event.soundModelHandle);
|
ModelData modelData = getModelDataForLocked(event.soundModelHandle);
|
||||||
if (modelData != null && modelData.isModelStarted()) {
|
if (modelData != null && (modelData.isModelStarted() || modelData.isStopPending())) {
|
||||||
modelData.setStoppedLocked();
|
modelData.setStopped();
|
||||||
try {
|
try {
|
||||||
IRecognitionStatusCallback callback = modelData.getCallback();
|
IRecognitionStatusCallback callback = modelData.getCallback();
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
@@ -932,6 +917,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
|
Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
|
||||||
}
|
}
|
||||||
|
updateRecognitionLocked(modelData, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,7 +964,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!event.recognitionStillActive) {
|
if (!event.recognitionStillActive) {
|
||||||
modelData.setStoppedLocked();
|
modelData.setStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1011,16 +997,22 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
|
|
||||||
private int updateRecognitionLocked(ModelData model, boolean notifyClientOnError) {
|
private int updateRecognitionLocked(ModelData model, boolean notifyClientOnError) {
|
||||||
boolean shouldStartModel = model.isRequested() && isRecognitionAllowedByDeviceState(model);
|
boolean shouldStartModel = model.isRequested() && isRecognitionAllowedByDeviceState(model);
|
||||||
if (shouldStartModel == model.isModelStarted()) {
|
if (shouldStartModel == model.isModelStarted() || model.isStopPending()) {
|
||||||
// No-op.
|
// No-op.
|
||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
if (shouldStartModel) {
|
if (shouldStartModel) {
|
||||||
int status = prepareForRecognition(model);
|
int status = prepareForRecognition(model);
|
||||||
if (status != STATUS_OK) {
|
if (status != STATUS_OK) {
|
||||||
|
Slog.w(TAG, "startRecognition failed to prepare model for recognition");
|
||||||
return status;
|
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 {
|
} else {
|
||||||
return stopRecognitionLocked(model, notifyClientOnError);
|
return stopRecognitionLocked(model, notifyClientOnError);
|
||||||
}
|
}
|
||||||
@@ -1203,10 +1195,13 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
if (mModule == null) {
|
if (mModule == null) {
|
||||||
return;
|
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());
|
Slog.d(TAG, "Stopping previously started dangling model " + modelData.getHandle());
|
||||||
if (mModule.stopRecognition(modelData.getHandle()) == STATUS_OK) {
|
if (mModule.stopRecognition(modelData.getHandle()) == STATUS_OK) {
|
||||||
modelData.setStoppedLocked();
|
modelData.setStopped();
|
||||||
modelData.setRequested(false);
|
modelData.setRequested(false);
|
||||||
} else {
|
} else {
|
||||||
Slog.e(TAG, "Failed to stop model " + modelData.getHandle());
|
Slog.e(TAG, "Failed to stop model " + modelData.getHandle());
|
||||||
@@ -1255,7 +1250,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
|
private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
|
||||||
ModelData modelData = mModelDataMap.get(modelId);
|
ModelData modelData = mModelDataMap.get(modelId);
|
||||||
if (modelData == null) {
|
if (modelData == null) {
|
||||||
modelData = createGenericModelData(modelId);
|
modelData = ModelData.createGenericModelData(modelId);
|
||||||
mModelDataMap.put(modelId, modelData);
|
mModelDataMap.put(modelId, modelData);
|
||||||
} else if (!modelData.isGenericModel()) {
|
} else if (!modelData.isGenericModel()) {
|
||||||
Slog.e(TAG, "UUID already used for non-generic model.");
|
Slog.e(TAG, "UUID already used for non-generic model.");
|
||||||
@@ -1287,7 +1282,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
mKeyphraseUuidMap.remove(keyphraseId);
|
mKeyphraseUuidMap.remove(keyphraseId);
|
||||||
mModelDataMap.remove(modelId);
|
mModelDataMap.remove(modelId);
|
||||||
mKeyphraseUuidMap.put(keyphraseId, modelId);
|
mKeyphraseUuidMap.put(keyphraseId, modelId);
|
||||||
ModelData modelData = createKeyphraseModelData(modelId);
|
ModelData modelData = ModelData.createKeyphraseModelData(modelId);
|
||||||
mModelDataMap.put(modelId, modelData);
|
mModelDataMap.put(modelId, modelData);
|
||||||
return modelData;
|
return modelData;
|
||||||
}
|
}
|
||||||
@@ -1419,26 +1414,18 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
Slog.w(TAG, "RemoteException in onError", e);
|
Slog.w(TAG, "RemoteException in onError", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
} else {
|
||||||
}
|
modelData.setStopPending();
|
||||||
|
MetricsLogger.count(mContext, "sth_stop_recognition_success", 1);
|
||||||
// Wait for model to be stopped.
|
// Notify of pause if needed.
|
||||||
try {
|
if (notify) {
|
||||||
modelData.waitStoppedLocked(STOP_TIMEOUT_MS);
|
try {
|
||||||
} catch (InterruptedException e) {
|
callback.onRecognitionPaused();
|
||||||
Slog.e(TAG, "Didn't receive model stop callback");
|
} catch (DeadObjectException e) {
|
||||||
return SoundTrigger.STATUS_ERROR;
|
forceStopAndUnloadModelLocked(modelData, e);
|
||||||
}
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
|
||||||
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) {
|
if (DBG) {
|
||||||
@@ -1473,7 +1460,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
|
|
||||||
// This class encapsulates the callbacks, state, handles and any other information that
|
// This class encapsulates the callbacks, state, handles and any other information that
|
||||||
// represents a model.
|
// represents a model.
|
||||||
private class ModelData {
|
private static class ModelData {
|
||||||
// Model not loaded (and hence not started).
|
// Model not loaded (and hence not started).
|
||||||
static final int MODEL_NOTLOADED = 0;
|
static final int MODEL_NOTLOADED = 0;
|
||||||
|
|
||||||
@@ -1483,6 +1470,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
// Started implies model was successfully loaded and start was called.
|
// Started implies model was successfully loaded and start was called.
|
||||||
static final int MODEL_STARTED = 2;
|
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).
|
// One of MODEL_NOTLOADED, MODEL_LOADED, MODEL_STARTED (which implies loaded).
|
||||||
private int mModelState;
|
private int mModelState;
|
||||||
private UUID mModelId;
|
private UUID mModelId;
|
||||||
@@ -1530,9 +1520,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
mModelType = modelType;
|
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
|
// 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.
|
// 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);
|
return new ModelData(modelId, SoundModel.TYPE_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1552,24 +1550,20 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
return mModelState == MODEL_NOTLOADED;
|
return mModelState == MODEL_NOTLOADED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized boolean isStopPending() {
|
||||||
|
return mModelState == MODEL_STOP_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
synchronized void setStarted() {
|
synchronized void setStarted() {
|
||||||
mModelState = MODEL_STARTED;
|
mModelState = MODEL_STARTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void setStoppedLocked() {
|
synchronized void setStopped() {
|
||||||
mModelState = MODEL_LOADED;
|
mModelState = MODEL_LOADED;
|
||||||
mLock.notifyAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitStoppedLocked(long timeoutMs) throws InterruptedException {
|
synchronized void setStopPending() {
|
||||||
long deadline = System.currentTimeMillis() + timeoutMs;
|
mModelState = MODEL_STOP_PENDING;
|
||||||
while (mModelState == MODEL_STARTED) {
|
|
||||||
long waitTime = deadline - System.currentTimeMillis();
|
|
||||||
if (waitTime <= 0) {
|
|
||||||
throw new InterruptedException();
|
|
||||||
}
|
|
||||||
mLock.wait(waitTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void setLoaded() {
|
synchronized void setLoaded() {
|
||||||
@@ -1589,7 +1583,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
mRecognitionConfig = null;
|
mRecognitionConfig = null;
|
||||||
mRequested = false;
|
mRequested = false;
|
||||||
mCallback = null;
|
mCallback = null;
|
||||||
notifyAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void clearCallback() {
|
synchronized void clearCallback() {
|
||||||
@@ -1694,12 +1687,4 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
|||||||
return "Model type: " + type + "\n";
|
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