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