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 OHOS::Rosen::RSSystemProperties::SetTypicalResidentProcess(true);
47 currentScreenId_ = config.screenId;
48 windowWidth_ = width;
49 windowHeight_ = height;
50 duration_ = duration * DELAY_TIME_MS;
51
52 eventThread_ = std::thread([this, &config] { this->StartEventHandler(config); });
53 }
54
StartEventHandler(const BootAnimationConfig & config)55 void BootAnimationOperation::StartEventHandler(const BootAnimationConfig& config)
56 {
57 LOGI("StartEventHandler");
58 runner_ = AppExecFwk::EventRunner::Create(false);
59 mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
60 mainHandler_->PostTask([this] { this->InitRsDisplayNode(); });
61 mainHandler_->PostTask([this, &config] { this->InitRsSurfaceNode(config.rotateDegree); });
62 mainHandler_->PostTask([this] { this->StopBootAnimation(); }, duration_);
63 #ifdef PLAYER_FRAMEWORK_ENABLE
64 if (IsBootVideoEnabled(config)) {
65 mainHandler_->PostTask([this, &config] { this->PlayVideo(config.videoDefaultPath); });
66 runner_->Run();
67 LOGI("runner run has ended.");
68 return;
69 } else {
70 mainHandler_->PostTask([this, &config] { this->PlaySound(config.soundPath); });
71 }
72 #else
73 LOGI("player framework is disabled");
74 #endif
75 mainHandler_->PostTask([this, &config] { this->PlayPicture(config.picZipPath); });
76 runner_->Run();
77 LOGI("runner run has ended.");
78 }
79
SetSoundEnable(bool isEnabled)80 void BootAnimationOperation::SetSoundEnable(bool isEnabled)
81 {
82 isSoundEnabled_ = isEnabled;
83 }
84
GetThread()85 std::thread& BootAnimationOperation::GetThread()
86 {
87 return eventThread_;
88 }
89
InitRsDisplayNode()90 bool BootAnimationOperation::InitRsDisplayNode()
91 {
92 LOGI("InitRsDisplayNode start");
93 OHOS::Rosen::RSDisplayNodeConfig config = { currentScreenId_ };
94 rsUIDirector_ = OHOS::Rosen::RSUIDirector::Create();
95 rsUIDirector_->Init(false, false);
96 auto rsUIContext = rsUIDirector_->GetRSUIContext();
97 rsDisplayNode_ = OHOS::Rosen::RSDisplayNode::Create(config, rsUIContext);
98 if (rsDisplayNode_ == nullptr) {
99 LOGE("init display node failed");
100 return false;
101 }
102 rsDisplayNode_->SetFrame(0, 0, windowWidth_, windowHeight_);
103 rsDisplayNode_->SetBounds(0, 0, windowWidth_, windowHeight_);
104 rsDisplayNode_->SetBootAnimation(true);
105 rsDisplayNode_->SetBackgroundColor(0xFF000000);
106 if (rsUIContext != nullptr) {
107 auto transaction = rsUIContext->GetRSTransaction();
108 if (transaction == nullptr) {
109 LOGE("transaction is nullptr");
110 return false;
111 }
112 transaction->FlushImplicitTransaction();
113 } else {
114 auto transactionProxy = OHOS::Rosen::RSTransactionProxy::GetInstance();
115 if (transactionProxy == nullptr) {
116 LOGE("transactionProxy is nullptr");
117 return false;
118 }
119 transactionProxy->FlushImplicitTransaction();
120 }
121 return true;
122 }
123
InitRsSurfaceNode(int32_t degree)124 bool BootAnimationOperation::InitRsSurfaceNode(int32_t degree)
125 {
126 LOGI("InitRsSurfaceNode start");
127 struct Rosen::RSSurfaceNodeConfig rsSurfaceNodeConfig;
128 rsSurfaceNodeConfig.SurfaceNodeName =
129 currentScreenId_ == 0 ? "BootAnimationNode" : "BootAnimationNodeExtra";
130 rsSurfaceNodeConfig.isSync = false;
131 Rosen::RSSurfaceNodeType rsSurfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
132 auto rsUIContext = rsUIDirector_->GetRSUIContext();
133 rsSurfaceNode_ = Rosen::RSSurfaceNode::Create(rsSurfaceNodeConfig, rsSurfaceNodeType, true, false, rsUIContext);
134 if (!rsSurfaceNode_) {
135 LOGE("create rsSurfaceNode failed");
136 return false;
137 }
138 LOGI("rotation degree: %{public}d", degree);
139 rsSurfaceNode_->SetRotation(degree);
140 rsSurfaceNode_->SetPositionZ(MAX_ZORDER);
141 rsSurfaceNode_->SetBounds({0, 0, windowWidth_, windowHeight_});
142 rsSurfaceNode_->SetBackgroundColor(0xFF000000);
143 rsSurfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT);
144 rsSurfaceNode_->SetBootAnimation(true);
145 OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
146 rsSurfaceNode_->AttachToDisplay(currentScreenId_);
147 OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
148 if (!system::GetBoolParameter(BOOT_ANIMATION_READY, false)) {
149 system::SetParameter(BOOT_ANIMATION_READY, "true");
150 LOGI("set boot animation ready true");
151 }
152 return true;
153 }
154
PlayVideo(const std::string & path)155 void BootAnimationOperation::PlayVideo(const std::string& path)
156 {
157 LOGI("boot animation play video");
158 PlayerParams params;
159 #ifdef PLAYER_FRAMEWORK_ENABLE
160 params.surface = rsSurfaceNode_ ? rsSurfaceNode_->GetSurface() : nullptr;
161 #endif
162 params.resPath = path;
163 callback_ = {
164 .userData = this,
165 .callback = [this](void*) { this->StopBootAnimation(); },
166 };
167 params.callback = &callback_;
168 params.screenId = currentScreenId_;
169 params.soundEnabled = isSoundEnabled_;
170 videoPlayer_ = std::make_shared<BootVideoPlayer>(params);
171 videoPlayer_->Play();
172 }
173
PlayPicture(const std::string & path)174 void BootAnimationOperation::PlayPicture(const std::string& path)
175 {
176 LOGI("boot animation play sequence frames");
177 if (!system::GetBoolParameter(BOOT_ANIMATION_STARTED, false)) {
178 system::SetParameter(BOOT_ANIMATION_STARTED, "true");
179 LOGI("set boot animation started true");
180 }
181
182 if (!InitRsSurface()) {
183 runner_->Stop();
184 return;
185 }
186 PlayerParams params;
187 params.screenId = currentScreenId_;
188 params.rsSurface = rsSurface_;
189 params.resPath = path;
190 picPlayer_ = std::make_shared<BootPicturePlayer>(params);
191 picPlayer_->Play();
192 }
193
PlaySound(const std::string & path)194 void BootAnimationOperation::PlaySound(const std::string& path)
195 {
196 LOGI("boot animation play sound");
197 PlayerParams params;
198 params.resPath = path;
199 params.screenId = currentScreenId_;
200 params.soundEnabled = isSoundEnabled_;
201 soundPlayer_ = std::make_shared<BootSoundPlayer>(params);
202 soundPlayer_->Play();
203 }
204
InitRsSurface()205 bool BootAnimationOperation::InitRsSurface()
206 {
207 LOGI("InitRsSurface start");
208 rsSurface_ = OHOS::Rosen::RSSurfaceExtractor::ExtractRSSurface(rsSurfaceNode_);
209 if (rsSurface_ == nullptr) {
210 LOGE("rsSurface is nullptr");
211 return false;
212 }
213 #ifdef ACE_ENABLE_GL
214 LOGI("init egl context start");
215 if (Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::OPENGL) {
216 OHOS::Rosen::RenderContext* rc = OHOS::Rosen::RenderContextFactory::GetInstance().CreateEngine();
217 if (rc == nullptr) {
218 LOGE("init egl context failed");
219 return false;
220 } else {
221 LOGI("init egl context success");
222 rc->InitializeEglContext();
223 rsSurface_->SetRenderContext(rc);
224 }
225 }
226 #endif // ACE_ENABLE_GL
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