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_app_event_holder.h"
17
18 #include <cinttypes>
19
20 #include "app_event_store.h"
21 #include "hilog/log.h"
22 #include "hiappevent_ani_util.h"
23
24 #undef LOG_DOMAIN
25 #define LOG_DOMAIN 0xD002D07
26
27 #undef LOG_TAG
28 #define LOG_TAG "AniHolder"
29
30 namespace OHOS {
31 namespace HiviewDFX {
32 namespace {
33 constexpr size_t PARAM_NUM = 1;
34 constexpr int DEFAULT_ROW_NUM = 1;
35 constexpr int DEFAULT_SIZE = 512 * 1024; // 512 * 1024: 512KB
36 const std::string HOLDER_CLASS_NAME = "AppEventPackageHolder";
37
GetObserverSeqByName(const std::string & name)38 int64_t GetObserverSeqByName(const std::string& name)
39 {
40 int64_t observerSeq = -1;
41 if (observerSeq = AppEventStore::GetInstance().QueryObserverSeq(name); observerSeq <= 0) {
42 HILOG_WARN(LOG_CORE, "failed to query seq by name=%{public}s", name.c_str());
43 return -1;
44 }
45 return observerSeq;
46 }
47 }
48
AniAppEventHolder(const std::string & name,int64_t observerSeq)49 AniAppEventHolder::AniAppEventHolder(const std::string& name, int64_t observerSeq)
50 : name_(name), observerSeq_(observerSeq), hasSetRow_(false), hasSetSize_(false)
51 {
52 takeRow_ = DEFAULT_ROW_NUM;
53 takeSize_ = DEFAULT_SIZE;
54 packageId_ = 0; // id is incremented from 0
55
56 // if the seq is invalid, need to get seq by the name(for js constructor)
57 if (observerSeq_ <= 0) {
58 observerSeq_ = GetObserverSeqByName(name_);
59 }
60 }
61
Wrap(ani_env * env,ani_object aniObject,AniAppEventHolder * holder)62 static ani_object Wrap(ani_env *env, ani_object aniObject, AniAppEventHolder *holder)
63 {
64 if (env->Object_SetFieldByName_Long(aniObject, "nativeHolder", reinterpret_cast<ani_long>(holder)) != ANI_OK) {
65 HILOG_ERROR(LOG_CORE, "New holder Fail");
66 return nullptr;
67 }
68 return aniObject;
69 }
70
Unwrap(ani_env * env,ani_object aniObject)71 static AniAppEventHolder* Unwrap(ani_env *env, ani_object aniObject)
72 {
73 ani_long context;
74 if (env->Object_GetFieldByName_Long(aniObject, "nativeHolder", &context) != ANI_OK) {
75 return nullptr;
76 }
77 return reinterpret_cast<AniAppEventHolder*>(context);
78 }
79
AniConstructor(ani_env * env,ani_object aniObject,ani_string watcherName)80 void AniAppEventHolder::AniConstructor(ani_env *env, ani_object aniObject, ani_string watcherName)
81 {
82 auto holder = new(std::nothrow) AniAppEventHolder(HiAppEventAniUtil::ParseStringValue(env, watcherName));
83 if (holder == nullptr) {
84 HILOG_INFO(LOG_CORE, "AniConstructor holder nullptr");
85 }
86 Wrap(env, aniObject, holder);
87 }
88
AniFinalize(ani_env * env,ani_object object,ani_long nativeHolder)89 void AniAppEventHolder::AniFinalize(ani_env *env, ani_object object, ani_long nativeHolder)
90 {
91 AniAppEventHolder* holder = reinterpret_cast<AniAppEventHolder*>(nativeHolder);
92 delete holder;
93 }
94
AniSetRow(ani_env * env,ani_object object,ani_double size)95 void AniAppEventHolder::AniSetRow(ani_env *env, ani_object object, ani_double size)
96 {
97 int num = static_cast<int>(size);
98 if (num <= 0) {
99 HiAppEventAniUtil::ThrowAniError(env, ERR_INVALID_SIZE, "Invalid size value.");
100 return;
101 }
102 AniAppEventHolder* holder = Unwrap(env, object);
103 if (holder != nullptr) {
104 holder->SetRow(num);
105 }
106 return;
107 }
108
AniSetSize(ani_env * env,ani_object object,ani_double size)109 void AniAppEventHolder::AniSetSize(ani_env *env, ani_object object, ani_double size)
110 {
111 int num = static_cast<int>(size);
112 if (num < 0) {
113 HiAppEventAniUtil::ThrowAniError(env, ERR_INVALID_SIZE, "Invalid size value.");
114 return;
115 }
116 AniAppEventHolder* holder = Unwrap(env, object);
117 if (holder != nullptr) {
118 holder->SetSize(num);
119 }
120 return;
121 }
122
AniTakeNext(ani_env * env,ani_object object)123 ani_object AniAppEventHolder::AniTakeNext(ani_env *env, ani_object object)
124 {
125 ani_object packageObj = HiAppEventAniUtil::CreateObject(env, CLASS_NAME_EVENT_PACKAGE);
126 AniAppEventHolder* holder = Unwrap(env, object);
127 if (holder == nullptr) {
128 return packageObj;
129 }
130 auto package = holder->TakeNext();
131 if (package == nullptr) {
132 return packageObj;
133 }
134 env->Object_SetPropertyByName_Double(packageObj, "packageId", package->packageId);
135 env->Object_SetPropertyByName_Double(packageObj, "row", package->row);
136 env->Object_SetPropertyByName_Double(packageObj, "size", package->size);
137 env->Object_SetPropertyByName_Ref(packageObj, "data", HiAppEventAniUtil::CreateStrings(env, package->data));
138 env->Object_SetPropertyByName_Ref(packageObj, "appEventInfos",
139 HiAppEventAniUtil::CreateEventInfoArray(env, package->events));
140 return packageObj;
141 }
142
SetRow(int row)143 void AniAppEventHolder::SetRow(int row)
144 {
145 HILOG_INFO(LOG_CORE, "hodler seq=%{public}" PRId64 " set row=%{public}d", observerSeq_, row);
146 takeRow_ = row;
147 hasSetRow_ = true;
148 }
149
SetSize(int size)150 void AniAppEventHolder::SetSize(int size)
151 {
152 HILOG_INFO(LOG_CORE, "hodler seq=%{public}" PRId64 " set size=%{public}d", observerSeq_, size);
153 takeSize_ = size;
154 hasSetSize_ = true;
155 }
156
TakeNext()157 std::shared_ptr<AppEventPackage> AniAppEventHolder::TakeNext()
158 {
159 std::vector<std::shared_ptr<AppEventPack>> events;
160 bool shouldTakeSize = hasSetSize_ && !hasSetRow_;
161 int rowNum = shouldTakeSize ? 0 : takeRow_;
162 if (AppEventStore::GetInstance().QueryEvents(events, observerSeq_, rowNum) != 0) {
163 HILOG_WARN(LOG_CORE, "failed to query events, seq=%{public}" PRId64, observerSeq_);
164 return nullptr;
165 }
166 if (events.empty()) {
167 HILOG_DEBUG(LOG_CORE, "end to query events, seq=%{public}" PRId64, observerSeq_);
168 return nullptr;
169 }
170
171 std::vector<int64_t> eventSeqs;
172 std::vector<std::string> eventStrs;
173 size_t totalSize = 0;
174 auto package = std::make_shared<AppEventPackage>();
175 for (auto event : events) {
176 std::string eventStr = event->GetEventStr();
177 if (shouldTakeSize && static_cast<int>(totalSize + eventStr.size()) > takeSize_) {
178 HILOG_INFO(LOG_CORE, "stop to take data, totalSize=%{public}zu, takeSize=%{public}d",
179 totalSize, takeSize_);
180 break;
181 }
182 totalSize += eventStr.size();
183 eventStrs.emplace_back(eventStr);
184 eventSeqs.emplace_back(event->GetSeq());
185 package->events.emplace_back(event);
186 }
187 if (eventStrs.empty()) {
188 HILOG_INFO(LOG_CORE, "take data is empty, seq=%{public}" PRId64, observerSeq_);
189 return nullptr;
190 }
191 if (!AppEventStore::GetInstance().DeleteData(observerSeq_, eventSeqs)) {
192 HILOG_INFO(LOG_CORE, "failed to delete mapping data, seq=%{public}" PRId64, observerSeq_);
193 return nullptr;
194 }
195
196 package->packageId = packageId_++;
197 package->row = static_cast<int>(eventStrs.size());
198 package->size = static_cast<int>(totalSize);
199 package->data = eventStrs;
200 return package;
201 }
202 } // namespace HiviewDFX
203 } // namespace OHOS
204