• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "napi_accessibility_utils.h"
17 #include "napi_accessibility_config_observer.h"
18 
19 #include <uv.h>
20 
21 #include "hilog_wrapper.h"
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::Accessibility;
27 using namespace OHOS::AccessibilityNapi;
28 using namespace OHOS::AccessibilityConfig;
29 
OnConfigChanged(const ConfigValue & value)30 void NAccessibilityConfigObserver::OnConfigChanged(const ConfigValue &value)
31 {
32     HILOG_INFO("id = [%{public}d]", static_cast<int32_t>(configId_));
33     switch (configId_) {
34         case CONFIG_CAPTION_STATE:
35             NotifyStateChanged2JS(value.captionState);
36             break;
37         case CONFIG_CAPTION_STYLE:
38             NotifyPropertyChanged2JS(value.captionStyle);
39             break;
40         case CONFIG_SCREEN_MAGNIFICATION:
41             NotifyStateChanged2JS(value.screenMagnifier);
42             break;
43         case CONFIG_MOUSE_KEY:
44             NotifyStateChanged2JS(value.mouseKey);
45             break;
46         case CONFIG_SHORT_KEY:
47             NotifyStateChanged2JS(value.shortkey);
48             break;
49         case CONFIG_SHORT_KEY_TARGET:
50             NotifyStringChanged2JS(value.shortkey_target);
51             break;
52         case CONFIG_MOUSE_AUTOCLICK:
53             NotifyIntChanged2JS(value.mouseAutoClick);
54             break;
55         case CONFIG_DALTONIZATION_COLOR_FILTER:
56             NotifyStringChanged2JS(ConvertDaltonizationTypeToString(value.daltonizationColorFilter));
57             break;
58         case CONFIG_CONTENT_TIMEOUT:
59             NotifyIntChanged2JS(static_cast<int32_t>(value.contentTimeout));
60             break;
61         case CONFIG_BRIGHTNESS_DISCOUNT:
62             NotifyFloatChanged2JS(value.brightnessDiscount);
63             break;
64         case CONFIG_AUDIO_BALANCE:
65             NotifyFloatChanged2JS(value.audioBalance);
66             break;
67         case CONFIG_HIGH_CONTRAST_TEXT:
68             NotifyStateChanged2JS(value.highContrastText);
69             break;
70         case CONFIG_INVERT_COLOR:
71             NotifyStateChanged2JS(value.invertColor);
72             break;
73         case CONFIG_AUDIO_MONO:
74             NotifyStateChanged2JS(value.audioMono);
75             break;
76         case CONFIG_ANIMATION_OFF:
77             NotifyStateChanged2JS(value.animationOff);
78             break;
79         default:
80             break;
81     }
82 }
83 
NotifyStateChanged2JS(bool enabled)84 void NAccessibilityConfigObserver::NotifyStateChanged2JS(bool enabled)
85 {
86     HILOG_INFO("id = [%{public}d] enabled = [%{public}s]", static_cast<int32_t>(configId_), enabled ? "true" : "false");
87 
88     StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo();
89     if (!callbackInfo) {
90         HILOG_ERROR("Failed to create callbackInfo.");
91         return;
92     }
93     callbackInfo->state_ = enabled;
94     callbackInfo->env_ = env_;
95     callbackInfo->ref_ = handlerRef_;
96     uv_work_t *work = new(std::nothrow) uv_work_t;
97     if (!work) {
98         HILOG_ERROR("Failed to create work.");
99         delete callbackInfo;
100         callbackInfo = nullptr;
101         return;
102     }
103     work->data = static_cast<void*>(callbackInfo);
104 
105     uv_loop_s *loop = nullptr;
106     napi_get_uv_event_loop(env_, &loop);
107     int ret = uv_queue_work(loop, work, [](uv_work_t *work) {},
108         [](uv_work_t *work, int status) {
109             StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data);
110             napi_value jsEvent;
111             napi_create_object(callbackInfo->env_, &jsEvent);
112             napi_get_boolean(callbackInfo->env_, callbackInfo->state_, &jsEvent);
113 
114             napi_value handler = nullptr;
115             napi_value callResult = nullptr;
116             napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler);
117             napi_value undefined = nullptr;
118             napi_get_undefined(callbackInfo->env_, &undefined);
119             napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult);
120             int32_t result;
121             napi_get_value_int32(callbackInfo->env_, callResult, &result);
122             HILOG_INFO("NotifyStateChangedJS napi_call_function result[%{public}d]", result);
123             delete callbackInfo;
124             callbackInfo = nullptr;
125             delete work;
126             work = nullptr;
127         });
128     if (ret != 0) {
129         HILOG_ERROR("Failed to execute NotifyStateChanged2JS work queue");
130         delete callbackInfo;
131         callbackInfo = nullptr;
132         delete work;
133         work = nullptr;
134     }
135 }
136 
NotifyPropertyChanged2JS(const OHOS::AccessibilityConfig::CaptionProperty & caption)137 void NAccessibilityConfigObserver::NotifyPropertyChanged2JS(const OHOS::AccessibilityConfig::CaptionProperty &caption)
138 {
139     HILOG_INFO("id = [%{public}d]", static_cast<int32_t>(configId_));
140 
141     CaptionCallbackInfo *callbackInfo = new(std::nothrow) CaptionCallbackInfo();
142     if (!callbackInfo) {
143         HILOG_ERROR("Failed to create callbackInfo.");
144         return;
145     }
146     callbackInfo->caption_ = caption;
147     callbackInfo->env_ = env_;
148     callbackInfo->ref_ = handlerRef_;
149     uv_work_t *work = new(std::nothrow) uv_work_t;
150     if (!work) {
151         HILOG_ERROR("Failed to create work.");
152         delete callbackInfo;
153         callbackInfo = nullptr;
154         return;
155     }
156     work->data = static_cast<void*>(callbackInfo);
157 
158     uv_loop_s *loop = nullptr;
159     napi_get_uv_event_loop(env_, &loop);
160     int ret = uv_queue_work(loop, work, [](uv_work_t *work) {},
161         [](uv_work_t *work, int status) {
162             CaptionCallbackInfo *callbackInfo = static_cast<CaptionCallbackInfo*>(work->data);
163             napi_value jsEvent;
164             napi_create_object(callbackInfo->env_, &jsEvent);
165             ConvertCaptionPropertyToJS(callbackInfo->env_, jsEvent, callbackInfo->caption_);
166 
167             napi_value handler = nullptr;
168             napi_value callResult = nullptr;
169             napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler);
170             napi_value undefined = nullptr;
171             napi_get_undefined(callbackInfo->env_, &undefined);
172             napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult);
173             int32_t result;
174             napi_get_value_int32(callbackInfo->env_, callResult, &result);
175             HILOG_INFO("NotifyPropertyChangedJS napi_call_function result[%{public}d]", result);
176             delete callbackInfo;
177             callbackInfo = nullptr;
178             delete work;
179             work = nullptr;
180         });
181     if (ret != 0) {
182         HILOG_ERROR("Failed to execute NotifyPropertyChanged2JS work queue");
183         delete callbackInfo;
184         callbackInfo = nullptr;
185         delete work;
186         work = nullptr;
187     }
188 }
189 
NotifyStringChanged2JS(const std::string & value)190 void NAccessibilityConfigObserver::NotifyStringChanged2JS(const std::string& value)
191 {
192     HILOG_INFO("value = [%{public}s]", value.c_str());
193 
194     StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo();
195     if (!callbackInfo) {
196         HILOG_ERROR("Failed to create callbackInfo.");
197         return;
198     }
199     callbackInfo->stringValue_ = value;
200     callbackInfo->env_ = env_;
201     callbackInfo->ref_ = handlerRef_;
202     uv_work_t *work = new(std::nothrow) uv_work_t;
203     if (!work) {
204         HILOG_ERROR("Failed to create work.");
205         delete callbackInfo;
206         callbackInfo = nullptr;
207         return;
208     }
209     work->data = static_cast<void*>(callbackInfo);
210 
211     uv_loop_s *loop = nullptr;
212     napi_get_uv_event_loop(env_, &loop);
213     int ret = uv_queue_work(loop, work, [](uv_work_t *work) {},
214         [](uv_work_t *work, int status) {
215             StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data);
216             napi_value jsEvent;
217             napi_create_string_utf8(callbackInfo->env_, callbackInfo->stringValue_.c_str(),
218                 callbackInfo->stringValue_.length(), &jsEvent);
219             napi_value handler = nullptr;
220             napi_value callResult = nullptr;
221             napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler);
222             napi_value undefined = nullptr;
223             napi_get_undefined(callbackInfo->env_, &undefined);
224             napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult);
225             size_t result;
226             const uint32_t BUF_SIZE = 1024;
227             char buf[BUF_SIZE] = {0};
228             napi_get_value_string_utf8(callbackInfo->env_, callResult, buf, BUF_SIZE, &result);
229             HILOG_INFO("NotifyStringChanged2JSInner napi_call_function result[%{public}zu]", result);
230             delete callbackInfo;
231             callbackInfo = nullptr;
232             delete work;
233             work = nullptr;
234         });
235     if (ret != 0) {
236         HILOG_ERROR("Failed to execute NotifyStringChanged2JS work queue");
237         delete callbackInfo;
238         callbackInfo = nullptr;
239         delete work;
240         work = nullptr;
241     }
242 }
243 
NotifyIntChanged2JS(int32_t value)244 void NAccessibilityConfigObserver::NotifyIntChanged2JS(int32_t value)
245 {
246     HILOG_INFO("id = [%{public}d] value = [%{public}d]", static_cast<int32_t>(configId_), value);
247 
248     StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo();
249     if (!callbackInfo) {
250         HILOG_ERROR("Failed to create callbackInfo.");
251         return;
252     }
253     callbackInfo->int32Value_ = value;
254     callbackInfo->env_ = env_;
255     callbackInfo->ref_ = handlerRef_;
256     uv_work_t *work = new(std::nothrow) uv_work_t;
257     if (!work) {
258         HILOG_ERROR("Failed to create work.");
259         delete callbackInfo;
260         callbackInfo = nullptr;
261         return;
262     }
263     work->data = static_cast<void*>(callbackInfo);
264 
265     uv_loop_s *loop = nullptr;
266     napi_get_uv_event_loop(env_, &loop);
267     int ret = uv_queue_work(
268         loop,
269         work,
270         [](uv_work_t *work) {},
271         [](uv_work_t *work, int status) {
272             StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data);
273             napi_value jsEvent;
274             napi_create_int32(callbackInfo->env_, callbackInfo->int32Value_, &jsEvent);
275 
276             napi_value handler = nullptr;
277             napi_value callResult = nullptr;
278             napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler);
279             napi_value undefined = nullptr;
280             napi_get_undefined(callbackInfo->env_, &undefined);
281             napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult);
282             int32_t result;
283             napi_get_value_int32(callbackInfo->env_, callResult, &result);
284             HILOG_INFO("NotifyIntChanged2JSInner napi_call_function result[%{public}d]", result);
285             delete callbackInfo;
286             callbackInfo = nullptr;
287             delete work;
288             work = nullptr;
289         });
290     if (ret != 0) {
291         HILOG_ERROR("Failed to execute NotifyIntChanged2JS work queue");
292         delete callbackInfo;
293         callbackInfo = nullptr;
294         delete work;
295         work = nullptr;
296     }
297 }
298 
NotifyUintChanged2JS(uint32_t value)299 void NAccessibilityConfigObserver::NotifyUintChanged2JS(uint32_t value)
300 {
301     HILOG_INFO("id = [%{public}d] value = [%{public}u]", static_cast<int32_t>(configId_), value);
302 
303     StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo();
304     if (!callbackInfo) {
305         HILOG_ERROR("Failed to create callbackInfo.");
306         return;
307     }
308     callbackInfo->uint32Value_ = value;
309     callbackInfo->env_ = env_;
310     callbackInfo->ref_ = handlerRef_;
311     uv_work_t *work = new(std::nothrow) uv_work_t;
312     if (!work) {
313         HILOG_ERROR("Failed to create work.");
314         delete callbackInfo;
315         callbackInfo = nullptr;
316         return;
317     }
318     work->data = static_cast<void*>(callbackInfo);
319 
320     uv_loop_s *loop = nullptr;
321     napi_get_uv_event_loop(env_, &loop);
322     int ret = uv_queue_work(
323         loop,
324         work,
325         [](uv_work_t *work) {},
326         [](uv_work_t *work, int status) {
327             StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data);
328             napi_value jsEvent;
329             napi_create_uint32(callbackInfo->env_, callbackInfo->uint32Value_, &jsEvent);
330 
331             napi_value handler = nullptr;
332             napi_value callResult = nullptr;
333             napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler);
334             napi_value undefined = nullptr;
335             napi_get_undefined(callbackInfo->env_, &undefined);
336             napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult);
337             uint32_t result;
338             napi_get_value_uint32(callbackInfo->env_, callResult, &result);
339             HILOG_INFO("NotifyUintChanged2JSInner napi_call_function result[%{public}d]", result);
340             delete callbackInfo;
341             callbackInfo = nullptr;
342             delete work;
343             work = nullptr;
344         });
345     if (ret != 0) {
346         HILOG_ERROR("Failed to execute NotifyUintChanged2JS work queue");
347         delete callbackInfo;
348         callbackInfo = nullptr;
349         delete work;
350         work = nullptr;
351     }
352 }
353 
NotifyFloatChanged2JS(float value)354 void NAccessibilityConfigObserver::NotifyFloatChanged2JS(float value)
355 {
356     HILOG_INFO("id = [%{public}d] value = [%{public}f]", static_cast<int32_t>(configId_), value);
357 
358     StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo();
359     if (!callbackInfo) {
360         HILOG_ERROR("Failed to create callbackInfo.");
361         return;
362     }
363     callbackInfo->floatValue_ = value;
364     callbackInfo->env_ = env_;
365     callbackInfo->ref_ = handlerRef_;
366     uv_work_t *work = new(std::nothrow) uv_work_t;
367     if (!work) {
368         HILOG_ERROR("Failed to create work.");
369         delete callbackInfo;
370         callbackInfo = nullptr;
371         return;
372     }
373     work->data = static_cast<void*>(callbackInfo);
374 
375     uv_loop_s *loop = nullptr;
376     napi_get_uv_event_loop(env_, &loop);
377     int ret = uv_queue_work(
378         loop,
379         work,
380         [](uv_work_t *work) {},
381         [](uv_work_t *work, int status) {
382             StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data);
383             napi_value jsEvent;
384             napi_create_double(callbackInfo->env_, double(callbackInfo->floatValue_), &jsEvent);
385 
386             napi_value handler = nullptr;
387             napi_value callResult = nullptr;
388             napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler);
389             napi_value undefined = nullptr;
390             napi_get_undefined(callbackInfo->env_, &undefined);
391             napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult);
392             int32_t result;
393             napi_get_value_int32(callbackInfo->env_, callResult, &result);
394             HILOG_INFO("NotifyFloatChanged2JSInner napi_call_function result[%{public}d]", result);
395             delete callbackInfo;
396             callbackInfo = nullptr;
397             delete work;
398             work = nullptr;
399         });
400     if (ret != 0) {
401         HILOG_ERROR("Failed to execute NotifyFloatChanged2JS work queue");
402         delete callbackInfo;
403         callbackInfo = nullptr;
404         delete work;
405         work = nullptr;
406     }
407 }
408 
SubscribeToFramework()409 void NAccessibilityConfigObserverImpl::SubscribeToFramework()
410 {
411     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
412     for (int32_t index = 0; index < static_cast<int32_t>(CONFIG_ID_MAX); index ++) {
413         instance.SubscribeConfigObserver(static_cast<CONFIG_ID>(index), shared_from_this(), false);
414     }
415 }
416 
OnConfigChanged(const OHOS::AccessibilityConfig::CONFIG_ID id,const OHOS::AccessibilityConfig::ConfigValue & value)417 void NAccessibilityConfigObserverImpl::OnConfigChanged(
418     const OHOS::AccessibilityConfig::CONFIG_ID id, const OHOS::AccessibilityConfig::ConfigValue& value)
419 {
420     HILOG_INFO();
421     std::lock_guard<std::mutex> lock(mutex_);
422     for (auto &observer : observers_) {
423         if (observer && observer->configId_ == id) {
424             observer->OnConfigChanged(value);
425         }
426     }
427 }
428 
SubscribeObserver(napi_env env,OHOS::AccessibilityConfig::CONFIG_ID id,napi_value observer)429 void NAccessibilityConfigObserverImpl::SubscribeObserver(napi_env env,
430     OHOS::AccessibilityConfig::CONFIG_ID id, napi_value observer)
431 {
432     HILOG_INFO();
433     std::lock_guard<std::mutex> lock(mutex_);
434     for (auto iter = observers_.begin(); iter != observers_.end();) {
435         if (CheckObserverEqual(env, observer, (*iter)->env_, (*iter)->handlerRef_)) {
436             HILOG_DEBUG("Observer exist");
437             return;
438         } else {
439             iter++;
440         }
441     }
442 
443     napi_ref handler = nullptr;
444     napi_create_reference(env, observer, 1, &handler);
445     std::shared_ptr<NAccessibilityConfigObserver> observerPtr =
446         std::make_shared<NAccessibilityConfigObserver>(env, handler, id);
447 
448     observers_.emplace_back(observerPtr);
449 }
450 
UnsubscribeObserver(napi_env env,OHOS::AccessibilityConfig::CONFIG_ID id,napi_value observer)451 void NAccessibilityConfigObserverImpl::UnsubscribeObserver(napi_env env,
452     OHOS::AccessibilityConfig::CONFIG_ID id, napi_value observer)
453 {
454     HILOG_INFO();
455     std::lock_guard<std::mutex> lock(mutex_);
456     for (auto iter = observers_.begin(); iter != observers_.end();) {
457         if ((*iter)->configId_ == id) {
458             if (CheckObserverEqual(env, observer, (*iter)->env_, (*iter)->handlerRef_)) {
459                 observers_.erase(iter);
460                 return;
461             } else {
462                 iter++;
463             }
464         } else {
465             iter++;
466         }
467     }
468 }
469 
UnsubscribeObservers(OHOS::AccessibilityConfig::CONFIG_ID id)470 void NAccessibilityConfigObserverImpl::UnsubscribeObservers(OHOS::AccessibilityConfig::CONFIG_ID id)
471 {
472     HILOG_INFO();
473     std::lock_guard<std::mutex> lock(mutex_);
474     for (auto iter = observers_.begin(); iter != observers_.end();) {
475         if ((*iter)->configId_ == id) {
476             iter = observers_.erase(iter);
477         } else {
478             iter++;
479         }
480     }
481 }