1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "knuckle_drawing_component.h"
17
18 #include <string>
19 #include "dlfcn.h"
20
21 #include "define_multimodal.h"
22 #include "mmi_log.h"
23 #include "timer_manager.h"
24
25 #undef MMI_LOG_TAG
26 #define MMI_LOG_TAG "KnuckleDrawingComponent"
27
28 namespace {
29 static const std::string KNUCKLE_DRAWING_LIB_PATH = "libmmi-knuckle.z.so";
30 constexpr int32_t UNLOAD_TIME_MS = 2 * 60 * 1000; // 2 minutes
31 constexpr int32_t CHECK_INTERVAL_MS = 20 * 1000; // check every 20 seconds
32 constexpr int32_t CHECK_COUNT = -1;
33 } // namespace
34
35 namespace OHOS {
36 namespace MMI {
GetInstance()37 KnuckleDrawingComponent &KnuckleDrawingComponent::GetInstance()
38 {
39 static KnuckleDrawingComponent instance;
40 return instance;
41 }
42
Draw(const OLD::DisplayInfo & displayInfo,const std::shared_ptr<PointerEvent> & touchEvent)43 void KnuckleDrawingComponent::Draw(const OLD::DisplayInfo& displayInfo,
44 const std::shared_ptr<PointerEvent> &touchEvent)
45 {
46 lastCallTime_ = std::chrono::steady_clock::now();
47 IKnuckleDrawing *impl = Load();
48 CHKPRV(impl, "load knuckle lib fail");
49 impl->Draw(displayInfo, touchEvent);
50 }
51
SetMultiWindowScreenId(uint64_t screenId,uint64_t displayNodeScreenId)52 void KnuckleDrawingComponent::SetMultiWindowScreenId(uint64_t screenId, uint64_t displayNodeScreenId)
53 {
54 lastCallTime_ = std::chrono::steady_clock::now();
55 IKnuckleDrawing *impl = Load();
56 CHKPRV(impl, "load knuckle lib fail");
57 impl->SetMultiWindowScreenId(screenId, displayNodeScreenId);
58 }
59
~KnuckleDrawingComponent()60 KnuckleDrawingComponent::~KnuckleDrawingComponent()
61 {
62 Unload();
63 }
64
Load()65 IKnuckleDrawing *KnuckleDrawingComponent::Load()
66 {
67 if (impl_ != nullptr) {
68 return impl_;
69 }
70
71 if (!LoadKnuckleSharedLibrary()) {
72 MMI_HILOGE("load knuckle shared library fail");
73 return nullptr;
74 }
75
76 impl_ = create_();
77 if (impl_ == nullptr) {
78 MMI_HILOGE("create KnuckleDrawing fail");
79 Unload();
80 return nullptr;
81 }
82 impl_->RegisterAddTimer([this]
83 (int32_t intervalMs, int32_t repeatCount, std::function<void()> callback, const std::string &name) -> int32_t {
84 return TimerMgr->AddTimer(intervalMs, repeatCount, callback, name);
85 });
86 if (timerId_ > 0) {
87 TimerMgr->RemoveTimer(timerId_);
88 }
89 timerId_ = TimerMgr->AddLongTimer(CHECK_INTERVAL_MS, CHECK_COUNT, [this] {
90 auto idleTime = std::chrono::duration_cast<std::chrono::milliseconds>(
91 std::chrono::steady_clock::now() - lastCallTime_).count();
92 if (idleTime >= UNLOAD_TIME_MS) {
93 KnuckleDrawingComponent::GetInstance().Unload();
94 }
95 }, "KnuckleDrawingComponent-Unload");
96 if (timerId_ < 0) {
97 MMI_HILOGE("Add timer for unloading knuckle library fail");
98 Unload();
99 return nullptr;
100 }
101 MMI_HILOGD("success to Load KnuckleDrawing");
102 return impl_;
103 }
104
LoadKnuckleSharedLibrary()105 bool KnuckleDrawingComponent::LoadKnuckleSharedLibrary()
106 {
107 if (handle_ == nullptr) {
108 handle_ = ::dlopen(KNUCKLE_DRAWING_LIB_PATH.c_str(), RTLD_LAZY);
109 if (handle_ == nullptr) {
110 MMI_HILOGE("%{public}s dlopen fail", KNUCKLE_DRAWING_LIB_PATH.c_str());
111 return false;
112 }
113 }
114
115 create_ = reinterpret_cast<GetKnuckleDrawingFunc>(::dlsym(handle_, "GetKnuckleDrawing"));
116 if (create_ == nullptr) {
117 MMI_HILOGE("dlsym GetKnuckleDrawing fail");
118 ::dlclose(handle_);
119 return false;
120 }
121
122 destroy_ = reinterpret_cast<DestroyKnuckleDrawingFunc>(::dlsym(handle_, "DestroyKnuckleDrawing"));
123 if (destroy_ == nullptr) {
124 MMI_HILOGE("dlsym DestroyKnuckleDrawing fail");
125 create_ = nullptr;
126 ::dlclose(handle_);
127 return false;
128 }
129 MMI_HILOGD("success to load knuckle shared library");
130 return true;
131 }
132
Unload()133 void KnuckleDrawingComponent::Unload()
134 {
135 TimerMgr->RemoveTimer(timerId_);
136 timerId_ = -1;
137
138 create_ = nullptr;
139 if (destroy_ != nullptr && impl_ != nullptr) {
140 destroy_(impl_);
141 }
142 destroy_ = nullptr;
143 impl_ = nullptr;
144
145 if (handle_ != nullptr) {
146 ::dlclose(handle_);
147 handle_ = nullptr;
148 }
149 MMI_HILOGD("success to Unload KnuckleDrawing");
150 }
151 } // namespace MMI
152 } // namespace OHOS
153