5 #import <OCMock/OCMock.h>
6 #import <XCTest/XCTest.h>
8 #include "flutter/fml/raster_thread_merger.h"
9 #include "flutter/fml/thread.h"
17 auto thread = std::make_unique<fml::Thread>(name);
18 auto runner = thread->GetTaskRunner();
26 - (void)onDisplayLink:(CADisplayLink*)link;
35 - (void)testSetAllowPauseAfterVsyncCorrect {
38 initWithTaskRunner:thread_task_runner
39 callback:[](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {}]
41 CADisplayLink* link = [vsyncClient getDisplayLink];
44 [vsyncClient onDisplayLink:link];
45 XCTAssertFalse(link.isPaused);
49 [vsyncClient onDisplayLink:link];
50 XCTAssertTrue(link.isPaused);
53 - (void)testSetCorrectVariableRefreshRates {
55 auto callback = [](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {};
56 id bundleMock = OCMPartialMock([NSBundle mainBundle]);
57 OCMStub([bundleMock objectForInfoDictionaryKey:
@"CADisableMinimumFrameDurationOnPhone"])
60 double maxFrameRate = 120;
61 [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
64 callback:callback] autorelease];
65 CADisplayLink* link = [vsyncClient getDisplayLink];
66 if (@available(iOS 15.0, *)) {
67 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, maxFrameRate, 0.1);
68 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, maxFrameRate, 0.1);
69 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, maxFrameRate / 2, 0.1);
71 XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, maxFrameRate, 0.1);
75 - (void)testDoNotSetVariableRefreshRatesIfCADisableMinimumFrameDurationOnPhoneIsNotOn {
77 auto callback = [](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {};
78 id bundleMock = OCMPartialMock([NSBundle mainBundle]);
79 OCMStub([bundleMock objectForInfoDictionaryKey:
@"CADisableMinimumFrameDurationOnPhone"])
82 double maxFrameRate = 120;
83 [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
86 callback:callback] autorelease];
87 CADisplayLink* link = [vsyncClient getDisplayLink];
88 if (@available(iOS 15.0, *)) {
89 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, 0, 0.1);
90 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, 0, 0.1);
91 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, 0, 0.1);
93 XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, 0, 0.1);
97 - (void)testDoNotSetVariableRefreshRatesIfCADisableMinimumFrameDurationOnPhoneIsNotSet {
99 auto callback = [](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {};
101 double maxFrameRate = 120;
102 [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
104 callback:callback] autorelease];
105 CADisplayLink* link = [vsyncClient getDisplayLink];
106 if (@available(iOS 15.0, *)) {
107 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, 0, 0.1);
108 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, 0, 0.1);
109 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, 0, 0.1);
111 XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, 0, 0.1);
115 - (void)testAwaitAndPauseWillWorkCorrectly {
118 initWithTaskRunner:thread_task_runner
119 callback:[](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {}]
122 CADisplayLink* link = [vsyncClient getDisplayLink];
123 XCTAssertTrue(link.isPaused);
126 XCTAssertFalse(link.isPaused);
129 XCTAssertTrue(link.isPaused);
132 - (void)testRefreshRateUpdatedTo80WhenThraedsMerge {
138 flutter::TaskRunners(
"test", platform_thread_task_runner, raster_thread_task_runner,
139 ui_thread_task_runner, io_thread_task_runner);
142 double maxFrameRate = 120;
143 [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
144 [[[mockDisplayLinkManager stub] andReturnValue:@(YES)] maxRefreshRateEnabledOnIPhone];
147 fml::scoped_nsobject<VSyncClient> vsyncClient = vsync_waiter.GetVsyncClient();
148 CADisplayLink* link = [vsyncClient.get() getDisplayLink];
150 if (@available(iOS 15.0, *)) {
151 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, maxFrameRate, 0.1);
152 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, maxFrameRate, 0.1);
153 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, maxFrameRate / 2, 0.1);
155 XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, maxFrameRate, 0.1);
158 const auto merger = fml::RasterThreadMerger::CreateOrShareThreadMerger(
159 nullptr, platform_thread_task_runner->GetTaskQueueId(),
160 raster_thread_task_runner->GetTaskQueueId());
162 merger->MergeWithLease(5);
163 vsync_waiter.AwaitVSync();
165 if (@available(iOS 15.0, *)) {
166 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, 80, 0.1);
167 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, 80, 0.1);
168 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, 60, 0.1);
170 XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, 80, 0.1);
173 merger->UnMergeNowIfLastOne();
174 vsync_waiter.AwaitVSync();
176 if (@available(iOS 15.0, *)) {
177 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, maxFrameRate, 0.1);
178 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, maxFrameRate, 0.1);
179 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, maxFrameRate / 2, 0.1);
181 XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, maxFrameRate, 0.1);
184 if (@available(iOS 14.0, *)) {
186 id processInfo = [NSProcessInfo processInfo];
187 id processInfoPartialMock = OCMPartialMock(processInfo);
188 bool iOSAppOnMac =
true;
189 [OCMStub([processInfoPartialMock isiOSAppOnMac]) andReturnValue:OCMOCK_VALUE(iOSAppOnMac)];
191 merger->MergeWithLease(5);
192 vsync_waiter.AwaitVSync();
195 if (@available(iOS 15.0, *)) {
196 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, maxFrameRate, 0.1);
197 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, maxFrameRate, 0.1);
198 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, maxFrameRate / 2, 0.1);
200 XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, 80, 0.1);
203 merger->UnMergeNowIfLastOne();
204 vsync_waiter.AwaitVSync();
206 if (@available(iOS 15.0, *)) {
207 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, maxFrameRate, 0.1);
208 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, maxFrameRate, 0.1);
209 XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, maxFrameRate / 2, 0.1);
211 XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, maxFrameRate, 0.1);