• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }