blob: f4a3425b6a0f124c4c52e6656c6ad80c5c0a0da9 [file] [log] [blame]
Valerie Haue9137b72019-08-27 13:22:18 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
18#include <gtest/gtest.h>
19#include <gui/SurfaceComposerClient.h>
20#include <gui/SurfaceControl.h>
21#include <ui/Fence.h>
22#include <utils/Timers.h>
chaviw3277faf2021-05-19 16:45:23 -050023#include <chrono>
Valerie Haue9137b72019-08-27 13:22:18 -070024#include <thread>
25
chaviw3277faf2021-05-19 16:45:23 -050026using ::std::literals::chrono_literals::operator""ms;
27using ::std::literals::chrono_literals::operator""s;
28
Valerie Haue9137b72019-08-27 13:22:18 -070029namespace android {
30
31namespace {
32
33struct CallbackData {
34 CallbackData() = default;
35 CallbackData(nsecs_t time, const sp<Fence>& fence,
36 const std::vector<SurfaceControlStats>& stats)
37 : latchTime(time), presentFence(fence), surfaceControlStats(stats) {}
38
39 nsecs_t latchTime;
40 sp<Fence> presentFence;
41 std::vector<SurfaceControlStats> surfaceControlStats;
42};
43
44class ExpectedResult {
45public:
46 enum Transaction {
47 NOT_PRESENTED = 0,
48 PRESENTED,
49 };
50
51 enum Buffer {
52 NOT_ACQUIRED = 0,
53 ACQUIRED,
54 };
55
56 enum PreviousBuffer {
57 NOT_RELEASED = 0,
58 RELEASED,
59 UNKNOWN,
60 };
61
62 void reset() {
63 mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED;
64 mExpectedSurfaceResults.clear();
65 }
66
67 void addSurface(ExpectedResult::Transaction transactionResult, const sp<SurfaceControl>& layer,
68 ExpectedResult::Buffer bufferResult = ACQUIRED,
69 ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
70 mTransactionResult = transactionResult;
71 mExpectedSurfaceResults.emplace(std::piecewise_construct, std::forward_as_tuple(layer),
72 std::forward_as_tuple(bufferResult, previousBufferResult));
73 }
74
75 void addSurfaces(ExpectedResult::Transaction transactionResult,
76 const std::vector<sp<SurfaceControl>>& layers,
77 ExpectedResult::Buffer bufferResult = ACQUIRED,
78 ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
79 for (const auto& layer : layers) {
80 addSurface(transactionResult, layer, bufferResult, previousBufferResult);
81 }
82 }
83
84 void addExpectedPresentTime(nsecs_t expectedPresentTime) {
85 mExpectedPresentTime = expectedPresentTime;
86 }
87
Ady Abraham29d16cb2021-03-08 13:19:21 -080088 void addExpectedPresentTimeForVsyncId(nsecs_t expectedPresentTime) {
89 mExpectedPresentTimeForVsyncId = expectedPresentTime;
90 }
91
Valerie Haue9137b72019-08-27 13:22:18 -070092 void verifyCallbackData(const CallbackData& callbackData) const {
93 const auto& [latchTime, presentFence, surfaceControlStats] = callbackData;
94 if (mTransactionResult == ExpectedResult::Transaction::PRESENTED) {
95 ASSERT_GE(latchTime, 0) << "bad latch time";
96 ASSERT_NE(presentFence, nullptr);
97 if (mExpectedPresentTime >= 0) {
98 ASSERT_EQ(presentFence->wait(3000), NO_ERROR);
99 ASSERT_GE(presentFence->getSignalTime(), mExpectedPresentTime - nsecs_t(5 * 1e6));
100 // if the panel is running at 30 hz, at the worst case, our expected time just
101 // misses vsync and we have to wait another 33.3ms
102 ASSERT_LE(presentFence->getSignalTime(),
103 mExpectedPresentTime + nsecs_t(66.666666 * 1e6));
Ady Abraham29d16cb2021-03-08 13:19:21 -0800104 } else if (mExpectedPresentTimeForVsyncId >= 0) {
105 ASSERT_EQ(presentFence->wait(3000), NO_ERROR);
106 // We give 4ms for prediction error
107 ASSERT_GE(presentFence->getSignalTime(),
108 mExpectedPresentTimeForVsyncId - 4'000'000);
Valerie Haue9137b72019-08-27 13:22:18 -0700109 }
110 } else {
111 ASSERT_EQ(presentFence, nullptr) << "transaction shouldn't have been presented";
112 ASSERT_EQ(latchTime, -1) << "unpresented transactions shouldn't be latched";
113 }
114
115 ASSERT_EQ(surfaceControlStats.size(), mExpectedSurfaceResults.size())
116 << "wrong number of surfaces";
117
118 for (const auto& stats : surfaceControlStats) {
119 ASSERT_NE(stats.surfaceControl, nullptr) << "returned null surface control";
120
121 const auto& expectedSurfaceResult = mExpectedSurfaceResults.find(stats.surfaceControl);
122 ASSERT_NE(expectedSurfaceResult, mExpectedSurfaceResults.end())
123 << "unexpected surface control";
124 expectedSurfaceResult->second.verifySurfaceControlStats(stats, latchTime);
125 }
126 }
127
128private:
129 class ExpectedSurfaceResult {
130 public:
131 ExpectedSurfaceResult(ExpectedResult::Buffer bufferResult,
132 ExpectedResult::PreviousBuffer previousBufferResult)
133 : mBufferResult(bufferResult), mPreviousBufferResult(previousBufferResult) {}
134
135 void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,
136 nsecs_t latchTime) const {
Valerie Hau871d6352020-01-29 08:44:02 -0800137 const auto&
138 [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence,
139 transformHint,
140 frameEvents] = surfaceControlStats;
Valerie Haue9137b72019-08-27 13:22:18 -0700141
142 ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)
143 << "bad acquire time";
144 ASSERT_LE(acquireTime, latchTime) << "acquire time should be <= latch time";
145
146 if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) {
147 ASSERT_NE(previousReleaseFence, nullptr)
148 << "failed to set release prev buffer fence";
149 } else if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::NOT_RELEASED) {
150 ASSERT_EQ(previousReleaseFence, nullptr)
151 << "should not have set released prev buffer fence";
152 }
153 }
154
155 private:
156 ExpectedResult::Buffer mBufferResult;
157 ExpectedResult::PreviousBuffer mPreviousBufferResult;
158 };
159
160 struct SCHash {
161 std::size_t operator()(const sp<SurfaceControl>& sc) const {
162 return std::hash<IBinder*>{}(sc->getHandle().get());
163 }
164 };
165 ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED;
166 nsecs_t mExpectedPresentTime = -1;
Ady Abraham29d16cb2021-03-08 13:19:21 -0800167 nsecs_t mExpectedPresentTimeForVsyncId = -1;
Valerie Haue9137b72019-08-27 13:22:18 -0700168 std::unordered_map<sp<SurfaceControl>, ExpectedSurfaceResult, SCHash> mExpectedSurfaceResults;
169};
170
171class CallbackHelper {
172public:
173 static void function(void* callbackContext, nsecs_t latchTime, const sp<Fence>& presentFence,
174 const std::vector<SurfaceControlStats>& stats) {
175 if (!callbackContext) {
176 ALOGE("failed to get callback context");
177 }
178 CallbackHelper* helper = static_cast<CallbackHelper*>(callbackContext);
179 std::lock_guard lock(helper->mMutex);
180 helper->mCallbackDataQueue.emplace(latchTime, presentFence, stats);
181 helper->mConditionVariable.notify_all();
182 }
183
184 void getCallbackData(CallbackData* outData) {
185 std::unique_lock lock(mMutex);
186
187 if (mCallbackDataQueue.empty()) {
188 ASSERT_NE(mConditionVariable.wait_for(lock, std::chrono::seconds(3)),
189 std::cv_status::timeout)
190 << "did not receive callback";
191 }
192
193 *outData = std::move(mCallbackDataQueue.front());
194 mCallbackDataQueue.pop();
195 }
196
197 void verifyFinalState() {
198 // Wait to see if there are extra callbacks
199 std::this_thread::sleep_for(500ms);
200
201 std::lock_guard lock(mMutex);
202 EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received";
203 mCallbackDataQueue = {};
204 }
205
206 void* getContext() { return static_cast<void*>(this); }
207
208 std::mutex mMutex;
209 std::condition_variable mConditionVariable;
210 std::queue<CallbackData> mCallbackDataQueue;
211};
212}
213} // namespace android