diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index b4c4bf8b5ef33..7ee7423538a07 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -199,6 +199,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
modelData.setHandle(handle[0]);
modelData.setLoaded();
+ Slog.d(TAG, "Generic sound model loaded with handle:" + handle[0]);
}
modelData.setCallback(callback);
modelData.setRecognitionConfig(recognitionConfig);
@@ -227,7 +228,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
synchronized (mLock) {
if (DBG) {
- Slog.d(TAG, "startRecognition for keyphraseId=" + keyphraseId
+ Slog.d(TAG, "startKeyphraseRecognition for keyphraseId=" + keyphraseId
+ " soundModel=" + soundModel + ", listener=" + listener.asBinder()
+ ", recognitionConfig=" + recognitionConfig);
Slog.d(TAG, "moduleProperties=" + mModuleProperties);
@@ -243,13 +244,13 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
if (mModuleProperties == null) {
- Slog.w(TAG, "Attempting startRecognition without the capability");
+ Slog.w(TAG, "Attempting startKeyphraseRecognition without the capability");
return STATUS_ERROR;
}
if (mModule == null) {
mModule = SoundTrigger.attachModule(mModuleProperties.id, this, null);
if (mModule == null) {
- Slog.w(TAG, "startRecognition cannot attach to sound trigger module");
+ Slog.w(TAG, "startKeyphraseRecognition cannot attach to sound trigger module");
return STATUS_ERROR;
}
}
@@ -348,26 +349,29 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
if (currentCallback == null || !modelData.isModelStarted()) {
- // startRecognition hasn't been called or it failed.
- Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition");
+ // startGenericRecognition hasn't been called or it failed.
+ Slog.w(TAG, "Attempting stopGenericRecognition without a successful" +
+ " startGenericRecognition");
return STATUS_ERROR;
}
if (currentCallback.asBinder() != listener.asBinder()) {
// We don't allow a different listener to stop the recognition than the one
// that started it.
- Slog.w(TAG, "Attempting stopRecognition for another recognition");
+ Slog.w(TAG, "Attempting stopGenericRecognition for another recognition");
return STATUS_ERROR;
}
- int status = stopGenericRecognitionLocked(modelData, false /* don't notify for synchronous calls */);
+ int status = stopGenericRecognitionLocked(modelData,
+ false /* don't notify for synchronous calls */);
if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "stopGenericRecognition failed: " + status);
return status;
}
// We leave the sound model loaded but not started, this helps us when we start
// back.
// Also clear the internal state once the recognition has been stopped.
- modelData.clearState();
+ modelData.setLoaded();
modelData.clearCallback();
if (!computeRecognitionRunning()) {
internalClearGlobalStateLocked();
@@ -471,6 +475,66 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
return mModuleProperties;
}
+ int unloadKeyphraseSoundModel(int keyphraseId) {
+ if (mModule == null || mCurrentKeyphraseModelHandle == INVALID_VALUE) {
+ return STATUS_ERROR;
+ }
+ if (mKeyphraseId != keyphraseId) {
+ Slog.w(TAG, "Given sound model is not the one loaded.");
+ return STATUS_ERROR;
+ }
+
+ synchronized (mLock) {
+ // Stop recognition if it's the current one.
+ mRequested = false;
+ int status = updateRecognitionLocked(false /* don't notify */);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "Stop recognition failed for keyphrase ID:" + status);
+ }
+
+ status = mModule.unloadSoundModel(mCurrentKeyphraseModelHandle);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "unloadKeyphraseSoundModel call failed with " + status);
+ }
+ internalClearKeyphraseSoundModelLocked();
+ return status;
+ }
+ }
+
+ int unloadGenericSoundModel(UUID modelId) {
+ if (modelId == null || mModule == null) {
+ return STATUS_ERROR;
+ }
+ ModelData modelData = mGenericModelDataMap.get(modelId);
+ if (modelData == null) {
+ Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" + modelId);
+ return STATUS_ERROR;
+ }
+ synchronized (mLock) {
+ if (!modelData.isModelLoaded()) {
+ // Nothing to do here.
+ Slog.i(TAG, "Unload: Given generic model is not loaded:" + modelId);
+ return STATUS_OK;
+ }
+ if (modelData.isModelStarted()) {
+ int status = stopGenericRecognitionLocked(modelData,
+ false /* don't notify for synchronous calls */);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "stopGenericRecognition failed: " + status);
+ }
+ }
+
+ int status = mModule.unloadSoundModel(modelData.getHandle());
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "unloadGenericSoundModel() call failed with " + status);
+ Slog.w(TAG, "unloadGenericSoundModel() force-marking model as unloaded.");
+ }
+ mGenericModelDataMap.remove(modelId);
+ if (DBG) dumpGenericModelState();
+ return status;
+ }
+ }
+
//---- SoundTrigger.StatusListener methods
@Override
public void onRecognition(RecognitionEvent event) {
@@ -913,6 +977,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
} else {
+ Slog.i(TAG, "startRecognition successful.");
modelData.setStarted();
// Notify of resume if needed.
if (notify) {
@@ -923,6 +988,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
}
+ if (DBG) dumpGenericModelState();
return status;
}
@@ -951,9 +1017,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
}
+ if (DBG) dumpGenericModelState();
return status;
}
+ private void dumpGenericModelState() {
+ for (UUID modelId : mGenericModelDataMap.keySet()) {
+ ModelData modelData = mGenericModelDataMap.get(modelId);
+ Slog.i(TAG, "Model :" + modelData.toString());
+ }
+ }
+
// Computes whether we have any recognition running at all (voice or generic). Sets
// the mRecognitionRunning variable with the result.
private boolean computeRecognitionRunning() {
@@ -1069,5 +1143,18 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
synchronized RecognitionConfig getRecognitionConfig() {
return mRecognitionConfig;
}
+
+ String stateToString() {
+ switch(mModelState) {
+ case MODEL_NOTLOADED: return "NOT_LOADED";
+ case MODEL_LOADED: return "LOADED";
+ case MODEL_STARTED: return "STARTED";
+ }
+ return "Unknown state";
+ }
+
+ public String toString() {
+ return "Handle: " + mModelHandle + "ModelState: " + stateToString();
+ }
}
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
index 772287624f6ab..113431f2de7e8 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
@@ -75,5 +75,7 @@ public abstract class SoundTriggerInternal {
public abstract ModuleProperties getModuleProperties();
+ public abstract int unloadKeyphraseModel(int keyphaseId);
+
public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 251f3146f8cc2..a4c1210ba1888 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -122,10 +122,10 @@ public class SoundTriggerService extends SystemService {
public int startRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback,
RecognitionConfig config) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ if (!isInitialized()) return STATUS_ERROR;
if (DEBUG) {
Slog.i(TAG, "startRecognition(): Uuid : " + parcelUuid);
}
- if (!isInitialized()) return STATUS_ERROR;
GenericSoundModel model = getSoundModel(parcelUuid);
if (model == null) {
@@ -173,6 +173,8 @@ public class SoundTriggerService extends SystemService {
if (DEBUG) {
Slog.i(TAG, "deleteSoundModel(): id = " + soundModelId);
}
+ // Unload the model if it is loaded.
+ mSoundTriggerHelper.unloadGenericSoundModel(soundModelId.getUuid());
mDbHelper.deleteGenericSoundModel(soundModelId.getUuid());
}
}
@@ -215,6 +217,12 @@ public class SoundTriggerService extends SystemService {
return mSoundTriggerHelper.getModuleProperties();
}
+ @Override
+ public int unloadKeyphraseModel(int keyphraseId) {
+ if (!isInitialized()) return STATUS_ERROR;
+ return mSoundTriggerHelper.unloadKeyphraseSoundModel(keyphraseId);
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!isInitialized()) return;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 4a54643b3cf54..6ab0b998bd6c5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -760,6 +760,10 @@ public class VoiceInteractionManagerService extends SystemService {
final long caller = Binder.clearCallingIdentity();
boolean deleted = false;
try {
+ int unloadStatus = mSoundTriggerInternal.unloadKeyphraseModel(keyphraseId);
+ if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
+ Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
+ }
deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
} finally {
diff --git a/tests/SoundTriggerTestApp/AndroidManifest.xml b/tests/SoundTriggerTestApp/AndroidManifest.xml
index a72b3ddb7c0cf..dc4cdb59b8db9 100644
--- a/tests/SoundTriggerTestApp/AndroidManifest.xml
+++ b/tests/SoundTriggerTestApp/AndroidManifest.xml
@@ -2,10 +2,12 @@
package="com.android.test.soundtrigger">
+