import android.hardware.soundtrigger.SoundTrigger.SoundModel;
import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent;
import android.hardware.soundtrigger.SoundTriggerModule;
+import android.os.DeadObjectException;
import android.os.PowerManager;
import android.os.RemoteException;
import android.telephony.PhoneStateListener;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
import java.util.UUID;
/**
ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
if (modelData == null || !modelData.isKeyphraseModel()) {
- Slog.e(TAG, "No model exists for given keyphrase Id.");
+ Slog.e(TAG, "No model exists for given keyphrase Id " + keyphraseId);
return STATUS_ERROR;
}
return;
}
+ model.setStopped();
try {
callback.onGenericSoundTriggerDetected((GenericRecognitionEvent) event);
+ } catch (DeadObjectException e) {
+ forceStopAndUnloadModel(model, e);
+ return;
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onGenericSoundTriggerDetected", e);
}
- model.setStopped();
RecognitionConfig config = model.getRecognitionConfig();
if (config == null) {
Slog.w(TAG, "Generic recognition event: Null RecognitionConfig for model handle: " +
modelData.setStopped();
try {
modelData.getCallback().onRecognitionPaused();
+ } catch (DeadObjectException e) {
+ forceStopAndUnloadModel(modelData, e);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
}
MetricsLogger.count(mContext, "sth_recognition_failure_event", 1);
try {
sendErrorCallbacksToAll(STATUS_ERROR);
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onError", e);
} finally {
internalClearModelStateLocked();
internalClearGlobalStateLocked();
Slog.w(TAG, "Received onRecognition event without callback for keyphrase model.");
return;
}
+ modelData.setStopped();
try {
modelData.getCallback().onKeyphraseDetected((KeyphraseRecognitionEvent) event);
+ } catch (DeadObjectException e) {
+ forceStopAndUnloadModel(modelData, e);
+ return;
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onKeyphraseDetected", e);
}
- modelData.setStopped();
-
RecognitionConfig config = modelData.getRecognitionConfig();
if (config != null) {
// Whether we should continue by starting this again.
private void onServiceDiedLocked() {
try {
- MetricsLogger.count(mContext, "sth_service_died", 1);
+ MetricsLogger.count(mContext, "sth_service_died", 1);
sendErrorCallbacksToAll(SoundTrigger.STATUS_DEAD_OBJECT);
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onError", e);
} finally {
internalClearModelStateLocked();
internalClearGlobalStateLocked();
}
// Sends an error callback to all models with a valid registered callback.
- private void sendErrorCallbacksToAll(int errorCode) throws RemoteException {
+ private void sendErrorCallbacksToAll(int errorCode) {
for (ModelData modelData : mModelDataMap.values()) {
IRecognitionStatusCallback callback = modelData.getCallback();
if (callback != null) {
- callback.onError(STATUS_ERROR);
+ try {
+ callback.onError(errorCode);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException sendErrorCallbacksToAll for model handle " +
+ modelData.getHandle(), e);
+ }
+ }
+ }
+ }
+
+ private void forceStopAndUnloadModel(ModelData modelData, Exception exception) {
+ if (exception != null) {
+ Slog.e(TAG, "forceStopAndUnloadModel", exception);
+ }
+ if (modelData.isModelStarted()) {
+ Slog.d(TAG, "Stopping previously started dangling model " + modelData.getHandle());
+ if (mModule.stopRecognition(modelData.getHandle()) != STATUS_OK) {
+ modelData.setStopped();
+ modelData.setRequested(false);
+ } else {
+ Slog.e(TAG, "Failed to stop model " + modelData.getHandle());
+ }
+ }
+ if (modelData.isModelLoaded()) {
+ Slog.d(TAG, "Unloading previously loaded dangling model " + modelData.getHandle());
+ if (mModule.unloadSoundModel(modelData.getHandle()) == STATUS_OK) {
+ // Remove the model data from existence.
+ mModelDataMap.remove(modelData.getModelId());
+ Iterator it = mKeyphraseUuidMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry pair = (Map.Entry) it.next();
+ if (pair.getValue().equals(modelData.getModelId())) {
+ it.remove();
+ }
+ }
+ modelData.clearState();
+ } else {
+ Slog.e(TAG, "Failed to unload model " + modelData.getHandle());
}
}
}
if (notify) {
try {
callback.onError(status);
+ } catch (DeadObjectException e) {
+ forceStopAndUnloadModel(modelData, e);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onError", e);
}
if (notify) {
try {
callback.onRecognitionResumed();
+ } catch (DeadObjectException e) {
+ forceStopAndUnloadModel(modelData, e);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onRecognitionResumed", e);
}
if (notify) {
try {
callback.onError(status);
+ } catch (DeadObjectException e) {
+ forceStopAndUnloadModel(modelData, e);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onError", e);
}
if (notify) {
try {
callback.onRecognitionPaused();
+ } catch (DeadObjectException e) {
+ forceStopAndUnloadModel(modelData, e);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
}