Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions runtime/service_protocol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const fml::StringView ServiceProtocol::kFlushUIThreadTasksExtensionName =
"_flutter.flushUIThreadTasks";
const fml::StringView ServiceProtocol::kSetAssetBundlePathExtensionName =
"_flutter.setAssetBundlePath";
const fml::StringView ServiceProtocol::kGetDisplayRefreshRateExtensionName =
"_flutter.getDisplayRefreshRate";

static constexpr fml::StringView kViewIdPrefx = "_flutterView/";
static constexpr fml::StringView kListViewsExtensionName = "_flutter.listViews";
Expand All @@ -45,6 +47,7 @@ ServiceProtocol::ServiceProtocol()
kRunInViewExtensionName,
kFlushUIThreadTasksExtensionName,
kSetAssetBundlePathExtensionName,
kGetDisplayRefreshRateExtensionName,
}),
handlers_mutex_(fml::SharedMutex::Create()) {}

Expand Down
1 change: 1 addition & 0 deletions runtime/service_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ServiceProtocol {
static const fml::StringView kRunInViewExtensionName;
static const fml::StringView kFlushUIThreadTasksExtensionName;
static const fml::StringView kSetAssetBundlePathExtensionName;
static const fml::StringView kGetDisplayRefreshRateExtensionName;

class Handler {
public:
Expand Down
4 changes: 4 additions & 0 deletions shell/common/animator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ Animator::Animator(Delegate& delegate,

Animator::~Animator() = default;

float Animator::GetDisplayRefreshRate() const {
return waiter_->GetDisplayRefreshRate();
}

void Animator::Stop() {
paused_ = true;
}
Expand Down
2 changes: 2 additions & 0 deletions shell/common/animator.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class Animator final {

~Animator();

float GetDisplayRefreshRate() const;

void RequestFrame(bool regenerate_layer_tree = true);

void Render(std::unique_ptr<flow::LayerTree> layer_tree);
Expand Down
4 changes: 4 additions & 0 deletions shell/common/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ Engine::Engine(Delegate& delegate,

Engine::~Engine() = default;

float Engine::GetDisplayRefreshRate() const {
return animator_->GetDisplayRefreshRate();
}

fml::WeakPtr<Engine> Engine::GetWeakPtr() const {
return weak_factory_.GetWeakPtr();
}
Expand Down
2 changes: 2 additions & 0 deletions shell/common/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class Engine final : public blink::RuntimeDelegate {

~Engine() override;

float GetDisplayRefreshRate() const;

fml::WeakPtr<Engine> GetWeakPtr() const;

FML_WARN_UNUSED_RESULT
Expand Down
15 changes: 15 additions & 0 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@ Shell::Shell(blink::TaskRunners task_runners, blink::Settings settings)
task_runners_.GetUITaskRunner(),
std::bind(&Shell::OnServiceProtocolSetAssetBundlePath, this,
std::placeholders::_1, std::placeholders::_2)};
service_protocol_handlers_
[blink::ServiceProtocol::kGetDisplayRefreshRateExtensionName.ToString()] =
{task_runners_.GetUITaskRunner(),
std::bind(&Shell::OnServiceProtocolGetDisplayRefreshRate, this,
std::placeholders::_1, std::placeholders::_2)};
}

Shell::~Shell() {
Expand Down Expand Up @@ -939,6 +944,16 @@ bool Shell::OnServiceProtocolFlushUIThreadTasks(
return true;
}

bool Shell::OnServiceProtocolGetDisplayRefreshRate(
const blink::ServiceProtocol::Handler::ServiceProtocolMap& params,
rapidjson::Document& response) {
FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
response.SetObject();
response.AddMember("fps", engine_->GetDisplayRefreshRate(),
response.GetAllocator());
return true;
}

// Service protocol handler
bool Shell::OnServiceProtocolSetAssetBundlePath(
const blink::ServiceProtocol::Handler::ServiceProtocolMap& params,
Expand Down
5 changes: 5 additions & 0 deletions shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ class Shell final : public PlatformView::Delegate,
const blink::ServiceProtocol::Handler::ServiceProtocolMap& params,
rapidjson::Document& response);

// Service protocol handler
bool OnServiceProtocolGetDisplayRefreshRate(
const blink::ServiceProtocol::Handler::ServiceProtocolMap& params,
rapidjson::Document& response);

FML_DISALLOW_COPY_AND_ASSIGN(Shell);
};

Expand Down
6 changes: 6 additions & 0 deletions shell/common/vsync_waiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

namespace shell {

constexpr float kUnknownRefreshRateFPS = 0.0;

class VsyncWaiter : public std::enable_shared_from_this<VsyncWaiter> {
public:
using Callback = std::function<void(fml::TimePoint frame_start_time,
Expand All @@ -26,6 +28,10 @@ class VsyncWaiter : public std::enable_shared_from_this<VsyncWaiter> {
void FireCallback(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time);

// Get the display's maximum refresh rate in the unit of frame per second.
// Return 0.0 if the refresh rate is unkonwn.
virtual float GetDisplayRefreshRate() const { return 0.0; }

protected:
const blink::TaskRunners task_runners_;
std::mutex callback_mutex_;
Expand Down
1 change: 1 addition & 0 deletions shell/platform/android/io/flutter/view/FlutterView.java
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,7 @@ private void updateViewportMetrics() {
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
float fps = wm.getDefaultDisplay().getRefreshRate();
VsyncWaiter.refreshPeriodNanos = (long) (1000000000.0 / fps);
VsyncWaiter.refreshRateFPS = fps;
}

// Called by native to update the semantics/accessibility tree.
Expand Down
4 changes: 4 additions & 0 deletions shell/platform/android/io/flutter/view/VsyncWaiter.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ public class VsyncWaiter {
// This estimate will be updated by FlutterView when it is attached to a Display.
public static long refreshPeriodNanos = 1000000000 / 60;

// This should also be updated by FlutterView when it is attached to a Display.
// The initial value of 0.0 indicates unkonwn refresh rate.
public static float refreshRateFPS = 0.0f;

public static void asyncWaitForVsync(final long cookie) {
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
@Override
Expand Down
16 changes: 16 additions & 0 deletions shell/platform/android/vsync_waiter_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,22 @@ bool VsyncWaiterAndroid::Register(JNIEnv* env) {
return env->RegisterNatives(clazz, methods, arraysize(methods)) == 0;
}

float VsyncWaiterAndroid::GetDisplayRefreshRate() const {
JNIEnv* env = fml::jni::AttachCurrentThread();
if (g_vsync_waiter_class == nullptr) {
return kUnknownRefreshRateFPS;
}
jclass clazz = g_vsync_waiter_class->obj();
if (clazz == nullptr) {
return kUnknownRefreshRateFPS;
}
jfieldID fid = env->GetStaticFieldID(clazz, "refreshRateFPS", "F");
// We can safely read this 32-bit float from Java in any thread because
// 32-bits read and write are guaranteed to be atomic:
// https://stackoverflow.com/questions/11459543/should-getters-and-setters-be-synchronized/11459616#11459616
return env->GetStaticFloatField(clazz, fid);
}

static void ConsumePendingCallback(jlong java_baton,
fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/android/vsync_waiter_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class VsyncWaiterAndroid final : public VsyncWaiter {

~VsyncWaiterAndroid() override;

float GetDisplayRefreshRate() const override;

private:
// |shell::VsyncWaiter|
void AwaitVSync() override;
Expand Down