VoiceInteractionService.java revision dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3
191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn/** 291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Copyright (C) 2014 The Android Open Source Project 391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * 491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * you may not use this file except in compliance with the License. 691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * You may obtain a copy of the License at 791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * 891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * 1091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 1191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 1291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * See the License for the specific language governing permissions and 1491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * limitations under the License. 1591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn */ 1691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 1791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornpackage android.service.voice; 1891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 1991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.annotation.SdkConstant; 2091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.app.Service; 21fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackbornimport android.content.ComponentName; 2291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.content.Context; 2391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.content.Intent; 24d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeepimport android.hardware.soundtrigger.KeyphraseEnrollmentInfo; 2518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackbornimport android.os.Bundle; 26fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackbornimport android.os.Handler; 2791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.IBinder; 28fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackbornimport android.os.Message; 2991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.RemoteException; 3091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.ServiceManager; 31fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackbornimport android.provider.Settings; 326daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha 3322968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddharthaimport com.android.internal.annotations.VisibleForTesting; 3491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.app.IVoiceInteractionManagerService; 3591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 366df952ec2208714d3206c54987eb388aee799be6Sandeep Siddharthaimport java.io.FileDescriptor; 376df952ec2208714d3206c54987eb388aee799be6Sandeep Siddharthaimport java.io.PrintWriter; 38dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddharthaimport java.util.Locale; 396df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha 40f7a13df899c30ddddbbf63274bc28174f6391f29Sandeep Siddhartha 41c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn/** 42c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * Top-level service of the current global voice interactor, which is providing 43c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * support for hotwording, the back-end of a {@link android.app.VoiceInteractor}, etc. 44c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * The current VoiceInteractionService that has been selected by the user is kept 45c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * always running by the system, to allow it to do things like listen for hotwords 46c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * in the background to instigate voice interactions. 47c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * 48c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * <p>Because this service is always running, it should be kept as lightweight as 49c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * possible. Heavy-weight operations (including showing UI) should be implemented 50c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * in the associated {@link android.service.voice.VoiceInteractionSessionService} when 51c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * an actual voice interaction is taking place, and that service should run in a 52c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn * separate process from this one. 53c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn */ 5491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornpublic class VoiceInteractionService extends Service { 5591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn /** 5691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * The {@link Intent} that must be declared as handled by the service. 5791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * To be supported, the service must also require the 5891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * {@link android.Manifest.permission#BIND_VOICE_INTERACTION} permission so 5991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * that other applications can not abuse it. 6091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn */ 6191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 6291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn public static final String SERVICE_INTERFACE = 6391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn "android.service.voice.VoiceInteractionService"; 6491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 6591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn /** 6691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Name under which a VoiceInteractionService component publishes information about itself. 6791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * This meta-data should reference an XML resource containing a 6891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * <code><{@link 6991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * android.R.styleable#VoiceInteractionService voice-interaction-service}></code> tag. 7091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn */ 7191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn public static final String SERVICE_META_DATA = "android.voice_interaction"; 7291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 7391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() { 74fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn @Override public void ready() { 75fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn mHandler.sendEmptyMessage(MSG_READY); 76fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 776daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha @Override public void shutdown() { 786daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha mHandler.sendEmptyMessage(MSG_SHUTDOWN); 796daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 806daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha @Override public void soundModelsChanged() { 816daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha mHandler.sendEmptyMessage(MSG_SOUND_MODELS_CHANGED); 826daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 8391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn }; 8491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 85fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn MyHandler mHandler; 86fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn 8791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn IVoiceInteractionManagerService mSystemService; 8891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 896daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha private final Object mLock = new Object(); 906daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha 91e912ac012e7146e9b0e8589bd9d88790e55372e3Sandeep Siddhartha private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo; 92e912ac012e7146e9b0e8589bd9d88790e55372e3Sandeep Siddhartha 936daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha private AlwaysOnHotwordDetector mHotwordDetector; 946daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha 95fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn static final int MSG_READY = 1; 966daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha static final int MSG_SHUTDOWN = 2; 976daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha static final int MSG_SOUND_MODELS_CHANGED = 3; 98fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn 99fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn class MyHandler extends Handler { 100fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn @Override 101fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn public void handleMessage(Message msg) { 102fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn switch (msg.what) { 103fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn case MSG_READY: 104fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn onReady(); 105fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn break; 1066daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha case MSG_SHUTDOWN: 1076daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha onShutdownInternal(); 1086daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha break; 1096daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha case MSG_SOUND_MODELS_CHANGED: 1106daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha onSoundModelsChangedInternal(); 1116daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha break; 112fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn default: 113fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn super.handleMessage(msg); 114fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 115fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 116fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 117fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn 118fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn /** 119fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn * Check whether the given service component is the currently active 120fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn * VoiceInteractionService. 121fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn */ 122fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn public static boolean isActiveService(Context context, ComponentName service) { 123fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn String cur = Settings.Secure.getString(context.getContentResolver(), 124fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn Settings.Secure.VOICE_INTERACTION_SERVICE); 125fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn if (cur == null || cur.isEmpty()) { 126fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn return false; 127fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 128fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn ComponentName curComp = ComponentName.unflattenFromString(cur); 129fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn if (curComp == null) { 130fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn return false; 131fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 132e2c020a449cf1de10230d2ac31a083f342aa75c8Barnaby James return curComp.equals(service); 133fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 134fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn 135fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn /** 136fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn * Initiate the execution of a new {@link android.service.voice.VoiceInteractionSession}. 137fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn * @param args Arbitrary arguments that will be propagated to the session. 138fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn */ 139c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn public void startSession(Bundle args) { 140fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn if (mSystemService == null) { 141fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn throw new IllegalStateException("Not available until onReady() is called"); 142fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 14391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn try { 144c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn mSystemService.startSession(mInterface, args); 14591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn } catch (RemoteException e) { 14691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn } 14791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn } 14891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 14991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn @Override 15091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn public void onCreate() { 15191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn super.onCreate(); 152fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn mHandler = new MyHandler(); 15391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn } 15491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn 15591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn @Override 15691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn public IBinder onBind(Intent intent) { 15791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn if (SERVICE_INTERFACE.equals(intent.getAction())) { 15891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn return mInterface.asBinder(); 15991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn } 16091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn return null; 16191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn } 162e912ac012e7146e9b0e8589bd9d88790e55372e3Sandeep Siddhartha 163e912ac012e7146e9b0e8589bd9d88790e55372e3Sandeep Siddhartha /** 164fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn * Called during service initialization to tell you when the system is ready 1656daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * to receive interaction from it. You should generally do initialization here 1666daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * rather than in {@link #onCreate()}. Methods such as {@link #startSession(Bundle)} and 167dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha * {@link #createAlwaysOnHotwordDetector(String, Locale, android.service.voice.AlwaysOnHotwordDetector.Callback)} 1686daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * will not be operational until this point. 169fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn */ 170fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn public void onReady() { 171fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn mSystemService = IVoiceInteractionManagerService.Stub.asInterface( 172fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE)); 173fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager()); 174fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 175fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn 1766daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha private void onShutdownInternal() { 1776daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha onShutdown(); 1786daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha // Stop any active recognitions when shutting down. 1796daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha // This ensures that if implementations forget to stop any active recognition, 1806daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha // It's still guaranteed to have been stopped. 1816daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha // This helps with cases where the voice interaction implementation is changed 1826daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha // by the user. 1836daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha safelyShutdownHotwordDetector(); 1846daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 1856daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha 1866daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha /** 1876daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * Called during service de-initialization to tell you when the system is shutting the 1886daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * service down. 1895e33fb057c20b84418d96574abe861e9d05956ebSandeep Siddhartha * At this point this service may no longer be the active {@link VoiceInteractionService}. 1906daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha */ 1916daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha public void onShutdown() { 1926daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 1936daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha 1946daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha private void onSoundModelsChangedInternal() { 1956daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha synchronized (this) { 1966daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha if (mHotwordDetector != null) { 1976daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha // TODO: Stop recognition if a sound model that was being recognized gets deleted. 1986daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha mHotwordDetector.onSoundModelsChanged(); 1996daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 2006daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 2016daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 2026daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha 203fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn /** 204dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha * FIXME: Remove once the prebuilts are updated. 205dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha * 206dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha * @hide 207dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha */ 208dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha @Deprecated 209dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector( 210dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) { 211dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha return createAlwaysOnHotwordDetector(keyphrase, new Locale(locale), callback); 212dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha } 213dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha 214dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha /** 2156daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * Creates an {@link AlwaysOnHotwordDetector} for the given keyphrase and locale. 2166daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * This instance must be retained and used by the client. 2176daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * Calling this a second time invalidates the previously created hotword detector 2186daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * which can no longer be used to manage recognition. 2196daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha * 220d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep * @param keyphrase The keyphrase that's being used, for example "Hello Android". 221d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep * @param locale The locale for which the enrollment needs to be performed. 222d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep * @param callback The callback to notify of detection events. 223d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep * @return An always-on hotword detector for the given keyphrase and locale. 224e912ac012e7146e9b0e8589bd9d88790e55372e3Sandeep Siddhartha */ 2256daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector( 226dcf3068fcb55f101680e70a8a6f84f3b2c9cb1e3Sandeep Siddhartha String keyphrase, Locale locale, AlwaysOnHotwordDetector.Callback callback) { 227fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn if (mSystemService == null) { 228fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn throw new IllegalStateException("Not available until onReady() is called"); 229fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn } 2306daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha synchronized (mLock) { 2316daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha // Allow only one concurrent recognition via the APIs. 2326daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha safelyShutdownHotwordDetector(); 2336daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback, 2346daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha mKeyphraseEnrollmentInfo, mInterface, mSystemService); 2356daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 2366daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha return mHotwordDetector; 237e912ac012e7146e9b0e8589bd9d88790e55372e3Sandeep Siddhartha } 23822968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha 23922968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha /** 24022968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha * @return Details of keyphrases available for enrollment. 24122968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha * @hide 24222968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha */ 24322968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha @VisibleForTesting 24422968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha protected final KeyphraseEnrollmentInfo getKeyphraseEnrollmentInfo() { 24522968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha return mKeyphraseEnrollmentInfo; 24622968950b814e66a6aa119ea92ae648884cbe0d9Sandeep Siddhartha } 2476daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha 2486daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha private void safelyShutdownHotwordDetector() { 2496daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha try { 2506daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha synchronized (mLock) { 2516daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha if (mHotwordDetector != null) { 2526daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha mHotwordDetector.stopRecognition(); 2536daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha mHotwordDetector.invalidate(); 2546daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha mHotwordDetector = null; 2556daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 2566daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 2576daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } catch (Exception ex) { 2586daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha // Ignore. 2596daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 2606daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha } 2616df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha 2626df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha @Override 2636df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2646df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha pw.println("VOICE INTERACTION"); 2656df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha synchronized (mLock) { 2666df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha pw.println(" AlwaysOnHotwordDetector"); 2676df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha if (mHotwordDetector == null) { 2686df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha pw.println(" NULL"); 2696df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha } else { 2706df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha mHotwordDetector.dump(" ", pw); 2716df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha } 2726df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha } 2736df952ec2208714d3206c54987eb388aee799be6Sandeep Siddhartha } 27491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn} 275