Loading services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +108 −50 Original line number Diff line number Diff line Loading @@ -40,6 +40,9 @@ import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent; import android.hardware.soundtrigger.SoundTriggerModule; import android.os.Binder; import android.os.DeadObjectException; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.PowerManager.ServiceType; import android.os.RemoteException; Loading Loading @@ -113,6 +116,13 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private PowerSaveModeListener mPowerSaveModeListener; // Handler to process call state changes will delay to allow time for the audio // and sound trigger HALs to process the end of call notifications // before we re enable pending recognition requests. private final Handler mHandler; private static final int MSG_CALL_STATE_CHANGED = 0; private static final int CALL_INACTIVE_MSG_DELAY_MS = 1000; SoundTriggerHelper(Context context) { ArrayList <ModuleProperties> modules = new ArrayList<>(); int status = SoundTrigger.listModules(modules); Loading @@ -130,6 +140,31 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // TODO: Figure out how to determine which module corresponds to the DSP hardware. mModuleProperties = modules.get(0); } Looper looper = Looper.myLooper(); if (looper == null) { looper = Looper.getMainLooper(); } if (looper != null) { mHandler = new Handler(looper) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_CALL_STATE_CHANGED: synchronized (mLock) { onCallStateChangedLocked( TelephonyManager.CALL_STATE_OFFHOOK == msg.arg1); } break; default: Slog.e(TAG, "unknown message in handler:" + msg.what); break; } } }; } else { mHandler = null; } } /** Loading Loading @@ -227,6 +262,37 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return status; } private int prepareForRecognition(ModelData modelData) { if (mModule == null) { mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null); if (mModule == null) { Slog.w(TAG, "prepareForRecognition: cannot attach to sound trigger module"); return STATUS_ERROR; } } // Load the model if it is not loaded. if (!modelData.isModelLoaded()) { // Before we try and load this model, we should first make sure that any other // models that don't have an active recognition/dead callback are unloaded. Since // there is a finite limit on the number of models that the hardware may be able to // have loaded, we want to make sure there's room for our model. stopAndUnloadDeadModelsLocked(); int[] handle = new int[] { 0 }; int status = mModule.loadSoundModel(modelData.getSoundModel(), handle); if (status != SoundTrigger.STATUS_OK) { Slog.w(TAG, "prepareForRecognition: loadSoundModel failed with status: " + status); return status; } modelData.setHandle(handle[0]); modelData.setLoaded(); if (DBG) { Slog.d(TAG, "prepareForRecognition: Sound model loaded with handle:" + handle[0]); } } return STATUS_OK; } /** * Starts recognition for the given sound model. A single routine for both keyphrase and * generic sound models. Loading @@ -248,12 +314,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { Slog.w(TAG, "Attempting startRecognition without the capability"); return STATUS_ERROR; } if (mModule == null) { mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null); if (mModule == null) { Slog.w(TAG, "startRecognition cannot attach to sound trigger module"); return STATUS_ERROR; IRecognitionStatusCallback oldCallback = modelData.getCallback(); if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) { Slog.w(TAG, "Canceling previous recognition for model id: " + modelData.getModelId()); try { oldCallback.onError(STATUS_ERROR); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onDetectionStopped", e); } modelData.clearCallback(); } // If the existing SoundModel is different (for the same UUID for Generic and same Loading Loading @@ -287,45 +358,22 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } } IRecognitionStatusCallback oldCallback = modelData.getCallback(); if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) { Slog.w(TAG, "Canceling previous recognition for model id: " + modelData.getModelId()); try { oldCallback.onError(STATUS_ERROR); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onDetectionStopped", e); } modelData.clearCallback(); } // Load the model if it is not loaded. if (!modelData.isModelLoaded()) { // Before we try and load this model, we should first make sure that any other // models that don't have an active recognition/dead callback are unloaded. Since // there is a finite limit on the number of models that the hardware may be able to // have loaded, we want to make sure there's room for our model. stopAndUnloadDeadModelsLocked(); int[] handle = new int[] { INVALID_VALUE }; int status = mModule.loadSoundModel(soundModel, handle); if (status != SoundTrigger.STATUS_OK) { Slog.w(TAG, "loadSoundModel call failed with " + status); return status; } if (handle[0] == INVALID_VALUE) { Slog.w(TAG, "loadSoundModel call returned invalid sound model handle"); return STATUS_ERROR; } modelData.setHandle(handle[0]); modelData.setLoaded(); Slog.d(TAG, "Sound model loaded with handle:" + handle[0]); } modelData.setCallback(callback); modelData.setRequested(true); modelData.setRecognitionConfig(recognitionConfig); modelData.setSoundModel(soundModel); int status = startRecognitionLocked(modelData, if (!isRecognitionAllowed()) { initializeTelephonyAndPowerStateListeners(); return STATUS_OK; } int status = prepareForRecognition(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 */); // Initialize power save, call active state monitoring logic. Loading Loading @@ -398,7 +446,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (DBG) { Slog.d(TAG, "stopRecognition for keyphraseId=" + keyphraseId + ", callback =" + callback.asBinder()); Slog.d(TAG, "current callback=" + (modelData == null ? "null" : Slog.d(TAG, "current callback=" + ((modelData == null || modelData.getCallback() == null) ? "null" : modelData.getCallback().asBinder())); } int status = stopRecognition(modelData, callback); Loading Loading @@ -507,8 +556,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { synchronized (mLock) { MetricsLogger.count(mContext, "sth_unload_keyphrase_sound_model", 1); ModelData modelData = getKeyphraseModelDataLocked(keyphraseId); if (mModule == null || modelData == null || modelData.getHandle() == INVALID_VALUE || !modelData.isKeyphraseModel()) { if (mModule == null || modelData == null || !modelData.isModelLoaded() || !modelData.isKeyphraseModel()) { return STATUS_ERROR; } Loading Loading @@ -943,6 +992,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return STATUS_OK; } if (start) { int status = prepareForRecognition(model); if (status != STATUS_OK) { return status; } return startRecognitionLocked(model, notify); } else { return stopRecognitionLocked(model, notify); Loading Loading @@ -992,8 +1045,15 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { @Override public void onCallStateChanged(int state, String arg1) { if (DBG) Slog.d(TAG, "onCallStateChanged: " + state); if (mHandler != null) { synchronized (mLock) { onCallStateChangedLocked(TelephonyManager.CALL_STATE_OFFHOOK == state); mHandler.removeMessages(MSG_CALL_STATE_CHANGED); Message msg = mHandler.obtainMessage(MSG_CALL_STATE_CHANGED, state, 0); mHandler.sendMessageDelayed( msg, (TelephonyManager.CALL_STATE_OFFHOOK == state) ? 0 : CALL_INACTIVE_MSG_DELAY_MS); } } } } Loading Loading @@ -1216,9 +1276,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // models. private int startRecognitionLocked(ModelData modelData, boolean notify) { IRecognitionStatusCallback callback = modelData.getCallback(); int handle = modelData.getHandle(); RecognitionConfig config = modelData.getRecognitionConfig(); if (callback == null || handle == INVALID_VALUE || config == null) { if (callback == null || !modelData.isModelLoaded() || config == null) { // Nothing to do here. Slog.w(TAG, "startRecognition: Bad data passed in."); MetricsLogger.count(mContext, "sth_start_recognition_error", 1); Loading @@ -1235,7 +1294,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (mModule == null) { return STATUS_ERROR; } int status = mModule.startRecognition(handle, config); int status = mModule.startRecognition(modelData.getHandle(), config); if (status != SoundTrigger.STATUS_OK) { Slog.w(TAG, "startRecognition failed with " + status); MetricsLogger.count(mContext, "sth_start_recognition_error", 1); Loading Loading @@ -1376,7 +1435,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // Model handle is an integer used by the HAL as an identifier for sound // models. private int mModelHandle = INVALID_VALUE; private int mModelHandle; // The SoundModel instance, one of KeyphraseSoundModel or GenericSoundModel. private SoundModel mSoundModel = null; Loading Loading @@ -1436,7 +1495,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { synchronized void clearState() { mModelState = MODEL_NOTLOADED; mModelHandle = INVALID_VALUE; mRecognitionConfig = null; mRequested = false; mCallback = null; Loading Loading
services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +108 −50 Original line number Diff line number Diff line Loading @@ -40,6 +40,9 @@ import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent; import android.hardware.soundtrigger.SoundTriggerModule; import android.os.Binder; import android.os.DeadObjectException; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.PowerManager.ServiceType; import android.os.RemoteException; Loading Loading @@ -113,6 +116,13 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private PowerSaveModeListener mPowerSaveModeListener; // Handler to process call state changes will delay to allow time for the audio // and sound trigger HALs to process the end of call notifications // before we re enable pending recognition requests. private final Handler mHandler; private static final int MSG_CALL_STATE_CHANGED = 0; private static final int CALL_INACTIVE_MSG_DELAY_MS = 1000; SoundTriggerHelper(Context context) { ArrayList <ModuleProperties> modules = new ArrayList<>(); int status = SoundTrigger.listModules(modules); Loading @@ -130,6 +140,31 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // TODO: Figure out how to determine which module corresponds to the DSP hardware. mModuleProperties = modules.get(0); } Looper looper = Looper.myLooper(); if (looper == null) { looper = Looper.getMainLooper(); } if (looper != null) { mHandler = new Handler(looper) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_CALL_STATE_CHANGED: synchronized (mLock) { onCallStateChangedLocked( TelephonyManager.CALL_STATE_OFFHOOK == msg.arg1); } break; default: Slog.e(TAG, "unknown message in handler:" + msg.what); break; } } }; } else { mHandler = null; } } /** Loading Loading @@ -227,6 +262,37 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return status; } private int prepareForRecognition(ModelData modelData) { if (mModule == null) { mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null); if (mModule == null) { Slog.w(TAG, "prepareForRecognition: cannot attach to sound trigger module"); return STATUS_ERROR; } } // Load the model if it is not loaded. if (!modelData.isModelLoaded()) { // Before we try and load this model, we should first make sure that any other // models that don't have an active recognition/dead callback are unloaded. Since // there is a finite limit on the number of models that the hardware may be able to // have loaded, we want to make sure there's room for our model. stopAndUnloadDeadModelsLocked(); int[] handle = new int[] { 0 }; int status = mModule.loadSoundModel(modelData.getSoundModel(), handle); if (status != SoundTrigger.STATUS_OK) { Slog.w(TAG, "prepareForRecognition: loadSoundModel failed with status: " + status); return status; } modelData.setHandle(handle[0]); modelData.setLoaded(); if (DBG) { Slog.d(TAG, "prepareForRecognition: Sound model loaded with handle:" + handle[0]); } } return STATUS_OK; } /** * Starts recognition for the given sound model. A single routine for both keyphrase and * generic sound models. Loading @@ -248,12 +314,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { Slog.w(TAG, "Attempting startRecognition without the capability"); return STATUS_ERROR; } if (mModule == null) { mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null); if (mModule == null) { Slog.w(TAG, "startRecognition cannot attach to sound trigger module"); return STATUS_ERROR; IRecognitionStatusCallback oldCallback = modelData.getCallback(); if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) { Slog.w(TAG, "Canceling previous recognition for model id: " + modelData.getModelId()); try { oldCallback.onError(STATUS_ERROR); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onDetectionStopped", e); } modelData.clearCallback(); } // If the existing SoundModel is different (for the same UUID for Generic and same Loading Loading @@ -287,45 +358,22 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } } IRecognitionStatusCallback oldCallback = modelData.getCallback(); if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) { Slog.w(TAG, "Canceling previous recognition for model id: " + modelData.getModelId()); try { oldCallback.onError(STATUS_ERROR); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onDetectionStopped", e); } modelData.clearCallback(); } // Load the model if it is not loaded. if (!modelData.isModelLoaded()) { // Before we try and load this model, we should first make sure that any other // models that don't have an active recognition/dead callback are unloaded. Since // there is a finite limit on the number of models that the hardware may be able to // have loaded, we want to make sure there's room for our model. stopAndUnloadDeadModelsLocked(); int[] handle = new int[] { INVALID_VALUE }; int status = mModule.loadSoundModel(soundModel, handle); if (status != SoundTrigger.STATUS_OK) { Slog.w(TAG, "loadSoundModel call failed with " + status); return status; } if (handle[0] == INVALID_VALUE) { Slog.w(TAG, "loadSoundModel call returned invalid sound model handle"); return STATUS_ERROR; } modelData.setHandle(handle[0]); modelData.setLoaded(); Slog.d(TAG, "Sound model loaded with handle:" + handle[0]); } modelData.setCallback(callback); modelData.setRequested(true); modelData.setRecognitionConfig(recognitionConfig); modelData.setSoundModel(soundModel); int status = startRecognitionLocked(modelData, if (!isRecognitionAllowed()) { initializeTelephonyAndPowerStateListeners(); return STATUS_OK; } int status = prepareForRecognition(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 */); // Initialize power save, call active state monitoring logic. Loading Loading @@ -398,7 +446,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (DBG) { Slog.d(TAG, "stopRecognition for keyphraseId=" + keyphraseId + ", callback =" + callback.asBinder()); Slog.d(TAG, "current callback=" + (modelData == null ? "null" : Slog.d(TAG, "current callback=" + ((modelData == null || modelData.getCallback() == null) ? "null" : modelData.getCallback().asBinder())); } int status = stopRecognition(modelData, callback); Loading Loading @@ -507,8 +556,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { synchronized (mLock) { MetricsLogger.count(mContext, "sth_unload_keyphrase_sound_model", 1); ModelData modelData = getKeyphraseModelDataLocked(keyphraseId); if (mModule == null || modelData == null || modelData.getHandle() == INVALID_VALUE || !modelData.isKeyphraseModel()) { if (mModule == null || modelData == null || !modelData.isModelLoaded() || !modelData.isKeyphraseModel()) { return STATUS_ERROR; } Loading Loading @@ -943,6 +992,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return STATUS_OK; } if (start) { int status = prepareForRecognition(model); if (status != STATUS_OK) { return status; } return startRecognitionLocked(model, notify); } else { return stopRecognitionLocked(model, notify); Loading Loading @@ -992,8 +1045,15 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { @Override public void onCallStateChanged(int state, String arg1) { if (DBG) Slog.d(TAG, "onCallStateChanged: " + state); if (mHandler != null) { synchronized (mLock) { onCallStateChangedLocked(TelephonyManager.CALL_STATE_OFFHOOK == state); mHandler.removeMessages(MSG_CALL_STATE_CHANGED); Message msg = mHandler.obtainMessage(MSG_CALL_STATE_CHANGED, state, 0); mHandler.sendMessageDelayed( msg, (TelephonyManager.CALL_STATE_OFFHOOK == state) ? 0 : CALL_INACTIVE_MSG_DELAY_MS); } } } } Loading Loading @@ -1216,9 +1276,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // models. private int startRecognitionLocked(ModelData modelData, boolean notify) { IRecognitionStatusCallback callback = modelData.getCallback(); int handle = modelData.getHandle(); RecognitionConfig config = modelData.getRecognitionConfig(); if (callback == null || handle == INVALID_VALUE || config == null) { if (callback == null || !modelData.isModelLoaded() || config == null) { // Nothing to do here. Slog.w(TAG, "startRecognition: Bad data passed in."); MetricsLogger.count(mContext, "sth_start_recognition_error", 1); Loading @@ -1235,7 +1294,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (mModule == null) { return STATUS_ERROR; } int status = mModule.startRecognition(handle, config); int status = mModule.startRecognition(modelData.getHandle(), config); if (status != SoundTrigger.STATUS_OK) { Slog.w(TAG, "startRecognition failed with " + status); MetricsLogger.count(mContext, "sth_start_recognition_error", 1); Loading Loading @@ -1376,7 +1435,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // Model handle is an integer used by the HAL as an identifier for sound // models. private int mModelHandle = INVALID_VALUE; private int mModelHandle; // The SoundModel instance, one of KeyphraseSoundModel or GenericSoundModel. private SoundModel mSoundModel = null; Loading Loading @@ -1436,7 +1495,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { synchronized void clearState() { mModelState = MODEL_NOTLOADED; mModelHandle = INVALID_VALUE; mRecognitionConfig = null; mRequested = false; mCallback = null; Loading