* Copyright (C) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <avcodec_sysevent.h>
#include <unistd.h>
#include <unordered_map>
#include <mutex>
#include <cstring>
#include "avcodec_log.h"
#include "avcodec_errors.h"
#include <openssl/evp.h>
#include "hisysevent.h"
#include <nlohmann/json.hpp>
using Json = nlohmann::json;
namespace {
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AVCodecSysEvent"};
constexpr char HISYSEVENT_DOMAIN_AVCODEC[] = "AV_CODEC";
const std::unordered_map<OHOS::MediaAVCodec::FaultType, std::string> FAULT_TYPE_TO_STRING = {
{OHOS::MediaAVCodec::FaultType::FAULT_TYPE_FREEZE, "Freeze"},
{OHOS::MediaAVCodec::FaultType::FAULT_TYPE_CRASH, "Crash"},
{OHOS::MediaAVCodec::FaultType::FAULT_TYPE_INNER_ERROR, "Inner error"},
};
constexpr static int32_t SOURCE_STATISTICS_REPORT_HOURS = 4;
}
namespace OHOS {
namespace MediaAVCodec {
void FaultEventWrite(FaultType faultType, const std::string& msg, const std::string& module)
{
CHECK_AND_RETURN_LOG(faultType >= FaultType::FAULT_TYPE_FREEZE && faultType < FaultType::FAULT_TYPE_END,
"Invalid fault type: %{public}d", faultType);
HiSysEventWrite(HISYSEVENT_DOMAIN_AVCODEC, "FAULT",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"MODULE", module,
"FAULTTYPE", FAULT_TYPE_TO_STRING.at(faultType),
"MSG", msg);
}
void ServiceStartEventWrite(uint32_t useTime, const std::string& module)
{
uint64_t useMemory = 5000;
HiSysEventWrite(HISYSEVENT_DOMAIN_AVCODEC, "SERVICE_START_INFO",
OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "MODULE", module.c_str(), "TIME", useTime,
"MEMORY", useMemory);
}
void StreamAppPackageNameEventWrite(const std::string& sysCap,
const std::string& packageName, const std::string& apiCall, const std::string& mediaEvents)
{
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, "MEDIAKIT_STATISTICS",
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
"SYSCAP", sysCap,
"APP_NAME", packageName,
"INSTANCE_ID", "",
"API_CALL", apiCall,
"MEDIA_EVENTS", mediaEvents);
}
void CodecStartEventWrite(CodecDfxInfo& codecDfxInfo)
{
HiSysEventWrite(HISYSEVENT_DOMAIN_AVCODEC, "CODEC_START_INFO",
OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
"CLIENT_PID", codecDfxInfo.clientPid,
"CLIENT_UID", codecDfxInfo.clientUid,
"CODEC_INSTANCE_ID", codecDfxInfo.codecInstanceId,
"CODEC_NAME", codecDfxInfo.codecName,
"CODEC_IS_VENDOR", codecDfxInfo.codecIsVendor,
"CODEC_MODE", codecDfxInfo.codecMode,
"ENCODER_BITRATE", codecDfxInfo.encoderBitRate,
"VIDEO_WIDTH", codecDfxInfo.videoWidth,
"VIDEO_HEIGHT", codecDfxInfo.videoHeight,
"VIDEO_FRAMERATE", codecDfxInfo.videoFrameRate,
"VIDEO_PIXEL_FORMAT", codecDfxInfo.videoPixelFormat,
"AUDIO_CHANNEL_COUNT", codecDfxInfo.audioChannelCount,
"AUDIO_SAMPLE_RATE", codecDfxInfo.audioSampleRate);
}
void CodecStopEventWrite(pid_t clientPid, uid_t clientUid, int32_t codecInstanceId)
{
HiSysEventWrite(HISYSEVENT_DOMAIN_AVCODEC, "CODEC_STOP_INFO",
OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
"CLIENT_PID", clientPid, "CLIENT_UID", clientUid, "CODEC_INSTANCE_ID", codecInstanceId);
}
void FaultDemuxerEventWrite(DemuxerFaultInfo& demuxerFaultInfo)
{
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, "DEMUXER_FAILURE",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"APP_NAME", demuxerFaultInfo.appName,
"INSTANCE_ID", demuxerFaultInfo.instanceId,
"CALLER_TYPE", demuxerFaultInfo.callerType,
"SOURCE_TYPE", demuxerFaultInfo.sourceType,
"CONTAINER_FORMAT", demuxerFaultInfo.containerFormat,
"STREAM_TYPE", demuxerFaultInfo.streamType,
"ERROR_MESG", demuxerFaultInfo.errMsg);
}
void FaultAudioCodecEventWrite(AudioCodecFaultInfo& audioCodecFaultInfo)
{
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, "AUDIO_CODEC_FAILURE",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"APP_NAME", audioCodecFaultInfo.appName,
"INSTANCE_ID", audioCodecFaultInfo.instanceId,
"CALLER_TYPE", audioCodecFaultInfo.callerType,
"AUDIO_CODEC", audioCodecFaultInfo.audioCodec,
"ERROR_MESG", audioCodecFaultInfo.errMsg);
}
void FaultVideoCodecEventWrite(VideoCodecFaultInfo& videoCodecFaultInfo)
{
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, "VIDEO_CODEC_FAILURE",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"APP_NAME", videoCodecFaultInfo.appName,
"INSTANCE_ID", videoCodecFaultInfo.instanceId,
"CALLER_TYPE", videoCodecFaultInfo.callerType,
"VIDEO_CODEC", videoCodecFaultInfo.videoCodec,
"ERROR_MESG", videoCodecFaultInfo.errMsg);
}
void FaultMuxerEventWrite(MuxerFaultInfo& muxerFaultInfo)
{
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, "MUXER_FAILURE",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"APP_NAME", muxerFaultInfo.appName,
"INSTANCE_ID", muxerFaultInfo.instanceId,
"CALLER_TYPE", muxerFaultInfo.callerType,
"VIDEO_CODEC", muxerFaultInfo.videoCodec,
"AUDIO_CODEC", muxerFaultInfo.audioCodec,
"CONTAINER_FORMAT", muxerFaultInfo.containerFormat,
"ERROR_MESG", muxerFaultInfo.errMsg);
}
void FaultRecordAudioEventWrite(AudioSourceFaultInfo& audioSourceFaultInfo)
{
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, "RECORD_AUDIO_FAILURE",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"APP_NAME", audioSourceFaultInfo.appName,
"INSTANCE_ID", audioSourceFaultInfo.instanceId,
"AUDIO_SOURCE_TYPE", audioSourceFaultInfo.audioSourceType,
"ERROR_MESG", audioSourceFaultInfo.errMsg);
}
void SourceStatisticsEventWrite(SourceStatisticsReportInfo& sourceReportInfo)
{
static std::list<std::string> reportInfoList;
static std::chrono::system_clock::time_point lastUpdateTime = std::chrono::system_clock::now();
static std::mutex sourceMutex;
std::lock_guard<std::mutex> lock(sourceMutex);
Json json;
uint8_t hash[EVP_MAX_MD_SIZE];
uint32_t hashLen;
EVP_Digest(sourceReportInfo.ca_.c_str(), sourceReportInfo.ca_.size(), hash, &hashLen, EVP_sha256(), NULL);
json["APP_NAME"] = sourceReportInfo.appName_;
json["MEDIA_EVENTS"]["SOURCE_TYPE"] = sourceReportInfo.sourceType_;
json["MEDIA_EVENTS"]["SOURCE_URI"] = sourceReportInfo.sourceUri_;
json["MEDIA_EVENTS"]["PLAY_STRATEGY_DURATION"] = sourceReportInfo.playStrategyDuration_;
json["MEDIA_EVENTS"]["PLAY_STRATEGY_BUFFER_DURATION_FOR_PLAYING"] =
sourceReportInfo.playStrateBufferDurationForPlaying_;
json["MEDIA_EVENTS"]["BITRATE"] = sourceReportInfo.bitRate_;
json["MEDIA_EVENTS"]["VIDEO_STREAM_CNT"] = sourceReportInfo.videoStreamCnt_;
json["MEDIA_EVENTS"]["AUDIO_STREAM_CNT"] = sourceReportInfo.audioStreamCnt_;
json["MEDIA_EVENTS"]["SUBTITLE_STREAM_CNT"] = sourceReportInfo.subtitleCnt_;
json["MEDIA_EVENTS"]["CERT_ISSUER_NAMES"] = sourceReportInfo.ca_;
json["MEDIA_EVENTS"]["CERT_HASH"] = hash;
std::string jsonString = json.dump();
reportInfoList.push_back(jsonString);
auto currentTime = std::chrono::system_clock::now();
auto diff = currentTime - lastUpdateTime;
auto hour = std::chrono::duration_cast<std::chrono::hours>(diff).count();
if (hour >= SOURCE_STATISTICS_REPORT_HOURS) {
for (auto& report : reportInfoList) {
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA,
"SOURCE_STATISTICS",
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
"EVENTS", report);
}
reportInfoList.clear();
lastUpdateTime = currentTime;
}
}
}
}