1 /*
2 * Copyright (c) 2021 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 "animation_module.h"
17
18 #include <cerrno>
19
20 #include <gslogger.h>
21 #include <scoped_bytrace.h>
22 #include <securec.h>
23
24 namespace OHOS {
25 namespace {
26 DEFINE_HILOG_LABEL("AnimationModule");
27 } // namespace
28
Init()29 GSError AnimationModule::Init()
30 {
31 handler = AppExecFwk::EventHandler::Current();
32 vhelper = VsyncHelper::Current();
33 auto wm = WindowManager::GetInstance();
34 auto option = WindowOption::Get();
35 option->SetWindowType(WINDOW_TYPE_ANIMATION);
36 auto wret = wm->CreateWindow(window, option);
37 if (wret != GSERROR_OK || window == nullptr) {
38 GSLOG2HI(ERROR) << "WindowManager::CreateWindow failed: " << GSErrorStr(wret);
39 return wret;
40 }
41
42 window->Hide();
43 auto producer = window->GetProducer();
44 return GSERROR_OK;
45 }
46
StartRotationAnimation(int32_t did,int32_t degree)47 GSError AnimationModule::StartRotationAnimation(int32_t did, int32_t degree)
48 {
49 if (isAnimationRunning == false) {
50 struct Animation animation {
51 .degree = degree,
52 .retval = new Promise<GSError>(),
53 };
54 handler->PostTask(std::bind(&AnimationModule::StartAnimation, this, std::ref(animation)));
55 return animation.retval->Await();
56 }
57 return GSERROR_ANIMATION_RUNNING;
58 }
59
OnScreenShot(const struct WMImageInfo & info)60 void AnimationModule::OnScreenShot(const struct WMImageInfo &info)
61 {
62 int32_t length = info.size;
63 struct AnimationScreenshotInfo ainfo = {
64 .wmimage = info,
65 .ptr = nullptr,
66 };
67 if (info.wret != GSERROR_OK) {
68 screenshotPromise->Resolve(ainfo);
69 return;
70 }
71
72 ainfo.ptr = std::make_shared<struct Array>();
73 ainfo.ptr->ptr = std::make_unique<uint8_t[]>(length);
74 ainfo.wmimage.data = ainfo.ptr.get();
75 if (memcpy_s(ainfo.ptr->ptr.get(), length, info.data, info.size) != EOK) {
76 GSLOG2HI(ERROR) << "memcpy_s failed: " << strerror(errno);
77 ainfo.wmimage.wret = static_cast<enum GSError>(GSERROR_INTERNAL);
78 screenshotPromise->Resolve(ainfo);
79 return;
80 }
81
82 screenshotPromise->Resolve(ainfo);
83 }
84
StartAnimation(struct Animation & animation)85 void AnimationModule::StartAnimation(struct Animation &animation)
86 {
87 if (isAnimationRunning) {
88 animation.retval->Resolve(GSERROR_ANIMATION_RUNNING);
89 return;
90 }
91
92 ScopedBytrace trace(__func__);
93 isAnimationRunning = true;
94 GSLOG2HI(INFO) << "Animation Start";
95 window->Hide();
96 auto wm = WindowManager::GetInstance();
97 screenshotPromise = new Promise<struct AnimationScreenshotInfo>();
98 wm->ListenNextScreenShot(0, this);
99 auto asinfo = screenshotPromise->Await();
100 if (asinfo.wmimage.wret) {
101 GSLOG2HI(ERROR) << "OnScreenShot failed: " << GSErrorStr(asinfo.wmimage.wret);
102 animation.retval->Resolve(static_cast<enum GSError>(asinfo.wmimage.wret));
103 isAnimationRunning = false;
104 return;
105 }
106
107 window->Show();
108
109 auto sret = eglSurface->InitContext();
110 if (sret != GSERROR_OK) {
111 GSLOG2HI(ERROR) << "EGLSurface InitContext failed: " << sret;
112 animation.retval->Resolve(static_cast<enum GSError>(sret));
113 isAnimationRunning = false;
114 return;
115 }
116
117 ranimation = std::make_unique<RotationAnimation>();
118 constexpr int32_t rotationAnimationDuration = 500;
119 auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
120 std::chrono::steady_clock::now().time_since_epoch()).count();
121 struct RotationAnimationParam param = {
122 .data = asinfo.ptr,
123 .width = window->GetWidth(),
124 .height = window->GetHeight(),
125 .startTime = now,
126 .duration = rotationAnimationDuration,
127 .degree = animation.degree,
128 };
129 auto gret = ranimation->Init(param);
130 if (gret != GSERROR_OK) {
131 GSLOG2HI(ERROR) << "RotationAnimation Init failed: " << GSErrorStr(gret);
132 animation.retval->Resolve(gret);
133 isAnimationRunning = false;
134 return;
135 }
136
137 struct FrameCallback cb = { .callback_ = std::bind(&AnimationModule::AnimationSync, this, SYNC_FUNC_ARG) };
138 animation.retval->Resolve(static_cast<enum GSError>(vhelper->RequestFrameCallback(cb)));
139 }
140
AnimationSync(int64_t time,void * data)141 void AnimationModule::AnimationSync(int64_t time, void *data)
142 {
143 ScopedBytrace trace(__func__);
144 if (ranimation->Draw()) {
145 eglSurface->SwapBuffers();
146 struct FrameCallback cb = { .callback_ = std::bind(&AnimationModule::AnimationSync, this, SYNC_FUNC_ARG) };
147 vhelper->RequestFrameCallback(cb);
148 trace.End();
149 } else {
150 trace.End();
151 GSLOG2HI(INFO) << "Animation End";
152 window->Hide();
153 isAnimationRunning = false;
154 }
155 }
156 } // namespace OHOS
157