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
Resolve(std::unique_ptr<Param> & param,RetStruct ret)92 static RetStruct Resolve(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 TLOGI(WmsLogTag::WMS_SCB, "screen shot ret=%{public}d.", param->wret);
117 if (isThrowError) {
118 return ret;
119 }
120 if (param->wret != DmErrorCode::DM_OK) {
121 ret.code = static_cast<int32_t>(param->wret);
122 TLOGE(WmsLogTag::WMS_SCB, "ret is not DmErrorCode DM_OK, errorCode:%{public}d", param->wret);
123 return ret;
124 }
125 if (param->isPick) {
126 TLOGI(WmsLogTag::WMS_SCB, "Resolve Screenshot by picker");
127 std::unique_ptr<CPickInfo> pickInfoPtr(CreatePickerObject(param));
128 ret.data = static_cast<void*>(pickInfoPtr.get());
129 return ret;
130 }
131 TLOGI(WmsLogTag::WMS_SCB, "Screenshot image Width %{public}d, Height %{public}d",
132 param->image->GetWidth(), param->image->GetHeight());
133 auto nativeImage = FFIData::Create<PixelMapImpl>(move(param->image));
134 if (nativeImage == nullptr) {
135 TLOGE(WmsLogTag::WMS_SCB, "create image failed");
136 return ret;
137 }
138 int64_t* pixelId = new int64_t(nativeImage->GetID());
139 ret.data = pixelId;
140 return ret;
141 }
142
GetScreenshot(std::unique_ptr<Param> & param)143 static void GetScreenshot(std::unique_ptr<Param>& param)
144 {
145 if (!param->validInputParam) {
146 TLOGE(WmsLogTag::WMS_SCB, "Invalid Input Param!");
147 param->image = nullptr;
148 param->wret = DmErrorCode::DM_ERROR_INVALID_PARAM;
149 param->errMessage = "Get Screenshot Failed: Invalid input param";
150 return;
151 }
152 CaptureOption option = { param->option.displayId, param->option.isNeedNotify, param->option.isNeedPointer };
153 if (!param->isPick && (!option.isNeedNotify_ || !option.isNeedPointer_)) {
154 if (param->useInputOption) {
155 param->image = DisplayManager::GetInstance().GetScreenshotWithOption(option,
156 param->option.rect, param->option.size, param->option.rotation, ¶m->wret);
157 } else {
158 param->image = DisplayManager::GetInstance().GetScreenshotWithOption(option, ¶m->wret);
159 }
160 } else {
161 if (param->useInputOption) {
162 TLOGI(WmsLogTag::WMS_SCB, "Get Screenshot by input option");
163 SnapShotConfig snapConfig;
164 snapConfig.displayId_ = param->option.displayId;
165 snapConfig.imageRect_ = param->option.rect;
166 snapConfig.imageSize_ = param->option.size;
167 snapConfig.rotation_ = param->option.rotation;
168 param->image = DisplayManager::GetInstance().GetScreenshotwithConfig(snapConfig, ¶m->wret, true);
169 } else if (param->isPick) {
170 TLOGI(WmsLogTag::WMS_SCB, "Get Screenshot by picker");
171 param->image = DisplayManager::GetInstance().GetSnapshotByPicker(param->imageRect, ¶m->wret);
172 } else {
173 TLOGI(WmsLogTag::WMS_SCB, "Get Screenshot by default option");
174 param->image = DisplayManager::GetInstance().GetScreenshot(param->option.displayId, ¶m->wret, true);
175 }
176 }
177 if (param->image == nullptr && param->wret == DmErrorCode::DM_OK) {
178 TLOGE(WmsLogTag::WMS_SCB, "Get Screenshot failed!");
179 param->wret = DmErrorCode::DM_ERROR_INVALID_SCREEN;
180 param->errMessage = "Get Screenshot failed: Screenshot image is nullptr";
181 }
182 }
183
GetScreenCapture(std::unique_ptr<Param> & param)184 static void GetScreenCapture(std::unique_ptr<Param>& param)
185 {
186 CaptureOption captureOption;
187 captureOption.displayId_ = param->option.displayId;
188 captureOption.isNeedNotify_ = param->option.isNeedNotify;
189 captureOption.isNeedPointer_ = param->option.isNeedPointer;
190 TLOGI(WmsLogTag::WMS_SCB, "capture option isNeedNotify=%{public}d isNeedPointer=%{public}d",
191 captureOption.isNeedNotify_, captureOption.isNeedPointer_);
192 param->image = DisplayManager::GetInstance().GetScreenCapture(captureOption, ¶m->wret);
193 if (param->image == nullptr && param->wret == DmErrorCode::DM_OK) {
194 TLOGE(WmsLogTag::WMS_SCB, "screen capture failed!");
195 param->wret = DmErrorCode::DM_ERROR_SYSTEM_INNORMAL;
196 param->errMessage = "ScreenCapture failed: image is null.";
197 }
198 }
199
PickFunc()200 RetStruct CJScreenshotModule::PickFunc()
201 {
202 TLOGI(WmsLogTag::WMS_SCB, "%{public}s called", __PRETTY_FUNCTION__);
203
204 RetStruct ret = { .code = static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL), .len = 0, .data = nullptr };
205 auto param = std::make_unique<Param>();
206 if (param == nullptr) {
207 TLOGE(WmsLogTag::WMS_SCB, "Create param failed.");
208 return ret;
209 }
210 param->validInputParam = true;
211 param->isPick = true;
212 GetScreenshot(param);
213 Resolve(param, ret);
214 return ret;
215 }
216
CaptureFunc(uint32_t displayId)217 RetStruct CJScreenshotModule::CaptureFunc(uint32_t displayId)
218 {
219 TLOGI(WmsLogTag::WMS_SCB, "%{public}s called", __PRETTY_FUNCTION__);
220
221 RetStruct ret = { .code = static_cast<int32_t>(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL), .len = 0, .data = nullptr };
222 auto param = std::make_unique<Param>();
223 if (param == nullptr) {
224 TLOGE(WmsLogTag::WMS_SCB, "Create param failed.");
225 return ret;
226 }
227 param->option.displayId = displayId;
228 GetScreenCapture(param);
229 Resolve(param, ret);
230 return ret;
231 }
232 } // namespace Rosen
233 } // namespace OHOS
234