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