blob: d837e06a51bf72880e581754731b82d7c54b4e07 [file] [log] [blame]
Honglin Yu0c4760a2020-04-18 20:53:31 +10001// Copyright 2020 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#ifndef ML_HANDWRITING_H_
6#define ML_HANDWRITING_H_
7
Charles Zhaoc882eb02020-07-27 10:02:35 +10008#include <string>
9
Honglin Yu0c4760a2020-04-18 20:53:31 +100010#include <base/no_destructor.h>
11#include <base/optional.h>
12#include <base/scoped_native_library.h>
Honglin Yucfb19302020-08-17 17:13:14 +100013#include <chromeos/libhandwriting/handwriting_interface.h>
Honglin Yu0c4760a2020-04-18 20:53:31 +100014
Honglin Yucfb19302020-08-17 17:13:14 +100015#include "chrome/knowledge/handwriting/handwriting_interface.pb.h"
Charles Zhaoc882eb02020-07-27 10:02:35 +100016#include "ml/mojom/handwriting_recognizer.mojom.h"
Honglin Yu3e360a02020-08-27 10:30:01 +100017#include "ml/util.h"
Honglin Yu0c4760a2020-04-18 20:53:31 +100018
19namespace ml {
20// A singleton proxy class for the handwriting DSO.
21// Usage:
22// auto* const hwr_library = HandwritingLibrary::GetInstance();
23// if (hwr_library->GetStatus() == HandwritingLibrary::kOk) {
24// // Do the real handwriting here.
25// recognizer = hwr_library->CreateHandwritingRecognizer();
26// ...
27// } else {
28// // Otherwise, use HandwritingLibrary::GetStatus() to get the error type.
29// // Maybe return "not installed".
30// ...
31// }
32class HandwritingLibrary {
33 public:
Honglin Yu0c4760a2020-04-18 20:53:31 +100034 enum class Status {
35 kOk = 0,
36 kUninitialized = 1,
37 kLoadLibraryFailed = 2,
charleszhao17777f92020-04-23 12:53:11 +100038 kFunctionLookupFailed = 3,
39 kNotSupported = 4,
Honglin Yu0c4760a2020-04-18 20:53:31 +100040 };
41
Charles Zhao6d467e62020-08-31 10:02:03 +100042 // Default handwriting model directory on rootfs.
43 static constexpr char kHandwritingDefaultModelDir[] =
44 "/opt/google/chrome/ml_models/handwriting";
45
Charles Zhaoc882eb02020-07-27 10:02:35 +100046 // Returns whether HandwritingLibrary is supported.
47 static constexpr bool IsHandwritingLibrarySupported() {
48 return (IsUseLibHandwritingEnabled() || IsUseLibHandwritingDlcEnabled()) &&
49 !IsAsan();
50 }
51
52 // Returns whether HandwritingLibrary is supported for unit tests.
53 static constexpr bool IsHandwritingLibraryUnitTestSupported() {
54 return IsUseLibHandwritingEnabled() && !IsAsan();
55 }
56
Charles Zhao6d467e62020-08-31 10:02:03 +100057 // Returns bool of use.ondevice_handwriting.
58 static constexpr bool IsUseLibHandwritingEnabled() {
59 return USE_ONDEVICE_HANDWRITING;
60 }
61
62 // Returns bool of use.ondevice_handwriting_dlc.
63 static constexpr bool IsUseLibHandwritingDlcEnabled() {
64 return USE_ONDEVICE_HANDWRITING_DLC;
65 }
66
67 // Gets the singleton HandwritingLibrary. The singleton is initialized with
68 // `model_path` on the first call to GetInstance; for the rest of the calls,
69 // the `model_path` is ignored, and the existing singleton is returned.
70 // The `model_path` should be either a path on rootfs or a path returned by
71 // DlcService.
72 static HandwritingLibrary* GetInstance(
73 const std::string& model_path = kHandwritingDefaultModelDir);
Honglin Yu0c4760a2020-04-18 20:53:31 +100074
alanlxl867da6c2021-04-19 10:36:35 +100075 // Sets a fake impl of HandwritingLibrary which doesn't dlopen the library.
76 // This is only used in fuzzer test.
77 static void UseFakeHandwritingLibraryForTesting(
78 HandwritingLibrary* fake_handwriting_library);
79
Honglin Yu0c4760a2020-04-18 20:53:31 +100080 // Get whether the library is successfully initialized.
Andrew Moylan79b34a42020-07-08 11:13:11 +100081 // Initially, the status is `Status::kUninitialized` (this value should never
Honglin Yu0c4760a2020-04-18 20:53:31 +100082 // be returned).
Andrew Moylan79b34a42020-07-08 11:13:11 +100083 // If libhandwriting.so can not be loaded, return `kLoadLibraryFailed`. This
Honglin Yu0c4760a2020-04-18 20:53:31 +100084 // usually means on-device handwriting is not supported.
85 // If the functions can not be successfully looked up, return
Andrew Moylan79b34a42020-07-08 11:13:11 +100086 // `kFunctionLookupFailed`.
87 // Return `Status::kOk` if everything works fine.
alanlxl867da6c2021-04-19 10:36:35 +100088 virtual Status GetStatus() const = 0;
Honglin Yu0c4760a2020-04-18 20:53:31 +100089
90 // The following public member functions define the interface functions of
Andrew Moylan79b34a42020-07-08 11:13:11 +100091 // the libhandwriting.so library. Function `InitHandwritingRecognizerLibrary`
92 // and `DeleteHandwritingResultData` do not need interfaces because the client
Honglin Yu0c4760a2020-04-18 20:53:31 +100093 // won't call it.
94
95 // Creates and returns a handwriting recognizer which is needed for using the
96 // other interface. The memory is owned by the user and should be deleted
Andrew Moylan79b34a42020-07-08 11:13:11 +100097 // using `DestroyHandwritingRecognizer` after usage.
alanlxl867da6c2021-04-19 10:36:35 +100098 virtual HandwritingRecognizer CreateHandwritingRecognizer() const = 0;
Charles Zhaoc882eb02020-07-27 10:02:35 +100099 // Load the models with `spec` stores the language, the path to the data files
100 // of the model (machine learning models, configurations etc.).
Honglin Yu0c4760a2020-04-18 20:53:31 +1000101 // Returns true if HandwritingRecognizer is correctly loaded and
102 // initialized. Returns false otherwise.
alanlxl867da6c2021-04-19 10:36:35 +1000103 virtual bool LoadHandwritingRecognizer(HandwritingRecognizer recognizer,
104 const std::string& language) const = 0;
Andrew Moylan79b34a42020-07-08 11:13:11 +1000105 // Sends the specified `request` to `recognizer`, if succeeds, `result` (which
Honglin Yu0c4760a2020-04-18 20:53:31 +1000106 // should not be null) is populated with the recognition result.
107 // Returns true if succeeds, otherwise returns false.
alanlxl867da6c2021-04-19 10:36:35 +1000108 virtual bool RecognizeHandwriting(
Honglin Yu0c4760a2020-04-18 20:53:31 +1000109 HandwritingRecognizer recognizer,
110 const chrome_knowledge::HandwritingRecognizerRequest& request,
alanlxl867da6c2021-04-19 10:36:35 +1000111 chrome_knowledge::HandwritingRecognizerResult* result) const = 0;
Honglin Yu0c4760a2020-04-18 20:53:31 +1000112 // Destroys the handwriting recognizer created by
Andrew Moylan79b34a42020-07-08 11:13:11 +1000113 // `CreateHandwritingRecognizer`. Must be called if the handwriting recognizer
Honglin Yu0c4760a2020-04-18 20:53:31 +1000114 // will not be used anymore, otherwise there will be memory leak.
alanlxl867da6c2021-04-19 10:36:35 +1000115 virtual void DestroyHandwritingRecognizer(
116 HandwritingRecognizer recognizer) const = 0;
117
118 protected:
119 HandwritingLibrary() = default;
120 virtual ~HandwritingLibrary() = default;
Honglin Yu0c4760a2020-04-18 20:53:31 +1000121
122 private:
123 friend class base::NoDestructor<HandwritingLibrary>;
Charles Zhaoc882eb02020-07-27 10:02:35 +1000124 FRIEND_TEST(HandwritingLibraryTest, CanLoadLibrary);
Honglin Yu0c4760a2020-04-18 20:53:31 +1000125
Charles Zhao6d467e62020-08-31 10:02:03 +1000126 // Currently HandwritingLibrary is supported only when the "sanitizer" is not
127 // enabled (see https://crbug.com/1082632).
128 static constexpr bool IsAsan() { return __has_feature(address_sanitizer); }
Honglin Yu0c4760a2020-04-18 20:53:31 +1000129};
130
131} // namespace ml
132
133#endif // ML_HANDWRITING_H_