• 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 "sensor_ani.h"
17 #include "securec.h"
18 #include "ani_utils.h"
19 #include "sensor_agent.h"
20 #include "event_handler.h"
21 
22 #undef LOG_TAG
23 #define LOG_TAG "SensorAniAPI"
24 
25 using namespace OHOS;
26 using namespace OHOS::Sensors;
27 
28 constexpr int32_t REPORTING_INTERVAL = 200000000;
29 constexpr int32_t INVALID_SENSOR_ID = -1;
30 constexpr float BODY_STATE_EXCEPT = 1.0f;
31 constexpr float THRESHOLD = 0.000001f;
32 constexpr int32_t ANI_SCOPE_SIZE = 16;
33 
34 static std::unordered_map<int, std::string> g_sensorTypeToClassName = {
35     {256, "LOrientationResponseImpl;"},
36 };
37 
38 std::map<int32_t, vector<string>> g_sensorAttributeList = {
39     { 0, { "x" } },
40     { SENSOR_TYPE_ID_ACCELEROMETER, { "x", "y", "z" } },
41     { SENSOR_TYPE_ID_GYROSCOPE, { "x", "y", "z" } },
42     { SENSOR_TYPE_ID_AMBIENT_LIGHT, { "intensity", "colorTemperature", "infraredLuminance" } },
43     { SENSOR_TYPE_ID_MAGNETIC_FIELD, { "x", "y", "z" } },
44     { SENSOR_TYPE_ID_BAROMETER, { "pressure" } },
45     { SENSOR_TYPE_ID_HALL, { "status" } },
46     { SENSOR_TYPE_ID_TEMPERATURE, { "temperature" } },
47     { SENSOR_TYPE_ID_PROXIMITY, { "distance" } },
48     { SENSOR_TYPE_ID_HUMIDITY, { "humidity" } },
49     { SENSOR_TYPE_ID_ORIENTATION, { "alpha", "beta", "gamma" } },
50     { SENSOR_TYPE_ID_GRAVITY, { "x", "y", "z" } },
51     { SENSOR_TYPE_ID_LINEAR_ACCELERATION, { "x", "y", "z" } },
52     { SENSOR_TYPE_ID_ROTATION_VECTOR, { "x", "y", "z", "w" } },
53     { SENSOR_TYPE_ID_AMBIENT_TEMPERATURE, { "temperature" } },
54     { SENSOR_TYPE_ID_MAGNETIC_FIELD_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
55     { SENSOR_TYPE_ID_GYROSCOPE_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
56     { SENSOR_TYPE_ID_SIGNIFICANT_MOTION, { "scalar" } },
57     { SENSOR_TYPE_ID_PEDOMETER_DETECTION, { "scalar" } },
58     { SENSOR_TYPE_ID_PEDOMETER, { "steps" } },
59     { SENSOR_TYPE_ID_HEART_RATE, { "heartRate" } },
60     { SENSOR_TYPE_ID_WEAR_DETECTION, { "value" } },
61     { SENSOR_TYPE_ID_ACCELEROMETER_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
62     { SENSOR_TYPE_ID_COLOR, { "lightIntensity", "colorTemperature" } },
63     { SENSOR_TYPE_ID_SAR, { "absorptionRatio" } }
64 };
65 
66 static std::unordered_map<std::string, int> stringToNumberMap = {
67     {"orientationChange", 256},
68 };
69 
70 static std::map<std::string, int64_t> g_samplingPeriod = {
71     {"normal", 200000000},
72     {"ui", 60000000},
73     {"game", 20000000},
74 };
75 
76 using ConvertDataFunc = bool(*)(sptr<AsyncCallbackInfo> asyncCallbackInfo, std::vector<ani_ref> &data);
77 static bool ConvertToSensorData(sptr<AsyncCallbackInfo> asyncCallbackInfo, std::vector<ani_ref> &data);
78 
79 static std::map<int32_t, ConvertDataFunc> g_convertfuncList = {
80     {ON_CALLBACK, ConvertToSensorData},
81 };
82 
83 static std::mutex mutex_;
84 static std::mutex bodyMutex_;
85 static float g_bodyState = -1.0f;
86 static std::map<int32_t, std::vector<sptr<AsyncCallbackInfo>>> g_subscribeCallbacks;
87 static std::mutex onMutex_;
88 static std::map<int32_t, std::vector<sptr<AsyncCallbackInfo>>> g_onCallbackInfos;
89 static thread_local std::shared_ptr<OHOS::AppExecFwk::EventHandler> mainHandler = nullptr;
90 
ThrowBusinessError(ani_env * env,int errCode,std::string && errMsg)91 static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg)
92 {
93     SEN_HILOGD("Begin ThrowBusinessError.");
94     static const char *errorClsName = "L@ohos/base/BusinessError;";
95     ani_class cls {};
96     if (ANI_OK != env->FindClass(errorClsName, &cls)) {
97         SEN_HILOGE("find class BusinessError %{public}s failed", errorClsName);
98         return;
99     }
100     ani_method ctor;
101     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) {
102         SEN_HILOGE("find method BusinessError.constructor failed");
103         return;
104     }
105     ani_object errorObject;
106     if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) {
107         SEN_HILOGE("create BusinessError object failed");
108         return;
109     }
110     ani_double aniErrCode = static_cast<ani_double>(errCode);
111     ani_string errMsgStr;
112     if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) {
113         SEN_HILOGE("convert errMsg to ani_string failed");
114         return;
115     }
116     if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) {
117         SEN_HILOGE("set error code failed");
118         return;
119     }
120     if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) {
121         SEN_HILOGE("set error message failed");
122         return;
123     }
124     env->ThrowError(static_cast<ani_error>(errorObject));
125     return;
126 }
127 
CheckSubscribe(int32_t sensorTypeId)128 static bool CheckSubscribe(int32_t sensorTypeId)
129 {
130     std::lock_guard<std::mutex> onCallbackLock(onMutex_);
131     auto iter = g_onCallbackInfos.find(sensorTypeId);
132     return iter != g_onCallbackInfos.end();
133 }
134 
CopySensorData(sptr<AsyncCallbackInfo> callbackInfo,SensorEvent * event)135 static bool CopySensorData(sptr<AsyncCallbackInfo> callbackInfo, SensorEvent *event)
136 {
137     CHKPF(callbackInfo);
138     CHKPF(event);
139     int32_t sensorTypeId = event->sensorTypeId;
140     callbackInfo->data.sensorData.sensorTypeId = sensorTypeId;
141     callbackInfo->data.sensorData.dataLength = event->dataLen;
142     callbackInfo->data.sensorData.timestamp = event->timestamp;
143     callbackInfo->data.sensorData.sensorAccuracy = event->option;
144     CHKPF(event->data);
145     if (event->dataLen < sizeof(float)) {
146         SEN_HILOGE("Event dataLen less than float size");
147         return false;
148     }
149     auto data = reinterpret_cast<float *>(event->data);
150     if (sensorTypeId == SENSOR_TYPE_ID_WEAR_DETECTION && callbackInfo->type == SUBSCRIBE_CALLBACK) {
151         std::lock_guard<std::mutex> onBodyLock(bodyMutex_);
152         g_bodyState = *data;
153         callbackInfo->data.sensorData.data[0] =
154             (fabs(g_bodyState - BODY_STATE_EXCEPT) < THRESHOLD) ? true : false;
155         return true;
156     }
157     if (memcpy_s(callbackInfo->data.sensorData.data, sizeof(callbackInfo->data.sensorData.data),
158         data, event->dataLen) != EOK) {
159         SEN_HILOGE("Copy data failed");
160         return false;
161     }
162     return true;
163 }
164 
CheckSystemSubscribe(int32_t sensorTypeId)165 static bool CheckSystemSubscribe(int32_t sensorTypeId)
166 {
167     std::lock_guard<std::mutex> subscribeLock(mutex_);
168     auto iter = g_subscribeCallbacks.find(sensorTypeId);
169     if (iter == g_subscribeCallbacks.end()) {
170         return false;
171     }
172     return true;
173 }
174 
IsInstanceOf(ani_env * env,const std::string & cls_name,ani_object obj)175 static ani_boolean IsInstanceOf(ani_env *env, const std::string &cls_name, ani_object obj)
176 {
177     ani_class cls;
178     if (ANI_OK != env->FindClass(cls_name.c_str(), &cls)) {
179         SEN_HILOGE("FindClass failed");
180         return ANI_FALSE;
181     }
182 
183     ani_boolean ret;
184     env->Object_InstanceOf(obj, cls, &ret);
185     return ret;
186 }
187 
SendEventToMainThread(const std::function<void ()> func)188 static bool SendEventToMainThread(const std::function<void()> func)
189 {
190     if (func == nullptr) {
191         SEN_HILOGE("func is nullptr!");
192         return false;
193     }
194 
195     if (!mainHandler) {
196         auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
197         if (!runner) {
198             SEN_HILOGE("get main event runner failed!");
199             return false;
200         }
201         mainHandler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
202     }
203     mainHandler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {});
204     return true;
205 }
206 
ValidateAndInitialize(sptr<AsyncCallbackInfo> asyncCallbackInfo,ani_object & obj)207 static bool ValidateAndInitialize(sptr<AsyncCallbackInfo> asyncCallbackInfo, ani_object &obj)
208 {
209     CHKPF(asyncCallbackInfo);
210     int32_t sensorTypeId = asyncCallbackInfo->data.sensorData.sensorTypeId;
211     if (g_sensorAttributeList.find(sensorTypeId) == g_sensorAttributeList.end()) {
212         SEN_HILOGE("Invalid sensor type");
213         return false;
214     }
215     if (sensorTypeId == SENSOR_TYPE_ID_WEAR_DETECTION && asyncCallbackInfo->type == SUBSCRIBE_CALLBACK) {
216         return false;
217     }
218     size_t size = g_sensorAttributeList[sensorTypeId].size();
219     uint32_t dataLength = asyncCallbackInfo->data.sensorData.dataLength / sizeof(float);
220     if (size > dataLength) {
221         SEN_HILOGE("Data length mismatch");
222         return false;
223     }
224 
225     if (g_sensorTypeToClassName.find(sensorTypeId) == g_sensorTypeToClassName.end()) {
226         SEN_HILOGE("Find class by sensorType failed");
227         return false;
228     }
229 
230     ani_namespace ns;
231     static const char *namespaceName = "L@ohos/sensor/sensor;";
232     if (ANI_OK != asyncCallbackInfo->env->FindNamespace(namespaceName, &ns)) {
233         SEN_HILOGE("Not found '%{public}s'", namespaceName);
234         return false;
235     }
236 
237     ani_class cls;
238     const char *className = g_sensorTypeToClassName[sensorTypeId].c_str();
239     if (ANI_OK != asyncCallbackInfo->env->Namespace_FindClass(ns, className, &cls)) {
240         SEN_HILOGE("FindClass %{public}s failed", className);
241         return false;
242     }
243 
244     ani_method ctor;
245     if (ANI_OK != asyncCallbackInfo->env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
246         SEN_HILOGE("Class_FindMethod 'constructor' failed");
247         return false;
248     }
249 
250     if (ANI_OK != asyncCallbackInfo->env->Object_New(cls, ctor, &obj)) {
251         SEN_HILOGE("Object_New '%{public}s' failed", className);
252         return false;
253     }
254     return true;
255 }
256 
GetEnumItem(ani_env * env,int32_t accuracy)257 static ani_enum_item GetEnumItem(ani_env *env, int32_t accuracy)
258 {
259     ani_namespace ns;
260     static const char *namespaceName = "L@ohos/sensor/sensor;";
261     if (ANI_OK != env->FindNamespace(namespaceName, &ns)) {
262         SEN_HILOGE("Not found '%{public}s'", namespaceName);
263         return nullptr;
264     }
265 
266     ani_enum aniEnum{};
267     const char *enumName = "LSensorAccuracy;";
268     if (ANI_OK != env->Namespace_FindEnum(ns, enumName, &aniEnum)) {
269         SEN_HILOGE("Not found '%{public}s'", enumName);
270         return nullptr;
271     }
272 
273     constexpr int32_t loopMaxNum = 1000;
274     for (int32_t index = 0U; index < loopMaxNum; index++) {
275         ani_enum_item enumItem{};
276         if (ANI_OK != env->Enum_GetEnumItemByIndex(aniEnum, index, &enumItem)) {
277             SEN_HILOGE("Enum_GetEnumItemByIndex failed");
278             return nullptr;
279         }
280         ani_int intValue = -1;
281         if (ANI_OK != env->EnumItem_GetValue_Int(enumItem, &intValue)) {
282             SEN_HILOGE("EnumItem_GetValue_Int FAILD.");
283             return nullptr;
284         }
285         if (intValue == accuracy) {
286             return enumItem;
287         }
288     }
289     SEN_HILOGE("Get enumItem by %{public}d failed.", accuracy);
290     return nullptr;
291 }
292 
SetSensorPropertiesAndPushData(sptr<AsyncCallbackInfo> asyncCallbackInfo,ani_object obj,std::vector<ani_ref> & data)293 static bool SetSensorPropertiesAndPushData(sptr<AsyncCallbackInfo> asyncCallbackInfo, ani_object obj,
294     std::vector<ani_ref> &data)
295 {
296     CALL_LOG_ENTER;
297     int32_t sensorTypeId = asyncCallbackInfo->data.sensorData.sensorTypeId;
298     size_t size = g_sensorAttributeList[sensorTypeId].size();
299     auto sensorAttributes = g_sensorAttributeList[sensorTypeId];
300     for (uint32_t i = 0; i < size; ++i) {
301         if (ANI_OK != asyncCallbackInfo->env->Object_SetPropertyByName_Double(obj, sensorAttributes[i].c_str(),
302             asyncCallbackInfo->data.sensorData.data[i])) {
303             SEN_HILOGE("Object_SetPropertyByName_Double failed");
304             return false;
305         }
306     }
307 
308     if (ANI_OK != asyncCallbackInfo->env->Object_SetPropertyByName_Double(obj, "timestamp",
309         asyncCallbackInfo->data.sensorData.timestamp)) {
310         SEN_HILOGE("Object_SetPropertyByName_Double timestamp failed");
311         return false;
312     }
313 
314     ani_enum_item accuracy = GetEnumItem(asyncCallbackInfo->env, asyncCallbackInfo->data.sensorData.sensorAccuracy);
315     if (accuracy == nullptr) {
316         SEN_HILOGE("GetEnumItem failed");
317         return false;
318     }
319     if (ANI_OK != asyncCallbackInfo->env->Object_SetPropertyByName_Ref(obj, "accuracy", accuracy)) {
320         SEN_HILOGE("Object_SetPropertyByName_Ref accuracy failed");
321         return false;
322     }
323 
324     data.push_back(obj);
325     return true;
326 }
327 
ConvertToSensorData(sptr<AsyncCallbackInfo> asyncCallbackInfo,std::vector<ani_ref> & data)328 static bool ConvertToSensorData(sptr<AsyncCallbackInfo> asyncCallbackInfo, std::vector<ani_ref> &data)
329 {
330     ani_object obj;
331     if (!ValidateAndInitialize(asyncCallbackInfo, obj)) {
332         return false;
333     }
334 
335     if (!SetSensorPropertiesAndPushData(asyncCallbackInfo, obj, data)) {
336         return false;
337     }
338 
339     return true;
340 }
341 
EmitUvEventLoop(sptr<AsyncCallbackInfo> asyncCallbackInfo)342 static void EmitUvEventLoop(sptr<AsyncCallbackInfo> asyncCallbackInfo)
343 {
344     CHKPV(asyncCallbackInfo);
345     auto task = [asyncCallbackInfo]() {
346         SEN_HILOGD("Begin to call task");
347         ani_env *env = nullptr;
348         ani_options aniArgs {0, nullptr};
349         if (ANI_ERROR == asyncCallbackInfo->vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) {
350             if (ANI_OK != asyncCallbackInfo->vm->GetEnv(ANI_VERSION_1, &env)) {
351                 SEN_HILOGE("GetEnv failed");
352                 return;
353             }
354         }
355         asyncCallbackInfo->env = env;
356 
357         AniLocalScopeGuard aniLocalScopeGuard(asyncCallbackInfo->env, ANI_SCOPE_SIZE);
358         if (!aniLocalScopeGuard.IsStatusOK()) {
359             SEN_HILOGE("CreateLocalScope failed");
360             return;
361         }
362 
363         if (!(g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end())) {
364             SEN_HILOGE("asyncCallbackInfo type is invalid");
365             ThrowBusinessError(asyncCallbackInfo->env, EINVAL, "asyncCallbackInfo type is invalid");
366             return;
367         }
368         std::vector<ani_ref> args;
369         g_convertfuncList[asyncCallbackInfo->type](asyncCallbackInfo, args);
370 
371         auto fnObj = reinterpret_cast<ani_fn_object>(asyncCallbackInfo->callback[0]);
372         SEN_HILOGD("Begin to call FunctionalObject_Call");
373         if (fnObj == nullptr) {
374             SEN_HILOGE("fnObj == nullptr");
375             ThrowBusinessError(asyncCallbackInfo->env, EINVAL, "fnObj == nullptr");
376             return;
377         }
378         if (IsInstanceOf(asyncCallbackInfo->env, "Lstd/core/Function1;", fnObj) == 0) {
379             SEN_HILOGE("fnObj is not instance Of function");
380             ThrowBusinessError(asyncCallbackInfo->env, EINVAL, "fnObj is not instance Of function");
381             return;
382         }
383 
384         ani_ref result;
385         if (ANI_OK != asyncCallbackInfo->env->FunctionalObject_Call(fnObj, 1, args.data(), &result)) {
386             SEN_HILOGE("FunctionalObject_Call failed");
387             ThrowBusinessError(asyncCallbackInfo->env, EINVAL, "FunctionalObject_Call failed");
388             return;
389         }
390         SEN_HILOGD("FunctionalObject_Call success");
391     };
392     if (!SendEventToMainThread(task)) {
393         SEN_HILOGE("failed to send event");
394     }
395 }
EmitOnCallback(SensorEvent * event)396 static void EmitOnCallback(SensorEvent *event)
397 {
398     CHKPV(event);
399     int32_t sensorTypeId = event->sensorTypeId;
400     if (!CheckSubscribe(sensorTypeId)) {
401         return;
402     }
403     std::lock_guard<std::mutex> onCallbackLock(onMutex_);
404     auto onCallbackInfos = g_onCallbackInfos[sensorTypeId];
405     for (auto &onCallbackInfo : onCallbackInfos) {
406         if (!CopySensorData(onCallbackInfo, event)) {
407             SEN_HILOGE("Copy sensor data failed");
408             continue;
409         }
410         EmitUvEventLoop(onCallbackInfo);
411     }
412 }
413 
DataCallbackImpl(SensorEvent * event)414 static void DataCallbackImpl(SensorEvent *event)
415 {
416     CHKPV(event);
417     EmitOnCallback(event);
418 }
419 
420 static const SensorUser user = {
421     .callback = DataCallbackImpl
422 };
423 
SubscribeSensor(int32_t sensorTypeId,int64_t interval,RecordSensorCallback callback)424 static int32_t SubscribeSensor(int32_t sensorTypeId, int64_t interval, RecordSensorCallback callback)
425 {
426     CALL_LOG_ENTER;
427     int32_t ret = SubscribeSensor(sensorTypeId, &user);
428     if (ret != ERR_OK) {
429         SEN_HILOGE("SubscribeSensor failed");
430         return ret;
431     }
432     ret = SetBatch(sensorTypeId, &user, interval, 0);
433     if (ret != ERR_OK) {
434         SEN_HILOGE("SetBatch failed");
435         return ret;
436     }
437     return ActivateSensor(sensorTypeId, &user);
438 }
439 
IsSubscribed(ani_env * env,int32_t sensorTypeId,ani_object callback)440 static bool IsSubscribed(ani_env *env, int32_t sensorTypeId, ani_object callback)
441 {
442     CALL_LOG_ENTER;
443     if (auto iter = g_onCallbackInfos.find(sensorTypeId); iter == g_onCallbackInfos.end()) {
444         SEN_HILOGW("No client subscribe, sensorTypeId:%{public}d", sensorTypeId);
445         return false;
446     }
447     std::vector<sptr<AsyncCallbackInfo>> callbackInfos = g_onCallbackInfos[sensorTypeId];
448     for (auto callbackInfo : callbackInfos) {
449         CHKPC(callbackInfo);
450         if (callbackInfo->env != env) {
451             continue;
452         }
453 
454         ani_boolean isEquals = false;
455         if (ANI_OK != env->Reference_StrictEquals(callback, callbackInfo->callback[0], &isEquals)) {
456             SEN_HILOGE("StrictEquals failed");
457             return false;
458         }
459         if (isEquals) {
460             return true;
461         }
462     }
463     return false;
464 }
465 
UpdateCallbackInfos(ani_env * env,int32_t sensorTypeId,ani_object callback)466 static void UpdateCallbackInfos(ani_env *env, int32_t sensorTypeId, ani_object callback)
467 {
468     CALL_LOG_ENTER;
469     std::lock_guard<std::mutex> onCallbackLock(onMutex_);
470     CHKCV((!IsSubscribed(env, sensorTypeId, callback)), "The callback has been subscribed");
471 
472     ani_vm *vm = nullptr;
473     if (ANI_OK != env->GetVM(&vm)) {
474         SEN_HILOGE("GetVM failed.");
475         return;
476     }
477     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(vm, env, ON_CALLBACK);
478     CHKPV(asyncCallbackInfo);
479 
480     if (ANI_OK != env->GlobalReference_Create(callback, &asyncCallbackInfo->callback[0])) {
481         SEN_HILOGE("GlobalReference_Create failed");
482         return;
483     }
484 
485     std::vector<sptr<AsyncCallbackInfo>> callbackInfos = g_onCallbackInfos[sensorTypeId];
486     callbackInfos.push_back(asyncCallbackInfo);
487     g_onCallbackInfos[sensorTypeId] = callbackInfos;
488 }
489 
GetIntervalValue(ani_env * env,ani_object options,int64_t & interval)490 static bool GetIntervalValue(ani_env *env, ani_object options, int64_t& interval)
491 {
492     ani_boolean isUndefined;
493     env->Reference_IsUndefined(options, &isUndefined);
494     if (isUndefined) {
495         return true;
496     }
497 
498     ani_ref intervalRef;
499     ani_boolean isIntervalUndefined;
500     if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "interval", &intervalRef)) {
501         SEN_HILOGE("Failed to get property named interval");
502         return false;
503     }
504 
505     env->Reference_IsUndefined(intervalRef, &isIntervalUndefined);
506     if (isIntervalUndefined) {
507         SEN_HILOGE("interval is undefined");
508         return false;
509     }
510 
511     ani_class stringClass;
512     env->FindClass("Lstd/core/String;", &stringClass);
513     ani_class doubleClass;
514     env->FindClass("Lstd/core/Double;", &doubleClass);
515 
516     ani_boolean isDouble;
517     env->Object_InstanceOf(static_cast<ani_object>(intervalRef), doubleClass, &isDouble);
518     ani_boolean isString;
519     env->Object_InstanceOf(static_cast<ani_object>(intervalRef), stringClass, &isString);
520     if (isDouble) {
521         ani_double doubleValue;
522         auto ret = env->Object_CallMethodByName_Double(static_cast<ani_object>(intervalRef), "unboxed",
523             nullptr, &doubleValue);
524         if (ret != ANI_OK) {
525             SEN_HILOGE("Failed to get property named doubleValue");
526             return false;
527         }
528         interval = static_cast<int64_t>(doubleValue);
529         return true;
530     }
531 
532     if (isString) {
533         auto mode = AniStringUtils::ToStd(env, static_cast<ani_string>(intervalRef));
534         auto iter = g_samplingPeriod.find(mode);
535         if (iter == g_samplingPeriod.end()) {
536             SEN_HILOGE("Find interval mode failed");
537             return false;
538         }
539         interval = iter->second;
540         SEN_HILOGI("GetIntervalValue mode: %{public}s", mode.c_str());
541         return true;
542     }
543 
544     SEN_HILOGE("Invalid interval type");
545     return false;
546 }
547 
On(ani_env * env,ani_string typeId,ani_object callback,ani_object options)548 static void On([[maybe_unused]] ani_env *env, ani_string typeId, ani_object callback, ani_object options)
549 {
550     CALL_LOG_ENTER;
551     if (!IsInstanceOf(env, "Lstd/core/Function1;", callback)) {
552         SEN_HILOGE("Wrong argument type");
553         return;
554     }
555 
556     int32_t sensorTypeId = INVALID_SENSOR_ID;
557     auto typeIdStr = AniStringUtils::ToStd(env, static_cast<ani_string>(typeId));
558     if (stringToNumberMap.find(typeIdStr) == stringToNumberMap.end()) {
559         SEN_HILOGE("Invalid sensor typeId: %{public}s", typeIdStr.c_str());
560         return;
561     }
562     sensorTypeId = stringToNumberMap[typeIdStr];
563 
564     int64_t interval = REPORTING_INTERVAL;
565     if (!GetIntervalValue(env, options, interval)) {
566         SEN_HILOGW("Get interval failed");
567     }
568     int32_t ret = SubscribeSensor(sensorTypeId, interval, DataCallbackImpl);
569     if (ret != ERR_OK) {
570         ThrowBusinessError(env, ret, "SubscribeSensor fail");
571         return;
572     }
573     UpdateCallbackInfos(env, sensorTypeId, callback);
574 }
575 
RemoveAllCallback(ani_env * env,int32_t sensorTypeId)576 static int32_t RemoveAllCallback(ani_env *env, int32_t sensorTypeId)
577 {
578     CALL_LOG_ENTER;
579     std::lock_guard<std::mutex> onCallbackLock(onMutex_);
580     std::vector<sptr<AsyncCallbackInfo>> callbackInfos = g_onCallbackInfos[sensorTypeId];
581     for (auto iter = callbackInfos.begin(); iter != callbackInfos.end();) {
582         CHKPC(*iter);
583         if ((*iter)->env != env) {
584             ++iter;
585             continue;
586         }
587         iter = callbackInfos.erase(iter);
588     }
589     if (callbackInfos.empty()) {
590         SEN_HILOGD("No subscription to change sensor data");
591         g_onCallbackInfos.erase(sensorTypeId);
592         return 0;
593     }
594     g_onCallbackInfos[sensorTypeId] = callbackInfos;
595     return callbackInfos.size();
596 }
597 
RemoveCallback(ani_env * env,int32_t sensorTypeId,ani_object callback)598 static int32_t RemoveCallback(ani_env *env, int32_t sensorTypeId, ani_object callback)
599 {
600     CALL_LOG_ENTER;
601     std::lock_guard<std::mutex> onCallbackLock(onMutex_);
602     std::vector<sptr<AsyncCallbackInfo>> callbackInfos = g_onCallbackInfos[sensorTypeId];
603     for (auto iter = callbackInfos.begin(); iter != callbackInfos.end();) {
604         CHKPC(*iter);
605         if ((*iter)->env != env) {
606             continue;
607         }
608 
609         ani_boolean isEquals = false;
610         if (ANI_OK != env->Reference_StrictEquals(callback, (*iter)->callback[0], &isEquals)) {
611             SEN_HILOGE("Reference_StrictEquals failed");
612             return false;
613         }
614         if (isEquals) {
615             iter = callbackInfos.erase(iter);
616             SEN_HILOGD("Remove callback success");
617             break;
618         } else {
619             ++iter;
620         }
621     }
622     if (callbackInfos.empty()) {
623         SEN_HILOGD("No subscription to change sensor data");
624         g_onCallbackInfos.erase(sensorTypeId);
625         return 0;
626     }
627     g_onCallbackInfos[sensorTypeId] = callbackInfos;
628     return callbackInfos.size();
629 }
630 
UnaniSubscribeSensor(int32_t sensorTypeId)631 static int32_t UnaniSubscribeSensor(int32_t sensorTypeId)
632 {
633     int32_t ret = DeactivateSensor(sensorTypeId, &user);
634     if (ret != ERR_OK) {
635         SEN_HILOGE("DeactivateSensor failed");
636         return ret;
637     }
638 
639     return UnsubscribeSensor(sensorTypeId, &user);
640 }
641 
Off(ani_env * env,ani_string type,ani_object callback)642 static void Off([[maybe_unused]] ani_env *env, ani_string type, ani_object callback)
643 {
644     CALL_LOG_ENTER;
645     int32_t sensorTypeId = INVALID_SENSOR_ID;
646     auto typeStr = AniStringUtils::ToStd(env, static_cast<ani_string>(type));
647     if (stringToNumberMap.find(typeStr) == stringToNumberMap.end()) {
648         SEN_HILOGE("Invalid sensor type: %{public}s", typeStr.c_str());
649         ThrowBusinessError(env, PARAMETER_ERROR, "Invalid sensor type");
650         return;
651     }
652     sensorTypeId = stringToNumberMap[typeStr];
653 
654     int32_t subscribeSize = -1;
655     ani_boolean isUndefined;
656     env->Reference_IsUndefined(callback, &isUndefined);
657     if (isUndefined) {
658         subscribeSize = RemoveAllCallback(env, sensorTypeId);
659     } else {
660         ani_boolean result;
661         if (env->Reference_IsNull(callback, &result) == ANI_OK && result) {
662             subscribeSize = RemoveAllCallback(env, sensorTypeId);
663         } else if (IsInstanceOf(env, "Lstd/core/Function1;", callback)) {
664             subscribeSize = RemoveCallback(env, sensorTypeId, callback);
665         } else {
666             ThrowBusinessError(env, PARAMETER_ERROR, "Invalid callback");
667             return;
668         }
669     }
670 
671     if (CheckSystemSubscribe(sensorTypeId) || (subscribeSize > 0)) {
672         SEN_HILOGW("There are other client subscribe system js api as well, not need unsubscribe");
673         return;
674     }
675     int32_t ret = UnaniSubscribeSensor(sensorTypeId);
676     if (ret == PARAMETER_ERROR || ret == PERMISSION_DENIED) {
677         ThrowBusinessError(env, ret, "UnaniSubscribeSensor fail");
678     }
679     return;
680 }
681 
ANI_Constructor(ani_vm * vm,uint32_t * result)682 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
683 {
684     ani_env *env;
685     if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
686         SEN_HILOGE("Unsupported ANI_VERSION_1");
687         return ANI_ERROR;
688     }
689 
690     ani_namespace ns;
691     static const char *spaceName = "L@ohos/sensor/sensor;";
692     if (ANI_OK != env->FindNamespace(spaceName, &ns)) {
693         SEN_HILOGE("Not found space name");
694         return ANI_ERROR;
695     }
696 
697     std::array methods = {
698         ani_native_function {"on", nullptr, reinterpret_cast<void *>(On)},
699         ani_native_function {"off", nullptr, reinterpret_cast<void *>(Off)},
700     };
701 
702     if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
703         SEN_HILOGE("Cannot bind native methods to %{public}s", spaceName);
704         return ANI_ERROR;
705     }
706 
707     *result = ANI_VERSION_1;
708     return ANI_OK;
709 }