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