• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
16 
17 namespace flutter {
18 
19 static fml::jni::ScopedJavaGlobalRef<jclass>* g_vsync_waiter_class = nullptr;
20 static jmethodID g_async_wait_for_vsync_method_ = nullptr;
21 
VsyncWaiterAndroid(flutter::TaskRunners task_runners)22 VsyncWaiterAndroid::VsyncWaiterAndroid(flutter::TaskRunners task_runners)
23     : VsyncWaiter(std::move(task_runners)) {}
24 
25 VsyncWaiterAndroid::~VsyncWaiterAndroid() = default;
26 
27 // |VsyncWaiter|
AwaitVSync()28 void VsyncWaiterAndroid::AwaitVSync() {
29   auto* weak_this = new std::weak_ptr<VsyncWaiter>(shared_from_this());
30   jlong java_baton = reinterpret_cast<jlong>(weak_this);
31 
32   task_runners_.GetPlatformTaskRunner()->PostTask([java_baton]() {
33     JNIEnv* env = fml::jni::AttachCurrentThread();
34     env->CallStaticVoidMethod(g_vsync_waiter_class->obj(),     //
35                               g_async_wait_for_vsync_method_,  //
36                               java_baton                       //
37     );
38   });
39 }
40 
GetDisplayRefreshRate() const41 float VsyncWaiterAndroid::GetDisplayRefreshRate() const {
42   JNIEnv* env = fml::jni::AttachCurrentThread();
43   if (g_vsync_waiter_class == nullptr) {
44     return kUnknownRefreshRateFPS;
45   }
46   jclass clazz = g_vsync_waiter_class->obj();
47   if (clazz == nullptr) {
48     return kUnknownRefreshRateFPS;
49   }
50   jfieldID fid = env->GetStaticFieldID(clazz, "refreshRateFPS", "F");
51   return env->GetStaticFloatField(clazz, fid);
52 }
53 
54 // static
OnNativeVsync(JNIEnv * env,jclass jcaller,jlong frameTimeNanos,jlong frameTargetTimeNanos,jlong java_baton)55 void VsyncWaiterAndroid::OnNativeVsync(JNIEnv* env,
56                                        jclass jcaller,
57                                        jlong frameTimeNanos,
58                                        jlong frameTargetTimeNanos,
59                                        jlong java_baton) {
60   auto frame_time = fml::TimePoint::FromEpochDelta(
61       fml::TimeDelta::FromNanoseconds(frameTimeNanos));
62   auto target_time = fml::TimePoint::FromEpochDelta(
63       fml::TimeDelta::FromNanoseconds(frameTargetTimeNanos));
64 
65   ConsumePendingCallback(java_baton, frame_time, target_time);
66 }
67 
68 // static
ConsumePendingCallback(jlong java_baton,fml::TimePoint frame_start_time,fml::TimePoint frame_target_time)69 void VsyncWaiterAndroid::ConsumePendingCallback(
70     jlong java_baton,
71     fml::TimePoint frame_start_time,
72     fml::TimePoint frame_target_time) {
73   auto* weak_this = reinterpret_cast<std::weak_ptr<VsyncWaiter>*>(java_baton);
74   auto shared_this = weak_this->lock();
75   delete weak_this;
76 
77   if (shared_this) {
78     shared_this->FireCallback(frame_start_time, frame_target_time);
79   }
80 }
81 
82 // static
Register(JNIEnv * env)83 bool VsyncWaiterAndroid::Register(JNIEnv* env) {
84   static const JNINativeMethod methods[] = {{
85       .name = "nativeOnVsync",
86       .signature = "(JJJ)V",
87       .fnPtr = reinterpret_cast<void*>(&OnNativeVsync),
88   }};
89 
90   jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
91 
92   if (clazz == nullptr) {
93     return false;
94   }
95 
96   g_vsync_waiter_class = new fml::jni::ScopedJavaGlobalRef<jclass>(env, clazz);
97 
98   FML_CHECK(!g_vsync_waiter_class->is_null());
99 
100   g_async_wait_for_vsync_method_ = env->GetStaticMethodID(
101       g_vsync_waiter_class->obj(), "asyncWaitForVsync", "(J)V");
102 
103   FML_CHECK(g_async_wait_for_vsync_method_ != nullptr);
104 
105   return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
106 }
107 
108 }  // namespace flutter
109