1 /*
2 * Copyright (c) 2025 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 "cj_screenshot_module.h"
17
18 #include <cinttypes>
19 #include <cstddef>
20 #include <cstdint>
21 #include <image_type.h>
22 #include <iosfwd>
23 #include <memory>
24 #include <string>
25 #include <type_traits>
26 #include <thread>
27 #include <queue>
28 #include <mutex>
29 #include <condition_variable>
30 #include <functional>
31
32 #include "display_manager.h"
33 #include "pixel_map.h"
34 #include "pixel_map_impl.h"
35 #include "window_manager_hilog.h"
36 #include "dm_common.h"
37
38 using namespace OHOS::FFI;
39 using namespace OHOS::Media;
40
41 namespace OHOS {
42 namespace Rosen {
43 struct Option {
44 Media::Rect rect;
45 Media::Size size;
46 int rotation = 0;
47 DisplayId displayId = 0;
48 bool isNeedNotify = true;
49 bool isNeedPointer = true;
50 };
51
52 struct Param {
53 DmErrorCode wret;
54 Option option;
55 std::string errMessage;
56 bool useInputOption;
57 bool validInputParam;
58 std::shared_ptr<Media::PixelMap> image;
59 Media::Rect imageRect;
60 bool isPick;
61 };
62
CreateRectObject(const Media::Rect & imageRect)63 static CRect CreateRectObject(const Media::Rect& imageRect)
64 {
65 CRect rect;
66 rect.left = imageRect.left;
67 rect.top = imageRect.top;
68 rect.width = imageRect.width;
69 rect.height = imageRect.height;
70 return rect;
71 }
72
CreatePickerObject(const std::unique_ptr<Param> & param)73 static std::unique_ptr<CPickInfo> CreatePickerObject(const std::unique_ptr<Param>& param)
74 {
75 if (param == nullptr) {
76 TLOGE(WmsLogTag::WMS_SCB, "param nullptr.");
77 return nullptr;
78 }
79 auto pickInfo = std::make_unique<CPickInfo>();
80 pickInfo->pickRect = CreateRectObject(param->imageRect);
81
82 auto nativeImage = FFIData::Create<PixelMapImpl>(move(param->image));
83 if (nativeImage == nullptr) {
84 TLOGE(WmsLogTag::WMS_SCB, "create image failed");
85 return pickInfo;
86 }
87 TLOGI(WmsLogTag::WMS_SCB, "pick end");
88 pickInfo->pixelMap = nativeImage->GetID();
89 return pickInfo;
90 }
91
CheckWretParam(std::unique_ptr<Param> & param,RetStruct ret)92 static bool CheckWretParam(std::unique_ptr<Param>& param, RetStruct ret)
93 {
94 bool isThrowError = true;
95 switch (param->wret) {
96 case DmErrorCode::DM_ERROR_NO_PERMISSION:
97 TLOGE(WmsLogTag::WMS_SCB, "[CJScreenshotModule] Get default DmErrorCode is DM_ERROR_NO_PERMISSION");
98 ret.code = static_cast<int32_t>(DmErrorCode::DM_ERROR_NO_PERMISSION);
99 break;
100 case DmErrorCode::DM_ERROR_INVALID_PARAM:
101 TLOGE(WmsLogTag::WMS_SCB, "[CJScreenshotModule] Get default DmErrorCode is DM_ERROR_INVALID_PARAM");
102 ret.code = static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM);
103 break;
104 case DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT:
105 TLOGE(WmsLogTag::WMS_SCB, "[CJScreenshotModule] Get default DmErrorCode is DM_ERROR_DEVICE_NOT_SUPPORT");
106 ret.code = static_cast<int32_t>(DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT);
107 break;
108 case DmErrorCode::DM_ERROR_SYSTEM_INNORMAL:
109 ret.code = static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL);
110 break;
111 default:
112 isThrowError = false;
113 ret.code = static_cast<int32_t>(DmErrorCode::DM_OK);
114 break;
115 }
116 return isThrowError;
117 }
118
Resolve(std::unique_ptr<Param> & param,RetStruct ret)119 static RetStruct Resolve(std::unique_ptr<Param>& param, RetStruct ret)
120 {
121 TLOGI(WmsLogTag::WMS_SCB, "screen shot ret=%{public}d.", param->wret);
122 bool isThrowError = CheckWretParam(param, ret);
123 if (isThrowError) {
124 return ret;
125 }
126 if (param->wret != DmErrorCode::DM_OK) {
127 ret.code = static_cast<int32_t>(param->wret);
128 TLOGE(WmsLogTag::WMS_SCB, "ret is not DmErrorCode DM_OK, errorCode:%{public}d", param->wret);
129 return ret;
130 }
131 if (param->isPick) {
132 TLOGI(WmsLogTag::WMS_SCB, "Resolve Screenshot by picker");
133 auto pickInfo = CreatePickerObject(param);
134 if (pickInfo == nullptr) {
135 ret.code = static_cast<int32_t>(DmErrorCode::DM_ERROR_INVALID_PARAM);
136 return ret;
137 }
138 ret.data = pickInfo.release();
139 return ret;
140 }
141 TLOGI(WmsLogTag::WMS_SCB, "Screenshot image Width %{public}d, Height %{public}d",
142 param->image->GetWidth(), param->image->GetHeight());
143 auto nativeImage = FFIData::Create<PixelMapImpl>(move(param->image));
144 if (nativeImage == nullptr) {
145 TLOGE(WmsLogTag::WMS_SCB, "create image failed");
146 return ret;
147 }
148 int64_t* pixelId = new int64_t(nativeImage->GetID());
149 ret.data = pixelId;
150 return ret;
151 }
152
GetScreenshot(std::unique_ptr<Param> & param)153 static void GetScreenshot(std::unique_ptr<Param>& param)
154 {
155 if (!param->validInputParam) {
156 TLOGE(WmsLogTag::WMS_SCB, "Invalid Input Param!");
157 param->image = nullptr;
158 param->wret = DmErrorCode::DM_ERROR_INVALID_PARAM;
159 param->errMessage = "Get Screenshot Failed: Invalid input param";
160 return;
161 }
162 CaptureOption option = { param->option.displayId, param->option.isNeedNotify, param->option.isNeedPointer };
163 if (!param->isPick && (!option.isNeedNotify_ || !option.isNeedPointer_)) {
164 if (param->useInputOption) {
165 param->image = DisplayManager::GetInstance().GetScreenshotWithOption(option,
166 param->option.rect, param->option.size, param->option.rotation, ¶m->wret);
167 } else {
168 param->image = DisplayManager::GetInstance().GetScreenshotWithOption(option, ¶m->wret);
169 }
170 } else {
171 if (param->useInputOption) {
172 TLOGI(WmsLogTag::WMS_SCB, "Get Screenshot by input option");
173 SnapShotConfig snapConfig;
174 snapConfig.displayId_ = param->option.displayId;
175 snapConfig.imageRect_ = param->option.rect;
176 snapConfig.imageSize_ = param->option.size;
177 snapConfig.rotation_ = param->option.rotation;
178 param->image = DisplayManager::GetInstance().GetScreenshotwithConfig(snapConfig, ¶m->wret, true);
179 } else if (param->isPick) {
180 TLOGI(WmsLogTag::WMS_SCB, "Get Screenshot by picker");
181 param->image = DisplayManager::GetInstance().GetSnapshotByPicker(param->imageRect, ¶m->wret);
182 } else {
183 TLOGI(WmsLogTag::WMS_SCB, "Get Screenshot by default option");
184 param->image = DisplayManager::GetInstance().GetScreenshot(param->option.displayId, ¶m->wret, true);
185 }
186 }
187 if (param->image == nullptr && param->wret == DmErrorCode::DM_OK) {
188 TLOGE(WmsLogTag::WMS_SCB, "Get Screenshot failed!");
189 param->wret = DmErrorCode::DM_ERROR_INVALID_SCREEN;
190 param->errMessage = "Get Screenshot failed: Screenshot image is nullptr";
191 }
192 }
193
GetScreenCapture(std::unique_ptr<Param> & param)194 static void GetScreenCapture(std::unique_ptr<Param>& param)
195 {
196 CaptureOption captureOption;
197 captureOption.displayId_ = param->option.displayId;
198 captureOption.isNeedNotify_ = param->option.isNeedNotify;
199 captureOption.isNeedPointer_ = param->option.isNeedPointer;
200 TLOGI(WmsLogTag::WMS_SCB, "capture option isNeedNotify=%{public}d isNeedPointer=%{public}d",
201 captureOption.isNeedNotify_, captureOption.isNeedPointer_);
202 param->image = DisplayManager::GetInstance().GetScreenCapture(captureOption, ¶m->wret);
203 if (param->image == nullptr && param->wret == DmErrorCode::DM_OK) {
204 TLOGE(WmsLogTag::WMS_SCB, "screen capture failed!");
205 param->wret = DmErrorCode::DM_ERROR_SYSTEM_INNORMAL;
206 param->errMessage = "ScreenCapture failed: image is null.";
207 }
208 }
209
PickFunc()210 RetStruct CJScreenshotModule::PickFunc()
211 {
212 TLOGI(WmsLogTag::WMS_SCB, "%{public}s called", __PRETTY_FUNCTION__);
213
214 RetStruct ret = { .code = static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL), .len = 0, .data = nullptr };
215 auto param = std::make_unique<Param>();
216 if (param == nullptr) {
217 TLOGE(WmsLogTag::WMS_SCB, "Create param failed.");
218 return ret;
219 }
220 param->validInputParam = true;
221 param->isPick = true;
222 GetScreenshot(param);
223 Resolve(param, ret);
224 return ret;
225 }
226
CaptureFunc(uint32_t displayId)227 RetStruct CJScreenshotModule::CaptureFunc(uint32_t displayId)
228 {
229 TLOGI(WmsLogTag::WMS_SCB, "%{public}s called", __PRETTY_FUNCTION__);
230
231 RetStruct ret = { .code = static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL), .len = 0, .data = nullptr };
232 auto param = std::make_unique<Param>();
233 if (param == nullptr) {
234 TLOGE(WmsLogTag::WMS_SCB, "Create param failed.");
235 return ret;
236 }
237 param->option.displayId = displayId;
238 GetScreenCapture(param);
239 Resolve(param, ret);
240 return ret;
241 }
242 } // namespace Rosen
243 } // namespace OHOS
244