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