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