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 <thread>
24 
25 namespace android {
26 
27 namespace {
28 
29 struct CallbackData {
30     CallbackData() = default;
CallbackDataCallbackData31     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 
40 class ExpectedResult {
41 public:
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 
reset()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 
addExpectedPresentTime(nsecs_t expectedPresentTime)80     void addExpectedPresentTime(nsecs_t expectedPresentTime) {
81         mExpectedPresentTime = expectedPresentTime;
82     }
83 
verifyCallbackData(const CallbackData & callbackData)84     void verifyCallbackData(const CallbackData& callbackData) const {
85         const auto& [latchTime, presentFence, surfaceControlStats] = callbackData;
86         if (mTransactionResult == ExpectedResult::Transaction::PRESENTED) {
87             ASSERT_GE(latchTime, 0) << "bad latch time";
88             ASSERT_NE(presentFence, nullptr);
89             if (mExpectedPresentTime >= 0) {
90                 ASSERT_EQ(presentFence->wait(3000), NO_ERROR);
91                 ASSERT_GE(presentFence->getSignalTime(), mExpectedPresentTime - nsecs_t(5 * 1e6));
92                 // if the panel is running at 30 hz, at the worst case, our expected time just
93                 // misses vsync and we have to wait another 33.3ms
94                 ASSERT_LE(presentFence->getSignalTime(),
95                           mExpectedPresentTime + nsecs_t(66.666666 * 1e6));
96             }
97         } else {
98             ASSERT_EQ(presentFence, nullptr) << "transaction shouldn't have been presented";
99             ASSERT_EQ(latchTime, -1) << "unpresented transactions shouldn't be latched";
100         }
101 
102         ASSERT_EQ(surfaceControlStats.size(), mExpectedSurfaceResults.size())
103                 << "wrong number of surfaces";
104 
105         for (const auto& stats : surfaceControlStats) {
106             ASSERT_NE(stats.surfaceControl, nullptr) << "returned null surface control";
107 
108             const auto& expectedSurfaceResult = mExpectedSurfaceResults.find(stats.surfaceControl);
109             ASSERT_NE(expectedSurfaceResult, mExpectedSurfaceResults.end())
110                     << "unexpected surface control";
111             expectedSurfaceResult->second.verifySurfaceControlStats(stats, latchTime);
112         }
113     }
114 
115 private:
116     class ExpectedSurfaceResult {
117     public:
ExpectedSurfaceResult(ExpectedResult::Buffer bufferResult,ExpectedResult::PreviousBuffer previousBufferResult)118         ExpectedSurfaceResult(ExpectedResult::Buffer bufferResult,
119                               ExpectedResult::PreviousBuffer previousBufferResult)
120               : mBufferResult(bufferResult), mPreviousBufferResult(previousBufferResult) {}
121 
verifySurfaceControlStats(const SurfaceControlStats & surfaceControlStats,nsecs_t latchTime)122         void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,
123                                        nsecs_t latchTime) const {
124             const auto&
125                     [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence,
126                      transformHint,
127                      frameEvents] = surfaceControlStats;
128 
129             ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)
130                     << "bad acquire time";
131             ASSERT_LE(acquireTime, latchTime) << "acquire time should be <= latch time";
132 
133             if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) {
134                 ASSERT_NE(previousReleaseFence, nullptr)
135                         << "failed to set release prev buffer fence";
136             } else if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::NOT_RELEASED) {
137                 ASSERT_EQ(previousReleaseFence, nullptr)
138                         << "should not have set released prev buffer fence";
139             }
140         }
141 
142     private:
143         ExpectedResult::Buffer mBufferResult;
144         ExpectedResult::PreviousBuffer mPreviousBufferResult;
145     };
146 
147     struct SCHash {
operatorSCHash148         std::size_t operator()(const sp<SurfaceControl>& sc) const {
149             return std::hash<IBinder*>{}(sc->getHandle().get());
150         }
151     };
152     ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED;
153     nsecs_t mExpectedPresentTime = -1;
154     std::unordered_map<sp<SurfaceControl>, ExpectedSurfaceResult, SCHash> mExpectedSurfaceResults;
155 };
156 
157 class CallbackHelper {
158 public:
function(void * callbackContext,nsecs_t latchTime,const sp<Fence> & presentFence,const std::vector<SurfaceControlStats> & stats)159     static void function(void* callbackContext, nsecs_t latchTime, const sp<Fence>& presentFence,
160                          const std::vector<SurfaceControlStats>& stats) {
161         if (!callbackContext) {
162             ALOGE("failed to get callback context");
163         }
164         CallbackHelper* helper = static_cast<CallbackHelper*>(callbackContext);
165         std::lock_guard lock(helper->mMutex);
166         helper->mCallbackDataQueue.emplace(latchTime, presentFence, stats);
167         helper->mConditionVariable.notify_all();
168     }
169 
getCallbackData(CallbackData * outData)170     void getCallbackData(CallbackData* outData) {
171         std::unique_lock lock(mMutex);
172 
173         if (mCallbackDataQueue.empty()) {
174             ASSERT_NE(mConditionVariable.wait_for(lock, std::chrono::seconds(3)),
175                       std::cv_status::timeout)
176                     << "did not receive callback";
177         }
178 
179         *outData = std::move(mCallbackDataQueue.front());
180         mCallbackDataQueue.pop();
181     }
182 
verifyFinalState()183     void verifyFinalState() {
184         // Wait to see if there are extra callbacks
185         std::this_thread::sleep_for(500ms);
186 
187         std::lock_guard lock(mMutex);
188         EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received";
189         mCallbackDataQueue = {};
190     }
191 
getContext()192     void* getContext() { return static_cast<void*>(this); }
193 
194     std::mutex mMutex;
195     std::condition_variable mConditionVariable;
196     std::queue<CallbackData> mCallbackDataQueue;
197 };
198 }
199 } // namespace android
200