• 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 
17 #include "boot_animation_utils.h"
18 #include "event_handler.h"
19 #include "rs_trace.h"
20 #include "transaction/rs_render_service_client.h"
21 #include "transaction/rs_interfaces.h"
22 #include "transaction/rs_transaction.h"
23 #ifdef NEW_RENDER_CONTEXT
24 #include "render_context_factory.h"
25 #include "rs_surface_factory.h"
26 #endif
27 #include "parameter.h"
28 #include "platform/common/rs_system_properties.h"
29 
30 using namespace OHOS;
31 
32 constexpr float MAX_ZORDER = 100000.0f;
33 constexpr int HALF_NUM = 2;
34 
OnDraw(SkCanvas * canvas,int32_t curNo)35 void BootAnimation::OnDraw(SkCanvas* canvas, int32_t curNo)
36 {
37     if (canvas == nullptr) {
38         LOGE("OnDraw canvas is nullptr");
39         return;
40     }
41     if (curNo > (imgVecSize_ - 1) || curNo < 0) {
42         return;
43     }
44     std::shared_ptr<ImageStruct> imgstruct = imageVector_[curNo];
45     sk_sp<SkImage> image = imgstruct->imageData;
46 
47     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawRect");
48     SkPaint backPaint;
49     backPaint.setColor(SK_ColorBLACK);
50     canvas->drawRect(SkRect::MakeXYWH(0.0, 0.0, windowWidth_, windowHeight_), backPaint);
51     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
52     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawImageRect");
53     SkPaint paint;
54     SkRect rect;
55     rect.setXYWH(pointX_, pointY_, realWidth_, realHeight_);
56     canvas->drawImageRect(image.get(), rect, SkSamplingOptions(), &paint);
57     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
58 }
59 
Draw()60 void BootAnimation::Draw()
61 {
62     if (picCurNo_ < (imgVecSize_ - 1)) {
63         picCurNo_ = picCurNo_ + 1;
64     } else {
65         CheckExitAnimation();
66         return;
67     }
68     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw RequestFrame");
69     auto frame = rsSurface_->RequestFrame(windowWidth_, windowHeight_);
70     if (frame == nullptr) {
71         LOGE("Draw frame is nullptr");
72         return;
73     }
74     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
75 #ifdef NEW_RENDER_CONTEXT
76     if (rsSurface_ == nullptr) {
77         LOGE("rsSurface is nullptr");
78         return;
79     }
80     auto canvas = rsSurface_->GetCanvas();
81     OnDraw(canvas, picCurNo_);
82     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");
83     rsSurface_->FlushFrame();
84     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
85 #else
86     framePtr_ = std::move(frame);
87     auto canvas = framePtr_->GetCanvas();
88     OnDraw(canvas, picCurNo_);
89     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");
90     rsSurface_->FlushFrame(framePtr_);
91     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
92 #endif
93 }
94 
Init(Rosen::ScreenId defaultId,int32_t width,int32_t height)95 void BootAnimation::Init(Rosen::ScreenId defaultId, int32_t width, int32_t height)
96 {
97     defaultId_ = defaultId;
98     windowWidth_ = width;
99     windowHeight_ = height;
100     LOGI("Init enter, width: %{public}d, height: %{public}d", width, height);
101 
102     InitPicCoordinates();
103     InitRsDisplayNode();
104     InitRsSurfaceNode();
105 #ifdef PLAYER_FRAMEWORK_ENABLE
106     if (animationConfig_.IsBootVideoEnabled()) {
107         LOGI("Init end");
108         return;
109     }
110 #endif
111     LOGI("Playing boot animation using sequence frames.");
112     system::SetParameter("bootevent.bootanimation.started", "true");
113     auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
114     while (receiver_ == nullptr) {
115         receiver_ = rsClient.CreateVSyncReceiver("BootAnimation", mainHandler_);
116     }
117     VsyncError ret = receiver_->Init();
118     if (ret) {
119         LOGE("vsync receiver init failed: %{public}d", ret);
120         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
121         return;
122     }
123     InitRsSurface();
124     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::preload");
125     if (animationConfig_.ReadPicZipFile(imageVector_, freq_)) {
126         imgVecSize_ = imageVector_.size();
127     } else {
128         LOGE("Read PicZipFile failed");
129         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
130         return;
131     }
132     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
133 
134     OHOS::Rosen::VSyncReceiver::FrameCallback fcb = {
135         .userData_ = this,
136         .callback_ = std::bind(&BootAnimation::OnVsync, this),
137     };
138     int32_t changefreq = static_cast<int32_t>((1000.0 / freq_) / 16);
139     ret = receiver_->SetVSyncRate(fcb, changefreq);
140     if (ret) {
141         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
142         LOGE("SetVSyncRate failed: %{public}d %{public}d %{public}d", ret, freq_, changefreq);
143         return;
144     } else {
145         LOGI("SetVSyncRate success: %{public}d %{public}d", freq_, changefreq);
146     }
147 }
148 
Run(Rosen::ScreenId id,int screenWidth,int screenHeight)149 void BootAnimation::Run(Rosen::ScreenId id, int screenWidth, int screenHeight)
150 {
151     LOGI("Run enter");
152     animationConfig_.ParserCustomCfgFile();
153     Rosen::RSInterfaces& interface = Rosen::RSInterfaces::GetInstance();
154     if (animationConfig_.GetRotateScreenId() >= 0) {
155         id = interface.GetActiveScreenId();
156         LOGI("GetActiveScreenId: " BPUBU64 "", id);
157         Rosen::RSScreenModeInfo modeinfo = interface.GetScreenActiveMode(id);
158         screenWidth = modeinfo.GetScreenWidth();
159         screenHeight = modeinfo.GetScreenHeight();
160         LOGI("screenWidth: %{public}d, screenHeight: %{public}d", screenWidth, screenHeight);
161         if (id > 0) {
162             LOGI("SetScreenPowerStatus POWER_STATUS_OFF_FAKE: 0");
163             interface.SetScreenPowerStatus(0, Rosen::ScreenPowerStatus::POWER_STATUS_OFF_FAKE);
164             LOGI("SetScreenPowerStatus POWER_STATUS_ON: " BPUBU64 "", id);
165             interface.SetScreenPowerStatus(id, Rosen::ScreenPowerStatus::POWER_STATUS_ON);
166         }
167     } else if (interface.GetScreenPowerStatus(id) != Rosen::ScreenPowerStatus::POWER_STATUS_ON) {
168         interface.SetScreenPowerStatus(id, Rosen::ScreenPowerStatus::POWER_STATUS_ON);
169     }
170 
171     runner_ = AppExecFwk::EventRunner::Create(false);
172     mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
173     mainHandler_->PostTask(std::bind(&BootAnimation::Init, this, id, screenWidth, screenHeight));
174     LOGI("PostTask Init");
175 #ifdef PLAYER_FRAMEWORK_ENABLE
176     if (animationConfig_.IsBootVideoEnabled()) {
177         mainHandler_->PostTask(std::bind(&BootAnimation::PlayVideo, this));
178         LOGI("PostTask PlayVideo");
179     } else {
180         mainHandler_->PostTask(std::bind(&BootAnimation::PlaySound, this));
181         LOGI("PostTask PlaySound");
182     }
183 #else
184     LOGI("player_framework part is not enabled.");
185 #endif
186     runner_->Run();
187 }
188 
InitRsSurfaceNode()189 void BootAnimation::InitRsSurfaceNode()
190 {
191     LOGI("Init RsSurfaceNode enter");
192     struct Rosen::RSSurfaceNodeConfig rsSurfaceNodeConfig;
193     rsSurfaceNodeConfig.SurfaceNodeName = "BootAnimationNode";
194     rsSurfaceNodeConfig.isSync = true;
195     Rosen::RSSurfaceNodeType rsSurfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
196     rsSurfaceNode_ = Rosen::RSSurfaceNode::Create(rsSurfaceNodeConfig, rsSurfaceNodeType);
197     if (!rsSurfaceNode_) {
198         LOGE("rsSurfaceNode_ is nullptr");
199         return;
200     }
201     int32_t rotateScreenId = animationConfig_.GetRotateScreenId();
202     if (rotateScreenId >= 0 && (Rosen::ScreenId)rotateScreenId == defaultId_) {
203         LOGI("SurfaceNode set rotation degree: %{public}d", animationConfig_.GetRotateDegree());
204         rsSurfaceNode_->SetRotation(animationConfig_.GetRotateDegree());
205     }
206     rsSurfaceNode_->SetPositionZ(MAX_ZORDER);
207     rsSurfaceNode_->SetBounds({0, 0, windowWidth_, windowHeight_});
208     rsSurfaceNode_->SetBackgroundColor(0xFF000000);
209     rsSurfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT);
210     rsSurfaceNode_->SetBootAnimation(true);
211     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
212     rsSurfaceNode_->AttachToDisplay(defaultId_);
213     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
214     system::SetParameter("bootevent.bootanimation.ready", "true");
215     LOGI("Set bootevent.bootanimation.ready true");
216 }
217 
InitRsSurface()218 void BootAnimation::InitRsSurface()
219 {
220     LOGI("InitRsSurface");
221 #if defined(NEW_RENDER_CONTEXT)
222     renderContext_ = Rosen::RenderContextBaseFactory::CreateRenderContext();
223     if (renderContext_ == nullptr) {
224         LOGE("Create Render Context failed");
225         return;
226     }
227     renderContext_->Init();
228     std::shared_ptr<Rosen::DrawingContext> drawingContext = std::make_shared<Rosen::DrawingContext>(
229         renderContext_->GetRenderType());
230     sptr<Surface> surface = rsSurfaceNode_->GetSurface();
231     drawingContext->SetUpDrawingContext();
232     rsSurface_ = Rosen::RSSurfaceFactory::CreateRSSurface(Rosen::PlatformName::OHOS, surface, drawingContext);
233     rsSurface_->SetRenderContext(renderContext_);
234 #else
235     rsSurface_ = OHOS::Rosen::RSSurfaceExtractor::ExtractRSSurface(rsSurfaceNode_);
236     if (rsSurface_ == nullptr) {
237         LOGE("rsSurface is nullptr");
238         return;
239     }
240 #ifdef ACE_ENABLE_GL
241     if (Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::OPENGL) {
242         rc_ = OHOS::Rosen::RenderContextFactory::GetInstance().CreateEngine();
243         if (rc_ == nullptr) {
244             LOGE("InitilizeEglContext failed");
245             return;
246         } else {
247             LOGI("init egl context");
248             rc_->InitializeEglContext();
249             rsSurface_->SetRenderContext(rc_);
250         }
251     }
252 #endif // ACE_ENABLE_GL
253     if (rc_ == nullptr) {
254         LOGI("rc is nullptr, use cpu");
255     }
256 #endif
257 }
258 
~BootAnimation()259 BootAnimation::~BootAnimation()
260 {
261     if (rsSurfaceNode_) {
262         rsSurfaceNode_->DetachToDisplay(defaultId_);
263     }
264     if (rsDisplayNode_) {
265         rsDisplayNode_->RemoveFromTree();
266     }
267     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
268 }
269 
InitPicCoordinates()270 void BootAnimation::InitPicCoordinates()
271 {
272     if (windowWidth_ >= windowHeight_) {
273         realHeight_ = windowHeight_;
274         realWidth_ = realHeight_;
275         pointX_ = (windowWidth_ - realWidth_) / HALF_NUM;
276     } else {
277         realWidth_ = windowWidth_;
278         realHeight_ = realWidth_;
279         pointY_ = (windowHeight_ - realHeight_) / HALF_NUM;
280     }
281 }
282 
OnVsync()283 void BootAnimation::OnVsync()
284 {
285     PostTask(std::bind(&BootAnimation::Draw, this));
286 }
287 
CheckExitAnimation()288 bool BootAnimation::CheckExitAnimation()
289 {
290     if (!isAnimationEnd_) {
291         LOGI("Boot animation is end");
292         system::SetParameter("bootevent.bootanimation.finished", "true");
293         isAnimationEnd_ = true;
294     }
295     std::string bootEventCompleted = system::GetParameter("bootevent.boot.completed", "false");
296     if (bootEventCompleted == "true") {
297         mainHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
298         LOGI("Read bootevent.boot.completed is true");
299         return true;
300     }
301     return false;
302 }
303 
304 #ifdef PLAYER_FRAMEWORK_ENABLE
PlaySound()305 void BootAnimation::PlaySound()
306 {
307     LOGI("PlaySound start");
308     bool bootSoundEnabled = BootAnimationUtils::GetBootAnimationSoundEnabled();
309     if (bootSoundEnabled == true) {
310         LOGI("PlaySound read bootSoundEnabled is true");
311         if (soundPlayer_ == nullptr) {
312             soundPlayer_ = Media::PlayerFactory::CreatePlayer();
313         }
314         std::string uri = animationConfig_.GetSoundUrl();
315         soundPlayer_->SetSource(uri);
316         soundPlayer_->SetLooping(false);
317         soundPlayer_->PrepareAsync();
318         soundPlayer_->Play();
319     }
320     LOGI("PlaySound end");
321 }
322 #endif
323 
324 #ifdef PLAYER_FRAMEWORK_ENABLE
PlayVideo()325 void BootAnimation::PlayVideo()
326 {
327     LOGI("PlayVideo start w:%{public}d h:%{public}d", windowWidth_, windowHeight_);
328     if (!animationConfig_.IsBootVideoEnabled()) {
329         return;
330     }
331     fcb_ = {
332         .userData_ = this,
333         .callback_ = std::bind(&BootAnimation::CloseVideoPlayer, this),
334     };
335     LOGI("PlayVideo setVideo screenId:%{public}d", (int32_t)defaultId_);
336     bootVideoPlayer_ = std::make_shared<BootVideoPlayer>();
337     bootVideoPlayer_->SetVideoPath(
338         defaultId_ == 0 ? animationConfig_.GetBootVideoPath() : animationConfig_.GetBootExtraVideoPath());
339     bootVideoPlayer_->SetPlayerSurface(rsSurfaceNode_ ? rsSurfaceNode_->GetSurface() : nullptr);
340     bootVideoPlayer_->SetCallback(&fcb_);
341     if (!bootVideoPlayer_->PlayVideo()) {
342         LOGE("Play video failed.");
343         CloseVideoPlayer();
344     }
345 }
346 #endif
347 
348 #ifdef PLAYER_FRAMEWORK_ENABLE
CloseVideoPlayer()349 void BootAnimation::CloseVideoPlayer()
350 {
351     LOGI("Close video player.");
352     while (!CheckExitAnimation()) {
353         usleep(SLEEP_TIME_US);
354     }
355     LOGI("Check Exit Animation end.");
356 }
357 #endif
358 
InitRsDisplayNode()359 void BootAnimation::InitRsDisplayNode()
360 {
361     OHOS::Rosen::RSDisplayNodeConfig config = {defaultId_, false, 0};
362 
363     rsDisplayNode_ = OHOS::Rosen::RSDisplayNode::Create(config);
364     if (rsDisplayNode_ == nullptr) {
365         LOGE("Failed to init display node!");
366         return;
367     }
368     rsDisplayNode_->SetDisplayOffset(0, 0);
369     rsDisplayNode_->SetFrame(0, 0, windowWidth_, windowHeight_);
370     rsDisplayNode_->SetBounds(0, 0, windowWidth_, windowHeight_);
371     rsDisplayNode_->SetBootAnimation(true);
372     // flush transaction
373     auto transactionProxy = OHOS::Rosen::RSTransactionProxy::GetInstance();
374     if (transactionProxy != nullptr) {
375         transactionProxy->FlushImplicitTransaction();
376     }
377     LOGD("InitRsDisplayNode success");
378 }