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