• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "boot_animation.h"
16 #include "event_handler.h"
17 #include "rs_trace.h"
18 #include "transaction/rs_render_service_client.h"
19 #include "transaction/rs_interfaces.h"
20 #include "transaction/rs_transaction.h"
21 #ifdef NEW_RENDER_CONTEXT
22 #include "render_context_factory.h"
23 #include "render_backend/rs_surface_factory.h"
24 #endif
25 #include <display_manager.h>
26 
27 using namespace OHOS;
28 using namespace Rosen;
29 
30 constexpr float MAX_ZORDER = 100000.0f;
31 
OnDraw(SkCanvas * canvas,int32_t curNo)32 void BootAnimation::OnDraw(SkCanvas* canvas, int32_t curNo)
33 {
34     if (canvas == nullptr) {
35         LOGE("OnDraw canvas is nullptr");
36         return;
37     }
38     if (curNo > (imgVecSize_ - 1) || curNo < 0) {
39         return;
40     }
41     std::shared_ptr<ImageStruct> imgstruct = imageVector_[curNo];
42     sk_sp<SkImage> image = imgstruct->imageData;
43 
44     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawRect");
45     SkPaint backPaint;
46     backPaint.setColor(SK_ColorBLACK);
47     canvas->drawRect(SkRect::MakeXYWH(0.0, 0.0, windowWidth_, windowHeight_), backPaint);
48     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
49     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawImageRect");
50     SkPaint paint;
51     SkRect rect;
52     rect.setXYWH(pointX_, pointY_, realWidth_, realHeight_);
53 #ifdef NEW_SKIA
54     canvas->drawImageRect(image.get(), rect, SkSamplingOptions(), &paint);
55 #else
56     canvas->drawImageRect(image.get(), rect, &paint);
57 #endif
58     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
59 }
60 
Draw()61 void BootAnimation::Draw()
62 {
63     if (picCurNo_ < (imgVecSize_ - 1)) {
64         picCurNo_ = picCurNo_ + 1;
65     } else {
66         CheckExitAnimation();
67         return;
68     }
69     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw RequestFrame");
70     auto frame = rsSurface_->RequestFrame(windowWidth_, windowHeight_);
71     if (frame == nullptr) {
72         LOGE("Draw frame is nullptr");
73         return;
74     }
75     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
76 #ifdef NEW_RENDER_CONTEXT
77     if (rsSurface_ == nullptr) {
78         LOGE("rsSurface is nullptr");
79         return;
80     }
81     auto canvas = rsSurface_->GetCanvas();
82     OnDraw(canvas, picCurNo_);
83     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");
84     rsSurface_->FlushFrame();
85     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
86 #else
87     framePtr_ = std::move(frame);
88     auto canvas = framePtr_->GetCanvas();
89     OnDraw(canvas, picCurNo_);
90     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");
91     rsSurface_->FlushFrame(framePtr_);
92     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
93 #endif
94 }
95 
Init(Rosen::ScreenId defaultId,int32_t width,int32_t height)96 void BootAnimation::Init(Rosen::ScreenId defaultId, int32_t width, int32_t height)
97 {
98     defaultId_ = defaultId;
99     windowWidth_ = width;
100     windowHeight_ = height;
101     LOGI("Init enter, width: %{public}d, height: %{public}d", width, height);
102 
103     InitPicCoordinates();
104     InitRsSurfaceNode();
105     if (animationConfig_.IsBootVideoEnabled()) {
106         LOGI("Init end");
107         return;
108     }
109 
110     auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
111     while (receiver_ == nullptr) {
112         receiver_ = rsClient.CreateVSyncReceiver("BootAnimation", mainHandler_);
113     }
114     VsyncError ret = receiver_->Init();
115     if (ret) {
116         LOGE("vsync receiver init failed: %{public}d", ret);
117         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
118         return;
119     }
120     InitRsSurface();
121     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::preload");
122     if (animationConfig_.ReadPicZipFile(imageVector_, freq_)) {
123         imgVecSize_ = imageVector_.size();
124     } else {
125         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
126         return;
127     }
128     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
129 
130     OHOS::Rosen::VSyncReceiver::FrameCallback fcb = {
131         .userData_ = this,
132         .callback_ = std::bind(&BootAnimation::OnVsync, this),
133     };
134     int32_t changefreq = static_cast<int32_t>((1000.0 / freq_) / 16);
135     ret = receiver_->SetVSyncRate(fcb, changefreq);
136     if (ret) {
137         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
138         LOGE("SetVSyncRate failed: %{public}d %{public}d %{public}d", ret, freq_, changefreq);
139         return;
140     } else {
141         LOGI("SetVSyncRate success: %{public}d %{public}d", freq_, changefreq);
142     }
143 }
144 
Run(Rosen::ScreenId id,int screenWidth,int screenHeight)145 void BootAnimation::Run(Rosen::ScreenId id, int screenWidth, int screenHeight)
146 {
147     LOGI("Run enter");
148     animationConfig_.ParserCustomCfgFile();
149 
150     runner_ = AppExecFwk::EventRunner::Create(false);
151     mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
152     mainHandler_->PostTask(std::bind(&BootAnimation::Init, this, id, screenWidth, screenHeight));
153     if (animationConfig_.IsBootVideoEnabled()) {
154         mainHandler_->PostTask(std::bind(&BootAnimation::PlayVideo, this));
155     } else {
156         mainHandler_->PostTask(std::bind(&BootAnimation::PlaySound, this));
157     }
158     runner_->Run();
159 }
160 
InitRsSurfaceNode()161 void BootAnimation::InitRsSurfaceNode()
162 {
163     LOGI("Init RsSurfaceNode enter");
164     struct Rosen::RSSurfaceNodeConfig rsSurfaceNodeConfig;
165     Rosen::RSSurfaceNodeType rsSurfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_NODE;
166     rsSurfaceNode_ = Rosen::RSSurfaceNode::Create(rsSurfaceNodeConfig, rsSurfaceNodeType);
167     if (!rsSurfaceNode_) {
168         LOGE("rsSurfaceNode_ is nullptr");
169         return;
170     }
171     rsSurfaceNode_->SetPositionZ(MAX_ZORDER);
172     rsSurfaceNode_->SetBounds({0, 0, windowWidth_, windowHeight_});
173     rsSurfaceNode_->SetBackgroundColor(0xFF000000);
174     rsSurfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT);
175     rsSurfaceNode_->AttachToDisplay(defaultId_);
176     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
177     system::SetParameter("bootevent.bootanimation.started", "true");
178     LOGI("Set bootevent.bootanimation.started true");
179 }
180 
InitRsSurface()181 void BootAnimation::InitRsSurface()
182 {
183 #if defined(NEW_RENDER_CONTEXT)
184     renderContext_ = Rosen::RenderContextBaseFactory::CreateRenderContext();
185     if (renderContext_ == nullptr) {
186         LOGE("Create Render Context failed");
187         return;
188     }
189     renderContext_->Init();
190     std::shared_ptr<Rosen::DrawingContext> drawingContext = std::make_shared<Rosen::DrawingContext>(
191         renderContext_->GetRenderType());
192     sptr<Surface> surface = rsSurfaceNode_->GetSurface();
193     drawingContext->SetUpDrawingContext();
194     rsSurface_ = Rosen::RSSurfaceFactory::CreateRSSurface(Rosen::PlatformName::OHOS, surface, drawingContext);
195     rsSurface_->SetRenderContext(renderContext_);
196 #else
197     rsSurface_ = OHOS::Rosen::RSSurfaceExtractor::ExtractRSSurface(rsSurfaceNode_);
198     if (rsSurface_ == nullptr) {
199         LOGE("rsSurface is nullptr");
200         return;
201     }
202 #ifdef ACE_ENABLE_GL
203     rc_ = OHOS::Rosen::RenderContextFactory::GetInstance().CreateEngine();
204     if (rc_ == nullptr) {
205         LOGE("InitilizeEglContext failed");
206         return;
207     } else {
208         LOGI("init egl context");
209         rc_->InitializeEglContext();
210         rsSurface_->SetRenderContext(rc_);
211     }
212 #endif
213     if (rc_ == nullptr) {
214         LOGI("rc is nullptr, use cpu");
215     }
216 #endif
217 }
218 
~BootAnimation()219 BootAnimation::~BootAnimation()
220 {
221     rsSurfaceNode_->DetachToDisplay(defaultId_);
222     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
223 }
224 
InitPicCoordinates()225 void BootAnimation::InitPicCoordinates()
226 {
227     if (windowWidth_ >= windowHeight_) {
228         realHeight_ = windowHeight_;
229         realWidth_ = realHeight_;
230         pointX_ = (windowWidth_ - realWidth_) / 2;
231     } else {
232         realWidth_ = windowWidth_;
233         realHeight_ = realWidth_;
234         pointY_ = (windowHeight_ - realHeight_) / 2;
235     }
236 }
237 
OnVsync()238 void BootAnimation::OnVsync()
239 {
240     PostTask(std::bind(&BootAnimation::Draw, this));
241 }
242 
CheckExitAnimation()243 bool BootAnimation::CheckExitAnimation()
244 {
245     if (!isAnimationEnd_) {
246         LOGI("Boot animation is end");
247         isAnimationEnd_ = true;
248     }
249     std::string bootEventCompleted = system::GetParameter("bootevent.boot.completed", "false");
250     if (bootEventCompleted == "true") {
251         mainHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
252         LOGI("Read bootevent.boot.completed is true");
253         return true;
254     }
255     return false;
256 }
257 
PlaySound()258 void BootAnimation::PlaySound()
259 {
260     LOGI("PlaySound start");
261     bool bootSoundEnabled = system::GetBoolParameter("persist.graphic.bootsound.enabled", true);
262     if (bootSoundEnabled == true) {
263         LOGI("PlaySound read bootSoundEnabled is true");
264         if (soundPlayer_ == nullptr) {
265             soundPlayer_ = Media::PlayerFactory::CreatePlayer();
266         }
267         std::string uri = animationConfig_.GetSoundUrl();
268         soundPlayer_->SetSource(uri);
269         soundPlayer_->SetLooping(false);
270         soundPlayer_->PrepareAsync();
271         soundPlayer_->Play();
272     }
273     LOGI("PlaySound end");
274 }
275 
PlayVideo()276 void BootAnimation::PlayVideo()
277 {
278     LOGI("PlayVideo start w:%{public}d h:%{public}d", windowWidth_, windowHeight_);
279     if (!animationConfig_.IsBootVideoEnabled()) {
280         return;
281     }
282     fcb_ = {
283         .userData_ = this,
284         .callback_ = std::bind(&BootAnimation::CloseVideoPlayer, this),
285     };
286     bootVideoPlayer_ = std::make_shared<BootVideoPlayer>();
287     bootVideoPlayer_->SetVideoPath(animationConfig_.GetBootVideoPath());
288     bootVideoPlayer_->SetPlayerSurface(rsSurfaceNode_ ? rsSurfaceNode_->GetSurface() : nullptr);
289     bootVideoPlayer_->SetCallback(&fcb_);
290     if (!bootVideoPlayer_->PlayVideo()) {
291         LOGE("Play video failed.");
292         CloseVideoPlayer();
293     }
294 }
295 
CloseVideoPlayer()296 void BootAnimation::CloseVideoPlayer()
297 {
298     LOGI("Close video player.");
299     while (!CheckExitAnimation()) {
300         usleep(SLEEP_TIME_US);
301     }
302     LOGI("Check Exit Animation end.");
303 }
304