• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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