1*38e8c45fSAndroid Build Coastguard Worker /* 2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project 3*38e8c45fSAndroid Build Coastguard Worker * 4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*38e8c45fSAndroid Build Coastguard Worker * 8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*38e8c45fSAndroid Build Coastguard Worker * 10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License. 15*38e8c45fSAndroid Build Coastguard Worker */ 16*38e8c45fSAndroid Build Coastguard Worker #pragma once 17*38e8c45fSAndroid Build Coastguard Worker 18*38e8c45fSAndroid Build Coastguard Worker #include <gtest/gtest.h> 19*38e8c45fSAndroid Build Coastguard Worker #include <gui/SurfaceComposerClient.h> 20*38e8c45fSAndroid Build Coastguard Worker #include <gui/SurfaceControl.h> 21*38e8c45fSAndroid Build Coastguard Worker #include <ui/Fence.h> 22*38e8c45fSAndroid Build Coastguard Worker #include <utils/Timers.h> 23*38e8c45fSAndroid Build Coastguard Worker #include <chrono> 24*38e8c45fSAndroid Build Coastguard Worker #include <thread> 25*38e8c45fSAndroid Build Coastguard Worker 26*38e8c45fSAndroid Build Coastguard Worker using ::std::literals::chrono_literals::operator""ms; 27*38e8c45fSAndroid Build Coastguard Worker using ::std::literals::chrono_literals::operator""s; 28*38e8c45fSAndroid Build Coastguard Worker 29*38e8c45fSAndroid Build Coastguard Worker namespace android { 30*38e8c45fSAndroid Build Coastguard Worker 31*38e8c45fSAndroid Build Coastguard Worker namespace { 32*38e8c45fSAndroid Build Coastguard Worker 33*38e8c45fSAndroid Build Coastguard Worker struct CallbackData { 34*38e8c45fSAndroid Build Coastguard Worker CallbackData() = default; CallbackDataCallbackData35*38e8c45fSAndroid Build Coastguard Worker CallbackData(nsecs_t time, const sp<Fence>& fence, 36*38e8c45fSAndroid Build Coastguard Worker const std::vector<SurfaceControlStats>& stats) 37*38e8c45fSAndroid Build Coastguard Worker : latchTime(time), presentFence(fence), surfaceControlStats(stats) {} 38*38e8c45fSAndroid Build Coastguard Worker 39*38e8c45fSAndroid Build Coastguard Worker nsecs_t latchTime; 40*38e8c45fSAndroid Build Coastguard Worker sp<Fence> presentFence; 41*38e8c45fSAndroid Build Coastguard Worker std::vector<SurfaceControlStats> surfaceControlStats; 42*38e8c45fSAndroid Build Coastguard Worker }; 43*38e8c45fSAndroid Build Coastguard Worker 44*38e8c45fSAndroid Build Coastguard Worker class ExpectedResult { 45*38e8c45fSAndroid Build Coastguard Worker public: 46*38e8c45fSAndroid Build Coastguard Worker enum Transaction { 47*38e8c45fSAndroid Build Coastguard Worker NOT_PRESENTED = 0, 48*38e8c45fSAndroid Build Coastguard Worker PRESENTED, 49*38e8c45fSAndroid Build Coastguard Worker }; 50*38e8c45fSAndroid Build Coastguard Worker 51*38e8c45fSAndroid Build Coastguard Worker enum Buffer { 52*38e8c45fSAndroid Build Coastguard Worker NOT_ACQUIRED = 0, 53*38e8c45fSAndroid Build Coastguard Worker ACQUIRED, 54*38e8c45fSAndroid Build Coastguard Worker ACQUIRED_NULL, 55*38e8c45fSAndroid Build Coastguard Worker }; 56*38e8c45fSAndroid Build Coastguard Worker 57*38e8c45fSAndroid Build Coastguard Worker enum PreviousBuffer { 58*38e8c45fSAndroid Build Coastguard Worker NOT_RELEASED = 0, 59*38e8c45fSAndroid Build Coastguard Worker RELEASED, 60*38e8c45fSAndroid Build Coastguard Worker UNKNOWN, 61*38e8c45fSAndroid Build Coastguard Worker }; 62*38e8c45fSAndroid Build Coastguard Worker reset()63*38e8c45fSAndroid Build Coastguard Worker void reset() { 64*38e8c45fSAndroid Build Coastguard Worker mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED; 65*38e8c45fSAndroid Build Coastguard Worker mExpectedSurfaceResults.clear(); 66*38e8c45fSAndroid Build Coastguard Worker } 67*38e8c45fSAndroid Build Coastguard Worker 68*38e8c45fSAndroid Build Coastguard Worker void addSurface(ExpectedResult::Transaction transactionResult, const sp<SurfaceControl>& layer, 69*38e8c45fSAndroid Build Coastguard Worker ExpectedResult::Buffer bufferResult = ACQUIRED, 70*38e8c45fSAndroid Build Coastguard Worker ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) { 71*38e8c45fSAndroid Build Coastguard Worker mTransactionResult = transactionResult; 72*38e8c45fSAndroid Build Coastguard Worker mExpectedSurfaceResults.emplace(std::piecewise_construct, std::forward_as_tuple(layer), 73*38e8c45fSAndroid Build Coastguard Worker std::forward_as_tuple(bufferResult, previousBufferResult)); 74*38e8c45fSAndroid Build Coastguard Worker } 75*38e8c45fSAndroid Build Coastguard Worker 76*38e8c45fSAndroid Build Coastguard Worker void addSurfaces(ExpectedResult::Transaction transactionResult, 77*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<SurfaceControl>>& layers, 78*38e8c45fSAndroid Build Coastguard Worker ExpectedResult::Buffer bufferResult = ACQUIRED, 79*38e8c45fSAndroid Build Coastguard Worker ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) { 80*38e8c45fSAndroid Build Coastguard Worker for (const auto& layer : layers) { 81*38e8c45fSAndroid Build Coastguard Worker addSurface(transactionResult, layer, bufferResult, previousBufferResult); 82*38e8c45fSAndroid Build Coastguard Worker } 83*38e8c45fSAndroid Build Coastguard Worker } 84*38e8c45fSAndroid Build Coastguard Worker addExpectedPresentTime(nsecs_t expectedPresentTime)85*38e8c45fSAndroid Build Coastguard Worker void addExpectedPresentTime(nsecs_t expectedPresentTime) { 86*38e8c45fSAndroid Build Coastguard Worker mExpectedPresentTime = expectedPresentTime; 87*38e8c45fSAndroid Build Coastguard Worker } 88*38e8c45fSAndroid Build Coastguard Worker addExpectedPresentTimeForVsyncId(nsecs_t expectedPresentTime)89*38e8c45fSAndroid Build Coastguard Worker void addExpectedPresentTimeForVsyncId(nsecs_t expectedPresentTime) { 90*38e8c45fSAndroid Build Coastguard Worker mExpectedPresentTimeForVsyncId = expectedPresentTime; 91*38e8c45fSAndroid Build Coastguard Worker } 92*38e8c45fSAndroid Build Coastguard Worker verifyCallbackData(const CallbackData & callbackData)93*38e8c45fSAndroid Build Coastguard Worker void verifyCallbackData(const CallbackData& callbackData) const { 94*38e8c45fSAndroid Build Coastguard Worker const auto& [latchTime, presentFence, surfaceControlStats] = callbackData; 95*38e8c45fSAndroid Build Coastguard Worker if (mTransactionResult == ExpectedResult::Transaction::PRESENTED) { 96*38e8c45fSAndroid Build Coastguard Worker ASSERT_GE(latchTime, 0) << "bad latch time"; 97*38e8c45fSAndroid Build Coastguard Worker ASSERT_NE(presentFence, nullptr); 98*38e8c45fSAndroid Build Coastguard Worker if (mExpectedPresentTime >= 0) { 99*38e8c45fSAndroid Build Coastguard Worker ASSERT_EQ(presentFence->wait(3000), NO_ERROR); 100*38e8c45fSAndroid Build Coastguard Worker ASSERT_GE(presentFence->getSignalTime(), mExpectedPresentTime - nsecs_t(5 * 1e6)); 101*38e8c45fSAndroid Build Coastguard Worker // if the panel is running at 30 hz, at the worst case, our expected time just 102*38e8c45fSAndroid Build Coastguard Worker // misses vsync and we have to wait another 33.3ms 103*38e8c45fSAndroid Build Coastguard Worker ASSERT_LE(presentFence->getSignalTime(), 104*38e8c45fSAndroid Build Coastguard Worker mExpectedPresentTime + nsecs_t(66.666666 * 1e6)); 105*38e8c45fSAndroid Build Coastguard Worker } else if (mExpectedPresentTimeForVsyncId >= 0) { 106*38e8c45fSAndroid Build Coastguard Worker ASSERT_EQ(presentFence->wait(3000), NO_ERROR); 107*38e8c45fSAndroid Build Coastguard Worker // We give 4ms for prediction error 108*38e8c45fSAndroid Build Coastguard Worker ASSERT_GE(presentFence->getSignalTime(), 109*38e8c45fSAndroid Build Coastguard Worker mExpectedPresentTimeForVsyncId - 4'000'000); 110*38e8c45fSAndroid Build Coastguard Worker } 111*38e8c45fSAndroid Build Coastguard Worker } else { 112*38e8c45fSAndroid Build Coastguard Worker ASSERT_EQ(presentFence, nullptr) << "transaction shouldn't have been presented"; 113*38e8c45fSAndroid Build Coastguard Worker ASSERT_EQ(latchTime, -1) << "unpresented transactions shouldn't be latched"; 114*38e8c45fSAndroid Build Coastguard Worker } 115*38e8c45fSAndroid Build Coastguard Worker 116*38e8c45fSAndroid Build Coastguard Worker ASSERT_EQ(surfaceControlStats.size(), mExpectedSurfaceResults.size()) 117*38e8c45fSAndroid Build Coastguard Worker << "wrong number of surfaces"; 118*38e8c45fSAndroid Build Coastguard Worker 119*38e8c45fSAndroid Build Coastguard Worker for (const auto& stats : surfaceControlStats) { 120*38e8c45fSAndroid Build Coastguard Worker ASSERT_NE(stats.surfaceControl, nullptr) << "returned null surface control"; 121*38e8c45fSAndroid Build Coastguard Worker 122*38e8c45fSAndroid Build Coastguard Worker const auto& expectedSurfaceResult = mExpectedSurfaceResults.find(stats.surfaceControl); 123*38e8c45fSAndroid Build Coastguard Worker ASSERT_NE(expectedSurfaceResult, mExpectedSurfaceResults.end()) 124*38e8c45fSAndroid Build Coastguard Worker << "unexpected surface control"; 125*38e8c45fSAndroid Build Coastguard Worker expectedSurfaceResult->second.verifySurfaceControlStats(stats, latchTime); 126*38e8c45fSAndroid Build Coastguard Worker } 127*38e8c45fSAndroid Build Coastguard Worker } 128*38e8c45fSAndroid Build Coastguard Worker 129*38e8c45fSAndroid Build Coastguard Worker private: 130*38e8c45fSAndroid Build Coastguard Worker class ExpectedSurfaceResult { 131*38e8c45fSAndroid Build Coastguard Worker public: ExpectedSurfaceResult(ExpectedResult::Buffer bufferResult,ExpectedResult::PreviousBuffer previousBufferResult)132*38e8c45fSAndroid Build Coastguard Worker ExpectedSurfaceResult(ExpectedResult::Buffer bufferResult, 133*38e8c45fSAndroid Build Coastguard Worker ExpectedResult::PreviousBuffer previousBufferResult) 134*38e8c45fSAndroid Build Coastguard Worker : mBufferResult(bufferResult), mPreviousBufferResult(previousBufferResult) {} 135*38e8c45fSAndroid Build Coastguard Worker verifySurfaceControlStats(const SurfaceControlStats & surfaceControlStats,nsecs_t)136*38e8c45fSAndroid Build Coastguard Worker void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, 137*38e8c45fSAndroid Build Coastguard Worker nsecs_t /* latchTime */) const { 138*38e8c45fSAndroid Build Coastguard Worker const auto& [surfaceControl, latch, acquireTimeOrFence, presentFence, 139*38e8c45fSAndroid Build Coastguard Worker previousReleaseFence, transformHint, frameEvents, ignore] = 140*38e8c45fSAndroid Build Coastguard Worker surfaceControlStats; 141*38e8c45fSAndroid Build Coastguard Worker 142*38e8c45fSAndroid Build Coastguard Worker nsecs_t acquireTime = -1; 143*38e8c45fSAndroid Build Coastguard Worker if (std::holds_alternative<nsecs_t>(acquireTimeOrFence)) { 144*38e8c45fSAndroid Build Coastguard Worker acquireTime = std::get<nsecs_t>(acquireTimeOrFence); 145*38e8c45fSAndroid Build Coastguard Worker } else { 146*38e8c45fSAndroid Build Coastguard Worker auto fence = std::get<sp<Fence>>(acquireTimeOrFence); 147*38e8c45fSAndroid Build Coastguard Worker if (fence) { 148*38e8c45fSAndroid Build Coastguard Worker ASSERT_EQ(fence->wait(3000), NO_ERROR); 149*38e8c45fSAndroid Build Coastguard Worker acquireTime = fence->getSignalTime(); 150*38e8c45fSAndroid Build Coastguard Worker } 151*38e8c45fSAndroid Build Coastguard Worker } 152*38e8c45fSAndroid Build Coastguard Worker 153*38e8c45fSAndroid Build Coastguard Worker if (mBufferResult == ExpectedResult::Buffer::ACQUIRED) { 154*38e8c45fSAndroid Build Coastguard Worker ASSERT_GT(acquireTime, 0) << "acquire time should be valid"; 155*38e8c45fSAndroid Build Coastguard Worker } else { 156*38e8c45fSAndroid Build Coastguard Worker ASSERT_LE(acquireTime, 0) << "acquire time should not be valid"; 157*38e8c45fSAndroid Build Coastguard Worker } 158*38e8c45fSAndroid Build Coastguard Worker ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED); 159*38e8c45fSAndroid Build Coastguard Worker 160*38e8c45fSAndroid Build Coastguard Worker if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) { 161*38e8c45fSAndroid Build Coastguard Worker ASSERT_NE(previousReleaseFence, nullptr) 162*38e8c45fSAndroid Build Coastguard Worker << "failed to set release prev buffer fence"; 163*38e8c45fSAndroid Build Coastguard Worker } else if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::NOT_RELEASED) { 164*38e8c45fSAndroid Build Coastguard Worker ASSERT_EQ(previousReleaseFence, nullptr) 165*38e8c45fSAndroid Build Coastguard Worker << "should not have set released prev buffer fence"; 166*38e8c45fSAndroid Build Coastguard Worker } 167*38e8c45fSAndroid Build Coastguard Worker } 168*38e8c45fSAndroid Build Coastguard Worker 169*38e8c45fSAndroid Build Coastguard Worker private: 170*38e8c45fSAndroid Build Coastguard Worker ExpectedResult::Buffer mBufferResult; 171*38e8c45fSAndroid Build Coastguard Worker ExpectedResult::PreviousBuffer mPreviousBufferResult; 172*38e8c45fSAndroid Build Coastguard Worker }; 173*38e8c45fSAndroid Build Coastguard Worker 174*38e8c45fSAndroid Build Coastguard Worker struct SCHash { operatorSCHash175*38e8c45fSAndroid Build Coastguard Worker std::size_t operator()(const sp<SurfaceControl>& sc) const { 176*38e8c45fSAndroid Build Coastguard Worker return std::hash<IBinder*>{}(sc->getHandle().get()); 177*38e8c45fSAndroid Build Coastguard Worker } 178*38e8c45fSAndroid Build Coastguard Worker }; 179*38e8c45fSAndroid Build Coastguard Worker ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED; 180*38e8c45fSAndroid Build Coastguard Worker nsecs_t mExpectedPresentTime = -1; 181*38e8c45fSAndroid Build Coastguard Worker nsecs_t mExpectedPresentTimeForVsyncId = -1; 182*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<sp<SurfaceControl>, ExpectedSurfaceResult, SCHash> mExpectedSurfaceResults; 183*38e8c45fSAndroid Build Coastguard Worker }; 184*38e8c45fSAndroid Build Coastguard Worker 185*38e8c45fSAndroid Build Coastguard Worker class CallbackHelper { 186*38e8c45fSAndroid Build Coastguard Worker public: function(void * callbackContext,nsecs_t latchTime,const sp<Fence> & presentFence,const std::vector<SurfaceControlStats> & stats)187*38e8c45fSAndroid Build Coastguard Worker static void function(void* callbackContext, nsecs_t latchTime, const sp<Fence>& presentFence, 188*38e8c45fSAndroid Build Coastguard Worker const std::vector<SurfaceControlStats>& stats) { 189*38e8c45fSAndroid Build Coastguard Worker if (!callbackContext) { 190*38e8c45fSAndroid Build Coastguard Worker ALOGE("failed to get callback context"); 191*38e8c45fSAndroid Build Coastguard Worker } 192*38e8c45fSAndroid Build Coastguard Worker CallbackHelper* helper = static_cast<CallbackHelper*>(callbackContext); 193*38e8c45fSAndroid Build Coastguard Worker std::lock_guard lock(helper->mMutex); 194*38e8c45fSAndroid Build Coastguard Worker helper->mCallbackDataQueue.emplace(latchTime, presentFence, stats); 195*38e8c45fSAndroid Build Coastguard Worker helper->mConditionVariable.notify_all(); 196*38e8c45fSAndroid Build Coastguard Worker } 197*38e8c45fSAndroid Build Coastguard Worker getCallbackData(CallbackData * outData)198*38e8c45fSAndroid Build Coastguard Worker void getCallbackData(CallbackData* outData) { 199*38e8c45fSAndroid Build Coastguard Worker std::unique_lock lock(mMutex); 200*38e8c45fSAndroid Build Coastguard Worker 201*38e8c45fSAndroid Build Coastguard Worker if (mCallbackDataQueue.empty()) { 202*38e8c45fSAndroid Build Coastguard Worker ASSERT_NE(mConditionVariable.wait_for(lock, std::chrono::seconds(3)), 203*38e8c45fSAndroid Build Coastguard Worker std::cv_status::timeout) 204*38e8c45fSAndroid Build Coastguard Worker << "did not receive callback"; 205*38e8c45fSAndroid Build Coastguard Worker } 206*38e8c45fSAndroid Build Coastguard Worker 207*38e8c45fSAndroid Build Coastguard Worker *outData = std::move(mCallbackDataQueue.front()); 208*38e8c45fSAndroid Build Coastguard Worker mCallbackDataQueue.pop(); 209*38e8c45fSAndroid Build Coastguard Worker } 210*38e8c45fSAndroid Build Coastguard Worker verifyFinalState()211*38e8c45fSAndroid Build Coastguard Worker void verifyFinalState() { 212*38e8c45fSAndroid Build Coastguard Worker // Wait to see if there are extra callbacks 213*38e8c45fSAndroid Build Coastguard Worker std::this_thread::sleep_for(500ms); 214*38e8c45fSAndroid Build Coastguard Worker 215*38e8c45fSAndroid Build Coastguard Worker std::lock_guard lock(mMutex); 216*38e8c45fSAndroid Build Coastguard Worker EXPECT_EQ(mCallbackDataQueue.size(), 0U) << "extra callbacks received"; 217*38e8c45fSAndroid Build Coastguard Worker mCallbackDataQueue = {}; 218*38e8c45fSAndroid Build Coastguard Worker } 219*38e8c45fSAndroid Build Coastguard Worker getContext()220*38e8c45fSAndroid Build Coastguard Worker void* getContext() { return static_cast<void*>(this); } 221*38e8c45fSAndroid Build Coastguard Worker 222*38e8c45fSAndroid Build Coastguard Worker std::mutex mMutex; 223*38e8c45fSAndroid Build Coastguard Worker std::condition_variable mConditionVariable; 224*38e8c45fSAndroid Build Coastguard Worker std::queue<CallbackData> mCallbackDataQueue; 225*38e8c45fSAndroid Build Coastguard Worker }; 226*38e8c45fSAndroid Build Coastguard Worker } // namespace 227*38e8c45fSAndroid Build Coastguard Worker } // namespace android 228