• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/animation/scheduler.h"
17 
18 #include "base/log/log.h"
19 #include "base/thread/task_executor.h"
20 #include "core/pipeline/pipeline_base.h"
21 
22 namespace OHOS::Ace {
23 
Start()24 void Scheduler::Start()
25 {
26     if (isRunning_) {
27         LOGW("Already running, no need to start again.");
28         return;
29     }
30     auto context = context_.Upgrade();
31     if (!context) {
32         LOGE("Start failed, context is null.");
33         return;
34     }
35     isRunning_ = true;
36     startupTimestamp_ = context->GetTimeFromExternalTimer();
37     scheduleId_ = static_cast<int32_t>(context->AddScheduleTask(AceType::Claim(this)));
38 
39     displaySync_ = AceType::MakeRefPtr<UIDisplaySync>();
40     displaySync_->RegisterOnFrameWithTimestamp([weak = WeakClaim(this)] (uint64_t nanoTimestamp) {
41         auto scheduler = weak.Upgrade();
42         CHECK_NULL_VOID(scheduler);
43         scheduler->OnFrame(nanoTimestamp);
44     });
45     displaySync_->AddToPipeline(context_);
46 }
47 
Stop()48 void Scheduler::Stop()
49 {
50     if (!isRunning_) {
51         return;
52     }
53     auto context = context_.Upgrade();
54     if (!context) {
55         LOGE("Stop failed, context is null.");
56         return;
57     }
58     isRunning_ = false;
59     context->RemoveScheduleTask(scheduleId_);
60     displaySync_->DelFromPipeline(context_);
61     scheduleId_ = 0;
62 }
63 
OnFrame(uint64_t nanoTimestamp)64 void Scheduler::OnFrame(uint64_t nanoTimestamp)
65 {
66     if (!isRunning_) {
67         return;
68     }
69 
70     // Refresh the startup time every frame.
71     uint64_t elapsedTimeMs = 0;
72     if (nanoTimestamp > startupTimestamp_) {
73         static const uint64_t milliToNano = 1000000;
74         elapsedTimeMs = (nanoTimestamp - startupTimestamp_) / milliToNano;
75         startupTimestamp_ += elapsedTimeMs * milliToNano;
76     }
77 
78     // Consume previous schedule as default.
79     scheduleId_ = 0;
80     if (callback_) {
81         // Need to convert nanoseconds to milliseconds
82         callback_(elapsedTimeMs);
83     }
84 
85     // Schedule next frame task.
86     auto context = context_.Upgrade();
87     if (!context) {
88         LOGE("Schedule next frame task failed, context is null.");
89         return;
90     }
91     if (IsActive()) {
92         scheduleId_ = static_cast<int32_t>(context->AddScheduleTask(AceType::Claim(this)));
93     }
94 }
95 
Animate(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> propertyCallback,const std::function<void ()> & finishCallBack)96 bool Scheduler::Animate(const AnimationOption& option, const RefPtr<Curve>& curve,
97     const std::function<void()> propertyCallback, const std::function<void()>& finishCallBack)
98 {
99     auto context = context_.Upgrade();
100     if (context == nullptr) {
101         LOGE("Failed to animate asynchronously, context is null!");
102         return false;
103     }
104 
105     return context->Animate(option, curve, propertyCallback, finishCallBack);
106 }
107 
OpenImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallBack)108 void Scheduler::OpenImplicitAnimation(const AnimationOption& option, const RefPtr<Curve>& curve,
109     const std::function<void()>& finishCallBack)
110 {
111     auto context = context_.Upgrade();
112     if (context == nullptr) {
113         LOGE("Failed to open implicit animation, context is null!");
114         return;
115     }
116 
117     return context->OpenImplicitAnimation(option, curve, finishCallBack);
118 }
119 
CloseImplicitAnimation()120 bool Scheduler::CloseImplicitAnimation()
121 {
122     auto context = context_.Upgrade();
123     if (context == nullptr) {
124         LOGE("Failed to close implicit animation, context is null!");
125         return false;
126     }
127 
128     return context->CloseImplicitAnimation();
129 }
130 
AddKeyFrame(float fraction,const RefPtr<Curve> & curve,const std::function<void ()> & propertyCallback)131 void Scheduler::AddKeyFrame(
132     float fraction, const RefPtr<Curve>& curve, const std::function<void()>& propertyCallback)
133 {
134     auto context = context_.Upgrade();
135     if (context == nullptr) {
136         LOGE("Failed to add keyframe, context is null!");
137         return;
138     }
139 
140     return context->AddKeyFrame(fraction, curve, propertyCallback);
141 }
142 
AddKeyFrame(float fraction,const std::function<void ()> & propertyCallback)143 void Scheduler::AddKeyFrame(float fraction, const std::function<void()>& propertyCallback)
144 {
145     auto context = context_.Upgrade();
146     if (context == nullptr) {
147         LOGE("Failed to add keyframe, context is null!");
148         return;
149     }
150 
151     return context->AddKeyFrame(fraction, propertyCallback);
152 }
153 
PrintVsyncInfoIfNeed() const154 bool Scheduler::PrintVsyncInfoIfNeed() const
155 {
156     auto pipeline = context_.Upgrade();
157     CHECK_NULL_RETURN(pipeline, false);
158     if (pipeline->PrintVsyncInfoIfNeed()) {
159         return true;
160     }
161     auto taskExecutor = pipeline->GetTaskExecutor();
162     CHECK_NULL_RETURN(taskExecutor, false);
163     const uint32_t delay = 3000; // unit: ms
164     // check vsync info after delay time.
165     taskExecutor->PostDelayedTask(
166         [weakContext = context_]() {
167             auto pipeline = weakContext.Upgrade();
168             CHECK_NULL_VOID(pipeline);
169             pipeline->PrintVsyncInfoIfNeed();
170         },
171         TaskExecutor::TaskType::UI, delay);
172     return false;
173 }
174 
175 } // namespace OHOS::Ace
176