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