blob: 459b35c54480b94af10e469252f480c62d8d0ac4 [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>
23#include <thread>
24
25namespace android {
26
27namespace {
28
29struct CallbackData {
30 CallbackData() = default;
31 CallbackData(nsecs_t time, const sp<Fence>& fence,
32 const std::vector<SurfaceControlStats>& stats)
33 : latchTime(time), presentFence(fence), surfaceControlStats(stats) {}
34
35 nsecs_t latchTime;
36 sp<Fence> presentFence;
37 std::vector<SurfaceControlStats> surfaceControlStats;
38};
39
40class ExpectedResult {
41public:
42 enum Transaction {
43 NOT_PRESENTED = 0,
44 PRESENTED,
45 };
46
47 enum Buffer {
48 NOT_ACQUIRED = 0,
49 ACQUIRED,
50 };
51
52 enum PreviousBuffer {
53 NOT_RELEASED = 0,
54 RELEASED,
55 UNKNOWN,
56 };
57
58 void reset() {
59 mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED;
60 mExpectedSurfaceResults.clear();
61 }
62
63 void addSurface(ExpectedResult::Transaction transactionResult, const sp<SurfaceControl>& layer,
64 ExpectedResult::Buffer bufferResult = ACQUIRED,
65 ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
66 mTransactionResult = transactionResult;
67 mExpectedSurfaceResults.emplace(std::piecewise_construct, std::forward_as_tuple(layer),
68 std::forward_as_tuple(bufferResult, previousBufferResult));
69 }
70
71 void addSurfaces(ExpectedResult::Transaction transactionResult,
72 const std::vector<sp<SurfaceControl>>& layers,
73 ExpectedResult::Buffer bufferResult = ACQUIRED,
74 ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
75 for (const auto& layer : layers) {
76 addSurface(transactionResult, layer, bufferResult, previousBufferResult);
77 }
78 }
79
80 void addExpectedPresentTime(nsecs_t expectedPresentTime) {
81 mExpectedPresentTime = expectedPresentTime;
82 }
83
Ady Abraham29d16cb2021-03-08 13:19:21 -080084 void addExpectedPresentTimeForVsyncId(nsecs_t expectedPresentTime) {
85 mExpectedPresentTimeForVsyncId = expectedPresentTime;
86 }
87
Valerie Haue9137b72019-08-27 13:22:18 -070088 void verifyCallbackData(const CallbackData& callbackData) const {
89 const auto& [latchTime, presentFence, surfaceControlStats] = callbackData;
90 if (mTransactionResult == ExpectedResult::Transaction::PRESENTED) {
91 ASSERT_GE(latchTime, 0) << "bad latch time";
92 ASSERT_NE(presentFence, nullptr);
93 if (mExpectedPresentTime >= 0) {
94 ASSERT_EQ(presentFence->wait(3000), NO_ERROR);
95 ASSERT_GE(presentFence->getSignalTime(), mExpectedPresentTime - nsecs_t(5 * 1e6));
96 // if the panel is running at 30 hz, at the worst case, our expected time just
97 // misses vsync and we have to wait another 33.3ms
98 ASSERT_LE(presentFence->getSignalTime(),
99 mExpectedPresentTime + nsecs_t(66.666666 * 1e6));
Ady Abraham29d16cb2021-03-08 13:19:21 -0800100 } else if (mExpectedPresentTimeForVsyncId >= 0) {
101 ASSERT_EQ(presentFence->wait(3000), NO_ERROR);
102 // We give 4ms for prediction error
103 ASSERT_GE(presentFence->getSignalTime(),
104 mExpectedPresentTimeForVsyncId - 4'000'000);
Valerie Haue9137b72019-08-27 13:22:18 -0700105 }
106 } else {
107 ASSERT_EQ(presentFence, nullptr) << "transaction shouldn't have been presented";
108 ASSERT_EQ(latchTime, -1) << "unpresented transactions shouldn't be latched";
109 }
110
111 ASSERT_EQ(surfaceControlStats.size(), mExpectedSurfaceResults.size())
112 << "wrong number of surfaces";
113
114 for (const auto& stats : surfaceControlStats) {
115 ASSERT_NE(stats.surfaceControl, nullptr) << "returned null surface control";
116
117 const auto& expectedSurfaceResult = mExpectedSurfaceResults.find(stats.surfaceControl);
118 ASSERT_NE(expectedSurfaceResult, mExpectedSurfaceResults.end())
119 << "unexpected surface control";
120 expectedSurfaceResult->second.verifySurfaceControlStats(stats, latchTime);
121 }
122 }
123
124private:
125 class ExpectedSurfaceResult {
126 public:
127 ExpectedSurfaceResult(ExpectedResult::Buffer bufferResult,
128 ExpectedResult::PreviousBuffer previousBufferResult)
129 : mBufferResult(bufferResult), mPreviousBufferResult(previousBufferResult) {}
130
131 void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,
132 nsecs_t latchTime) const {
Valerie Hau871d6352020-01-29 08:44:02 -0800133 const auto&
134 [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence,
135 transformHint,
136 frameEvents] = surfaceControlStats;
Valerie Haue9137b72019-08-27 13:22:18 -0700137
138 ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)
139 << "bad acquire time";
140 ASSERT_LE(acquireTime, latchTime) << "acquire time should be <= latch time";
141
142 if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) {
143 ASSERT_NE(previousReleaseFence, nullptr)
144 << "failed to set release prev buffer fence";
145 } else if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::NOT_RELEASED) {
146 ASSERT_EQ(previousReleaseFence, nullptr)
147 << "should not have set released prev buffer fence";
148 }
149 }
150
151 private:
152 ExpectedResult::Buffer mBufferResult;
153 ExpectedResult::PreviousBuffer mPreviousBufferResult;
154 };
155
156 struct SCHash {
157 std::size_t operator()(const sp<SurfaceControl>& sc) const {
158 return std::hash<IBinder*>{}(sc->getHandle().get());
159 }
160 };
161 ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED;
162 nsecs_t mExpectedPresentTime = -1;
Ady Abraham29d16cb2021-03-08 13:19:21 -0800163 nsecs_t mExpectedPresentTimeForVsyncId = -1;
Valerie Haue9137b72019-08-27 13:22:18 -0700164 std::unordered_map<sp<SurfaceControl>, ExpectedSurfaceResult, SCHash> mExpectedSurfaceResults;
165};
166
167class CallbackHelper {
168public:
169 static void function(void* callbackContext, nsecs_t latchTime, const sp<Fence>& presentFence,
170 const std::vector<SurfaceControlStats>& stats) {
171 if (!callbackContext) {
172 ALOGE("failed to get callback context");
173 }
174 CallbackHelper* helper = static_cast<CallbackHelper*>(callbackContext);
175 std::lock_guard lock(helper->mMutex);
176 helper->mCallbackDataQueue.emplace(latchTime, presentFence, stats);
177 helper->mConditionVariable.notify_all();
178 }
179
180 void getCallbackData(CallbackData* outData) {
181 std::unique_lock lock(mMutex);
182
183 if (mCallbackDataQueue.empty()) {
184 ASSERT_NE(mConditionVariable.wait_for(lock, std::chrono::seconds(3)),
185 std::cv_status::timeout)
186 << "did not receive callback";
187 }
188
189 *outData = std::move(mCallbackDataQueue.front());
190 mCallbackDataQueue.pop();
191 }
192
193 void verifyFinalState() {
194 // Wait to see if there are extra callbacks
195 std::this_thread::sleep_for(500ms);
196
197 std::lock_guard lock(mMutex);
198 EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received";
199 mCallbackDataQueue = {};
200 }
201
202 void* getContext() { return static_cast<void*>(this); }
203
204 std::mutex mMutex;
205 std::condition_variable mConditionVariable;
206 std::queue<CallbackData> mCallbackDataQueue;
207};
208}
209} // namespace android