Merge "Unload logic for generic and keyphrase sound models." into nyc-dev

This commit is contained in:
Arunesh Mishra
2016-02-23 03:11:17 +00:00
committed by Android (Google) Code Review
6 changed files with 162 additions and 22 deletions

View File

@@ -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();
}
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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 {

View File

@@ -2,10 +2,12 @@
package="com.android.test.soundtrigger">
<uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
<uses-permission android:name="android.permission.WAKE_LOCk" />
<application>
<activity
android:name="TestSoundTriggerActivity"
android:label="SoundTrigger Test Application"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Material">
<!--
<intent-filter>

View File

@@ -28,6 +28,8 @@ import android.media.soundtrigger.SoundTriggerManager;
import android.text.Editable;
import android.text.method.ScrollingMovementMethod;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.UserManager;
import android.util.Log;
import android.view.View;
@@ -54,6 +56,8 @@ public class TestSoundTriggerActivity extends Activity {
private TextView mDebugView = null;
private int mSelectedModelId = 1;
private ScrollView mScrollView = null;
private PowerManager.WakeLock mScreenWakelock;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -66,6 +70,7 @@ public class TestSoundTriggerActivity extends Activity {
mDebugView.setMovementMethod(new ScrollingMovementMethod());
mSoundTriggerUtil = new SoundTriggerUtil(this);
mRandom = new Random();
mHandler = new Handler();
}
private void postMessage(String msg) {
@@ -85,24 +90,43 @@ public class TestSoundTriggerActivity extends Activity {
});
}
private UUID getSelectedUuid() {
private synchronized UUID getSelectedUuid() {
if (mSelectedModelId == 2) return mModelUuid2;
if (mSelectedModelId == 3) return mModelUuid3;
return mModelUuid1; // Default.
}
private void setDetector(SoundTriggerDetector detector) {
if (mSelectedModelId == 2) mDetector2 = detector;
if (mSelectedModelId == 3) mDetector3 = detector;
private synchronized void setDetector(SoundTriggerDetector detector) {
if (mSelectedModelId == 2) {
mDetector2 = detector;
return;
}
if (mSelectedModelId == 3) {
mDetector3 = detector;
return;
}
mDetector1 = detector;
}
private SoundTriggerDetector getDetector() {
private synchronized SoundTriggerDetector getDetector() {
if (mSelectedModelId == 2) return mDetector2;
if (mSelectedModelId == 3) return mDetector3;
return mDetector1;
}
private void screenWakeup() {
PowerManager pm = ((PowerManager)getSystemService(POWER_SERVICE));
if (mScreenWakelock == null) {
mScreenWakelock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");
}
mScreenWakelock.acquire();
}
private void screenRelease() {
PowerManager pm = ((PowerManager)getSystemService(POWER_SERVICE));
mScreenWakelock.release();
}
/**
* Called when the user clicks the enroll button.
* Performs a fresh enrollment.
@@ -139,7 +163,7 @@ public class TestSoundTriggerActivity extends Activity {
Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
return;
}
boolean status = mSoundTriggerUtil.deleteSoundModel(mModelUuid1);
boolean status = mSoundTriggerUtil.deleteSoundModel(modelUuid);
if (status) {
Toast.makeText(this, "Successfully deleted model UUID=" + soundModel.uuid,
Toast.LENGTH_SHORT)
@@ -204,22 +228,28 @@ public class TestSoundTriggerActivity extends Activity {
}
}
public void onRadioButtonClicked(View view) {
public synchronized void onRadioButtonClicked(View view) {
// Is the button now checked?
boolean checked = ((RadioButton) view).isChecked();
// Check which radio button was clicked
switch(view.getId()) {
case R.id.model_one:
if (checked) mSelectedModelId = 1;
postMessage("Selected model one.");
if (checked) {
mSelectedModelId = 1;
postMessage("Selected model one.");
}
break;
case R.id.model_two:
if (checked) mSelectedModelId = 2;
postMessage("Selected model two.");
if (checked) {
mSelectedModelId = 2;
postMessage("Selected model two.");
}
break;
case R.id.model_three:
if (checked) mSelectedModelId = 3;
postMessage("Selected model three.");
if (checked) {
mSelectedModelId = 3;
postMessage("Selected model three.");
}
break;
}
}
@@ -232,6 +262,13 @@ public class TestSoundTriggerActivity extends Activity {
public void onDetected(SoundTriggerDetector.EventPayload event) {
postMessage("onDetected(): " + eventPayloadToString(event));
screenWakeup();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
screenRelease();
}
}, 1000L);
}
public void onError() {