• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
21 using namespace OHOS;
22 static const std::string BOOT_PIC_ZIP = "/system/etc/init/bootpic.zip";
23 static const std::string BOOT_SOUND_URI = "file://system/etc/init/bootsound.wav";
24 
25 
OnDraw(SkCanvas * canvas,int32_t curNo)26 void BootAnimation::OnDraw(SkCanvas* canvas, int32_t curNo)
27 {
28     if (canvas == nullptr) {
29         LOGE("OnDraw canvas is nullptr");
30         return;
31     }
32     if (curNo > (imgVecSize_ - 1) || curNo < 0) {
33         return;
34     }
35     std::shared_ptr<ImageStruct> imgstruct = imageVector_[curNo];
36     sk_sp<SkImage> image = imgstruct->imageData;
37 
38     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawRect");
39     SkPaint backPaint;
40     backPaint.setColor(SK_ColorBLACK);
41     canvas->drawRect(SkRect::MakeXYWH(0.0, 0.0, windowWidth_, windowHeight_), backPaint);
42     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
43     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawImageRect");
44     SkPaint paint;
45     SkRect rect;
46     rect.setXYWH(pointX_, pointY_, realWidth_, realHeight_);
47     canvas->drawImageRect(image.get(), rect, &paint);
48     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
49 }
50 
Draw()51 void BootAnimation::Draw()
52 {
53     if (picCurNo_ < (imgVecSize_ - 1)) {
54         picCurNo_ = picCurNo_ + 1;
55     } else {
56         CheckExitAnimation();
57         return;
58     }
59     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw RequestFrame");
60     auto frame = rsSurface_->RequestFrame(windowWidth_, windowHeight_);
61     if (frame == nullptr) {
62         LOGE("Draw frame is nullptr");
63         return;
64     }
65     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
66     framePtr_ = std::move(frame);
67     auto canvas = framePtr_->GetCanvas();
68     OnDraw(canvas, picCurNo_);
69     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");
70     rsSurface_->FlushFrame(framePtr_);
71     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
72 }
73 
CheckFrameRateValid(int32_t ratevalue)74 bool BootAnimation::CheckFrameRateValid(int32_t ratevalue)
75 {
76     std::vector<int> freqs = {60, 30};
77     int nCount = std::count(freqs.begin(), freqs.end(), ratevalue);
78     if (nCount <= 0) {
79         return false;
80     }
81     return true;
82 }
83 
Init(int32_t width,int32_t height)84 void BootAnimation::Init(int32_t width, int32_t height)
85 {
86     windowWidth_ = width;
87     windowHeight_ = height;
88     LOGI("Init enter, width: %{public}d, height: %{public}d", width, height);
89 
90     auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
91     while (receiver_ == nullptr) {
92         receiver_ = rsClient.CreateVSyncReceiver("BootAnimation", mainHandler_);
93     }
94     VsyncError ret = receiver_->Init();
95     if (ret) {
96         LOGE("vsync receiver init failed: %{public}d", ret);
97         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
98         return;
99     }
100 
101     InitBootWindow();
102     InitRsSurface();
103     InitPicCoordinates();
104     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::preload");
105     BootAniConfig jsonConfig;
106     ReadZipFile(BOOT_PIC_ZIP, imageVector_, jsonConfig);
107     imgVecSize_ = static_cast<int32_t>(imageVector_.size());
108     if (imgVecSize_ <= 0) {
109         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
110         LOGE("zip pic num is 0.");
111         return;
112     }
113     SortZipFile(imageVector_);
114     if (CheckFrameRateValid(jsonConfig.frameRate)) {
115         freq_ = jsonConfig.frameRate;
116     } else {
117         LOGI("Only Support 30, 60 frame rate: %{public}d", jsonConfig.frameRate);
118     }
119     LOGI("end to Readzip pics freq: %{public}d totalPicNum: %{public}d", freq_, imgVecSize_);
120     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
121 
122     OHOS::Rosen::VSyncReceiver::FrameCallback fcb = {
123         .userData_ = this,
124         .callback_ = std::bind(&BootAnimation::OnVsync, this),
125     };
126     int32_t changefreq = static_cast<int32_t>((1000.0 / freq_) / 16);
127     ret = receiver_->SetVSyncRate(fcb, changefreq);
128     if (ret) {
129         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
130         LOGE("SetVSyncRate failed: %{public}d %{public}d %{public}d", ret, freq_, changefreq);
131         return;
132     } else {
133         LOGI("SetVSyncRate success: %{public}d %{public}d", freq_, changefreq);
134     }
135 }
136 
Run(std::vector<sptr<OHOS::Rosen::Display>> & displays)137 void BootAnimation::Run(std::vector<sptr<OHOS::Rosen::Display>>& displays)
138 {
139     runner_ = AppExecFwk::EventRunner::Create(false);
140     mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
141     mainHandler_->PostTask(std::bind(&BootAnimation::Init, this, displays[0]->GetWidth(), displays[0]->GetHeight()));
142     mainHandler_->PostTask(std::bind(&BootAnimation::PlaySound, this));
143     runner_->Run();
144 }
145 
InitBootWindow()146 void BootAnimation::InitBootWindow()
147 {
148     sptr<OHOS::Rosen::WindowOption> option = new OHOS::Rosen::WindowOption();
149     option->SetWindowType(OHOS::Rosen::WindowType::WINDOW_TYPE_BOOT_ANIMATION);
150     option->RemoveWindowFlag(OHOS::Rosen::WindowFlag::WINDOW_FLAG_NEED_AVOID);
151     option->SetWindowRect({0, 0, windowWidth_, windowHeight_} );
152     option->SetTouchable(false);
153     int displayId = 0;
154     sptr<OHOS::Rosen::IWindowLifeCycle> listener = nullptr;
155     scene_ = new OHOS::Rosen::WindowScene();
156     scene_->Init(displayId, nullptr, listener, option);
157     window_ = scene_->GetMainWindow();
158     while (window_ == nullptr) {
159         LOGI("window is nullptr, continue to init window");
160         scene_->Init(displayId, nullptr, listener, option);
161         window_ = scene_->GetMainWindow();
162         sleep(1);
163     }
164     scene_->GoForeground();
165 }
166 
InitRsSurface()167 void BootAnimation::InitRsSurface()
168 {
169     rsSurface_ = OHOS::Rosen::RSSurfaceExtractor::ExtractRSSurface(window_->GetSurfaceNode());
170     if (rsSurface_ == nullptr) {
171         LOGE("rsSurface is nullptr");
172         return;
173     }
174 #ifdef ACE_ENABLE_GL
175     rc_ = OHOS::Rosen::RenderContextFactory::GetInstance().CreateEngine();
176     if (rc_ == nullptr) {
177         LOGE("InitilizeEglContext failed");
178         return;
179     } else {
180         LOGI("init egl context");
181         rc_->InitializeEglContext();
182         rsSurface_->SetRenderContext(rc_);
183     }
184 #endif
185     if (rc_ == nullptr) {
186         LOGI("rc is nullptr, use cpu");
187     }
188 }
189 
~BootAnimation()190 BootAnimation::~BootAnimation()
191 {
192     window_->Destroy();
193 }
194 
InitPicCoordinates()195 void BootAnimation::InitPicCoordinates()
196 {
197     if (windowWidth_ >= windowHeight_) {
198         realHeight_ = windowHeight_;
199         realWidth_ = realHeight_;
200         pointX_ = (windowWidth_ - realWidth_) / 2;
201     } else {
202         realWidth_ = windowWidth_;
203         realHeight_ = realWidth_;
204         pointY_ = (windowHeight_ - realHeight_) / 2;
205     }
206 }
207 
OnVsync()208 void BootAnimation::OnVsync()
209 {
210     PostTask(std::bind(&BootAnimation::Draw, this));
211 }
212 
CheckExitAnimation()213 void BootAnimation::CheckExitAnimation()
214 {
215     LOGI("CheckExitAnimation enter");
216     if (!setBootEvent_) {
217         LOGI("CheckExitAnimation set bootevent parameter");
218         system::SetParameter("bootevent.bootanimation.started", "true");
219         setBootEvent_ = true;
220     }
221     std::string windowInit = system::GetParameter("bootevent.boot.completed", "false");
222     if (windowInit == "true") {
223         PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));
224         LOGI("CheckExitAnimation read windowInit is true");
225         return;
226     }
227 }
228 
PlaySound()229 void BootAnimation::PlaySound()
230 {
231     LOGI("PlaySound start");
232     bool bootSoundEnabled = system::GetBoolParameter("persist.graphic.bootsound.enabled", true);
233     if (bootSoundEnabled == true) {
234         LOGI("PlaySound read bootSoundEnabled is true");
235         if (soundPlayer_ == nullptr) {
236             soundPlayer_ = Media::PlayerFactory::CreatePlayer();
237         }
238         std::string uri = BOOT_SOUND_URI;
239         soundPlayer_->SetSource(uri);
240         soundPlayer_->SetLooping(false);
241         soundPlayer_->PrepareAsync();
242         soundPlayer_->Play();
243     }
244     LOGI("PlaySound end");
245 }
246