1 /*
2 * Copyright (c) 2023 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 "js_drag_manager.h"
17
18 #include "devicestatus_define.h"
19 #include "interaction_manager.h"
20 #include "napi_constants.h"
21 #include "util_napi.h"
22
23 #undef LOG_TAG
24 #define LOG_TAG "JsDragManager"
25
26 namespace OHOS {
27 namespace Msdp {
28 namespace DeviceStatus {
29
ResetEnv()30 void JsDragManager::ResetEnv()
31 {
32 CALL_INFO_TRACE;
33 std::lock_guard<std::mutex> guard(mutex_);
34 listeners_.clear();
35 }
36
IsSameHandle(napi_env env,napi_value handle,napi_ref ref)37 bool JsDragManager::IsSameHandle(napi_env env, napi_value handle, napi_ref ref)
38 {
39 CALL_INFO_TRACE;
40 napi_handle_scope scope = nullptr;
41 napi_open_handle_scope(env, &scope);
42 CHKPF(scope);
43 napi_value handlerTemp = nullptr;
44 CHKRF_SCOPE(env, napi_get_reference_value(env, ref, &handlerTemp), GET_REFERENCE_VALUE, scope);
45 bool isEqual = false;
46 CHKRF_SCOPE(env, napi_strict_equals(env, handle, handlerTemp, &isEqual), STRICT_EQUALS, scope);
47 napi_close_handle_scope(env, scope);
48 return isEqual;
49 }
50
GetDataSummary(napi_env env)51 napi_value JsDragManager::GetDataSummary(napi_env env)
52 {
53 CALL_INFO_TRACE;
54 napi_value arr = nullptr;
55 CHKRP(napi_create_array(env, &arr), CREATE_ARRAY);
56 std::map<std::string, int64_t> summarys;
57 if (INTERACTION_MGR->GetDragSummary(summarys, true) != RET_OK) {
58 FI_HILOGE("Failed to GetDragSummary");
59 return arr;
60 }
61 uint32_t index = 0;
62 for (const auto &summary : summarys) {
63 napi_value dataType = nullptr;
64 CHKRP(napi_create_string_utf8(env, summary.first.c_str(), NAPI_AUTO_LENGTH, &dataType), CREATE_STRING_UTF8);
65 napi_value dataSize = nullptr;
66 CHKRP(napi_create_int64(env, summary.second, &dataSize), CREATE_INT64);
67 napi_value object = nullptr;
68 CHKRP(napi_create_object(env, &object), CREATE_OBJECT);
69 CHKRP(napi_set_named_property(env, object, "dataType", dataType), SET_NAMED_PROPERTY);
70 CHKRP(napi_set_named_property(env, object, "dataSize", dataSize), SET_NAMED_PROPERTY);
71 CHKRP(napi_set_element(env, arr, index, object), SET_ELEMENT);
72 ++index;
73 }
74 return arr;
75 }
76
RegisterListener(napi_env env,napi_value handle)77 void JsDragManager::RegisterListener(napi_env env, napi_value handle)
78 {
79 CALL_INFO_TRACE;
80 std::lock_guard<std::mutex> guard(mutex_);
81 for (const auto &item : listeners_) {
82 CHKPC(item);
83 if (item->env == env && IsSameHandle(env, handle, item->ref)) {
84 FI_HILOGE("The handle already exists");
85 return;
86 }
87 }
88 napi_ref ref = nullptr;
89 CHKRV(napi_create_reference(env, handle, 1, &ref), CREATE_REFERENCE);
90 sptr<CallbackInfo> monitor = new (std::nothrow) CallbackInfo();
91 CHKPV(monitor);
92 monitor->env = env;
93 monitor->ref = ref;
94 listeners_.push_back(std::move(monitor));
95 if (!hasRegistered_) {
96 hasRegistered_ = true;
97 INTERACTION_MGR->AddDraglistener(shared_from_this(), true);
98 }
99 }
100
UnregisterListener(napi_env env,napi_value handle)101 void JsDragManager::UnregisterListener(napi_env env, napi_value handle)
102 {
103 CALL_INFO_TRACE;
104 std::lock_guard<std::mutex> guard(mutex_);
105 if (listeners_.empty()) {
106 FI_HILOGE("The listener list is empty");
107 return;
108 }
109 for (auto iter = listeners_.begin(); iter != listeners_.end();) {
110 if (handle == nullptr) {
111 RELEASE_CALLBACKINFO((*iter)->env, (*iter)->ref);
112 iter = listeners_.erase(iter);
113 } else {
114 if ((*iter)->env == env && IsSameHandle(env, handle, (*iter)->ref)) {
115 FI_HILOGD("Removing monitor successfully");
116 RELEASE_CALLBACKINFO((*iter)->env, (*iter)->ref);
117 iter = listeners_.erase(iter);
118 break;
119 }
120 ++iter;
121 }
122 }
123 if (hasRegistered_ && listeners_.empty()) {
124 hasRegistered_ = false;
125 INTERACTION_MGR->RemoveDraglistener(shared_from_this(), true);
126 }
127 }
128
OnDragMessage(DragState state)129 void JsDragManager::OnDragMessage(DragState state)
130 {
131 CALL_DEBUG_ENTER;
132 std::lock_guard<std::mutex> guard(mutex_);
133 if (listeners_.empty()) {
134 FI_HILOGE("The listener list is empty");
135 return;
136 }
137 for (auto &item : listeners_) {
138 CHKPC(item);
139 CHKPC(item->env);
140 uv_loop_s* loop = nullptr;
141 CHKRV(napi_get_uv_event_loop(item->env, &loop), GET_UV_EVENT_LOOP);
142 uv_work_t* work = new (std::nothrow) uv_work_t;
143 CHKPV(work);
144 item->state = state;
145 item->IncStrongRef(nullptr);
146 work->data = item.GetRefPtr();
147 int32_t result = uv_queue_work_with_qos(loop, work, [](uv_work_t* work) {}, CallDragMsg, uv_qos_default);
148 if (result != 0) {
149 FI_HILOGE("uv_queue_work_with_qos failed");
150 item->DecStrongRef(nullptr);
151 DeletePtr<uv_work_t*>(work);
152 }
153 }
154 }
155
CallDragMsg(uv_work_t * work,int32_t status)156 void JsDragManager::CallDragMsg(uv_work_t *work, int32_t status)
157 {
158 CALL_DEBUG_ENTER;
159 CHKPV(work);
160 if (work->data == nullptr) {
161 DeletePtr<uv_work_t*>(work);
162 FI_HILOGE("Check data is nullptr");
163 return;
164 }
165 sptr<CallbackInfo> temp(static_cast<CallbackInfo*>(work->data));
166 DeletePtr<uv_work_t*>(work);
167 temp->DecStrongRef(nullptr);
168 std::lock_guard<std::mutex> guard(mutex_);
169 if (listeners_.empty()) {
170 FI_HILOGE("The listener list is empty");
171 return;
172 }
173 for (const auto &item : listeners_) {
174 CHKPC(item->env);
175 if (item->ref != temp->ref) {
176 continue;
177 }
178 napi_handle_scope scope = nullptr;
179 napi_open_handle_scope(item->env, &scope);
180 CHKPC(scope);
181 napi_value stateMsg = nullptr;
182 CHKRV_SCOPE(item->env, napi_create_int32(item->env, static_cast<int32_t>(item->state), &stateMsg),
183 CREATE_INT32, scope);
184 napi_value handler = nullptr;
185 CHKRV_SCOPE(item->env, napi_get_reference_value(item->env, item->ref, &handler), GET_REFERENCE_VALUE, scope);
186 napi_value ret = nullptr;
187 CHKRV_SCOPE(item->env,
188 napi_call_function(item->env, nullptr, handler, 1, &stateMsg, &ret), CALL_FUNCTION, scope);
189 napi_close_handle_scope(item->env, scope);
190 }
191 }
192 } // namespace DeviceStatus
193 } // namespace Msdp
194 } // namespace OHOS
195