1049e185fSopenharmony_ci/*
2049e185fSopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3049e185fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4049e185fSopenharmony_ci * you may not use this file except in compliance with the License.
5049e185fSopenharmony_ci * You may obtain a copy of the License at
6049e185fSopenharmony_ci *
7049e185fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8049e185fSopenharmony_ci *
9049e185fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10049e185fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11049e185fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12049e185fSopenharmony_ci * See the License for the specific language governing permissions and
13049e185fSopenharmony_ci * limitations under the License.
14049e185fSopenharmony_ci */
15049e185fSopenharmony_ci
16049e185fSopenharmony_ci#include "player_xcollie.h"
17049e185fSopenharmony_ci#include <unistd.h>
18049e185fSopenharmony_ci#include "media_errors.h"
19049e185fSopenharmony_ci#include "media_log.h"
20049e185fSopenharmony_ci#include "param_wrapper.h"
21049e185fSopenharmony_ci#ifdef HICOLLIE_ENABLE
22049e185fSopenharmony_ci#include "xcollie/xcollie.h"
23049e185fSopenharmony_ci#include "xcollie/xcollie_define.h"
24049e185fSopenharmony_ci#endif
25049e185fSopenharmony_ci
26049e185fSopenharmony_cinamespace {
27049e185fSopenharmony_ciconstexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "PlayerXCollie"};
28049e185fSopenharmony_ci}
29049e185fSopenharmony_ci
30049e185fSopenharmony_cinamespace OHOS {
31049e185fSopenharmony_cinamespace Media {
32049e185fSopenharmony_ciPlayerXCollie &PlayerXCollie::GetInstance()
33049e185fSopenharmony_ci{
34049e185fSopenharmony_ci    static PlayerXCollie instance;
35049e185fSopenharmony_ci    return instance;
36049e185fSopenharmony_ci}
37049e185fSopenharmony_ci
38049e185fSopenharmony_ciPlayerXCollie::~PlayerXCollie()
39049e185fSopenharmony_ci{
40049e185fSopenharmony_ci    MEDIA_LOGI("~PlayerXCollie()");
41049e185fSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
42049e185fSopenharmony_ci#ifdef HICOLLIE_ENABLE
43049e185fSopenharmony_ci    for (const auto &iter : dfxDumper_) {
44049e185fSopenharmony_ci        HiviewDFX::XCollie::GetInstance().CancelTimer(iter.first);
45049e185fSopenharmony_ci    }
46049e185fSopenharmony_ci#endif
47049e185fSopenharmony_ci    dfxDumper_.clear();
48049e185fSopenharmony_ci}
49049e185fSopenharmony_ci
50049e185fSopenharmony_civoid PlayerXCollie::TimerCallback(void *data)
51049e185fSopenharmony_ci{
52049e185fSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
53049e185fSopenharmony_ci    threadDeadlockCount_++;
54049e185fSopenharmony_ci    MEDIA_LOGE("threadDeadlockCount: %{public}d", threadDeadlockCount_);
55049e185fSopenharmony_ci    static constexpr uint32_t threshold = 5; // >5 Restart service
56049e185fSopenharmony_ci    if (threadDeadlockCount_ >= threshold) {
57049e185fSopenharmony_ci        _exit(-1);
58049e185fSopenharmony_ci    }
59049e185fSopenharmony_ci}
60049e185fSopenharmony_ci
61049e185fSopenharmony_ciint32_t PlayerXCollie::Dump(int32_t fd)
62049e185fSopenharmony_ci{
63049e185fSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
64049e185fSopenharmony_ci    std::string dumpString = "------------------XCollieDfx------------------\n";
65049e185fSopenharmony_ci    for (const auto &iter : dfxDumper_) {
66049e185fSopenharmony_ci        dumpString += "WaitTask-----";
67049e185fSopenharmony_ci        dumpString += iter.second;
68049e185fSopenharmony_ci        dumpString += "-----\n";
69049e185fSopenharmony_ci    }
70049e185fSopenharmony_ci    if (fd != -1) {
71049e185fSopenharmony_ci        write(fd, dumpString.c_str(), dumpString.size());
72049e185fSopenharmony_ci        dumpString.clear();
73049e185fSopenharmony_ci    }
74049e185fSopenharmony_ci    return MSERR_OK;
75049e185fSopenharmony_ci}
76049e185fSopenharmony_ci
77049e185fSopenharmony_ciint32_t PlayerXCollie::SetTimer(const std::string &name, bool recovery, uint32_t timeout)
78049e185fSopenharmony_ci{
79049e185fSopenharmony_ci#ifdef HICOLLIE_ENABLE
80049e185fSopenharmony_ci    auto func = [this](void *data) {
81049e185fSopenharmony_ci        this->TimerCallback(data);
82049e185fSopenharmony_ci    };
83049e185fSopenharmony_ci
84049e185fSopenharmony_ci    unsigned int flag = HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_NOOP;
85049e185fSopenharmony_ci    if (recovery) {
86049e185fSopenharmony_ci        flag |= HiviewDFX::XCOLLIE_FLAG_RECOVERY;
87049e185fSopenharmony_ci    }
88049e185fSopenharmony_ci    int32_t id = HiviewDFX::XCollie::GetInstance().SetTimer(name, timeout, func, this, flag);
89049e185fSopenharmony_ci    if (id != HiviewDFX::INVALID_ID) {
90049e185fSopenharmony_ci        std::lock_guard<std::mutex> lock(mutex_);
91049e185fSopenharmony_ci        dfxDumper_.emplace(id, name);
92049e185fSopenharmony_ci    }
93049e185fSopenharmony_ci    return id;
94049e185fSopenharmony_ci#else
95049e185fSopenharmony_ci    return -1;
96049e185fSopenharmony_ci#endif
97049e185fSopenharmony_ci}
98049e185fSopenharmony_ci
99049e185fSopenharmony_ciint32_t PlayerXCollie::SetTimerByLog(const std::string &name, uint32_t timeout)
100049e185fSopenharmony_ci{
101049e185fSopenharmony_ci#ifdef HICOLLIE_ENABLE
102049e185fSopenharmony_ci    unsigned int flag = HiviewDFX::XCOLLIE_FLAG_LOG;
103049e185fSopenharmony_ci    int32_t id = HiviewDFX::XCollie::GetInstance().SetTimer(name, timeout, nullptr, this, flag);
104049e185fSopenharmony_ci    if (id != HiviewDFX::INVALID_ID) {
105049e185fSopenharmony_ci        std::lock_guard<std::mutex> lock(mutex_);
106049e185fSopenharmony_ci        dfxDumper_.emplace(id, name);
107049e185fSopenharmony_ci    }
108049e185fSopenharmony_ci    return id;
109049e185fSopenharmony_ci#else
110049e185fSopenharmony_ci    return -1;
111049e185fSopenharmony_ci#endif
112049e185fSopenharmony_ci}
113049e185fSopenharmony_ci
114049e185fSopenharmony_civoid PlayerXCollie::CancelTimer(int32_t id)
115049e185fSopenharmony_ci{
116049e185fSopenharmony_ci#ifdef HICOLLIE_ENABLE
117049e185fSopenharmony_ci    if (id != HiviewDFX::INVALID_ID) {
118049e185fSopenharmony_ci        std::lock_guard<std::mutex> lock(mutex_);
119049e185fSopenharmony_ci        if (dfxDumper_.size() == 0) {
120049e185fSopenharmony_ci            return;
121049e185fSopenharmony_ci        }
122049e185fSopenharmony_ci        auto it = dfxDumper_.find(id);
123049e185fSopenharmony_ci        if (it != dfxDumper_.end()) {
124049e185fSopenharmony_ci            dfxDumper_.erase(it);
125049e185fSopenharmony_ci            return HiviewDFX::XCollie::GetInstance().CancelTimer(id);
126049e185fSopenharmony_ci        }
127049e185fSopenharmony_ci    }
128049e185fSopenharmony_ci#else
129049e185fSopenharmony_ci    (void)id;
130049e185fSopenharmony_ci    return;
131049e185fSopenharmony_ci#endif
132049e185fSopenharmony_ci}
133049e185fSopenharmony_ci} // namespace Media
134049e185fSopenharmony_ci} // namespace OHOS