1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware.soundtrigger; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.os.Handler; 22 import android.os.Looper; 23 import android.os.Message; 24 import java.lang.ref.WeakReference; 25 import java.util.UUID; 26 27 /** 28 * The SoundTriggerModule provides APIs to control sound models and sound detection 29 * on a given sound trigger hardware module. 30 * 31 * @hide 32 */ 33 public class SoundTriggerModule { 34 private long mNativeContext; 35 36 private int mId; 37 private NativeEventHandlerDelegate mEventHandlerDelegate; 38 39 // to be kept in sync with core/jni/android_hardware_SoundTrigger.cpp 40 private static final int EVENT_RECOGNITION = 1; 41 private static final int EVENT_SERVICE_DIED = 2; 42 private static final int EVENT_SOUNDMODEL = 3; 43 private static final int EVENT_SERVICE_STATE_CHANGE = 4; 44 45 SoundTriggerModule(int moduleId, SoundTrigger.StatusListener listener, Handler handler) { 46 mId = moduleId; 47 mEventHandlerDelegate = new NativeEventHandlerDelegate(listener, handler); 48 native_setup(new WeakReference<SoundTriggerModule>(this)); 49 } 50 private native void native_setup(Object module_this); 51 52 @Override 53 protected void finalize() { 54 native_finalize(); 55 } 56 private native void native_finalize(); 57 58 /** 59 * Detach from this module. The {@link SoundTrigger.StatusListener} callback will not be called 60 * anymore and associated resources will be released. 61 * */ 62 public native void detach(); 63 64 /** 65 * Load a {@link SoundTrigger.SoundModel} to the hardware. A sound model must be loaded in 66 * order to start listening to a key phrase in this model. 67 * @param model The sound model to load. 68 * @param soundModelHandle an array of int where the sound model handle will be returned. 69 * @return - {@link SoundTrigger#STATUS_OK} in case of success 70 * - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error 71 * - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have 72 * system permission 73 * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached 74 * - {@link SoundTrigger#STATUS_BAD_VALUE} if parameters are invalid 75 * - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native 76 * service fails 77 * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence 78 */ 79 public native int loadSoundModel(SoundTrigger.SoundModel model, int[] soundModelHandle); 80 81 /** 82 * Unload a {@link SoundTrigger.SoundModel} and abort any pendiong recognition 83 * @param soundModelHandle The sound model handle 84 * @return - {@link SoundTrigger#STATUS_OK} in case of success 85 * - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error 86 * - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have 87 * system permission 88 * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached 89 * - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid 90 * - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native 91 * service fails 92 */ 93 public native int unloadSoundModel(int soundModelHandle); 94 95 /** 96 * Start listening to all key phrases in a {@link SoundTrigger.SoundModel}. 97 * Recognition must be restarted after each callback (success or failure) received on 98 * the {@link SoundTrigger.StatusListener}. 99 * @param soundModelHandle The sound model handle to start listening to 100 * @param config contains configuration information for this recognition request: 101 * recognition mode, keyphrases, users, minimum confidence levels... 102 * @return - {@link SoundTrigger#STATUS_OK} in case of success 103 * - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error 104 * - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have 105 * system permission 106 * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached 107 * - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid 108 * - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native 109 * service fails 110 * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence 111 */ 112 public native int startRecognition(int soundModelHandle, SoundTrigger.RecognitionConfig config); 113 114 /** 115 * Stop listening to all key phrases in a {@link SoundTrigger.SoundModel} 116 * @param soundModelHandle The sound model handle to stop listening to 117 * @return - {@link SoundTrigger#STATUS_OK} in case of success 118 * - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error 119 * - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have 120 * system permission 121 * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached 122 * - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid 123 * - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native 124 * service fails 125 * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence 126 */ 127 public native int stopRecognition(int soundModelHandle); 128 129 private class NativeEventHandlerDelegate { 130 private final Handler mHandler; 131 132 NativeEventHandlerDelegate(final SoundTrigger.StatusListener listener, 133 Handler handler) { 134 // find the looper for our new event handler 135 Looper looper; 136 if (handler != null) { 137 looper = handler.getLooper(); 138 } else { 139 looper = Looper.getMainLooper(); 140 } 141 142 // construct the event handler with this looper 143 if (looper != null) { 144 // implement the event handler delegate 145 mHandler = new Handler(looper) { 146 @Override 147 public void handleMessage(Message msg) { 148 switch(msg.what) { 149 case EVENT_RECOGNITION: 150 if (listener != null) { 151 listener.onRecognition( 152 (SoundTrigger.RecognitionEvent)msg.obj); 153 } 154 break; 155 case EVENT_SOUNDMODEL: 156 if (listener != null) { 157 listener.onSoundModelUpdate( 158 (SoundTrigger.SoundModelEvent)msg.obj); 159 } 160 break; 161 case EVENT_SERVICE_STATE_CHANGE: 162 if (listener != null) { 163 listener.onServiceStateChange(msg.arg1); 164 } 165 break; 166 case EVENT_SERVICE_DIED: 167 if (listener != null) { 168 listener.onServiceDied(); 169 } 170 break; 171 default: 172 break; 173 } 174 } 175 }; 176 } else { 177 mHandler = null; 178 } 179 } 180 181 Handler handler() { 182 return mHandler; 183 } 184 } 185 186 @SuppressWarnings("unused") 187 private static void postEventFromNative(Object module_ref, 188 int what, int arg1, int arg2, Object obj) { 189 SoundTriggerModule module = (SoundTriggerModule)((WeakReference)module_ref).get(); 190 if (module == null) { 191 return; 192 } 193 194 NativeEventHandlerDelegate delegate = module.mEventHandlerDelegate; 195 if (delegate != null) { 196 Handler handler = delegate.handler(); 197 if (handler != null) { 198 Message m = handler.obtainMessage(what, arg1, arg2, obj); 199 handler.sendMessage(m); 200 } 201 } 202 } 203 } 204 205