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