Skip to content

Commit f4bc821

Browse files
authored
Listen for display refresh changes and report them correctly (flutter#29800)
This makes sure the frame timings recorder and vsync waiter implementations get the correct refresh rate if or when it adjusts at runtime. This should be OK because we'll only query the refresh rate when the display metrics actually change, which is much less frequent than every frame. I experimented with an NDK implementation in the previous patch, but that vastly restricts the API levels we can support, and currently on API 30 and 31 it just calls Java methods through JNI anyway. I've refactored the way Display updates are reported so that AndroidDisplay can just dynamically get the refresh rate correctly. These values are used by a service protocol extension and by some Stopwatches on the CompositorContext. See also flutter#29765 Fixes flutter#93688 Fixes flutter#93698
1 parent eac4cd2 commit f4bc821

19 files changed

Lines changed: 335 additions & 66 deletions

File tree

ci/licenses_golden/licenses_flutter

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ FILE: ../../../flutter/shell/common/canvas_spy_unittests.cc
696696
FILE: ../../../flutter/shell/common/context_options.cc
697697
FILE: ../../../flutter/shell/common/context_options.h
698698
FILE: ../../../flutter/shell/common/dart_native_benchmarks.cc
699+
FILE: ../../../flutter/shell/common/display.cc
699700
FILE: ../../../flutter/shell/common/display.h
700701
FILE: ../../../flutter/shell/common/display_manager.cc
701702
FILE: ../../../flutter/shell/common/display_manager.h
@@ -775,6 +776,8 @@ FILE: ../../../flutter/shell/platform/android/AndroidManifest.xml
775776
FILE: ../../../flutter/shell/platform/android/android_context_gl.cc
776777
FILE: ../../../flutter/shell/platform/android/android_context_gl.h
777778
FILE: ../../../flutter/shell/platform/android/android_context_gl_unittests.cc
779+
FILE: ../../../flutter/shell/platform/android/android_display.cc
780+
FILE: ../../../flutter/shell/platform/android/android_display.h
778781
FILE: ../../../flutter/shell/platform/android/android_environment_gl.cc
779782
FILE: ../../../flutter/shell/platform/android/android_environment_gl.h
780783
FILE: ../../../flutter/shell/platform/android/android_exports.lst

shell/common/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ source_set("common") {
6666
"canvas_spy.h",
6767
"context_options.cc",
6868
"context_options.h",
69+
"display.cc",
6970
"display.h",
7071
"display_manager.cc",
7172
"display_manager.h",

shell/common/display.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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/common/display.h"
6+
7+
namespace flutter {
8+
double Display::GetRefreshRate() const {
9+
return refresh_rate_;
10+
}
11+
} // namespace flutter

shell/common/display.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include <optional>
99

10+
#include "flutter/fml/macros.h"
11+
1012
namespace flutter {
1113

1214
/// Unique ID per display that is stable until the Flutter application restarts.
@@ -36,18 +38,20 @@ class Display {
3638
explicit Display(double refresh_rate)
3739
: display_id_({}), refresh_rate_(refresh_rate) {}
3840

39-
~Display() = default;
41+
virtual ~Display() = default;
4042

4143
// Get the display's maximum refresh rate in the unit of frame per second.
4244
// Return `kUnknownDisplayRefreshRate` if the refresh rate is unknown.
43-
double GetRefreshRate() const { return refresh_rate_; }
45+
virtual double GetRefreshRate() const;
4446

4547
/// Returns the `DisplayId` of the display.
4648
std::optional<DisplayId> GetDisplayId() const { return display_id_; }
4749

4850
private:
4951
std::optional<DisplayId> display_id_;
5052
double refresh_rate_;
53+
54+
FML_DISALLOW_COPY_AND_ASSIGN(Display);
5155
};
5256

5357
} // namespace flutter

shell/common/display_manager.cc

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,31 @@ double DisplayManager::GetMainDisplayRefreshRate() const {
1818
if (displays_.empty()) {
1919
return kUnknownDisplayRefreshRate;
2020
} else {
21-
return displays_[0].GetRefreshRate();
21+
return displays_[0]->GetRefreshRate();
2222
}
2323
}
2424

25-
void DisplayManager::HandleDisplayUpdates(DisplayUpdateType update_type,
26-
std::vector<Display> displays) {
25+
void DisplayManager::HandleDisplayUpdates(
26+
DisplayUpdateType update_type,
27+
std::vector<std::unique_ptr<Display>> displays) {
2728
std::scoped_lock lock(displays_mutex_);
2829
CheckDisplayConfiguration(displays);
2930
switch (update_type) {
3031
case DisplayUpdateType::kStartup:
3132
FML_CHECK(displays_.empty());
32-
displays_ = displays;
33+
displays_ = std::move(displays);
3334
return;
3435
default:
3536
FML_CHECK(false) << "Unknown DisplayUpdateType.";
3637
}
3738
}
3839

3940
void DisplayManager::CheckDisplayConfiguration(
40-
std::vector<Display> displays) const {
41+
const std::vector<std::unique_ptr<Display>>& displays) const {
4142
FML_CHECK(!displays.empty());
4243
if (displays.size() > 1) {
4344
for (auto& display : displays) {
44-
FML_CHECK(display.GetDisplayId().has_value());
45+
FML_CHECK(display->GetDisplayId().has_value());
4546
}
4647
}
4748
}

shell/common/display_manager.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,19 @@ class DisplayManager {
4040

4141
/// Handles the display updates.
4242
void HandleDisplayUpdates(DisplayUpdateType update_type,
43-
std::vector<Display> displays);
43+
std::vector<std::unique_ptr<Display>> displays);
4444

4545
private:
4646
/// Guards `displays_` vector.
4747
mutable std::mutex displays_mutex_;
48-
std::vector<Display> displays_;
48+
std::vector<std::unique_ptr<Display>> displays_;
4949

5050
/// Checks that the provided display configuration is valid. Currently this
5151
/// ensures that all the displays have an id in the case there are multiple
5252
/// displays. In case where there is a single display, it is valid for the
5353
/// display to not have an id.
54-
void CheckDisplayConfiguration(std::vector<Display> displays) const;
54+
void CheckDisplayConfiguration(
55+
const std::vector<std::unique_ptr<Display>>& displays) const;
5556
};
5657

5758
} // namespace flutter

shell/common/shell.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,8 +1867,8 @@ void Shell::SetGpuAvailability(GpuAvailability availability) {
18671867
}
18681868

18691869
void Shell::OnDisplayUpdates(DisplayUpdateType update_type,
1870-
std::vector<Display> displays) {
1871-
display_manager_->HandleDisplayUpdates(update_type, displays);
1870+
std::vector<std::unique_ptr<Display>> displays) {
1871+
display_manager_->HandleDisplayUpdates(update_type, std::move(displays));
18721872
}
18731873

18741874
fml::TimePoint Shell::GetCurrentTimePoint() {

shell/common/shell.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ class Shell final : public PlatformView::Delegate,
373373
/// @brief Notifies the display manager of the updates.
374374
///
375375
void OnDisplayUpdates(DisplayUpdateType update_type,
376-
std::vector<Display> displays);
376+
std::vector<std::unique_ptr<Display>> displays);
377377

378378
//----------------------------------------------------------------------------
379379
/// @brief Queries the `DisplayManager` for the main display refresh rate.

shell/platform/android/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ source_set("flutter_shell_native_src") {
6464
"$root_build_dir/flutter_icu/icudtl.o",
6565
"android_context_gl.cc",
6666
"android_context_gl.h",
67+
"android_display.cc",
68+
"android_display.h",
6769
"android_environment_gl.cc",
6870
"android_environment_gl.h",
6971
"android_external_texture_gl.cc",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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/android_display.h"
6+
#include "android_display.h"
7+
8+
namespace flutter {
9+
10+
AndroidDisplay::AndroidDisplay(
11+
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
12+
: Display(jni_facade->GetDisplayRefreshRate()),
13+
jni_facade_(std::move(jni_facade)) {}
14+
15+
double AndroidDisplay::GetRefreshRate() const {
16+
return jni_facade_->GetDisplayRefreshRate();
17+
}
18+
19+
} // namespace flutter

0 commit comments

Comments
 (0)