• 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 "ani_event_target.h"
17 #include "ani_util.h"
18 #include "bytrace_adapter.h"
19 
20 #undef MMI_LOG_TAG
21 #define MMI_LOG_TAG "AniEventTarget"
22 
23 namespace OHOS {
24 namespace MMI {
25 namespace {
26 constexpr int32_t INPUT_PARAMETER_MIDDLE { 2 };
27 
28 std::mutex mutex_;
29 const std::string ADD_EVENT = "add";
30 const std::string REMOVE_EVENT = "remove";
31 const std::string CHANGED_TYPE = "change";
32 constexpr int32_t ANI_SCOPE_SIZE = 16;
33 
34 struct DeviceItem {
35     int32_t deviceId;
36     void *item;
37 };
38 
39 } // namespace
40 
AniEventTarget()41 AniEventTarget::AniEventTarget()
42 {
43     CALL_DEBUG_ENTER;
44     std::lock_guard<std::mutex> lock(mutex_);
45     auto ret = devListener_.insert({ CHANGED_TYPE, std::vector<std::unique_ptr<AniUtil::CallbackInfo>>() });
46     CK(ret.second, VAL_NOT_EXP);
47     GetMainEventHandler();
48 }
49 
~AniEventTarget()50 AniEventTarget::~AniEventTarget()
51 {
52     CALL_DEBUG_ENTER;
53     handler_ = nullptr;
54 }
55 
GetMainEventHandler()56 void AniEventTarget::GetMainEventHandler()
57 {
58     CALL_DEBUG_ENTER;
59     auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
60     handler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
61 }
62 
EmitCallbackWork(ani_env * env,const std::shared_ptr<AniUtil::ReportData> & reportData,const std::string & type)63 bool AniEventTarget::EmitCallbackWork(ani_env *env, const std::shared_ptr<AniUtil::ReportData> &reportData,
64     const std::string &type)
65 {
66     CALL_DEBUG_ENTER;
67     AniLocalScopeGuard aniLocalScopeGuard(env, ANI_SCOPE_SIZE);
68     if (!aniLocalScopeGuard.IsStatusOK()) {
69         MMI_HILOGE("%{public}s: CreateLocalScope failed", __func__);
70         return false;
71     }
72     std::vector<ani_ref> args;
73     const char *nsName = "L@ohos/multimodalInput/inputDevice/inputDevice;";
74     const char *className = "LDeviceListenerImpl;";
75     auto obj = AniUtil::CreateAniObject(env, nsName, className);
76     if (obj == nullptr) {
77         MMI_HILOGE("%{public}s: CreateAniObject DeviceListenerObj failed", __func__);
78         return false;
79     }
80     ani_string stringValue = AniUtil::StdStringToANIString(env, type);
81     if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "type", stringValue)) {
82         MMI_HILOGE("%{public}s: Object_SetPropertyByName_Ref failed",  __func__);
83         return false;
84     }
85 
86     if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "deviceId", reportData->deviceId)) {
87         MMI_HILOGE("%{public}s: SetPropertyByName deviceId:%{public}d failed", __func__, reportData->deviceId);
88         return false;
89     }
90 
91     MMI_HILOGE("%{public}s: type:%{public}s, deviceId:%{public}d", __func__, type.c_str(), reportData->deviceId);
92     args.push_back(obj);
93 
94     auto fnObj = reinterpret_cast<ani_fn_object>(reportData->ref);
95     if (AniUtil::IsInstanceOf(env, "Lstd/core/Function1;", fnObj) == 0) {
96         MMI_HILOGE("%{public}s: fnObj is not instance Of function", __func__);
97         return false;
98     }
99 
100     ani_ref result;
101     if (ANI_OK != env->FunctionalObject_Call(fnObj, 1, args.data(), &result)) {
102         MMI_HILOGE("%{public}s: FunctionalObject_Call failed", __func__);
103         return false;
104     }
105     MMI_HILOGD("FunctionalObject_Call success");
106     return true;
107 }
108 
EmitAddedDeviceEvent(const std::shared_ptr<AniUtil::ReportData> & reportData)109 void AniEventTarget::EmitAddedDeviceEvent(const std::shared_ptr<AniUtil::ReportData> &reportData)
110 {
111     CALL_DEBUG_ENTER;
112     std::lock_guard<std::mutex> guard(mutex_);
113     auto addEvent = devListener_.find(CHANGED_TYPE);
114     if (addEvent == devListener_.end()) {
115         MMI_HILOGE("%{public}s: Find change event failed", __func__);
116         return;
117     }
118     CHKPV(reportData);
119     for (const auto &item : addEvent->second) {
120         CHKPC(item->env_);
121         if (item->callback_ != reportData->ref) {
122             continue;
123         }
124 
125         if (!EmitCallbackWork(item->env_, reportData, ADD_EVENT)) {
126             continue;
127         }
128 
129         BytraceAdapter::StartDevListener(ADD_EVENT, reportData->deviceId);
130         MMI_HILOGI("Report device change task, event type:%{public}s, deviceid:%{public}d",
131             ADD_EVENT.c_str(), reportData->deviceId);
132         BytraceAdapter::StopDevListener();
133     }
134 }
135 
EmitRemoveDeviceEvent(const std::shared_ptr<AniUtil::ReportData> & reportData)136 void AniEventTarget::EmitRemoveDeviceEvent(const std::shared_ptr<AniUtil::ReportData> &reportData)
137 {
138     CALL_DEBUG_ENTER;
139     std::lock_guard<std::mutex> guard(mutex_);
140     auto removeEvent = devListener_.find(CHANGED_TYPE);
141     if (removeEvent == devListener_.end()) {
142         MMI_HILOGE("%{public}s: Find change event failed", __func__);
143         return;
144     }
145     CHKPV(reportData);
146     for (const auto &item : removeEvent->second) {
147         CHKPC(item->env_);
148         if (item->callback_ != reportData->ref) {
149             continue;
150         }
151 
152         if (!EmitCallbackWork(item->env_, reportData, REMOVE_EVENT)) {
153             continue;
154         }
155 
156         BytraceAdapter::StartDevListener(REMOVE_EVENT, reportData->deviceId);
157         MMI_HILOGI("Report device change task, event type:%{public}s, deviceid:%{public}d",
158             REMOVE_EVENT.c_str(), reportData->deviceId);
159         BytraceAdapter::StopDevListener();
160     }
161 }
162 
PostMainThreadTask(const std::function<void ()> task)163 void AniEventTarget::PostMainThreadTask(const std::function<void()> task)
164 {
165     if (!handler_) {
166         auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
167         if (!runner) {
168             MMI_HILOGE("get main event runner failed!");
169             return;
170         }
171         handler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
172     }
173     bool ret = handler_->PostTask(task, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {});
174     MMI_HILOGI("%{public}s: PostTask %{public}s", __func__, (ret? "success" : "failed"));
175 }
176 
OnDeviceAdded(int32_t deviceId,const std::string & type)177 void AniEventTarget::OnDeviceAdded(int32_t deviceId, const std::string &type)
178 {
179     CALL_DEBUG_ENTER;
180     std::lock_guard<std::mutex> guard(mutex_);
181     auto changeEvent = devListener_.find(CHANGED_TYPE);
182     if (changeEvent == devListener_.end()) {
183         MMI_HILOGE("%{public}s: Find %{public}s failed", __func__, CHANGED_TYPE.c_str());
184         return;
185     }
186 
187     for (auto &item : changeEvent->second) {
188         CHKPC(item);
189         CHKPC(item->env_);
190         auto reportData = std::make_shared<AniUtil::ReportData>();
191         if (reportData == nullptr) {
192             MMI_HILOGE("%{public}s: Memory allocation failed", __func__);
193             return;
194         }
195         reportData->deviceId = deviceId;
196         reportData->ref = item->callback_;
197         auto task = [reportData, this] () { EmitAddedDeviceEvent(reportData); };
198         PostMainThreadTask(task);
199     }
200 }
201 
OnDeviceRemoved(int32_t deviceId,const std::string & type)202 void AniEventTarget::OnDeviceRemoved(int32_t deviceId, const std::string &type)
203 {
204     CALL_DEBUG_ENTER;
205     std::lock_guard<std::mutex> guard(mutex_);
206     auto changeEvent = devListener_.find(CHANGED_TYPE);
207     if (changeEvent == devListener_.end()) {
208         MMI_HILOGE("%{public}s: Find %{public}s failed", __func__, CHANGED_TYPE.c_str());
209         return;
210     }
211     for (auto &item : changeEvent->second) {
212         CHKPC(item);
213         CHKPC(item->env_);
214         std::shared_ptr<AniUtil::ReportData> reportData = std::make_shared<AniUtil::ReportData>();
215         if (reportData == nullptr) {
216             MMI_HILOGE("%{public}s: Memory allocation failed", __func__);
217             return;
218         }
219         reportData->deviceId = deviceId;
220         reportData->ref = item->callback_;
221         auto task = [reportData, this] () { EmitRemoveDeviceEvent(reportData); };
222         PostMainThreadTask(task);
223     }
224 }
225 
AddListener(ani_env * env,const std::string & type,ani_object handle)226 void AniEventTarget::AddListener(ani_env *env, const std::string &type, ani_object handle)
227 {
228     CALL_DEBUG_ENTER;
229     std::lock_guard<std::mutex> guard(mutex_);
230     auto it = devListener_.find(type);
231     if (it == devListener_.end()) {
232         MMI_HILOGE("%{public}s: Find %{public}s failed", __func__, type.c_str());
233         return;
234     }
235 
236     auto monitor = std::make_unique<AniUtil::CallbackInfo>();
237     monitor->env_ = env;
238     if (!monitor->SetCallback(handle)) {
239         return;
240     }
241 
242     for (const auto &iter : it->second) {
243         CHKPC(iter);
244         if (AniUtil::IsSameHandle(env, monitor->callback_, iter->env_, iter->callback_)) {
245             MMI_HILOGW("The handle already exists");
246             return;
247         }
248     }
249 
250     it->second.push_back(std::move(monitor));
251     if (!isListeningProcess_) {
252         isListeningProcess_ = true;
253         InputManager::GetInstance()->RegisterDevListener("change", shared_from_this());
254     }
255 }
256 
ResetEnv()257 void AniEventTarget::ResetEnv()
258 {
259     CALL_DEBUG_ENTER;
260     std::lock_guard<std::mutex> guard(mutex_);
261     devListener_.clear();
262     InputManager::GetInstance()->UnregisterDevListener("change", shared_from_this());
263 }
264 } // namespace MMI
265 } // namespace OHOS
266