Flutter Engine
The Flutter Engine
vsync_waiter_android.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/shell/platform/android/vsync_waiter_android.h"
6
7#include <cmath>
8#include <utility>
9
10#include "flutter/common/task_runners.h"
11#include "flutter/fml/logging.h"
12#include "flutter/fml/platform/android/jni_util.h"
13#include "flutter/fml/platform/android/scoped_java_ref.h"
14#include "flutter/fml/size.h"
15#include "flutter/fml/trace_event.h"
17
18namespace flutter {
19
21static jmethodID g_async_wait_for_vsync_method_ = nullptr;
22static std::atomic_uint g_refresh_rate_ = 60;
23
25 : VsyncWaiter(task_runners) {}
26
28
29// |VsyncWaiter|
30void VsyncWaiterAndroid::AwaitVSync() {
32 auto* weak_this = new std::weak_ptr<VsyncWaiter>(shared_from_this());
34 task_runners_.GetUITaskRunner(), [weak_this]() {
35 const auto& choreographer =
36 impeller::android::Choreographer::GetInstance();
37 choreographer.PostFrameCallback([weak_this](auto time) {
38 auto time_ns =
39 std::chrono::time_point_cast<std::chrono::nanoseconds>(time)
40 .time_since_epoch()
41 .count();
42 OnVsyncFromNDK(time_ns, weak_this);
43 });
44 });
45 } else {
46 // TODO(99798): Remove it when we drop support for API level < 29 and 32-bit
47 // devices.
48 auto* weak_this = new std::weak_ptr<VsyncWaiter>(shared_from_this());
49 jlong java_baton = reinterpret_cast<jlong>(weak_this);
52 env->CallStaticVoidMethod(g_vsync_waiter_class->obj(), //
54 java_baton //
55 );
56 });
57 }
58}
59
60// static
61void VsyncWaiterAndroid::OnVsyncFromNDK(int64_t frame_nanos, void* data) {
62 auto frame_time = fml::TimePoint::FromEpochDelta(
64 auto now = fml::TimePoint::Now();
65 if (frame_time > now) {
66 frame_time = now;
67 }
68 auto target_time = frame_time + fml::TimeDelta::FromNanoseconds(
69 1000000000.0 / g_refresh_rate_);
70
71 TRACE_EVENT2_INT("flutter", "PlatformVsync", "frame_start_time",
72 frame_time.ToEpochDelta().ToMicroseconds(),
73 "frame_target_time",
74 target_time.ToEpochDelta().ToMicroseconds());
75
76 auto* weak_this = reinterpret_cast<std::weak_ptr<VsyncWaiter>*>(data);
77 ConsumePendingCallback(weak_this, frame_time, target_time);
78}
79
80// static
81void VsyncWaiterAndroid::OnVsyncFromJava(JNIEnv* env,
82 jclass jcaller,
83 jlong frameDelayNanos,
84 jlong refreshPeriodNanos,
85 jlong java_baton) {
86 auto frame_time =
88 auto target_time =
89 frame_time + fml::TimeDelta::FromNanoseconds(refreshPeriodNanos);
90
91 TRACE_EVENT2_INT("flutter", "PlatformVsync", "frame_start_time",
92 frame_time.ToEpochDelta().ToMicroseconds(),
93 "frame_target_time",
94 target_time.ToEpochDelta().ToMicroseconds());
95
96 auto* weak_this = reinterpret_cast<std::weak_ptr<VsyncWaiter>*>(java_baton);
97 ConsumePendingCallback(weak_this, frame_time, target_time);
98}
99
100// static
101void VsyncWaiterAndroid::ConsumePendingCallback(
102 std::weak_ptr<VsyncWaiter>* weak_this,
103 fml::TimePoint frame_start_time,
104 fml::TimePoint frame_target_time) {
105 auto shared_this = weak_this->lock();
106 delete weak_this;
107
108 if (shared_this) {
109 shared_this->FireCallback(frame_start_time, frame_target_time);
110 }
111}
112
113// static
114void VsyncWaiterAndroid::OnUpdateRefreshRate(JNIEnv* env,
115 jclass jcaller,
116 jfloat refresh_rate) {
117 FML_DCHECK(refresh_rate > 0);
118 g_refresh_rate_ = static_cast<uint>(refresh_rate);
119}
120
121// static
123 static const JNINativeMethod methods[] = {
124 {
125 .name = "nativeOnVsync",
126 .signature = "(JJJ)V",
127 .fnPtr = reinterpret_cast<void*>(&OnVsyncFromJava),
128 },
129 {
130 .name = "nativeUpdateRefreshRate",
131 .signature = "(F)V",
132 .fnPtr = reinterpret_cast<void*>(&OnUpdateRefreshRate),
133 }};
134
135 jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
136
137 if (clazz == nullptr) {
138 return false;
139 }
140
142 FML_CHECK(!g_vsync_waiter_class->is_null());
143
144 g_async_wait_for_vsync_method_ = env->GetStaticMethodID(
145 g_vsync_waiter_class->obj(), "asyncWaitForVsync", "(J)V");
147
148 return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
149}
150
151} // namespace flutter
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
Definition: task_runners.cc:34
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
Definition: task_runners.cc:30
friend class VsyncWaiterAndroid
Definition: vsync_waiter.h:41
const TaskRunners task_runners_
Definition: vsync_waiter.h:44
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
Definition: task_runner.cc:55
virtual void PostTask(const fml::closure &task) override
Definition: task_runner.cc:24
static constexpr TimeDelta FromNanoseconds(int64_t nanos)
Definition: time_delta.h:40
static TimePoint Now()
Definition: time_point.cc:49
static constexpr TimePoint FromEpochDelta(TimeDelta ticks)
Definition: time_point.h:43
TaskRunners task_runners_
#define FML_CHECK(condition)
Definition: logging.h:85
#define FML_DCHECK(condition)
Definition: logging.h:103
Definition: __init__.py:1
static fml::jni::ScopedJavaGlobalRef< jclass > * g_vsync_waiter_class
static jmethodID g_async_wait_for_vsync_method_
static std::atomic_uint g_refresh_rate_
JNIEnv * AttachCurrentThread()
Definition: jni_util.cc:34
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
#define TRACE_EVENT2_INT(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
Definition: trace_event.h:202