1 /** 2 * Copyright (C) 2021 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 package com.android.car.voicecontrol; 17 18 import android.content.Intent; 19 import android.os.Bundle; 20 import android.os.Handler; 21 import android.os.RemoteException; 22 import android.speech.SpeechRecognizer; 23 import android.util.Log; 24 25 import androidx.annotation.Nullable; 26 27 import java.util.ArrayList; 28 import java.util.Collections; 29 30 /** 31 * Sample {@link android.speech.RecognitionService}. A real implementation would obtain access to 32 * the microphone and stream audio to either a backend service or an offline on-device voice 33 * recognition model. This sample code just pretends to have detected a set of pre-recorded phrases. 34 */ 35 public class RecognitionService extends android.speech.RecognitionService { 36 private static final String TAG = "Mica.RecognitionService"; 37 private Callback mCurrentListener; 38 private Handler mHandler = new Handler(); 39 private Runnable mExecutionTask = this::onExecutionComplete; 40 private String[] mPrerecordedPhrases; 41 private int mPrerecordedPhraseIndex; 42 43 @Override onCreate()44 public void onCreate() { 45 super.onCreate(); 46 mPrerecordedPhrases = getResources().getStringArray(R.array.recognizer_phrases); 47 mPrerecordedPhraseIndex = 0; 48 } 49 50 @Override onStartListening(Intent recognizerIntent, Callback listener)51 protected void onStartListening(Intent recognizerIntent, Callback listener) { 52 Log.d(TAG, "onStartListening(recognizerIntent: " + recognizerIntent 53 + ", listener: " + listener); 54 if (mCurrentListener != null) { 55 mHandler.removeCallbacks(mExecutionTask); 56 sendEndOfSpeech(); 57 sendResults(null); 58 } 59 mCurrentListener = listener; 60 sendBeginningOfSpeech(); 61 mHandler.postDelayed(mExecutionTask, 1000); 62 } 63 64 @Override onCancel(Callback listener)65 protected void onCancel(Callback listener) { 66 Log.d(TAG, "onCancel(listener: " + listener); 67 if (mCurrentListener == null || listener != mCurrentListener) { 68 return; 69 } 70 mHandler.removeCallbacks(mExecutionTask); 71 mCurrentListener = null; 72 } 73 74 @Override onStopListening(Callback listener)75 protected void onStopListening(Callback listener) { 76 Log.d(TAG, "onStopListening(listener: " + listener); 77 if (mCurrentListener == null || listener != mCurrentListener) { 78 return; 79 } 80 mHandler.removeCallbacks(mExecutionTask); 81 sendEndOfSpeech(); 82 sendResults(null); 83 mCurrentListener = null; 84 } 85 onExecutionComplete()86 private void onExecutionComplete() { 87 if (mCurrentListener != null) { 88 sendEndOfSpeech(); 89 sendResults(getNextResult()); 90 } 91 } 92 sendBeginningOfSpeech()93 private void sendBeginningOfSpeech() { 94 try { 95 mCurrentListener.beginningOfSpeech(); 96 Log.d(TAG, "Sent beginningOfSpeech"); 97 } catch (RemoteException e) { 98 Log.e(TAG, "Error initiating speech", e.getCause()); 99 } 100 } 101 sendEndOfSpeech()102 private void sendEndOfSpeech() { 103 try { 104 mCurrentListener.endOfSpeech(); 105 Log.d(TAG, "Sent endOfSpeech"); 106 } catch (RemoteException e) { 107 Log.e(TAG, "Error cancelling speech", e.getCause()); 108 } 109 } 110 getNextResult()111 private String getNextResult() { 112 String currentString = mPrerecordedPhrases[mPrerecordedPhraseIndex++]; 113 mPrerecordedPhraseIndex %= mPrerecordedPhrases.length; 114 return currentString; 115 } 116 sendResults(@ullable String result)117 private void sendResults(@Nullable String result) { 118 try { 119 mCurrentListener.endOfSpeech(); 120 Bundle results = new Bundle(); 121 results.putStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION, result != null 122 ? new ArrayList<>(Collections.singletonList(result)) 123 : new ArrayList<>()); 124 results.putFloatArray(SpeechRecognizer.CONFIDENCE_SCORES, result != null 125 ? new float[]{1.0f} 126 : new float[0]); 127 mCurrentListener.results(results); 128 Log.d(TAG, "Sent results: " + results); 129 } catch (RemoteException e) { 130 Log.e(TAG, "Error sending results", e.getCause()); 131 } 132 } 133 } 134