1da853ecaSopenharmony_ci/*
2da853ecaSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
3da853ecaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4da853ecaSopenharmony_ci * you may not use this file except in compliance with the License.
5da853ecaSopenharmony_ci * You may obtain a copy of the License at
6da853ecaSopenharmony_ci *
7da853ecaSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8da853ecaSopenharmony_ci *
9da853ecaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10da853ecaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11da853ecaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12da853ecaSopenharmony_ci * See the License for the specific language governing permissions and
13da853ecaSopenharmony_ci * limitations under the License.
14da853ecaSopenharmony_ci */
15da853ecaSopenharmony_ci
16da853ecaSopenharmony_ci#include "avcodec_xcollie.h"
17da853ecaSopenharmony_ci#include <unistd.h>
18da853ecaSopenharmony_ci#include "avcodec_errors.h"
19da853ecaSopenharmony_ci#include "param_wrapper.h"
20da853ecaSopenharmony_ci#include "avcodec_dump_utils.h"
21da853ecaSopenharmony_ci#include "avcodec_log.h"
22da853ecaSopenharmony_ci#include "avcodec_sysevent.h"
23da853ecaSopenharmony_ci#ifdef HICOLLIE_ENABLE
24da853ecaSopenharmony_ci#include "xcollie/xcollie.h"
25da853ecaSopenharmony_ci#include "xcollie/xcollie_define.h"
26da853ecaSopenharmony_ci#endif
27da853ecaSopenharmony_ci
28da853ecaSopenharmony_cinamespace {
29da853ecaSopenharmony_ci    constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AVCodecXCollie"};
30da853ecaSopenharmony_ci    constexpr uint32_t DUMP_XCOLLIE_INDEX = 0x01000000;
31da853ecaSopenharmony_ci    constexpr uint8_t DUMP_OFFSET_16 = 16;
32da853ecaSopenharmony_ci    constexpr uint64_t COLLIE_INVALID_INDEX = 0;
33da853ecaSopenharmony_ci}
34da853ecaSopenharmony_ci
35da853ecaSopenharmony_cinamespace OHOS {
36da853ecaSopenharmony_cinamespace MediaAVCodec {
37da853ecaSopenharmony_ciAVCodecXCollie &AVCodecXCollie::GetInstance()
38da853ecaSopenharmony_ci{
39da853ecaSopenharmony_ci    static AVCodecXCollie instance;
40da853ecaSopenharmony_ci    return instance;
41da853ecaSopenharmony_ci}
42da853ecaSopenharmony_ci
43da853ecaSopenharmony_civoid AVCodecXCollie::ServiceTimerCallback(void *data)
44da853ecaSopenharmony_ci{
45da853ecaSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
46da853ecaSopenharmony_ci    threadDeadlockCount_++;
47da853ecaSopenharmony_ci    std::string name = data != nullptr ? (char *)data : "";
48da853ecaSopenharmony_ci
49da853ecaSopenharmony_ci    AVCODEC_LOGE("Service task %{public}s timeout", name.c_str());
50da853ecaSopenharmony_ci    FaultEventWrite(FaultType::FAULT_TYPE_FREEZE, std::string("Service task ") +
51da853ecaSopenharmony_ci        name + std::string(" timeout"), "Service");
52da853ecaSopenharmony_ci
53da853ecaSopenharmony_ci    static constexpr uint32_t threshold = 1; // >= 1 Restart service
54da853ecaSopenharmony_ci    if (threadDeadlockCount_ >= threshold) {
55da853ecaSopenharmony_ci        FaultEventWrite(FaultType::FAULT_TYPE_FREEZE,
56da853ecaSopenharmony_ci            "Process timeout, AVCodec service process exit.", "Service");
57da853ecaSopenharmony_ci        AVCODEC_LOGF("Process timeout, AVCodec service process exit.");
58da853ecaSopenharmony_ci        _exit(-1);
59da853ecaSopenharmony_ci    }
60da853ecaSopenharmony_ci}
61da853ecaSopenharmony_ci
62da853ecaSopenharmony_civoid AVCodecXCollie::ClientTimerCallback(void *data)
63da853ecaSopenharmony_ci{
64da853ecaSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
65da853ecaSopenharmony_ci    std::string name = data != nullptr ? (char *)data : "";
66da853ecaSopenharmony_ci    AVCODEC_LOGE("Client task %{public}s timeout", name.c_str());
67da853ecaSopenharmony_ci    FaultEventWrite(FaultType::FAULT_TYPE_FREEZE, std::string("Client task ") +
68da853ecaSopenharmony_ci        name + std::string(" timeout"), "Client");
69da853ecaSopenharmony_ci}
70da853ecaSopenharmony_ci
71da853ecaSopenharmony_ciint32_t AVCodecXCollie::Dump(int32_t fd)
72da853ecaSopenharmony_ci{
73da853ecaSopenharmony_ci    if (dfxDumper_.empty()) {
74da853ecaSopenharmony_ci        return AVCS_ERR_OK;
75da853ecaSopenharmony_ci    }
76da853ecaSopenharmony_ci
77da853ecaSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
78da853ecaSopenharmony_ci    std::string dumpString = "[AVCodec_XCollie]\n";
79da853ecaSopenharmony_ci    AVCodecDumpControler dumpControler;
80da853ecaSopenharmony_ci    uint32_t dumperIndex = 1;
81da853ecaSopenharmony_ci    for (const auto &iter : dfxDumper_) {
82da853ecaSopenharmony_ci        dumpControler.AddInfo(DUMP_XCOLLIE_INDEX + (dumperIndex << DUMP_OFFSET_16), "Timer_Name", iter.second.second);
83da853ecaSopenharmony_ci        dumperIndex++;
84da853ecaSopenharmony_ci    }
85da853ecaSopenharmony_ci    dumpControler.GetDumpString(dumpString);
86da853ecaSopenharmony_ci    if (fd != -1) {
87da853ecaSopenharmony_ci        write(fd, dumpString.c_str(), dumpString.size());
88da853ecaSopenharmony_ci        dumpString.clear();
89da853ecaSopenharmony_ci    }
90da853ecaSopenharmony_ci    return AVCS_ERR_OK;
91da853ecaSopenharmony_ci}
92da853ecaSopenharmony_ci
93da853ecaSopenharmony_ci
94da853ecaSopenharmony_ciuint64_t AVCodecXCollie::SetTimer(const std::string &name, bool isService, bool recovery, uint32_t timeout)
95da853ecaSopenharmony_ci{
96da853ecaSopenharmony_ci#ifdef HICOLLIE_ENABLE
97da853ecaSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
98da853ecaSopenharmony_ci
99da853ecaSopenharmony_ci    std::function<void (void *)> func;
100da853ecaSopenharmony_ci    if (isService) {
101da853ecaSopenharmony_ci        func = [this](void *data) { this->ServiceTimerCallback(data); };
102da853ecaSopenharmony_ci    } else {
103da853ecaSopenharmony_ci        func = [this](void *data) { this->ClientTimerCallback(data); };
104da853ecaSopenharmony_ci    }
105da853ecaSopenharmony_ci
106da853ecaSopenharmony_ci    unsigned int flag = HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_NOOP;
107da853ecaSopenharmony_ci    if (recovery) {
108da853ecaSopenharmony_ci        flag |= HiviewDFX::XCOLLIE_FLAG_RECOVERY;
109da853ecaSopenharmony_ci    }
110da853ecaSopenharmony_ci    uint64_t tempIndex = dumperIndex_++;
111da853ecaSopenharmony_ci    dfxDumper_.emplace(tempIndex, std::pair<int32_t, std::string>(HiviewDFX::INVALID_ID, name));
112da853ecaSopenharmony_ci    int32_t id = HiviewDFX::XCollie::GetInstance().SetTimer(name,
113da853ecaSopenharmony_ci        timeout, func, (void *)dfxDumper_[tempIndex].second.c_str(), flag);
114da853ecaSopenharmony_ci    if (id == HiviewDFX::INVALID_ID) {
115da853ecaSopenharmony_ci        auto it = dfxDumper_.find(tempIndex);
116da853ecaSopenharmony_ci        if (it != dfxDumper_.end()) {
117da853ecaSopenharmony_ci            dfxDumper_.erase(it);
118da853ecaSopenharmony_ci            return COLLIE_INVALID_INDEX;
119da853ecaSopenharmony_ci        }
120da853ecaSopenharmony_ci    }
121da853ecaSopenharmony_ci    dfxDumper_[tempIndex].first = id;
122da853ecaSopenharmony_ci    return tempIndex;
123da853ecaSopenharmony_ci#else
124da853ecaSopenharmony_ci    (void)dumperIndex_;
125da853ecaSopenharmony_ci    return COLLIE_INVALID_INDEX;
126da853ecaSopenharmony_ci#endif
127da853ecaSopenharmony_ci}
128da853ecaSopenharmony_ci
129da853ecaSopenharmony_civoid AVCodecXCollie::CancelTimer(uint64_t index)
130da853ecaSopenharmony_ci{
131da853ecaSopenharmony_ci#ifdef HICOLLIE_ENABLE
132da853ecaSopenharmony_ci    if (index == COLLIE_INVALID_INDEX) {
133da853ecaSopenharmony_ci        return;
134da853ecaSopenharmony_ci    }
135da853ecaSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
136da853ecaSopenharmony_ci    auto it = dfxDumper_.find(index);
137da853ecaSopenharmony_ci    if (it == dfxDumper_.end()) {
138da853ecaSopenharmony_ci        return;
139da853ecaSopenharmony_ci    }
140da853ecaSopenharmony_ci    int32_t id = it->second.first;
141da853ecaSopenharmony_ci    dfxDumper_.erase(it);
142da853ecaSopenharmony_ci    return HiviewDFX::XCollie::GetInstance().CancelTimer(id);
143da853ecaSopenharmony_ci#else
144da853ecaSopenharmony_ci    (void)index;
145da853ecaSopenharmony_ci    return;
146da853ecaSopenharmony_ci#endif
147da853ecaSopenharmony_ci}
148da853ecaSopenharmony_ci} // namespace MediaAVCodec
149da853ecaSopenharmony_ci} // namespace OHOS