blob: b22ad902bb62497662f5b87604fa38199b76098e [file] [log] [blame]
Andrew Moylanff6be512018-07-03 11:05:01 +10001// Copyright 2018 The Chromium OS 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.
4
5#include "ml/machine_learning_service_impl.h"
6
Michael Martisa74af932018-08-13 16:52:36 +10007#include <memory>
Andrew Moylanff6be512018-07-03 11:05:01 +10008#include <utility>
9
Michael Martisa74af932018-08-13 16:52:36 +100010#include <base/bind.h>
11#include <base/bind_helpers.h>
Honglin Yuf33dce32019-12-05 15:10:39 +110012#include <base/files/file.h>
13#include <base/files/file_util.h>
Honglin Yu20391cd2020-10-27 15:58:49 +110014#include <base/files/memory_mapped_file.h>
Michael Martis8783c8e2019-06-26 17:30:54 +100015#include <tensorflow/lite/model.h>
Honglin Yuf33dce32019-12-05 15:10:39 +110016#include <unicode/putil.h>
17#include <unicode/udata.h>
18#include <utils/memory/mmap.h>
Michael Martisa74af932018-08-13 16:52:36 +100019
Jing Wang961b8af2020-10-26 12:40:35 +110020#include "ml/grammar_checker_impl.h"
21#include "ml/grammar_library.h"
charleszhao17777f92020-04-23 12:53:11 +100022#include "ml/handwriting.h"
23#include "ml/handwriting_recognizer_impl.h"
Michael Martisa74af932018-08-13 16:52:36 +100024#include "ml/model_impl.h"
charleszhao17777f92020-04-23 12:53:11 +100025#include "ml/mojom/handwriting_recognizer.mojom.h"
Hidehiko Abeaa488c32018-08-31 23:49:41 +090026#include "ml/mojom/model.mojom.h"
Honglin Yud2204272020-08-26 14:21:37 +100027#include "ml/mojom/soda.mojom.h"
Andrew Moylan44c352f2020-11-04 15:19:46 +110028#include "ml/request_metrics.h"
Honglin Yud2204272020-08-26 14:21:37 +100029#include "ml/soda_recognizer_impl.h"
Honglin Yuf33dce32019-12-05 15:10:39 +110030#include "ml/text_classifier_impl.h"
Michael Martisa74af932018-08-13 16:52:36 +100031
Andrew Moylanff6be512018-07-03 11:05:01 +100032namespace ml {
33
Michael Martisa74af932018-08-13 16:52:36 +100034namespace {
35
Honglin Yu0ed72352019-08-27 17:42:01 +100036using ::chromeos::machine_learning::mojom::BuiltinModelId;
37using ::chromeos::machine_learning::mojom::BuiltinModelSpecPtr;
38using ::chromeos::machine_learning::mojom::FlatBufferModelSpecPtr;
Andrew Moylanb481af72020-07-09 15:22:00 +100039using ::chromeos::machine_learning::mojom::HandwritingRecognizer;
charleszhao05c5a4a2020-06-09 16:49:54 +100040using ::chromeos::machine_learning::mojom::HandwritingRecognizerSpec;
41using ::chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr;
Charles Zhao6d467e62020-08-31 10:02:03 +100042using ::chromeos::machine_learning::mojom::LoadHandwritingModelResult;
Michael Martisa74af932018-08-13 16:52:36 +100043using ::chromeos::machine_learning::mojom::LoadModelResult;
Andrew Moylanb481af72020-07-09 15:22:00 +100044using ::chromeos::machine_learning::mojom::MachineLearningService;
45using ::chromeos::machine_learning::mojom::Model;
Honglin Yud2204272020-08-26 14:21:37 +100046using ::chromeos::machine_learning::mojom::SodaClient;
47using ::chromeos::machine_learning::mojom::SodaConfigPtr;
48using ::chromeos::machine_learning::mojom::SodaRecognizer;
Andrew Moylanb481af72020-07-09 15:22:00 +100049using ::chromeos::machine_learning::mojom::TextClassifier;
Michael Martisa74af932018-08-13 16:52:36 +100050
51constexpr char kSystemModelDir[] = "/opt/google/chrome/ml_models/";
Andrew Moylan79b34a42020-07-08 11:13:11 +100052// Base name for UMA metrics related to model loading (`LoadBuiltinModel`,
53// `LoadFlatBufferModel`, `LoadTextClassifier` or LoadHandwritingModel).
Honglin Yu6adafcd2019-07-22 13:48:11 +100054constexpr char kMetricsRequestName[] = "LoadModelResult";
Michael Martisa74af932018-08-13 16:52:36 +100055
Honglin Yuf33dce32019-12-05 15:10:39 +110056constexpr char kIcuDataFilePath[] = "/opt/google/chrome/icudtl.dat";
57
Honglin Yu20391cd2020-10-27 15:58:49 +110058// Used to hold the mmap object of the icu data file. Each process should only
59// have one instance of it. Intentionally never close it.
60// We can not make it as a member of `MachineLearningServiceImpl` because it
61// will crash the unit test (because in that case, when the
62// `MachineLearningServiceImpl` object is destructed, the file will be
63// unmapped but the icu data can not be reset in the testing process).
64base::MemoryMappedFile* g_icu_data_mmap_file = nullptr;
65
66void InitIcuIfNeeded() {
67 if (!g_icu_data_mmap_file) {
68 g_icu_data_mmap_file = new base::MemoryMappedFile();
69 CHECK(g_icu_data_mmap_file->Initialize(
70 base::FilePath(kIcuDataFilePath),
71 base::MemoryMappedFile::Access::READ_ONLY));
72 // Init the Icu library.
73 UErrorCode err = U_ZERO_ERROR;
74 udata_setCommonData(const_cast<uint8_t*>(g_icu_data_mmap_file->data()),
75 &err);
76 DCHECK(err == U_ZERO_ERROR);
77 // Never try to load Icu data from files.
78 udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
79 DCHECK(err == U_ZERO_ERROR);
80 }
81}
82
Michael Martisa74af932018-08-13 16:52:36 +100083} // namespace
84
Andrew Moylanff6be512018-07-03 11:05:01 +100085MachineLearningServiceImpl::MachineLearningServiceImpl(
Michael Martisa74af932018-08-13 16:52:36 +100086 mojo::ScopedMessagePipeHandle pipe,
Andrew Moylanb481af72020-07-09 15:22:00 +100087 base::Closure disconnect_handler,
Michael Martisa74af932018-08-13 16:52:36 +100088 const std::string& model_dir)
Honglin Yu20391cd2020-10-27 15:58:49 +110089 : builtin_model_metadata_(GetBuiltinModelMetadata()),
Michael Martisa74af932018-08-13 16:52:36 +100090 model_dir_(model_dir),
Andrew Moylanb481af72020-07-09 15:22:00 +100091 receiver_(this,
92 mojo::InterfaceRequest<
93 chromeos::machine_learning::mojom::MachineLearningService>(
94 std::move(pipe))) {
95 receiver_.set_disconnect_handler(std::move(disconnect_handler));
Andrew Moylanff6be512018-07-03 11:05:01 +100096}
97
Michael Martisa74af932018-08-13 16:52:36 +100098MachineLearningServiceImpl::MachineLearningServiceImpl(
Charles Zhaod4fb7b62020-08-25 17:21:58 +100099 mojo::ScopedMessagePipeHandle pipe,
100 base::Closure disconnect_handler,
101 dbus::Bus* bus)
Andrew Moylanb481af72020-07-09 15:22:00 +1000102 : MachineLearningServiceImpl(
Charles Zhaod4fb7b62020-08-25 17:21:58 +1000103 std::move(pipe), std::move(disconnect_handler), kSystemModelDir) {
104 if (bus) {
105 dlcservice_client_ = std::make_unique<DlcserviceClient>(bus);
106 }
107}
Michael Martisa74af932018-08-13 16:52:36 +1000108
Andrew Moylanb481af72020-07-09 15:22:00 +1000109void MachineLearningServiceImpl::Clone(
110 mojo::PendingReceiver<MachineLearningService> receiver) {
111 clone_receivers_.Add(this, std::move(receiver));
Andrew Moylan2fb80af2020-07-08 10:52:08 +1000112}
113
Honglin Yu0ed72352019-08-27 17:42:01 +1000114void MachineLearningServiceImpl::LoadBuiltinModel(
115 BuiltinModelSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000116 mojo::PendingReceiver<Model> receiver,
Qijiang Fan5d381a02020-04-19 23:42:37 +0900117 LoadBuiltinModelCallback callback) {
Honglin Yu0ed72352019-08-27 17:42:01 +1000118 // Unsupported models do not have metadata entries.
119 const auto metadata_lookup = builtin_model_metadata_.find(spec->id);
120 if (metadata_lookup == builtin_model_metadata_.end()) {
Honglin Yua81145a2019-09-23 15:20:13 +1000121 LOG(WARNING) << "LoadBuiltinModel requested for unsupported model ID "
122 << spec->id << ".";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900123 std::move(callback).Run(LoadModelResult::MODEL_SPEC_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000124 RecordModelSpecificationErrorEvent();
125 return;
126 }
127
128 const BuiltinModelMetadata& metadata = metadata_lookup->second;
129
130 DCHECK(!metadata.metrics_model_name.empty());
131
charleszhao5a7050e2020-07-14 15:21:41 +1000132 RequestMetrics request_metrics(metadata.metrics_model_name,
133 kMetricsRequestName);
Honglin Yu0ed72352019-08-27 17:42:01 +1000134 request_metrics.StartRecordingPerformanceMetrics();
135
136 // Attempt to load model.
137 const std::string model_path = model_dir_ + metadata.model_file;
138 std::unique_ptr<tflite::FlatBufferModel> model =
139 tflite::FlatBufferModel::BuildFromFile(model_path.c_str());
140 if (model == nullptr) {
141 LOG(ERROR) << "Failed to load model file '" << model_path << "'.";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900142 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000143 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
144 return;
145 }
146
Honglin Yuc0cef102020-01-17 15:26:01 +1100147 ModelImpl::Create(metadata.required_inputs, metadata.required_outputs,
Andrew Moylanb481af72020-07-09 15:22:00 +1000148 std::move(model), std::move(receiver),
Honglin Yuc0cef102020-01-17 15:26:01 +1100149 metadata.metrics_model_name);
Honglin Yu0ed72352019-08-27 17:42:01 +1000150
Qijiang Fan5d381a02020-04-19 23:42:37 +0900151 std::move(callback).Run(LoadModelResult::OK);
Honglin Yu0ed72352019-08-27 17:42:01 +1000152
153 request_metrics.FinishRecordingPerformanceMetrics();
154 request_metrics.RecordRequestEvent(LoadModelResult::OK);
155}
156
157void MachineLearningServiceImpl::LoadFlatBufferModel(
158 FlatBufferModelSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000159 mojo::PendingReceiver<Model> receiver,
Qijiang Fan5d381a02020-04-19 23:42:37 +0900160 LoadFlatBufferModelCallback callback) {
Honglin Yu0ed72352019-08-27 17:42:01 +1000161 DCHECK(!spec->metrics_model_name.empty());
162
charleszhao5a7050e2020-07-14 15:21:41 +1000163 RequestMetrics request_metrics(spec->metrics_model_name, kMetricsRequestName);
Honglin Yu0ed72352019-08-27 17:42:01 +1000164 request_metrics.StartRecordingPerformanceMetrics();
165
Andrew Moylan79b34a42020-07-08 11:13:11 +1000166 // Take the ownership of the content of `model_string` because `ModelImpl` has
Honglin Yu0ed72352019-08-27 17:42:01 +1000167 // to hold the memory.
Andrew Moylan44c352f2020-11-04 15:19:46 +1100168 auto model_data =
169 std::make_unique<AlignedModelData>(std::move(spec->model_string));
Honglin Yu0ed72352019-08-27 17:42:01 +1000170
171 std::unique_ptr<tflite::FlatBufferModel> model =
Andrew Moylan44c352f2020-11-04 15:19:46 +1100172 tflite::FlatBufferModel::VerifyAndBuildFromBuffer(model_data->data(),
173 model_data->size());
Honglin Yu0ed72352019-08-27 17:42:01 +1000174 if (model == nullptr) {
175 LOG(ERROR) << "Failed to load model string of metric name: "
176 << spec->metrics_model_name << "'.";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900177 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000178 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
179 return;
180 }
181
Honglin Yuc0cef102020-01-17 15:26:01 +1100182 ModelImpl::Create(
Honglin Yu0ed72352019-08-27 17:42:01 +1000183 std::map<std::string, int>(spec->inputs.begin(), spec->inputs.end()),
184 std::map<std::string, int>(spec->outputs.begin(), spec->outputs.end()),
Andrew Moylan44c352f2020-11-04 15:19:46 +1100185 std::move(model), std::move(model_data), std::move(receiver),
Honglin Yu0ed72352019-08-27 17:42:01 +1000186 spec->metrics_model_name);
187
Qijiang Fan5d381a02020-04-19 23:42:37 +0900188 std::move(callback).Run(LoadModelResult::OK);
Honglin Yu0ed72352019-08-27 17:42:01 +1000189
190 request_metrics.FinishRecordingPerformanceMetrics();
191 request_metrics.RecordRequestEvent(LoadModelResult::OK);
192}
193
Honglin Yuf33dce32019-12-05 15:10:39 +1100194void MachineLearningServiceImpl::LoadTextClassifier(
Andrew Moylanb481af72020-07-09 15:22:00 +1000195 mojo::PendingReceiver<TextClassifier> receiver,
Honglin Yuf33dce32019-12-05 15:10:39 +1100196 LoadTextClassifierCallback callback) {
charleszhao5a7050e2020-07-14 15:21:41 +1000197 RequestMetrics request_metrics("TextClassifier", kMetricsRequestName);
Honglin Yuf33dce32019-12-05 15:10:39 +1100198 request_metrics.StartRecordingPerformanceMetrics();
199
Honglin Yuf33dce32019-12-05 15:10:39 +1100200 // Create the TextClassifier.
Honglin Yu3f99ff12020-10-15 00:40:11 +1100201 if (!TextClassifierImpl::Create(std::move(receiver))) {
Honglin Yuf33dce32019-12-05 15:10:39 +1100202 LOG(ERROR) << "Failed to create TextClassifierImpl object.";
203 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
204 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
205 return;
206 }
207
208 // initialize the icu library.
209 InitIcuIfNeeded();
210
211 std::move(callback).Run(LoadModelResult::OK);
212
213 request_metrics.FinishRecordingPerformanceMetrics();
214 request_metrics.RecordRequestEvent(LoadModelResult::OK);
215}
216
Charles Zhao6d467e62020-08-31 10:02:03 +1000217void LoadHandwritingModelFromDir(
218 HandwritingRecognizerSpecPtr spec,
219 mojo::PendingReceiver<HandwritingRecognizer> receiver,
220 MachineLearningServiceImpl::LoadHandwritingModelCallback callback,
221 const std::string& root_path) {
222 RequestMetrics request_metrics("HandwritingModel", kMetricsRequestName);
223 request_metrics.StartRecordingPerformanceMetrics();
224
225 // Returns error if root_path is empty.
226 if (root_path.empty()) {
227 std::move(callback).Run(LoadHandwritingModelResult::DLC_GET_PATH_ERROR);
228 request_metrics.RecordRequestEvent(
229 LoadHandwritingModelResult::DLC_GET_PATH_ERROR);
230 return;
231 }
232
233 // Load HandwritingLibrary.
234 auto* const hwr_library = ml::HandwritingLibrary::GetInstance(root_path);
235
236 if (hwr_library->GetStatus() != ml::HandwritingLibrary::Status::kOk) {
237 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
238 << static_cast<int>(hwr_library->GetStatus());
239
240 switch (hwr_library->GetStatus()) {
241 case ml::HandwritingLibrary::Status::kLoadLibraryFailed: {
242 std::move(callback).Run(
243 LoadHandwritingModelResult::LOAD_NATIVE_LIB_ERROR);
244 request_metrics.RecordRequestEvent(
245 LoadHandwritingModelResult::LOAD_NATIVE_LIB_ERROR);
246 return;
247 }
248 case ml::HandwritingLibrary::Status::kFunctionLookupFailed: {
249 std::move(callback).Run(
250 LoadHandwritingModelResult::LOAD_FUNC_PTR_ERROR);
251 request_metrics.RecordRequestEvent(
252 LoadHandwritingModelResult::LOAD_FUNC_PTR_ERROR);
253 return;
254 }
255 default: {
256 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_ERROR);
257 request_metrics.RecordRequestEvent(
258 LoadHandwritingModelResult::LOAD_MODEL_ERROR);
259 return;
260 }
261 }
262 }
263
264 // Create HandwritingRecognizer.
265 if (!HandwritingRecognizerImpl::Create(std::move(spec),
266 std::move(receiver))) {
267 LOG(ERROR) << "LoadHandwritingRecognizer returned false.";
268 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_FILES_ERROR);
269 request_metrics.RecordRequestEvent(
270 LoadHandwritingModelResult::LOAD_MODEL_FILES_ERROR);
271 return;
272 }
273
274 std::move(callback).Run(LoadHandwritingModelResult::OK);
275 request_metrics.FinishRecordingPerformanceMetrics();
276 request_metrics.RecordRequestEvent(LoadHandwritingModelResult::OK);
277}
278
279void MachineLearningServiceImpl::LoadHandwritingModel(
280 chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr spec,
281 mojo::PendingReceiver<
282 chromeos::machine_learning::mojom::HandwritingRecognizer> receiver,
283 LoadHandwritingModelCallback callback) {
284 // If handwriting is installed on rootfs, load it from there.
285 if (ml::HandwritingLibrary::IsUseLibHandwritingEnabled()) {
286 LoadHandwritingModelFromDir(
287 std::move(spec), std::move(receiver), std::move(callback),
288 ml::HandwritingLibrary::kHandwritingDefaultModelDir);
289 return;
290 }
291
292 // If handwriting is installed as DLC, get the dir and subsequently load it
293 // from there.
294 if (ml::HandwritingLibrary::IsUseLibHandwritingDlcEnabled()) {
295 dlcservice_client_->GetDlcRootPath(
296 "libhandwriting",
297 base::BindOnce(&LoadHandwritingModelFromDir, std::move(spec),
298 std::move(receiver), std::move(callback)));
299 return;
300 }
301
302 // If handwriting is not on rootfs and not in DLC, this function should not
303 // be called.
304 LOG(ERROR) << "Calling LoadHandwritingModel without Handwriting enabled "
305 "should never happen.";
306 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_ERROR);
charleszhao05c5a4a2020-06-09 16:49:54 +1000307}
308
309void MachineLearningServiceImpl::LoadHandwritingModelWithSpec(
310 HandwritingRecognizerSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000311 mojo::PendingReceiver<HandwritingRecognizer> receiver,
Charles Zhaoc882eb02020-07-27 10:02:35 +1000312 LoadHandwritingModelWithSpecCallback callback) {
charleszhao5a7050e2020-07-14 15:21:41 +1000313 RequestMetrics request_metrics("HandwritingModel", kMetricsRequestName);
charleszhao17777f92020-04-23 12:53:11 +1000314 request_metrics.StartRecordingPerformanceMetrics();
315
316 // Load HandwritingLibrary.
317 auto* const hwr_library = ml::HandwritingLibrary::GetInstance();
318
319 if (hwr_library->GetStatus() ==
320 ml::HandwritingLibrary::Status::kNotSupported) {
321 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
322 << static_cast<int>(hwr_library->GetStatus());
323
324 std::move(callback).Run(LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
325 request_metrics.RecordRequestEvent(
326 LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
327 return;
328 }
329
330 if (hwr_library->GetStatus() != ml::HandwritingLibrary::Status::kOk) {
331 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
332 << static_cast<int>(hwr_library->GetStatus());
333
334 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
335 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
336 return;
337 }
338
339 // Create HandwritingRecognizer.
Andrew Moylanb481af72020-07-09 15:22:00 +1000340 if (!HandwritingRecognizerImpl::Create(std::move(spec),
341 std::move(receiver))) {
charleszhao17777f92020-04-23 12:53:11 +1000342 LOG(ERROR) << "LoadHandwritingRecognizer returned false.";
343 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
344 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
345 return;
346 }
347
348 std::move(callback).Run(LoadModelResult::OK);
349 request_metrics.FinishRecordingPerformanceMetrics();
350 request_metrics.RecordRequestEvent(LoadModelResult::OK);
351}
352
Honglin Yud2204272020-08-26 14:21:37 +1000353void MachineLearningServiceImpl::LoadSpeechRecognizer(
354 SodaConfigPtr config,
355 mojo::PendingRemote<SodaClient> soda_client,
356 mojo::PendingReceiver<SodaRecognizer> soda_recognizer,
357 LoadSpeechRecognizerCallback callback) {
358 RequestMetrics request_metrics("Soda", kMetricsRequestName);
359 request_metrics.StartRecordingPerformanceMetrics();
360
361 // Create the SodaRecognizer.
362 if (!SodaRecognizerImpl::Create(std::move(config), std::move(soda_client),
363 std::move(soda_recognizer))) {
364 LOG(ERROR) << "Failed to create SodaRecognizerImpl object.";
365 // TODO(robsc): it may be better that SODA has its specific enum values to
366 // return, similar to handwriting. So before we finalize the impl of SODA
367 // Mojo API, we may revisit this return value.
368 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
369 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
370 return;
371 }
372
373 std::move(callback).Run(LoadModelResult::OK);
374
375 request_metrics.FinishRecordingPerformanceMetrics();
376 request_metrics.RecordRequestEvent(LoadModelResult::OK);
377}
378
Jing Wang961b8af2020-10-26 12:40:35 +1100379void MachineLearningServiceImpl::LoadGrammarChecker(
380 mojo::PendingReceiver<chromeos::machine_learning::mojom::GrammarChecker>
381 receiver,
382 LoadGrammarCheckerCallback callback) {
383 RequestMetrics request_metrics("GrammarChecker", kMetricsRequestName);
384 request_metrics.StartRecordingPerformanceMetrics();
385
386 // Load GrammarLibrary.
387 auto* const grammar_library = ml::GrammarLibrary::GetInstance();
388
389 if (grammar_library->GetStatus() ==
390 ml::GrammarLibrary::Status::kNotSupported) {
391 LOG(ERROR) << "Initialize ml::GrammarLibrary with error "
392 << static_cast<int>(grammar_library->GetStatus());
393
394 std::move(callback).Run(LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
395 request_metrics.RecordRequestEvent(
396 LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
397 return;
398 }
399
400 if (grammar_library->GetStatus() != ml::GrammarLibrary::Status::kOk) {
401 LOG(ERROR) << "Initialize ml::GrammarLibrary with error "
402 << static_cast<int>(grammar_library->GetStatus());
403
404 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
405 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
406 return;
407 }
408
409 // Create GrammarChecker.
410 if (!GrammarCheckerImpl::Create(std::move(receiver))) {
411 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
412 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
413 return;
414 }
415
416 std::move(callback).Run(LoadModelResult::OK);
417
418 request_metrics.FinishRecordingPerformanceMetrics();
419 request_metrics.RecordRequestEvent(LoadModelResult::OK);
420}
421
Andrew Moylanff6be512018-07-03 11:05:01 +1000422} // namespace ml