Flutter Engine
 
Loading...
Searching...
No Matches
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
6
7#include <cmath>
8#include <utility>
9
11#include "flutter/fml/logging.h"
16
17namespace flutter {
18
20static jmethodID g_async_wait_for_vsync_method_ = nullptr;
21static std::atomic_uint g_refresh_rate_ = 60;
22
25
27
28// |VsyncWaiter|
29void VsyncWaiterAndroid::AwaitVSync() {
30 const static bool use_choreographer =
32 if (use_choreographer) {
33 auto* weak_this = new std::weak_ptr<VsyncWaiter>(shared_from_this());
34 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
36 task_runners_.GetUITaskRunner(), [weak_this]() {
37 const auto& choreographer =
38 impeller::android::Choreographer::GetInstance();
39 choreographer.PostFrameCallback([weak_this](auto time) {
40 auto time_ns =
41 std::chrono::time_point_cast<std::chrono::nanoseconds>(time)
42 .time_since_epoch()
43 .count();
44 OnVsyncFromNDK(time_ns, weak_this);
45 });
46 });
47 } else {
48 // TODO(99798): Remove it when we drop support for API level < 29 and 32-bit
49 // devices.
50 auto* weak_this = new std::weak_ptr<VsyncWaiter>(shared_from_this());
51 jlong java_baton = reinterpret_cast<jlong>(weak_this);
52 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
54 JNIEnv* env = fml::jni::AttachCurrentThread();
55 env->CallStaticVoidMethod(g_vsync_waiter_class->obj(), //
57 java_baton //
58 );
59 });
60 }
61}
62
63// static
64void VsyncWaiterAndroid::OnVsyncFromNDK(int64_t frame_nanos, void* data) {
65 auto frame_time = fml::TimePoint::FromEpochDelta(
67 auto now = fml::TimePoint::Now();
68 if (frame_time > now) {
69 frame_time = now;
70 }
71 auto target_time = frame_time + fml::TimeDelta::FromNanoseconds(
72 1000000000.0 / g_refresh_rate_);
73
74 TRACE_EVENT2_INT("flutter", "PlatformVsync", "frame_start_time",
75 frame_time.ToEpochDelta().ToMicroseconds(),
76 "frame_target_time",
77 target_time.ToEpochDelta().ToMicroseconds());
78
79 auto* weak_this = reinterpret_cast<std::weak_ptr<VsyncWaiter>*>(data);
80 ConsumePendingCallback(weak_this, frame_time, target_time);
81}
82
83// static
84void VsyncWaiterAndroid::OnVsyncFromJava(JNIEnv* env,
85 jclass jcaller,
86 jlong frameDelayNanos,
87 jlong refreshPeriodNanos,
88 jlong java_baton) {
89 auto frame_time =
91 auto target_time =
92 frame_time + fml::TimeDelta::FromNanoseconds(refreshPeriodNanos);
93
94 TRACE_EVENT2_INT("flutter", "PlatformVsync", "frame_start_time",
95 frame_time.ToEpochDelta().ToMicroseconds(),
96 "frame_target_time",
97 target_time.ToEpochDelta().ToMicroseconds());
98
99 auto* weak_this = reinterpret_cast<std::weak_ptr<VsyncWaiter>*>(java_baton);
100 ConsumePendingCallback(weak_this, frame_time, target_time);
101}
102
103// static
104void VsyncWaiterAndroid::ConsumePendingCallback(
105 std::weak_ptr<VsyncWaiter>* weak_this,
106 fml::TimePoint frame_start_time,
107 fml::TimePoint frame_target_time) {
108 auto shared_this = weak_this->lock();
109 delete weak_this;
110
111 if (shared_this) {
112 shared_this->FireCallback(frame_start_time, frame_target_time);
113 }
114}
115
116// static
117void VsyncWaiterAndroid::OnUpdateRefreshRate(JNIEnv* env,
118 jclass jcaller,
119 jfloat refresh_rate) {
120 FML_DCHECK(refresh_rate > 0);
121 g_refresh_rate_ = static_cast<uint>(refresh_rate);
122}
123
124// static
125bool VsyncWaiterAndroid::Register(JNIEnv* env) {
126 static const JNINativeMethod methods[] = {
127 {
128 .name = "nativeOnVsync",
129 .signature = "(JJJ)V",
130 .fnPtr = reinterpret_cast<void*>(&OnVsyncFromJava),
131 },
132 {
133 .name = "nativeUpdateRefreshRate",
134 .signature = "(F)V",
135 .fnPtr = reinterpret_cast<void*>(&OnUpdateRefreshRate),
136 }};
137
138 jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
139
140 if (clazz == nullptr) {
141 return false;
142 }
143
145 FML_CHECK(!g_vsync_waiter_class->is_null());
146
147 g_async_wait_for_vsync_method_ = env->GetStaticMethodID(
148 g_vsync_waiter_class->obj(), "asyncWaitForVsync", "(J)V");
150
151 return env->RegisterNatives(clazz, methods, std::size(methods)) == 0;
152}
153
154} // namespace flutter
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
friend class VsyncWaiterAndroid
const TaskRunners task_runners_
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
virtual void PostTask(const fml::closure &task) override
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:104
#define FML_DCHECK(condition)
Definition logging.h:122
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
std::shared_ptr< const fml::Mapping > data
#define TRACE_EVENT2_INT(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)