1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <ani.h>
17 #include <array>
18 #include <iostream>
19 #include <ctime>
20 #include "time_hilog.h"
21 #include "time_service_client.h"
22
23 using namespace OHOS::MiscServices;
24
25 constexpr ani_long SECS_TO_NANO = 1000000000;
26 constexpr ani_long SECS_TO_MILLI = 1000;
27 constexpr ani_long NANO_TO_MILLI = 1000000;
28
GetRealTime(ani_boolean isNano)29 static ani_long GetRealTime(ani_boolean isNano)
30 {
31 struct timespec ts;
32
33 if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
34 TIME_HILOGE(TIME_MODULE_JS_ANI, "failed clock_gettime, errno: %{public}s", strerror(errno));
35 return 0;
36 }
37
38 if (isNano) {
39 return ts.tv_sec * SECS_TO_NANO + ts.tv_nsec;
40 }
41
42 return ts.tv_sec * SECS_TO_MILLI + ts.tv_nsec / NANO_TO_MILLI;
43 }
44
GetTime(ani_env * env,ani_object booleanObject)45 static ani_double GetTime([[maybe_unused]] ani_env *env, ani_object booleanObject)
46 {
47 ani_boolean isUndefined = false;
48 env->Reference_IsUndefined(booleanObject, &isUndefined);
49 if (isUndefined) {
50 return GetRealTime(false);
51 }
52 ani_boolean isNano;
53 if (ANI_OK !=env->Object_CallMethodByName_Boolean(booleanObject, "unboxed", nullptr, &isNano)) {
54 TIME_HILOGE(TIME_MODULE_JS_ANI, "Object_CallMethodByName_Boolean Fail");
55 }
56 return GetRealTime(isNano);
57 }
58
GetTimeZone(ani_env * env)59 static ani_string GetTimeZone([[maybe_unused]] ani_env *env)
60 {
61 std::string timezone;
62 auto status = TimeServiceClient::GetInstance()->GetTimeZone(timezone);
63 if (ANI_OK != status) {
64 TIME_HILOGE(TIME_MODULE_JS_ANI, "GetTimeZone failed, errno: %{public}d", status);
65 }
66 ani_string tzCstr;
67 env->String_NewUTF8(timezone.c_str(), timezone.size(), &tzCstr);
68 return tzCstr;
69 }
70
ANI_Constructor(ani_vm * vm,uint32_t * result)71 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
72 {
73 ani_env *env;
74 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
75 TIME_HILOGE(TIME_MODULE_JS_ANI, "Unsupported ANI_VERSION_1");
76 return ANI_ERROR;
77 }
78
79 static const char *namespaceName = "L@ohos/systemDateTime/systemDateTime;";
80 ani_namespace ns;
81 if (ANI_OK != env->FindNamespace(namespaceName, &ns)) {
82 TIME_HILOGE(TIME_MODULE_JS_ANI, "Not found '%{public}s'", namespaceName);
83 return ANI_ERROR;
84 }
85
86 std::array methods = {
87 ani_native_function {"getTime", nullptr, reinterpret_cast<void *>(GetTime)},
88 ani_native_function {"getTimezoneSync", ":Lstd/core/String;", reinterpret_cast<void *>(GetTimeZone)},
89 };
90
91 if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
92 TIME_HILOGE(TIME_MODULE_JS_ANI, "Cannot bind native methods to '%{public}s'", namespaceName);
93 return ANI_ERROR;
94 };
95
96 *result = ANI_VERSION_1;
97 return ANI_OK;
98 }