1 /*
2 * Copyright (c) 2024 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 "drawing_demo.h"
16
17 #include <sstream>
18
19 #include "accesstoken_kit.h"
20 #ifdef SUPPORT_ACCESS_TOKEN
21 #include "nativetoken_kit.h"
22 #include "token_setproc.h"
23 #endif
24 #include "display_manager.h"
25 #include "test_case_factory.h"
26 #include "test_case/test_common.h"
27
28 using namespace OHOS::Rosen;
29
30 namespace OHOS {
31 namespace Rosen {
DrawingDemo(int argc,char * argv[])32 DrawingDemo::DrawingDemo(int argc, char* argv[])
33 {
34 argc_ = argc;
35 for (int i = 0; i < argc_; i++) {
36 std::string str = argv[i];
37 argv_.emplace_back(str);
38 }
39 };
40
~DrawingDemo()41 DrawingDemo::~DrawingDemo()
42 {
43 if (window_) {
44 window_->Hide();
45 window_->Destroy();
46 }
47 };
48
Test(TestDisplayCanvas * canvas)49 int DrawingDemo::Test(TestDisplayCanvas* canvas)
50 {
51 TestCommon::Log("eg: drawing_demo function [cpu | gpu] {caseName?} {displayTime?}");
52 TestCommon::Log("eg: drawing_demo performance [cpu | gpu] caseName count {displayTime?}");
53 if (argc_ <= INDEX_DRAWING_TYPE) {
54 return RET_PARAM_ERR;
55 }
56
57 testType_ = argv_[INDEX_TEST_TYPE];
58 drawingType_ = argv_[INDEX_DRAWING_TYPE];
59 if (testType_ == "function") {
60 if (drawingType_ == "cpu") {
61 return TestFunction(FUNCTION_CPU);
62 } else if (drawingType_ == "gpu") {
63 return TestFunction(FUNCTION_GPU_UPSCREEN);
64 }
65 } else if (testType_ == "performance") {
66 if (drawingType_ == "cpu") {
67 return TestPerformance(canvas, PERFORMANCE_CPU);
68 } else if (drawingType_ == "gpu") {
69 return TestPerformance(canvas, PERFORMANCE_GPU_UPSCREEN);
70 }
71 }
72 return RET_PARAM_ERR;
73 }
74
InitWindow()75 int DrawingDemo::InitWindow()
76 {
77 rsUiDirector_ = RSUIDirector::Create();
78 if (rsUiDirector_ == nullptr) {
79 TestCommon::Log("Failed to create rsUiDirector_");
80 return RET_FAILED;
81 }
82 rsUiDirector_->Init();
83 RSTransaction::FlushImplicitTransaction();
84 sleep(1);
85 auto surfaceNode = window_->GetSurfaceNode();
86 rsUiDirector_->SetRSSurfaceNode(surfaceNode);
87
88 rootNode_ = RSRootNode::Create();
89 if (rootNode_ == nullptr) {
90 TestCommon::Log("Failed to create rootNode");
91 return RET_FAILED;
92 }
93 rootNode_->SetBounds(0, 0, rect_.width_, rect_.height_);
94 rootNode_->SetFrame(0, 0, rect_.width_, rect_.height_);
95 rootNode_->SetBackgroundColor(Drawing::Color::COLOR_WHITE);
96 rsUiDirector_->SetRSRootNode(rootNode_->ReinterpretCastTo<RSRootNode>());
97
98 canvasNode_ = RSCanvasNode::Create();
99 if (canvasNode_ == nullptr) {
100 TestCommon::Log("Failed to create canvasNode");
101 return RET_FAILED;
102 }
103 canvasNode_->SetFrame(0, 0, rect_.width_, rect_.height_);
104 rootNode_->AddChild(canvasNode_, -1);
105 rsUiDirector_->SendMessages();
106 sleep(1);
107 return RET_OK;
108 }
109
InitNativeTokenInfo()110 void InitNativeTokenInfo()
111 {
112 #ifdef SUPPORT_ACCESS_TOKEN
113 uint64_t tokenId;
114 const char *perms[1];
115 perms[0] = "ohos.permission.SYSTEM_FLOAT_WINDOW";
116 NativeTokenInfoParams infoInstance = {
117 .dcapsNum = 0,
118 .permsNum = 1,
119 .aclsNum = 0,
120 .dcaps = NULL,
121 .perms = perms,
122 .acls = NULL,
123 .processName = "drawing_demo",
124 .aplStr = "system_basic",
125 };
126 tokenId = GetAccessTokenId(&infoInstance);
127 SetSelfTokenID(tokenId);
128 Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
129 #endif
130 }
131
CreateWindow()132 int DrawingDemo::CreateWindow()
133 {
134 #ifdef SUPPORT_ACCESS_TOKEN
135 InitNativeTokenInfo();
136 TestCommon::Log("create window start");
137 sptr<Display> display = DisplayManager::GetInstance().GetDefaultDisplay();
138 if (display == nullptr) {
139 TestCommon::Log("Failed to get display!");
140 return RET_FAILED;
141 }
142 int32_t defaultWidth = display->GetWidth();
143 int32_t defaultHeight = display->GetHeight();
144 std::ostringstream stream;
145 stream << "display: " << defaultWidth << "*" << defaultHeight;
146 TestCommon::Log(stream.str());
147
148 std::string demoName = "drawing_demo";
149 RSSystemProperties::GetUniRenderEnabled();
150 sptr<WindowOption> option = new WindowOption();
151 option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
152 option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
153 option->SetWindowRect({ 0, 0, defaultWidth, defaultHeight });
154
155 int count = 0;
156 do {
157 if (window_ != nullptr) {
158 window_->Hide();
159 window_->Destroy();
160 }
161 window_ = Window::Create(demoName, option);
162 if (window_ == nullptr) {
163 TestCommon::Log("Failed to create window");
164 return RET_FAILED;
165 }
166
167 window_->Show();
168 usleep(SLEEP_TIME);
169 rect_ = window_->GetRect();
170 count++;
171 } while (rect_.width_ == 0 && rect_.height_ == 0 && count < MAX_TRY_NUMBER);
172
173 if (rect_.width_ == 0 || rect_.height_ == 0) {
174 TestCommon::Log("Failed to create window, rect is 0!");
175 return RET_FAILED;
176 }
177
178 int ret = InitWindow();
179 if (ret != RET_OK) {
180 return ret;
181 }
182 stream.str("");
183 stream << "create window success: " << rect_.width_ << " * " << rect_.height_;
184 TestCommon::Log(stream.str());
185 return RET_OK;
186 #endif
187 }
188
GetFunctionalParam(std::unordered_map<std::string,std::function<std::shared_ptr<TestBase> ()>> & map)189 int DrawingDemo::GetFunctionalParam(std::unordered_map<std::string, std::function<std::shared_ptr<TestBase>()>>& map)
190 {
191 // drawing_demo functional {cpu | gpu} {caseName?} {displayTime?}
192 if (argc_ <= INDEX_CASE_NAME) {
193 caseName_ = ALL_TAST_CASE;
194 return RET_OK;
195 }
196
197 caseName_ = argv_[INDEX_CASE_NAME];
198 if (map.find(caseName_) == map.end()) {
199 TestCommon::Log("TestCase not exist, please try again. All testcase:");
200 for (auto iter : map) {
201 TestCommon::Log(iter.first);
202 }
203 return RET_PARAM_ERR;
204 }
205
206 if (argc_ > INDEX_FUNCTION_TIME) {
207 std::string displayTimeStr = argv_[INDEX_FUNCTION_TIME];
208 displayTime_ = std::stoi(displayTimeStr);
209 }
210 return RET_OK;
211 }
212
TestFunction(int type)213 int DrawingDemo::TestFunction(int type)
214 {
215 auto map = TestCaseFactory::GetFunctionCase();
216 int ret = GetFunctionalParam(map);
217 if (ret != RET_OK) {
218 return ret;
219 }
220
221 TestCommon::Log("TestFunction start!");
222 ret = CreateWindow();
223 if (ret != RET_OK) {
224 return ret;
225 }
226 for (auto iter : map) {
227 if ((caseName_ != ALL_TAST_CASE) && (caseName_ != iter.first)) {
228 continue;
229 }
230
231 auto canvas = canvasNode_->BeginRecording(rect_.width_, rect_.height_);
232 auto testCase = iter.second();
233 if (testCase == nullptr) {
234 std::ostringstream stream;
235 stream << "Failed to create testcase:" << iter.first;
236 TestCommon::Log(stream.str());
237 continue;
238 }
239
240 testCase->SetCanvas((TestDisplayCanvas*)(canvas));
241 if (type == FUNCTION_CPU) {
242 testCase->SetFileName(iter.first);
243 testCase->TestFunctionCpu();
244 } else if (type == FUNCTION_GPU_UPSCREEN) {
245 testCase->TestFunctionGpuUpScreen();
246 }
247 canvasNode_->FinishRecording();
248 rsUiDirector_->SendMessages();
249 if (type == FUNCTION_GPU_UPSCREEN) {
250 sleep(2); // Wait for 2 seconds to make the screen display normal
251 (void)TestCommon::PackingPixmap(window_->Snapshot(), iter.first);
252 }
253 }
254
255 int time = (caseName_ != ALL_TAST_CASE ? displayTime_ : 1);
256 std::ostringstream stream;
257 stream << "wait: " << time << "s";
258 TestCommon::Log(stream.str());
259 sleep(time);
260 TestCommon::Log("TestFunction end!");
261 return RET_OK;
262 }
263
GetPerformanceParam(std::shared_ptr<TestBase> & testCase)264 int DrawingDemo::GetPerformanceParam(std::shared_ptr<TestBase>& testCase)
265 {
266 // drawing_demo performance {cpu | gpu} caseName count {displaytime?}
267 if (argc_ <= INDEX_COUNT) {
268 return RET_PARAM_ERR;
269 }
270
271 caseName_ = argv_[INDEX_CASE_NAME];
272 auto map = TestCaseFactory::GetPerformanceCase();
273 auto iter = map.find(caseName_);
274 if (iter == map.end()) {
275 TestCommon::Log("TestCase not exist, please try again. All testcase:");
276 for (auto iter : map) {
277 TestCommon::Log(iter.first);
278 }
279 return RET_PARAM_ERR;
280 }
281 testCase = iter->second();
282 if (testCase == nullptr) {
283 TestCommon::Log("Failed to create testcase");
284 return RET_FAILED;
285 }
286
287 std::string testCountStr = argv_[INDEX_COUNT];
288 testCount_ = std::stoi(testCountStr);
289
290 if (argc_ > INDEX_PERFORMANCE_TIME) {
291 std::string displayTimeStr = argv_[INDEX_PERFORMANCE_TIME];
292 displayTime_ = std::stoi(displayTimeStr);
293 }
294 return RET_OK;
295 }
296
TestPerformance(TestDisplayCanvas * canvasExt,int type)297 int DrawingDemo::TestPerformance(TestDisplayCanvas* canvasExt, int type)
298 {
299 std::shared_ptr<TestBase> testCase = nullptr;
300 int ret = GetPerformanceParam(testCase);
301 if (ret != RET_OK || testCase == nullptr) {
302 return ret;
303 }
304
305 TestCommon::Log("TestPerformance start!");
306 TestDisplayCanvas* canvas = nullptr;
307 if (canvasExt == nullptr) {
308 ret = CreateWindow();
309 if (ret != RET_OK) {
310 return ret;
311 }
312 canvas = reinterpret_cast<TestDisplayCanvas*>(canvasNode_->BeginRecording(rect_.width_, rect_.height_));
313 if (canvas == nullptr) {
314 TestCommon::Log("Failed to get canvas");
315 return RET_FAILED;
316 }
317 } else {
318 canvas = canvasExt;
319 }
320
321 testCase->SetCanvas((TestDisplayCanvas*)(canvas));
322 testCase->SetTestCount(testCount_);
323
324 if (type == PERFORMANCE_CPU) {
325 testCase->TestPerformanceCpu();
326 } else if (type == PERFORMANCE_GPU_UPSCREEN) {
327 testCase->TestPerformanceGpuUpScreen();
328 }
329
330 if (canvasExt == nullptr) {
331 canvasNode_->FinishRecording();
332 rsUiDirector_->SendMessages();
333
334 std::ostringstream stream;
335 stream << "wait: " << displayTime_ << "s";
336 TestCommon::Log(stream.str());
337 sleep(displayTime_);
338 }
339
340 TestCommon::Log("TestPerformance end!");
341 return RET_OK;
342 }
343 } // namespace Rosen
344 } // namespace OHOS
345
main(int argc,char * argv[])346 int main(int argc, char* argv[])
347 {
348 std::shared_ptr<DrawingDemo> drawingDemo = std::make_shared<DrawingDemo>(argc, argv);
349 if (drawingDemo == nullptr) {
350 TestCommon::Log("Failed to create DrawingDemo");
351 return 0;
352 }
353 int ret = drawingDemo->Test(nullptr);
354 if (ret == RET_PARAM_ERR) {
355 TestCommon::Log("Invalid parameter, please confirm");
356 }
357 return ret;
358 }
359
360 #ifdef __cplusplus
361 extern "C" {
362 #endif
DrawingTest(void * canvas,int argc,char * argv[])363 int DrawingTest(void* canvas, int argc, char* argv[])
364 {
365 if (canvas == nullptr) {
366 TestCommon::Log("canvas is nullptr");
367 return 0;
368 }
369 std::shared_ptr<DrawingDemo> drawingDemo = std::make_shared<DrawingDemo>(argc, argv);
370 if (drawingDemo == nullptr) {
371 TestCommon::Log("Failed to create DrawingDemo");
372 return 0;
373 }
374 int ret = drawingDemo->Test((TestDisplayCanvas*)(canvas));
375 if (ret == RET_PARAM_ERR) {
376 TestCommon::Log("Invalid parameter, please confirm");
377 }
378 return ret;
379 }
380 #ifdef __cplusplus
381 }
382 #endif