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