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