1 /*
2 * Copyright (C) 2025 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 <ani.h>
17 #include <array>
18 #include <iostream>
19 #include "ani_accessibility_system_ability_client.h"
20 #include "hilog_wrapper.h"
21 #include <ani_signature_builder.h>
22
23 using namespace arkts::ani_signature;
24
25 constexpr int32_t INVALID_ANI_VERSION = 1;
26 constexpr int32_t MODULE_NOT_FOUND = 2;
27 constexpr int32_t NAMESPACE_NOT_FOUND = 3;
28 constexpr int32_t BIND_METHOD_FAILED = 4;
29
30 static bool BindMethod(ani_env *env, ani_namespace cls, ani_module mod);
31
ANI_Constructor(ani_vm * vm,uint32_t * result)32 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
33 {
34 ani_env *env;
35 if (vm->GetEnv(ANI_VERSION_1, &env) != ANI_OK) {
36 HILOG_ERROR("Unsupported ANI_VERSION_1");
37 return (ani_status)INVALID_ANI_VERSION;
38 }
39
40 Namespace accessibilityNamespace = Builder::BuildNamespace("@ohos.accessibility.accessibility");
41 ani_namespace ns;
42 if (env->FindNamespace(accessibilityNamespace.Descriptor().c_str(), &ns) != ANI_OK) {
43 HILOG_ERROR("namespace accessibility not found");
44 return (ani_status)NAMESPACE_NOT_FOUND;
45 }
46
47 Module accessibilityModule = Builder::BuildModule("@ohos.accessibility");
48 ani_module mod;
49 if (env->FindModule(accessibilityModule.Descriptor().c_str(), &mod) != ANI_OK) {
50 HILOG_ERROR("module accessibility not found");
51 return (ani_status)MODULE_NOT_FOUND;
52 }
53
54 if (!BindMethod(env, ns, mod)) {
55 HILOG_ERROR("bind method failed");
56 return (ani_status)BIND_METHOD_FAILED;
57 }
58
59 ANIAccessibilityClient::accessibilityStateListeners_->SubscribeToFramework();
60 ANIAccessibilityClient::touchGuideStateListeners_->SubscribeToFramework();
61 ANIAccessibilityClient::screenReaderStateListeners_->SubscribeToFramework();
62 ANIAccessibilityClient::touchModeListeners_->SubscribeToFramework();
63
64 *result = ANI_VERSION_1;
65 return ANI_OK;
66 }
67
BindMethod(ani_env * env,ani_namespace ns,ani_module mod)68 static bool BindMethod(ani_env *env, ani_namespace ns, ani_module mod)
69 {
70 std::array methods = {
71 ani_native_function {"isOpenTouchGuideSync", nullptr, reinterpret_cast<void *>(
72 ANIAccessibilityClient::IsOpenTouchGuideSync)},
73 };
74
75 if (env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()) != ANI_OK) {
76 return false;
77 };
78
79 methods = {
80 ani_native_function {"isOpenAccessibilitySync", nullptr, reinterpret_cast<void *>(
81 ANIAccessibilityClient::IsOpenAccessibilitySync)},
82 };
83
84 if (env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()) != ANI_OK) {
85 return false;
86 };
87
88 methods = {
89 ani_native_function {"on", nullptr, reinterpret_cast<void *>(ANIAccessibilityClient::SubscribeState)},
90 };
91
92 if (env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()) != ANI_OK) {
93 return false;
94 };
95
96 methods = {
97 ani_native_function {"offObserver", nullptr, reinterpret_cast<void *>(
98 ANIAccessibilityClient::UnsubscribeState)},
99 };
100
101 if (env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()) != ANI_OK) {
102 return false;
103 };
104
105 methods = {
106 ani_native_function {"offAll", nullptr, reinterpret_cast<void *>(ANIAccessibilityClient::UnsubscribeStateAll)},
107 };
108
109 if (env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()) != ANI_OK) {
110 return false;
111 };
112
113 methods = {
114 ani_native_function {"sendAccessibilityEventSync", nullptr,
115 reinterpret_cast<void *>(ANIAccessibilityClient::SendAccessibilityEvent)},
116 };
117
118 if (env->Module_BindNativeFunctions(mod, methods.data(), methods.size()) != ANI_OK) {
119 return false;
120 };
121
122 return true;
123 }
124
ANI_Destructor(ani_vm * vm)125 ANI_EXPORT ani_status ANI_Destructor(ani_vm *vm)
126 {
127 if (ANIAccessibilityClient::accessibilityStateListeners_) {
128 ANIAccessibilityClient::accessibilityStateListeners_->UnsubscribeFromFramework();
129 }
130 if (ANIAccessibilityClient::touchGuideStateListeners_) {
131 ANIAccessibilityClient::touchGuideStateListeners_->UnsubscribeFromFramework();
132 }
133 if (ANIAccessibilityClient::screenReaderStateListeners_) {
134 ANIAccessibilityClient::screenReaderStateListeners_->UnsubscribeFromFramework();
135 }
136 if (ANIAccessibilityClient::touchModeListeners_) {
137 ANIAccessibilityClient::touchModeListeners_->UnsubscribeFromFramework();
138 }
139
140 return ANI_OK;
141 }