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