12f0d0f1aSopenharmony_ci/* 22f0d0f1aSopenharmony_ci* Copyright (c) 2024 Huawei Device Co., Ltd. 32f0d0f1aSopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License"); 42f0d0f1aSopenharmony_ci* you may not use this file except in compliance with the License. 52f0d0f1aSopenharmony_ci* You may obtain a copy of the License at 62f0d0f1aSopenharmony_ci* 72f0d0f1aSopenharmony_ci* http://www.apache.org/licenses/LICENSE-2.0 82f0d0f1aSopenharmony_ci* 92f0d0f1aSopenharmony_ci* Unless required by applicable law or agreed to in writing, software 102f0d0f1aSopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS, 112f0d0f1aSopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 122f0d0f1aSopenharmony_ci* See the License for the specific language governing permissions and 132f0d0f1aSopenharmony_ci* limitations under the License. 142f0d0f1aSopenharmony_ci*/ 152f0d0f1aSopenharmony_ci 162f0d0f1aSopenharmony_ci#include <iostream> 172f0d0f1aSopenharmony_ci#include <fstream> 182f0d0f1aSopenharmony_ci#include <sstream> 192f0d0f1aSopenharmony_ci#include <algorithm> 202f0d0f1aSopenharmony_ci#include <cstdlib> 212f0d0f1aSopenharmony_ci#include <climits> 222f0d0f1aSopenharmony_ci#include <unordered_map> 232f0d0f1aSopenharmony_ci#include <functional> 242f0d0f1aSopenharmony_ci#include <mutex> 252f0d0f1aSopenharmony_ci#include "app_event.h" 262f0d0f1aSopenharmony_ci#include "app_event_processor_mgr.h" 272f0d0f1aSopenharmony_ci#include "drm_log.h" 282f0d0f1aSopenharmony_ci#include "drm_error_code.h" 292f0d0f1aSopenharmony_ci#include "drm_api_operation.h" 302f0d0f1aSopenharmony_ci 312f0d0f1aSopenharmony_cinamespace OHOS { 322f0d0f1aSopenharmony_cinamespace DrmStandard { 332f0d0f1aSopenharmony_ci// Global variables for caching file content and mutex 342f0d0f1aSopenharmony_cistd::string ConfigParser::g_fileContent = ""; 352f0d0f1aSopenharmony_ciint64_t ConfigParser::g_processorId = -1; 362f0d0f1aSopenharmony_cistd::mutex ConfigParser::g_apiOperationMutex; 372f0d0f1aSopenharmony_ciconst int32_t APP_FLAG = -200; 382f0d0f1aSopenharmony_ci 392f0d0f1aSopenharmony_cibool ConfigParser::LoadConfigurationFile(const std::string &configFile) 402f0d0f1aSopenharmony_ci{ 412f0d0f1aSopenharmony_ci std::ifstream file(configFile); 422f0d0f1aSopenharmony_ci if (!file.is_open()) { 432f0d0f1aSopenharmony_ci perror("Unable to open api operation config file!"); 442f0d0f1aSopenharmony_ci return false; 452f0d0f1aSopenharmony_ci } 462f0d0f1aSopenharmony_ci 472f0d0f1aSopenharmony_ci std::ostringstream oss; 482f0d0f1aSopenharmony_ci std::string line; 492f0d0f1aSopenharmony_ci while (std::getline(file, line)) { 502f0d0f1aSopenharmony_ci line = Trim(line); 512f0d0f1aSopenharmony_ci if (!line.empty() && line[0] != '#') { 522f0d0f1aSopenharmony_ci oss << line << "\n"; 532f0d0f1aSopenharmony_ci } 542f0d0f1aSopenharmony_ci } 552f0d0f1aSopenharmony_ci g_fileContent = oss.str(); 562f0d0f1aSopenharmony_ci file.close(); 572f0d0f1aSopenharmony_ci return true; 582f0d0f1aSopenharmony_ci} 592f0d0f1aSopenharmony_ci 602f0d0f1aSopenharmony_civoid ConfigParser::GetConfigurationParams(ApiReportConfig &reportConfig, ApiEventConfig &eventConfig) 612f0d0f1aSopenharmony_ci{ 622f0d0f1aSopenharmony_ci std::istringstream stream(g_fileContent); 632f0d0f1aSopenharmony_ci ParseApiOperationManagement(stream, reportConfig, eventConfig); 642f0d0f1aSopenharmony_ci} 652f0d0f1aSopenharmony_ci 662f0d0f1aSopenharmony_cistd::string ConfigParser::Trim(const std::string &str) 672f0d0f1aSopenharmony_ci{ 682f0d0f1aSopenharmony_ci const char* whitespace = " \t\n\r"; 692f0d0f1aSopenharmony_ci size_t first = str.find_first_not_of(whitespace); 702f0d0f1aSopenharmony_ci size_t last = str.find_last_not_of(whitespace); 712f0d0f1aSopenharmony_ci return (first == std::string::npos) ? "" : str.substr(first, last - first + 1); 722f0d0f1aSopenharmony_ci} 732f0d0f1aSopenharmony_ci 742f0d0f1aSopenharmony_cistd::pair<std::string, std::string> ConfigParser::ParseKeyValue(const std::string &line) 752f0d0f1aSopenharmony_ci{ 762f0d0f1aSopenharmony_ci size_t colonPos = line.find(':'); 772f0d0f1aSopenharmony_ci if (colonPos != std::string::npos) { 782f0d0f1aSopenharmony_ci std::string key = Trim(line.substr(0, colonPos)); 792f0d0f1aSopenharmony_ci std::string value = Trim(line.substr(colonPos + 1)); 802f0d0f1aSopenharmony_ci key.erase(std::remove(key.begin(), key.end(), '"'), key.end()); 812f0d0f1aSopenharmony_ci value.erase(std::remove(value.begin(), value.end(), '"'), value.end()); 822f0d0f1aSopenharmony_ci if (!value.empty() && value.back() == ',') { 832f0d0f1aSopenharmony_ci value.pop_back(); // Remove trailing comma if present 842f0d0f1aSopenharmony_ci } 852f0d0f1aSopenharmony_ci return std::make_pair(key, value); 862f0d0f1aSopenharmony_ci } 872f0d0f1aSopenharmony_ci return std::make_pair("", ""); 882f0d0f1aSopenharmony_ci} 892f0d0f1aSopenharmony_ci 902f0d0f1aSopenharmony_cibool ConfigParser::TryParseInt(const std::string& str, int& out) 912f0d0f1aSopenharmony_ci{ 922f0d0f1aSopenharmony_ci char* end; 932f0d0f1aSopenharmony_ci long val = strtol(str.c_str(), &end, 10); 942f0d0f1aSopenharmony_ci if (*end == '\0' && end != str.c_str() && val >= INT_MIN && val <= INT_MAX) { 952f0d0f1aSopenharmony_ci out = static_cast<int>(val); 962f0d0f1aSopenharmony_ci return true; 972f0d0f1aSopenharmony_ci } else { 982f0d0f1aSopenharmony_ci DRM_ERR_LOG("Invalid integer: %{public}s", str.c_str()); 992f0d0f1aSopenharmony_ci return false; 1002f0d0f1aSopenharmony_ci } 1012f0d0f1aSopenharmony_ci} 1022f0d0f1aSopenharmony_ci 1032f0d0f1aSopenharmony_civoid ConfigParser::ParseReportConfig(std::istringstream &stream, ApiReportConfig &reportConfig) 1042f0d0f1aSopenharmony_ci{ 1052f0d0f1aSopenharmony_ci std::unordered_map<std::string, std::function<void(const std::string&)>> configMap = { 1062f0d0f1aSopenharmony_ci {"config_name", [&](const std::string &value) { reportConfig.config_name = value; }}, 1072f0d0f1aSopenharmony_ci {"config_appId", [&](const std::string &value) { reportConfig.config_appId = value; }}, 1082f0d0f1aSopenharmony_ci {"config_routeInfo", [&](const std::string &value) { reportConfig.config_routeInfo = value; }}, 1092f0d0f1aSopenharmony_ci {"config_TriggerCond.timeout", [&](const std::string &value) { 1102f0d0f1aSopenharmony_ci int temp; 1112f0d0f1aSopenharmony_ci if (TryParseInt(value, temp)) { 1122f0d0f1aSopenharmony_ci reportConfig.config_timeout = temp; 1132f0d0f1aSopenharmony_ci } else { 1142f0d0f1aSopenharmony_ci DRM_ERR_LOG("Invalid integer for config_timeout: %{public}s", value.c_str()); 1152f0d0f1aSopenharmony_ci } 1162f0d0f1aSopenharmony_ci }}, 1172f0d0f1aSopenharmony_ci {"config_TriggerCond.row", [&](const std::string &value) { 1182f0d0f1aSopenharmony_ci int temp; 1192f0d0f1aSopenharmony_ci if (TryParseInt(value, temp)) { 1202f0d0f1aSopenharmony_ci reportConfig.config_row = temp; 1212f0d0f1aSopenharmony_ci } else { 1222f0d0f1aSopenharmony_ci DRM_ERR_LOG("Invalid integer for config_row: %{public}s", value.c_str()); 1232f0d0f1aSopenharmony_ci } 1242f0d0f1aSopenharmony_ci }} 1252f0d0f1aSopenharmony_ci }; 1262f0d0f1aSopenharmony_ci 1272f0d0f1aSopenharmony_ci std::string line; 1282f0d0f1aSopenharmony_ci while (std::getline(stream, line)) { 1292f0d0f1aSopenharmony_ci line = Trim(line); 1302f0d0f1aSopenharmony_ci if (line == "},") { 1312f0d0f1aSopenharmony_ci break; 1322f0d0f1aSopenharmony_ci } 1332f0d0f1aSopenharmony_ci auto keyValue = ParseKeyValue(line); 1342f0d0f1aSopenharmony_ci auto it = configMap.find(keyValue.first); 1352f0d0f1aSopenharmony_ci if (it != configMap.end()) { 1362f0d0f1aSopenharmony_ci it->second(keyValue.second); 1372f0d0f1aSopenharmony_ci } 1382f0d0f1aSopenharmony_ci } 1392f0d0f1aSopenharmony_ci} 1402f0d0f1aSopenharmony_ci 1412f0d0f1aSopenharmony_civoid ConfigParser::ParseEvent(std::istringstream &stream, ApiEvent &event) 1422f0d0f1aSopenharmony_ci{ 1432f0d0f1aSopenharmony_ci std::unordered_map<std::string, std::function<void(const std::string&)>> eventMap = { 1442f0d0f1aSopenharmony_ci {"domain", [&](const std::string &value) { event.domain = value; }}, 1452f0d0f1aSopenharmony_ci {"name", [&](const std::string &value) { event.name = value; }}, 1462f0d0f1aSopenharmony_ci {"isRealTime", [&](const std::string &value) { event.isRealTime = (value == "true"); }} 1472f0d0f1aSopenharmony_ci }; 1482f0d0f1aSopenharmony_ci 1492f0d0f1aSopenharmony_ci std::string line; 1502f0d0f1aSopenharmony_ci while (std::getline(stream, line)) { 1512f0d0f1aSopenharmony_ci line = Trim(line); 1522f0d0f1aSopenharmony_ci if (line == "},") { 1532f0d0f1aSopenharmony_ci break; 1542f0d0f1aSopenharmony_ci } 1552f0d0f1aSopenharmony_ci auto keyValue = ParseKeyValue(line); 1562f0d0f1aSopenharmony_ci auto it = eventMap.find(keyValue.first); 1572f0d0f1aSopenharmony_ci if (it != eventMap.end()) { 1582f0d0f1aSopenharmony_ci it->second(keyValue.second); 1592f0d0f1aSopenharmony_ci } 1602f0d0f1aSopenharmony_ci } 1612f0d0f1aSopenharmony_ci} 1622f0d0f1aSopenharmony_ci 1632f0d0f1aSopenharmony_civoid ConfigParser::ParseEventConfig(std::istringstream &stream, ApiEventConfig &eventConfig) 1642f0d0f1aSopenharmony_ci{ 1652f0d0f1aSopenharmony_ci std::unordered_map<std::string, std::function<void(std::istringstream&)>> eventConfigMap = { 1662f0d0f1aSopenharmony_ci {"\"event1\": {", [&](std::istringstream &stream) { ParseEvent(stream, eventConfig.event1); }}, 1672f0d0f1aSopenharmony_ci {"\"event2\": {", [&](std::istringstream &stream) { ParseEvent(stream, eventConfig.event2); }}, 1682f0d0f1aSopenharmony_ci {"\"event3\": {", [&](std::istringstream &stream) { ParseEvent(stream, eventConfig.event3); }} 1692f0d0f1aSopenharmony_ci }; 1702f0d0f1aSopenharmony_ci 1712f0d0f1aSopenharmony_ci std::string line; 1722f0d0f1aSopenharmony_ci while (std::getline(stream, line)) { 1732f0d0f1aSopenharmony_ci line = Trim(line); 1742f0d0f1aSopenharmony_ci if (line == "},") { 1752f0d0f1aSopenharmony_ci break; 1762f0d0f1aSopenharmony_ci } 1772f0d0f1aSopenharmony_ci auto it = eventConfigMap.find(line); 1782f0d0f1aSopenharmony_ci if (it != eventConfigMap.end()) { 1792f0d0f1aSopenharmony_ci it->second(stream); 1802f0d0f1aSopenharmony_ci } 1812f0d0f1aSopenharmony_ci } 1822f0d0f1aSopenharmony_ci} 1832f0d0f1aSopenharmony_ci 1842f0d0f1aSopenharmony_civoid ConfigParser::ParseApiOperationManagement(std::istringstream &stream, ApiReportConfig &reportConfig, 1852f0d0f1aSopenharmony_ci ApiEventConfig &eventConfig) 1862f0d0f1aSopenharmony_ci{ 1872f0d0f1aSopenharmony_ci std::unordered_map<std::string, std::function<void(std::istringstream&)>> apiOpMgmtMap = { 1882f0d0f1aSopenharmony_ci {"\"report_config\": {", [&](std::istringstream &stream) { ParseReportConfig(stream, reportConfig); }}, 1892f0d0f1aSopenharmony_ci {"\"event_config\": {", [&](std::istringstream &stream) { ParseEventConfig(stream, eventConfig); }} 1902f0d0f1aSopenharmony_ci }; 1912f0d0f1aSopenharmony_ci 1922f0d0f1aSopenharmony_ci std::string line; 1932f0d0f1aSopenharmony_ci while (std::getline(stream, line)) { 1942f0d0f1aSopenharmony_ci line = Trim(line); 1952f0d0f1aSopenharmony_ci if (line == "}") { 1962f0d0f1aSopenharmony_ci break; 1972f0d0f1aSopenharmony_ci } 1982f0d0f1aSopenharmony_ci auto it = apiOpMgmtMap.find(line); 1992f0d0f1aSopenharmony_ci if (it != apiOpMgmtMap.end()) { 2002f0d0f1aSopenharmony_ci it->second(stream); 2012f0d0f1aSopenharmony_ci } 2022f0d0f1aSopenharmony_ci } 2032f0d0f1aSopenharmony_ci} 2042f0d0f1aSopenharmony_ci 2052f0d0f1aSopenharmony_ciint64_t ConfigParser::AddProcessor() 2062f0d0f1aSopenharmony_ci{ 2072f0d0f1aSopenharmony_ci DRM_INFO_LOG("AddProcessor enter."); 2082f0d0f1aSopenharmony_ci ApiReportConfig reportConfig; 2092f0d0f1aSopenharmony_ci ApiEventConfig eventConfig; 2102f0d0f1aSopenharmony_ci std::lock_guard<std::mutex> lock(g_apiOperationMutex); 2112f0d0f1aSopenharmony_ci if (g_processorId != -1) { 2122f0d0f1aSopenharmony_ci DRM_DEBUG_LOG("AddProcessor exit"); 2132f0d0f1aSopenharmony_ci return g_processorId; 2142f0d0f1aSopenharmony_ci } 2152f0d0f1aSopenharmony_ci if (g_processorId == APP_FLAG) { 2162f0d0f1aSopenharmony_ci DRM_ERR_LOG("dotting is not supported for non-apps"); 2172f0d0f1aSopenharmony_ci return g_processorId; 2182f0d0f1aSopenharmony_ci } 2192f0d0f1aSopenharmony_ci if (LoadConfigurationFile(DRM_API_OPERATION_CONFIG_PATH) != true) { 2202f0d0f1aSopenharmony_ci DRM_ERR_LOG("AddProcessor LoadConfigurationFile error!"); 2212f0d0f1aSopenharmony_ci return DRM_OPERATION_NOT_ALLOWED; 2222f0d0f1aSopenharmony_ci } 2232f0d0f1aSopenharmony_ci GetConfigurationParams(reportConfig, eventConfig); 2242f0d0f1aSopenharmony_ci HiviewDFX::HiAppEvent::ReportConfig config; 2252f0d0f1aSopenharmony_ci config.name = reportConfig.config_name; 2262f0d0f1aSopenharmony_ci config.appId = reportConfig.config_appId; 2272f0d0f1aSopenharmony_ci config.routeInfo = reportConfig.config_routeInfo; 2282f0d0f1aSopenharmony_ci config.triggerCond.timeout = reportConfig.config_timeout; 2292f0d0f1aSopenharmony_ci config.triggerCond.row = reportConfig.config_row; 2302f0d0f1aSopenharmony_ci config.eventConfigs.clear(); 2312f0d0f1aSopenharmony_ci HiviewDFX::HiAppEvent::EventConfig event1; 2322f0d0f1aSopenharmony_ci event1.domain = eventConfig.event1.domain; 2332f0d0f1aSopenharmony_ci event1.name = eventConfig.event1.name; 2342f0d0f1aSopenharmony_ci event1.isRealTime = eventConfig.event1.isRealTime; 2352f0d0f1aSopenharmony_ci config.eventConfigs.push_back(event1); 2362f0d0f1aSopenharmony_ci HiviewDFX::HiAppEvent::EventConfig event2; 2372f0d0f1aSopenharmony_ci event2.domain = eventConfig.event2.domain; 2382f0d0f1aSopenharmony_ci event2.name = eventConfig.event2.name; 2392f0d0f1aSopenharmony_ci event2.isRealTime = eventConfig.event2.isRealTime; 2402f0d0f1aSopenharmony_ci config.eventConfigs.push_back(event2); 2412f0d0f1aSopenharmony_ci HiviewDFX::HiAppEvent::EventConfig event3; 2422f0d0f1aSopenharmony_ci event3.domain = eventConfig.event3.domain; 2432f0d0f1aSopenharmony_ci event3.name = eventConfig.event3.name; 2442f0d0f1aSopenharmony_ci event3.isRealTime = eventConfig.event3.isRealTime; 2452f0d0f1aSopenharmony_ci config.eventConfigs.push_back(event3); 2462f0d0f1aSopenharmony_ci g_processorId = HiviewDFX::HiAppEvent::AppEventProcessorMgr::AddProcessor(config); 2472f0d0f1aSopenharmony_ci return g_processorId; 2482f0d0f1aSopenharmony_ci} 2492f0d0f1aSopenharmony_ci 2502f0d0f1aSopenharmony_civoid ConfigParser::WriteEndEvent(const int result, const int errCode, std::string apiName, int64_t beginTime) 2512f0d0f1aSopenharmony_ci{ 2522f0d0f1aSopenharmony_ci DRM_INFO_LOG("WriteEndEvent enter."); 2532f0d0f1aSopenharmony_ci (void)AddProcessor(); 2542f0d0f1aSopenharmony_ci std::string transId = std::string("traceId_") + std::to_string(std::rand()); 2552f0d0f1aSopenharmony_ci int64_t endTime = std::chrono::duration_cast<std::chrono::milliseconds>( 2562f0d0f1aSopenharmony_ci std::chrono::system_clock::now().time_since_epoch()).count(); 2572f0d0f1aSopenharmony_ci 2582f0d0f1aSopenharmony_ci HiviewDFX::HiAppEvent::Event event("api_diagnostic", "api_exec_end", OHOS::HiviewDFX::HiAppEvent::BEHAVIOR); 2592f0d0f1aSopenharmony_ci event.AddParam("trans_id", transId); 2602f0d0f1aSopenharmony_ci event.AddParam("api_name", apiName); 2612f0d0f1aSopenharmony_ci event.AddParam("sdk_name", std::string("DrmKit")); 2622f0d0f1aSopenharmony_ci event.AddParam("begin_time", beginTime); 2632f0d0f1aSopenharmony_ci event.AddParam("end_time", endTime); 2642f0d0f1aSopenharmony_ci event.AddParam("result", result); 2652f0d0f1aSopenharmony_ci event.AddParam("error_code", errCode); 2662f0d0f1aSopenharmony_ci HiviewDFX::HiAppEvent::Write(event); 2672f0d0f1aSopenharmony_ci} 2682f0d0f1aSopenharmony_ci} // namespace DrmStandard 2692f0d0f1aSopenharmony_ci} // namespace OHOS