From 7d87b58379d740b1d9f1588b84f19490f540fb07 Mon Sep 17 00:00:00 2001 From: xuyong Date: Mon, 14 Jul 2025 15:01:08 +0800 Subject: [PATCH 1/2] cherry pick ani from 0328 to 0702 Signed-off-by: xuyong --- interfaces/ets/ani/hisysevent/BUILD.gn | 3 + .../ani/hisysevent/ets/@ohos.hiSysEvent.ets | 75 ++- .../hisysevent/include/ani_callback_context.h | 36 ++ .../hisysevent/include/ani_callback_manager.h | 49 ++ .../include/ani_hisysevent_listener.h | 47 ++ .../include/ani_hisysevent_querier.h | 49 ++ .../ani/hisysevent/include/hisysevent_ani.h | 11 +- .../hisysevent/include/hisysevent_ani_util.h | 118 +++- .../ets/ani/hisysevent/include/ret_def.h | 1 + .../hisysevent/src/ani_callback_manager.cpp | 112 ++++ .../src/ani_hisysevent_listener.cpp | 123 ++++ .../hisysevent/src/ani_hisysevent_querier.cpp | 129 ++++ .../ets/ani/hisysevent/src/hisysevent_ani.cpp | 464 ++++++++++++-- .../hisysevent/src/hisysevent_ani_util.cpp | 583 ++++++++++++++++-- 14 files changed, 1658 insertions(+), 142 deletions(-) create mode 100644 interfaces/ets/ani/hisysevent/include/ani_callback_context.h create mode 100644 interfaces/ets/ani/hisysevent/include/ani_callback_manager.h create mode 100644 interfaces/ets/ani/hisysevent/include/ani_hisysevent_listener.h create mode 100644 interfaces/ets/ani/hisysevent/include/ani_hisysevent_querier.h create mode 100644 interfaces/ets/ani/hisysevent/src/ani_callback_manager.cpp create mode 100644 interfaces/ets/ani/hisysevent/src/ani_hisysevent_listener.cpp create mode 100644 interfaces/ets/ani/hisysevent/src/ani_hisysevent_querier.cpp diff --git a/interfaces/ets/ani/hisysevent/BUILD.gn b/interfaces/ets/ani/hisysevent/BUILD.gn index 4e25109..1d6096d 100644 --- a/interfaces/ets/ani/hisysevent/BUILD.gn +++ b/interfaces/ets/ani/hisysevent/BUILD.gn @@ -17,6 +17,9 @@ import("//build/ohos.gni") ohos_shared_library("hisysevent_ani") { include_dirs = [ "./include/" ] sources = [ + "./src/ani_callback_manager.cpp", + "./src/ani_hisysevent_listener.cpp", + "./src/ani_hisysevent_querier.cpp", "./src/hisysevent_ani.cpp", "./src/hisysevent_ani_util.cpp", ] diff --git a/interfaces/ets/ani/hisysevent/ets/@ohos.hiSysEvent.ets b/interfaces/ets/ani/hisysevent/ets/@ohos.hiSysEvent.ets index bb41553..c4a8134 100644 --- a/interfaces/ets/ani/hisysevent/ets/@ohos.hiSysEvent.ets +++ b/interfaces/ets/ani/hisysevent/ets/@ohos.hiSysEvent.ets @@ -22,8 +22,29 @@ class SysEventInfoAni implements hiSysEvent.SysEventInfo { params?: object; } -class HiSysEventAni { - native static write(info: hiSysEvent.SysEventInfo): Result; +class WatcherAni implements hiSysEvent.Watcher { + rules: hiSysEvent.WatchRule[] = []; + onEvent: (info: hiSysEvent.SysEventInfo) => void = (info: hiSysEvent.SysEventInfo) => {}; + onServiceDied: () => void = () => {}; +} + +class QuerierAni implements hiSysEvent.Querier { + onQuery: (infos: hiSysEvent.SysEventInfo[]) => void = (infos: hiSysEvent.SysEventInfo[]) => {}; + onComplete: (reason: number, total: number) => void = (reason: number, total: number) => {}; +} + +class QueryArgAni implements hiSysEvent.QueryArg { + beginTime: number = 0; + endTime: number = 0; + maxEvents: number = 0; + fromSeq?: number | undefined; + toSeq?: number | undefined; +} + +class QueryRuleAni implements hiSysEvent.QueryRule { + domain: string = ""; + names: string[] = []; + condition?: string | undefined; } interface Result { @@ -52,8 +73,54 @@ export default namespace hiSysEvent { params?: object; } + export interface Watcher { + rules: WatchRule[]; + onEvent: (info: SysEventInfo) => void; + onServiceDied: () => void; + } + + export interface WatchRule { + domain: string; + name: string; + tag?: string; + ruleType: RuleType; + } + + export enum RuleType { + WHOLE_WORD = 1, + PREFIX = 2, + REGULAR = 3 + } + + export interface QueryRule { + domain: string; + names: string[]; + condition?: string; + } + + export interface QueryArg { + beginTime: number; + endTime: number; + maxEvents: number; + fromSeq?: number; + toSeq?: number; + } + + export interface Querier { + onQuery: (infos: SysEventInfo[]) => void; + onComplete: (reason: number, total: number) => void; + } + + native function writeSync(info: SysEventInfo): Result; + export native function addWatcher(watcher: Watcher): void; + export native function removeWatcher(watcher: Watcher): void; + export native function query(queryArg: QueryArg, rules: QueryRule[], querier: Querier): void; + export native function exportSysEvents(queryArg: QueryArg, rules: QueryRule[]): number; + export native function subscribe(rules: QueryRule[]): number; + export native function unsubscribe(): void; + export function write(info: SysEventInfo, callback: AsyncCallback): void { - let cb = (): Result => { return HiSysEventAni.write(info) } + let cb = (): Result => { return writeSync(info) } taskpool.execute(cb).then((ret: NullishType): void => { let retError = new BusinessError(); let writeResult: Result = ret as Result; @@ -65,7 +132,7 @@ export default namespace hiSysEvent { export function write(info: SysEventInfo): Promise { return new Promise((resolve: (v: undefined) => void, reject: (e: BusinessError) => void): void => { - let cb = (): Result => { return HiSysEventAni.write(info) } + let cb = (): Result => { return writeSync(info) } taskpool.execute(cb).then((ret: NullishType): void => { let retError = new BusinessError(); let writeResult: Result = ret as Result; diff --git a/interfaces/ets/ani/hisysevent/include/ani_callback_context.h b/interfaces/ets/ani/hisysevent/include/ani_callback_context.h new file mode 100644 index 0000000..6170607 --- /dev/null +++ b/interfaces/ets/ani/hisysevent/include/ani_callback_context.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANI_CALLBACK_CONTEXT_H +#define ANI_CALLBACK_CONTEXT_H + +#include +#include +#include + +namespace OHOS { +namespace HiviewDFX { +using CALLBACK_FUNC = std::function; +using RELEASE_FUNC = std::function; +using CallbackContextAni = struct CallbackContextAni { + ani_vm *vm = nullptr; + ani_ref ref = nullptr; + CALLBACK_FUNC callback; + RELEASE_FUNC release; + pid_t threadId; +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif // ANI_CALLBACK_CONTEXT_H diff --git a/interfaces/ets/ani/hisysevent/include/ani_callback_manager.h b/interfaces/ets/ani/hisysevent/include/ani_callback_manager.h new file mode 100644 index 0000000..78438dd --- /dev/null +++ b/interfaces/ets/ani/hisysevent/include/ani_callback_manager.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANI_CALLBACK_MANAGER_H +#define ANI_CALLBACK_MANAGER_H + +#include +#include +#include +#include +#include + +#include "ani_callback_context.h" + +namespace OHOS { +namespace HiviewDFX { +using TaskQueue = std::queue>; +class AniCallbackManager final { +public: + explicit AniCallbackManager() {} +public: + void Add(CallbackContextAni *context, CALLBACK_FUNC callback, RELEASE_FUNC release = nullptr); + void Release(); + +private: + void ImmediateRun(ani_vm *vm, bool needPop = false); + void Clear(TaskQueue& tasks); + +private: + std::atomic inCalling = false; + std::atomic IsReleased = false; + std::mutex managerMutex; + TaskQueue AniCallbacks; +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif // ANI_CALLBACK_MANAGER_H diff --git a/interfaces/ets/ani/hisysevent/include/ani_hisysevent_listener.h b/interfaces/ets/ani/hisysevent/include/ani_hisysevent_listener.h new file mode 100644 index 0000000..36499fd --- /dev/null +++ b/interfaces/ets/ani/hisysevent/include/ani_hisysevent_listener.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANI_HISYSEVENT_LISTENER_H +#define ANI_HISYSEVENT_LISTENER_H + +#include +#include +#include +#include +#include "ani_callback_context.h" +#include "hisysevent_base_listener.h" +#include "ani_callback_manager.h" + +namespace OHOS { +namespace HiviewDFX { +class AniHiSysEventListener : public HiSysEventBaseListener { +public: + AniHiSysEventListener(CallbackContextAni *context); + virtual ~AniHiSysEventListener(); + +public: + virtual void OnEvent(const std::string& domain, const std::string& eventName, const int eventType, + const std::string& eventDetail) override; + virtual void OnServiceDied() override; + +private: + CallbackContextAni *callbackContextAni; + std::shared_ptr aniCallbackManager; + +friend class HiSysEventManager; +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif // ANI_HISYSEVENT_LISTENER_H diff --git a/interfaces/ets/ani/hisysevent/include/ani_hisysevent_querier.h b/interfaces/ets/ani/hisysevent/include/ani_hisysevent_querier.h new file mode 100644 index 0000000..994159f --- /dev/null +++ b/interfaces/ets/ani/hisysevent/include/ani_hisysevent_querier.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANI_HISYSEVENT_QUERIER_H +#define ANI_HISYSEVENT_QUERIER_H + +#include +#include +#include +#include +#include + +#include "hisysevent_base_query_callback.h" +#include "ani_callback_manager.h" +#include "ani_callback_context.h" + +namespace OHOS { +namespace HiviewDFX { +using ON_COMPLETE_FUNC = std::function; +class AniHiSysEventQuerier : public HiSysEventBaseQueryCallback { +public: + AniHiSysEventQuerier(CallbackContextAni *context, ON_COMPLETE_FUNC handler); + virtual ~AniHiSysEventQuerier(); + +public: + virtual void OnQuery(const ::std::vector& sysEvents, + const std::vector& seq) override; + virtual void OnComplete(int32_t reason, int32_t total, int64_t seq) override; + +private: + CallbackContextAni *callbackContextAni; + ON_COMPLETE_FUNC onCompleteHandler; + std::shared_ptr aniCallbackManager; +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif // ANI_HISYSEVENT_QUERIER_H diff --git a/interfaces/ets/ani/hisysevent/include/hisysevent_ani.h b/interfaces/ets/ani/hisysevent/include/hisysevent_ani.h index 973cc26..d6e1164 100644 --- a/interfaces/ets/ani/hisysevent/include/hisysevent_ani.h +++ b/interfaces/ets/ani/hisysevent/include/hisysevent_ani.h @@ -49,8 +49,14 @@ enum AniArgsType { class HiSysEventAni { public: - static ani_object Write(ani_env *env, ani_object object, ani_object info); - + static ani_object WriteSync(ani_env *env, ani_object info); + static void AddWatcher(ani_env *env, ani_object watcher); + static void RemoveWatcher(ani_env *env, ani_object watcher); + static void Query(ani_env *env, ani_object queryArg, ani_array rules, ani_object querier); + static ani_double ExportSysEvents(ani_env *env, ani_object queryArg, ani_array rules); + static ani_double Subscribe(ani_env *env, ani_array rules); + static void Unsubscribe(ani_env *env); + private: static int32_t WriteInner(ani_env *env, const HiSysEventInfo &eventInfo); static void AppendParams(HiSysEvent::EventBase &eventBase, @@ -103,5 +109,4 @@ private: }; } // namespace HiviewDFX } // namespace OHOS - #endif // HITRACE_METER_ANI_H diff --git a/interfaces/ets/ani/hisysevent/include/hisysevent_ani_util.h b/interfaces/ets/ani/hisysevent/include/hisysevent_ani_util.h index e9645cb..8c43645 100644 --- a/interfaces/ets/ani/hisysevent/include/hisysevent_ani_util.h +++ b/interfaces/ets/ani/hisysevent/include/hisysevent_ani_util.h @@ -19,32 +19,54 @@ #include #include #include +#include +#include +#include +#include +#include +#include "hilog/log.h" namespace OHOS { namespace HiviewDFX { -constexpr char CLASS_NAME_RESULTINNER[] = "L@ohos/hiSysEvent/ResultInner;"; -constexpr char CLASS_NAME_INT[] = "Lstd/core/Int;"; -constexpr char CLASS_NAME_BOOLEAN[] = "Lstd/core/Boolean;"; -constexpr char CLASS_NAME_DOUBLE[] = "Lstd/core/Double;"; -constexpr char CLASS_NAME_STRING[] = "Lstd/core/String;"; -constexpr char CLASS_NAME_BIGINT[] = "Lescompat/BigInt;"; -constexpr char CLASS_NAME_ARRAY[] = "Lescompat/Array;"; -constexpr char CLASS_NAME_ITERATOR[] = "Lescompat/Iterator;"; -constexpr char CLASS_NAME_RECORD[] = "Lescompat/Record;"; +#undef LOG_DOMAIN +#define LOG_DOMAIN 0xD002D08 + +#undef LOG_TAG +#define LOG_TAG "ANI_HISYSEVENT_UTIL" + +enum EventTypeAni : int32_t { + FAULT = 1, + STATISTIC = 2, + SECURITY = 3, + BEHAVIOR = 4 +}; + +constexpr char CLASS_NAME_INT[] = "std.core.Int"; +constexpr char CLASS_NAME_BOOLEAN[] = "std.core.Boolean"; +constexpr char CLASS_NAME_DOUBLE[] = "std.core.Double"; +constexpr char CLASS_NAME_STACKTRACE[] = "std.core.StackTrace"; +constexpr char CLASS_NAME_STRING[] = "std.core.String"; +constexpr char CLASS_NAME_BIGINT[] = "escompat.BigInt"; +constexpr char CLASS_NAME_ARRAY[] = "escompat.Array"; +constexpr char CLASS_NAME_SYSEVENTINFOANI[] = "@ohos.hiSysEvent.SysEventInfoAni"; +constexpr char ENUM_NAME_EVENT_TYPE[] = "@ohos.hiSysEvent.hiSysEvent.EventType"; +constexpr char CLASS_NAME_HISYSEVENTANI[] = "@ohos.hiSysEvent.hiSysEvent"; +constexpr char CLASS_NAME_RESULTINNER[] = "@ohos.hiSysEvent.ResultInner"; +constexpr char CLASS_NAME_WATCHERANI[] = "@ohos.hiSysEvent.WatcherAni"; +constexpr char CLASS_NAME_QUERIERANI[] = "@ohos.hiSysEvent.QuerierAni"; +constexpr char CLASS_NAME_BUSINESSERROR[] = "@ohos.base.BusinessError"; +constexpr char CLASS_NAME_ITERATOR[] = "escompat.Iterator"; +constexpr char CLASS_NAME_RECORD[] = "escompat.Record"; +constexpr char EVENT_TYPE_ATTR[] = "eventType"; constexpr char FUNC_NAME_GETLONG[] = "getLong"; constexpr char FUNC_NAME_UNBOXED[] = "unboxed"; constexpr char FUNC_NAME_NEXT[] = "next"; -constexpr char CLASS_NAME_STACKTRACE[] = "Lstd/core/StackTrace;"; -constexpr int64_t DEFAULT_LINE_NUM = -1; -constexpr int FUNC_NAME_INDEX = 1; -constexpr int LINE_INFO_INDEX = 2; -constexpr int LINE_INDEX = 1; -constexpr char CALL_FUNC_INFO_DELIMITER = ' '; -constexpr char CALL_LINE_INFO_DELIMITER = ':'; -constexpr char PATH_DELIMITER = '/'; +constexpr char DOMAIN_ATTR[] = "domain"; +constexpr char NAME_ATTR[] = "name"; class HiSysEventAniUtil { public: + static std::string AniStringToStdString(ani_env *env, ani_string aniStr); static bool CheckKeyTypeString(const std::string &str); static bool IsArray(ani_env *env, ani_object object); static bool IsRefUndefined(ani_env *env, ani_ref ref); @@ -55,15 +77,63 @@ public: static std::map ParseRecord(ani_env *env, ani_ref recordRef); static std::string ParseStringValue(ani_env *env, ani_ref aniStrRef); static int ParseIntValue(ani_env *env, ani_ref elementRef); - static void GetBooleans(ani_env *env, ani_ref arrayRef, std::vector &bools); - static void GetDoubles(ani_env *env, ani_ref arrayRef, std::vector &doubles); - static void GetIntsToDoubles(ani_env *env, ani_ref arrayRef, std::vector &doubles); - static void GetStrings(ani_env *env, ani_ref arrayRef, std::vector &strs); - static void GetBigints(ani_env *env, ani_ref arrayRef, std::vector &bigints); + static bool GetBooleans(ani_env *env, ani_ref arrayRef, std::vector& bools); + static bool GetDoubles(ani_env *env, ani_ref arrayRef, std::vector& doubles); + static bool GetIntsToDoubles(ani_env *env, ani_ref arrayRef, std::vector& doubles); + static bool GetStrings(ani_env *env, ani_ref arrayRef, std::vector& strs); + static bool GetBigints(ani_env *env, ani_ref arrayRef, std::vector& bigints); + static ani_object WriteResult(ani_env *env, const std::pair& result); + static ani_object CreateDoubleUint64(ani_env *env, uint64_t number); + static ani_object CreateDoubleInt64(ani_env *env, int64_t number); + static ani_object CreateDoubleUint32(ani_env *env, uint32_t number); + static ani_object CreateDoubleInt32(ani_env *env, int number); + static ani_enum_item ToAniEnum(ani_env *env, EventTypeAni value); + static ani_object CreateStringValue(ani_env *env, const std::string& value); + static ani_object CreateDouble(ani_env *env, double number); + static ani_object CreateBool(ani_env *env, bool boolValue); + static void CreateHiSysEventInfoJsObject(ani_env *env, const std::string& jsonStr, ani_object& sysEventInfo); + static void CreateJsSysEventInfoArray(ani_env *env, const std::vector& originValues, + ani_array& sysEventInfoJsArray); + static void AppendInt32PropertyToJsObject(ani_env *env, const std::string& key, const int32_t& value, + ani_object& jsObj); + static void AppendStringPropertyToJsObject(ani_env *env, const std::string& key, const std::string& value, + ani_object& jsObj); + +public: static std::pair GetErrorDetailByRet(const int32_t retCode); - static ani_object WriteResult(ani_env *env, std::pair result); + static void ThrowAniError(ani_env *env, int32_t code, const std::string &message); + static void ThrowErrorByRet(ani_env *env, const int32_t retCode); + +public: + static ani_vm* GetAniVm(ani_env *env); + static ani_env* GetAniEnv(ani_vm *vm); + static ani_env* AttachAniEnv(ani_vm *vm); + static void DetachAniEnv(ani_vm *vm); + +public: + template + static typename std::unordered_map>>::iterator + CompareAndReturnCacheItem(ani_env *env, ani_object& standard, + std::unordered_map>>& resources) + { + auto iter = resources.begin(); + for (; iter != resources.end(); iter++) { + if (iter->second.first != getproctid()) { + continue; + } + ani_ref val = iter->first; + ani_boolean isEquals; + ani_status ret = env->Reference_StrictEquals(standard, static_cast(val), &isEquals); + if (ret != ANI_OK) { + continue; + } + if (isEquals) { + break; + } + } + return iter; + } }; } // namespace HiviewDFX } // namespace OHOS - #endif // HISYSEVENT_ANI_UTILS_H diff --git a/interfaces/ets/ani/hisysevent/include/ret_def.h b/interfaces/ets/ani/hisysevent/include/ret_def.h index 5d871b0..bb451f3 100644 --- a/interfaces/ets/ani/hisysevent/include/ret_def.h +++ b/interfaces/ets/ani/hisysevent/include/ret_def.h @@ -70,3 +70,4 @@ static constexpr int32_t ERR_ANI_LISTENER_NOT_FOUND = -107; } // namespace OHOS #endif // ANI_HISYSEVENT_RET_DEF_H + diff --git a/interfaces/ets/ani/hisysevent/src/ani_callback_manager.cpp b/interfaces/ets/ani/hisysevent/src/ani_callback_manager.cpp new file mode 100644 index 0000000..6ff6986 --- /dev/null +++ b/interfaces/ets/ani/hisysevent/src/ani_callback_manager.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_callback_manager.h" +#include "hisysevent_ani_util.h" +#include "hilog/log.h" +namespace OHOS { +namespace HiviewDFX { +#undef LOG_DOMAIN +#define LOG_DOMAIN 0xD002D08 + +#undef LOG_TAG +#define LOG_TAG "ANI_CALLBACK_MANAGER" +namespace { +constexpr int CONTEXT_INDEX = 0; +constexpr int CALLBACK_FUNC_INDEX = 1; +constexpr int RELEASE_FUNC_INDEX = 2; +} + +void RunCallback(ani_vm *vm, CallbackContextAni *context, + std::tuple& current) +{ + context->callback = std::get(current); + context->release = std::get(current); + if (context->callback != nullptr) { + context->callback(vm, context->ref, context->threadId); + } + if (context->release != nullptr) { + context->release(vm, context->threadId); + } +} + +void AniCallbackManager::Add(CallbackContextAni *context, CALLBACK_FUNC callback, + RELEASE_FUNC release) +{ + { + if (IsReleased.load(std::memory_order_acquire)) { + return; + } + std::lock_guard lock(managerMutex); + AniCallbacks.emplace(std::make_tuple(context, callback, [this, release, context] (ani_vm*, pid_t threadId) { + if (release == nullptr) { + this->ImmediateRun(context->vm, true); + } else { + // Destructor of JsCallbackManager will be called in release callback, + // so no need to call next callback in queue. + release(context->vm, threadId); + } + })); + if (inCalling.load(std::memory_order_acquire)) { + return; + } + } + ImmediateRun(context->vm); +} + +void AniCallbackManager::Release() +{ + IsReleased = true; + Clear(AniCallbacks); +} + +void AniCallbackManager::ImmediateRun(ani_vm *vm, bool needPop) +{ + inCalling = true; + std::tuple current; + CallbackContextAni *context; + { + if (IsReleased.load(std::memory_order_acquire)) { + return; + } + std::lock_guard lock(managerMutex); + if (needPop && !AniCallbacks.empty()) { + AniCallbacks.pop(); + } + + if (AniCallbacks.empty() && !IsReleased.load(std::memory_order_acquire)) { + inCalling = false; + return; + } + current = AniCallbacks.front(); + context = std::get(current); + if (context == nullptr || IsReleased.load(std::memory_order_acquire)) { + inCalling = false; + return; + } + } + if (IsReleased.load(std::memory_order_acquire)) { + return; + } + RunCallback(vm, context, current); +} + +void AniCallbackManager::Clear(TaskQueue& tasks) +{ + TaskQueue empty; + swap(empty, tasks); +} +} // HiviewDFX +} // OHOS diff --git a/interfaces/ets/ani/hisysevent/src/ani_hisysevent_listener.cpp b/interfaces/ets/ani/hisysevent/src/ani_hisysevent_listener.cpp new file mode 100644 index 0000000..7f1d81c --- /dev/null +++ b/interfaces/ets/ani/hisysevent/src/ani_hisysevent_listener.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_hisysevent_listener.h" +#include "hilog/log.h" +#include "hisysevent_ani_util.h" + +namespace OHOS { +namespace HiviewDFX { +#undef LOG_DOMAIN +#define LOG_DOMAIN 0xD002D08 + +#undef LOG_TAG +#define LOG_TAG "ANI_HISYSEVENT_LISTENER" + +namespace { +constexpr size_t ON_EVENT_PARAM_COUNT = 1; +} + +AniHiSysEventListener::AniHiSysEventListener(CallbackContextAni *context) +{ + callbackContextAni = context; + aniCallbackManager = std::make_shared(); +} + +AniHiSysEventListener::~AniHiSysEventListener() +{ + if (aniCallbackManager != nullptr) { + aniCallbackManager->Release(); + } + ani_env *env = nullptr; + ani_options aniArgs {0, nullptr}; + if (ANI_OK == callbackContextAni->vm->GetEnv(ANI_VERSION_1, &env) && env != nullptr) { + env->GlobalReference_Delete(callbackContextAni->ref); + } else if (ANI_OK == callbackContextAni->vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env) && env != nullptr) { + env->GlobalReference_Delete(callbackContextAni->ref); + callbackContextAni->vm->DetachCurrentThread(); + } else { + HILOG_WARN(LOG_CORE, "fail to delete the global reference."); + } + delete callbackContextAni; +} + +void AniHiSysEventListener::OnEvent(const std::string& domain, const std::string& eventName, const int eventType, + const std::string& eventDetail) +{ + aniCallbackManager->Add(callbackContextAni, + [this, domain, eventName, eventType, eventDetail] (ani_vm *vm, ani_ref ref, pid_t threadId) { + ani_env *env = HiSysEventAniUtil::AttachAniEnv(vm); + ani_object sysEventInfo = nullptr; + ani_class cls {}; + if (ANI_OK != env->FindClass(CLASS_NAME_SYSEVENTINFOANI, &cls)) { + HILOG_ERROR(LOG_CORE, "find Class %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + ani_method ctor {}; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + HILOG_ERROR(LOG_CORE, "get method %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + if (ANI_OK != env->Object_New(cls, ctor, &sysEventInfo)) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + HiSysEventAniUtil::CreateHiSysEventInfoJsObject(env, eventDetail, sysEventInfo); + ani_ref argv[ON_EVENT_PARAM_COUNT] = {sysEventInfo}; + ani_class watcherCls {}; + if (ANI_OK != env->FindClass(CLASS_NAME_WATCHERANI, &watcherCls)) { + HILOG_ERROR(LOG_CORE, "find class failed."); + return; + } + ani_ref onEvent {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast(ref), "onEvent", &onEvent)) { + HILOG_ERROR(LOG_CORE, "get Object_GetPropertyByName_Ref failed."); + return; + } + ani_ref result = nullptr; + if (ANI_OK != env->FunctionalObject_Call(static_cast(onEvent), ON_EVENT_PARAM_COUNT, + argv, &result)) { + HILOG_ERROR(LOG_CORE, "get FunctionalObject_Call onEvent failed."); + return; + } + HiSysEventAniUtil::DetachAniEnv(vm); + }); +} + +void AniHiSysEventListener::OnServiceDied() +{ + aniCallbackManager->Add(callbackContextAni, + [this] (ani_vm *vm, ani_ref ref, pid_t threadId) { + ani_env *env = HiSysEventAniUtil::AttachAniEnv(vm); + ani_class watcherCls {}; + if (ANI_OK != env->FindClass(CLASS_NAME_WATCHERANI, &watcherCls)) { + return; + } + ani_ref onServiceDied {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast(ref), "onServiceDied", + &onServiceDied)) { + return; + } + ani_ref result = nullptr; + ani_ref argv[] = {}; + if (ANI_OK != env->FunctionalObject_Call(static_cast(onServiceDied), 1, argv, &result)) { + HILOG_ERROR(LOG_CORE, "get FunctionalObject_Call onServiceDied failed."); + return; + } + HiSysEventAniUtil::DetachAniEnv(vm); + }); +} +} // HiviewDFX +} // OHOS diff --git a/interfaces/ets/ani/hisysevent/src/ani_hisysevent_querier.cpp b/interfaces/ets/ani/hisysevent/src/ani_hisysevent_querier.cpp new file mode 100644 index 0000000..3b087e4 --- /dev/null +++ b/interfaces/ets/ani/hisysevent/src/ani_hisysevent_querier.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_hisysevent_querier.h" +#include "hilog/log.h" +#include "hisysevent_ani_util.h" +namespace OHOS { +namespace HiviewDFX { +#undef LOG_DOMAIN +#define LOG_DOMAIN 0xD002D08 + +#undef LOG_TAG +#define LOG_TAG "ANI_HISYSEVENT_QUERIER" + +namespace { +constexpr size_t ON_QUERY_PARAM_COUNT = 1; +constexpr size_t ON_QUERY_COMPLTE_COUNT = 3; +} + +AniHiSysEventQuerier::AniHiSysEventQuerier(CallbackContextAni *context, ON_COMPLETE_FUNC handler) +{ + callbackContextAni = context; + onCompleteHandler = handler; + aniCallbackManager = std::make_shared(); +} + +AniHiSysEventQuerier::~AniHiSysEventQuerier() +{ + if (aniCallbackManager != nullptr) { + aniCallbackManager->Release(); + } + ani_env *env = nullptr; + ani_options aniArgs {0, nullptr}; + if (ANI_OK == callbackContextAni->vm->GetEnv(ANI_VERSION_1, &env) && env != nullptr) { + env->GlobalReference_Delete(callbackContextAni->ref); + } else if (ANI_OK == callbackContextAni->vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env) && env != nullptr) { + env->GlobalReference_Delete(callbackContextAni->ref); + callbackContextAni->vm->DetachCurrentThread(); + } else { + HILOG_WARN(LOG_CORE, "fail to delete the global reference."); + } + delete callbackContextAni; +} + +void AniHiSysEventQuerier::OnQuery(const std::vector& sysEvents, + const std::vector& seq) +{ + aniCallbackManager->Add(callbackContextAni, + [this, sysEvents, seq] (ani_vm *vm, ani_ref ref, pid_t threadId) { + ani_env *env = HiSysEventAniUtil::AttachAniEnv(vm); + ani_array sysEventInfoJsArray = nullptr; + ani_class cls {}; + if (ANI_OK != env->FindClass(CLASS_NAME_SYSEVENTINFOANI, &cls)) { + HILOG_ERROR(LOG_CORE, "find Class %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + if (ANI_OK != env->Array_New(sysEvents.size(), nullptr, &sysEventInfoJsArray)) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + HiSysEventAniUtil::CreateJsSysEventInfoArray(env, sysEvents, sysEventInfoJsArray); + ani_ref argv[ON_QUERY_PARAM_COUNT] = {sysEventInfoJsArray}; + ani_class querierCls {}; + if (ANI_OK != env->FindClass(CLASS_NAME_QUERIERANI, &querierCls)) { + return; + } + ani_ref onQuery {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast(ref), "onQuery", &onQuery)) { + HILOG_ERROR(LOG_CORE, "get onQuery failed."); + return; + } + ani_ref result = nullptr; + if (ANI_OK != env->FunctionalObject_Call(static_cast(onQuery), ON_QUERY_PARAM_COUNT, + argv, &result)) { + HILOG_ERROR(LOG_CORE, "failed to call OnQuery function."); + return; + } + HiSysEventAniUtil::DetachAniEnv(vm); + }); +} + +void AniHiSysEventQuerier::OnComplete(int32_t reason, int32_t total, int64_t seq) +{ + aniCallbackManager->Add(callbackContextAni, + [this, reason, total, seq] (ani_vm *vm, ani_ref ref, pid_t threadId) { + ani_env *env = HiSysEventAniUtil::AttachAniEnv(vm); + ani_object reasonJsParam = nullptr; + reasonJsParam = HiSysEventAniUtil::CreateDoubleInt32(env, reason); + ani_object totalJsParam = nullptr; + totalJsParam = HiSysEventAniUtil::CreateDoubleInt32(env, total); + ani_object seqJsParm = nullptr; + seqJsParm = HiSysEventAniUtil::CreateDoubleInt64(env, seq); + ani_ref argv[ON_QUERY_COMPLTE_COUNT] = {reasonJsParam, totalJsParam, seqJsParm}; + ani_class querierCls {}; + if (ANI_OK != env->FindClass(CLASS_NAME_QUERIERANI, &querierCls)) { + return; + } + ani_ref onComplete {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast(ref), "onComplete", &onComplete)) { + HILOG_ERROR(LOG_CORE, "get onQuery failed."); + return; + } + ani_ref result = nullptr; + if (ANI_OK != env->FunctionalObject_Call(static_cast(onComplete), ON_QUERY_COMPLTE_COUNT, + argv, &result)) { + HILOG_ERROR(LOG_CORE, "failed to call OnComplete function."); + return; + } + HiSysEventAniUtil::DetachAniEnv(vm); + }, [this] (ani_vm *vm, pid_t threadId) { + if (this->onCompleteHandler != nullptr && this->callbackContextAni != nullptr) { + this->onCompleteHandler(vm, this->callbackContextAni->ref); + } + }); +} +} // HiviewDFX +} // OHOS diff --git a/interfaces/ets/ani/hisysevent/src/hisysevent_ani.cpp b/interfaces/ets/ani/hisysevent/src/hisysevent_ani.cpp index 1147c32..e1bc2fe 100644 --- a/interfaces/ets/ani/hisysevent/src/hisysevent_ani.cpp +++ b/interfaces/ets/ani/hisysevent/src/hisysevent_ani.cpp @@ -17,28 +17,45 @@ #include #include "hisysevent_ani.h" - +#include "ani_hisysevent_querier.h" +#include "ani_hisysevent_listener.h" +#include "ani_callback_context.h" +#include "def.h" +#include "hisysevent_base_manager.h" +#include "hisysevent_rules.h" #include "hilog/log.h" #include "hilog/log_cpp.h" #include "hisysevent_ani_util.h" -#include "write_controller.h" -#include "stringfilter.h" #include "hisysevent.h" #include "ret_code.h" #include "ret_def.h" +#include "rule_type.h" #include "write_controller.h" +#include "stringfilter.h" using namespace OHOS::HiviewDFX; - #undef LOG_DOMAIN #define LOG_DOMAIN 0xD002D08 #undef LOG_TAG #define LOG_TAG "ANI_HISYSEVENT" - namespace { -constexpr char CLASS_NAME_HISYSEVENTANI[] = "L@ohos/hiSysEvent/HiSysEventAni;"; - +using ANI_LISTENER_PAIR = std::pair>; +using ANI_QUERIER_PAIR = std::pair>; +constexpr long long DEFAULT_TIME_STAMP = -1; +constexpr int DEFAULT_EVENT_COUNT = 1000; +constexpr int TIME_STAMP_LENGTH = 13; +std::mutex g_listenerMapMutex; +std::unordered_map listeners; +std::mutex g_querierMapMutex; +std::unordered_map queriers; +constexpr int64_t DEFAULT_LINE_NUM = -1; +constexpr int FUNC_NAME_INDEX = 1; +constexpr int LINE_INFO_INDEX = 2; +constexpr int LINE_INDEX = 1; +constexpr char CALL_FUNC_INFO_DELIMITER = ' '; +constexpr char CALL_LINE_INFO_DELIMITER = ':'; +constexpr char PATH_DELIMITER = '/'; const std::pair OBJECT_TYPE[] = { {CLASS_NAME_BOOLEAN, AniArgsType::ANI_BOOLEAN}, {CLASS_NAME_INT, AniArgsType::ANI_INT}, @@ -60,7 +77,7 @@ static AniArgsType GetArgType(ani_env *env, ani_object elementObj) } ani_boolean isInstance = ANI_FALSE; if (ANI_OK != env->Object_InstanceOf(elementObj, cls, &isInstance)) { - HILOG_ERROR(LOG_CORE, "Object_InstanceOf %{public}s failed", objType.first); + HILOG_ERROR(LOG_CORE, "check instance failed for type '%{public}s'", objType.first); continue; } if (static_cast(isInstance)) { @@ -76,64 +93,75 @@ static bool IsValidParamType(AniArgsType type) type < static_cast(AniArgsType::ANI_UNDEFINED)); } -static AniArgsType GetArrayType(ani_env *env, ani_array_ref arrayRef) +static AniArgsType GetArrayType(ani_env *env, ani_array arrayRef) { ani_size index = 0; ani_ref valueRef {}; - if (ANI_OK != env->Array_Get_Ref(static_cast(arrayRef), index, &valueRef)) { + if (ANI_OK != env->Array_Get(arrayRef, index, &valueRef)) { HILOG_ERROR(LOG_CORE, "fail to get first element in array."); return AniArgsType::ANI_UNKNOWN; } return GetArgType(env, static_cast(valueRef)); } -static bool AddArrayParamToEventInfo(ani_env *env, const std::string& key, ani_ref arrayRef, HiSysEventInfo& info) +static bool AddArrayParamToEventInfoExec(ani_env *env, const std::string& key, ani_ref arrayRef, + AniArgsType arrayType, HiSysEventInfo& info) { - ani_size size = 0; - if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &size)) { - HILOG_ERROR(LOG_CORE, "get array length failed"); - return false; - } - AniArgsType arrayType = GetArrayType(env, static_cast(arrayRef)); - if (!IsValidParamType(arrayType)) { - return false; - } switch (arrayType) { case AniArgsType::ANI_BOOLEAN: { std::vector bools; - HiSysEventAniUtil::GetBooleans(env, arrayRef, bools); - info.params[key] = bools; + if (HiSysEventAniUtil::GetBooleans(env, arrayRef, bools)) { + info.params[key] = bools; + return true; + } break; } case AniArgsType::ANI_INT: { std::vector doubles; - HiSysEventAniUtil::GetIntsToDoubles(env, arrayRef, doubles); - info.params[key] = doubles; + if (HiSysEventAniUtil::GetIntsToDoubles(env, arrayRef, doubles)) { + info.params[key] = doubles; + return true; + } break; } case AniArgsType::ANI_DOUBLE: { std::vector doubles; - HiSysEventAniUtil::GetDoubles(env, arrayRef, doubles); - info.params[key] = doubles; + if (HiSysEventAniUtil::GetDoubles(env, arrayRef, doubles)) { + info.params[key] = doubles; + return true; + } break; } case AniArgsType::ANI_STRING: { std::vector strs; - HiSysEventAniUtil::GetStrings(env, arrayRef, strs); - info.params[key] = strs; + if (HiSysEventAniUtil::GetStrings(env, arrayRef, strs)) { + info.params[key] = strs; + return true; + } break; } case AniArgsType::ANI_BIGINT:{ std::vector bigints; - HiSysEventAniUtil::GetBigints(env, arrayRef, bigints); - info.params[key] = bigints; + if (HiSysEventAniUtil::GetBigints(env, arrayRef, bigints)) { + info.params[key] = bigints; + return true; + } break; } default: HILOG_ERROR(LOG_CORE, "Unexpected type"); return false; } - return true; + return false; +} + +static bool AddArrayParamToEventInfo(ani_env *env, const std::string& key, ani_ref arrayRef, HiSysEventInfo& info) +{ + AniArgsType arrayType = GetArrayType(env, static_cast(arrayRef)); + if (!IsValidParamType(arrayType)) { + return false; + } + return AddArrayParamToEventInfoExec(env, key, arrayRef, arrayType, info); } static bool AddParamToEventInfo(ani_env *env, const std::string& key, ani_ref value, HiSysEventInfo& info) @@ -191,42 +219,213 @@ static bool ParseParamsInSysEventInfo(ani_env *env, ani_ref params, HiSysEventIn return true; } +static ListenerRule ParseListenerRule(ani_env *env, const ani_object value) +{ + ani_ref domainRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(value, "domain", &domainRef)) { + HILOG_ERROR(LOG_CORE, "get property domain failed"); + return ListenerRule("", RuleType::WHOLE_WORD); + } + std::string domain = HiSysEventAniUtil::ParseStringValue(env, domainRef); + ani_ref nameRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(value, "name", &nameRef)) { + HILOG_ERROR(LOG_CORE, "get property name failed"); + return ListenerRule("", RuleType::WHOLE_WORD); + } + std::string name = HiSysEventAniUtil::ParseStringValue(env, nameRef); + ani_ref tagRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(value, "tag", &tagRef)) { + HILOG_ERROR(LOG_CORE, "get property tag failed"); + return ListenerRule("", RuleType::WHOLE_WORD); + } + std::string tag = ""; + if (!HiSysEventAniUtil::IsRefUndefined(env, tagRef)) { + tag = HiSysEventAniUtil::ParseStringValue(env, tagRef); + } + ani_ref ruleTypeRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(value, "ruleType", &ruleTypeRef)) { + HILOG_ERROR(LOG_CORE, "get property ruleType failed"); + return ListenerRule("", RuleType::WHOLE_WORD); + } + ani_enum_item ruleTypeItem = static_cast(ruleTypeRef); + int32_t ruleTypeValue; + if (ANI_OK != env->EnumItem_GetValue_Int(ruleTypeItem, &ruleTypeValue)) { + HILOG_ERROR(LOG_CORE, "get enum failed"); + return ListenerRule("", RuleType::WHOLE_WORD); + } + int32_t ruleType = static_cast(ruleTypeValue); + return ListenerRule(domain, name, tag, RuleType(ruleType)); +} + +static void ParseWatcher(ani_env *env, ani_object watcher, std::vector& listenerRules) +{ + ani_ref rulesRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(watcher, "rules", &rulesRef)) { + HILOG_ERROR(LOG_CORE, "get property rules failed"); + return; + } + ani_size size; + if (ANI_OK != env->Array_GetLength(static_cast(rulesRef), &size)) { + HILOG_ERROR(LOG_CORE, "get array failed"); + return; + } + for (ani_size i = 0; i < size ; i++) { + ani_ref value; + auto status = env->Array_Get(static_cast(rulesRef), i, &value); + if (status != ANI_OK) { + HILOG_ERROR(LOG_CORE, "get %{public}zu item from array failed", i); + return; + } + listenerRules.emplace_back(ParseListenerRule(env, static_cast(value))); + } +} + +static QueryRule ParseQueryRule(ani_env *env, const ani_object value) +{ + ani_ref namesRef {}; + std::vector names; + if (ANI_OK != env->Object_GetPropertyByName_Ref(value, "names", &namesRef)) { + HILOG_ERROR(LOG_CORE, "get property names failed"); + return QueryRule("", names); + } + ani_size size; + if (ANI_OK != env->Array_GetLength(static_cast(namesRef), &size)) { + HILOG_ERROR(LOG_CORE, "get array failed"); + return QueryRule("", names); + } + for (ani_size i = 0; i < size ; i++) { + ani_ref value; + auto status = env->Array_Get(static_cast(namesRef), i, &value); + if (status != ANI_OK) { + return QueryRule("", names); + } + std::string result = HiSysEventAniUtil::ParseStringValue(env, value); + names.emplace_back(HiSysEventAniUtil::ParseStringValue(env, value)); + } + ani_ref domainRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(value, "domain", &domainRef)) { + HILOG_ERROR(LOG_CORE, "get property domain failed"); + return QueryRule("", names); + } + std::string domain = HiSysEventAniUtil::ParseStringValue(env, domainRef); + ani_ref conditionRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(value, "condition", &conditionRef)) { + HILOG_ERROR(LOG_CORE, "get property condition failed"); + } + std::string condition = ""; + if (!HiSysEventAniUtil::IsRefUndefined(env, conditionRef)) { + condition = HiSysEventAniUtil::ParseStringValue(env, conditionRef); + } + return QueryRule(domain, names, RuleType::WHOLE_WORD, 0, condition); +} + +static bool IsQueryRuleValid(ani_env *env, const QueryRule& rule) +{ + auto domain = rule.GetDomain(); + if (!StringFilter::GetInstance().IsValidName(domain, MAX_DOMAIN_LENGTH)) { + HiSysEventAniUtil::ThrowErrorByRet(env, AniInnerError::ERR_INVALID_DOMAIN_IN_QUERY_RULE); + return false; + } + auto names = rule.GetEventList(); + if (std::any_of(names.begin(), names.end(), [] (auto& name) { + return !StringFilter::GetInstance().IsValidName(name, MAX_EVENT_NAME_LENGTH); + })) { + HiSysEventAniUtil::ThrowErrorByRet(env, AniInnerError::ERR_INVALID_EVENT_NAME_IN_QUERY_RULE); + return false; + } + return true; +} + +static int32_t ParseQueryRules(ani_env *env, ani_array rulesAni, std::vector &rules) +{ + ani_size size; + if (ANI_OK != env->Array_GetLength(static_cast(rulesAni), &size)) { + HILOG_ERROR(LOG_CORE, "get array failed"); + return ERR_ANI_PARSED_FAILED; + } + for (ani_size i = 0; i < size ; i++) { + ani_ref value; + auto status = env->Array_Get(static_cast(rulesAni), i, &value); + if (status != ANI_OK) { + HILOG_ERROR(LOG_CORE, "get %{public}zu item from array failed", i); + return ERR_ANI_PARSED_FAILED; + } + auto queryRule = ParseQueryRule(env, static_cast(value)); + if (IsQueryRuleValid(env, queryRule)) { + rules.emplace_back(queryRule); + } else { + return ERR_ANI_PARSED_FAILED; + } + } + return ANI_SUCCESS; +} + +static void ParseQueryArg(ani_env *env, ani_object queryArgAni, QueryArg &queryArg) +{ + ani_double beginTimeRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Double(queryArgAni, "beginTime", &beginTimeRef)) { + HILOG_ERROR(LOG_CORE, "get property beginTime failed,"); + } + queryArg.beginTime = static_cast(beginTimeRef); + ani_double endTimeRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Double(queryArgAni, "endTime", &endTimeRef)) { + HILOG_ERROR(LOG_CORE, "get property endTime failed"); + } + queryArg.endTime = static_cast(endTimeRef); + ani_double maxEventsRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Double(queryArgAni, "maxEvents", &maxEventsRef)) { + HILOG_ERROR(LOG_CORE, "get property maxEvents failed"); + } + queryArg.maxEvents = static_cast(maxEventsRef); + ani_ref fromSeqRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(queryArgAni, "fromSeq", &fromSeqRef)) { + HILOG_ERROR(LOG_CORE, "get property fromSeq failed"); + } + if (!HiSysEventAniUtil::IsRefUndefined(env, fromSeqRef)) { + queryArg.fromSeq = HiSysEventAniUtil::ParseBigintValue(env, fromSeqRef); + } + ani_ref toSeqRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Ref(queryArgAni, "toSeq", &toSeqRef)) { + HILOG_ERROR(LOG_CORE, "get property toSeq failed"); + } + if (!HiSysEventAniUtil::IsRefUndefined(env, toSeqRef)) { + queryArg.toSeq = HiSysEventAniUtil::ParseBigintValue(env, toSeqRef); + } +} + static void ParseSysEventInfo(ani_env *env, ani_object info, HiSysEventInfo& eventInfo) { ani_ref domainRef {}; if (ANI_OK != env->Object_GetPropertyByName_Ref(info, "domain", &domainRef)) { - HILOG_ERROR(LOG_CORE, "Object_GetPropertyByName_Ref domain failed"); + HILOG_ERROR(LOG_CORE, "get property domain failed"); return; } eventInfo.domain = HiSysEventAniUtil::ParseStringValue(env, domainRef); - ani_ref nameRef {}; if (ANI_OK != env->Object_GetPropertyByName_Ref(info, "name", &nameRef)) { - HILOG_ERROR(LOG_CORE, "Object_GetPropertyByName_Ref name failed"); + HILOG_ERROR(LOG_CORE, "get property name failed"); return; } eventInfo.name = HiSysEventAniUtil::ParseStringValue(env, nameRef); - ani_ref eventTypeRef {}; if (ANI_OK != env->Object_GetPropertyByName_Ref(info, "eventType", &eventTypeRef)) { - HILOG_ERROR(LOG_CORE, "Object_GetPropertyByName_Ref eventType failed"); + HILOG_ERROR(LOG_CORE, "get property eventType failed"); return; } ani_enum_item eventTypeItem = static_cast(eventTypeRef); int32_t eventTypeValue; if (ANI_OK != env->EnumItem_GetValue_Int(eventTypeItem, &eventTypeValue)) { - HILOG_ERROR(LOG_CORE, "EnumItem_GetValue_Int failed"); + HILOG_ERROR(LOG_CORE, "get enum failed"); return; } eventInfo.eventType = static_cast(eventTypeValue); - ani_ref paramsRef {}; if (ANI_OK != env->Object_GetPropertyByName_Ref(info, "params", ¶msRef)) { - HILOG_ERROR(LOG_CORE, "Object_GetPropertyByName_Ref params failed"); + HILOG_ERROR(LOG_CORE, "get property params failed"); return; } if (!ParseParamsInSysEventInfo(env, paramsRef, eventInfo)) { - HILOG_ERROR(LOG_CORE, "ParseParamsInSysEventInfo params failed"); + HILOG_ERROR(LOG_CORE, "get property params failed"); return; } } @@ -326,7 +525,7 @@ static void GetStack(ani_env *env, std::string &stackTrace) } for (ani_size i = 0; i < length; i++) { ani_ref stackTraceElementRef = nullptr; - status = env->Array_Get_Ref(static_cast(stackTraceElementArray), i, &stackTraceElementRef); + status = env->Array_Get(static_cast(stackTraceElementArray), i, &stackTraceElementRef); if (ANI_OK != status) { HILOG_ERROR(LOG_CORE, "get %{public}zu item from array failed", i); } @@ -336,7 +535,7 @@ static void GetStack(ani_env *env, std::string &stackTrace) if (ANI_OK != status) { HILOG_ERROR(LOG_CORE, "call method toString failed"); } - stackTrace = HiSysEventAniUtil::ParseStringValue(env, stackTraceStr); + stackTrace = HiSysEventAniUtil::AniStringToStdString(env, static_cast(stackTraceStr)); } } @@ -373,36 +572,197 @@ int32_t HiSysEventAni::WriteInner(ani_env *env, const HiSysEventInfo &eventInfo) return eventBase.GetRetCode(); } -ani_object HiSysEventAni::Write(ani_env *env, [[maybe_unused]] ani_object object, ani_object info) +ani_object HiSysEventAni::WriteSync(ani_env *env, ani_object info) { if (!HiSysEventAniUtil::IsSystemAppCall()) { return HiSysEventAniUtil::WriteResult(env, {AniError::ERR_NON_SYS_APP_PERMISSION, "Permission denied. " "System api can be invoked only by system applications."}); } - HiSysEventInfo eventInfo; ParseSysEventInfo(env, info, eventInfo); - - int32_t eventWroteResult = HiSysEventAni::WriteInner(env, eventInfo); + int32_t eventWroteResult = HiSysEventAni::WriteInner(env, eventInfo); return HiSysEventAniUtil::WriteResult(env, HiSysEventAniUtil::GetErrorDetailByRet(eventWroteResult)); } +void HiSysEventAni::AddWatcher(ani_env *env, ani_object watcher) +{ + if (!HiSysEventAniUtil::IsSystemAppCall()) { + HiSysEventAniUtil::ThrowAniError(env, AniError::ERR_NON_SYS_APP_PERMISSION, "Permission denied. " + "System api can be invoked only by system applications."); + return; + } + ani_vm *vm = HiSysEventAniUtil::GetAniVm(env); + std::vector rules; + ParseWatcher(env, watcher, rules); + CallbackContextAni *callbackContextAni = new CallbackContextAni(); + callbackContextAni->vm = vm; + callbackContextAni->threadId = getproctid(); + ani_ref listenerRef; + env->GlobalReference_Create(static_cast(watcher), &listenerRef); + callbackContextAni->ref = listenerRef; + std::shared_ptr listener = std::make_shared(callbackContextAni); + auto ret = HiSysEventBaseManager::AddListener(listener, rules); + if (ret != ANI_SUCCESS) { + HILOG_ERROR(LOG_CORE, "failed to add event listener, result code is %{public}d.", ret); + delete callbackContextAni; + HiSysEventAniUtil::ThrowErrorByRet(env, ret); + return; + } + std::lock_guard lock(g_listenerMapMutex); + listeners[callbackContextAni->ref] = std::make_pair(callbackContextAni->threadId, listener); +} + +void HiSysEventAni::RemoveWatcher(ani_env *env, ani_object watcher) +{ + if (!HiSysEventAniUtil::IsSystemAppCall()) { + HiSysEventAniUtil::ThrowAniError(env, AniError::ERR_NON_SYS_APP_PERMISSION, "Permission denied. " + "System api can be invoked only by system applications."); + return; + } + auto iter = HiSysEventAniUtil::CompareAndReturnCacheItem(env, watcher, listeners); + if (iter == listeners.end()) { + HILOG_ERROR(LOG_CORE, "listener not exist."); + HiSysEventAniUtil::ThrowErrorByRet(env, ERR_ANI_LISTENER_NOT_FOUND); + return; + } + if (auto ret = HiSysEventBaseManager::RemoveListener(iter->second.second); + ret != ANI_SUCCESS) { + HILOG_ERROR(LOG_CORE, "failed to remove event listener, result code is %{public}d.", ret); + HiSysEventAniUtil::ThrowErrorByRet(env, ret); + return; + } + std::lock_guard lock(g_listenerMapMutex); + listeners.erase(iter); +} + +void HiSysEventAni::Query(ani_env *env, ani_object queryArgAni, ani_array rulesAni, ani_object querierAni) +{ + if (!HiSysEventAniUtil::IsSystemAppCall()) { + HiSysEventAniUtil::ThrowAniError(env, AniError::ERR_NON_SYS_APP_PERMISSION, "Permission denied. " + "System api can be invoked only by system applications."); + return; + } + ani_vm *vm = HiSysEventAniUtil::GetAniVm(env); + QueryArg queryArg = { DEFAULT_TIME_STAMP, DEFAULT_TIME_STAMP, DEFAULT_EVENT_COUNT }; + ParseQueryArg(env, queryArgAni, queryArg); + std::vector rules; + auto result = ParseQueryRules(env, rulesAni, rules); + if (result != SUCCESS) { + HILOG_ERROR(LOG_CORE, "failed to parse query rules, result code is %{public}d.", result); + return; + } + CallbackContextAni *callbackContextAni = new CallbackContextAni(); + callbackContextAni->vm = vm; + callbackContextAni->threadId = getproctid(); + ani_ref querierRef; + env->GlobalReference_Create(static_cast(querierAni), &querierRef); + callbackContextAni->ref = querierRef; + std::shared_ptr querier = std::make_shared(callbackContextAni, + [] (ani_vm *vm, ani_ref ref) { + ani_object querierObj = static_cast(ref); + std::lock_guard lock(g_querierMapMutex); + ani_env *env = HiSysEventAniUtil::AttachAniEnv(vm); + auto iter = HiSysEventAniUtil::CompareAndReturnCacheItem(env, querierObj, queriers); + if (iter != queriers.end()) { + queriers.erase(iter); + } + HiSysEventAniUtil::DetachAniEnv(vm); + }); + auto ret = HiSysEventBaseManager::Query(queryArg, rules, querier); + if (ret != ANI_SUCCESS) { + HILOG_ERROR(LOG_CORE, "failed to query hisysevent, result code is %{public}d.", ret); + HiSysEventAniUtil::ThrowErrorByRet(env, ret); + return; + } + std::lock_guard lock(g_querierMapMutex); + queriers[callbackContextAni->ref] = std::make_pair(callbackContextAni->threadId, querier); +} + +ani_double HiSysEventAni::ExportSysEvents(ani_env *env, ani_object queryArgAni, ani_array rulesAni) +{ + if (!HiSysEventAniUtil::IsSystemAppCall()) { + HiSysEventAniUtil::ThrowAniError(env, AniError::ERR_NON_SYS_APP_PERMISSION, "Permission denied. " + "System api can be invoked only by system applications."); + return static_cast(0); + } + QueryArg queryArg = { DEFAULT_TIME_STAMP, DEFAULT_TIME_STAMP, DEFAULT_EVENT_COUNT }; + ParseQueryArg(env, queryArgAni, queryArg); + std::vector rules; + auto result = ParseQueryRules(env, rulesAni, rules); + if (result != SUCCESS) { + HILOG_ERROR(LOG_CORE, "failed to parse query rules, result code is %{public}d.", result); + return static_cast(result); + } + auto ret = HiSysEventBaseManager::Export(queryArg, rules); + if (std::to_string(ret).length() < TIME_STAMP_LENGTH) { + HILOG_ERROR(LOG_CORE, "failed to export event"); + int32_t retCode = static_cast(ret); + HiSysEventAniUtil::ThrowErrorByRet(env, retCode); + return static_cast(0); + } + return static_cast(ret); +} + +ani_double HiSysEventAni::Subscribe(ani_env *env, ani_array rulesAni) +{ + if (!HiSysEventAniUtil::IsSystemAppCall()) { + HiSysEventAniUtil::ThrowAniError(env, AniError::ERR_NON_SYS_APP_PERMISSION, "Permission denied. " + "System api can be invoked only by system applications."); + return static_cast(0); + } + std::vector rules; + auto result = ParseQueryRules(env, rulesAni, rules); + if (result != SUCCESS) { + HILOG_ERROR(LOG_CORE, "failed to parse query rules, result code is %{public}d.", result); + return static_cast(result); + } + auto ret = HiSysEventBaseManager::Subscribe(rules); + if (std::to_string(ret).length() < TIME_STAMP_LENGTH) { + HILOG_ERROR(LOG_CORE, "failed to subscribe event."); + int32_t retCode = static_cast(ret); + HiSysEventAniUtil::ThrowErrorByRet(env, retCode); + return static_cast(0); + } + return static_cast(ret); +} + +void HiSysEventAni::Unsubscribe(ani_env *env) +{ + if (!HiSysEventAniUtil::IsSystemAppCall()) { + HiSysEventAniUtil::ThrowAniError(env, AniError::ERR_NON_SYS_APP_PERMISSION, "Permission denied. " + "System api can be invoked only by system applications."); + return; + } + auto ret = HiSysEventBaseManager::Unsubscribe(); + if (ret != ANI_SUCCESS) { + HILOG_ERROR(LOG_CORE, "failed to unsubscribe, result code is %{public}d.", ret); + int32_t retCode = static_cast(ret); + HiSysEventAniUtil::ThrowErrorByRet(env, retCode); + } +} + ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { ani_env *env; if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { return ANI_ERROR; } - ani_class cls {}; - if (ANI_OK != env->FindClass(CLASS_NAME_HISYSEVENTANI, &cls)) { - return ANI_ERROR; + ani_namespace ns {}; + if (ANI_OK != env->FindNamespace(CLASS_NAME_HISYSEVENTANI, &ns)) { + return ANI_INVALID_ARGS; } std::array methods = { - ani_native_function {"write", nullptr, reinterpret_cast(HiSysEventAni::Write) }, + ani_native_function {"writeSync", nullptr, reinterpret_cast(HiSysEventAni::WriteSync) }, + ani_native_function {"addWatcher", nullptr, reinterpret_cast(HiSysEventAni::AddWatcher) }, + ani_native_function {"removeWatcher", nullptr, reinterpret_cast(HiSysEventAni::RemoveWatcher) }, + ani_native_function {"query", nullptr, reinterpret_cast(HiSysEventAni::Query) }, + ani_native_function {"exportSysEvents", nullptr, reinterpret_cast(HiSysEventAni::ExportSysEvents) }, + ani_native_function {"subscribe", nullptr, reinterpret_cast(HiSysEventAni::Subscribe) }, + ani_native_function {"unsubscribe", nullptr, reinterpret_cast(HiSysEventAni::Unsubscribe) }, }; - if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { - return ANI_ERROR; + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) { + return ANI_INVALID_TYPE; }; *result = ANI_VERSION_1; return ANI_OK; diff --git a/interfaces/ets/ani/hisysevent/src/hisysevent_ani_util.cpp b/interfaces/ets/ani/hisysevent/src/hisysevent_ani_util.cpp index ff41e4f..91a78a4 100644 --- a/interfaces/ets/ani/hisysevent/src/hisysevent_ani_util.cpp +++ b/interfaces/ets/ani/hisysevent/src/hisysevent_ani_util.cpp @@ -14,28 +14,38 @@ */ #include "hisysevent_ani_util.h" - #include "def.h" -#include "hilog/log.h" #include "hilog/log_cpp.h" #include "ipc_skeleton.h" #include "ret_code.h" #include "ret_def.h" +#include "json/json.h" #include "tokenid_kit.h" +using namespace OHOS::HiviewDFX; #undef LOG_DOMAIN #define LOG_DOMAIN 0xD002D08 #undef LOG_TAG #define LOG_TAG "ANI_HISYSEVENT_UTIL" - -using namespace OHOS::HiviewDFX; -static const std::string INVALID_KEY_TYPE_ARR[] = { +namespace { +constexpr char DOMAIN__KEY[] = "domain_"; +constexpr char NAME__KEY[] = "name_"; +constexpr char TYPE__KEY[] = "type_"; +const std::string INVALID_KEY_TYPE_ARR[] = { "[object Object]", "null", "()", "," }; +} + +static const std::map ANI_EVENTTYPE_INDEX_MAP = { + {EventTypeAni::FAULT, 0}, + {EventTypeAni::STATISTIC, 1}, + {EventTypeAni::SECURITY, 2}, + {EventTypeAni::BEHAVIOR, 3}, +}; bool HiSysEventAniUtil::CheckKeyTypeString(const std::string& str) { @@ -81,22 +91,22 @@ bool HiSysEventAniUtil::IsSystemAppCall() int64_t HiSysEventAniUtil::ParseBigintValue(ani_env *env, ani_ref elementRef) { - ani_long longnum = static_cast(0); + ani_long longNum = 0; ani_class cls {}; if (ANI_OK != env->FindClass(CLASS_NAME_BIGINT, &cls)) { HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_BIGINT); - return static_cast(longnum); + return static_cast(longNum); } ani_method getLongMethod {}; - if (ANI_OK != env->Class_FindMethod(cls, FUNC_NAME_GETLONG, ":J", &getLongMethod)) { + if (ANI_OK != env->Class_FindMethod(cls, FUNC_NAME_GETLONG, ":l", &getLongMethod)) { HILOG_ERROR(LOG_CORE, "find method %{public}s failed", FUNC_NAME_GETLONG); - return static_cast(longnum); + return static_cast(longNum); } - if (ANI_OK != env->Object_CallMethod_Long(static_cast(elementRef), getLongMethod, &longnum)) { + if (ANI_OK != env->Object_CallMethod_Long(static_cast(elementRef), getLongMethod, &longNum)) { HILOG_ERROR(LOG_CORE, "call method %{public}s failed", FUNC_NAME_GETLONG); - return static_cast(longnum); + return static_cast(longNum); } - return static_cast(longnum); + return static_cast(longNum); } bool HiSysEventAniUtil::ParseBoolValue(ani_env *env, ani_ref elementRef) @@ -108,7 +118,7 @@ bool HiSysEventAniUtil::ParseBoolValue(ani_env *env, ani_ref elementRef) return false; } ani_method unboxedMethod {}; - if (ANI_OK != env->Class_FindMethod(cls, FUNC_NAME_UNBOXED, ":Z", &unboxedMethod)) { + if (ANI_OK != env->Class_FindMethod(cls, FUNC_NAME_UNBOXED, ":z", &unboxedMethod)) { HILOG_ERROR(LOG_CORE, "find method %{public}s failed", FUNC_NAME_UNBOXED); return false; } @@ -125,18 +135,18 @@ int HiSysEventAniUtil::ParseIntValue(ani_env *env, ani_ref elementRef) ani_class cls {}; if (ANI_OK != env->FindClass(CLASS_NAME_INT, &cls)) { HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_INT); - return static_cast(intVal); + return static_cast(intVal); } ani_method unboxedMethod {}; - if (ANI_OK != env->Class_FindMethod(cls, FUNC_NAME_UNBOXED, ":I", &unboxedMethod)) { + if (ANI_OK != env->Class_FindMethod(cls, FUNC_NAME_UNBOXED, ":i", &unboxedMethod)) { HILOG_ERROR(LOG_CORE, "find method %{public}s failed", FUNC_NAME_UNBOXED); - return static_cast(intVal); + return static_cast(intVal); } if (ANI_OK != env->Object_CallMethod_Int(static_cast(elementRef), unboxedMethod, &intVal)) { HILOG_ERROR(LOG_CORE, "call method %{public}s failed", FUNC_NAME_UNBOXED); - return static_cast(intVal); + return static_cast(intVal); } - return static_cast(intVal); + return static_cast(intVal); } double HiSysEventAniUtil::ParseNumberValue(ani_env *env, ani_ref elementRef) @@ -148,7 +158,7 @@ double HiSysEventAniUtil::ParseNumberValue(ani_env *env, ani_ref elementRef) return static_cast(doubleVal); } ani_method unboxedMethod {}; - if (ANI_OK != env->Class_FindMethod(cls, FUNC_NAME_UNBOXED, ":D", &unboxedMethod)) { + if (ANI_OK != env->Class_FindMethod(cls, FUNC_NAME_UNBOXED, ":d", &unboxedMethod)) { HILOG_ERROR(LOG_CORE, "find method %{public}s failed", FUNC_NAME_UNBOXED); return static_cast(doubleVal); } @@ -164,12 +174,12 @@ std::map HiSysEventAniUtil::ParseRecord(ani_env *env, ani_ std::map recordResult = {}; ani_ref keys {}; if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast(recordRef), "keys", - ":Lescompat/IterableIterator;", &keys)) { + ":C{escompat.IterableIterator}", &keys)) { HILOG_ERROR(LOG_CORE, "call method keys failed."); return recordResult; } ani_boolean done = ANI_FALSE; - while (!done) { + while (done != ANI_TRUE) { ani_ref next {}; if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast(keys), "next", nullptr, &next)) { HILOG_ERROR(LOG_CORE, "call method next failed."); @@ -284,33 +294,31 @@ std::pair HiSysEventAniUtil::GetErrorDetailByRet(const int std::make_pair(AniError::ERR_ENV_ABNORMAL, "Abnormal environment") : errMap.at(retCode); } -ani_object HiSysEventAniUtil::WriteResult(ani_env *env, std::pair result) +ani_object HiSysEventAniUtil::WriteResult(ani_env *env, const std::pair& result) { - ani_object results_obj {}; + ani_object resultObj {}; ani_class cls {}; if (ANI_OK != env->FindClass(CLASS_NAME_RESULTINNER, &cls)) { HILOG_ERROR(LOG_CORE, "find Class %{public}s failed", CLASS_NAME_RESULTINNER); - return results_obj; + return resultObj; } ani_method ctor {}; if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { HILOG_ERROR(LOG_CORE, "get method %{public}s failed", CLASS_NAME_RESULTINNER); - return results_obj; + return resultObj; } - if (ANI_OK != env->Object_New(cls, ctor, &results_obj)) { + if (ANI_OK != env->Object_New(cls, ctor, &resultObj)) { HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_RESULTINNER); - return results_obj; + return resultObj; } - ani_method codeSetter {}; if (ANI_OK != env->Class_FindMethod(cls, "code", nullptr, &codeSetter)) { HILOG_ERROR(LOG_CORE, "find method code failed"); } - if (ANI_OK != env->Object_CallMethod_Void(results_obj, codeSetter, static_cast(result.first))) { + if (ANI_OK != env->Object_CallMethod_Void(resultObj, codeSetter, static_cast(result.first))) { HILOG_ERROR(LOG_CORE, "call method code failed"); - return results_obj; + return resultObj; } - ani_method messageSetter {}; if (ANI_OK != env->Class_FindMethod(cls, "message", nullptr, &messageSetter)) { HILOG_ERROR(LOG_CORE, "find method message failed"); @@ -318,95 +326,552 @@ ani_object HiSysEventAniUtil::WriteResult(ani_env *env, std::pairString_NewUTF8(message.c_str(), message.size(), &message_string); - if (ANI_OK != env->Object_CallMethod_Void(results_obj, messageSetter, message_string)) { + if (ANI_OK != env->Object_CallMethod_Void(resultObj, messageSetter, message_string)) { HILOG_ERROR(LOG_CORE, "call method message failed"); - return results_obj; + return resultObj; + } + return resultObj; +} + +ani_object HiSysEventAniUtil::CreateDoubleInt64(ani_env *env, int64_t number) +{ + ani_object personInfoObj = nullptr; + ani_class personCls; + if (ANI_OK != env->FindClass(CLASS_NAME_DOUBLE, &personCls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(personCls, "", "d:", &personInfoCtor)) { + HILOG_ERROR(LOG_CORE, "find method failed"); + return personInfoObj; + } + if (ANI_OK != env->Object_New(personCls, personInfoCtor, &personInfoObj, static_cast(number))) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + return personInfoObj; +} + +ani_object HiSysEventAniUtil::CreateDouble(ani_env *env, double number) +{ + ani_object personInfoObj = nullptr; + ani_class personCls; + if (ANI_OK != env->FindClass(CLASS_NAME_DOUBLE, &personCls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(personCls, "", "d:", &personInfoCtor)) { + HILOG_ERROR(LOG_CORE, "find method failed"); + return personInfoObj; + } + if (ANI_OK != env->Object_New(personCls, personInfoCtor, &personInfoObj, static_cast(number))) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + return personInfoObj; +} + +ani_object HiSysEventAniUtil::CreateBool(ani_env *env, bool boolValue) +{ + ani_object personInfoObj = nullptr; + ani_class personCls; + if (ANI_OK != env->FindClass(CLASS_NAME_BOOLEAN, &personCls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(personCls, "", "d:", &personInfoCtor)) { + HILOG_ERROR(LOG_CORE, "find method failed"); + return personInfoObj; + } + if (ANI_OK != env->Object_New(personCls, personInfoCtor, &personInfoObj, static_cast(boolValue))) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + return personInfoObj; +} + +ani_object HiSysEventAniUtil::CreateDoubleUint64(ani_env *env, uint64_t number) +{ + ani_object personInfoObj = nullptr; + ani_class personCls; + if (ANI_OK != env->FindClass(CLASS_NAME_DOUBLE, &personCls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(personCls, "", "d:", &personInfoCtor)) { + HILOG_ERROR(LOG_CORE, "find method failed"); + return personInfoObj; + } + if (ANI_OK != env->Object_New(personCls, personInfoCtor, &personInfoObj, static_cast(number))) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + return personInfoObj; +} + +ani_object HiSysEventAniUtil::CreateDoubleInt32(ani_env *env, int32_t number) +{ + ani_object personInfoObj = nullptr; + ani_class personCls; + if (ANI_OK != env->FindClass(CLASS_NAME_DOUBLE, &personCls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(personCls, "", "d:", &personInfoCtor)) { + HILOG_ERROR(LOG_CORE, "find method failed"); + return personInfoObj; + } + if (ANI_OK != env->Object_New(personCls, personInfoCtor, &personInfoObj, static_cast(number))) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + return personInfoObj; +} + +ani_enum_item HiSysEventAniUtil::ToAniEnum(ani_env *env, EventTypeAni value) +{ + ani_enum_item aniEnumItem {}; + auto it = ANI_EVENTTYPE_INDEX_MAP.find(value); + if (it == ANI_EVENTTYPE_INDEX_MAP.end()) { + HILOG_ERROR(LOG_CORE, "find enum %{public}d failed", value); + return aniEnumItem; + } + ani_int enumIndex = static_cast(it->second); + ani_enum aniEnum {}; + if (ANI_OK != env->FindEnum(ENUM_NAME_EVENT_TYPE, &aniEnum)) { + HILOG_ERROR(LOG_CORE, "find enum %{public}s failed", ENUM_NAME_EVENT_TYPE); + return aniEnumItem; + } + if (env->Enum_GetEnumItemByIndex(aniEnum, enumIndex, &aniEnumItem)) { + HILOG_ERROR(LOG_CORE, "get enum eventType value failed"); + return aniEnumItem; + } + return aniEnumItem; +} + +ani_object HiSysEventAniUtil::CreateDoubleUint32(ani_env *env, uint32_t number) +{ + ani_object personInfoObj = nullptr; + ani_class personCls; + if (ANI_OK != env->FindClass(CLASS_NAME_DOUBLE, &personCls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(personCls, "", "d:", &personInfoCtor)) { + HILOG_ERROR(LOG_CORE, "find method failed"); + return personInfoObj; + } + if (ANI_OK != env->Object_New(personCls, personInfoCtor, &personInfoObj, static_cast(number))) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_DOUBLE); + return personInfoObj; + } + return personInfoObj; +} + +ani_object HiSysEventAniUtil::CreateStringValue(ani_env *env, const std::string& value) +{ + ani_string valueStr {}; + if (ANI_OK != env->String_NewUTF8(value.c_str(), value.size(), &valueStr)) { + HILOG_ERROR(LOG_CORE, "create new value string failed"); + return static_cast(valueStr); + } + return static_cast(valueStr); +} + +void HiSysEventAniUtil::ThrowAniError(ani_env *env, int32_t code, const std::string &message) +{ + ani_class cls {}; + if (ANI_OK != env->FindClass(CLASS_NAME_BUSINESSERROR, &cls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_BUSINESSERROR); + return; + } + ani_method ctor {}; + if (ANI_OK != env->Class_FindMethod(cls, "", ":", &ctor)) { + HILOG_ERROR(LOG_CORE, "find method BusinessError constructor failed"); + return; + } + ani_object error {}; + if (ANI_OK != env->Object_New(cls, ctor, &error)) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_BUSINESSERROR); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Double(error, "code", static_cast(code))) { + HILOG_ERROR(LOG_CORE, "set property BusinessError.code failed"); + return; + } + ani_string messageRef {}; + if (ANI_OK != env->String_NewUTF8(message.c_str(), message.size(), &messageRef)) { + HILOG_ERROR(LOG_CORE, "create new message string failed"); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(error, "message", static_cast(messageRef))) { + HILOG_ERROR(LOG_CORE, "set property BusinessError.message failed"); + return; + } + if (ANI_OK != env->ThrowError(static_cast(error))) { + HILOG_ERROR(LOG_CORE, "throwError ani_error object failed"); + } +} + +void HiSysEventAniUtil::ThrowErrorByRet(ani_env *env, const int32_t retCode) +{ + auto detail = GetErrorDetailByRet(retCode); + HiSysEventAniUtil::ThrowAniError(env, detail.first, detail.second); +} + +static std::string TranslateKeyToAttrName(const std::string& key) +{ + if (key == DOMAIN__KEY) { + return DOMAIN_ATTR; + } + if (key == NAME__KEY) { + return NAME_ATTR; + } + if (key == TYPE__KEY) { + return EVENT_TYPE_ATTR; + } + return ""; +} + +void HiSysEventAniUtil::AppendInt32PropertyToJsObject(ani_env *env, const std::string& key, const int32_t& value, + ani_object& sysEventInfo) +{ + ani_class cls; + if (ANI_OK != env->FindClass(CLASS_NAME_SYSEVENTINFOANI, &cls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + ani_enum_item eventType_ctor = HiSysEventAniUtil::ToAniEnum(env, static_cast(value)); + if (ANI_OK != env->Object_SetPropertyByName_Ref(sysEventInfo, "eventType", static_cast(eventType_ctor))) { + HILOG_ERROR(LOG_CORE, "set property SysEventInfoAni.eventType failed"); + } +} + +void HiSysEventAniUtil::AppendStringPropertyToJsObject(ani_env *env, const std::string& key, const std::string& value, + ani_object& sysEventInfo) +{ + ani_class cls; + if (ANI_OK != env->FindClass(CLASS_NAME_SYSEVENTINFOANI, &cls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + + if (key == DOMAIN_ATTR) { + ani_object domain_ctor = HiSysEventAniUtil::CreateStringValue(env, value); + if (ANI_OK != env->Object_SetPropertyByName_Ref(sysEventInfo, "domain", static_cast(domain_ctor))) { + HILOG_ERROR(LOG_CORE, "set property SysEventInfoAni.domain failed"); + } + } else if (key == NAME_ATTR) { + ani_object name_ctor = HiSysEventAniUtil::CreateStringValue(env, value); + if (ANI_OK != env->Object_SetPropertyByName_Ref(sysEventInfo, "name", static_cast(name_ctor))) { + HILOG_ERROR(LOG_CORE, "set property SysEventInfoAni.name failed"); + } + } +} + +static void AppendBaseInfo(ani_env *env, ani_object& sysEventInfo, const std::string& key, Json::Value& value) +{ + if ((key == DOMAIN__KEY || key == NAME__KEY) && value.isString()) { + HiSysEventAniUtil::AppendStringPropertyToJsObject(env, TranslateKeyToAttrName(key), + value.asString(), sysEventInfo); + } + if (key == TYPE__KEY && value.isInt()) { + HiSysEventAniUtil::AppendInt32PropertyToJsObject(env, TranslateKeyToAttrName(key), + static_cast(value.asInt()), sysEventInfo); + } +} + +static bool CreateParamItemTypeValue(ani_env *env, Json::Value& jsonValue, ani_object& value) +{ + if (jsonValue.isBool()) { + value = HiSysEventAniUtil::CreateBool(env, jsonValue.asBool()); + return true; + } + if (jsonValue.isInt()) { + value = HiSysEventAniUtil::CreateDoubleInt32(env, static_cast(jsonValue.asInt())); + return true; + } + if (jsonValue.isUInt()) { + value = HiSysEventAniUtil::CreateDoubleUint32(env, static_cast(jsonValue.asUInt())); + return true; + } +#ifdef JSON_HAS_INT64 + if (jsonValue.isInt64() && jsonValue.type() != Json::ValueType::uintValue) { + value = HiSysEventAniUtil::CreateDoubleInt64(env, jsonValue.asInt64()); + return true; + } + if (jsonValue.isUInt64() && jsonValue.type() != Json::ValueType::intValue) { + value = HiSysEventAniUtil::CreateDoubleUint64(env, jsonValue.asUInt64()); + return true; + } +#endif + if (jsonValue.isDouble()) { + value = HiSysEventAniUtil::CreateDouble(env, jsonValue.asDouble()); + return true; } + if (jsonValue.isString()) { + value = HiSysEventAniUtil::CreateStringValue(env, jsonValue.asString()); + return true; + } + return false; +} - return results_obj; +static void AppendArrayParams(ani_env *env, ani_object& sysEventInfo, std::string& key, Json::Value& value) +{ + size_t len = value.size(); + ani_array array = nullptr; + ani_class cls; + if (ANI_OK != env->FindClass(CLASS_NAME_SYSEVENTINFOANI, &cls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + ani_ref initial_array = nullptr; + if (ANI_OK != env->Array_New(len, initial_array, &array)) { + HILOG_ERROR(LOG_CORE, "create %{public}s array failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + for (size_t i = 0; i < len; i++) { + ani_object item; + if (!CreateParamItemTypeValue(env, value[static_cast(i)], item)) { + continue; + } + if (ANI_OK != env->Array_Set(array, i, static_cast(item))) { + HILOG_ERROR(LOG_CORE, "set %{public}zu item failed", i); + return; + } + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(sysEventInfo, "params", static_cast(array))) { + HILOG_ERROR(LOG_CORE, "set property SysEventInfoAni.params failed"); + } } -void HiSysEventAniUtil::GetBooleans(ani_env *env, ani_ref arrayRef, std::vector& bools) +static void AppendParamsInfo(ani_env *env, ani_object& sysEventInfo, std::string& key, Json::Value& jsonValue) +{ + if (jsonValue.isArray()) { + AppendArrayParams(env, sysEventInfo, key, jsonValue); + return; + } + ani_object property = nullptr; + if (!CreateParamItemTypeValue(env, jsonValue, property)) { + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(sysEventInfo, "params", static_cast(property))) { + HILOG_ERROR(LOG_CORE, "set params %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + } +} + +static bool IsBaseInfoKey(std::string& propertyName) +{ + return propertyName == DOMAIN__KEY || propertyName == NAME__KEY || propertyName == TYPE__KEY; +} + +void HiSysEventAniUtil::CreateJsSysEventInfoArray(ani_env *env, const std::vector& originValues, + ani_array& sysEventInfoJsArray) +{ + auto len = originValues.size(); + ani_class cls; + if (ANI_OK != env->FindClass(CLASS_NAME_SYSEVENTINFOANI, &cls)) { + HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + ani_object sysEventInfo = nullptr; + ani_method ctor {}; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + HILOG_ERROR(LOG_CORE, "get method %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + for (size_t i = 0; i < len; i++) { + if (ANI_OK != env->Object_New(cls, ctor, &sysEventInfo)) { + HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_SYSEVENTINFOANI); + return; + } + CreateHiSysEventInfoJsObject(env, originValues[i], sysEventInfo); + ani_status ret = env->Array_Set(sysEventInfoJsArray, i, static_cast(sysEventInfo)); + if (ret != ANI_OK) { + HILOG_DEBUG(LOG_CORE, "set %{public}zu sysEventInfo failed", i); + } + } +} + +void HiSysEventAniUtil::CreateHiSysEventInfoJsObject(ani_env *env, const std::string& jsonStr, ani_object& sysEventInfo) +{ + Json::Value eventJson; +#ifdef JSONCPP_VERSION_STRING + Json::CharReaderBuilder jsonRBuilder; + Json::CharReaderBuilder::strictMode(&jsonRBuilder.settings_); + std::unique_ptr const reader(jsonRBuilder.newCharReader()); + JSONCPP_STRING errs; + if (!reader->parse(jsonStr.data(), jsonStr.data() + jsonStr.size(), &eventJson, &errs)) { + HILOG_ERROR(LOG_CORE, "parse event detail info failed, please check the style of json infomation: %{public}s", + jsonStr.c_str()); + return; + } +#else + Json::Reader reader(Json::Features::strictMode()); + if (!reader.parse(jsonStr, eventJson)) { + HILOG_ERROR(LOG_CORE, "parse event detail info failed, please check the style of json infomation: %{public}s", + jsonStr.c_str()); + return; + } +#endif + if (!eventJson.isObject()) { + HILOG_ERROR(LOG_CORE, "event json parsed isn't a json object"); + return; + } + auto eventNameList = eventJson.getMemberNames(); + for (auto it = eventNameList.cbegin(); it != eventNameList.cend(); it++) { + auto propertyName = *it; + if (IsBaseInfoKey(propertyName)) { + AppendBaseInfo(env, sysEventInfo, propertyName, eventJson[propertyName]); + } else { + AppendParamsInfo(env, sysEventInfo, propertyName, eventJson[propertyName]); + } + } +} + +std::string HiSysEventAniUtil::AniStringToStdString(ani_env *env, ani_string aniStr) +{ + ani_size strSize; + env->String_GetUTF8Size(aniStr, &strSize); + std::vector buffer(strSize + 1); + char *utf8Buffer = buffer.data(); + ani_size bytesWritten = 0; + env->String_GetUTF8(aniStr, utf8Buffer, strSize + 1, &bytesWritten); + utf8Buffer[bytesWritten] = '\0'; + std::string content = std::string(utf8Buffer); + return content; +} + +ani_vm* HiSysEventAniUtil::GetAniVm(ani_env *env) +{ + ani_vm *vm = nullptr; + if (ANI_OK != env->GetVM(&vm)) { + HILOG_ERROR(LOG_CORE, "get vm failed"); + return nullptr; + } + return vm; +} + +ani_env* HiSysEventAniUtil::GetAniEnv(ani_vm *vm) +{ + ani_env *env = nullptr; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + HILOG_ERROR(LOG_CORE, "get env failed"); + return nullptr; + } + return env; +} + +ani_env* HiSysEventAniUtil::AttachAniEnv(ani_vm *vm) +{ + ani_env *workerEnv = nullptr; + ani_options aniArgs {0, nullptr}; + if (ANI_OK != vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &workerEnv)) { + HILOG_ERROR(LOG_CORE, "get attach env failed"); + return nullptr; + } + return workerEnv; +} + +void HiSysEventAniUtil::DetachAniEnv(ani_vm *vm) +{ + if (ANI_OK != vm->DetachCurrentThread()) { + HILOG_ERROR(LOG_CORE, "detach env failed"); + } +} + +bool HiSysEventAniUtil::GetBooleans(ani_env *env, ani_ref arrayRef, std::vector& bools) { ani_size len = 0; - if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { + if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { HILOG_ERROR(LOG_CORE, "failed to get the length of array"); - return; + return false; } for (ani_size i = 0; i < len; i++) { ani_ref element = nullptr; - if (ANI_OK != env->Array_Get_Ref(static_cast(arrayRef), i, &element)) { + if (ANI_OK != env->Array_Get(static_cast(arrayRef), i, &element)) { HILOG_ERROR(LOG_CORE, "failed to get the element of array"); - return; + return false; } bools.emplace_back(HiSysEventAniUtil::ParseBoolValue(env, element)); } + return true; } -void HiSysEventAniUtil::GetDoubles(ani_env *env, ani_ref arrayRef, std::vector& doubles) +bool HiSysEventAniUtil::GetDoubles(ani_env *env, ani_ref arrayRef, std::vector& doubles) { ani_size len = 0; - if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { + if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { HILOG_ERROR(LOG_CORE, "failed to get the length of array"); - return; + return false; } for (ani_size i = 0; i < len; i++) { ani_ref element = nullptr; - if (ANI_OK != env->Array_Get_Ref(static_cast(arrayRef), i, &element)) { + if (ANI_OK != env->Array_Get(static_cast(arrayRef), i, &element)) { HILOG_ERROR(LOG_CORE, "failed to get the element of array"); - return; + return false; } doubles.push_back(HiSysEventAniUtil::ParseNumberValue(env, element)); } + return true; } -void HiSysEventAniUtil::GetStrings(ani_env *env, ani_ref arrayRef, std::vector& strs) +bool HiSysEventAniUtil::GetStrings(ani_env *env, ani_ref arrayRef, std::vector& strs) { ani_size len = 0; - if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { + if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { HILOG_ERROR(LOG_CORE, "failed to get the length of array"); - return; + return false; } for (ani_size i = 0; i < len; i++) { ani_ref element = nullptr; - if (ANI_OK != env->Array_Get_Ref(static_cast(arrayRef), i, &element)) { + if (ANI_OK != env->Array_Get(static_cast(arrayRef), i, &element)) { HILOG_ERROR(LOG_CORE, "failed to get the element of array"); - return; + return false; } strs.push_back(HiSysEventAniUtil::ParseStringValue(env, element)); } + return true; } -void HiSysEventAniUtil::GetIntsToDoubles(ani_env *env, ani_ref arrayRef, std::vector& doubles) +bool HiSysEventAniUtil::GetIntsToDoubles(ani_env *env, ani_ref arrayRef, std::vector& doubles) { ani_size len = 0; - if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { + if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { HILOG_ERROR(LOG_CORE, "failed to get the length of array"); - return; + return false; } for (ani_size i = 0; i < len; i++) { ani_ref element = nullptr; - if (ANI_OK != env->Array_Get_Ref(static_cast(arrayRef), i, &element)) { + if (ANI_OK != env->Array_Get(static_cast(arrayRef), i, &element)) { HILOG_ERROR(LOG_CORE, "failed to get the element of array"); - return; + return false; } doubles.push_back(static_cast(HiSysEventAniUtil::ParseIntValue(env, element))); } + return true; } -void HiSysEventAniUtil::GetBigints(ani_env *env, ani_ref arrayRef, std::vector& bigints) +bool HiSysEventAniUtil::GetBigints(ani_env *env, ani_ref arrayRef, std::vector& bigints) { ani_size len = 0; - if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { + if (ANI_OK != env->Array_GetLength(static_cast(arrayRef), &len)) { HILOG_ERROR(LOG_CORE, "failed to get the length of array"); - return; + return false; } for (ani_size i = 0; i < len; i++) { ani_ref element = nullptr; - if (ANI_OK != env->Array_Get_Ref(static_cast(arrayRef), i, &element)) { + if (ANI_OK != env->Array_Get(static_cast(arrayRef), i, &element)) { HILOG_ERROR(LOG_CORE, "failed to get the element of array"); - return; + return false; } bigints.push_back(HiSysEventAniUtil::ParseBigintValue(env, element)); } + return true; } -- Gitee From fa0c57d7f0addc9338626c93953b85da723fd122 Mon Sep 17 00:00:00 2001 From: xuyong Date: Mon, 21 Jul 2025 21:13:55 +0800 Subject: [PATCH 2/2] replace number with int/long Signed-off-by: xuyong --- .../ani/hisysevent/ets/@ohos.hiSysEvent.ets | 32 +++++++++---------- .../ets/ani/hisysevent/src/hisysevent_ani.cpp | 12 +++---- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/interfaces/ets/ani/hisysevent/ets/@ohos.hiSysEvent.ets b/interfaces/ets/ani/hisysevent/ets/@ohos.hiSysEvent.ets index c4a8134..df3e81d 100644 --- a/interfaces/ets/ani/hisysevent/ets/@ohos.hiSysEvent.ets +++ b/interfaces/ets/ani/hisysevent/ets/@ohos.hiSysEvent.ets @@ -30,15 +30,15 @@ class WatcherAni implements hiSysEvent.Watcher { class QuerierAni implements hiSysEvent.Querier { onQuery: (infos: hiSysEvent.SysEventInfo[]) => void = (infos: hiSysEvent.SysEventInfo[]) => {}; - onComplete: (reason: number, total: number) => void = (reason: number, total: number) => {}; + onComplete: (reason: int, total: int) => void = (reason: int, total: int) => {}; } class QueryArgAni implements hiSysEvent.QueryArg { - beginTime: number = 0; - endTime: number = 0; - maxEvents: number = 0; - fromSeq?: number | undefined; - toSeq?: number | undefined; + beginTime: long = 0; + endTime: long = 0; + maxEvents: long = 0; + fromSeq?: long | undefined; + toSeq?: long | undefined; } class QueryRuleAni implements hiSysEvent.QueryRule { @@ -48,12 +48,12 @@ class QueryRuleAni implements hiSysEvent.QueryRule { } interface Result { - code: number; + code: int; message: string; } class ResultInner implements Result { - code: number = 0; + code: int = 0; message: string = ""; } @@ -99,24 +99,24 @@ export default namespace hiSysEvent { } export interface QueryArg { - beginTime: number; - endTime: number; - maxEvents: number; - fromSeq?: number; - toSeq?: number; + beginTime: long; + endTime: long; + maxEvents: long; + fromSeq?: long; + toSeq?: long; } export interface Querier { onQuery: (infos: SysEventInfo[]) => void; - onComplete: (reason: number, total: number) => void; + onComplete: (reason: int, total: int) => void; } native function writeSync(info: SysEventInfo): Result; export native function addWatcher(watcher: Watcher): void; export native function removeWatcher(watcher: Watcher): void; export native function query(queryArg: QueryArg, rules: QueryRule[], querier: Querier): void; - export native function exportSysEvents(queryArg: QueryArg, rules: QueryRule[]): number; - export native function subscribe(rules: QueryRule[]): number; + export native function exportSysEvents(queryArg: QueryArg, rules: QueryRule[]): long; + export native function subscribe(rules: QueryRule[]): long; export native function unsubscribe(): void; export function write(info: SysEventInfo, callback: AsyncCallback): void { diff --git a/interfaces/ets/ani/hisysevent/src/hisysevent_ani.cpp b/interfaces/ets/ani/hisysevent/src/hisysevent_ani.cpp index e1bc2fe..3aa9637 100644 --- a/interfaces/ets/ani/hisysevent/src/hisysevent_ani.cpp +++ b/interfaces/ets/ani/hisysevent/src/hisysevent_ani.cpp @@ -362,18 +362,18 @@ static int32_t ParseQueryRules(ani_env *env, ani_array rulesAni, std::vectorObject_GetPropertyByName_Double(queryArgAni, "beginTime", &beginTimeRef)) { + ani_long beginTimeRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Long(queryArgAni, "beginTime", &beginTimeRef)) { HILOG_ERROR(LOG_CORE, "get property beginTime failed,"); } queryArg.beginTime = static_cast(beginTimeRef); - ani_double endTimeRef {}; - if (ANI_OK != env->Object_GetPropertyByName_Double(queryArgAni, "endTime", &endTimeRef)) { + ani_long endTimeRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Long(queryArgAni, "endTime", &endTimeRef)) { HILOG_ERROR(LOG_CORE, "get property endTime failed"); } queryArg.endTime = static_cast(endTimeRef); - ani_double maxEventsRef {}; - if (ANI_OK != env->Object_GetPropertyByName_Double(queryArgAni, "maxEvents", &maxEventsRef)) { + ani_long maxEventsRef {}; + if (ANI_OK != env->Object_GetPropertyByName_Long(queryArgAni, "maxEvents", &maxEventsRef)) { HILOG_ERROR(LOG_CORE, "get property maxEvents failed"); } queryArg.maxEvents = static_cast(maxEventsRef); -- Gitee