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 }