1 /*
2  * Copyright (c) 2023 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 "dscreen_hidumper.h"
17 
18 #include "dscreen_errcode.h"
19 #include "dscreen_log.h"
20 #include "dscreen_util.h"
21 
22 namespace OHOS {
23 namespace DistributedHardware {
24 IMPLEMENT_SINGLE_INSTANCE(DscreenHidumper);
25 
26 namespace {
27 const std::string ARGS_HELP = "-h";
28 const std::string ARGS_DUMP_SCREEN_DATA = "--dump";
29 const std::string ARGS_DUMP_SCREEN_DATA_RESTART = "--redump";
30 const std::string ARGS_DUMP_SCREEN_DATA_STOP = "--stopdump";
31 
32 const std::map<std::string, HidumpFlag> ARGS_MAP = {
33     { ARGS_HELP, HidumpFlag::GET_HELP },
34     { ARGS_DUMP_SCREEN_DATA, HidumpFlag::DUMP_SCREEN_DATA },
35     { ARGS_DUMP_SCREEN_DATA_RESTART, HidumpFlag::DUMP_SCREEN_DATA_RESTART },
36     { ARGS_DUMP_SCREEN_DATA_STOP, HidumpFlag::DUMP_SCREEN_DATA_STOP },
37 };
38 }
39 
DscreenHidumper()40 DscreenHidumper::DscreenHidumper()
41 {
42     DHLOGI("Distributed screen hidumper constructed.");
43 }
44 
~DscreenHidumper()45 DscreenHidumper::~DscreenHidumper()
46 {
47     DHLOGI("Distributed screen hidumper deconstructed.");
48 }
49 
Dump(const std::vector<std::string> & args,std::string & result)50 bool DscreenHidumper::Dump(const std::vector<std::string> &args, std::string &result)
51 {
52     DHLOGI("Distributed screen hidumper dump args.size():%{public}zu.", args.size());
53     result.clear();
54     int32_t argsSize = static_cast<int32_t>(args.size());
55     for (int32_t i = 0; i < argsSize; i++) {
56         DHLOGI("Distributed screen hidumper dump args[%{public}d]: %{public}s.", i, args.at(i).c_str());
57     }
58 
59     if (args.empty()) {
60         ShowHelp(result);
61         return true;
62     }
63 
64     if (args.size() > 1) {
65         ShowIllegalInfomation(result);
66         return true;
67     }
68 
69     return ProcessDump(args[0], result) == DH_SUCCESS;
70 }
71 
ProcessDump(const std::string & args,std::string & result)72 int32_t DscreenHidumper::ProcessDump(const std::string &args, std::string &result)
73 {
74     DHLOGI("Process dump.");
75     HidumpFlag hidumpFlag = HidumpFlag::UNKNOWN;
76     auto operatorIter = ARGS_MAP.find(args);
77     if (operatorIter != ARGS_MAP.end()) {
78         hidumpFlag = operatorIter->second;
79     }
80 
81     if (hidumpFlag == HidumpFlag::GET_HELP) {
82         ShowHelp(result);
83         return DH_SUCCESS;
84     }
85     result.clear();
86     switch (hidumpFlag) {
87         case HidumpFlag::DUMP_SCREEN_DATA: {
88             return DumpScreenData(result);
89         }
90         case HidumpFlag::DUMP_SCREEN_DATA_RESTART: {
91             return ReDumpScreenData(result);
92         }
93         case HidumpFlag::DUMP_SCREEN_DATA_STOP: {
94             SetFlagFalse();
95             return DH_SUCCESS;
96         }
97         default: {
98             return ShowIllegalInfomation(result);
99         }
100     }
101 }
102 
DumpScreenData(std::string & result)103 int32_t DscreenHidumper::DumpScreenData(std::string &result)
104 {
105     DHLOGI("Dump screen data.");
106 
107     if (access(DUMP_FILE_PATH.c_str(), 0) < 0) {
108         if (mkdir(DUMP_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
109             DHLOGI("Create dir err.");
110             DHLOGI("dir path : %{public}s", DUMP_FILE_PATH.c_str());
111             return DSCREEN_BAD_VALUE;
112         }
113     }
114 
115     if (fileFullFlag_ == false) {
116         result.append("Dump...");
117         hidumperFlag_ = true;
118     } else {
119         result.append("File oversize 300M : stop dump, use parameter \"--redump\" to clear dumpfile and redump");
120     }
121     return DH_SUCCESS;
122 }
123 
ReDumpScreenData(std::string & result)124 int32_t DscreenHidumper::ReDumpScreenData(std::string &result)
125 {
126     DHLOGI("Redump screen data.");
127 
128     if (access(DUMP_FILE_PATH.c_str(), 0) < 0) {
129         if (mkdir(DUMP_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
130             DHLOGI("Create dir err.");
131             DHLOGI("dir path : %{public}s", DUMP_FILE_PATH.c_str());
132             return DSCREEN_BAD_VALUE;
133         }
134     }
135     SetFileFlagFalse();
136     SetReDumpFlagTrue();
137     result.append("ReDumpStart...");
138     hidumperFlag_ = true;
139     SetTransReDumpFlagTrue();
140     return DH_SUCCESS;
141 }
142 
GetFlagStatus()143 bool DscreenHidumper::GetFlagStatus()
144 {
145     return hidumperFlag_;
146 }
147 
SetFlagFalse()148 void DscreenHidumper::SetFlagFalse()
149 {
150     hidumperFlag_ = false;
151 }
152 
GetFileFlag()153 bool DscreenHidumper::GetFileFlag()
154 {
155     return fileFullFlag_;
156 }
157 
SetFileFlagFalse()158 void DscreenHidumper::SetFileFlagFalse()
159 {
160     fileFullFlag_ = false;
161 }
162 
SetFileFlagTrue()163 void DscreenHidumper::SetFileFlagTrue()
164 {
165     fileFullFlag_ = true;
166 }
167 
GetReDumpFlag()168 bool DscreenHidumper::GetReDumpFlag()
169 {
170     return reDumpFlag_;
171 }
172 
SetReDumpFlagFalse()173 void DscreenHidumper::SetReDumpFlagFalse()
174 {
175     reDumpFlag_ = false;
176 }
177 
SetReDumpFlagTrue()178 void DscreenHidumper::SetReDumpFlagTrue()
179 {
180     reDumpFlag_ = true;
181 }
182 
GetTransReDumpFlag()183 bool DscreenHidumper::GetTransReDumpFlag()
184 {
185     return transReDumpFlag_;
186 }
187 
SetTransReDumpFlagFalse()188 void DscreenHidumper::SetTransReDumpFlagFalse()
189 {
190     transReDumpFlag_ = false;
191 }
192 
SetTransReDumpFlagTrue()193 void DscreenHidumper::SetTransReDumpFlagTrue()
194 {
195     transReDumpFlag_ = true;
196 }
197 
ShowHelp(std::string & result)198 void DscreenHidumper::ShowHelp(std::string &result)
199 {
200     DHLOGI("Show help.");
201     result.append("Usage:dump  <command> [options]\n")
202         .append("Description:\n")
203         .append("-h            ")
204         .append(": show help\n")
205         .append("--dump        ")
206         .append(": dump screen data in /data/data/dscreen\n")
207         .append("--redump      ")
208         .append(": clear file and restart dump screen data\n")
209         .append("--stopdump    ")
210         .append(": stop dump screen data\n");
211 }
212 
ShowIllegalInfomation(std::string & result)213 int32_t DscreenHidumper::ShowIllegalInfomation(std::string &result)
214 {
215     DHLOGI("Show illegal information.");
216     result.append("unknown command, -h for help.");
217     return DH_SUCCESS;
218 }
219 
SaveFile(std::string file,const VideoData & video)220 void DscreenHidumper::SaveFile(std::string file, const VideoData &video)
221 {
222     DHLOGE("Saving File.");
223     std::string fileName = DUMP_FILE_PATH + "/" + file + std::to_string(video.width) + ")_height(" +
224          std::to_string(video.height) + ")_" + video.format + ".jpg";
225     DHLOGE("fileName = %{public}s", fileName.c_str());
226     if (GetReDumpFlag() == true) {
227         std::remove(fileName.c_str());
228         SetReDumpFlagFalse();
229     }
230     std::ofstream ofs(fileName, std::ios::binary | std::ios::out | std::ios::app);
231 
232     if (!ofs.is_open()) {
233         DHLOGE("open file failed.");
234         return;
235     }
236     DHLOGE("open Hidumper SaveFile file success.");
237     ofs.seekp(0, std::ios::end);
238     std::ofstream::pos_type fileSize = ofs.tellp();
239     if (fileSize < 0) {
240         DHLOGE("filesize get err");
241         fileSize = 0;
242     }
243     if ((static_cast<size_t>(fileSize) + video.size) < DUMP_FILE_MAX_SIZE) {
244         SetFileFlagFalse();
245         ofs.write(reinterpret_cast<const char *>(video.data), video.size);
246     } else {
247         SetFileFlagTrue();
248     }
249     ofs.close();
250 }
251 } // namespace DistributedHardware
252 } // namespace OHOS