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     };
55 
56     enum PreviousBuffer {
57         NOT_RELEASED = 0,
58         RELEASED,
59         UNKNOWN,
60     };
61 
reset()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 
addExpectedPresentTime(nsecs_t expectedPresentTime)84     void addExpectedPresentTime(nsecs_t expectedPresentTime) {
85         mExpectedPresentTime = expectedPresentTime;
86     }
87 
addExpectedPresentTimeForVsyncId(nsecs_t expectedPresentTime)88     void addExpectedPresentTimeForVsyncId(nsecs_t expectedPresentTime) {
89         mExpectedPresentTimeForVsyncId = expectedPresentTime;
90     }
91 
verifyCallbackData(const CallbackData & callbackData)92     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));
104             } 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);
109             }
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 
128 private:
129     class ExpectedSurfaceResult {
130     public:
ExpectedSurfaceResult(ExpectedResult::Buffer bufferResult,ExpectedResult::PreviousBuffer previousBufferResult)131         ExpectedSurfaceResult(ExpectedResult::Buffer bufferResult,
132                               ExpectedResult::PreviousBuffer previousBufferResult)
133               : mBufferResult(bufferResult), mPreviousBufferResult(previousBufferResult) {}
134 
verifySurfaceControlStats(const SurfaceControlStats & surfaceControlStats,nsecs_t latchTime)135         void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,
136                                        nsecs_t latchTime) const {
137             const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence,
138                          transformHint, frameEvents, ignore] = surfaceControlStats;
139 
140             ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)
141                     << "bad acquire time";
142             ASSERT_LE(acquireTime, latchTime) << "acquire time should be <= latch time";
143 
144             if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) {
145                 ASSERT_NE(previousReleaseFence, nullptr)
146                         << "failed to set release prev buffer fence";
147             } else if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::NOT_RELEASED) {
148                 ASSERT_EQ(previousReleaseFence, nullptr)
149                         << "should not have set released prev buffer fence";
150             }
151         }
152 
153     private:
154         ExpectedResult::Buffer mBufferResult;
155         ExpectedResult::PreviousBuffer mPreviousBufferResult;
156     };
157 
158     struct SCHash {
operatorSCHash159         std::size_t operator()(const sp<SurfaceControl>& sc) const {
160             return std::hash<IBinder*>{}(sc->getHandle().get());
161         }
162     };
163     ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED;
164     nsecs_t mExpectedPresentTime = -1;
165     nsecs_t mExpectedPresentTimeForVsyncId = -1;
166     std::unordered_map<sp<SurfaceControl>, ExpectedSurfaceResult, SCHash> mExpectedSurfaceResults;
167 };
168 
169 class CallbackHelper {
170 public:
function(void * callbackContext,nsecs_t latchTime,const sp<Fence> & presentFence,const std::vector<SurfaceControlStats> & stats)171     static void function(void* callbackContext, nsecs_t latchTime, const sp<Fence>& presentFence,
172                          const std::vector<SurfaceControlStats>& stats) {
173         if (!callbackContext) {
174             ALOGE("failed to get callback context");
175         }
176         CallbackHelper* helper = static_cast<CallbackHelper*>(callbackContext);
177         std::lock_guard lock(helper->mMutex);
178         helper->mCallbackDataQueue.emplace(latchTime, presentFence, stats);
179         helper->mConditionVariable.notify_all();
180     }
181 
getCallbackData(CallbackData * outData)182     void getCallbackData(CallbackData* outData) {
183         std::unique_lock lock(mMutex);
184 
185         if (mCallbackDataQueue.empty()) {
186             ASSERT_NE(mConditionVariable.wait_for(lock, std::chrono::seconds(3)),
187                       std::cv_status::timeout)
188                     << "did not receive callback";
189         }
190 
191         *outData = std::move(mCallbackDataQueue.front());
192         mCallbackDataQueue.pop();
193     }
194 
verifyFinalState()195     void verifyFinalState() {
196         // Wait to see if there are extra callbacks
197         std::this_thread::sleep_for(500ms);
198 
199         std::lock_guard lock(mMutex);
200         EXPECT_EQ(mCallbackDataQueue.size(), 0U) << "extra callbacks received";
201         mCallbackDataQueue = {};
202     }
203 
getContext()204     void* getContext() { return static_cast<void*>(this); }
205 
206     std::mutex mMutex;
207     std::condition_variable mConditionVariable;
208     std::queue<CallbackData> mCallbackDataQueue;
209 };
210 } // namespace
211 } // namespace android
212