1f857971dSopenharmony_ci/*
2f857971dSopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3f857971dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4f857971dSopenharmony_ci * you may not use this file except in compliance with the License.
5f857971dSopenharmony_ci * You may obtain a copy of the License at
6f857971dSopenharmony_ci *
7f857971dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8f857971dSopenharmony_ci *
9f857971dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10f857971dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11f857971dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f857971dSopenharmony_ci * See the License for the specific language governing permissions and
13f857971dSopenharmony_ci * limitations under the License.
14f857971dSopenharmony_ci */
15f857971dSopenharmony_ci
16f857971dSopenharmony_ci#include "devicestatus_dumper.h"
17f857971dSopenharmony_ci
18f857971dSopenharmony_ci#include <cinttypes>
19f857971dSopenharmony_ci#include <cstring>
20f857971dSopenharmony_ci#include <getopt.h>
21f857971dSopenharmony_ci#include <iomanip>
22f857971dSopenharmony_ci#include <map>
23f857971dSopenharmony_ci#include <sstream>
24f857971dSopenharmony_ci
25f857971dSopenharmony_ci#include <ipc_skeleton.h>
26f857971dSopenharmony_ci#include "securec.h"
27f857971dSopenharmony_ci#include "string_ex.h"
28f857971dSopenharmony_ci#include "unique_fd.h"
29f857971dSopenharmony_ci
30f857971dSopenharmony_ci#include "devicestatus_common.h"
31f857971dSopenharmony_ci#include "devicestatus_define.h"
32f857971dSopenharmony_ci#include "include/util.h"
33f857971dSopenharmony_ci
34f857971dSopenharmony_ci#undef LOG_TAG
35f857971dSopenharmony_ci#define LOG_TAG "DeviceStatusDumper"
36f857971dSopenharmony_ci
37f857971dSopenharmony_cinamespace OHOS {
38f857971dSopenharmony_cinamespace Msdp {
39f857971dSopenharmony_cinamespace DeviceStatus {
40f857971dSopenharmony_cinamespace {
41f857971dSopenharmony_ciconstexpr size_t MAX_DEVICE_STATUS_SIZE { 10 };
42f857971dSopenharmony_ci} // namespace
43f857971dSopenharmony_ci
44f857971dSopenharmony_ciDeviceStatusDumper::DeviceStatusDumper() {}
45f857971dSopenharmony_ciDeviceStatusDumper::~DeviceStatusDumper() {}
46f857971dSopenharmony_ci
47f857971dSopenharmony_ciint32_t DeviceStatusDumper::Init(IContext *context)
48f857971dSopenharmony_ci{
49f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
50f857971dSopenharmony_ci    CHKPR(context, RET_ERR);
51f857971dSopenharmony_ci    context_ = context;
52f857971dSopenharmony_ci    return RET_OK;
53f857971dSopenharmony_ci}
54f857971dSopenharmony_ci
55f857971dSopenharmony_civoid DeviceStatusDumper::ParseCommand(int32_t fd, const std::vector<std::string> &args, const std::vector<Data> &datas)
56f857971dSopenharmony_ci{
57f857971dSopenharmony_ci    constexpr size_t BUFSIZE { 1024 };
58f857971dSopenharmony_ci    char buf[BUFSIZE] { "hidumper" };
59f857971dSopenharmony_ci
60f857971dSopenharmony_ci    std::vector<char *> argv(args.size() + 1);
61f857971dSopenharmony_ci    argv[0] = buf;
62f857971dSopenharmony_ci
63f857971dSopenharmony_ci    size_t len = std::strlen(buf) + 1;
64f857971dSopenharmony_ci    char *pbuf = buf + len;
65f857971dSopenharmony_ci    size_t bufLen = sizeof(buf) - len;
66f857971dSopenharmony_ci
67f857971dSopenharmony_ci    for (size_t index = 0, cnt = args.size(); index < cnt; ++index) {
68f857971dSopenharmony_ci        len = args[index].size() + 1;
69f857971dSopenharmony_ci        if (len > bufLen) {
70f857971dSopenharmony_ci            FI_HILOGE("Buffer overflow");
71f857971dSopenharmony_ci            return;
72f857971dSopenharmony_ci        }
73f857971dSopenharmony_ci        args[index].copy(pbuf, args[index].size());
74f857971dSopenharmony_ci        pbuf[args[index].size()] = '\0';
75f857971dSopenharmony_ci
76f857971dSopenharmony_ci        argv[index + 1] = pbuf;
77f857971dSopenharmony_ci        pbuf += len;
78f857971dSopenharmony_ci        bufLen -= len;
79f857971dSopenharmony_ci    }
80f857971dSopenharmony_ci
81f857971dSopenharmony_ci    struct option dumpOptions[] {
82f857971dSopenharmony_ci        { "help", no_argument, nullptr, 'h' },
83f857971dSopenharmony_ci        { "subscribe", no_argument, nullptr, 's' },
84f857971dSopenharmony_ci        { "list", no_argument, nullptr, 'l' },
85f857971dSopenharmony_ci        { "current", no_argument, nullptr, 'c' },
86f857971dSopenharmony_ci        { "coordination", no_argument, nullptr, 'o' },
87f857971dSopenharmony_ci        { "drag", no_argument, nullptr, 'd' },
88f857971dSopenharmony_ci        { "macroState", no_argument, nullptr, 'm' },
89f857971dSopenharmony_ci        { nullptr, 0, nullptr, 0 }
90f857971dSopenharmony_ci    };
91f857971dSopenharmony_ci    optind = 0;
92f857971dSopenharmony_ci
93f857971dSopenharmony_ci    for (;;) {
94f857971dSopenharmony_ci        int32_t opt = getopt_long(argv.size(), argv.data(), "+hslcodm", dumpOptions, nullptr);
95f857971dSopenharmony_ci        if (opt < 0) {
96f857971dSopenharmony_ci            break;
97f857971dSopenharmony_ci        }
98f857971dSopenharmony_ci        ExecutDump(fd, datas, opt);
99f857971dSopenharmony_ci    }
100f857971dSopenharmony_ci}
101f857971dSopenharmony_ci
102f857971dSopenharmony_civoid DeviceStatusDumper::ExecutDump(int32_t fd, const std::vector<Data> &datas, int32_t opt)
103f857971dSopenharmony_ci{
104f857971dSopenharmony_ci    switch (opt) {
105f857971dSopenharmony_ci        case 'h': {
106f857971dSopenharmony_ci            DumpHelpInfo(fd);
107f857971dSopenharmony_ci            break;
108f857971dSopenharmony_ci        }
109f857971dSopenharmony_ci        case 's': {
110f857971dSopenharmony_ci            DumpDeviceStatusSubscriber(fd);
111f857971dSopenharmony_ci            break;
112f857971dSopenharmony_ci        }
113f857971dSopenharmony_ci        case 'l': {
114f857971dSopenharmony_ci            DumpDeviceStatusChanges(fd);
115f857971dSopenharmony_ci            break;
116f857971dSopenharmony_ci        }
117f857971dSopenharmony_ci        case 'c': {
118f857971dSopenharmony_ci            DumpDeviceStatusCurrentStatus(fd, datas);
119f857971dSopenharmony_ci            break;
120f857971dSopenharmony_ci        }
121f857971dSopenharmony_ci        case 'o': {
122f857971dSopenharmony_ci#ifdef OHOS_BUILD_ENABLE_COORDINATION
123f857971dSopenharmony_ci            dprintf(fd, "device coordination is not supported\n");
124f857971dSopenharmony_ci#endif // OHOS_BUILD_ENABLE_COORDINATION
125f857971dSopenharmony_ci            break;
126f857971dSopenharmony_ci        }
127f857971dSopenharmony_ci        case 'd': {
128f857971dSopenharmony_ci            CHKPV(context_);
129f857971dSopenharmony_ci            context_->GetDragManager().Dump(fd);
130f857971dSopenharmony_ci            break;
131f857971dSopenharmony_ci        }
132f857971dSopenharmony_ci        case 'm': {
133f857971dSopenharmony_ci            DumpCheckDefine(fd);
134f857971dSopenharmony_ci            break;
135f857971dSopenharmony_ci        }
136f857971dSopenharmony_ci        default: {
137f857971dSopenharmony_ci            dprintf(fd, "cmd param is error\n");
138f857971dSopenharmony_ci            DumpHelpInfo(fd);
139f857971dSopenharmony_ci            break;
140f857971dSopenharmony_ci        }
141f857971dSopenharmony_ci    }
142f857971dSopenharmony_ci}
143f857971dSopenharmony_ci
144f857971dSopenharmony_civoid DeviceStatusDumper::DumpDeviceStatusSubscriber(int32_t fd)
145f857971dSopenharmony_ci{
146f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
147f857971dSopenharmony_ci    std::unique_lock lock(mutex_);
148f857971dSopenharmony_ci    if (appInfos_.empty()) {
149f857971dSopenharmony_ci        FI_HILOGE("appInfos_ is empty");
150f857971dSopenharmony_ci        return;
151f857971dSopenharmony_ci    }
152f857971dSopenharmony_ci    std::string startTime;
153f857971dSopenharmony_ci    GetTimeStamp(startTime);
154f857971dSopenharmony_ci    dprintf(fd, "Current time:%s \n", startTime.c_str());
155f857971dSopenharmony_ci    for (const auto &item : appInfos_) {
156f857971dSopenharmony_ci        for (const auto &appInfo : item.second) {
157f857971dSopenharmony_ci            dprintf(fd, "startTime:%s | uid:%d | pid:%d | type:%s | packageName:%s\n",
158f857971dSopenharmony_ci                appInfo->startTime.c_str(), appInfo->uid, appInfo->pid, GetStatusType(appInfo->type).c_str(),
159f857971dSopenharmony_ci                appInfo->packageName.c_str());
160f857971dSopenharmony_ci        }
161f857971dSopenharmony_ci    }
162f857971dSopenharmony_ci}
163f857971dSopenharmony_ci
164f857971dSopenharmony_civoid DeviceStatusDumper::DumpDeviceStatusChanges(int32_t fd)
165f857971dSopenharmony_ci{
166f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
167f857971dSopenharmony_ci    std::unique_lock lock(mutex_);
168f857971dSopenharmony_ci    if (deviceStatusQueue_.empty()) {
169f857971dSopenharmony_ci        FI_HILOGI("deviceStatusQueue_ is empty");
170f857971dSopenharmony_ci        return;
171f857971dSopenharmony_ci    }
172f857971dSopenharmony_ci    std::string startTime;
173f857971dSopenharmony_ci    GetTimeStamp(startTime);
174f857971dSopenharmony_ci    dprintf(fd, "Current time:%s\n", startTime.c_str());
175f857971dSopenharmony_ci    size_t length = deviceStatusQueue_.size() > MAX_DEVICE_STATUS_SIZE ?
176f857971dSopenharmony_ci        MAX_DEVICE_STATUS_SIZE : deviceStatusQueue_.size();
177f857971dSopenharmony_ci    for (size_t i = 0; i < length; ++i) {
178f857971dSopenharmony_ci        auto record = deviceStatusQueue_.front();
179f857971dSopenharmony_ci        CHKPC(record);
180f857971dSopenharmony_ci        deviceStatusQueue_.push(record);
181f857971dSopenharmony_ci        deviceStatusQueue_.pop();
182f857971dSopenharmony_ci        dprintf(fd, "startTime:%s | type:%s | value:%s\n",
183f857971dSopenharmony_ci            record->startTime.c_str(), GetStatusType(record->data.type).c_str(),
184f857971dSopenharmony_ci            GetDeviceState(record->data.value).c_str());
185f857971dSopenharmony_ci    }
186f857971dSopenharmony_ci}
187f857971dSopenharmony_ci
188f857971dSopenharmony_civoid DeviceStatusDumper::DumpDeviceStatusCurrentStatus(int32_t fd, const std::vector<Data> &datas) const
189f857971dSopenharmony_ci{
190f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
191f857971dSopenharmony_ci    std::string startTime;
192f857971dSopenharmony_ci    GetTimeStamp(startTime);
193f857971dSopenharmony_ci    dprintf(fd, "Current time:%s\n", startTime.c_str());
194f857971dSopenharmony_ci    dprintf(fd, "Current device status:\n");
195f857971dSopenharmony_ci    if (datas.empty()) {
196f857971dSopenharmony_ci        dprintf(fd, "No device status available\n");
197f857971dSopenharmony_ci        return;
198f857971dSopenharmony_ci    }
199f857971dSopenharmony_ci    for (auto it = datas.begin(); it != datas.end(); ++it) {
200f857971dSopenharmony_ci        if (it->value == VALUE_INVALID) {
201f857971dSopenharmony_ci            continue;
202f857971dSopenharmony_ci        }
203f857971dSopenharmony_ci        dprintf(fd, "type:%s | state:%s\n",
204f857971dSopenharmony_ci            GetStatusType(it->type).c_str(), GetDeviceState(it->value).c_str());
205f857971dSopenharmony_ci    }
206f857971dSopenharmony_ci}
207f857971dSopenharmony_ci
208f857971dSopenharmony_cistd::string DeviceStatusDumper::GetDeviceState(OnChangedValue value) const
209f857971dSopenharmony_ci{
210f857971dSopenharmony_ci    std::string state;
211f857971dSopenharmony_ci    switch (value) {
212f857971dSopenharmony_ci        case VALUE_ENTER: {
213f857971dSopenharmony_ci            state = "enter";
214f857971dSopenharmony_ci            break;
215f857971dSopenharmony_ci        }
216f857971dSopenharmony_ci        case VALUE_EXIT: {
217f857971dSopenharmony_ci            state = "exit";
218f857971dSopenharmony_ci            break;
219f857971dSopenharmony_ci        }
220f857971dSopenharmony_ci        case VALUE_INVALID: {
221f857971dSopenharmony_ci            state = "invalid";
222f857971dSopenharmony_ci            break;
223f857971dSopenharmony_ci        }
224f857971dSopenharmony_ci        default: {
225f857971dSopenharmony_ci            state = "unknown";
226f857971dSopenharmony_ci            break;
227f857971dSopenharmony_ci        }
228f857971dSopenharmony_ci    }
229f857971dSopenharmony_ci    return state;
230f857971dSopenharmony_ci}
231f857971dSopenharmony_ci
232f857971dSopenharmony_cistd::string DeviceStatusDumper::GetStatusType(Type type) const
233f857971dSopenharmony_ci{
234f857971dSopenharmony_ci    std::string stateType;
235f857971dSopenharmony_ci    switch (type) {
236f857971dSopenharmony_ci        case TYPE_ABSOLUTE_STILL: {
237f857971dSopenharmony_ci            stateType = "absolute still";
238f857971dSopenharmony_ci            break;
239f857971dSopenharmony_ci        }
240f857971dSopenharmony_ci        case TYPE_HORIZONTAL_POSITION: {
241f857971dSopenharmony_ci            stateType = "horizontal position";
242f857971dSopenharmony_ci            break;
243f857971dSopenharmony_ci        }
244f857971dSopenharmony_ci        case TYPE_VERTICAL_POSITION: {
245f857971dSopenharmony_ci            stateType = "vertical position";
246f857971dSopenharmony_ci            break;
247f857971dSopenharmony_ci        }
248f857971dSopenharmony_ci        case TYPE_LID_OPEN: {
249f857971dSopenharmony_ci            stateType = "lid open";
250f857971dSopenharmony_ci            break;
251f857971dSopenharmony_ci        }
252f857971dSopenharmony_ci        default: {
253f857971dSopenharmony_ci            stateType = "unknown";
254f857971dSopenharmony_ci            break;
255f857971dSopenharmony_ci        }
256f857971dSopenharmony_ci    }
257f857971dSopenharmony_ci    return stateType;
258f857971dSopenharmony_ci}
259f857971dSopenharmony_ci
260f857971dSopenharmony_civoid DeviceStatusDumper::DumpHelpInfo(int32_t fd) const
261f857971dSopenharmony_ci{
262f857971dSopenharmony_ci    dprintf(fd, "Usage:\n");
263f857971dSopenharmony_ci    dprintf(fd, "      -h: dump help\n");
264f857971dSopenharmony_ci    dprintf(fd, "      -s: dump the subscribers\n");
265f857971dSopenharmony_ci    dprintf(fd, "      -l: dump the last 10 device status change\n");
266f857971dSopenharmony_ci    dprintf(fd, "      -c: dump the current device status\n");
267f857971dSopenharmony_ci    dprintf(fd, "      -o: dump the coordination status\n");
268f857971dSopenharmony_ci    dprintf(fd, "      -d: dump the drag status\n");
269f857971dSopenharmony_ci    dprintf(fd, "      -m, dump the macro state\n");
270f857971dSopenharmony_ci}
271f857971dSopenharmony_ci
272f857971dSopenharmony_civoid DeviceStatusDumper::SaveAppInfo(std::shared_ptr<AppInfo> appInfo)
273f857971dSopenharmony_ci{
274f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
275f857971dSopenharmony_ci    CHKPV(appInfo);
276f857971dSopenharmony_ci    GetTimeStamp(appInfo->startTime);
277f857971dSopenharmony_ci    std::set<std::shared_ptr<AppInfo>> appInfos;
278f857971dSopenharmony_ci    std::unique_lock lock(mutex_);
279f857971dSopenharmony_ci    auto iter = appInfos_.find(appInfo->type);
280f857971dSopenharmony_ci    if (iter == appInfos_.end()) {
281f857971dSopenharmony_ci        if (appInfos.insert(appInfo).second) {
282f857971dSopenharmony_ci            auto [_, ret] = appInfos_.insert(std::make_pair(appInfo->type, appInfos));
283f857971dSopenharmony_ci            if (!ret) {
284f857971dSopenharmony_ci                FI_HILOGW("type is duplicated");
285f857971dSopenharmony_ci            }
286f857971dSopenharmony_ci        }
287f857971dSopenharmony_ci    } else {
288f857971dSopenharmony_ci        if (!appInfos_[iter->first].insert(appInfo).second) {
289f857971dSopenharmony_ci            FI_HILOGW("appInfo is duplicated");
290f857971dSopenharmony_ci        }
291f857971dSopenharmony_ci    }
292f857971dSopenharmony_ci}
293f857971dSopenharmony_ci
294f857971dSopenharmony_civoid DeviceStatusDumper::RemoveAppInfo(std::shared_ptr<AppInfo> appInfo)
295f857971dSopenharmony_ci{
296f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
297f857971dSopenharmony_ci    CHKPV(appInfo);
298f857971dSopenharmony_ci    CHKPV(appInfo->callback);
299f857971dSopenharmony_ci    std::unique_lock lock(mutex_);
300f857971dSopenharmony_ci    auto appInfoSetIter = appInfos_.find(appInfo->type);
301f857971dSopenharmony_ci    if (appInfoSetIter == appInfos_.end()) {
302f857971dSopenharmony_ci        FI_HILOGE("Not exist %{public}d type appInfo", appInfo->type);
303f857971dSopenharmony_ci        return;
304f857971dSopenharmony_ci    }
305f857971dSopenharmony_ci    FI_HILOGI("callbacklist type:%{public}d, size:%{public}zu, appInfoMap size:%{public}zu",
306f857971dSopenharmony_ci        appInfo->type, appInfos_[appInfoSetIter->first].size(), appInfos_.size());
307f857971dSopenharmony_ci    auto iter = appInfos_.find(appInfo->type);
308f857971dSopenharmony_ci    if (iter == appInfos_.end()) {
309f857971dSopenharmony_ci        FI_HILOGW("Remove app info is not exists");
310f857971dSopenharmony_ci        return;
311f857971dSopenharmony_ci    }
312f857971dSopenharmony_ci    for (const auto &item : iter->second) {
313f857971dSopenharmony_ci        if (item->pid == appInfo->pid) {
314f857971dSopenharmony_ci            iter->second.erase(item);
315f857971dSopenharmony_ci            break;
316f857971dSopenharmony_ci        }
317f857971dSopenharmony_ci    }
318f857971dSopenharmony_ci}
319f857971dSopenharmony_ci
320f857971dSopenharmony_civoid DeviceStatusDumper::PushDeviceStatus(const Data &data)
321f857971dSopenharmony_ci{
322f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
323f857971dSopenharmony_ci    std::unique_lock lock(mutex_);
324f857971dSopenharmony_ci    auto record = std::make_shared<DeviceStatusRecord>();
325f857971dSopenharmony_ci    GetTimeStamp(record->startTime);
326f857971dSopenharmony_ci    record->data = data;
327f857971dSopenharmony_ci    deviceStatusQueue_.push(record);
328f857971dSopenharmony_ci    if (deviceStatusQueue_.size() > MAX_DEVICE_STATUS_SIZE) {
329f857971dSopenharmony_ci        deviceStatusQueue_.pop();
330f857971dSopenharmony_ci    }
331f857971dSopenharmony_ci}
332f857971dSopenharmony_ci
333f857971dSopenharmony_cistd::string DeviceStatusDumper::GetPackageName(Security::AccessToken::AccessTokenID tokenId)
334f857971dSopenharmony_ci{
335f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
336f857971dSopenharmony_ci    std::string packageName = "unknown";
337f857971dSopenharmony_ci    int32_t tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
338f857971dSopenharmony_ci    switch (tokenType) {
339f857971dSopenharmony_ci        case Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE: {
340f857971dSopenharmony_ci            Security::AccessToken::NativeTokenInfo tokenInfo;
341f857971dSopenharmony_ci            if (Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) != 0) {
342f857971dSopenharmony_ci                FI_HILOGE("Get native token info fail");
343f857971dSopenharmony_ci                return packageName;
344f857971dSopenharmony_ci            }
345f857971dSopenharmony_ci            packageName = tokenInfo.processName;
346f857971dSopenharmony_ci            break;
347f857971dSopenharmony_ci        }
348f857971dSopenharmony_ci        case Security::AccessToken::ATokenTypeEnum::TOKEN_HAP: {
349f857971dSopenharmony_ci            Security::AccessToken::HapTokenInfo hapInfo;
350f857971dSopenharmony_ci            if (Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != RET_OK) {
351f857971dSopenharmony_ci                FI_HILOGE("Get hap token info fail");
352f857971dSopenharmony_ci                return packageName;
353f857971dSopenharmony_ci            }
354f857971dSopenharmony_ci            packageName = hapInfo.bundleName;
355f857971dSopenharmony_ci            break;
356f857971dSopenharmony_ci        }
357f857971dSopenharmony_ci        default: {
358f857971dSopenharmony_ci            FI_HILOGW("token type not match");
359f857971dSopenharmony_ci            break;
360f857971dSopenharmony_ci        }
361f857971dSopenharmony_ci    }
362f857971dSopenharmony_ci    return packageName;
363f857971dSopenharmony_ci}
364f857971dSopenharmony_ci
365f857971dSopenharmony_civoid DeviceStatusDumper::DumpCheckDefine(int32_t fd)
366f857971dSopenharmony_ci{
367f857971dSopenharmony_ci    ChkDefineOutput(fd);
368f857971dSopenharmony_ci}
369f857971dSopenharmony_ci
370f857971dSopenharmony_civoid DeviceStatusDumper::ChkDefineOutput(int32_t fd)
371f857971dSopenharmony_ci{
372f857971dSopenharmony_ci    CheckDefineOutput(fd, "Macro switch state:\n");
373f857971dSopenharmony_ci#ifdef OHOS_BUILD_ENABLE_COORDINATION
374f857971dSopenharmony_ci    CheckDefineOutput(fd, "%-40s", "OHOS_BUILD_ENABLE_COORDINATION");
375f857971dSopenharmony_ci#endif // OHOS_BUILD_ENABLE_COORDINATION
376f857971dSopenharmony_ci}
377f857971dSopenharmony_ci
378f857971dSopenharmony_citemplate<class ...Ts>
379f857971dSopenharmony_civoid DeviceStatusDumper::CheckDefineOutput(int32_t fd, const char* fmt, Ts... args)
380f857971dSopenharmony_ci{
381f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
382f857971dSopenharmony_ci    CHKPV(fmt);
383f857971dSopenharmony_ci    char buf[MAX_PACKET_BUF_SIZE] = { 0 };
384f857971dSopenharmony_ci    int32_t ret = snprintf_s(buf, MAX_PACKET_BUF_SIZE, MAX_PACKET_BUF_SIZE - 1, fmt, args...);
385f857971dSopenharmony_ci    if (ret == -1) {
386f857971dSopenharmony_ci        FI_HILOGE("Call snprintf_s failed, ret:%{public}d", ret);
387f857971dSopenharmony_ci        return;
388f857971dSopenharmony_ci    }
389f857971dSopenharmony_ci    dprintf(fd, "%s", buf);
390f857971dSopenharmony_ci}
391f857971dSopenharmony_ci} // namespace DeviceStatus
392f857971dSopenharmony_ci} // namespace Msdp
393f857971dSopenharmony_ci} // namespace OHOS
394