blob: 93702bad4416aea6da3fb09ea6948aace49b955f [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>
Qijiang Fan713061e2021-03-08 15:45:12 +090012#include <base/check.h>
Honglin Yuf33dce32019-12-05 15:10:39 +110013#include <base/files/file.h>
14#include <base/files/file_util.h>
Honglin Yu20391cd2020-10-27 15:58:49 +110015#include <base/files/memory_mapped_file.h>
Michael Martis8783c8e2019-06-26 17:30:54 +100016#include <tensorflow/lite/model.h>
Honglin Yuf33dce32019-12-05 15:10:39 +110017#include <unicode/putil.h>
18#include <unicode/udata.h>
19#include <utils/memory/mmap.h>
Michael Martisa74af932018-08-13 16:52:36 +100020
Jing Wang961b8af2020-10-26 12:40:35 +110021#include "ml/grammar_checker_impl.h"
22#include "ml/grammar_library.h"
charleszhao17777f92020-04-23 12:53:11 +100023#include "ml/handwriting.h"
24#include "ml/handwriting_recognizer_impl.h"
Michael Martisa74af932018-08-13 16:52:36 +100025#include "ml/model_impl.h"
charleszhao17777f92020-04-23 12:53:11 +100026#include "ml/mojom/handwriting_recognizer.mojom.h"
Hidehiko Abeaa488c32018-08-31 23:49:41 +090027#include "ml/mojom/model.mojom.h"
Honglin Yud2204272020-08-26 14:21:37 +100028#include "ml/mojom/soda.mojom.h"
Andrew Moylan44c352f2020-11-04 15:19:46 +110029#include "ml/request_metrics.h"
Honglin Yud2204272020-08-26 14:21:37 +100030#include "ml/soda_recognizer_impl.h"
Honglin Yuf33dce32019-12-05 15:10:39 +110031#include "ml/text_classifier_impl.h"
Michael Martisa74af932018-08-13 16:52:36 +100032
Andrew Moylanff6be512018-07-03 11:05:01 +100033namespace ml {
34
Michael Martisa74af932018-08-13 16:52:36 +100035namespace {
36
Honglin Yu0ed72352019-08-27 17:42:01 +100037using ::chromeos::machine_learning::mojom::BuiltinModelId;
38using ::chromeos::machine_learning::mojom::BuiltinModelSpecPtr;
39using ::chromeos::machine_learning::mojom::FlatBufferModelSpecPtr;
Andrew Moylanb481af72020-07-09 15:22:00 +100040using ::chromeos::machine_learning::mojom::HandwritingRecognizer;
charleszhao05c5a4a2020-06-09 16:49:54 +100041using ::chromeos::machine_learning::mojom::HandwritingRecognizerSpec;
42using ::chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr;
Charles Zhao6d467e62020-08-31 10:02:03 +100043using ::chromeos::machine_learning::mojom::LoadHandwritingModelResult;
Michael Martisa74af932018-08-13 16:52:36 +100044using ::chromeos::machine_learning::mojom::LoadModelResult;
Andrew Moylanb481af72020-07-09 15:22:00 +100045using ::chromeos::machine_learning::mojom::MachineLearningService;
46using ::chromeos::machine_learning::mojom::Model;
Honglin Yud2204272020-08-26 14:21:37 +100047using ::chromeos::machine_learning::mojom::SodaClient;
48using ::chromeos::machine_learning::mojom::SodaConfigPtr;
49using ::chromeos::machine_learning::mojom::SodaRecognizer;
Andrew Moylanb481af72020-07-09 15:22:00 +100050using ::chromeos::machine_learning::mojom::TextClassifier;
Michael Martisa74af932018-08-13 16:52:36 +100051
52constexpr char kSystemModelDir[] = "/opt/google/chrome/ml_models/";
Andrew Moylan79b34a42020-07-08 11:13:11 +100053// Base name for UMA metrics related to model loading (`LoadBuiltinModel`,
54// `LoadFlatBufferModel`, `LoadTextClassifier` or LoadHandwritingModel).
Honglin Yu6adafcd2019-07-22 13:48:11 +100055constexpr char kMetricsRequestName[] = "LoadModelResult";
Michael Martisa74af932018-08-13 16:52:36 +100056
Honglin Yuf33dce32019-12-05 15:10:39 +110057constexpr char kIcuDataFilePath[] = "/opt/google/chrome/icudtl.dat";
58
Honglin Yu20391cd2020-10-27 15:58:49 +110059// Used to hold the mmap object of the icu data file. Each process should only
60// have one instance of it. Intentionally never close it.
61// We can not make it as a member of `MachineLearningServiceImpl` because it
62// will crash the unit test (because in that case, when the
63// `MachineLearningServiceImpl` object is destructed, the file will be
64// unmapped but the icu data can not be reset in the testing process).
65base::MemoryMappedFile* g_icu_data_mmap_file = nullptr;
66
67void InitIcuIfNeeded() {
68 if (!g_icu_data_mmap_file) {
69 g_icu_data_mmap_file = new base::MemoryMappedFile();
70 CHECK(g_icu_data_mmap_file->Initialize(
71 base::FilePath(kIcuDataFilePath),
72 base::MemoryMappedFile::Access::READ_ONLY));
73 // Init the Icu library.
74 UErrorCode err = U_ZERO_ERROR;
75 udata_setCommonData(const_cast<uint8_t*>(g_icu_data_mmap_file->data()),
76 &err);
77 DCHECK(err == U_ZERO_ERROR);
78 // Never try to load Icu data from files.
79 udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
80 DCHECK(err == U_ZERO_ERROR);
81 }
82}
83
Michael Martisa74af932018-08-13 16:52:36 +100084} // namespace
85
Andrew Moylanff6be512018-07-03 11:05:01 +100086MachineLearningServiceImpl::MachineLearningServiceImpl(
Michael Martisa74af932018-08-13 16:52:36 +100087 mojo::ScopedMessagePipeHandle pipe,
Andrew Moylanb481af72020-07-09 15:22:00 +100088 base::Closure disconnect_handler,
Michael Martisa74af932018-08-13 16:52:36 +100089 const std::string& model_dir)
Honglin Yu20391cd2020-10-27 15:58:49 +110090 : builtin_model_metadata_(GetBuiltinModelMetadata()),
Michael Martisa74af932018-08-13 16:52:36 +100091 model_dir_(model_dir),
Andrew Moylanb481af72020-07-09 15:22:00 +100092 receiver_(this,
93 mojo::InterfaceRequest<
94 chromeos::machine_learning::mojom::MachineLearningService>(
95 std::move(pipe))) {
96 receiver_.set_disconnect_handler(std::move(disconnect_handler));
Andrew Moylanff6be512018-07-03 11:05:01 +100097}
98
Michael Martisa74af932018-08-13 16:52:36 +100099MachineLearningServiceImpl::MachineLearningServiceImpl(
Charles Zhaod4fb7b62020-08-25 17:21:58 +1000100 mojo::ScopedMessagePipeHandle pipe,
101 base::Closure disconnect_handler,
102 dbus::Bus* bus)
Andrew Moylanb481af72020-07-09 15:22:00 +1000103 : MachineLearningServiceImpl(
Charles Zhaod4fb7b62020-08-25 17:21:58 +1000104 std::move(pipe), std::move(disconnect_handler), kSystemModelDir) {
105 if (bus) {
106 dlcservice_client_ = std::make_unique<DlcserviceClient>(bus);
107 }
108}
Michael Martisa74af932018-08-13 16:52:36 +1000109
Andrew Moylanb481af72020-07-09 15:22:00 +1000110void MachineLearningServiceImpl::Clone(
111 mojo::PendingReceiver<MachineLearningService> receiver) {
112 clone_receivers_.Add(this, std::move(receiver));
Andrew Moylan2fb80af2020-07-08 10:52:08 +1000113}
114
Honglin Yu0ed72352019-08-27 17:42:01 +1000115void MachineLearningServiceImpl::LoadBuiltinModel(
116 BuiltinModelSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000117 mojo::PendingReceiver<Model> receiver,
Qijiang Fan5d381a02020-04-19 23:42:37 +0900118 LoadBuiltinModelCallback callback) {
Honglin Yu0ed72352019-08-27 17:42:01 +1000119 // Unsupported models do not have metadata entries.
120 const auto metadata_lookup = builtin_model_metadata_.find(spec->id);
121 if (metadata_lookup == builtin_model_metadata_.end()) {
Honglin Yua81145a2019-09-23 15:20:13 +1000122 LOG(WARNING) << "LoadBuiltinModel requested for unsupported model ID "
123 << spec->id << ".";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900124 std::move(callback).Run(LoadModelResult::MODEL_SPEC_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000125 RecordModelSpecificationErrorEvent();
126 return;
127 }
128
129 const BuiltinModelMetadata& metadata = metadata_lookup->second;
130
131 DCHECK(!metadata.metrics_model_name.empty());
132
charleszhao5a7050e2020-07-14 15:21:41 +1000133 RequestMetrics request_metrics(metadata.metrics_model_name,
134 kMetricsRequestName);
Honglin Yu0ed72352019-08-27 17:42:01 +1000135 request_metrics.StartRecordingPerformanceMetrics();
136
137 // Attempt to load model.
138 const std::string model_path = model_dir_ + metadata.model_file;
139 std::unique_ptr<tflite::FlatBufferModel> model =
140 tflite::FlatBufferModel::BuildFromFile(model_path.c_str());
141 if (model == nullptr) {
142 LOG(ERROR) << "Failed to load model file '" << model_path << "'.";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900143 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000144 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
145 return;
146 }
147
Honglin Yuc0cef102020-01-17 15:26:01 +1100148 ModelImpl::Create(metadata.required_inputs, metadata.required_outputs,
Andrew Moylanb481af72020-07-09 15:22:00 +1000149 std::move(model), std::move(receiver),
Honglin Yuc0cef102020-01-17 15:26:01 +1100150 metadata.metrics_model_name);
Honglin Yu0ed72352019-08-27 17:42:01 +1000151
Qijiang Fan5d381a02020-04-19 23:42:37 +0900152 std::move(callback).Run(LoadModelResult::OK);
Honglin Yu0ed72352019-08-27 17:42:01 +1000153
154 request_metrics.FinishRecordingPerformanceMetrics();
155 request_metrics.RecordRequestEvent(LoadModelResult::OK);
156}
157
158void MachineLearningServiceImpl::LoadFlatBufferModel(
159 FlatBufferModelSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000160 mojo::PendingReceiver<Model> receiver,
Qijiang Fan5d381a02020-04-19 23:42:37 +0900161 LoadFlatBufferModelCallback callback) {
Honglin Yu0ed72352019-08-27 17:42:01 +1000162 DCHECK(!spec->metrics_model_name.empty());
163
charleszhao5a7050e2020-07-14 15:21:41 +1000164 RequestMetrics request_metrics(spec->metrics_model_name, kMetricsRequestName);
Honglin Yu0ed72352019-08-27 17:42:01 +1000165 request_metrics.StartRecordingPerformanceMetrics();
166
Andrew Moylan79b34a42020-07-08 11:13:11 +1000167 // Take the ownership of the content of `model_string` because `ModelImpl` has
Honglin Yu0ed72352019-08-27 17:42:01 +1000168 // to hold the memory.
Andrew Moylan44c352f2020-11-04 15:19:46 +1100169 auto model_data =
170 std::make_unique<AlignedModelData>(std::move(spec->model_string));
Honglin Yu0ed72352019-08-27 17:42:01 +1000171
172 std::unique_ptr<tflite::FlatBufferModel> model =
Andrew Moylan44c352f2020-11-04 15:19:46 +1100173 tflite::FlatBufferModel::VerifyAndBuildFromBuffer(model_data->data(),
174 model_data->size());
Honglin Yu0ed72352019-08-27 17:42:01 +1000175 if (model == nullptr) {
176 LOG(ERROR) << "Failed to load model string of metric name: "
177 << spec->metrics_model_name << "'.";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900178 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000179 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
180 return;
181 }
182
Honglin Yuc0cef102020-01-17 15:26:01 +1100183 ModelImpl::Create(
Honglin Yu0ed72352019-08-27 17:42:01 +1000184 std::map<std::string, int>(spec->inputs.begin(), spec->inputs.end()),
185 std::map<std::string, int>(spec->outputs.begin(), spec->outputs.end()),
Andrew Moylan44c352f2020-11-04 15:19:46 +1100186 std::move(model), std::move(model_data), std::move(receiver),
Honglin Yu0ed72352019-08-27 17:42:01 +1000187 spec->metrics_model_name);
188
Qijiang Fan5d381a02020-04-19 23:42:37 +0900189 std::move(callback).Run(LoadModelResult::OK);
Honglin Yu0ed72352019-08-27 17:42:01 +1000190
191 request_metrics.FinishRecordingPerformanceMetrics();
192 request_metrics.RecordRequestEvent(LoadModelResult::OK);
193}
194
Honglin Yuf33dce32019-12-05 15:10:39 +1100195void MachineLearningServiceImpl::LoadTextClassifier(
Andrew Moylanb481af72020-07-09 15:22:00 +1000196 mojo::PendingReceiver<TextClassifier> receiver,
Honglin Yuf33dce32019-12-05 15:10:39 +1100197 LoadTextClassifierCallback callback) {
charleszhao5a7050e2020-07-14 15:21:41 +1000198 RequestMetrics request_metrics("TextClassifier", kMetricsRequestName);
Honglin Yuf33dce32019-12-05 15:10:39 +1100199 request_metrics.StartRecordingPerformanceMetrics();
200
Honglin Yuf33dce32019-12-05 15:10:39 +1100201 // Create the TextClassifier.
Honglin Yu3f99ff12020-10-15 00:40:11 +1100202 if (!TextClassifierImpl::Create(std::move(receiver))) {
Honglin Yuf33dce32019-12-05 15:10:39 +1100203 LOG(ERROR) << "Failed to create TextClassifierImpl object.";
204 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
205 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
206 return;
207 }
208
209 // initialize the icu library.
210 InitIcuIfNeeded();
211
212 std::move(callback).Run(LoadModelResult::OK);
213
214 request_metrics.FinishRecordingPerformanceMetrics();
215 request_metrics.RecordRequestEvent(LoadModelResult::OK);
216}
217
Charles Zhao6d467e62020-08-31 10:02:03 +1000218void LoadHandwritingModelFromDir(
219 HandwritingRecognizerSpecPtr spec,
220 mojo::PendingReceiver<HandwritingRecognizer> receiver,
221 MachineLearningServiceImpl::LoadHandwritingModelCallback callback,
222 const std::string& root_path) {
223 RequestMetrics request_metrics("HandwritingModel", kMetricsRequestName);
224 request_metrics.StartRecordingPerformanceMetrics();
225
226 // Returns error if root_path is empty.
227 if (root_path.empty()) {
228 std::move(callback).Run(LoadHandwritingModelResult::DLC_GET_PATH_ERROR);
229 request_metrics.RecordRequestEvent(
230 LoadHandwritingModelResult::DLC_GET_PATH_ERROR);
231 return;
232 }
233
234 // Load HandwritingLibrary.
235 auto* const hwr_library = ml::HandwritingLibrary::GetInstance(root_path);
236
237 if (hwr_library->GetStatus() != ml::HandwritingLibrary::Status::kOk) {
238 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
239 << static_cast<int>(hwr_library->GetStatus());
240
241 switch (hwr_library->GetStatus()) {
242 case ml::HandwritingLibrary::Status::kLoadLibraryFailed: {
243 std::move(callback).Run(
244 LoadHandwritingModelResult::LOAD_NATIVE_LIB_ERROR);
245 request_metrics.RecordRequestEvent(
246 LoadHandwritingModelResult::LOAD_NATIVE_LIB_ERROR);
247 return;
248 }
249 case ml::HandwritingLibrary::Status::kFunctionLookupFailed: {
250 std::move(callback).Run(
251 LoadHandwritingModelResult::LOAD_FUNC_PTR_ERROR);
252 request_metrics.RecordRequestEvent(
253 LoadHandwritingModelResult::LOAD_FUNC_PTR_ERROR);
254 return;
255 }
256 default: {
257 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_ERROR);
258 request_metrics.RecordRequestEvent(
259 LoadHandwritingModelResult::LOAD_MODEL_ERROR);
260 return;
261 }
262 }
263 }
264
265 // Create HandwritingRecognizer.
266 if (!HandwritingRecognizerImpl::Create(std::move(spec),
267 std::move(receiver))) {
268 LOG(ERROR) << "LoadHandwritingRecognizer returned false.";
269 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_FILES_ERROR);
270 request_metrics.RecordRequestEvent(
271 LoadHandwritingModelResult::LOAD_MODEL_FILES_ERROR);
272 return;
273 }
274
275 std::move(callback).Run(LoadHandwritingModelResult::OK);
276 request_metrics.FinishRecordingPerformanceMetrics();
277 request_metrics.RecordRequestEvent(LoadHandwritingModelResult::OK);
278}
279
280void MachineLearningServiceImpl::LoadHandwritingModel(
281 chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr spec,
282 mojo::PendingReceiver<
283 chromeos::machine_learning::mojom::HandwritingRecognizer> receiver,
284 LoadHandwritingModelCallback callback) {
285 // If handwriting is installed on rootfs, load it from there.
286 if (ml::HandwritingLibrary::IsUseLibHandwritingEnabled()) {
287 LoadHandwritingModelFromDir(
288 std::move(spec), std::move(receiver), std::move(callback),
289 ml::HandwritingLibrary::kHandwritingDefaultModelDir);
290 return;
291 }
292
293 // If handwriting is installed as DLC, get the dir and subsequently load it
294 // from there.
295 if (ml::HandwritingLibrary::IsUseLibHandwritingDlcEnabled()) {
296 dlcservice_client_->GetDlcRootPath(
297 "libhandwriting",
298 base::BindOnce(&LoadHandwritingModelFromDir, std::move(spec),
299 std::move(receiver), std::move(callback)));
300 return;
301 }
302
303 // If handwriting is not on rootfs and not in DLC, this function should not
304 // be called.
305 LOG(ERROR) << "Calling LoadHandwritingModel without Handwriting enabled "
306 "should never happen.";
307 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_ERROR);
charleszhao05c5a4a2020-06-09 16:49:54 +1000308}
309
310void MachineLearningServiceImpl::LoadHandwritingModelWithSpec(
311 HandwritingRecognizerSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000312 mojo::PendingReceiver<HandwritingRecognizer> receiver,
Charles Zhaoc882eb02020-07-27 10:02:35 +1000313 LoadHandwritingModelWithSpecCallback callback) {
charleszhao5a7050e2020-07-14 15:21:41 +1000314 RequestMetrics request_metrics("HandwritingModel", kMetricsRequestName);
charleszhao17777f92020-04-23 12:53:11 +1000315 request_metrics.StartRecordingPerformanceMetrics();
316
317 // Load HandwritingLibrary.
318 auto* const hwr_library = ml::HandwritingLibrary::GetInstance();
319
320 if (hwr_library->GetStatus() ==
321 ml::HandwritingLibrary::Status::kNotSupported) {
322 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
323 << static_cast<int>(hwr_library->GetStatus());
324
325 std::move(callback).Run(LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
326 request_metrics.RecordRequestEvent(
327 LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
328 return;
329 }
330
331 if (hwr_library->GetStatus() != ml::HandwritingLibrary::Status::kOk) {
332 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
333 << static_cast<int>(hwr_library->GetStatus());
334
335 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
336 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
337 return;
338 }
339
340 // Create HandwritingRecognizer.
Andrew Moylanb481af72020-07-09 15:22:00 +1000341 if (!HandwritingRecognizerImpl::Create(std::move(spec),
342 std::move(receiver))) {
charleszhao17777f92020-04-23 12:53:11 +1000343 LOG(ERROR) << "LoadHandwritingRecognizer returned false.";
344 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
345 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
346 return;
347 }
348
349 std::move(callback).Run(LoadModelResult::OK);
350 request_metrics.FinishRecordingPerformanceMetrics();
351 request_metrics.RecordRequestEvent(LoadModelResult::OK);
352}
353
Honglin Yud2204272020-08-26 14:21:37 +1000354void MachineLearningServiceImpl::LoadSpeechRecognizer(
355 SodaConfigPtr config,
356 mojo::PendingRemote<SodaClient> soda_client,
357 mojo::PendingReceiver<SodaRecognizer> soda_recognizer,
358 LoadSpeechRecognizerCallback callback) {
359 RequestMetrics request_metrics("Soda", kMetricsRequestName);
360 request_metrics.StartRecordingPerformanceMetrics();
361
362 // Create the SodaRecognizer.
363 if (!SodaRecognizerImpl::Create(std::move(config), std::move(soda_client),
364 std::move(soda_recognizer))) {
365 LOG(ERROR) << "Failed to create SodaRecognizerImpl object.";
366 // TODO(robsc): it may be better that SODA has its specific enum values to
367 // return, similar to handwriting. So before we finalize the impl of SODA
368 // Mojo API, we may revisit this return value.
369 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
370 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
371 return;
372 }
373
374 std::move(callback).Run(LoadModelResult::OK);
375
376 request_metrics.FinishRecordingPerformanceMetrics();
377 request_metrics.RecordRequestEvent(LoadModelResult::OK);
378}
379
Jing Wang961b8af2020-10-26 12:40:35 +1100380void MachineLearningServiceImpl::LoadGrammarChecker(
381 mojo::PendingReceiver<chromeos::machine_learning::mojom::GrammarChecker>
382 receiver,
383 LoadGrammarCheckerCallback callback) {
384 RequestMetrics request_metrics("GrammarChecker", kMetricsRequestName);
385 request_metrics.StartRecordingPerformanceMetrics();
386
387 // Load GrammarLibrary.
388 auto* const grammar_library = ml::GrammarLibrary::GetInstance();
389
390 if (grammar_library->GetStatus() ==
391 ml::GrammarLibrary::Status::kNotSupported) {
392 LOG(ERROR) << "Initialize ml::GrammarLibrary with error "
393 << static_cast<int>(grammar_library->GetStatus());
394
395 std::move(callback).Run(LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
396 request_metrics.RecordRequestEvent(
397 LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
398 return;
399 }
400
401 if (grammar_library->GetStatus() != ml::GrammarLibrary::Status::kOk) {
402 LOG(ERROR) << "Initialize ml::GrammarLibrary with error "
403 << static_cast<int>(grammar_library->GetStatus());
404
405 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
406 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
407 return;
408 }
409
410 // Create GrammarChecker.
411 if (!GrammarCheckerImpl::Create(std::move(receiver))) {
412 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
413 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
414 return;
415 }
416
417 std::move(callback).Run(LoadModelResult::OK);
418
419 request_metrics.FinishRecordingPerformanceMetrics();
420 request_metrics.RecordRequestEvent(LoadModelResult::OK);
421}
422
Andrew Moylanff6be512018-07-03 11:05:01 +1000423} // namespace ml