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 #include "boot_picture_player.h"
16
17 #include "event_handler.h"
18 #include "log.h"
19 #include "rs_trace.h"
20 #include "transaction/rs_interfaces.h"
21
22 namespace OHOS {
23 namespace {
24 const std::string BOOT_PIC_ZIP = "/system/etc/graphic/bootpic.zip";
25 }
26
BootPicturePlayer(const PlayerParams & params)27 BootPicturePlayer::BootPicturePlayer(const PlayerParams& params)
28 {
29 resPath_ = params.resPath;
30 rsSurface_ = params.rsSurface;
31 InitPicCoordinates(params.screenId);
32 }
33
Play()34 void BootPicturePlayer::Play()
35 {
36 auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
37 int waitVsyncReceiverCreateTime = 0;
38 while (receiver_ == nullptr && waitVsyncReceiverCreateTime < MAX_WAIT_VSYNCRECEIVER_CREATE_TIME) {
39 LOGI("receiver is nullptr, try create again");
40 receiver_ = rsClient.CreateVSyncReceiver("BootAnimation", AppExecFwk::EventHandler::Current());
41 usleep(SLEEP_TIME_US);
42 waitVsyncReceiverCreateTime += SLEEP_TIME_US;
43 }
44
45 if (receiver_ == nullptr) {
46 LOGI("receiver create fail");
47 Stop();
48 return;
49 }
50
51 VsyncError ret = receiver_->Init();
52 if (ret) {
53 LOGE("vsync receiver init failed: %{public}d", ret);
54 Stop();
55 return;
56 }
57
58 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::preload");
59 if (ReadPicZipFile(imageVector_, freq_)) {
60 imgVecSize_ = static_cast<int32_t> (imageVector_.size());
61 } else {
62 LOGE("read pic zip failed");
63 Stop();
64 return;
65 }
66 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
67
68 OHOS::Rosen::VSyncReceiver::FrameCallback fcb = {
69 .userData_ = this,
70 .callback_ = [this](int64_t, void*) { this->OnVsync(); },
71 };
72 int32_t changeFreq = static_cast<int32_t> (1000.0 / freq_ / 16);
73 ret = receiver_->SetVSyncRate(fcb, changeFreq);
74 if (ret) {
75 LOGE("SetVSyncRate failed: %{public}d %{public}d", ret, freq_);
76 Stop();
77 return;
78 } else {
79 LOGI("SetVSyncRate success: %{public}d, %{public}d", freq_, changeFreq);
80 }
81 }
82
InitPicCoordinates(Rosen::ScreenId screenId)83 void BootPicturePlayer::InitPicCoordinates(Rosen::ScreenId screenId)
84 {
85 Rosen::RSInterfaces& interface = Rosen::RSInterfaces::GetInstance();
86 Rosen::RSScreenModeInfo modeinfo = interface.GetScreenActiveMode(screenId);
87 windowWidth_ = modeinfo.GetScreenWidth();
88 windowHeight_ = modeinfo.GetScreenHeight();
89 if (windowWidth_ >= windowHeight_) {
90 realHeight_ = windowHeight_;
91 realWidth_ = realHeight_;
92 pointX_ = (windowWidth_ - realWidth_) / NUMBER_TWO;
93 } else {
94 realWidth_ = windowWidth_;
95 realHeight_ = realWidth_;
96 pointY_ = (windowHeight_ - realHeight_) / NUMBER_TWO;
97 }
98 }
99
ReadPicZipFile(ImageStructVec & imgVec,int32_t & freq)100 bool BootPicturePlayer::ReadPicZipFile(ImageStructVec& imgVec, int32_t& freq)
101 {
102 FrameRateConfig frameConfig;
103 ReadZipFile(GetPicZipPath(), imgVec, frameConfig);
104 int32_t imageNum = static_cast<int32_t>(imgVec.size());
105 if (imageNum < 0) {
106 LOGE("zip pic num is invalid.");
107 return false;
108 }
109
110 SortZipFile(imgVec);
111
112 if (CheckFrameRateValid(frameConfig.frameRate)) {
113 freq = frameConfig.frameRate;
114 } else {
115 LOGW("Only Support 30, 60 frame rate: %{public}d", frameConfig.frameRate);
116 }
117 LOGI("read freq: %{public}d, pic num: %{public}d", freq, imageNum);
118 return true;
119 }
120
GetPicZipPath()121 std::string BootPicturePlayer::GetPicZipPath()
122 {
123 if (!IsFileExisted(resPath_)) {
124 LOGI("pic zip path empty or not exist, use default path");
125 return BOOT_PIC_ZIP;
126 }
127 return resPath_;
128 }
129
CheckFrameRateValid(int32_t frameRate)130 bool BootPicturePlayer::CheckFrameRateValid(int32_t frameRate)
131 {
132 std::vector<int> freqs = {60, 30};
133 int nCount = std::count(freqs.begin(), freqs.end(), frameRate);
134 return nCount > 0;
135 }
136
OnVsync()137 void BootPicturePlayer::OnVsync()
138 {
139 PostTask([this] { this->Draw(); });
140 }
141
Draw()142 bool BootPicturePlayer::Draw()
143 {
144 if (picCurNo_ >= (imgVecSize_ - 1)) {
145 LOGI("play sequence frames end");
146 Stop();
147 return false;
148 }
149 picCurNo_ = picCurNo_ + 1;
150 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw RequestFrame");
151 auto frame = rsSurface_->RequestFrame(windowWidth_, windowHeight_);
152 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
153 if (frame == nullptr) {
154 LOGE("draw frame is nullptr");
155 Stop();
156 return false;
157 }
158 rsSurfaceFrame_ = std::move(frame);
159 auto canvas = rsSurfaceFrame_->GetCanvas();
160 OnDraw(canvas, picCurNo_);
161 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");
162 rsSurface_->FlushFrame(rsSurfaceFrame_);
163 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
164 return true;
165 }
166
OnDraw(Rosen::Drawing::CoreCanvas * canvas,int32_t curNo)167 bool BootPicturePlayer::OnDraw(Rosen::Drawing::CoreCanvas* canvas, int32_t curNo)
168 {
169 if (canvas == nullptr) {
170 LOGE("OnDraw canvas is nullptr");
171 Stop();
172 return false;
173 }
174 if (curNo > (imgVecSize_ - 1) || curNo < 0) {
175 Stop();
176 return false;
177 }
178 std::shared_ptr<ImageStruct> imgstruct = imageVector_[curNo];
179 std::shared_ptr<Rosen::Drawing::Image> image = imgstruct->imageData;
180
181 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawRect");
182 Rosen::Drawing::Brush brush;
183 brush.SetColor(Rosen::Drawing::Color::COLOR_BLACK);
184 Rosen::Drawing::Rect bgRect(0.0, 0.0, windowWidth_, windowHeight_);
185 canvas->AttachBrush(brush);
186 canvas->DrawRect(bgRect);
187 canvas->DetachBrush();
188 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
189 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawImageRect");
190 Rosen::Drawing::Rect rect(pointX_, pointY_, pointX_ + realWidth_, pointY_ + realHeight_);
191 Rosen::Drawing::SamplingOptions samplingOptions;
192 canvas->DrawImageRect(*image, rect, samplingOptions);
193 imageVector_[curNo].reset();
194 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
195 return true;
196 }
197
Stop()198 bool BootPicturePlayer::Stop()
199 {
200 auto runner = AppExecFwk::EventRunner::Current();
201 if (runner == nullptr) {
202 LOGE("runner is null");
203 return false;
204 }
205 runner->Stop();
206 return true;
207 }
208 } // namespace OHOS
209