1 /*
2 * Copyright (c) 2022 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 "wukong_util.h"
17
18 #include <climits>
19 #include <dirent.h>
20 #include <fstream>
21 #include <iostream>
22 #include <memory.h>
23 #include <sstream>
24 #include <sys/stat.h>
25
26 #include "display_manager.h"
27 #include "if_system_ability_manager.h"
28 #include "iservice_registry.h"
29 #include "launcher_service.h"
30 #include "png.h"
31 #include "string_ex.h"
32 #include "system_ability_definition.h"
33 #include "wukong_define.h"
34 #include "bundle_mgr_proxy.h"
35 #include "common.h"
36 #include "accessibility_ui_test_ability.h"
37 #include "component_manager.h"
38
39 namespace OHOS {
40 namespace WuKong {
41 namespace {
42 const std::string DEFAULT_DIR = "/data/local/tmp/wukong/report/";
TakeWuKongScreenCap(const std::string & wkScreenPath)43 bool TakeWuKongScreenCap(const std::string &wkScreenPath)
44 {
45 // get PixelMap from DisplayManager API
46 Rosen::DisplayManager &displayMgr = Rosen::DisplayManager::GetInstance();
47 std::shared_ptr<Media::PixelMap> pixelMap = displayMgr.GetScreenshot(displayMgr.GetDefaultDisplayId());
48 static constexpr int bitmapDepth = 8;
49 if (pixelMap == nullptr) {
50 DEBUG_LOG("Failed to get display pixelMap");
51 return false;
52 }
53 auto width = static_cast<uint32_t>(pixelMap->GetWidth());
54 auto height = static_cast<uint32_t>(pixelMap->GetHeight());
55 auto data = pixelMap->GetPixels();
56 auto stride = static_cast<uint32_t>(pixelMap->GetRowBytes());
57 png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
58 if (pngStruct == nullptr) {
59 DEBUG_LOG("error: png_create_write_struct nullptr!");
60 return false;
61 }
62 png_infop pngInfo = png_create_info_struct(pngStruct);
63 if (pngInfo == nullptr) {
64 DEBUG_LOG("error: png_create_info_struct error nullptr!");
65 png_destroy_write_struct(&pngStruct, nullptr);
66 return false;
67 }
68 FILE *fp = fopen(wkScreenPath.c_str(), "wb");
69 if (fp == nullptr) {
70 ERROR_LOG("error: open file error!");
71 png_destroy_write_struct(&pngStruct, &pngInfo);
72 return false;
73 }
74 png_init_io(pngStruct, fp);
75 png_set_IHDR(pngStruct, pngInfo, width, height, bitmapDepth, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
76 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
77 png_set_packing(pngStruct); // set packing info
78 png_write_info(pngStruct, pngInfo); // write to header
79 for (uint32_t i = 0; i < height; i++) {
80 png_write_row(pngStruct, data + (i * stride));
81 }
82 png_write_end(pngStruct, pngInfo);
83 // free
84 png_destroy_write_struct(&pngStruct, &pngInfo);
85 (void)fclose(fp);
86 return true;
87 }
88 } // namespace
89 using namespace std;
90 using namespace OHOS::AppExecFwk;
91 const int USE_ID = 100;
WuKongUtil()92 WuKongUtil::WuKongUtil()
93 {
94 TRACK_LOG_STD();
95 const int timeBufsize = 32;
96 char fileNameBuf[timeBufsize] = {0};
97 time_t currentTime = time(0);
98 uint32_t res = 0;
99
100 if (currentTime > 0) {
101 tm *timePtr = localtime(¤tTime);
102 if (timePtr == nullptr) {
103 ERROR_LOG("timePtr is nullptr");
104 return;
105 }
106 res = strftime(fileNameBuf, timeBufsize, "%Y%m%d_%H%M%S", timePtr);
107 }
108 if (res > 0) {
109 startRunTime_ = std::string(fileNameBuf);
110 } else {
111 startRunTime_ = "unvalid_time";
112 }
113 curDir_ = DEFAULT_DIR + startRunTime_ + "/";
114 DEBUG_LOG_STR("common dir{%s}", curDir_.c_str());
115 DIR *rootDir = nullptr;
116 std::string dirStr = "/";
117 std::vector<std::string> strs;
118 OHOS::SplitStr(curDir_, "/", strs);
119 for (auto str : strs) {
120 dirStr.append(str);
121 dirStr.append("/");
122 if ((rootDir = opendir(dirStr.c_str())) == nullptr) {
123 int ret = mkdir(dirStr.c_str(), S_IROTH | S_IRWXU | S_IRWXG);
124 if (ret != 0 && dirStr != "/data/" && dirStr != "/data/local/") {
125 std::cerr << "failed to create dir: " << dirStr << std::endl;
126 break;
127 }
128 } else {
129 closedir(rootDir);
130 }
131 }
132 DEBUG_LOG_STR("%s", startRunTime_.c_str());
133 TRACK_LOG_END();
134 }
135
136 /**
137 * @brief: release util
138 */
~WuKongUtil()139 WuKongUtil::~WuKongUtil()
140 {
141 TRACK_LOG_STD();
142 }
143
GetAllAppInfo()144 ErrCode WuKongUtil::GetAllAppInfo()
145 {
146 AppExecFwk::LauncherService launcherservice;
147 std::vector<AppExecFwk::LauncherAbilityInfo> launcherAbilityInfos(0);
148
149 bool result = launcherservice.GetAllLauncherAbilityInfos(USE_ID, launcherAbilityInfos);
150 DEBUG_LOG_STR("GetAllLauncherAbilityInfos: size (%u), result (%d)", launcherAbilityInfos.size(), result);
151 if (launcherAbilityInfos.size() == 0) {
152 ERROR_LOG("GetAllLauncherAbilityInfos size is 0");
153 return OHOS::ERR_INVALID_VALUE;
154 }
155 for (auto item : launcherAbilityInfos) {
156 iconPath_ = item.applicationInfo.iconPath;
157 DEBUG_LOG_STR("iconPath: %s", item.applicationInfo.iconPath.c_str());
158 DEBUG_LOG_STR("codePath: %s", item.applicationInfo.codePath.c_str());
159 DEBUG_LOG_STR("dataDir: %s", item.applicationInfo.dataDir.c_str());
160 DEBUG_LOG_STR("dataBaseDir: %s", item.applicationInfo.dataBaseDir.c_str());
161 DEBUG_LOG_STR("cacheDir: %s", item.applicationInfo.cacheDir.c_str());
162 DEBUG_LOG_STR("entryDir: %s", item.applicationInfo.entryDir.c_str());
163 std::string bundleName = item.elementName.GetBundleName();
164 // store the list of all bundle names
165 bundleList_.push_back(bundleName);
166 abilityList_.push_back(item.elementName.GetAbilityName());
167 uint32_t isInBlockList = FindElement(blockList_, bundleName);
168 if (isInBlockList != INVALIDVALUE) {
169 continue;
170 }
171 // store the list of bundle names except for block list
172 validBundleList_.push_back(bundleName);
173 validAbilityList_.push_back(item.elementName.GetAbilityName());
174 }
175 GetAllAbilities();
176 return OHOS::ERR_OK;
177 }
178
GetBundleList(std::vector<std::string> & bundlelist,std::vector<std::string> & abilitylist)179 void WuKongUtil::GetBundleList(std::vector<std::string> &bundlelist, std::vector<std::string> &abilitylist)
180 {
181 if (bundleList_.size() == 0) {
182 GetAllAppInfo();
183 }
184 bundlelist = bundleList_;
185 abilitylist = abilityList_;
186 }
187
FindElement(std::vector<std::string> bundleList,std::string key)188 uint32_t WuKongUtil::FindElement(std::vector<std::string> bundleList, std::string key)
189 {
190 auto it = find(bundleList.begin(), bundleList.end(), key);
191 if (it != bundleList.end()) {
192 return distance(bundleList.begin(), it);
193 }
194 return INVALIDVALUE;
195 }
196
CheckBundleNameList()197 ErrCode WuKongUtil::CheckBundleNameList()
198 {
199 std::set<std::string> m(allowList_.begin(), allowList_.end());
200
201 for (auto it = blockList_.begin(); it != blockList_.end(); it++) {
202 if (m.find(*it) != m.end()) {
203 ERROR_LOG("invalid param:please check params of '-p' and '-b'");
204 return OHOS::ERR_INVALID_VALUE;
205 }
206 }
207 return OHOS::ERR_OK;
208 }
209
CheckArgumentList(std::vector<std::string> & arguments,bool isAddToList)210 ErrCode WuKongUtil::CheckArgumentList(std::vector<std::string> &arguments, bool isAddToList)
211 {
212 ErrCode result = OHOS::ERR_OK;
213 GetAllAppInfo();
214 for (uint32_t i = 0; i < arguments.size(); i++) {
215 uint32_t index = FindElement(bundleList_, arguments[i]);
216 if (index == INVALIDVALUE) {
217 uint32_t unLaunchedIndex = FindElement(unLaunchedBundleList_, arguments[i]);
218 if (unLaunchedIndex == INVALIDVALUE) {
219 ERROR_LOG_STR("bundle name '%s' is not be included in all bundles", arguments[i].c_str());
220 result = OHOS::ERR_INVALID_VALUE;
221 } else if (isAddToList) {
222 bundleList_.push_back(arguments[i]);
223 abilityList_.push_back(unLaunchedAbilityList_[unLaunchedIndex]);
224 }
225 }
226 }
227 return result;
228 }
229
SetAllowList(const std::string & optarg)230 ErrCode WuKongUtil::SetAllowList(const std::string &optarg)
231 {
232 SplitStr(optarg, ",", allowList_);
233 ErrCode result = CheckArgumentList(allowList_, true);
234 if (result == OHOS::ERR_OK) {
235 // delete repeat argument
236 DelRepeatArguments(allowList_);
237 if (allowList_.size() > 0) {
238 result = CheckBundleNameList();
239 }
240 }
241 return result;
242 }
243
SetBlockList(const std::string & optarg)244 ErrCode WuKongUtil::SetBlockList(const std::string &optarg)
245 {
246 SplitStr(optarg, ",", blockList_);
247 ErrCode result = CheckArgumentList(blockList_, false);
248 if (result == OHOS::ERR_OK) {
249 // delete repeat argument
250 DelRepeatArguments(blockList_);
251 if (blockList_.size() > 0) {
252 result = CheckBundleNameList();
253 }
254 }
255 return result;
256 }
257
SetBlockPageList(const std::string & optarg)258 ErrCode WuKongUtil::SetBlockPageList(const std::string &optarg)
259 {
260 ErrCode result = OHOS::ERR_OK;
261 std::vector<std::string> temp;
262 SplitStr(optarg, ",", temp);
263 blockPageList_.insert(blockPageList_.end(), temp.begin(), temp.end());
264 // delete repeat argument
265 DelRepeatArguments(blockPageList_);
266 if (blockPageList_.size() > 0) {
267 stringstream ss;
268 for (const auto& str:blockPageList_) {
269 ss << str << " ";
270 }
271 INFO_LOG_STR("Please confirm that the blocked page is %s", ss.str().c_str());
272 result = OHOS::ERR_OK;
273 }
274 return result;
275 }
276
DelRepeatArguments(std::vector<std::string> & argumentlist)277 void WuKongUtil::DelRepeatArguments(std::vector<std::string> &argumentlist)
278 {
279 std::set<std::string> s(argumentlist.begin(), argumentlist.end());
280 argumentlist.assign(s.begin(), s.end());
281 }
282
GetAllowList(std::vector<std::string> & allowList)283 void WuKongUtil::GetAllowList(std::vector<std::string> &allowList)
284 {
285 allowList = allowList_;
286 }
287
GetBlockList(std::vector<std::string> & blockList)288 void WuKongUtil::GetBlockList(std::vector<std::string> &blockList)
289 {
290 blockList = blockList_;
291 }
292
GetBlockPageList(std::vector<std::string> & blockPageList)293 void WuKongUtil::GetBlockPageList(std::vector<std::string> &blockPageList)
294 {
295 blockPageList = blockPageList_;
296 }
297
GetValidBundleList(std::vector<std::string> & validbundlelist)298 void WuKongUtil::GetValidBundleList(std::vector<std::string> &validbundlelist)
299 {
300 validbundlelist = validBundleList_;
301 }
302
SetAllAppInfo(std::vector<std::string> & bundleList,std::vector<std::string> & abilityList)303 void WuKongUtil::SetAllAppInfo(std::vector<std::string> &bundleList, std::vector<std::string> &abilityList)
304 {
305 bundleList_ = bundleList;
306 abilityList_ = abilityList;
307 }
308
SetTempAllowList(std::vector<std::string> tempAllowList)309 void WuKongUtil::SetTempAllowList(std::vector<std::string> tempAllowList)
310 {
311 tempAllowList_ = tempAllowList;
312 }
313
GetTempAllowList()314 std::vector<std::string> WuKongUtil::GetTempAllowList()
315 {
316 return tempAllowList_;
317 }
318
SetOrderFlag(bool orderFlag)319 void WuKongUtil::SetOrderFlag(bool orderFlag)
320 {
321 orderFlag_ = orderFlag;
322 }
323
GetOrderFlag()324 bool WuKongUtil::GetOrderFlag()
325 {
326 return orderFlag_;
327 }
328
GetScreenSize(int32_t & width,int32_t & height)329 ErrCode WuKongUtil::GetScreenSize(int32_t &width, int32_t &height)
330 {
331 ErrCode result = OHOS::ERR_OK;
332 if (screenWidth_ == -1 || screenHeight_ == -1) {
333 OHOS::Rosen::DisplayManager &displayMgr = OHOS::Rosen::DisplayManager::GetInstance();
334 sptr<OHOS::Rosen::Display> display = displayMgr.GetDefaultDisplay();
335 if (display == nullptr) {
336 ERROR_LOG("get screen size failed");
337 return OHOS::ERR_NO_INIT;
338 }
339 screenWidth_ = display->GetWidth();
340 screenHeight_ = display->GetHeight();
341 }
342 width = screenWidth_;
343 height = screenHeight_;
344 return result;
345 }
346
GetIconPath(std::string & iconpath)347 void WuKongUtil::GetIconPath(std::string &iconpath)
348 {
349 iconpath = iconPath_;
350 }
351
WukongScreenCap(std::string & screenStorePath,bool gCommandUitest)352 ErrCode WuKongUtil::WukongScreenCap(std::string &screenStorePath, bool gCommandUitest)
353 {
354 using namespace std::chrono;
355 ErrCode result = ERR_OK;
356 auto wukongts = to_string(time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count());
357 int fileExist_ = access((curDir_ + "screenshot").c_str(), F_OK);
358 if (fileExist_ == 0) {
359 DEBUG_LOG("File exist.");
360 } else {
361 const int wukongScreenShot = mkdir((curDir_ + "screenshot").c_str(), 0777);
362 DEBUG_LOG("File create.");
363 if (wukongScreenShot == -1) {
364 DEBUG_LOG("Error creating directory!");
365 result = ERR_NO_INIT;
366 }
367 }
368 auto wkScreenPath = curDir_ + "screenshot/" + "/" + wukongts + ".png";
369 DEBUG_LOG_STR("WukongScreenCap store path is {%s}", wkScreenPath.c_str());
370 if (gCommandUitest) {
371 auto cm = ComponentManager::GetInstance();
372 auto auita = Accessibility::AccessibilityUITestAbility::GetInstance();
373 auita->Disconnect();
374 std::string uitestCmd = "uitest dumpLayout -i -p " + curDir_ + "screenshot" + "/" + wukongts + ".json";
375 std::string res = Common::runProcess(uitestCmd);
376 DEBUG_LOG_STR("unitestCmd : %s", res.c_str());
377 cm->Disconnect();
378 if (!cm->Connect()) {
379 ERROR_LOG("ComponentManager Connect failed");
380 return OHOS::ERR_INVALID_OPERATION;
381 }
382 }
383 bool isTakeScreen = TakeWuKongScreenCap(wkScreenPath);
384 if (isTakeScreen == true) {
385 screenStorePath = wkScreenPath;
386 DEBUG_LOG("The snapshot has been created.");
387 } else {
388 DEBUG_LOG("This snapshot can not be created.");
389 }
390 return result;
391 }
392
GetBundleMgrProxy() const393 sptr<IBundleMgr> WuKongUtil::GetBundleMgrProxy() const
394 {
395 sptr<ISystemAbilityManager> systemAbilityManager =
396 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
397 if (!systemAbilityManager) {
398 ERROR_LOG("failed to get system ability mgr.");
399 return nullptr;
400 }
401
402 sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
403 if (!remoteObject) {
404 ERROR_LOG("failed to get bundle manager proxy.");
405 return nullptr;
406 }
407
408 return iface_cast<IBundleMgr>(remoteObject);
409 }
410
GetAllAbilitiesByBundleName(std::string bundleName,std::vector<std::string> & abilities)411 void WuKongUtil::GetAllAbilitiesByBundleName(std::string bundleName, std::vector<std::string> &abilities)
412 {
413 TRACK_LOG_STD();
414 sptr<IBundleMgr> bundleMgrProxy = GetBundleMgrProxy();
415 std::vector<BundleInfo> bundleInfos;
416 if (!bundleMgrProxy) {
417 ERROR_LOG("bundleMgrProxy is nullptr");
418 return;
419 }
420 bool getInfoResult = bundleMgrProxy->GetBundleInfos(BundleFlag::GET_BUNDLE_DEFAULT, bundleInfos, USE_ID);
421 if (!getInfoResult) {
422 ERROR_LOG("GetBundleInfos ERR");
423 return;
424 }
425 DEBUG_LOG_STR("bundles length{%d}", bundleInfos.size());
426 for (const auto &bundleIter : bundleInfos) {
427 TRACK_LOG_STR("bundleIter.name{%s}", bundleIter.name.c_str());
428 BundleInfo bundleInfo;
429 if (bundleIter.name == bundleName) {
430 TRACK_LOG_STR("map bundleName{%s}", bundleIter.name.c_str());
431 bool result =
432 bundleMgrProxy->GetBundleInfo(bundleIter.name, BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, 100);
433 if (!result) {
434 ERROR_LOG_STR("WriteBundleInfo getBundleInfo result %d, bundleName: %s", result,
435 bundleIter.name.c_str());
436 break;
437 }
438 for (auto &abilityIter : bundleInfo.abilityInfos) {
439 TRACK_LOG_STR("bundleName{%s} container abilities item{%s}", bundleIter.name.c_str(),
440 (abilityIter.name).c_str());
441 abilities.push_back(abilityIter.name);
442 }
443 }
444 }
445 TRACK_LOG_END();
446 }
447
GetAllAbilities()448 ErrCode WuKongUtil::GetAllAbilities()
449 {
450 TRACK_LOG_STD();
451 ErrCode result = OHOS::ERR_INVALID_VALUE;
452 sptr<IBundleMgr> bundleMgrProxy = GetBundleMgrProxy();
453 std::vector<BundleInfo> bundleInfos;
454 if (!bundleMgrProxy) {
455 ERROR_LOG("bundleMgrProxy is nullptr");
456 return result;
457 }
458 bool getInfoResult = bundleMgrProxy->GetBundleInfos(BundleFlag::GET_BUNDLE_DEFAULT, bundleInfos, USE_ID);
459 if (!getInfoResult) {
460 ERROR_LOG("GetBundleInfos ERR");
461 return result;
462 }
463 DEBUG_LOG_STR("bundles length{%d}", bundleInfos.size());
464 for (const auto &bundleIter : bundleInfos) {
465 std::string bundleName = bundleIter.name;
466 uint32_t bundleListIndex = FindElement(bundleList_, bundleName);
467 if (bundleListIndex != INVALIDVALUE) {
468 continue;
469 }
470 BundleInfo bundleInfo;
471 bool getBundleResult =
472 bundleMgrProxy->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, 100);
473 if (!getBundleResult) {
474 ERROR_LOG_STR("WriteWuKongBundleInfo getBundleInfo result %d", getBundleResult);
475 continue;
476 }
477 for (auto &abilityIter : bundleInfo.abilityInfos) {
478 unLaunchedBundleList_.push_back(bundleName);
479 unLaunchedAbilityList_.push_back(abilityIter.name);
480 DEBUG_LOG_STR("bundleName: %s, abilityName: %s", bundleName.c_str(), abilityIter.name.c_str());
481 }
482 }
483 if (unLaunchedAbilityList_.size() > 0) {
484 result = OHOS::ERR_OK;
485 }
486 TRACK_LOG_END();
487 return result;
488 }
489
GetCurrentTestDir()490 std::string WuKongUtil::GetCurrentTestDir()
491 {
492 return curDir_;
493 }
494
CopyFile(std::string & targetFile,std::string & sourceDir,std::string & destDir)495 bool WuKongUtil::CopyFile(std::string &targetFile, std::string &sourceDir, std::string &destDir)
496 {
497 std::ifstream in;
498 std::ofstream out;
499 DEBUG_LOG_STR("targetFile{%s} sourceDir{%s} destDir{%s}", targetFile.c_str(), sourceDir.c_str(), destDir.c_str());
500 char filepathSource[PATH_MAX] = {'\0'};
501 std::string sourceFile = sourceDir + targetFile;
502 char *realPathSource = realpath(sourceFile.c_str(), filepathSource);
503 if (realPathSource == nullptr) {
504 ERROR_LOG_STR("failed to get source file path (%s), errno: (%d)", sourceFile.c_str(), errno);
505 return false;
506 }
507 in.open(filepathSource, std::ios::binary);
508 if (in.fail()) {
509 std::cout << "Error 1: Fail to open the source file." << std::endl;
510 in.close();
511 out.close();
512 return false;
513 }
514
515 char filepathDest[PATH_MAX] = {'\0'};
516 char *realPathDest = realpath(destDir.c_str(), filepathDest);
517 if (realPathDest == nullptr) {
518 ERROR_LOG_STR("failed to get dest dir path (%s), errno: (%d)", destDir.c_str(), errno);
519 return false;
520 }
521 DEBUG_LOG_STR("destDir{%s}", filepathDest);
522 std::string destFile = destDir + targetFile;
523 out.open(destFile.c_str(), std::ios::binary);
524 if (out.fail()) {
525 std::cout << "Error 2: Fail to create the new file." << std::endl;
526 out.close();
527 in.close();
528 return false;
529 }
530 out << in.rdbuf();
531 out.close();
532 in.close();
533 return true;
534 }
535
DeleteFile(std::string targetDir)536 bool WuKongUtil::DeleteFile(std::string targetDir)
537 {
538 DIR *dirdp = nullptr;
539 char filepathSource[PATH_MAX] = {'\0'};
540 char *realPathSource = realpath(targetDir.c_str(), filepathSource);
541 if (realPathSource != nullptr) {
542 struct dirent *dp;
543 dirdp = opendir(targetDir.c_str());
544 while ((dp = readdir(dirdp)) != NULL) {
545 std::string currentFileName(dp->d_name);
546 std::string sourceFile = targetDir + currentFileName;
547 char *realFileSource = realpath(sourceFile.c_str(), filepathSource);
548 if (realFileSource != nullptr) {
549 remove(sourceFile.c_str());
550 }
551 }
552 } else {
553 return false;
554 }
555 (void)closedir(dirdp);
556 return true;
557 }
558 } // namespace WuKong
559 } // namespace OHOS
560