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