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 }