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
20 #include "uri.h"
21 #include "ani_utils.h"
22 #include "datashare_predicates.h"
23 #include "datashare_template.h"
24 #include "ani_base_context.h"
25 #include "ani_datashare_helper.h"
26 #include "datashare_business_error.h"
27 #include "ipc_skeleton.h"
28 #include "tokenid_kit.h"
29
30 using namespace OHOS;
31 using namespace OHOS::DataShare;
32 using namespace OHOS::Security::AccessToken;
33 using Uri = OHOS::Uri;
34
35 static constexpr int EXCEPTION_SYSTEMAPP_CHECK = 202;
36 static std::map<std::string, std::list<sptr<ANIDataShareObserver>>> observerMap_;
37
IsSystemApp()38 static bool IsSystemApp()
39 {
40 uint64_t tokenId = IPCSkeleton::GetSelfTokenID();
41 return TokenIdKit::IsSystemAppByFullTokenID(tokenId);
42 }
43
ThrowBusinessError(ani_env * env,int errCode,std::string && errMsg)44 static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg)
45 {
46 LOG_DEBUG("Begin ThrowBusinessError.");
47 static const char *errorClsName = "L@ohos/base/BusinessError;";
48 ani_class cls {};
49 if (ANI_OK != env->FindClass(errorClsName, &cls)) {
50 LOG_ERROR("find class BusinessError %{public}s failed", errorClsName);
51 return;
52 }
53 ani_method ctor;
54 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) {
55 LOG_ERROR("find method BusinessError.constructor failed");
56 return;
57 }
58 ani_object errorObject;
59 if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) {
60 LOG_ERROR("create BusinessError object failed");
61 return;
62 }
63 ani_double aniErrCode = static_cast<ani_double>(errCode);
64 ani_string errMsgStr;
65 if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) {
66 LOG_ERROR("convert errMsg to ani_string failed");
67 return;
68 }
69 if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) {
70 LOG_ERROR("set error code failed");
71 return;
72 }
73 if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) {
74 LOG_ERROR("set error message failed");
75 return;
76 }
77 env->ThrowError(static_cast<ani_error>(errorObject));
78 return;
79 }
80
getNameSpace(ani_env * env,ani_namespace & ns)81 static bool getNameSpace(ani_env *env, ani_namespace &ns)
82 {
83 const char *spaceName = "L@ohos/data/dataShare/dataShare;";
84 if (ANI_OK != env->FindNamespace(spaceName, &ns)) {
85 LOG_ERROR("Not found space name '%{public}s'", spaceName);
86 return false;
87 }
88
89 return true;
90 }
91
getClass(ani_env * env,ani_class & cls)92 static bool getClass(ani_env *env, ani_class &cls)
93 {
94 ani_namespace ns;
95 if (!getNameSpace(env, ns)) {
96 return false;
97 }
98
99 const char *className = "LDataShareHelperInner;";
100 if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) {
101 LOG_ERROR("Not found class name '%{public}s'", className);
102 return false;
103 }
104
105 return true;
106 }
107
getUri(ani_env * env,ani_string uri,std::string & strUri)108 static bool getUri(ani_env *env, ani_string uri, std::string &strUri)
109 {
110 strUri = AniStringUtils::ToStd(env, uri);
111 if (strUri.empty()) {
112 LOG_ERROR("uri is empty");
113 return false;
114 }
115
116 return true;
117 }
118
getType(ani_env * env,ani_string type,std::string & strType)119 static bool getType(ani_env *env, ani_string type, std::string &strType)
120 {
121 strType = AniStringUtils::ToStd(env, type);
122 if (strType.empty()) {
123 LOG_ERROR("type is empty");
124 return false;
125 }
126
127 return true;
128 }
129
getEvent(ani_env * env,ani_string event,std::string & strEvent)130 static bool getEvent(ani_env *env, ani_string event, std::string &strEvent)
131 {
132 strEvent = AniStringUtils::ToStd(env, event);
133 if (strEvent.empty()) {
134 LOG_ERROR("event is empty");
135 return false;
136 }
137
138 return true;
139 }
140
getDataShareHelper(ani_env * env,ani_object object,DataShareHelper * & helper)141 static bool getDataShareHelper(ani_env *env, ani_object object, DataShareHelper *&helper)
142 {
143 ani_long nativePtr;
144 if (ANI_OK != env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr)) {
145 LOG_ERROR("nativePtr is nullptr");
146 return false;
147 }
148
149 auto helperHolder = reinterpret_cast<SharedPtrHolder<DataShareHelper> *>(nativePtr);
150 if (helperHolder == nullptr) {
151 LOG_ERROR("SharedPtrHolder is nullptr");
152 return false;
153 }
154
155 helper = helperHolder->Get().get();
156 if (helper == nullptr) {
157 LOG_ERROR("DataShareHelper is nullptr");
158 return false;
159 }
160
161 return true;
162 }
163
GetIsProxy(ani_env * env,ani_object options,bool & isProxy)164 static ani_status GetIsProxy(ani_env *env, ani_object options, bool &isProxy)
165 {
166 ani_ref proxyObj;
167 ani_status result = env->Object_GetPropertyByName_Ref(options, "isProxy", &proxyObj);
168 if (ANI_OK != result) {
169 LOG_ERROR("options Failed to get property named type: %{public}d", result);
170 return result;
171 }
172
173 ani_boolean isUndefined;
174 result = env->Reference_IsUndefined(static_cast<ani_object>(proxyObj), &isUndefined);
175 if (ANI_OK != result) {
176 LOG_ERROR("options Object_GetFieldByName_Ref isProxyField Failed");
177 return result;
178 }
179
180 if (isUndefined) {
181 LOG_ERROR("options isProxyField is Undefined Now");
182 isProxy = false;
183 return ANI_OK;
184 }
185
186 ani_boolean proxy;
187 result = env->Object_CallMethodByName_Boolean(static_cast<ani_object>(proxyObj), "unboxed", nullptr, &proxy);
188 if (ANI_OK != result) {
189 LOG_ERROR("options Failed to get property named isProxy: %{public}d", result);
190 return result;
191 }
192
193 isProxy = proxy;
194 return ANI_OK;
195 }
196
CreateDataShareHelper(ani_env * env,ani_object options,std::string & strUri,std::shared_ptr<AbilityRuntime::Context> & ctx)197 static std::shared_ptr<DataShareHelper> CreateDataShareHelper(ani_env *env, ani_object options, std::string &strUri,
198 std::shared_ptr<AbilityRuntime::Context> &ctx)
199 {
200 bool isProxy = false;
201 if (GetIsProxy(env, options, isProxy) != ANI_OK) {
202 LOG_ERROR("Get isProxy Failed");
203 return nullptr;
204 }
205 CreateOptions opts = {
206 isProxy,
207 ctx->GetToken(),
208 Uri(strUri).GetScheme() == "datashareproxy",
209 };
210
211 return DataShareHelper::Creator(strUri, opts);
212 }
213
ANI_Create(ani_env * env,ani_object context,ani_string uri,ani_object options)214 static ani_object ANI_Create([[maybe_unused]] ani_env *env, ani_object context, ani_string uri, ani_object options)
215 {
216 if (env == nullptr) {
217 LOG_ERROR("env is nullptr %{public}s", __func__);
218 return nullptr;
219 }
220
221 if (!IsSystemApp()) {
222 ThrowBusinessError(env, EXCEPTION_SYSTEMAPP_CHECK, "not system app");
223 }
224
225 std::string strUri;
226 ani_class cls;
227 if (!getUri(env, uri, strUri) || !getClass(env, cls)) {
228 return nullptr;
229 }
230
231 ani_boolean isUndefined;
232 if (ANI_OK != env->Reference_IsUndefined(options, &isUndefined)) {
233 LOG_ERROR("Get is undefined Failed");
234 return nullptr;
235 }
236
237 auto ctx = AbilityRuntime::GetStageModeContext(env, context);
238 if (ctx == nullptr) {
239 LOG_ERROR("Get Context Failed");
240 return nullptr;
241 }
242 std::shared_ptr<DataShareHelper> dataShareHelper;
243 if (isUndefined) {
244 dataShareHelper = DataShareHelper::Creator(ctx->GetToken(), strUri);
245 } else {
246 dataShareHelper = CreateDataShareHelper(env, options, strUri, ctx);
247 }
248
249 if (dataShareHelper == nullptr) {
250 LOG_ERROR("Create Object DataShareHelper is null");
251 return nullptr;
252 }
253
254 auto shareptrData = new (std::nothrow) SharedPtrHolder<DataShareHelper>(dataShareHelper);
255 if (shareptrData == nullptr) {
256 LOG_ERROR("Create Object SharedPtrHolder is null");
257 return nullptr;
258 }
259
260 const char *spaceName = "L@ohos/data/dataShare/dataShare;";
261 const char *className = "LDataShareHelperInner;";
262 ani_object dataShareObj = AniObjectUtils::Create(env, spaceName, className,
263 reinterpret_cast<ani_long>(shareptrData));
264
265 return dataShareObj;
266 }
267
ANI_OnType(ani_env * env,ani_object object,ani_string type,ani_string uri,ani_object callback)268 static void ANI_OnType([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
269 ani_string type, ani_string uri, ani_object callback)
270 {
271 if (env == nullptr) {
272 LOG_ERROR("env is nullptr %{public}s", __func__);
273 return;
274 }
275 std::string strType;
276 std::string strUri;
277 DataShareHelper *helper = nullptr;
278 if (!getType(env, type, strType) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) {
279 return;
280 }
281
282 ani_ref callbackRef;
283 if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) {
284 LOG_ERROR("Create callback failed");
285 return;
286 }
287
288 if (strType == "dataChange") {
289 observerMap_.try_emplace(strUri);
290
291 auto &list = observerMap_.find(strUri)->second;
292 for (auto &it : list) {
293 if (callbackRef == it->observer_->GetCallback()) {
294 LOG_ERROR("The observer has already subscribed.");
295 return;
296 }
297 }
298
299 ani_vm *vm = nullptr;
300 if (ANI_OK != env->GetVM(&vm)) {
301 LOG_ERROR("GetVM failed.");
302 return;
303 }
304
305 auto innerObserver = std::make_shared<ANIInnerObserver>(vm, callbackRef);
306 sptr<ANIDataShareObserver> observer(new (std::nothrow) ANIDataShareObserver(innerObserver));
307 if (observer == nullptr) {
308 LOG_ERROR("observer is nullptr");
309 return;
310 }
311
312 helper->RegisterObserver(Uri(strUri), observer);
313 list.push_back(observer);
314 }
315 }
316
DataChangeOffEvent(ani_env * env,ani_ref & callbackRef,std::string & strUri,DataShareHelper * & helper)317 static void DataChangeOffEvent(ani_env *env, ani_ref &callbackRef, std::string &strUri, DataShareHelper *&helper)
318 {
319 auto obs = observerMap_.find(strUri);
320 if (obs == observerMap_.end()) {
321 LOG_ERROR("this uri hasn't been registered");
322 return;
323 }
324
325 auto &list = obs->second;
326 auto it = list.begin();
327 while (it != list.end()) {
328 ani_boolean isEquals = false;
329 if (ANI_OK != env->Reference_StrictEquals(callbackRef, (*it)->observer_->GetCallback(), &isEquals)) {
330 LOG_ERROR("%{public}s: check observer equal failed!", __func__);
331 return;
332 }
333
334 if (callbackRef != nullptr && !isEquals) {
335 ++it;
336 continue;
337 }
338
339 helper->UnregisterObserverExt(Uri(strUri),
340 std::shared_ptr<DataShareObserver>((*it).GetRefPtr(), [holder = *it](const auto*) {}));
341 it = list.erase(it);
342 }
343
344 if (list.empty()) {
345 observerMap_.erase(strUri);
346 }
347 }
348
DataChangeOffType(ani_env * env,ani_ref & callbackRef,std::string & strUri,DataShareHelper * & helper)349 static void DataChangeOffType(ani_env *env, ani_ref &callbackRef, std::string &strUri, DataShareHelper *&helper)
350 {
351 auto obs = observerMap_.find(strUri);
352 if (obs == observerMap_.end()) {
353 LOG_ERROR("this uri hasn't been registered");
354 return;
355 }
356
357 auto &list = obs->second;
358 auto it = list.begin();
359 while (it != list.end()) {
360 ani_boolean isEquals = false;
361 if (ANI_OK != env->Reference_StrictEquals(callbackRef, (*it)->observer_->GetCallback(), &isEquals)) {
362 LOG_ERROR("%{public}s: check observer equal failed!", __func__);
363 return;
364 }
365
366 if (callbackRef != nullptr && !isEquals) {
367 ++it;
368 continue;
369 }
370
371 helper->UnregisterObserver(Uri(strUri), *it);
372 it = list.erase(it);
373 }
374
375 if (list.empty()) {
376 observerMap_.erase(strUri);
377 }
378 }
379
ANI_OffType(ani_env * env,ani_object object,ani_string type,ani_string uri,ani_object callback)380 static void ANI_OffType([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
381 ani_string type, ani_string uri, ani_object callback)
382 {
383 if (env == nullptr) {
384 LOG_ERROR("env is nullptr %{public}s", __func__);
385 return;
386 }
387 std::string strType;
388 std::string strUri;
389 DataShareHelper *helper = nullptr;
390 if (!getType(env, type, strType) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) {
391 return;
392 }
393
394 ani_boolean isUndefined;
395 if (ANI_OK != env->Reference_IsUndefined(callback, &isUndefined)) {
396 LOG_ERROR("Call Reference_IsUndefined failed");
397 return;
398 }
399
400 ani_ref callbackRef;
401 if (isUndefined) {
402 LOG_ERROR("%{public}s: callback is undefined", __func__);
403 callbackRef = nullptr;
404 } else {
405 if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) {
406 LOG_ERROR("Create callback failed");
407 return;
408 }
409 }
410
411 if (strType == "dataChange") {
412 DataChangeOffType(env, callbackRef, strUri, helper);
413 }
414 }
415
ANI_OnEvent(ani_env * env,ani_object object,ani_string event,ani_enum_item subscriptionType,ani_string uri,ani_object callback)416 static void ANI_OnEvent([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
417 ani_string event, ani_enum_item subscriptionType, ani_string uri, ani_object callback)
418 {
419 if (env == nullptr) {
420 LOG_ERROR("env is nullptr %{public}s", __func__);
421 return;
422 }
423 std::string strEvent;
424 std::string strUri;
425 DataShareHelper *helper = nullptr;
426 if (!getEvent(env, event, strEvent) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) {
427 return;
428 }
429
430 ani_ref callbackRef;
431 if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) {
432 LOG_ERROR("Create callback failed");
433 return;
434 }
435
436 if (strEvent == "dataChange") {
437 observerMap_.try_emplace(strUri);
438
439 auto &list = observerMap_.find(strUri)->second;
440 for (auto &it : list) {
441 if (callbackRef == it->observer_->GetCallback()) {
442 LOG_ERROR("The observer has already subscribed.");
443 return;
444 }
445 }
446
447 ani_vm *vm = nullptr;
448 if (ANI_OK != env->GetVM(&vm)) {
449 LOG_ERROR("GetVM failed.");
450 return;
451 }
452
453 auto innerObserver = std::make_shared<ANIInnerObserver>(vm, callbackRef);
454 sptr<ANIDataShareObserver> observer(new (std::nothrow) ANIDataShareObserver(innerObserver));
455 if (observer == nullptr) {
456 LOG_ERROR("observer is nullptr");
457 return;
458 }
459
460 helper->RegisterObserverExt(Uri(strUri),
461 std::shared_ptr<DataShareObserver>(observer.GetRefPtr(), [holder = observer](const auto*) {}), false);
462 list.push_back(observer);
463 }
464 }
465
ANI_OffEvent(ani_env * env,ani_object object,ani_string event,ani_enum_item subscriptionType,ani_string uri,ani_object callback)466 static void ANI_OffEvent([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
467 ani_string event, ani_enum_item subscriptionType, ani_string uri, ani_object callback)
468 {
469 if (env == nullptr) {
470 LOG_ERROR("env is nullptr %{public}s", __func__);
471 return;
472 }
473 std::string strEvent;
474 std::string strUri;
475 DataShareHelper *helper = nullptr;
476 if (!getEvent(env, event, strEvent) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) {
477 return;
478 }
479
480 ani_boolean isUndefined;
481 if (ANI_OK != env->Reference_IsUndefined(callback, &isUndefined)) {
482 LOG_ERROR("Call Reference_IsUndefined failed");
483 return;
484 }
485
486 ani_ref callbackRef;
487 if (isUndefined) {
488 LOG_ERROR("%{public}s: callback is undefined", __func__);
489 callbackRef = nullptr;
490 } else {
491 if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) {
492 LOG_ERROR("Create callback failed");
493 return;
494 }
495 }
496
497 if (strEvent == "dataChange") {
498 DataChangeOffEvent(env, callbackRef, strUri, helper);
499 }
500 }
501
ANI_Query(ani_env * env,ani_object object,ani_string uri,ani_object predicates,ani_object columns)502 static ani_object ANI_Query([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
503 ani_string uri, ani_object predicates, ani_object columns)
504 {
505 if (env == nullptr) {
506 LOG_ERROR("env is nullptr %{public}s", __func__);
507 return nullptr;
508 }
509 std::string strUri;
510 ani_class cls;
511 DataShareHelper *helper = nullptr;
512 if (!getUri(env, uri, strUri) || !getClass(env, cls) || !getDataShareHelper(env, object, helper)) {
513 return nullptr;
514 }
515
516 auto pred = AniObjectUtils::Unwrap<DataSharePredicates>(env, predicates);
517 if (pred == nullptr) {
518 LOG_ERROR("dataSharePredicates is nullptr : %{public}d", pred == nullptr);
519 return nullptr;
520 }
521
522 std::vector<std::string> strings;
523 if (!UnionAccessor(env, columns).TryConvertArray<std::string>(strings)) {
524 LOG_ERROR("TryConvertArray columns Failed");
525 return nullptr;
526 }
527
528 Uri uriObj(strUri);
529 DatashareBusinessError businessError;
530 auto resultObject = helper->Query(uriObj, *pred, strings, &businessError);
531 if (resultObject == nullptr) {
532 LOG_ERROR("query failed, result is null!");
533 return nullptr;
534 }
535
536 if (businessError.GetCode() != 0) {
537 LOG_ERROR("query failed, errorCode : %{public}d", businessError.GetCode());
538 return nullptr;
539 }
540
541 auto shareptrData = new (std::nothrow) SharedPtrHolder<DataShareResultSet>(resultObject);
542 if (shareptrData == nullptr) {
543 LOG_ERROR("Create Object SharedPtrHolder is null");
544 return nullptr;
545 }
546
547 const char *className = "L@ohos/data/DataShareResultSet/DataShareResultSetImpl;";
548 ani_object resultSetObj = AniObjectUtils::Create(env, className,
549 reinterpret_cast<ani_long>(shareptrData));
550
551 return resultSetObj;
552 }
553
554 using BucketMap = std::map<std::string, DataShareValueObject::Type>;
555 using BucketPtr = std::shared_ptr<BucketMap>;
556 using CallbackType = convertCallback<BucketMap>;
557
__anon5dc89c280302(ani_env *env, ani_ref &ani_key, ani_ref &object, BucketPtr records) 558 auto g_convertValuesBucket = [](ani_env *env, ani_ref &ani_key, ani_ref &object, BucketPtr records) {
559 auto key = AniStringUtils::ToStd(env, static_cast<ani_string>(ani_key));
560 auto unionObject = static_cast<ani_object>(object);
561 UnionAccessor unionAccessor(env, unionObject);
562 if (unionAccessor.IsInstanceOf("Lstd/core/Double;")) {
563 double value;
564 unionAccessor.TryConvert<double>(value);
565 records->emplace(key, value);
566 return true;
567 }
568
569 if (unionAccessor.IsInstanceOf("Lstd/core/String;")) {
570 std::string value;
571 unionAccessor.TryConvert<std::string>(value);
572 records->emplace(key, value);
573 return true;
574 }
575
576 if (unionAccessor.IsInstanceOf("Lstd/core/Boolean;")) {
577 bool value;
578 unionAccessor.TryConvert<bool>(value);
579 records->emplace(key, value);
580 return true;
581 }
582
583 std::vector<uint8_t> arrayUint8Values;
584 if (unionAccessor.TryConvertArray<uint8_t>(arrayUint8Values)) {
585 records->emplace(key, arrayUint8Values);
586 return true;
587 }
588
589 if (OptionalAccessor(env, unionObject).IsNull()) {
590 records->emplace(key, nullptr);
591 return true;
592 }
593
594 LOG_ERROR("Unexpected object type");
595 return false;
596 };
597
ANI_Update(ani_env * env,ani_object object,ani_string uri,ani_object predicates,ani_object value)598 static ani_double ANI_Update([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object,
599 ani_string uri, ani_object predicates, ani_object value)
600 {
601 if (env == nullptr) {
602 LOG_ERROR("env is nullptr %{public}s", __func__);
603 return ani_double(DATA_SHARE_ERROR);
604 }
605 std::string strUri;
606 ani_class cls;
607 DataShareHelper *helper = nullptr;
608 if (!getUri(env, uri, strUri) || !getClass(env, cls) || !getDataShareHelper(env, object, helper)) {
609 return ani_double(DATA_SHARE_ERROR);
610 }
611
612 auto pred = AniObjectUtils::Unwrap<DataSharePredicates>(env, predicates);
613 if (pred == nullptr) {
614 LOG_ERROR("dataSharePredicates is nullptr : %{public}d", pred == nullptr);
615 return ani_double(DATA_SHARE_ERROR);
616 }
617
618 auto bucket = std::make_shared<BucketMap>();
619 if (!forEachMapEntry<CallbackType, BucketMap>(env, value, g_convertValuesBucket, bucket)) {
620 LOG_ERROR("Is bucket null: %{public}d", bucket->empty());
621 return ani_double(DATA_SHARE_ERROR);
622 }
623
624 Uri uriObj(strUri);
625 DataShareValuesBucket dataShareValuesBucket(*bucket);
626
627 return static_cast<ani_double>(helper->Update(uriObj, *pred, dataShareValuesBucket));
628 }
629
ANI_Constructor(ani_vm * vm,uint32_t * result)630 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
631 {
632 ani_env *env;
633 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
634 LOG_ERROR("Unsupported ANI_VERSION_1");
635 return ANI_ERROR;
636 }
637
638 ani_namespace ns;
639 if (!getNameSpace(env, ns)) {
640 return ANI_ERROR;
641 }
642
643 std::array functions = {
644 ani_native_function {"create", nullptr, reinterpret_cast<void *>(ANI_Create)},
645 };
646
647 if (ANI_OK != env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) {
648 LOG_ERROR("Cannot bind native functions to namespace");
649 return ANI_ERROR;
650 }
651
652 std::array methods = {
653 ani_native_function {"on", "Lstd/core/String;Lstd/core/String;Lstd/core/Function2;:V",
654 reinterpret_cast<void *>(ANI_OnType)},
655 ani_native_function {"off", "Lstd/core/String;Lstd/core/String;Lstd/core/Function2;:V",
656 reinterpret_cast<void *>(ANI_OffType)},
657 ani_native_function {"on",
658 "Lstd/core/String;L@ohos/data/dataShare/dataShare/SubscriptionType;Lstd/core/String;Lstd/core/Function2;:V",
659 reinterpret_cast<void *>(ANI_OnEvent)},
660 ani_native_function {"off",
661 "Lstd/core/String;L@ohos/data/dataShare/dataShare/SubscriptionType;Lstd/core/String;Lstd/core/Function2;:V",
662 reinterpret_cast<void *>(ANI_OffEvent)},
663 ani_native_function {"ani_query", nullptr, reinterpret_cast<void *>(ANI_Query)},
664 ani_native_function {"ani_update", nullptr, reinterpret_cast<void *>(ANI_Update)},
665 };
666
667 ani_class cls;
668 if (!getClass(env, cls)) {
669 return ANI_ERROR;
670 }
671
672 if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) {
673 LOG_ERROR("Cannot bind native methods to class");
674 return ANI_ERROR;
675 }
676
677 static const char *cleanerName = "LCleaner;";
678 auto cleanerCls = AniTypeFinder(env).FindClass(ns, cleanerName);
679 NativePtrCleaner(env).Bind(cleanerCls.value());
680
681 *result = ANI_VERSION_1;
682 return ANI_OK;
683 }