/* * Copyright (C) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "accessibility_utils.h" #include "accessibility_config_observer.h" #include <uv.h> #include "hilog_wrapper.h" #include "napi/native_api.h" #include "napi/native_node_api.h" using namespace OHOS; using namespace OHOS::Accessibility; using namespace OHOS::AccessibilityNapi; using namespace OHOS::AccessibilityConfig; namespace OHOS { namespace Accessibility { namespace { constexpr int ROUND_STEP = 10; } napi_handle_scope TmpOpenScope(napi_env env) { napi_handle_scope scope = nullptr; NAPI_CALL(env, napi_open_handle_scope(env, &scope)); return scope; } } // namespace Accessibility } // namespace OHOS void NAccessibilityConfigObserver::OnConfigChangedExtra(const ConfigValue &value) { HILOG_INFO("id = [%{public}d]", static_cast<int32_t>(configId_)); if (configId_ == CONFIG_CONTENT_TIMEOUT) { NotifyIntChanged2JS(static_cast<int32_t>(value.contentTimeout)); } else if (configId_ == CONFIG_BRIGHTNESS_DISCOUNT) { NotifyDoubleChanged2JS(static_cast<double>(value.brightnessDiscount)); } else if (configId_ == CONFIG_AUDIO_BALANCE) { float audioBalance = value.audioBalance; double value = static_cast<double>(audioBalance); value = round(value * ROUND_STEP) / ROUND_STEP; NotifyDoubleChanged2JS(value); } else if (configId_ == CONFIG_HIGH_CONTRAST_TEXT) { NotifyStateChanged2JS(value.highContrastText); } else if (configId_ == CONFIG_DALTONIZATION_STATE) { NotifyStateChanged2JS(value.daltonizationState); } else if (configId_ == CONFIG_INVERT_COLOR) { NotifyStateChanged2JS(value.invertColor); } else if (configId_ == CONFIG_ANIMATION_OFF) { NotifyStateChanged2JS(value.animationOff); } else if (configId_ == CONFIG_AUDIO_MONO) { NotifyStateChanged2JS(value.audioMono); } else if (configId_ == CONIFG_CLICK_RESPONSE_TIME) { NotifyStringChanged2JS(ConvertClickResponseTimeTypeToString(value.clickResponseTime)); } else if (configId_ == CONFIG_IGNORE_REPEAT_CLICK_TIME) { NotifyStringChanged2JS(ConvertIgnoreRepeatClickTimeTypeToString(value.ignoreRepeatClickTime)); } else if (configId_ == CONFIG_IGNORE_REPEAT_CLICK_STATE) { NotifyStateChanged2JS(value.ignoreRepeatClickState); } } void NAccessibilityConfigObserver::OnConfigChanged(const ConfigValue &value) { HILOG_INFO("id = [%{public}d]", static_cast<int32_t>(configId_)); if (configId_ == CONFIG_CAPTION_STATE) { NotifyStateChanged2JS(value.captionState); } else if (configId_ == CONFIG_CAPTION_STYLE) { NotifyPropertyChanged2JS(value.captionStyle); } else if (configId_ == CONFIG_SCREEN_MAGNIFICATION) { NotifyStateChanged2JS(value.screenMagnifier); } else if (configId_ == CONFIG_MOUSE_KEY) { NotifyStateChanged2JS(value.mouseKey); } else if (configId_ == CONFIG_SHORT_KEY) { NotifyStateChanged2JS(value.shortkey); } else if (configId_ == CONFIG_SHORT_KEY_TARGET) { NotifyStringChanged2JS(value.shortkey_target); } else if (configId_ == CONFIG_SHORT_KEY_MULTI_TARGET) { NotifyStringVectorChanged2JS(value.shortkeyMultiTarget); } else if (configId_ == CONFIG_MOUSE_AUTOCLICK) { NotifyIntChanged2JS(value.mouseAutoClick); } else if (configId_ == CONFIG_DALTONIZATION_COLOR_FILTER) { OnDaltonizationColorFilterConfigChanged(); } else { OnConfigChangedExtra(value); } } void NAccessibilityConfigObserver::OnDaltonizationColorFilterConfigChanged() { auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance(); DALTONIZATION_TYPE type = Normal; RetError ret = instance.GetDaltonizationColorFilter(type); if (ret == RET_OK) { NotifyStringChanged2JS(ConvertDaltonizationTypeToString(type)); } else { NotifyStringChanged2JS(ConvertDaltonizationTypeToString(type)); HILOG_ERROR("get DaltonizationColorFilter failed: %{public}d", ret); } } int NAccessibilityConfigObserver::NotifyStateChanged(uv_work_t *work) { uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); if (loop == nullptr || work == nullptr) { HILOG_ERROR("loop or work is nullptr."); return RET_ERR_FAILED; } int ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) { StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data); napi_env env = callbackInfo->env_; auto closeScope = [env](napi_handle_scope scope) { napi_close_handle_scope(env, scope); }; std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes( OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope); napi_value jsEvent = nullptr; napi_create_object(callbackInfo->env_, &jsEvent); if (jsEvent == nullptr) { HILOG_ERROR("napi_create_object fail."); return; } napi_get_boolean(callbackInfo->env_, callbackInfo->state_, &jsEvent); napi_value handler = nullptr; napi_value callResult = nullptr; napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler); napi_value undefined = nullptr; napi_get_undefined(callbackInfo->env_, &undefined); napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult); int32_t result; napi_get_value_int32(callbackInfo->env_, callResult, &result); HILOG_INFO("NotifyStateChangedJS napi_call_function result[%{public}d]", result); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; }, uv_qos_default); return ret; } int NAccessibilityConfigObserver::NotifyPropertyChanged(uv_work_t *work) { uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); if (loop == nullptr || work == nullptr) { HILOG_ERROR("loop or work is nullptr."); return RET_ERR_FAILED; } int ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) { CaptionCallbackInfo *callbackInfo = static_cast<CaptionCallbackInfo*>(work->data); napi_env env = callbackInfo->env_; auto closeScope = [env](napi_handle_scope scope) { napi_close_handle_scope(env, scope); }; std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes( OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope); napi_value jsEvent = nullptr; napi_create_object(callbackInfo->env_, &jsEvent); if (jsEvent == nullptr) { HILOG_ERROR("napi_create_object fail."); return; } ConvertCaptionPropertyToJS(callbackInfo->env_, jsEvent, callbackInfo->caption_); napi_value handler = nullptr; napi_value callResult = nullptr; napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler); napi_value undefined = nullptr; napi_get_undefined(callbackInfo->env_, &undefined); napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult); int32_t result; napi_get_value_int32(callbackInfo->env_, callResult, &result); HILOG_INFO("NotifyPropertyChangedJS napi_call_function result[%{public}d]", result); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; }, uv_qos_default); return ret; } int NAccessibilityConfigObserver::NotifyStringChanged(uv_work_t *work) { uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); if (loop == nullptr || work == nullptr) { HILOG_ERROR("loop or work is nullptr."); return RET_ERR_FAILED; } int ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) { StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data); napi_env env = callbackInfo->env_; auto closeScope = [env](napi_handle_scope scope) { napi_close_handle_scope(env, scope); }; std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes( OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope); napi_value jsEvent = nullptr; napi_create_string_utf8(callbackInfo->env_, callbackInfo->stringValue_.c_str(), callbackInfo->stringValue_.length(), &jsEvent); napi_value handler = nullptr; napi_value callResult = nullptr; napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler); napi_value undefined = nullptr; napi_get_undefined(callbackInfo->env_, &undefined); napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult); size_t result; const uint32_t BUF_SIZE = 1024; char buf[BUF_SIZE] = {0}; napi_get_value_string_utf8(callbackInfo->env_, callResult, buf, BUF_SIZE, &result); HILOG_INFO("NotifyStringChanged2JSInner napi_call_function result[%{public}zu]", result); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; }, uv_qos_default); return ret; } int NAccessibilityConfigObserver::NotifyStringVectorChanged(uv_work_t *work) { uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); if (loop == nullptr || work == nullptr) { HILOG_ERROR("loop or work is nullptr."); return RET_ERR_FAILED; } int ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) { StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data); napi_env env = callbackInfo->env_; auto closeScope = [env](napi_handle_scope scope) { napi_close_handle_scope(env, scope); }; std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes( OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope); napi_value jsEvent = nullptr; napi_create_array(callbackInfo->env_, &jsEvent); ConvertStringVecToJS(callbackInfo->env_, jsEvent, callbackInfo->stringVector_); napi_value handler = nullptr; napi_value callResult = nullptr; napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler); napi_value undefined = nullptr; napi_get_undefined(callbackInfo->env_, &undefined); napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult); size_t result; const uint32_t BUF_SIZE = 1024; char buf[BUF_SIZE] = {0}; napi_get_value_string_utf8(callbackInfo->env_, callResult, buf, BUF_SIZE, &result); HILOG_DEBUG("NotifyStringVectorChanged napi_call_function result[%{public}zu]", result); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; }, uv_qos_default); return ret; } int NAccessibilityConfigObserver::NotifyIntChanged(uv_work_t *work) { uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); if (loop == nullptr || work == nullptr) { HILOG_ERROR("loop or work is nullptr."); return RET_ERR_FAILED; } int ret = uv_queue_work_with_qos( loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) { StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data); napi_env env = callbackInfo->env_; auto closeScope = [env](napi_handle_scope scope) { napi_close_handle_scope(env, scope); }; std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes( OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope); napi_value jsEvent = nullptr; napi_create_int32(callbackInfo->env_, callbackInfo->int32Value_, &jsEvent); napi_value handler = nullptr; napi_value callResult = nullptr; napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler); napi_value undefined = nullptr; napi_get_undefined(callbackInfo->env_, &undefined); napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult); int32_t result; napi_get_value_int32(callbackInfo->env_, callResult, &result); HILOG_INFO("NotifyIntChanged2JSInner napi_call_function result[%{public}d]", result); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; }, uv_qos_default); return ret; } int NAccessibilityConfigObserver::NotifyUintChanged(uv_work_t *work) { uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); if (loop == nullptr || work == nullptr) { HILOG_ERROR("loop or work is nullptr."); return RET_ERR_FAILED; } int ret = uv_queue_work_with_qos( loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) { StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data); napi_env env = callbackInfo->env_; auto closeScope = [env](napi_handle_scope scope) { napi_close_handle_scope(env, scope); }; std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes( OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope); napi_value jsEvent = nullptr; napi_create_uint32(callbackInfo->env_, callbackInfo->uint32Value_, &jsEvent); napi_value handler = nullptr; napi_value callResult = nullptr; napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler); napi_value undefined = nullptr; napi_get_undefined(callbackInfo->env_, &undefined); napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult); uint32_t result; napi_get_value_uint32(callbackInfo->env_, callResult, &result); HILOG_INFO("NotifyUintChanged2JSInner napi_call_function result[%{public}d]", result); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; }, uv_qos_default); return ret; } int NAccessibilityConfigObserver::NotifyDoubleChanged(uv_work_t *work) { uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); if (loop == nullptr || work == nullptr) { HILOG_ERROR("loop or work is nullptr."); return RET_ERR_FAILED; } int ret = uv_queue_work_with_qos( loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) { StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data); napi_env env = callbackInfo->env_; auto closeScope = [env](napi_handle_scope scope) { napi_close_handle_scope(env, scope); }; std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes( OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope); napi_value jsEvent = nullptr; napi_create_double(callbackInfo->env_, callbackInfo->doubleValue_, &jsEvent); napi_value handler = nullptr; napi_value callResult = nullptr; napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler); napi_value undefined = nullptr; napi_get_undefined(callbackInfo->env_, &undefined); napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult); int32_t result; napi_get_value_int32(callbackInfo->env_, callResult, &result); HILOG_INFO("NotifyDoubleChanged2JSInner napi_call_function result[%{public}d]", result); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; }, uv_qos_default); return ret; } void NAccessibilityConfigObserver::NotifyStateChanged2JS(bool enabled) { HILOG_INFO("id = [%{public}d] enabled = [%{public}s]", static_cast<int32_t>(configId_), enabled ? "true" : "false"); StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo(); if (callbackInfo == nullptr) { HILOG_ERROR("Failed to create callbackInfo."); return; } callbackInfo->state_ = enabled; callbackInfo->env_ = env_; callbackInfo->ref_ = handlerRef_; uv_work_t *work = new(std::nothrow) uv_work_t; if (!work) { HILOG_ERROR("NotifyStateChanged2JS Failed to create work."); delete callbackInfo; callbackInfo = nullptr; return; } work->data = static_cast<void*>(callbackInfo); int ret = NotifyStateChanged(work); if (ret != 0) { HILOG_ERROR("Failed to execute NotifyStateChanged2JS work queue"); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; } } void NAccessibilityConfigObserver::NotifyPropertyChanged2JS(const OHOS::AccessibilityConfig::CaptionProperty &caption) { HILOG_INFO("id = [%{public}d]", static_cast<int32_t>(configId_)); CaptionCallbackInfo *callbackInfo = new(std::nothrow) CaptionCallbackInfo(); if (callbackInfo == nullptr) { HILOG_ERROR("Failed to create callbackInfo."); return; } callbackInfo->caption_ = caption; callbackInfo->env_ = env_; callbackInfo->ref_ = handlerRef_; uv_work_t *work = new(std::nothrow) uv_work_t; if (!work) { HILOG_ERROR("NotifyPropertyChanged2JS Failed to create work."); delete callbackInfo; callbackInfo = nullptr; return; } work->data = static_cast<void*>(callbackInfo); int ret = NotifyPropertyChanged(work); if (ret != 0) { HILOG_ERROR("Failed to execute NotifyPropertyChanged2JS work queue"); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; } } void NAccessibilityConfigObserver::NotifyStringChanged2JS(const std::string& value) { HILOG_INFO("value = [%{public}s]", value.c_str()); StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo(); if (callbackInfo == nullptr) { HILOG_ERROR("Failed to create callbackInfo."); return; } callbackInfo->stringValue_ = value; callbackInfo->env_ = env_; callbackInfo->ref_ = handlerRef_; uv_work_t *work = new(std::nothrow) uv_work_t; if (!work) { HILOG_ERROR("NotifyStringChanged2JS Failed to create work."); delete callbackInfo; callbackInfo = nullptr; return; } work->data = static_cast<void*>(callbackInfo); int ret = NotifyStringChanged(work); if (ret != 0) { HILOG_ERROR("Failed to execute NotifyStringChanged2JS work queue"); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; } } void NAccessibilityConfigObserver::NotifyStringVectorChanged2JS(std::vector<std::string> value) { HILOG_DEBUG(); StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo(); if (callbackInfo == nullptr) { HILOG_ERROR("Failed to create callbackInfo."); return; } callbackInfo->stringVector_ = value; callbackInfo->env_ = env_; callbackInfo->ref_ = handlerRef_; uv_work_t *work = new(std::nothrow) uv_work_t; if (!work) { HILOG_ERROR("NotifyStringVectorChanged2JS Failed to create work."); delete callbackInfo; callbackInfo = nullptr; return; } work->data = static_cast<void*>(callbackInfo); int ret = NotifyStringVectorChanged(work); if (ret != 0) { HILOG_ERROR("Failed to execute NotifyStringVectorChanged2JS work queue"); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; } } void NAccessibilityConfigObserver::NotifyIntChanged2JS(int32_t value) { HILOG_INFO("id = [%{public}d] value = [%{public}d]", static_cast<int32_t>(configId_), value); StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo(); if (callbackInfo == nullptr) { HILOG_ERROR("Failed to create callbackInfo."); return; } callbackInfo->int32Value_ = value; callbackInfo->env_ = env_; callbackInfo->ref_ = handlerRef_; uv_work_t *work = new(std::nothrow) uv_work_t; if (!work) { HILOG_ERROR("NotifyIntChanged2JS Failed to create work."); delete callbackInfo; callbackInfo = nullptr; return; } work->data = static_cast<void*>(callbackInfo); int ret = NotifyIntChanged(work); if (ret != 0) { HILOG_ERROR("Failed to execute NotifyIntChanged2JS work queue"); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; } } void NAccessibilityConfigObserver::NotifyUintChanged2JS(uint32_t value) { HILOG_INFO("id = [%{public}d] value = [%{public}u]", static_cast<int32_t>(configId_), value); StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo(); if (callbackInfo == nullptr) { HILOG_ERROR("Failed to create callbackInfo."); return; } callbackInfo->uint32Value_ = value; callbackInfo->env_ = env_; callbackInfo->ref_ = handlerRef_; uv_work_t *work = new(std::nothrow) uv_work_t; if (!work) { HILOG_ERROR("NotifyUintChanged2JS Failed to create work."); delete callbackInfo; callbackInfo = nullptr; return; } work->data = static_cast<void*>(callbackInfo); int ret = NotifyUintChanged(work); if (ret != 0) { HILOG_ERROR("Failed to execute NotifyUintChanged2JS work queue"); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; } } void NAccessibilityConfigObserver::NotifyDoubleChanged2JS(double value) { HILOG_INFO("id = [%{public}d] value = [%{public}f]", static_cast<int32_t>(configId_), value); StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo(); if (callbackInfo == nullptr) { HILOG_ERROR("Failed to create callbackInfo."); return; } callbackInfo->doubleValue_ = value; callbackInfo->env_ = env_; callbackInfo->ref_ = handlerRef_; uv_work_t *work = new(std::nothrow) uv_work_t; if (!work) { HILOG_ERROR("NotifyDoubleChanged2JS Failed to create work."); delete callbackInfo; callbackInfo = nullptr; return; } work->data = static_cast<void*>(callbackInfo); int ret = NotifyDoubleChanged(work); if (ret != 0) { HILOG_ERROR("Failed to execute NotifyDoubleChanged2JS work queue"); delete callbackInfo; callbackInfo = nullptr; delete work; work = nullptr; } } void NAccessibilityConfigObserverImpl::SubscribeToFramework() { auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance(); for (int32_t index = 0; index < static_cast<int32_t>(CONFIG_ID_MAX); index ++) { instance.SubscribeConfigObserver(static_cast<CONFIG_ID>(index), shared_from_this(), false); } } void NAccessibilityConfigObserverImpl::OnConfigChanged( const OHOS::AccessibilityConfig::CONFIG_ID id, const OHOS::AccessibilityConfig::ConfigValue& value) { HILOG_INFO(); std::lock_guard<ffrt::mutex> lock(mutex_); for (auto &observer : observers_) { if (observer && observer->configId_ == id) { observer->OnConfigChanged(value); } } } void NAccessibilityConfigObserverImpl::SubscribeObserver(napi_env env, OHOS::AccessibilityConfig::CONFIG_ID id, napi_value observer) { HILOG_INFO(); std::lock_guard<ffrt::mutex> lock(mutex_); for (auto iter = observers_.begin(); iter != observers_.end();) { if (CheckObserverEqual(env, observer, (*iter)->env_, (*iter)->handlerRef_)) { HILOG_DEBUG("SubscribeObserver Observer exist"); return; } else { iter++; } } napi_ref handler = nullptr; napi_create_reference(env, observer, 1, &handler); std::shared_ptr<NAccessibilityConfigObserver> observerPtr = std::make_shared<NAccessibilityConfigObserver>(env, handler, id); observers_.emplace_back(observerPtr); } void NAccessibilityConfigObserverImpl::UnsubscribeObserver(napi_env env, OHOS::AccessibilityConfig::CONFIG_ID id, napi_value observer) { HILOG_INFO(); std::lock_guard<ffrt::mutex> lock(mutex_); for (auto iter = observers_.begin(); iter != observers_.end();) { if ((*iter)->configId_ == id) { if (CheckObserverEqual(env, observer, (*iter)->env_, (*iter)->handlerRef_)) { observers_.erase(iter); return; } else { iter++; } } else { iter++; } } } void NAccessibilityConfigObserverImpl::UnsubscribeObservers(OHOS::AccessibilityConfig::CONFIG_ID id) { HILOG_INFO(); std::lock_guard<ffrt::mutex> lock(mutex_); for (auto iter = observers_.begin(); iter != observers_.end();) { if ((*iter)->configId_ == id) { iter = observers_.erase(iter); } else { iter++; } } }