1 /*
2 * Copyright (c) 2024 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 "intention_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 "IntentionDumper"
25
26 namespace OHOS {
27 namespace Msdp {
28 namespace DeviceStatus {
Dump(int32_t fd, const std::vector<std::string> &args)29 void IntentionDumper::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 len = args[index].size() + 1;
43 if (len > bufLen) {
44 FI_HILOGE("Buffer overflow");
45 return;
46 }
47 args[index].copy(pbuf, args[index].size());
48 pbuf[args[index].size()] = '\0';
49
50 argv[index + 1] = pbuf;
51 pbuf += len;
52 bufLen -= len;
53 }
54
55 struct option dumpOptions[] {
56 { "help", no_argument, nullptr, 'h' },
57 { "subscribe", no_argument, nullptr, 's' },
58 { "list", no_argument, nullptr, 'l' },
59 { "current", no_argument, nullptr, 'c' },
60 { "drag", no_argument, nullptr, 'd' },
61 { "macroState", no_argument, nullptr, 'm' },
62 { nullptr, 0, nullptr, 0 }
63 };
64 optind = 0;
65 int32_t opt = -1;
66
67 while ((opt = getopt_long(argv.size(), argv.data(), "+hslcodm", dumpOptions, nullptr)) >= 0) {
68 DumpOnce(fd, opt);
69 }
70 }
71
DumpOnce(int32_t fd, int32_t option)72 void IntentionDumper::DumpOnce(int32_t fd, int32_t option)
73 {
74 switch (option) {
75 case 's': {
76 DumpDeviceStatusSubscriber(fd);
77 break;
78 }
79 case 'l': {
80 DumpDeviceStatusChanges(fd);
81 break;
82 }
83 case 'c': {
84 DumpCurrentDeviceStatus(fd);
85 break;
86 }
87 case 'd': {
88 DumpDrag(fd);
89 break;
90 }
91 case 'm': {
92 DumpCheckDefine(fd);
93 break;
94 }
95 default: {
96 DumpHelpInfo(fd);
97 break;
98 }
99 }
100 }
101
DumpHelpInfo(int32_t fd) const102 void IntentionDumper::DumpHelpInfo(int32_t fd) const
103 {
104 dprintf(fd, "Usage:\n");
105 dprintf(fd, "\t-h\t\tdump help\n");
106 dprintf(fd, "\t-s\t\tdump the subscribers\n");
107 dprintf(fd, "\t-l\t\tdump the last 10 device status change\n");
108 dprintf(fd, "\t-c\t\tdump the current device status\n");
109 dprintf(fd, "\t-d\t\tdump the drag status\n");
110 dprintf(fd, "\t-m\t\tdump the macro state\n");
111 }
112
DumpDeviceStatusSubscriber(int32_t fd) const113 void IntentionDumper::DumpDeviceStatusSubscriber(int32_t fd) const
114 {
115 CHKPV(env_);
116 FI_HILOGI("Dump subscribers of device status");
117 int32_t ret = env_->GetDelegateTasks().PostSyncTask([this, fd] {
118 stationary_.DumpDeviceStatusSubscriber(fd);
119 return RET_OK;
120 });
121 if (ret != RET_OK) {
122 FI_HILOGE("IDelegateTasks::PostSyncTask fail, error:%{public}d", ret);
123 }
124 }
125
DumpDeviceStatusChanges(int32_t fd) const126 void IntentionDumper::DumpDeviceStatusChanges(int32_t fd) const
127 {
128 CHKPV(env_);
129 FI_HILOGI("Dump changes of device status");
130 int32_t ret = env_->GetDelegateTasks().PostSyncTask([this, fd] {
131 stationary_.DumpDeviceStatusChanges(fd);
132 return RET_OK;
133 });
134 if (ret != RET_OK) {
135 FI_HILOGE("IDelegateTasks::PostSyncTask fail, error:%{public}d", ret);
136 }
137 }
138
DumpCurrentDeviceStatus(int32_t fd)139 void IntentionDumper::DumpCurrentDeviceStatus(int32_t fd)
140 {
141 CHKPV(env_);
142 FI_HILOGI("Dump current device status");
143 int32_t ret = env_->GetDelegateTasks().PostSyncTask([this, fd] {
144 stationary_.DumpDeviceStatusChanges(fd);
145 return RET_OK;
146 });
147 if (ret != RET_OK) {
148 FI_HILOGE("IDelegateTasks::PostSyncTask fail, error:%{public}d", ret);
149 }
150 }
151
DumpDrag(int32_t fd) const152 void IntentionDumper::DumpDrag(int32_t fd) const
153 {
154 CHKPV(env_);
155 FI_HILOGI("Dump drag information");
156 int32_t ret = env_->GetDelegateTasks().PostSyncTask([env = env_, fd] {
157 env->GetDragManager().Dump(fd);
158 return RET_OK;
159 });
160 if (ret != RET_OK) {
161 FI_HILOGE("IDelegateTasks::PostSyncTask fail, error:%{public}d", ret);
162 }
163 }
164
DumpCheckDefine(int32_t fd) const165 void IntentionDumper::DumpCheckDefine(int32_t fd) const
166 {
167 CheckDefineOutput(fd, "Macro switch state:\n");
168 #ifdef OHOS_BUILD_ENABLE_COORDINATION
169 CheckDefineOutput(fd, "\t%s\n", "OHOS_BUILD_ENABLE_COORDINATION");
170 #endif // OHOS_BUILD_ENABLE_COORDINATION
171 }
172
173 template<class ...Ts>
CheckDefineOutput(int32_t fd, const char* fmt, Ts... args) const174 void IntentionDumper::CheckDefineOutput(int32_t fd, const char* fmt, Ts... args) const
175 {
176 char buf[MAX_PACKET_BUF_SIZE] {};
177 int32_t ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, args...);
178 if (ret < 0) {
179 FI_HILOGE("snprintf_s fail, error:%{public}d", ret);
180 return;
181 }
182 dprintf(fd, "%s", buf);
183 }
184 } // namespace DeviceStatus
185 } // namespace Msdp
186 } // namespace OHOS
187