1 /*
2  * Copyright (C) 2010 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.speech;
18 
19 import android.Manifest;
20 import android.annotation.CallbackExecutor;
21 import android.annotation.IntDef;
22 import android.annotation.MainThread;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.RequiresPermission;
26 import android.annotation.TestApi;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.ResolveInfo;
31 import android.os.Bundle;
32 
33 import com.android.internal.R;
34 
35 import java.lang.annotation.Documented;
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 import java.util.List;
39 import java.util.concurrent.Executor;
40 
41 /**
42  * This class provides access to the speech recognition service. This service allows access to the
43  * speech recognizer. Do not instantiate this class directly, instead, call
44  * {@link SpeechRecognizer#createSpeechRecognizer(Context)}, or
45  * {@link SpeechRecognizer#createOnDeviceSpeechRecognizer(Context)}. This class's methods must be
46  * invoked only from the main application thread.
47  *
48  * <p><strong>Important:</strong> the caller MUST invoke {@link #destroy()} on a
49  * SpeechRecognizer object when it is no longer needed.
50  *
51  * <p>The implementation of this API is likely to stream audio to remote servers to perform speech
52  * recognition. As such this API is not intended to be used for continuous recognition, which would
53  * consume a significant amount of battery and bandwidth.
54  *
55  * <p>Please note that the application must have {@link android.Manifest.permission#RECORD_AUDIO}
56  * permission to use this class.
57  */
58 public class SpeechRecognizer {
59 
60     /**
61      * Key used to retrieve an {@code ArrayList<String>} from the {@link Bundle} passed to the
62      * {@link RecognitionListener#onResults(Bundle)} and
63      * {@link RecognitionListener#onPartialResults(Bundle)} methods. These strings are the possible
64      * recognition results, where the first element is the most likely candidate.
65      */
66     public static final String RESULTS_RECOGNITION = "results_recognition";
67 
68     /**
69      * Key used to retrieve a float array from the {@link Bundle} passed to the
70      * {@link RecognitionListener#onResults(Bundle)} and
71      * {@link RecognitionListener#onPartialResults(Bundle)} methods. The array should be
72      * the same size as the ArrayList provided in {@link #RESULTS_RECOGNITION}, and should contain
73      * values ranging from 0.0 to 1.0, or -1 to represent an unavailable confidence score.
74      * <p>
75      * Confidence values close to 1.0 indicate high confidence (the speech recognizer is confident
76      * that the recognition result is correct), while values close to 0.0 indicate low confidence.
77      * <p>
78      * This value is optional and might not be provided.
79      */
80     public static final String CONFIDENCE_SCORES = "confidence_scores";
81 
82     /**
83      * Key used to retrieve an ArrayList&lt;{@link AlternativeSpans}&gt; from the {@link Bundle}
84      * passed to the {@link RecognitionListener#onResults(Bundle)} and
85      * {@link RecognitionListener#onPartialResults(Bundle)} methods. The list should be the same
86      * size as the ArrayList provided in {@link #RESULTS_RECOGNITION}.
87      *
88      * <p> A single {@link SpeechRecognizer} result is represented as a {@link String}. For a
89      * specific span (substring) of the originally recognized result string the recognizer provides
90      * a list of alternative hypotheses in the form of an {@link AlternativeSpan} object.
91      * Alternatives for different spans of a result string are listed in an {@link AlternativeSpans}
92      * object. Each item from the ArrayList retrieved by this key corresponds to a single result
93      * string provided in {@link #RESULTS_RECOGNITION}.
94      *
95      * <p> This value is optional and might not be provided.
96      */
97     public static final String RESULTS_ALTERNATIVES = "results_alternatives";
98 
99     /**
100      * Key used to receive an ArrayList&lt;{@link RecognitionPart}&gt; object from the
101      * {@link Bundle} passed to the {@link RecognitionListener#onResults(Bundle)} and
102      * {@link RecognitionListener#onSegmentResults(Bundle)} methods.
103      *
104      * <p> A single {@link SpeechRecognizer} result is represented as a {@link String}. Each word of
105      * the resulting String, as well as any potential adjacent punctuation, is represented by a
106      * {@link RecognitionPart} item from the ArrayList retrieved by this key.
107      */
108     public static final String RECOGNITION_PARTS = "recognition_parts";
109 
110     /**
111      * Key used to retrieve a {@link String} representation of the IETF language tag (as defined by
112      * BCP 47, e.g., "en-US", "de-DE") of the detected language of the most recent audio chunk.
113      *
114      * <p> This info is returned to the client in the {@link Bundle} passed to
115      * {@link RecognitionListener#onLanguageDetection(Bundle)} only if
116      * {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_DETECTION} is set. Additionally, if
117      * {@link RecognizerIntent#EXTRA_LANGUAGE_DETECTION_ALLOWED_LANGUAGES} are listed,
118      * the detected language is constrained to be one from the list.
119      */
120     public static final String DETECTED_LANGUAGE = "detected_language";
121 
122     /**
123      * Key used to retrieve the level of confidence of the detected language
124      * of the most recent audio chunk,
125      * represented by an {@code int} value prefixed by {@code LANGUAGE_DETECTION_CONFIDENCE_LEVEL_}.
126      *
127      * <p> This info is returned to the client in the {@link Bundle} passed to
128      * {@link RecognitionListener#onLanguageDetection(Bundle)} only if
129      * {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_DETECTION} is set.
130      */
131     public static final String LANGUAGE_DETECTION_CONFIDENCE_LEVEL =
132             "language_detection_confidence_level";
133 
134     /**
135      * The level of language detection confidence.
136      *
137      * @hide
138      */
139     @Documented
140     @Retention(RetentionPolicy.SOURCE)
141     @IntDef(prefix = {"LANGUAGE_DETECTION_CONFIDENCE_LEVEL_"}, value = {
142             LANGUAGE_DETECTION_CONFIDENCE_LEVEL_UNKNOWN,
143             LANGUAGE_DETECTION_CONFIDENCE_LEVEL_NOT_CONFIDENT,
144             LANGUAGE_DETECTION_CONFIDENCE_LEVEL_CONFIDENT,
145             LANGUAGE_DETECTION_CONFIDENCE_LEVEL_HIGHLY_CONFIDENT
146     })
147     public @interface LanguageDetectionConfidenceLevel {}
148 
149     public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_UNKNOWN = 0;
150     public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_NOT_CONFIDENT = 1;
151     public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_CONFIDENT = 2;
152     public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_HIGHLY_CONFIDENT = 3;
153 
154     /**
155      * Key used to retrieve an ArrayList&lt;{@link String}&gt; containing representations of the
156      * IETF language tags (as defined by BCP 47, e.g., "en-US", "en-UK") denoting the alternative
157      * locales for the same language retrieved by the key {@link #DETECTED_LANGUAGE}.
158      *
159      * This info is returned to the client in the {@link Bundle} passed to
160      * {@link RecognitionListener#onLanguageDetection(Bundle)} only if
161      * {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_DETECTION} is set.
162      */
163     public static final String TOP_LOCALE_ALTERNATIVES = "top_locale_alternatives";
164 
165     /**
166      * Key used to retrieve the result of the language switch of the most recent audio chunk,
167      * represented by an {@code int} value prefixed by {@code LANGUAGE_SWITCH_}.
168      *
169      * <p> This info is returned to the client in the {@link Bundle} passed to the
170      * {@link RecognitionListener#onLanguageDetection(Bundle)} only if
171      * {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_SWITCH} is set.
172      */
173     public static final String LANGUAGE_SWITCH_RESULT = "language_switch_result";
174 
175     /**
176      * The result of the language switch.
177      *
178      * @hide
179      */
180     @Documented
181     @Retention(RetentionPolicy.SOURCE)
182     @IntDef(prefix = {"LANGUAGE_SWITCH_RESULT_"}, value = {
183             LANGUAGE_SWITCH_RESULT_NOT_ATTEMPTED,
184             LANGUAGE_SWITCH_RESULT_SUCCEEDED,
185             LANGUAGE_SWITCH_RESULT_FAILED,
186             LANGUAGE_SWITCH_RESULT_SKIPPED_NO_MODEL
187     })
188     public @interface LanguageSwitchResult {}
189 
190     /** Switch not attempted. */
191     public static final int LANGUAGE_SWITCH_RESULT_NOT_ATTEMPTED = 0;
192 
193     /** Switch attempted and succeeded. */
194     public static final int LANGUAGE_SWITCH_RESULT_SUCCEEDED = 1;
195 
196     /** Switch attempted and failed. */
197     public static final int LANGUAGE_SWITCH_RESULT_FAILED = 2;
198 
199     /**
200      * Switch skipped because the language model is missing
201      * or the language is not allowlisted for auto switch.
202      */
203     public static final int LANGUAGE_SWITCH_RESULT_SKIPPED_NO_MODEL = 3;
204 
205     /**
206      * The reason speech recognition failed.
207      *
208      * @hide
209      */
210     @Documented
211     @Retention(RetentionPolicy.SOURCE)
212     @IntDef(prefix = {"ERROR_"}, value = {
213             ERROR_NETWORK_TIMEOUT,
214             ERROR_NETWORK,
215             ERROR_AUDIO,
216             ERROR_SERVER,
217             ERROR_CLIENT,
218             ERROR_SPEECH_TIMEOUT,
219             ERROR_NO_MATCH,
220             ERROR_RECOGNIZER_BUSY,
221             ERROR_INSUFFICIENT_PERMISSIONS,
222             ERROR_TOO_MANY_REQUESTS,
223             ERROR_SERVER_DISCONNECTED,
224             ERROR_LANGUAGE_NOT_SUPPORTED,
225             ERROR_LANGUAGE_UNAVAILABLE,
226             ERROR_CANNOT_CHECK_SUPPORT,
227             ERROR_CANNOT_LISTEN_TO_DOWNLOAD_EVENTS,
228     })
229     public @interface RecognitionError {}
230 
231     /** Network operation timed out. */
232     public static final int ERROR_NETWORK_TIMEOUT = 1;
233 
234     /** Other network related errors. */
235     public static final int ERROR_NETWORK = 2;
236 
237     /** Audio recording error. */
238     public static final int ERROR_AUDIO = 3;
239 
240     /** Server sends error status. */
241     public static final int ERROR_SERVER = 4;
242 
243     /** Other client side errors. */
244     public static final int ERROR_CLIENT = 5;
245 
246     /** No speech input */
247     public static final int ERROR_SPEECH_TIMEOUT = 6;
248 
249     /** No recognition result matched. */
250     public static final int ERROR_NO_MATCH = 7;
251 
252     /** RecognitionService busy. */
253     public static final int ERROR_RECOGNIZER_BUSY = 8;
254 
255     /** Insufficient permissions */
256     public static final int ERROR_INSUFFICIENT_PERMISSIONS = 9;
257 
258     /** Too many requests from the same client. */
259     public static final int ERROR_TOO_MANY_REQUESTS = 10;
260 
261     /** Server has been disconnected, e.g. because the app has crashed. */
262     public static final int ERROR_SERVER_DISCONNECTED = 11;
263 
264     /** Requested language is not available to be used with the current recognizer. */
265     public static final int ERROR_LANGUAGE_NOT_SUPPORTED = 12;
266 
267     /** Requested language is supported, but not available currently (e.g. not downloaded yet). */
268     public static final int ERROR_LANGUAGE_UNAVAILABLE = 13;
269 
270     /** The service does not allow to check for support. */
271     public static final int ERROR_CANNOT_CHECK_SUPPORT = 14;
272 
273     /** The service does not support listening to model downloads events. */
274     public static final int ERROR_CANNOT_LISTEN_TO_DOWNLOAD_EVENTS = 15;
275 
276     /** action codes */
277     private static final int MSG_START = 1;
278     private static final int MSG_STOP = 2;
279     private static final int MSG_CANCEL = 3;
280     private static final int MSG_CHANGE_LISTENER = 4;
281     private static final int MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT = 5;
282     private static final int MSG_CHECK_RECOGNITION_SUPPORT = 6;
283     private static final int MSG_TRIGGER_MODEL_DOWNLOAD = 7;
284 
SpeechRecognizer()285     SpeechRecognizer() { }
286 
287     /**
288      * Checks whether a speech recognition service is available on the system. If this method
289      * returns {@code false}, {@link SpeechRecognizer#createSpeechRecognizer(Context)} will
290      * fail.
291      *
292      * @param context with which {@code SpeechRecognizer} will be created
293      * @return {@code true} if recognition is available, {@code false} otherwise
294      */
isRecognitionAvailable(@onNull Context context)295     public static boolean isRecognitionAvailable(@NonNull Context context) {
296         // TODO(b/176578753): make sure this works well with system speech recognizers.
297         final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
298                 new Intent(RecognitionService.SERVICE_INTERFACE), 0);
299         return list != null && list.size() != 0;
300     }
301 
302     /**
303      * Checks whether an on-device speech recognition service is available on the system. If this
304      * method returns {@code false},
305      * {@link SpeechRecognizer#createOnDeviceSpeechRecognizer(Context)} will
306      * fail.
307      *
308      * @param context with which on-device {@code SpeechRecognizer} will be created
309      * @return {@code true} if on-device recognition is available, {@code false} otherwise
310      */
isOnDeviceRecognitionAvailable(@onNull Context context)311     public static boolean isOnDeviceRecognitionAvailable(@NonNull Context context) {
312         ComponentName componentName =
313                 ComponentName.unflattenFromString(
314                         context.getString(R.string.config_defaultOnDeviceSpeechRecognitionService));
315         return componentName != null;
316     }
317 
318     /**
319      * Factory method to create a new {@code SpeechRecognizer}. Please note that
320      * {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any
321      * command to the created {@code SpeechRecognizer}, otherwise no notifications will be
322      * received.
323      *
324      * <p><strong>Important:</strong> the caller MUST invoke {@link #destroy()} on a
325      * SpeechRecognizer object when it is no longer needed.
326      *
327      * <p>For apps targeting Android 11 (API level 30) interaction with a speech recognition
328      * service requires <queries> element to be added to the manifest file:
329      * <pre>{@code
330      * <queries>
331      *   <intent>
332      *     <action
333      *        android:name="android.speech.RecognitionService" />
334      *   </intent>
335      * </queries>
336      * }</pre>
337      *
338      * @param context in which to create {@code SpeechRecognizer}
339      * @return a new {@code SpeechRecognizer}
340      */
341     @MainThread
createSpeechRecognizer(Context context)342     public static SpeechRecognizer createSpeechRecognizer(Context context) {
343         return createSpeechRecognizer(context, null);
344     }
345 
346     /**
347      * Factory method to create a new {@code SpeechRecognizer}. Please note that
348      * {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any
349      * command to the created {@code SpeechRecognizer}, otherwise no notifications will be
350      * received.
351      * Use this version of the method to specify a specific service to direct this
352      * {@link SpeechRecognizer} to.
353      *
354      * <p><strong>Important:</strong> the caller MUST invoke {@link #destroy()} on a
355      * SpeechRecognizer object when it is no longer needed.
356      *
357      * <p><strong>Important</strong>: before calling this method, please check via
358      * {@link android.content.pm.PackageManager#queryIntentServices(Intent, int)} that {@code
359      * serviceComponent} actually exists and provides
360      * {@link RecognitionService#SERVICE_INTERFACE}. Normally you would not use this; call
361      * {@link #createSpeechRecognizer(Context)} to use the system default recognition
362      * service instead or {@link #createOnDeviceSpeechRecognizer(Context)} to use on-device
363      * recognition.</p>
364      *
365      * <p>For apps targeting Android 11 (API level 30) interaction with a speech recognition
366      * service requires <queries> element to be added to the manifest file:
367      * <pre>{@code
368      * <queries>
369      *   <intent>
370      *     <action
371      *        android:name="android.speech.RecognitionService" />
372      *   </intent>
373      * </queries>
374      * }</pre>
375      *
376      * @param context          in which to create {@code SpeechRecognizer}
377      * @param serviceComponent the {@link ComponentName} of a specific service to direct this
378      *                         {@code SpeechRecognizer} to
379      * @return a new {@code SpeechRecognizer}
380      */
381     @MainThread
createSpeechRecognizer(Context context, ComponentName serviceComponent)382     public static SpeechRecognizer createSpeechRecognizer(Context context,
383                                                    ComponentName serviceComponent) {
384         if (context == null) {
385             throw new IllegalArgumentException("Context cannot be null");
386         }
387         SpeechRecognizerImpl.checkIsCalledFromMainThread();
388         return wrapWithProxy(new SpeechRecognizerImpl(context, serviceComponent));
389     }
390 
391     /**
392      * Factory method to create a new {@code SpeechRecognizer}.
393      *
394      * <p>Please note that {@link #setRecognitionListener(RecognitionListener)} should be called
395      * before dispatching any command to the created {@code SpeechRecognizer}, otherwise no
396      * notifications will be received.
397      *
398      * <p><strong>Important:</strong> the caller MUST invoke {@link #destroy()} on a
399      * SpeechRecognizer object when it is no longer needed.
400      *
401      * @param context in which to create {@code SpeechRecognizer}
402      * @return a new on-device {@code SpeechRecognizer}.
403      * @throws UnsupportedOperationException iff {@link #isOnDeviceRecognitionAvailable(Context)}
404      *                                       is false
405      */
406     @NonNull
407     @MainThread
createOnDeviceSpeechRecognizer(@onNull Context context)408     public static SpeechRecognizer createOnDeviceSpeechRecognizer(@NonNull Context context) {
409         if (!isOnDeviceRecognitionAvailable(context)) {
410             throw new UnsupportedOperationException("On-device recognition is not available");
411         }
412         return wrapWithProxy(SpeechRecognizerImpl.lenientlyCreateOnDeviceSpeechRecognizer(context));
413     }
414 
wrapWithProxy(SpeechRecognizer delegate)415     private static SpeechRecognizer wrapWithProxy(SpeechRecognizer delegate) {
416         return new SpeechRecognizerProxy(delegate);
417     }
418 
419     /**
420      * Helper method to create on-device SpeechRecognizer in tests even when the device does not
421      * support on-device speech recognition.
422      *
423      * @hide
424      */
425     @TestApi
426     @NonNull
427     @MainThread
createOnDeviceTestingSpeechRecognizer( @onNull Context context)428     public static SpeechRecognizer createOnDeviceTestingSpeechRecognizer(
429             @NonNull Context context) {
430         return wrapWithProxy(SpeechRecognizerImpl.lenientlyCreateOnDeviceSpeechRecognizer(context));
431     }
432 
433     /**
434      * Sets the listener that will receive all the callbacks. The previous unfinished commands will
435      * be executed with the old listener, while any following command will be executed with the new
436      * listener.
437      *
438      * @param listener listener that will receive all the callbacks from the created
439      *                 {@link SpeechRecognizer}, this must not be null.
440      */
441     @MainThread
setRecognitionListener(RecognitionListener listener)442     public void setRecognitionListener(RecognitionListener listener) {
443         throw new UnsupportedOperationException();
444     }
445 
446     /**
447      * Starts listening for speech. Please note that
448      * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise
449      * no notifications will be received.
450      *
451      * @param recognizerIntent contains parameters for the recognition to be performed. The intent
452      *                         may also contain optional extras, see {@link RecognizerIntent}. If
453      *                         these values are not set explicitly, default values will be used by
454      *                         the recognizer.
455      */
456     @MainThread
startListening(Intent recognizerIntent)457     public void startListening(Intent recognizerIntent) {
458         throw new UnsupportedOperationException();
459     }
460 
461     /**
462      * Stops listening for speech. Speech captured so far will be recognized as if the user had
463      * stopped speaking at this point.
464      *
465      * <p>Note that in the default case, this does not need to be called, as the speech endpointer
466      * will automatically stop the recognizer listening when it determines speech has completed.
467      * However, you can manipulate endpointer parameters directly using the intent extras defined in
468      * {@link RecognizerIntent}, in which case you may sometimes want to manually call this method
469      * to stop listening sooner.
470      *
471      * <p>Upon invocation clients must wait until {@link RecognitionListener#onResults} or
472      * {@link RecognitionListener#onError} are invoked before calling
473      * {@link SpeechRecognizer#startListening} again. Otherwise such an attempt would be rejected by
474      * recognition service.
475      *
476      * <p>Please note that
477      * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise
478      * no notifications will be received.
479      */
480     @MainThread
stopListening()481     public void stopListening() {
482         throw new UnsupportedOperationException();
483     }
484 
485     /**
486      * Cancels the speech recognition. Please note that
487      * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise
488      * no notifications will be received.
489      */
490     @MainThread
cancel()491     public void cancel() {
492         throw new UnsupportedOperationException();
493     }
494 
495     /**
496      * Checks whether {@code recognizerIntent} is supported by
497      * {@link SpeechRecognizer#startListening(Intent)}.
498      *
499      * @param recognizerIntent contains parameters for the recognition to be performed. The intent
500      *                         may also contain optional extras. See {@link RecognizerIntent} for
501      *                         the list of supported extras, any unlisted extra might be ignored.
502      * @param supportListener  the listener on which to receive the support query results.
503      */
checkRecognitionSupport( @onNull Intent recognizerIntent, @NonNull @CallbackExecutor Executor executor, @NonNull RecognitionSupportCallback supportListener)504     public void checkRecognitionSupport(
505             @NonNull Intent recognizerIntent,
506             @NonNull @CallbackExecutor Executor executor,
507             @NonNull RecognitionSupportCallback supportListener) {
508         throw new UnsupportedOperationException();
509     }
510 
511     /**
512      * Attempts to download the support for the given {@code recognizerIntent}. This might trigger
513      * user interaction to approve the download. Callers can verify the status of the request via
514      * {@link #checkRecognitionSupport(Intent, Executor, RecognitionSupportCallback)}.
515      *
516      * @param recognizerIntent contains parameters for the recognition to be performed. The intent
517      *                         may also contain optional extras, see {@link RecognizerIntent}.
518      */
triggerModelDownload(@onNull Intent recognizerIntent)519     public void triggerModelDownload(@NonNull Intent recognizerIntent) {
520         throw new UnsupportedOperationException();
521     }
522 
523     /**
524      * Attempts to download the support for the given {@code recognizerIntent}. This might trigger
525      * user interaction to approve the download. Callers can verify the status of the request via
526      * {@link #checkRecognitionSupport(Intent, Executor, RecognitionSupportCallback)}.
527      *
528      * <p> The updates about the model download request are received via the given
529      * {@link ModelDownloadListener}:
530      *
531      * <li> If the model is already available, {@link ModelDownloadListener#onSuccess()} will be
532      * called directly. The model can be safely used afterwards.
533      *
534      * <li> If the {@link RecognitionService} has started the download,
535      * {@link ModelDownloadListener#onProgress(int)} will be called an unspecified (zero or more)
536      * number of times until the download is complete.
537      * When the download finishes, {@link ModelDownloadListener#onSuccess()} will be called.
538      * The model can be safely used afterwards.
539      *
540      * <li> If the {@link RecognitionService} has only scheduled the download, but won't satisfy it
541      * immediately, {@link ModelDownloadListener#onScheduled()} will be called.
542      * There will be no further updates on this listener.
543      *
544      * <li> If the request fails at any time due to a network or scheduling error,
545      * {@link ModelDownloadListener#onError(int)} will be called.
546      *
547      * @param recognizerIntent contains parameters for the recognition to be performed. The intent
548      *                         may also contain optional extras, see {@link RecognizerIntent}.
549      * @param executor         for dispatching listener callbacks
550      * @param listener         on which to receive updates about the model download request.
551      */
triggerModelDownload( @onNull Intent recognizerIntent, @NonNull @CallbackExecutor Executor executor, @NonNull ModelDownloadListener listener)552     public void triggerModelDownload(
553             @NonNull Intent recognizerIntent,
554             @NonNull @CallbackExecutor Executor executor,
555             @NonNull ModelDownloadListener listener) {
556         throw new UnsupportedOperationException();
557     }
558 
559     /**
560      * Sets a temporary component to power on-device speech recognizer.
561      *
562      * <p>This is only expected to be called in tests, system would reject calls from client apps.
563      *
564      * @param componentName name of the component to set temporary replace speech recognizer. {@code
565      *                      null} value resets the recognizer to default.
566      * @hide
567      */
568     @TestApi
569     @RequiresPermission(Manifest.permission.MANAGE_SPEECH_RECOGNITION)
setTemporaryOnDeviceRecognizer(@ullable ComponentName componentName)570     public void setTemporaryOnDeviceRecognizer(@Nullable ComponentName componentName) {
571         throw new UnsupportedOperationException();
572     }
573 
574     /**
575      * Destroys the {@code SpeechRecognizer} object.
576      */
destroy()577     public void destroy() {
578         throw new UnsupportedOperationException();
579     }
580 }
581