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 
16 #include "boot_animation_operation.h"
17 
18 #include "boot_picture_player.h"
19 #include "boot_sound_player.h"
20 #include "boot_video_player.h"
21 #include "log.h"
22 #include <parameters.h>
23 #include "platform/common/rs_system_properties.h"
24 #include "transaction/rs_transaction.h"
25 #include "transaction/rs_interfaces.h"
26 
27 using namespace OHOS;
28 static const int DELAY_TIME_MS = 1000;
29 
~BootAnimationOperation()30 BootAnimationOperation::~BootAnimationOperation()
31 {
32     if (rsSurfaceNode_) {
33         rsSurfaceNode_->DetachToDisplay(currentScreenId_);
34     }
35     if (rsDisplayNode_) {
36         rsDisplayNode_->RemoveFromTree();
37     }
38     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
39     LOGI("Release RsNode");
40 }
41 
Init(const BootAnimationConfig & config,int32_t width,int32_t height,int32_t duration)42 void BootAnimationOperation::Init(const BootAnimationConfig& config, int32_t width, int32_t height, int32_t duration)
43 {
44     LOGI("Init enter, width: %{public}d, height: %{public}d, screenId : " BPUBU64 "", width, height, config.screenId);
45     currentScreenId_ = config.screenId;
46     windowWidth_ = width;
47     windowHeight_ = height;
48     duration_ = duration * DELAY_TIME_MS;
49 
50     eventThread_ = std::thread([this, &config] { this->StartEventHandler(config); });
51 }
52 
StartEventHandler(const BootAnimationConfig & config)53 void BootAnimationOperation::StartEventHandler(const BootAnimationConfig& config)
54 {
55     LOGI("StartEventHandler");
56     runner_ = AppExecFwk::EventRunner::Create(false);
57     mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
58     mainHandler_->PostTask([this] { this->InitRsDisplayNode(); });
59     mainHandler_->PostTask([this, &config] { this->InitRsSurfaceNode(config.rotateDegree); });
60     mainHandler_->PostTask([this] { this->StopBootAnimation(); }, duration_);
61 #ifdef PLAYER_FRAMEWORK_ENABLE
62     if (IsBootVideoEnabled(config)) {
63         mainHandler_->PostTask([this, &config] { this->PlayVideo(config.videoDefaultPath); });
64         runner_->Run();
65         LOGI("runner run has ended.");
66         return;
67     } else {
68         mainHandler_->PostTask([this, &config] { this->PlaySound(config.soundPath); });
69     }
70 #else
71     LOGI("player framework is disabled");
72 #endif
73     mainHandler_->PostTask([this, &config] { this->PlayPicture(config.picZipPath); });
74     runner_->Run();
75     LOGI("runner run has ended.");
76 }
77 
SetSoundEnable(bool isEnabled)78 void BootAnimationOperation::SetSoundEnable(bool isEnabled)
79 {
80     isSoundEnabled_ = isEnabled;
81 }
82 
GetThread()83 std::thread& BootAnimationOperation::GetThread()
84 {
85     return eventThread_;
86 }
87 
InitRsDisplayNode()88 bool BootAnimationOperation::InitRsDisplayNode()
89 {
90     LOGI("InitRsDisplayNode start");
91     OHOS::Rosen::RSDisplayNodeConfig config = {currentScreenId_, false, 0};
92 
93     rsDisplayNode_ = OHOS::Rosen::RSDisplayNode::Create(config);
94     if (rsDisplayNode_ == nullptr) {
95         LOGE("init display node failed");
96         return false;
97     }
98     rsDisplayNode_->SetDisplayOffset(0, 0);
99     rsDisplayNode_->SetFrame(0, 0, windowWidth_, windowHeight_);
100     rsDisplayNode_->SetBounds(0, 0, windowWidth_, windowHeight_);
101     rsDisplayNode_->SetBootAnimation(true);
102     // flush transaction
103     auto transactionProxy = OHOS::Rosen::RSTransactionProxy::GetInstance();
104     if (transactionProxy == nullptr) {
105         LOGE("transactionProxy is nullptr");
106         return false;
107     }
108     transactionProxy->FlushImplicitTransaction();
109     return true;
110 }
111 
InitRsSurfaceNode(int32_t degree)112 bool BootAnimationOperation::InitRsSurfaceNode(int32_t degree)
113 {
114     LOGI("InitRsSurfaceNode start");
115     struct Rosen::RSSurfaceNodeConfig rsSurfaceNodeConfig;
116     rsSurfaceNodeConfig.SurfaceNodeName =
117         currentScreenId_ == 0 ? "BootAnimationNode" : "BootAnimationNodeExtra";
118     rsSurfaceNodeConfig.isSync = false;
119     Rosen::RSSurfaceNodeType rsSurfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
120     rsSurfaceNode_ = Rosen::RSSurfaceNode::Create(rsSurfaceNodeConfig, rsSurfaceNodeType);
121     if (!rsSurfaceNode_) {
122         LOGE("create rsSurfaceNode failed");
123         return false;
124     }
125     LOGI("rotation degree: %{public}d", degree);
126     rsSurfaceNode_->SetRotation(degree);
127     rsSurfaceNode_->SetPositionZ(MAX_ZORDER);
128     rsSurfaceNode_->SetBounds({0, 0, windowWidth_, windowHeight_});
129     rsSurfaceNode_->SetBackgroundColor(0xFF000000);
130     rsSurfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT);
131     rsSurfaceNode_->SetBootAnimation(true);
132     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
133     rsSurfaceNode_->AttachToDisplay(currentScreenId_);
134     OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
135     if (!system::GetBoolParameter(BOOT_ANIMATION_READY, false)) {
136         system::SetParameter(BOOT_ANIMATION_READY, "true");
137         LOGI("set boot animation ready true");
138     }
139     return true;
140 }
141 
PlayVideo(const std::string & path)142 void BootAnimationOperation::PlayVideo(const std::string& path)
143 {
144     LOGI("boot animation play video");
145     PlayerParams params;
146 #ifdef PLAYER_FRAMEWORK_ENABLE
147     params.surface = rsSurfaceNode_ ? rsSurfaceNode_->GetSurface() : nullptr;
148 #endif
149     params.resPath = path;
150     callback_ = {
151         .userData = this,
152         .callback = [this](void*) { this->StopBootAnimation(); },
153     };
154     params.callback = &callback_;
155     params.screenId = currentScreenId_;
156     params.soundEnabled = isSoundEnabled_;
157     videoPlayer_ = std::make_shared<BootVideoPlayer>(params);
158     videoPlayer_->Play();
159 }
160 
PlayPicture(const std::string & path)161 void BootAnimationOperation::PlayPicture(const std::string& path)
162 {
163     LOGI("boot animation play sequence frames");
164     if (!system::GetBoolParameter(BOOT_ANIMATION_STARTED, false)) {
165         system::SetParameter(BOOT_ANIMATION_STARTED, "true");
166         LOGI("set boot animation started true");
167     }
168 
169     InitRsSurface();
170     PlayerParams params;
171     params.screenId = currentScreenId_;
172     params.rsSurface = rsSurface_;
173     params.resPath = path;
174     picPlayer_ = std::make_shared<BootPicturePlayer>(params);
175     picPlayer_->Play();
176 }
177 
PlaySound(const std::string & path)178 void BootAnimationOperation::PlaySound(const std::string& path)
179 {
180     LOGI("boot animation play sound");
181     PlayerParams params;
182     params.resPath = path;
183     params.screenId = currentScreenId_;
184     params.soundEnabled = isSoundEnabled_;
185     soundPlayer_ = std::make_shared<BootSoundPlayer>(params);
186     soundPlayer_->Play();
187 }
188 
InitRsSurface()189 bool BootAnimationOperation::InitRsSurface()
190 {
191     LOGI("InitRsSurface start");
192 #ifdef NEW_RENDER_CONTEXT
193     std::shared_ptr<OHOS::Rosen::RenderContextBase> renderContext =
194         Rosen::RenderContextBaseFactory::CreateRenderContext();
195     if (renderContext == nullptr) {
196         LOGE("create render context failed");
197         return false;
198     }
199     renderContext->Init();
200     std::shared_ptr<Rosen::DrawingContext> drawingContext = std::make_shared<Rosen::DrawingContext>(
201         renderContext->GetRenderType());
202     sptr<Surface> surface = rsSurfaceNode_->GetSurface();
203     drawingContext->SetUpDrawingContext();
204     rsSurface_ = Rosen::RSSurfaceFactory::CreateRSSurface(Rosen::PlatformName::OHOS, surface, drawingContext);
205     rsSurface_->SetRenderContext(renderContext);
206 #else
207     rsSurface_ = OHOS::Rosen::RSSurfaceExtractor::ExtractRSSurface(rsSurfaceNode_);
208     if (rsSurface_ == nullptr) {
209         LOGE("rsSurface is nullptr");
210         return false;
211     }
212 #ifdef ACE_ENABLE_GL
213     LOGI("init egl context start");
214     if (Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::OPENGL) {
215         OHOS::Rosen::RenderContext* rc = OHOS::Rosen::RenderContextFactory::GetInstance().CreateEngine();
216         if (rc == nullptr) {
217             LOGE("init egl context failed");
218             return false;
219         } else {
220             LOGI("init egl context success");
221             rc->InitializeEglContext();
222             rsSurface_->SetRenderContext(rc);
223         }
224     }
225 #endif // ACE_ENABLE_GL
226 #endif // NEW_RENDER_CONTEXT
227     return true;
228 }
229 
IsBootVideoEnabled(const BootAnimationConfig & config)230 bool BootAnimationOperation::IsBootVideoEnabled(const BootAnimationConfig& config)
231 {
232     if (config.videoDefaultPath.empty() && !config.picZipPath.empty()) {
233         LOGI("video path is empty and picture path is not empty");
234         return false;
235     }
236     return true;
237 }
238 
StopBootAnimation()239 void BootAnimationOperation::StopBootAnimation()
240 {
241     LOGI("StopBootAnimation");
242     if (!system::GetBoolParameter(BOOT_ANIMATION_STARTED, false)) {
243         system::SetParameter(BOOT_ANIMATION_STARTED, "true");
244         LOGI("set boot animation started true");
245     }
246     runner_->Stop();
247     LOGI("runner has called stop.");
248     mainHandler_ = nullptr;
249 }
250