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" 29using namespace OHOS::HiviewDFX; 30using namespace OHOS::CJSystemapi::HiAppEvent; 31 32namespace { 33constexpr int ERR_CODE_PARAM_FORMAT = -1; 34constexpr int ERR_CODE_PARAM_INVALID = -2; 35const int8_t INT32_VALUE = 0; 36const int8_t DOUBLE_VALUE = 1; 37const int8_t STRING_VALUE = 2; 38const int8_t BOOL_VALUE = 3; 39const int8_t INT32_ARRAY_VALUE = 4; 40const int8_t DOUBLE_ARRAY_VALUE = 5; 41const int8_t STRING_ARRAY_VALUE = 6; 42const int8_t BOOL_ARRAY_VALUE = 7; 43constexpr int BIT_MASK = 1; 44constexpr unsigned int BIT_ALL_TYPES = 0xff; 45 46int 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 67void 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 74std::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 82int 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 97int 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 135void 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 184extern "C" { 185int 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 195int 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 207RetDataBool 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 231int FfiOHOSHiAppEventRemoveProcessor(int64_t id) 232{ 233 int res = HiAppEventImpl::RemoveProcessor(id); 234 return res; 235} 236 237int 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 252RetDataCString 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 272int 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 287RetDataCString 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 307void FfiOHOSHiAppEventclearData() 308{ 309 HiAppEventImpl::ClearData(); 310} 311 312int64_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 321int 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 336ReTakeNext 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 349RetDataI64 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 397int 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}