Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / speech / speech_recognizer_impl_android.cc
blob0a43def06b32aecc7619ded533db143bc3195ca8
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
3 // found in the LICENSE file.
5 #include "content/browser/speech/speech_recognizer_impl_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/bind.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/speech_recognition_event_listener.h"
15 #include "content/public/browser/speech_recognition_manager.h"
16 #include "content/public/browser/speech_recognition_session_config.h"
17 #include "content/public/common/speech_recognition_grammar.h"
18 #include "content/public/common/speech_recognition_result.h"
19 #include "jni/SpeechRecognition_jni.h"
21 using base::android::AppendJavaStringArrayToStringVector;
22 using base::android::AttachCurrentThread;
23 using base::android::ConvertUTF8ToJavaString;
24 using base::android::GetApplicationContext;
25 using base::android::JavaFloatArrayToFloatVector;
27 namespace content {
29 SpeechRecognizerImplAndroid::SpeechRecognizerImplAndroid(
30 SpeechRecognitionEventListener* listener,
31 int session_id)
32 : SpeechRecognizer(listener, session_id),
33 state_(STATE_IDLE) {
36 SpeechRecognizerImplAndroid::~SpeechRecognizerImplAndroid() { }
38 void SpeechRecognizerImplAndroid::StartRecognition(
39 const std::string& device_id) {
40 DCHECK_CURRENTLY_ON(BrowserThread::IO);
41 // TODO(xians): Open the correct device for speech on Android.
42 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
43 &SpeechRecognitionEventListener::OnRecognitionStart,
44 base::Unretained(listener()),
45 session_id()));
46 SpeechRecognitionSessionConfig config =
47 SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id());
48 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
49 &content::SpeechRecognizerImplAndroid::StartRecognitionOnUIThread, this,
50 config.language, config.continuous, config.interim_results));
53 void SpeechRecognizerImplAndroid::StartRecognitionOnUIThread(
54 std::string language, bool continuous, bool interim_results) {
55 DCHECK_CURRENTLY_ON(BrowserThread::UI);
56 JNIEnv* env = AttachCurrentThread();
57 j_recognition_.Reset(Java_SpeechRecognition_createSpeechRecognition(env,
58 GetApplicationContext(), reinterpret_cast<intptr_t>(this)));
59 Java_SpeechRecognition_startRecognition(env, j_recognition_.obj(),
60 ConvertUTF8ToJavaString(env, language).obj(), continuous,
61 interim_results);
64 void SpeechRecognizerImplAndroid::AbortRecognition() {
65 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
66 state_ = STATE_IDLE;
67 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
68 &content::SpeechRecognizerImplAndroid::AbortRecognition, this));
69 return;
71 DCHECK_CURRENTLY_ON(BrowserThread::UI);
72 JNIEnv* env = AttachCurrentThread();
73 if (!j_recognition_.is_null())
74 Java_SpeechRecognition_abortRecognition(env, j_recognition_.obj());
77 void SpeechRecognizerImplAndroid::StopAudioCapture() {
78 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
79 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
80 &content::SpeechRecognizerImplAndroid::StopAudioCapture, this));
81 return;
83 DCHECK_CURRENTLY_ON(BrowserThread::UI);
84 JNIEnv* env = AttachCurrentThread();
85 if (!j_recognition_.is_null())
86 Java_SpeechRecognition_stopRecognition(env, j_recognition_.obj());
89 bool SpeechRecognizerImplAndroid::IsActive() const {
90 DCHECK_CURRENTLY_ON(BrowserThread::IO);
91 return state_ != STATE_IDLE;
94 bool SpeechRecognizerImplAndroid::IsCapturingAudio() const {
95 DCHECK_CURRENTLY_ON(BrowserThread::IO);
96 return state_ == STATE_CAPTURING_AUDIO;
99 void SpeechRecognizerImplAndroid::OnAudioStart(JNIEnv* env, jobject obj) {
100 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
101 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
102 &SpeechRecognizerImplAndroid::OnAudioStart, this,
103 static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
104 return;
106 DCHECK_CURRENTLY_ON(BrowserThread::IO);
107 state_ = STATE_CAPTURING_AUDIO;
108 listener()->OnAudioStart(session_id());
111 void SpeechRecognizerImplAndroid::OnSoundStart(JNIEnv* env, jobject obj) {
112 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
113 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
114 &SpeechRecognizerImplAndroid::OnSoundStart, this,
115 static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
116 return;
118 DCHECK_CURRENTLY_ON(BrowserThread::IO);
119 listener()->OnSoundStart(session_id());
122 void SpeechRecognizerImplAndroid::OnSoundEnd(JNIEnv* env, jobject obj) {
123 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
124 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
125 &SpeechRecognizerImplAndroid::OnSoundEnd, this,
126 static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
127 return;
129 DCHECK_CURRENTLY_ON(BrowserThread::IO);
130 listener()->OnSoundEnd(session_id());
133 void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env, jobject obj) {
134 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
135 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
136 &SpeechRecognizerImplAndroid::OnAudioEnd, this,
137 static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
138 return;
140 DCHECK_CURRENTLY_ON(BrowserThread::IO);
141 if (state_ == STATE_CAPTURING_AUDIO)
142 state_ = STATE_AWAITING_FINAL_RESULT;
143 listener()->OnAudioEnd(session_id());
146 void SpeechRecognizerImplAndroid::OnRecognitionResults(JNIEnv* env, jobject obj,
147 jobjectArray strings, jfloatArray floats, jboolean provisional) {
148 DCHECK_CURRENTLY_ON(BrowserThread::UI);
149 std::vector<base::string16> options;
150 AppendJavaStringArrayToStringVector(env, strings, &options);
151 std::vector<float> scores(options.size(), 0.0);
152 if (floats != NULL)
153 JavaFloatArrayToFloatVector(env, floats, &scores);
154 SpeechRecognitionResults results;
155 results.push_back(SpeechRecognitionResult());
156 SpeechRecognitionResult& result = results.back();
157 CHECK_EQ(options.size(), scores.size());
158 for (size_t i = 0; i < options.size(); ++i) {
159 result.hypotheses.push_back(SpeechRecognitionHypothesis(
160 options[i], static_cast<double>(scores[i])));
162 result.is_provisional = provisional;
163 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
164 &SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread,
165 this, results));
168 void SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread(
169 SpeechRecognitionResults const &results) {
170 DCHECK_CURRENTLY_ON(BrowserThread::IO);
171 listener()->OnRecognitionResults(session_id(), results);
174 void SpeechRecognizerImplAndroid::OnRecognitionError(JNIEnv* env,
175 jobject obj, jint error) {
176 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
177 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
178 &SpeechRecognizerImplAndroid::OnRecognitionError, this,
179 static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL), error));
180 return;
182 DCHECK_CURRENTLY_ON(BrowserThread::IO);
183 SpeechRecognitionErrorCode code =
184 static_cast<SpeechRecognitionErrorCode>(error);
185 listener()->OnRecognitionError(session_id(), SpeechRecognitionError(code));
188 void SpeechRecognizerImplAndroid::OnRecognitionEnd(JNIEnv* env,
189 jobject obj) {
190 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
191 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
192 &SpeechRecognizerImplAndroid::OnRecognitionEnd, this,
193 static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
194 return;
196 DCHECK_CURRENTLY_ON(BrowserThread::IO);
197 state_ = STATE_IDLE;
198 listener()->OnRecognitionEnd(session_id());
201 // static
202 bool SpeechRecognizerImplAndroid::RegisterSpeechRecognizer(JNIEnv* env) {
203 return RegisterNativesImpl(env);
206 } // namespace content