1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "boomerang_dumper.h"
17
18 #include <getopt.h>
19 #include <securec.h>
20
21 #include "devicestatus_define.h"
22
23 #undef LOG_TAG
24 #define LOG_TAG "BoomerangDumper"
25
26 namespace OHOS {
27 namespace Msdp {
28 namespace DeviceStatus {
Dump(int32_t fd,const std::vector<std::string> & args)29 void BoomerangDumper::Dump(int32_t fd, const std::vector<std::string> &args)
30 {
31 constexpr size_t bufSize { 1024 };
32 char buf[bufSize] { "hidumper" };
33
34 std::vector<char *> argv(args.size() + 1);
35 argv[0] = buf;
36
37 size_t len = std::strlen(buf) + 1;
38 char *pbuf = buf + len;
39 size_t bufLen = sizeof(buf) - len;
40
41 for (size_t index = 0, cnt = args.size(); index < cnt; ++index) {
42 size_t argLen = args[index].size();
43 if (argLen + 1 > bufLen) {
44 FI_HILOGE("Buffer overflow");
45 return;
46 }
47 if (argLen > 0) {
48 args[index].copy(pbuf, argLen);
49 pbuf[argLen] = '\0';
50 } else {
51 pbuf[0] = '\0';
52 }
53
54 argv[index + 1] = pbuf;
55 pbuf += argLen + 1;
56 bufLen -= argLen + 1;
57 }
58
59 struct option dumpOptions[] {
60 { "help", no_argument, nullptr, 'h' },
61 { "subscribe", no_argument, nullptr, 's' },
62 { "list", no_argument, nullptr, 'l' },
63 { "current", no_argument, nullptr, 'c' },
64 { "drag", no_argument, nullptr, 'd' },
65 { "macroState", no_argument, nullptr, 'm' },
66 { nullptr, 0, nullptr, 0 }
67 };
68 optind = 0;
69 int32_t opt = -1;
70
71 while ((opt = getopt_long(argv.size(), argv.data(), "+hslcodm", dumpOptions, nullptr)) >= 0) {
72 DumpOnce(fd, opt);
73 }
74 }
75
DumpOnce(int32_t fd,int32_t option)76 void BoomerangDumper::DumpOnce(int32_t fd, int32_t option)
77 {
78 switch (option) {
79 case 's': {
80 DumpDeviceStatusSubscriber(fd);
81 break;
82 }
83 case 'l': {
84 DumpDeviceStatusChanges(fd);
85 break;
86 }
87 case 'c': {
88 DumpCurrentDeviceStatus(fd);
89 break;
90 }
91 case 'd': {
92 DumpDrag(fd);
93 break;
94 }
95 case 'm': {
96 DumpCheckDefine(fd);
97 break;
98 }
99 default: {
100 DumpHelpInfo(fd);
101 break;
102 }
103 }
104 }
105
DumpHelpInfo(int32_t fd) const106 void BoomerangDumper::DumpHelpInfo(int32_t fd) const
107 {
108 dprintf(fd, "Usage:\n");
109 dprintf(fd, "\t-h\t\tdump help\n");
110 dprintf(fd, "\t-s\t\tdump the subscribers\n");
111 dprintf(fd, "\t-l\t\tdump the last 10 device status change\n");
112 dprintf(fd, "\t-c\t\tdump the current device status\n");
113 dprintf(fd, "\t-d\t\tdump the drag status\n");
114 dprintf(fd, "\t-m\t\tdump the macro state\n");
115 }
116
DumpDeviceStatusSubscriber(int32_t fd) const117 void BoomerangDumper::DumpDeviceStatusSubscriber(int32_t fd) const
118 {
119 CHKPV(env_);
120 FI_HILOGI("Dump subscribers of device status");
121 int32_t ret = env_->GetDelegateTasks().PostSyncTask([this, fd] {
122 boomerang_.DumpDeviceStatusSubscriber(fd);
123 return RET_OK;
124 });
125 if (ret != RET_OK) {
126 FI_HILOGE("IDelegateTasks::PostSyncTask fail, error:%{public}d", ret);
127 }
128 }
129
DumpDeviceStatusChanges(int32_t fd) const130 void BoomerangDumper::DumpDeviceStatusChanges(int32_t fd) const
131 {
132 CHKPV(env_);
133 FI_HILOGI("Dump changes of device status");
134 int32_t ret = env_->GetDelegateTasks().PostSyncTask([this, fd] {
135 boomerang_.DumpDeviceStatusChanges(fd);
136 return RET_OK;
137 });
138 if (ret != RET_OK) {
139 FI_HILOGE("IDelegateTasks::PostSyncTask fail, error:%{public}d", ret);
140 }
141 }
142
DumpCurrentDeviceStatus(int32_t fd)143 void BoomerangDumper::DumpCurrentDeviceStatus(int32_t fd)
144 {
145 CHKPV(env_);
146 FI_HILOGI("Dump current device status");
147 int32_t ret = env_->GetDelegateTasks().PostSyncTask([this, fd] {
148 boomerang_.DumpDeviceStatusChanges(fd);
149 return RET_OK;
150 });
151 if (ret != RET_OK) {
152 FI_HILOGE("IDelegateTasks::PostSyncTask fail, error:%{public}d", ret);
153 }
154 }
155
DumpDrag(int32_t fd) const156 void BoomerangDumper::DumpDrag(int32_t fd) const
157 {
158 CHKPV(env_);
159 FI_HILOGI("Dump drag information");
160 int32_t ret = env_->GetDelegateTasks().PostSyncTask([env = env_, fd] {
161 env->GetDragManager().Dump(fd);
162 return RET_OK;
163 });
164 if (ret != RET_OK) {
165 FI_HILOGE("IDelegateTasks::PostSyncTask fail, error:%{public}d", ret);
166 }
167 }
168
DumpCheckDefine(int32_t fd) const169 void BoomerangDumper::DumpCheckDefine(int32_t fd) const
170 {
171 CheckDefineOutput(fd, "Macro switch state:\n");
172 #ifdef OHOS_BUILD_ENABLE_COORDINATION
173 CheckDefineOutput(fd, "\t%s\n", "OHOS_BUILD_ENABLE_COORDINATION");
174 #endif // OHOS_BUILD_ENABLE_COORDINATION
175 }
176
177 template<class ...Ts>
CheckDefineOutput(int32_t fd,const char * fmt,Ts...args) const178 void BoomerangDumper::CheckDefineOutput(int32_t fd, const char* fmt, Ts... args) const
179 {
180 char buf[MAX_PACKET_BUF_SIZE] {};
181 int32_t ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, args...);
182 if (ret < 0) {
183 FI_HILOGE("snprintf_s fail, error:%{public}d", ret);
184 return;
185 }
186 dprintf(fd, "%s", buf);
187 }
188 } // namespace DeviceStatus
189 } // namespace Msdp
190 } // namespace OHOS