| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
| 6 | 6 |
| 7 import android.content.ComponentName; | 7 import android.content.ComponentName; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.Intent; | 9 import android.content.Intent; |
| 10 import android.content.pm.PackageManager; | 10 import android.content.pm.PackageManager; |
| 11 import android.content.pm.PackageManager.NameNotFoundException; | 11 import android.content.pm.PackageManager.NameNotFoundException; |
| 12 import android.content.pm.ResolveInfo; | 12 import android.content.pm.ResolveInfo; |
| 13 import android.content.pm.ServiceInfo; | 13 import android.content.pm.ServiceInfo; |
| 14 import android.os.Bundle; | 14 import android.os.Bundle; |
| 15 import android.speech.RecognitionListener; | 15 import android.speech.RecognitionListener; |
| 16 import android.speech.RecognitionService; | 16 import android.speech.RecognitionService; |
| 17 import android.speech.RecognizerIntent; | 17 import android.speech.RecognizerIntent; |
| 18 import android.speech.SpeechRecognizer; | 18 import android.speech.SpeechRecognizer; |
| 19 | 19 |
| 20 import org.chromium.base.CalledByNative; | 20 import org.chromium.base.CalledByNative; |
| 21 import org.chromium.base.JNINamespace; | 21 import org.chromium.base.JNINamespace; |
| 22 import org.chromium.content_public.common.SpeechRecognitionErrorCode; | |
| 23 | 22 |
| 24 import java.util.ArrayList; | 23 import java.util.ArrayList; |
| 25 import java.util.List; | 24 import java.util.List; |
| 26 | 25 |
| 27 /** | 26 /** |
| 28 * This class uses Android's SpeechRecognizer to perform speech recognition for
the Web Speech API | 27 * This class uses Android's SpeechRecognizer to perform speech recognition for
the Web Speech API |
| 29 * on Android. Using Android's platform recognizer offers several benefits, like
good quality and | 28 * on Android. Using Android's platform recognizer offers several benefits, like
good quality and |
| 30 * good local fallback when no data connection is available. | 29 * good local fallback when no data connection is available. |
| 31 */ | 30 */ |
| 32 @JNINamespace("content") | 31 @JNINamespace("content") |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 nativeOnSoundEnd(mNativeSpeechRecognizerImplAndroid); | 82 nativeOnSoundEnd(mNativeSpeechRecognizerImplAndroid); |
| 84 // Since Android doesn't have a dedicated event for when audio c
apture is finished, | 83 // Since Android doesn't have a dedicated event for when audio c
apture is finished, |
| 85 // we fire it after speech has ended. | 84 // we fire it after speech has ended. |
| 86 nativeOnAudioEnd(mNativeSpeechRecognizerImplAndroid); | 85 nativeOnAudioEnd(mNativeSpeechRecognizerImplAndroid); |
| 87 mState = STATE_IDLE; | 86 mState = STATE_IDLE; |
| 88 } | 87 } |
| 89 } | 88 } |
| 90 | 89 |
| 91 @Override | 90 @Override |
| 92 public void onError(int error) { | 91 public void onError(int error) { |
| 93 int code = SpeechRecognitionErrorCode.NONE; | 92 int code = SpeechRecognitionError.NONE; |
| 94 | 93 |
| 95 // Translate Android SpeechRecognizer errors to Web Speech API error
s. | 94 // Translate Android SpeechRecognizer errors to Web Speech API error
s. |
| 96 switch(error) { | 95 switch(error) { |
| 97 case SpeechRecognizer.ERROR_AUDIO: | 96 case SpeechRecognizer.ERROR_AUDIO: |
| 98 code = SpeechRecognitionErrorCode.AUDIO; | 97 code = SpeechRecognitionError.AUDIO; |
| 99 break; | 98 break; |
| 100 case SpeechRecognizer.ERROR_CLIENT: | 99 case SpeechRecognizer.ERROR_CLIENT: |
| 101 code = SpeechRecognitionErrorCode.ABORTED; | 100 code = SpeechRecognitionError.ABORTED; |
| 102 break; | 101 break; |
| 103 case SpeechRecognizer.ERROR_RECOGNIZER_BUSY: | 102 case SpeechRecognizer.ERROR_RECOGNIZER_BUSY: |
| 104 case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS: | 103 case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS: |
| 105 code = SpeechRecognitionErrorCode.NOT_ALLOWED; | 104 code = SpeechRecognitionError.NOT_ALLOWED; |
| 106 break; | 105 break; |
| 107 case SpeechRecognizer.ERROR_NETWORK_TIMEOUT: | 106 case SpeechRecognizer.ERROR_NETWORK_TIMEOUT: |
| 108 case SpeechRecognizer.ERROR_NETWORK: | 107 case SpeechRecognizer.ERROR_NETWORK: |
| 109 case SpeechRecognizer.ERROR_SERVER: | 108 case SpeechRecognizer.ERROR_SERVER: |
| 110 code = SpeechRecognitionErrorCode.NETWORK; | 109 code = SpeechRecognitionError.NETWORK; |
| 111 break; | 110 break; |
| 112 case SpeechRecognizer.ERROR_NO_MATCH: | 111 case SpeechRecognizer.ERROR_NO_MATCH: |
| 113 code = SpeechRecognitionErrorCode.NO_MATCH; | 112 code = SpeechRecognitionError.NO_MATCH; |
| 114 break; | 113 break; |
| 115 case SpeechRecognizer.ERROR_SPEECH_TIMEOUT: | 114 case SpeechRecognizer.ERROR_SPEECH_TIMEOUT: |
| 116 code = SpeechRecognitionErrorCode.NO_SPEECH; | 115 code = SpeechRecognitionError.NO_SPEECH; |
| 117 break; | 116 break; |
| 118 default: | 117 default: |
| 119 assert false; | 118 assert false; |
| 120 return; | 119 return; |
| 121 } | 120 } |
| 122 | 121 |
| 123 terminate(code); | 122 terminate(code); |
| 124 } | 123 } |
| 125 | 124 |
| 126 @Override | 125 @Override |
| 127 public void onEvent(int event, Bundle bundle) { } | 126 public void onEvent(int event, Bundle bundle) { } |
| 128 | 127 |
| 129 @Override | 128 @Override |
| 130 public void onPartialResults(Bundle bundle) { | 129 public void onPartialResults(Bundle bundle) { |
| 131 handleResults(bundle, true); | 130 handleResults(bundle, true); |
| 132 } | 131 } |
| 133 | 132 |
| 134 @Override | 133 @Override |
| 135 public void onReadyForSpeech(Bundle bundle) { | 134 public void onReadyForSpeech(Bundle bundle) { |
| 136 mState = STATE_AWAITING_SPEECH; | 135 mState = STATE_AWAITING_SPEECH; |
| 137 nativeOnAudioStart(mNativeSpeechRecognizerImplAndroid); | 136 nativeOnAudioStart(mNativeSpeechRecognizerImplAndroid); |
| 138 } | 137 } |
| 139 | 138 |
| 140 @Override | 139 @Override |
| 141 public void onResults(Bundle bundle) { | 140 public void onResults(Bundle bundle) { |
| 142 handleResults(bundle, false); | 141 handleResults(bundle, false); |
| 143 // We assume that onResults is called only once, at the end of a ses
sion, thus we | 142 // We assume that onResults is called only once, at the end of a ses
sion, thus we |
| 144 // terminate. If one day the recognition provider changes dictation
mode behavior to | 143 // terminate. If one day the recognition provider changes dictation
mode behavior to |
| 145 // call onResults several times, we should terminate only if (!mCont
inuous). | 144 // call onResults several times, we should terminate only if (!mCont
inuous). |
| 146 terminate(SpeechRecognitionErrorCode.NONE); | 145 terminate(SpeechRecognitionError.NONE); |
| 147 } | 146 } |
| 148 | 147 |
| 149 @Override | 148 @Override |
| 150 public void onRmsChanged(float rms) { } | 149 public void onRmsChanged(float rms) { } |
| 151 | 150 |
| 152 private void handleResults(Bundle bundle, boolean provisional) { | 151 private void handleResults(Bundle bundle, boolean provisional) { |
| 153 if (mContinuous && provisional) { | 152 if (mContinuous && provisional) { |
| 154 // In continuous mode, Android's recognizer sends final results
as provisional. | 153 // In continuous mode, Android's recognizer sends final results
as provisional. |
| 155 provisional = false; | 154 provisional = false; |
| 156 } | 155 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 private void terminate(int error) { | 230 private void terminate(int error) { |
| 232 | 231 |
| 233 if (mState != STATE_IDLE) { | 232 if (mState != STATE_IDLE) { |
| 234 if (mState == STATE_CAPTURING_SPEECH) { | 233 if (mState == STATE_CAPTURING_SPEECH) { |
| 235 nativeOnSoundEnd(mNativeSpeechRecognizerImplAndroid); | 234 nativeOnSoundEnd(mNativeSpeechRecognizerImplAndroid); |
| 236 } | 235 } |
| 237 nativeOnAudioEnd(mNativeSpeechRecognizerImplAndroid); | 236 nativeOnAudioEnd(mNativeSpeechRecognizerImplAndroid); |
| 238 mState = STATE_IDLE; | 237 mState = STATE_IDLE; |
| 239 } | 238 } |
| 240 | 239 |
| 241 if (error != SpeechRecognitionErrorCode.NONE) | 240 if (error != SpeechRecognitionError.NONE) |
| 242 nativeOnRecognitionError(mNativeSpeechRecognizerImplAndroid, error); | 241 nativeOnRecognitionError(mNativeSpeechRecognizerImplAndroid, error); |
| 243 | 242 |
| 244 mRecognizer.destroy(); | 243 mRecognizer.destroy(); |
| 245 mRecognizer = null; | 244 mRecognizer = null; |
| 246 nativeOnRecognitionEnd(mNativeSpeechRecognizerImplAndroid); | 245 nativeOnRecognitionEnd(mNativeSpeechRecognizerImplAndroid); |
| 247 mNativeSpeechRecognizerImplAndroid = 0; | 246 mNativeSpeechRecognizerImplAndroid = 0; |
| 248 } | 247 } |
| 249 | 248 |
| 250 @CalledByNative | 249 @CalledByNative |
| 251 private static SpeechRecognition createSpeechRecognition( | 250 private static SpeechRecognition createSpeechRecognition( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 264 mIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, interimResults)
; | 263 mIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, interimResults)
; |
| 265 mRecognizer.startListening(mIntent); | 264 mRecognizer.startListening(mIntent); |
| 266 } | 265 } |
| 267 | 266 |
| 268 @CalledByNative | 267 @CalledByNative |
| 269 private void abortRecognition() { | 268 private void abortRecognition() { |
| 270 if (mRecognizer == null) | 269 if (mRecognizer == null) |
| 271 return; | 270 return; |
| 272 | 271 |
| 273 mRecognizer.cancel(); | 272 mRecognizer.cancel(); |
| 274 terminate(SpeechRecognitionErrorCode.ABORTED); | 273 terminate(SpeechRecognitionError.ABORTED); |
| 275 } | 274 } |
| 276 | 275 |
| 277 @CalledByNative | 276 @CalledByNative |
| 278 private void stopRecognition() { | 277 private void stopRecognition() { |
| 279 if (mRecognizer == null) | 278 if (mRecognizer == null) |
| 280 return; | 279 return; |
| 281 | 280 |
| 282 mContinuous = false; | 281 mContinuous = false; |
| 283 mRecognizer.stopListening(); | 282 mRecognizer.stopListening(); |
| 284 } | 283 } |
| 285 | 284 |
| 286 // Native JNI calls to content/browser/speech/speech_recognizer_impl_android
.cc | 285 // Native JNI calls to content/browser/speech/speech_recognizer_impl_android
.cc |
| 287 private native void nativeOnAudioStart(long nativeSpeechRecognizerImplAndroi
d); | 286 private native void nativeOnAudioStart(long nativeSpeechRecognizerImplAndroi
d); |
| 288 private native void nativeOnSoundStart(long nativeSpeechRecognizerImplAndroi
d); | 287 private native void nativeOnSoundStart(long nativeSpeechRecognizerImplAndroi
d); |
| 289 private native void nativeOnSoundEnd(long nativeSpeechRecognizerImplAndroid)
; | 288 private native void nativeOnSoundEnd(long nativeSpeechRecognizerImplAndroid)
; |
| 290 private native void nativeOnAudioEnd(long nativeSpeechRecognizerImplAndroid)
; | 289 private native void nativeOnAudioEnd(long nativeSpeechRecognizerImplAndroid)
; |
| 291 private native void nativeOnRecognitionResults(long nativeSpeechRecognizerIm
plAndroid, | 290 private native void nativeOnRecognitionResults(long nativeSpeechRecognizerIm
plAndroid, |
| 292 String[] results, | 291 String[] results, |
| 293 float[] scores, | 292 float[] scores, |
| 294 boolean provisional); | 293 boolean provisional); |
| 295 private native void nativeOnRecognitionError(long nativeSpeechRecognizerImpl
Android, int error); | 294 private native void nativeOnRecognitionError(long nativeSpeechRecognizerImpl
Android, int error); |
| 296 private native void nativeOnRecognitionEnd(long nativeSpeechRecognizerImplAn
droid); | 295 private native void nativeOnRecognitionEnd(long nativeSpeechRecognizerImplAn
droid); |
| 297 } | 296 } |
| OLD | NEW |