blob: bf9919d0d70eb6b39c5982d95fc5a85e56bf6b18 [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>
13#include <chromeos/libhandwriting/interface.h>
14
15#include "chrome/knowledge/handwriting/interface.pb.h"
Charles Zhaoc882eb02020-07-27 10:02:35 +100016#include "ml/mojom/handwriting_recognizer.mojom.h"
Honglin Yu0c4760a2020-04-18 20:53:31 +100017
18namespace ml {
19// A singleton proxy class for the handwriting DSO.
20// Usage:
21// auto* const hwr_library = HandwritingLibrary::GetInstance();
22// if (hwr_library->GetStatus() == HandwritingLibrary::kOk) {
23// // Do the real handwriting here.
24// recognizer = hwr_library->CreateHandwritingRecognizer();
25// ...
26// } else {
27// // Otherwise, use HandwritingLibrary::GetStatus() to get the error type.
28// // Maybe return "not installed".
29// ...
30// }
31class HandwritingLibrary {
32 public:
Honglin Yu0c4760a2020-04-18 20:53:31 +100033 enum class Status {
34 kOk = 0,
35 kUninitialized = 1,
36 kLoadLibraryFailed = 2,
charleszhao17777f92020-04-23 12:53:11 +100037 kFunctionLookupFailed = 3,
38 kNotSupported = 4,
Honglin Yu0c4760a2020-04-18 20:53:31 +100039 };
40
41 ~HandwritingLibrary() = default;
42
Charles Zhaoc882eb02020-07-27 10:02:35 +100043 // Returns whether HandwritingLibrary is supported.
44 static constexpr bool IsHandwritingLibrarySupported() {
45 return (IsUseLibHandwritingEnabled() || IsUseLibHandwritingDlcEnabled()) &&
46 !IsAsan();
47 }
48
49 // Returns whether HandwritingLibrary is supported for unit tests.
50 static constexpr bool IsHandwritingLibraryUnitTestSupported() {
51 return IsUseLibHandwritingEnabled() && !IsAsan();
52 }
53
54 // Gets the singleton HandwritingLibrary.
Honglin Yu0c4760a2020-04-18 20:53:31 +100055 static HandwritingLibrary* GetInstance();
56
57 // Get whether the library is successfully initialized.
Andrew Moylan79b34a42020-07-08 11:13:11 +100058 // Initially, the status is `Status::kUninitialized` (this value should never
Honglin Yu0c4760a2020-04-18 20:53:31 +100059 // be returned).
Andrew Moylan79b34a42020-07-08 11:13:11 +100060 // If libhandwriting.so can not be loaded, return `kLoadLibraryFailed`. This
Honglin Yu0c4760a2020-04-18 20:53:31 +100061 // usually means on-device handwriting is not supported.
62 // If the functions can not be successfully looked up, return
Andrew Moylan79b34a42020-07-08 11:13:11 +100063 // `kFunctionLookupFailed`.
64 // Return `Status::kOk` if everything works fine.
Honglin Yu0c4760a2020-04-18 20:53:31 +100065 Status GetStatus() const;
66
67 // The following public member functions define the interface functions of
Andrew Moylan79b34a42020-07-08 11:13:11 +100068 // the libhandwriting.so library. Function `InitHandwritingRecognizerLibrary`
69 // and `DeleteHandwritingResultData` do not need interfaces because the client
Honglin Yu0c4760a2020-04-18 20:53:31 +100070 // won't call it.
71
72 // Creates and returns a handwriting recognizer which is needed for using the
73 // other interface. The memory is owned by the user and should be deleted
Andrew Moylan79b34a42020-07-08 11:13:11 +100074 // using `DestroyHandwritingRecognizer` after usage.
Honglin Yu0c4760a2020-04-18 20:53:31 +100075 HandwritingRecognizer CreateHandwritingRecognizer() const;
Charles Zhaoc882eb02020-07-27 10:02:35 +100076 // Load the models with `spec` stores the language, the path to the data files
77 // of the model (machine learning models, configurations etc.).
Honglin Yu0c4760a2020-04-18 20:53:31 +100078 // Returns true if HandwritingRecognizer is correctly loaded and
79 // initialized. Returns false otherwise.
80 bool LoadHandwritingRecognizer(
81 HandwritingRecognizer recognizer,
Charles Zhaoc882eb02020-07-27 10:02:35 +100082 chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr spec)
Honglin Yu0c4760a2020-04-18 20:53:31 +100083 const;
Andrew Moylan79b34a42020-07-08 11:13:11 +100084 // Sends the specified `request` to `recognizer`, if succeeds, `result` (which
Honglin Yu0c4760a2020-04-18 20:53:31 +100085 // should not be null) is populated with the recognition result.
86 // Returns true if succeeds, otherwise returns false.
87 bool RecognizeHandwriting(
88 HandwritingRecognizer recognizer,
89 const chrome_knowledge::HandwritingRecognizerRequest& request,
90 chrome_knowledge::HandwritingRecognizerResult* result) const;
91 // Destroys the handwriting recognizer created by
Andrew Moylan79b34a42020-07-08 11:13:11 +100092 // `CreateHandwritingRecognizer`. Must be called if the handwriting recognizer
Honglin Yu0c4760a2020-04-18 20:53:31 +100093 // will not be used anymore, otherwise there will be memory leak.
94 void DestroyHandwritingRecognizer(HandwritingRecognizer recognizer) const;
95
96 private:
97 friend class base::NoDestructor<HandwritingLibrary>;
Charles Zhaoc882eb02020-07-27 10:02:35 +100098 FRIEND_TEST(HandwritingLibraryTest, CanLoadLibrary);
Honglin Yu0c4760a2020-04-18 20:53:31 +100099
100 // Initialize the handwriting library.
Charles Zhaoc882eb02020-07-27 10:02:35 +1000101 explicit HandwritingLibrary();
102
103 // Currently HandwritingLibrary is supported only when the "sanitizer" is not
104 // enabled (see https://crbug.com/1082632).
105 static constexpr bool IsAsan() { return __has_feature(address_sanitizer); }
106
107 // Returns bool of use.ondevice_handwriting.
108 static constexpr bool IsUseLibHandwritingEnabled() {
109 return USE_ONDEVICE_HANDWRITING;
110 }
111
112 // Returns bool of use.ondevice_handwriting_dlc.
113 static constexpr bool IsUseLibHandwritingDlcEnabled() {
114 return USE_ONDEVICE_HANDWRITING_DLC;
115 }
Honglin Yu0c4760a2020-04-18 20:53:31 +1000116
117 base::Optional<base::ScopedNativeLibrary> library_;
118 Status status_;
119
120 // Store the interface function pointers.
121 // TODO(honglinyu) as pointed out by cjmcdonald@, we should group the pointers
Andrew Moylan79b34a42020-07-08 11:13:11 +1000122 // into a single `HandwritingInterface` struct and make it optional, i.e.,
Honglin Yu0c4760a2020-04-18 20:53:31 +1000123 // declaring something like |base::Optional<HandwritingInterface> interface_|.
124 CreateHandwritingRecognizerFn create_handwriting_recognizer_;
125 LoadHandwritingRecognizerFn load_handwriting_recognizer_;
126 RecognizeHandwritingFn recognize_handwriting_;
127 DeleteHandwritingResultDataFn delete_handwriting_result_data_;
128 DestroyHandwritingRecognizerFn destroy_handwriting_recognizer_;
129
130 DISALLOW_COPY_AND_ASSIGN(HandwritingLibrary);
131};
132
133} // namespace ml
134
135#endif // ML_HANDWRITING_H_