1/* 2 * Copyright (C) 2021 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#include <iostream> 16#include <sstream> 17#include <thread> 18#include <unistd.h> 19#include <fcntl.h> 20#include <sys/stat.h> 21#include "include/sp_utils.h" 22#include "include/Capture.h" 23#include "include/sp_log.h" 24#include "display_manager.h" 25#include "wm_common.h" 26#include "png.h" 27#include <filesystem> 28#include "include/common.h" 29namespace OHOS { 30namespace SmartPerf { 31using namespace OHOS::Media; 32using namespace OHOS::Rosen; 33std::map<std::string, std::string> Capture::ItemData() 34{ 35 std::map<std::string, std::string> result; 36 const int two = 2; 37 const int modResult = callNum % two; 38 callNum++; 39 curTime = GetCurTimes(); 40 std::string screenCapPath = "data/local/tmp/capture/screenCap_" + std::to_string(curTime); 41 std::string path = "NA"; 42 if (isSocketMessage) { 43 if (modResult == 0) { 44 path = screenCapPath + ".jpeg"; 45 result["capture"] = path; 46 TriggerGetCatchSocket(curTime); 47 isSocketMessage = false; 48 } 49 } else { 50 if (modResult == 1) { 51 path = screenCapPath + ".png"; 52 result["capture"] = path; 53 TriggerGetCatch(); 54 } 55 } 56 result["capture"] = path; 57 58 LOGI("Capture::ItemData map size(%u)", result.size()); 59 return result; 60} 61 62void Capture::SocketMessage() 63{ 64 isSocketMessage = true; 65} 66 67long long Capture::GetCurTimes() 68{ 69 return SPUtils::GetCurTime(); 70} 71void Capture::ThreadGetCatch() 72{ 73 const std::string captureDir = "/data/local/tmp/capture"; 74 const std::string savePath = captureDir + "/screenCap_" + std::to_string(curTime) + ".png"; 75 std::string cmdResult; 76 if (!SPUtils::FileAccess(captureDir)) { 77 std::string capturePath = CMD_COMMAND_MAP.at(CmdCommand::CAPTURE_FILE); 78 if (!SPUtils::LoadCmd(capturePath, cmdResult)) { 79 LOGI("%s capture not be created!", captureDir.c_str()); 80 return; 81 } else { 82 LOGI("%s created successfully!", captureDir.c_str()); 83 } 84 }; 85 std::ostringstream errorRecv; 86 auto fd = open(savePath.c_str(), O_RDWR | O_CREAT, 0666); 87 if (fd == -1) { 88 LOGI("Failed to open file: %s", savePath.c_str()); 89 } 90 if (!TakeScreenCap(savePath)) { 91 LOGE("Screen Capture Failed!"); 92 } 93 close(fd); 94} 95 96 97void Capture::ThreadGetCatchSocket(const std::string &captureTime) const 98{ 99 std::string captureDir = "/data/local/tmp/capture"; 100 std::string savePath = captureDir + "/screenCap_" + captureTime + ".jpeg"; 101 std::string cmdResult; 102 if (!SPUtils::FileAccess(captureDir)) { 103 std::string capturePath = CMD_COMMAND_MAP.at(CmdCommand::CAPTURE_FILE); 104 if (!SPUtils::LoadCmd(capturePath, cmdResult)) { 105 LOGI("%s capture not be created!", captureDir.c_str()); 106 return; 107 } else { 108 LOGI("%s created successfully!", captureDir.c_str()); 109 } 110 }; 111 112 char realPath[PATH_MAX] = {0x00}; 113 if (realpath(savePath.c_str(), realPath) == nullptr) { 114 std::cout << "" << std::endl; 115 } 116 117 auto fd = open(realPath, O_RDWR | O_CREAT, 0644); 118 if (fd == -1) { 119 LOGI("Failed to open file: %s", savePath.c_str()); 120 } 121 std::string snapshot = CMD_COMMAND_MAP.at(CmdCommand::SNAPSHOT); 122 if (!SPUtils::LoadCmd(snapshot + savePath, cmdResult)) { 123 LOGI("snapshot_display command failed!"); 124 close(fd); 125 return; 126 } 127 close(fd); 128} 129 130void Capture::TriggerGetCatch() 131{ 132 auto tStart = std::thread([this]() { 133 this->ThreadGetCatch(); 134 }); 135 tStart.detach(); 136} 137 138void Capture::TriggerGetCatchSocket(long long captureTime) const 139{ 140 std::string curTimeStr = std::to_string(captureTime); 141 auto tStart = std::thread([this, curTimeStr]() { 142 this->ThreadGetCatchSocket(curTimeStr); 143 }); 144 tStart.detach(); 145} 146 147bool Capture::TakeScreenCap(const std::string &savePath) const 148{ 149 Rosen::DisplayManager &displayMgr = Rosen::DisplayManager::GetInstance(); 150 std::shared_ptr<Media::PixelMap> pixelMap = displayMgr.GetScreenshot(displayMgr.GetDefaultDisplayId()); 151 static constexpr int bitmapDepth = 8; 152 if (pixelMap == nullptr) { 153 LOGE("Failed to get display pixelMap"); 154 return false; 155 } 156 auto width = static_cast<uint32_t>(pixelMap->GetWidth()); 157 auto height = static_cast<uint32_t>(pixelMap->GetHeight()); 158 auto data = pixelMap->GetPixels(); 159 auto stride = static_cast<uint32_t>(pixelMap->GetRowBytes()); 160 png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); 161 if (pngStruct == nullptr) { 162 LOGE("png_create_write_struct nullptr!"); 163 return false; 164 } 165 png_infop pngInfo = png_create_info_struct(pngStruct); 166 if (pngInfo == nullptr) { 167 LOGE("png_create_info_struct error nullptr!"); 168 png_destroy_write_struct(&pngStruct, nullptr); 169 return false; 170 } 171 char realPath[PATH_MAX] = {0x00}; 172 if (realpath(savePath.c_str(), realPath) == nullptr) { 173 std::cout << "" << std::endl; 174 } 175 FILE *fp = fopen(realPath, "wb"); 176 if (fp == nullptr) { 177 LOGE("open file error!"); 178 png_destroy_write_struct(&pngStruct, &pngInfo); 179 return false; 180 } 181 png_init_io(pngStruct, fp); 182 png_set_IHDR(pngStruct, pngInfo, width, height, bitmapDepth, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, 183 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 184 png_set_packing(pngStruct); // set packing info 185 png_write_info(pngStruct, pngInfo); // write to header 186 for (uint32_t i = 0; i < height; i++) { 187 png_write_row(pngStruct, data + (i * stride)); 188 } 189 png_write_end(pngStruct, pngInfo); 190 // free 191 png_destroy_write_struct(&pngStruct, &pngInfo); 192 (void)fclose(fp); 193 return true; 194} 195} 196} 197