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