blob: 36b7a1ad3801729e4956aa927ed46d87fdaa4d77 [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>
hscham4ce3c992021-02-19 16:37:23 +090011#include <base/callback_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"
Curtis McMullanf11584f2021-01-13 12:21:36 +110032#include "ml/text_suggester_impl.h"
33#include "ml/text_suggestions.h"
Michael Martisa74af932018-08-13 16:52:36 +100034
Andrew Moylanff6be512018-07-03 11:05:01 +100035namespace ml {
36
Michael Martisa74af932018-08-13 16:52:36 +100037namespace {
38
Honglin Yu0ed72352019-08-27 17:42:01 +100039using ::chromeos::machine_learning::mojom::BuiltinModelId;
40using ::chromeos::machine_learning::mojom::BuiltinModelSpecPtr;
41using ::chromeos::machine_learning::mojom::FlatBufferModelSpecPtr;
Andrew Moylanb481af72020-07-09 15:22:00 +100042using ::chromeos::machine_learning::mojom::HandwritingRecognizer;
charleszhao05c5a4a2020-06-09 16:49:54 +100043using ::chromeos::machine_learning::mojom::HandwritingRecognizerSpec;
44using ::chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr;
Charles Zhao6d467e62020-08-31 10:02:03 +100045using ::chromeos::machine_learning::mojom::LoadHandwritingModelResult;
Michael Martisa74af932018-08-13 16:52:36 +100046using ::chromeos::machine_learning::mojom::LoadModelResult;
Andrew Moylanb481af72020-07-09 15:22:00 +100047using ::chromeos::machine_learning::mojom::MachineLearningService;
48using ::chromeos::machine_learning::mojom::Model;
Honglin Yud2204272020-08-26 14:21:37 +100049using ::chromeos::machine_learning::mojom::SodaClient;
50using ::chromeos::machine_learning::mojom::SodaConfigPtr;
51using ::chromeos::machine_learning::mojom::SodaRecognizer;
Andrew Moylanb481af72020-07-09 15:22:00 +100052using ::chromeos::machine_learning::mojom::TextClassifier;
Michael Martisa74af932018-08-13 16:52:36 +100053
54constexpr char kSystemModelDir[] = "/opt/google/chrome/ml_models/";
Andrew Moylan79b34a42020-07-08 11:13:11 +100055// Base name for UMA metrics related to model loading (`LoadBuiltinModel`,
56// `LoadFlatBufferModel`, `LoadTextClassifier` or LoadHandwritingModel).
Honglin Yu6adafcd2019-07-22 13:48:11 +100057constexpr char kMetricsRequestName[] = "LoadModelResult";
Michael Martisa74af932018-08-13 16:52:36 +100058
Honglin Yuf33dce32019-12-05 15:10:39 +110059constexpr char kIcuDataFilePath[] = "/opt/google/chrome/icudtl.dat";
60
Honglin Yu20391cd2020-10-27 15:58:49 +110061// Used to hold the mmap object of the icu data file. Each process should only
62// have one instance of it. Intentionally never close it.
63// We can not make it as a member of `MachineLearningServiceImpl` because it
64// will crash the unit test (because in that case, when the
65// `MachineLearningServiceImpl` object is destructed, the file will be
66// unmapped but the icu data can not be reset in the testing process).
67base::MemoryMappedFile* g_icu_data_mmap_file = nullptr;
68
69void InitIcuIfNeeded() {
70 if (!g_icu_data_mmap_file) {
71 g_icu_data_mmap_file = new base::MemoryMappedFile();
72 CHECK(g_icu_data_mmap_file->Initialize(
73 base::FilePath(kIcuDataFilePath),
74 base::MemoryMappedFile::Access::READ_ONLY));
75 // Init the Icu library.
76 UErrorCode err = U_ZERO_ERROR;
77 udata_setCommonData(const_cast<uint8_t*>(g_icu_data_mmap_file->data()),
78 &err);
79 DCHECK(err == U_ZERO_ERROR);
80 // Never try to load Icu data from files.
81 udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
82 DCHECK(err == U_ZERO_ERROR);
83 }
84}
85
Michael Martisa74af932018-08-13 16:52:36 +100086} // namespace
87
Andrew Moylanff6be512018-07-03 11:05:01 +100088MachineLearningServiceImpl::MachineLearningServiceImpl(
hschamd13deea2021-03-08 09:46:15 +090089 mojo::PendingReceiver<
90 chromeos::machine_learning::mojom::MachineLearningService> receiver,
Andrew Moylanb481af72020-07-09 15:22:00 +100091 base::Closure disconnect_handler,
Michael Martisa74af932018-08-13 16:52:36 +100092 const std::string& model_dir)
Honglin Yu20391cd2020-10-27 15:58:49 +110093 : builtin_model_metadata_(GetBuiltinModelMetadata()),
Michael Martisa74af932018-08-13 16:52:36 +100094 model_dir_(model_dir),
hschamd13deea2021-03-08 09:46:15 +090095 receiver_(this, std::move(receiver)) {
Andrew Moylanb481af72020-07-09 15:22:00 +100096 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(
hschamd13deea2021-03-08 09:46:15 +0900100 mojo::PendingReceiver<
101 chromeos::machine_learning::mojom::MachineLearningService> receiver,
Charles Zhaod4fb7b62020-08-25 17:21:58 +1000102 base::Closure disconnect_handler,
103 dbus::Bus* bus)
Andrew Moylanb481af72020-07-09 15:22:00 +1000104 : MachineLearningServiceImpl(
hschamd13deea2021-03-08 09:46:15 +0900105 std::move(receiver), std::move(disconnect_handler), kSystemModelDir) {
Charles Zhaod4fb7b62020-08-25 17:21:58 +1000106 if (bus) {
107 dlcservice_client_ = std::make_unique<DlcserviceClient>(bus);
108 }
109}
Michael Martisa74af932018-08-13 16:52:36 +1000110
Andrew Moylanb481af72020-07-09 15:22:00 +1000111void MachineLearningServiceImpl::Clone(
112 mojo::PendingReceiver<MachineLearningService> receiver) {
113 clone_receivers_.Add(this, std::move(receiver));
Andrew Moylan2fb80af2020-07-08 10:52:08 +1000114}
115
Honglin Yu0ed72352019-08-27 17:42:01 +1000116void MachineLearningServiceImpl::LoadBuiltinModel(
117 BuiltinModelSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000118 mojo::PendingReceiver<Model> receiver,
Qijiang Fan5d381a02020-04-19 23:42:37 +0900119 LoadBuiltinModelCallback callback) {
Honglin Yu0ed72352019-08-27 17:42:01 +1000120 // Unsupported models do not have metadata entries.
121 const auto metadata_lookup = builtin_model_metadata_.find(spec->id);
122 if (metadata_lookup == builtin_model_metadata_.end()) {
Honglin Yua81145a2019-09-23 15:20:13 +1000123 LOG(WARNING) << "LoadBuiltinModel requested for unsupported model ID "
124 << spec->id << ".";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900125 std::move(callback).Run(LoadModelResult::MODEL_SPEC_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000126 RecordModelSpecificationErrorEvent();
127 return;
128 }
129
130 const BuiltinModelMetadata& metadata = metadata_lookup->second;
131
132 DCHECK(!metadata.metrics_model_name.empty());
133
charleszhao5a7050e2020-07-14 15:21:41 +1000134 RequestMetrics request_metrics(metadata.metrics_model_name,
135 kMetricsRequestName);
Honglin Yu0ed72352019-08-27 17:42:01 +1000136 request_metrics.StartRecordingPerformanceMetrics();
137
138 // Attempt to load model.
139 const std::string model_path = model_dir_ + metadata.model_file;
140 std::unique_ptr<tflite::FlatBufferModel> model =
141 tflite::FlatBufferModel::BuildFromFile(model_path.c_str());
142 if (model == nullptr) {
143 LOG(ERROR) << "Failed to load model file '" << model_path << "'.";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900144 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000145 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
146 return;
147 }
148
Honglin Yuc0cef102020-01-17 15:26:01 +1100149 ModelImpl::Create(metadata.required_inputs, metadata.required_outputs,
Andrew Moylanb481af72020-07-09 15:22:00 +1000150 std::move(model), std::move(receiver),
Honglin Yuc0cef102020-01-17 15:26:01 +1100151 metadata.metrics_model_name);
Honglin Yu0ed72352019-08-27 17:42:01 +1000152
Qijiang Fan5d381a02020-04-19 23:42:37 +0900153 std::move(callback).Run(LoadModelResult::OK);
Honglin Yu0ed72352019-08-27 17:42:01 +1000154
155 request_metrics.FinishRecordingPerformanceMetrics();
156 request_metrics.RecordRequestEvent(LoadModelResult::OK);
157}
158
159void MachineLearningServiceImpl::LoadFlatBufferModel(
160 FlatBufferModelSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000161 mojo::PendingReceiver<Model> receiver,
Qijiang Fan5d381a02020-04-19 23:42:37 +0900162 LoadFlatBufferModelCallback callback) {
Honglin Yu0ed72352019-08-27 17:42:01 +1000163 DCHECK(!spec->metrics_model_name.empty());
164
charleszhao5a7050e2020-07-14 15:21:41 +1000165 RequestMetrics request_metrics(spec->metrics_model_name, kMetricsRequestName);
Honglin Yu0ed72352019-08-27 17:42:01 +1000166 request_metrics.StartRecordingPerformanceMetrics();
167
Andrew Moylan79b34a42020-07-08 11:13:11 +1000168 // Take the ownership of the content of `model_string` because `ModelImpl` has
Honglin Yu0ed72352019-08-27 17:42:01 +1000169 // to hold the memory.
Andrew Moylan44c352f2020-11-04 15:19:46 +1100170 auto model_data =
171 std::make_unique<AlignedModelData>(std::move(spec->model_string));
Honglin Yu0ed72352019-08-27 17:42:01 +1000172
173 std::unique_ptr<tflite::FlatBufferModel> model =
Andrew Moylan44c352f2020-11-04 15:19:46 +1100174 tflite::FlatBufferModel::VerifyAndBuildFromBuffer(model_data->data(),
175 model_data->size());
Honglin Yu0ed72352019-08-27 17:42:01 +1000176 if (model == nullptr) {
177 LOG(ERROR) << "Failed to load model string of metric name: "
178 << spec->metrics_model_name << "'.";
Qijiang Fan5d381a02020-04-19 23:42:37 +0900179 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
Honglin Yu0ed72352019-08-27 17:42:01 +1000180 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
181 return;
182 }
183
Honglin Yuc0cef102020-01-17 15:26:01 +1100184 ModelImpl::Create(
Honglin Yu0ed72352019-08-27 17:42:01 +1000185 std::map<std::string, int>(spec->inputs.begin(), spec->inputs.end()),
186 std::map<std::string, int>(spec->outputs.begin(), spec->outputs.end()),
Andrew Moylan44c352f2020-11-04 15:19:46 +1100187 std::move(model), std::move(model_data), std::move(receiver),
Honglin Yu0ed72352019-08-27 17:42:01 +1000188 spec->metrics_model_name);
189
Qijiang Fan5d381a02020-04-19 23:42:37 +0900190 std::move(callback).Run(LoadModelResult::OK);
Honglin Yu0ed72352019-08-27 17:42:01 +1000191
192 request_metrics.FinishRecordingPerformanceMetrics();
193 request_metrics.RecordRequestEvent(LoadModelResult::OK);
194}
195
Honglin Yuf33dce32019-12-05 15:10:39 +1100196void MachineLearningServiceImpl::LoadTextClassifier(
Andrew Moylanb481af72020-07-09 15:22:00 +1000197 mojo::PendingReceiver<TextClassifier> receiver,
Honglin Yuf33dce32019-12-05 15:10:39 +1100198 LoadTextClassifierCallback callback) {
charleszhao5a7050e2020-07-14 15:21:41 +1000199 RequestMetrics request_metrics("TextClassifier", kMetricsRequestName);
Honglin Yuf33dce32019-12-05 15:10:39 +1100200 request_metrics.StartRecordingPerformanceMetrics();
201
Honglin Yuf33dce32019-12-05 15:10:39 +1100202 // Create the TextClassifier.
Honglin Yu3f99ff12020-10-15 00:40:11 +1100203 if (!TextClassifierImpl::Create(std::move(receiver))) {
Honglin Yuf33dce32019-12-05 15:10:39 +1100204 LOG(ERROR) << "Failed to create TextClassifierImpl object.";
205 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
206 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
207 return;
208 }
209
210 // initialize the icu library.
211 InitIcuIfNeeded();
212
213 std::move(callback).Run(LoadModelResult::OK);
214
215 request_metrics.FinishRecordingPerformanceMetrics();
216 request_metrics.RecordRequestEvent(LoadModelResult::OK);
217}
218
Charles Zhao6d467e62020-08-31 10:02:03 +1000219void LoadHandwritingModelFromDir(
220 HandwritingRecognizerSpecPtr spec,
221 mojo::PendingReceiver<HandwritingRecognizer> receiver,
222 MachineLearningServiceImpl::LoadHandwritingModelCallback callback,
223 const std::string& root_path) {
224 RequestMetrics request_metrics("HandwritingModel", kMetricsRequestName);
225 request_metrics.StartRecordingPerformanceMetrics();
226
227 // Returns error if root_path is empty.
228 if (root_path.empty()) {
229 std::move(callback).Run(LoadHandwritingModelResult::DLC_GET_PATH_ERROR);
230 request_metrics.RecordRequestEvent(
231 LoadHandwritingModelResult::DLC_GET_PATH_ERROR);
232 return;
233 }
234
235 // Load HandwritingLibrary.
236 auto* const hwr_library = ml::HandwritingLibrary::GetInstance(root_path);
237
238 if (hwr_library->GetStatus() != ml::HandwritingLibrary::Status::kOk) {
239 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
240 << static_cast<int>(hwr_library->GetStatus());
241
242 switch (hwr_library->GetStatus()) {
243 case ml::HandwritingLibrary::Status::kLoadLibraryFailed: {
244 std::move(callback).Run(
245 LoadHandwritingModelResult::LOAD_NATIVE_LIB_ERROR);
246 request_metrics.RecordRequestEvent(
247 LoadHandwritingModelResult::LOAD_NATIVE_LIB_ERROR);
248 return;
249 }
250 case ml::HandwritingLibrary::Status::kFunctionLookupFailed: {
251 std::move(callback).Run(
252 LoadHandwritingModelResult::LOAD_FUNC_PTR_ERROR);
253 request_metrics.RecordRequestEvent(
254 LoadHandwritingModelResult::LOAD_FUNC_PTR_ERROR);
255 return;
256 }
257 default: {
258 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_ERROR);
259 request_metrics.RecordRequestEvent(
260 LoadHandwritingModelResult::LOAD_MODEL_ERROR);
261 return;
262 }
263 }
264 }
265
266 // Create HandwritingRecognizer.
267 if (!HandwritingRecognizerImpl::Create(std::move(spec),
268 std::move(receiver))) {
269 LOG(ERROR) << "LoadHandwritingRecognizer returned false.";
270 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_FILES_ERROR);
271 request_metrics.RecordRequestEvent(
272 LoadHandwritingModelResult::LOAD_MODEL_FILES_ERROR);
273 return;
274 }
275
276 std::move(callback).Run(LoadHandwritingModelResult::OK);
277 request_metrics.FinishRecordingPerformanceMetrics();
278 request_metrics.RecordRequestEvent(LoadHandwritingModelResult::OK);
279}
280
281void MachineLearningServiceImpl::LoadHandwritingModel(
282 chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr spec,
283 mojo::PendingReceiver<
284 chromeos::machine_learning::mojom::HandwritingRecognizer> receiver,
285 LoadHandwritingModelCallback callback) {
286 // If handwriting is installed on rootfs, load it from there.
287 if (ml::HandwritingLibrary::IsUseLibHandwritingEnabled()) {
288 LoadHandwritingModelFromDir(
289 std::move(spec), std::move(receiver), std::move(callback),
290 ml::HandwritingLibrary::kHandwritingDefaultModelDir);
291 return;
292 }
293
294 // If handwriting is installed as DLC, get the dir and subsequently load it
295 // from there.
296 if (ml::HandwritingLibrary::IsUseLibHandwritingDlcEnabled()) {
297 dlcservice_client_->GetDlcRootPath(
298 "libhandwriting",
299 base::BindOnce(&LoadHandwritingModelFromDir, std::move(spec),
300 std::move(receiver), std::move(callback)));
301 return;
302 }
303
304 // If handwriting is not on rootfs and not in DLC, this function should not
305 // be called.
306 LOG(ERROR) << "Calling LoadHandwritingModel without Handwriting enabled "
307 "should never happen.";
308 std::move(callback).Run(LoadHandwritingModelResult::LOAD_MODEL_ERROR);
charleszhao05c5a4a2020-06-09 16:49:54 +1000309}
310
311void MachineLearningServiceImpl::LoadHandwritingModelWithSpec(
312 HandwritingRecognizerSpecPtr spec,
Andrew Moylanb481af72020-07-09 15:22:00 +1000313 mojo::PendingReceiver<HandwritingRecognizer> receiver,
Charles Zhaoc882eb02020-07-27 10:02:35 +1000314 LoadHandwritingModelWithSpecCallback callback) {
charleszhao5a7050e2020-07-14 15:21:41 +1000315 RequestMetrics request_metrics("HandwritingModel", kMetricsRequestName);
charleszhao17777f92020-04-23 12:53:11 +1000316 request_metrics.StartRecordingPerformanceMetrics();
317
318 // Load HandwritingLibrary.
319 auto* const hwr_library = ml::HandwritingLibrary::GetInstance();
320
321 if (hwr_library->GetStatus() ==
322 ml::HandwritingLibrary::Status::kNotSupported) {
323 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
324 << static_cast<int>(hwr_library->GetStatus());
325
326 std::move(callback).Run(LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
327 request_metrics.RecordRequestEvent(
328 LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
329 return;
330 }
331
332 if (hwr_library->GetStatus() != ml::HandwritingLibrary::Status::kOk) {
333 LOG(ERROR) << "Initialize ml::HandwritingLibrary with error "
334 << static_cast<int>(hwr_library->GetStatus());
335
336 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
337 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
338 return;
339 }
340
341 // Create HandwritingRecognizer.
Andrew Moylanb481af72020-07-09 15:22:00 +1000342 if (!HandwritingRecognizerImpl::Create(std::move(spec),
343 std::move(receiver))) {
charleszhao17777f92020-04-23 12:53:11 +1000344 LOG(ERROR) << "LoadHandwritingRecognizer returned false.";
345 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
346 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
347 return;
348 }
349
350 std::move(callback).Run(LoadModelResult::OK);
351 request_metrics.FinishRecordingPerformanceMetrics();
352 request_metrics.RecordRequestEvent(LoadModelResult::OK);
353}
354
Honglin Yud2204272020-08-26 14:21:37 +1000355void MachineLearningServiceImpl::LoadSpeechRecognizer(
356 SodaConfigPtr config,
357 mojo::PendingRemote<SodaClient> soda_client,
358 mojo::PendingReceiver<SodaRecognizer> soda_recognizer,
359 LoadSpeechRecognizerCallback callback) {
360 RequestMetrics request_metrics("Soda", kMetricsRequestName);
361 request_metrics.StartRecordingPerformanceMetrics();
362
363 // Create the SodaRecognizer.
364 if (!SodaRecognizerImpl::Create(std::move(config), std::move(soda_client),
365 std::move(soda_recognizer))) {
366 LOG(ERROR) << "Failed to create SodaRecognizerImpl object.";
367 // TODO(robsc): it may be better that SODA has its specific enum values to
368 // return, similar to handwriting. So before we finalize the impl of SODA
369 // Mojo API, we may revisit this return value.
370 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
371 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
372 return;
373 }
374
375 std::move(callback).Run(LoadModelResult::OK);
376
377 request_metrics.FinishRecordingPerformanceMetrics();
378 request_metrics.RecordRequestEvent(LoadModelResult::OK);
379}
380
Jing Wang961b8af2020-10-26 12:40:35 +1100381void MachineLearningServiceImpl::LoadGrammarChecker(
382 mojo::PendingReceiver<chromeos::machine_learning::mojom::GrammarChecker>
383 receiver,
384 LoadGrammarCheckerCallback callback) {
385 RequestMetrics request_metrics("GrammarChecker", kMetricsRequestName);
386 request_metrics.StartRecordingPerformanceMetrics();
387
388 // Load GrammarLibrary.
389 auto* const grammar_library = ml::GrammarLibrary::GetInstance();
390
391 if (grammar_library->GetStatus() ==
392 ml::GrammarLibrary::Status::kNotSupported) {
393 LOG(ERROR) << "Initialize ml::GrammarLibrary with error "
394 << static_cast<int>(grammar_library->GetStatus());
395
396 std::move(callback).Run(LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
397 request_metrics.RecordRequestEvent(
398 LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
399 return;
400 }
401
402 if (grammar_library->GetStatus() != ml::GrammarLibrary::Status::kOk) {
403 LOG(ERROR) << "Initialize ml::GrammarLibrary with error "
404 << static_cast<int>(grammar_library->GetStatus());
405
406 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
407 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
408 return;
409 }
410
411 // Create GrammarChecker.
412 if (!GrammarCheckerImpl::Create(std::move(receiver))) {
413 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
414 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
415 return;
416 }
417
418 std::move(callback).Run(LoadModelResult::OK);
419
420 request_metrics.FinishRecordingPerformanceMetrics();
421 request_metrics.RecordRequestEvent(LoadModelResult::OK);
422}
423
Curtis McMullanf11584f2021-01-13 12:21:36 +1100424void MachineLearningServiceImpl::LoadTextSuggester(
425 mojo::PendingReceiver<chromeos::machine_learning::mojom::TextSuggester>
426 receiver,
427 LoadTextSuggesterCallback callback) {
428 RequestMetrics request_metrics("TextSuggester", kMetricsRequestName);
429 request_metrics.StartRecordingPerformanceMetrics();
430
431 // Load TextSuggestions library.
432 auto* const text_suggestions = ml::TextSuggestions::GetInstance();
433
434 if (text_suggestions->GetStatus() ==
435 ml::TextSuggestions::Status::kNotSupported) {
436 LOG(ERROR) << "Initialize ml::TextSuggestions with error "
437 << static_cast<int>(text_suggestions->GetStatus());
438
439 std::move(callback).Run(LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
440 request_metrics.RecordRequestEvent(
441 LoadModelResult::FEATURE_NOT_SUPPORTED_ERROR);
442 return;
443 }
444
445 if (text_suggestions->GetStatus() != ml::TextSuggestions::Status::kOk) {
446 LOG(ERROR) << "Initialize ml::TextSuggestions with error "
447 << static_cast<int>(text_suggestions->GetStatus());
448
449 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
450 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
451 return;
452 }
453
454 // Create TextSuggester.
455 if (!TextSuggesterImpl::Create(std::move(receiver))) {
456 std::move(callback).Run(LoadModelResult::LOAD_MODEL_ERROR);
457 request_metrics.RecordRequestEvent(LoadModelResult::LOAD_MODEL_ERROR);
458 return;
459 }
460
461 std::move(callback).Run(LoadModelResult::OK);
462
463 request_metrics.FinishRecordingPerformanceMetrics();
464 request_metrics.RecordRequestEvent(LoadModelResult::OK);
465}
466
Andrew Moylanff6be512018-07-03 11:05:01 +1000467} // namespace ml