1 /*
2 * Copyright (c) 2024 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 <regex>
17 #include <string>
18 #include <unordered_set>
19 #include <vector>
20
21 #include "appevent_watcher_impl.h"
22 #include "cj_ffi/cj_common_ffi.h"
23 #include "ffi_remote_data.h"
24 #include "hiappevent_ffi.h"
25 #include "hiappevent_impl.h"
26 #include "hiappevent_verify.h"
27 #include "log.h"
28 #include "error.h"
29 using namespace OHOS::HiviewDFX;
30 using namespace OHOS::CJSystemapi::HiAppEvent;
31
32 namespace {
33 constexpr int ERR_CODE_PARAM_FORMAT = -1;
34 constexpr int ERR_CODE_PARAM_INVALID = -2;
35 const int8_t INT32_VALUE = 0;
36 const int8_t DOUBLE_VALUE = 1;
37 const int8_t STRING_VALUE = 2;
38 const int8_t BOOL_VALUE = 3;
39 const int8_t INT32_ARRAY_VALUE = 4;
40 const int8_t DOUBLE_ARRAY_VALUE = 5;
41 const int8_t STRING_ARRAY_VALUE = 6;
42 const int8_t BOOL_ARRAY_VALUE = 7;
43 constexpr int BIT_MASK = 1;
44 constexpr unsigned int BIT_ALL_TYPES = 0xff;
45
CheckCondition(TriggerCondition & cond,CTriggerCondition triggerCondition)46 int CheckCondition(TriggerCondition &cond, CTriggerCondition triggerCondition)
47 {
48 int ret = ERR_PARAM;
49 cond.row = triggerCondition.row;
50 if (cond.row < 0) {
51 ret = ERR_INVALID_COND_ROW;
52 return ret;
53 }
54 cond.size = triggerCondition.size;
55 if (cond.size < 0) {
56 ret = ERR_INVALID_COND_SIZE;
57 return ret;
58 }
59 if (triggerCondition.timeOut * HiAppEvent::TIMEOUT_STEP < 0) {
60 ret = ERR_INVALID_COND_TIMEOUT;
61 return ret;
62 }
63 cond.timeout = triggerCondition.timeOut * HiAppEvent::TIMEOUT_STEP;
64 return ret;
65 }
66
CharPtrToVector(char ** charPtr,int size,std::vector<std::string> & result)67 void CharPtrToVector(char** charPtr, int size, std::vector<std::string> &result)
68 {
69 for (int i = 0; i < size; i++) {
70 result.push_back(std::string(charPtr[i]));
71 }
72 }
73
genArrString2Set(const CArrString & str)74 std::unordered_set<std::string> genArrString2Set(const CArrString& str)
75 {
76 std::vector<std::string> strVec;
77 CharPtrToVector(str.head, str.size, strVec);
78 std::unordered_set<std::string> res(strVec.begin(), strVec.end());
79 return res;
80 }
81
ConvertConfigReportProp(const CAppEventReportConfig & config,EventConfig reportConf)82 int ConvertConfigReportProp(const CAppEventReportConfig& config, EventConfig reportConf)
83 {
84 if (config.domain != nullptr) {
85 reportConf.domain = config.domain;
86 }
87 if (config.name != nullptr) {
88 reportConf.name = config.name;
89 }
90 reportConf.isRealTime = config.isRealTime;
91 if (!IsValidEventConfig(reportConf)) {
92 return ERR_CODE_PARAM_INVALID;
93 }
94 return SUCCESS_CODE;
95 }
96
ConvertReportConfig(const CProcessor & processor,ReportConfig & conf)97 int ConvertReportConfig(const CProcessor& processor, ReportConfig& conf)
98 {
99 if (processor.name != nullptr && IsValidProcessorName(std::string(processor.name))) {
100 conf.name = processor.name;
101 } else {
102 return ERR_CODE_PARAM_FORMAT;
103 }
104 conf.debugMode = processor.debugMode;
105 conf.routeInfo = processor.routeInfo;
106 conf.appId = processor.appId;
107 conf.triggerCond.onStartup = processor.onStartReport;
108 conf.triggerCond.onBackground = processor.onBackgroundReport;
109 if (!IsValidPeriodReport(processor.periodReport)) {
110 conf.triggerCond.timeout = 0;
111 } else {
112 conf.triggerCond.timeout = processor.periodReport;
113 }
114 if (!IsValidBatchReport(processor.batchReport)) {
115 conf.triggerCond.row = 0;
116 } else {
117 conf.triggerCond.row = processor.batchReport;
118 }
119 conf.userIdNames = genArrString2Set(processor.userIds);
120 conf.userPropertyNames = genArrString2Set(processor.userProperties);
121 std::vector<EventConfig> eventConfigs;
122 CAppEventReportConfig* configPtr = processor.eventConfigs.head;
123 for (int i = 0; i < processor.eventConfigs.size; i++) {
124 EventConfig reportConf;
125 int res = ConvertConfigReportProp(configPtr[i], reportConf);
126 if (res != 0) {
127 return res;
128 }
129 eventConfigs.push_back(reportConf);
130 }
131 conf.eventConfigs = eventConfigs;
132 return SUCCESS_CODE;
133 }
134
AddParams2EventPack(const CArrParameters & params,std::shared_ptr<AppEventPack> appEventPack_)135 void AddParams2EventPack(const CArrParameters& params, std::shared_ptr<AppEventPack> appEventPack_)
136 {
137 for (int i = 0; i < params.size; i++) {
138 auto head = params.head + i;
139 switch (head->valueType) {
140 case INT32_VALUE: // int32_t
141 appEventPack_->AddParam(std::string(head->key), *(int32_t*)head->value);
142 break;
143 case DOUBLE_VALUE: // double
144 appEventPack_->AddParam(std::string(head->key), *(double*)head->value);
145 break;
146 case STRING_VALUE: // std::string
147 appEventPack_->AddParam(std::string(head->key), std::string((char*)head->value));
148 break;
149 case BOOL_VALUE: // bool
150 appEventPack_->AddParam(std::string(head->key), *(bool*)head->value);
151 break;
152 case INT32_ARRAY_VALUE: { // int32_array
153 int* intArr = (int*)head->value;
154 std::vector<int> intVec(intArr, intArr + head->size);
155 appEventPack_->AddParam(std::string(head->key), intVec);
156 break;
157 }
158 case DOUBLE_ARRAY_VALUE: { // double_array
159 double* doubleArr = (double*)head->value;
160 std::vector<double> doubleVec(doubleArr, doubleArr + head->size);
161 appEventPack_->AddParam(std::string(head->key), doubleVec);
162 break;
163 }
164 case STRING_ARRAY_VALUE: { // string_array
165 char** strPtr = (char**)head->value;
166 std::vector<std::string> strVec;
167 CharPtrToVector(strPtr, head->size, strVec);
168 appEventPack_->AddParam(std::string(head->key), strVec);
169 break;
170 }
171 case BOOL_ARRAY_VALUE: { // bool_array
172 bool* boolArr = (bool*)head->value;
173 std::vector<bool> boolVec(boolArr, boolArr + head->size);
174 appEventPack_->AddParam(std::string(head->key), boolVec);
175 break;
176 }
177 default:
178 break;
179 }
180 }
181 }
182 }
183
184 extern "C" {
FfiOHOSHiAppEventConfigure(CConfigOption config)185 int FfiOHOSHiAppEventConfigure(CConfigOption config)
186 {
187 int code = HiAppEventImpl::Configure(config.disable, config.maxStorage);
188 if (code != SUCCESS_CODE) {
189 LOGE("FfiOHOSHiAppEventConfigure failed");
190 return code;
191 }
192 return SUCCESS_CODE;
193 }
194
FfiOHOSHiAppEventWrite(CAppEventInfo info)195 int FfiOHOSHiAppEventWrite(CAppEventInfo info)
196 {
197 auto appEventPack_ = std::make_shared<AppEventPack>(info.domain, info.name, info.event);
198 AddParams2EventPack(info.cArrParamters, appEventPack_);
199 int code = HiAppEventImpl::Write(appEventPack_);
200 if (code != SUCCESS_CODE) {
201 LOGE("HiAppEvent::FfiOHOSHiAppEventWrite failed");
202 return GetErrorCode(code);
203 }
204 return code;
205 }
206
FfiOHOSHiAppEventAddProcessor(CProcessor processor)207 RetDataBool FfiOHOSHiAppEventAddProcessor(CProcessor processor)
208 {
209 RetDataBool ret = { .code = ErrorCode::ERROR_UNKNOWN, .data = false };
210 ReportConfig conf;
211 int res = ConvertReportConfig(processor, conf);
212 if (res == ERR_CODE_PARAM_FORMAT) {
213 LOGE("failed to add processor, params format error");
214 ret.code = ERR_PARAM;
215 ret.data = false;
216 return ret;
217 }
218 if (HiAppEventImpl::Load(conf.name) != 0) {
219 LOGE("failed to add processor=%{public}s, name no found", conf.name.c_str());
220 return {ERR_CODE_PARAM_FORMAT, true};
221 }
222 int64_t processorId = HiAppEventImpl::AddProcessor(conf);
223 if (processorId <= 0) {
224 LOGE("HiAppEvent::FfiOHOSHiAppEventAddProcessor failed");
225 }
226 ret.code = processorId;
227 ret.data = true;
228 return ret;
229 }
230
FfiOHOSHiAppEventRemoveProcessor(int64_t id)231 int FfiOHOSHiAppEventRemoveProcessor(int64_t id)
232 {
233 int res = HiAppEventImpl::RemoveProcessor(id);
234 return res;
235 }
236
FfiOHOSHiAppEventSetUserId(const char * name,const char * value)237 int FfiOHOSHiAppEventSetUserId(const char* name, const char* value)
238 {
239 if (!IsValidUserIdName(std::string(name))) {
240 return ERR_PARAM;
241 }
242 if (!IsValidUserIdValue(std::string(value))) {
243 return ERR_PARAM;
244 }
245 int res = HiAppEventImpl::SetUserId(std::string(name), std::string(value));
246 if (res != 0) {
247 return ERR_PARAM;
248 }
249 return SUCCESS_CODE;
250 }
251
FfiOHOSHiAppEventGetUserId(const char * name)252 RetDataCString FfiOHOSHiAppEventGetUserId(const char* name)
253 {
254 RetDataCString ret = { .code = ERR_PARAM, .data = nullptr };
255 if (!IsValidUserIdName(std::string(name))) {
256 ret.code = ERR_PARAM;
257 ret.data = nullptr;
258 return ret;
259 }
260 auto [status, userId] = HiAppEventImpl::GetUserId(std::string(name));
261 if (status != 0) {
262 LOGE("HiAppEvent::FfiOHOSHiAppEventGetUserId error");
263 ret.code = status;
264 ret.data = nullptr;
265 return ret;
266 }
267 ret.code = status;
268 ret.data = MallocCString(userId);
269 return ret;
270 }
271
FfiOHOSHiAppEventSetUserProperty(const char * name,const char * value)272 int FfiOHOSHiAppEventSetUserProperty(const char* name, const char* value)
273 {
274 if (!IsValidUserPropName(name)) {
275 return ERR_PARAM;
276 }
277 if (!IsValidUserPropValue(value)) {
278 return ERR_PARAM;
279 }
280 int res = HiAppEventImpl::SetUserProperty(std::string(name), std::string(value));
281 if (res != 0) {
282 return ERR_PARAM;
283 }
284 return res;
285 }
286
FfiOHOSHiAppEventgetUserProperty(const char * name)287 RetDataCString FfiOHOSHiAppEventgetUserProperty(const char* name)
288 {
289 RetDataCString ret = { .code = ERR_PARAM, .data = nullptr };
290 if (!IsValidUserPropName(std::string(name))) {
291 ret.code = ERR_PARAM;
292 ret.data = nullptr;
293 return ret;
294 }
295 auto [status, propertyId] = HiAppEventImpl::GetUserProperty(std::string(name));
296 if (status != 0) {
297 LOGE("HiAppEvent::FfiOHOSHiAppEventgetUserProperty error");
298 ret.code = status;
299 ret.data = nullptr;
300 return ret;
301 }
302 ret.code = status;
303 ret.data = MallocCString(propertyId);
304 return ret;
305 }
306
FfiOHOSHiAppEventclearData()307 void FfiOHOSHiAppEventclearData()
308 {
309 HiAppEventImpl::ClearData();
310 }
311
FfiOHOSHiAppEventConstructor(char * cWatcherName)312 int64_t FfiOHOSHiAppEventConstructor(char* cWatcherName)
313 {
314 auto nativeHolder = OHOS::FFI::FFIData::Create<AppEventPackageHolderImpl>(cWatcherName, -1L);
315 if (nativeHolder == nullptr) {
316 return -1;
317 }
318 return nativeHolder->GetID();
319 }
320
FfiOHOSHiAppEventSetSize(int64_t id,int size)321 int FfiOHOSHiAppEventSetSize(int64_t id, int size)
322 {
323 auto nativeAppEventPackageHolder = OHOS::FFI::FFIData::GetData<AppEventPackageHolderImpl>(id);
324 if (nativeAppEventPackageHolder == nullptr) {
325 return -1;
326 }
327 int ret = SUCCESS_CODE;
328 if (size >= 0) {
329 nativeAppEventPackageHolder->SetSize(size);
330 } else {
331 ret = ERR_INVALID_SIZE;
332 }
333 return ret;
334 }
335
FfiOHOSHiAppEventTakeNext(int64_t id)336 ReTakeNext FfiOHOSHiAppEventTakeNext(int64_t id)
337 {
338 auto nativeAppEventPackageHolder = OHOS::FFI::FFIData::GetData<AppEventPackageHolderImpl>(id);
339 if (nativeAppEventPackageHolder == nullptr) {
340 return ReTakeNext{.status = -1, .event = RetAppEventPackage{0}};
341 }
342 auto [state, package] = nativeAppEventPackageHolder->TakeNext();
343 ReTakeNext ret;
344 ret.status = state;
345 ret.event = package;
346 return ret;
347 }
348
FfiOHOSHiAppEventAddWatcher(CWatcher watcher)349 RetDataI64 FfiOHOSHiAppEventAddWatcher(CWatcher watcher)
350 {
351 RetDataI64 ret = { .code = ERR_PARAM, .data = 0 };
352 // check isValid
353 std::string name = std::string(watcher.name);
354 if (!IsValidWatcherName(name)) {
355 ret.code = ERR_INVALID_WATCHER_NAME;
356 return ret;
357 }
358 TriggerCondition cond;
359 ret.code = CheckCondition(cond, watcher.triggerCondition);
360 if (ret.code != ERR_PARAM) {
361 return ret;
362 }
363 std::vector<AppEventFilter> filters;
364 std::unordered_set<std::string> names;
365 for (int i = 0; i < watcher.appEventFilters.size; i++) {
366 for (int j = 0; j < watcher.appEventFilters.head[i].names.size; j++) {
367 names.insert(std::string(watcher.appEventFilters.head[i].names.head[j]));
368 }
369 std::string domain = std::string(watcher.appEventFilters.head[i].domain);
370 if (!IsValidDomain(domain)) {
371 ret.code = ERR_INVALID_FILTER_DOMAIN;
372 return ret;
373 }
374 uint32_t types = 0;
375 for (int k = 0; k < watcher.appEventFilters.head[i].eventTypes.size; k++) {
376 types |= (BIT_MASK << watcher.appEventFilters.head[i].eventTypes.head[k]);
377 }
378 types = types > 0 ? types : BIT_ALL_TYPES;
379 filters.emplace_back(AppEventFilter(domain, names, types));
380 }
381
382 auto [status, holderId] = HiAppEventImpl::addWatcher(name, filters, cond,
383 watcher.callbackOnTriggerRef, watcher.callbackOnReceiveRef);
384 if (status != 0) {
385 ret.code = status;
386 return ret;
387 }
388 if (holderId == -1) {
389 ret.data = -1;
390 return ret;
391 }
392 ret.code = status;
393 ret.data = holderId;
394 return ret;
395 }
396
FfiOHOSHiAppEventRemoveWatcher(CWatcher watcher)397 int FfiOHOSHiAppEventRemoveWatcher(CWatcher watcher)
398 {
399 std::string name = std::string(watcher.name);
400 if (!IsValidWatcherName(name)) {
401 return ERR_INVALID_WATCHER_NAME;
402 }
403 HiAppEventImpl::removeWatcher(name);
404 return SUCCESS_CODE;
405 }
406 }