diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java index 007f4bcd43fca..dc4f0b70651fe 100644 --- a/core/java/android/hardware/soundtrigger/SoundTrigger.java +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java @@ -611,6 +611,13 @@ public class SoundTrigger { * @hide */ public static final int RECOGNITION_STATUS_FAILURE = 2; + /** + * Recognition event was triggered by a getModelState request, not by the + * DSP. + * + * @hide + */ + public static final int RECOGNITION_STATUS_GET_STATE_RESPONSE = 3; /** * A RecognitionEvent is provided by the diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java index e970747d66421..402c228b93b1f 100644 --- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java +++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java @@ -133,12 +133,21 @@ public class SoundTriggerModule { public native int stopRecognition(int soundModelHandle); /** - * Get the current state of a {@link SoundTrigger.SoundModel} + * Get the current state of a {@link SoundTrigger.SoundModel}. + * The state will be returned asynchronously as a {@link SoundTrigger#RecognitionEvent} + * in the callback registered in the {@link SoundTrigger.startRecognition} method. * @param soundModelHandle The sound model handle indicating which model's state to return - * @return - {@link SoundTrigger#RecognitionEvent} in case of success - * - null in case of an error or if not supported + * @return - {@link SoundTrigger#STATUS_OK} in case of success + * - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error + * - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have + * system permission + * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached + * - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid + * - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native + * service fails + * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence */ - public native SoundTrigger.RecognitionEvent getModelState(int soundModelHandle); + public native int getModelState(int soundModelHandle); private class NativeEventHandlerDelegate { private final Handler mHandler; diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl index c0c689ced5217..764c0cfbd01c5 100644 --- a/core/java/com/android/internal/app/ISoundTriggerService.aidl +++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl @@ -53,5 +53,5 @@ interface ISoundTriggerService { /** For both ...Intent and ...Service based usage */ boolean isRecognitionActive(in ParcelUuid parcelUuid); - SoundTrigger.RecognitionEvent getModelState(in ParcelUuid parcelUuid); + int getModelState(in ParcelUuid soundModelId); } diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp index b417a5629f628..98bc735e1faea 100644 --- a/core/jni/android_hardware_SoundTrigger.cpp +++ b/core/jni/android_hardware_SoundTrigger.cpp @@ -788,61 +788,18 @@ android_hardware_SoundTrigger_stopRecognition(JNIEnv *env, jobject thiz, return status; } -static jobject +static jint android_hardware_SoundTrigger_getModelState(JNIEnv *env, jobject thiz, jint jHandle) { + jint status = SOUNDTRIGGER_STATUS_OK; ALOGV("getModelState"); sp module = getSoundTrigger(env, thiz); if (module == NULL) { - return NULL; + return SOUNDTRIGGER_STATUS_ERROR; } - sp memory; - jint status = module->getModelState(jHandle, memory); - if (status != 0 || memory == NULL) { - ALOGW("getModelState, failed to get model state, status: %d", status); - return NULL; - } - struct sound_trigger_recognition_event* event = - (struct sound_trigger_recognition_event *)memory->pointer(); - if (event == NULL) { - return NULL; - } - if (event->type != SOUND_MODEL_TYPE_GENERIC) { - ALOGW("getModelState, unsupported model type: %d", event->type); - return NULL; - } - - jbyteArray jData = NULL; - if (event->data_size) { - jData = env->NewByteArray(event->data_size); - jbyte *nData = env->GetByteArrayElements(jData, NULL); - memcpy(nData, (char *)event + event->data_offset, event->data_size); - env->ReleaseByteArrayElements(jData, nData, 0); - } - - jobject jAudioFormat = NULL; - if (event->trigger_in_data || event->capture_available) { - jAudioFormat = env->NewObject(gAudioFormatClass, - gAudioFormatCstor, - audioFormatFromNative(event->audio_config.format), - event->audio_config.sample_rate, - inChannelMaskFromNative(event->audio_config.channel_mask)); - - } - jobject jEvent = NULL; - jEvent = env->NewObject(gGenericRecognitionEventClass, gGenericRecognitionEventCstor, - event->status, event->model, event->capture_available, - event->capture_session, event->capture_delay_ms, - event->capture_preamble_ms, event->trigger_in_data, - jAudioFormat, jData); - if (jAudioFormat != NULL) { - env->DeleteLocalRef(jAudioFormat); - } - if (jData != NULL) { - env->DeleteLocalRef(jData); - } - return jEvent; + status = module->getModelState(jHandle); + return status; } static const JNINativeMethod gMethods[] = { @@ -875,7 +832,7 @@ static const JNINativeMethod gModuleMethods[] = { "(I)I", (void *)android_hardware_SoundTrigger_stopRecognition}, {"getModelState", - "(I)Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;", + "(I)I", (void *)android_hardware_SoundTrigger_getModelState}, }; diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java index cf7bf19909d90..fa69062c34dfc 100644 --- a/media/java/android/media/soundtrigger/SoundTriggerManager.java +++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java @@ -24,7 +24,6 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.UnsupportedAppUsage; -import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.hardware.soundtrigger.SoundTrigger; @@ -367,15 +366,15 @@ public final class SoundTriggerManager { } /** - * Synchronously get state of the indicated model. The model state is returned as - * a recognition event, or null if the model is not loaded, or if this method - * is not supported. + * Asynchronously get state of the indicated model. The model state is returned as + * a recognition event in the callback that was registered in the startRecognition + * method. * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) - public SoundTrigger.RecognitionEvent getModelState(UUID soundModelId) { + public int getModelState(UUID soundModelId) { if (soundModelId == null) { - return null; + return STATUS_ERROR; } try { return mSoundTriggerService.getModelState(new ParcelUuid(soundModelId)); diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java index ad2501d7c8cfa..d6b40aecf52e3 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java @@ -42,6 +42,7 @@ import android.os.RemoteException; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Slog; + import com.android.internal.logging.MetricsLogger; import java.io.FileDescriptor; @@ -566,38 +567,34 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } } - SoundTrigger.RecognitionEvent getGenericModelState(UUID modelId) { + int getGenericModelState(UUID modelId) { synchronized (mLock) { MetricsLogger.count(mContext, "sth_get_generic_model_state", 1); if (modelId == null || mModule == null) { - return null; + return STATUS_ERROR; } ModelData modelData = mModelDataMap.get(modelId); if (modelData == null || !modelData.isGenericModel()) { Slog.w(TAG, "GetGenericModelState error: Invalid generic model id:" + modelId); - return null; + return STATUS_ERROR; } if (!modelData.isModelLoaded()) { Slog.i(TAG, "GetGenericModelState: Given generic model is not loaded:" + modelId); - return null; + return STATUS_ERROR; } if (!modelData.isModelStarted()) { Slog.i(TAG, "GetGenericModelState: Given generic model is not started:" + modelId); - return null; + return STATUS_ERROR; } - SoundTrigger.RecognitionEvent ret = mModule.getModelState(modelData.getHandle()); - if (ret == null) { - Slog.w(TAG, "GetGenericModelState() call failed"); - } - return ret; + return mModule.getModelState(modelData.getHandle()); } } - SoundTrigger.RecognitionEvent getKeyphraseModelState(UUID modelId) { + int getKeyphraseModelState(UUID modelId) { Slog.w(TAG, "GetKeyphraseModelState error: Not implemented"); - return null; + return STATUS_ERROR; } //---- SoundTrigger.StatusListener methods diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java index d57fcb105f9b9..8c82cc835ed98 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java @@ -436,9 +436,10 @@ public class SoundTriggerService extends SystemService { } @Override - public SoundTrigger.RecognitionEvent getModelState(ParcelUuid soundModelId) { + public int getModelState(ParcelUuid soundModelId) { enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER); - if (!isInitialized()) return null; + int ret = STATUS_ERROR; + if (!isInitialized()) return ret; if (DEBUG) { Slog.i(TAG, "getModelState(): id = " + soundModelId); } @@ -447,9 +448,8 @@ public class SoundTriggerService extends SystemService { SoundModel soundModel = mLoadedModels.get(soundModelId.getUuid()); if (soundModel == null) { Slog.e(TAG, soundModelId + " is not loaded"); - return null; + return ret; } - SoundTrigger.RecognitionEvent ret = null; switch (soundModel.type) { case SoundModel.TYPE_KEYPHRASE: ret = mSoundTriggerHelper.getKeyphraseModelState(soundModel.uuid); @@ -461,9 +461,6 @@ public class SoundTriggerService extends SystemService { Slog.e(TAG, "Unknown model type"); break; } - if (ret == null) { - Slog.e(TAG, "Failed to get model state"); - } return ret; } @@ -942,7 +939,11 @@ public class SoundTriggerService extends SystemService { runOrAddOperation(new Operation( // always execute: () -> { - if (!mRecognitionConfig.allowMultipleTriggers) { + // Don't remove the callback if multiple triggers are allowed or + // if this event was triggered by a getModelState request + if (!mRecognitionConfig.allowMultipleTriggers + && event.status + != SoundTrigger.RECOGNITION_STATUS_GET_STATE_RESPONSE) { // Unregister this remoteService once op is done synchronized (mCallbacksLock) { mCallbacks.remove(mPuuid.getUuid());