Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e79f2881 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Iaad31c0d,I76b824f2

* changes:
  SurfaceFlinger: add Transaction test for setAllowedDisplayConfigs
  SurfaceFlinger: add a unit test for DispSyncSource
parents 487bda0c df9df4ad
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -453,7 +453,10 @@ DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) {
    mThread = new DispSyncThread(name, mTraceDetailedInfo);
}

DispSync::~DispSync() {}
DispSync::~DispSync() {
    mThread->stop();
    mThread->requestExitAndWait();
}

void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
    mIgnorePresentFences = !hasSyncFramework;
+62 −1
Original line number Diff line number Diff line
@@ -32,8 +32,9 @@
#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
#include <hardware/hwcomposer_defs.h>
#include <private/android_filesystem_config.h>
#include <private/gui/ComposerService.h>

#include <ui/ColorSpace.h>
#include <ui/DisplayInfo.h>
@@ -5522,4 +5523,64 @@ TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) {
    sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
}

class DisplayActiveConfigTest : public ::testing::Test {
protected:
    void SetUp() override {
        mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
        SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &mDisplayconfigs);
        EXPECT_GT(mDisplayconfigs.size(), 0);

        // set display power to on to make sure config can be changed
        SurfaceComposerClient::setDisplayPowerMode(mDisplayToken, HWC_POWER_MODE_NORMAL);
    }

    sp<IBinder> mDisplayToken;
    Vector<DisplayInfo> mDisplayconfigs;
};

TEST_F(DisplayActiveConfigTest, allConfigsAllowed) {
    std::vector<int32_t> allowedConfigs;

    // Add all configs to the allowed configs
    for (int i = 0; i < mDisplayconfigs.size(); i++) {
        allowedConfigs.push_back(i);
    }

    status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs);
    EXPECT_EQ(res, NO_ERROR);

    std::vector<int32_t> outConfigs;
    res = SurfaceComposerClient::getAllowedDisplayConfigs(mDisplayToken, &outConfigs);
    EXPECT_EQ(res, NO_ERROR);
    EXPECT_EQ(allowedConfigs, outConfigs);
}

TEST_F(DisplayActiveConfigTest, changeAllowedConfig) {
    // we need at least 2 configs available for this test
    if (mDisplayconfigs.size() <= 1) return;

    int activeConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken);

    // We want to set the allowed config to everything but the active config
    std::vector<int32_t> allowedConfigs;
    for (int i = 0; i < mDisplayconfigs.size(); i++) {
        if (i != activeConfig) {
            allowedConfigs.push_back(i);
        }
    }

    status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs);
    EXPECT_EQ(res, NO_ERROR);

    // Allow some time for the config change
    std::this_thread::sleep_for(200ms);

    int newActiveConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken);
    EXPECT_NE(activeConfig, newActiveConfig);

    // Make sure the new config is part of allowed config
    EXPECT_TRUE(std::find(allowedConfigs.begin(), allowedConfigs.end(), newActiveConfig) !=
                allowedConfigs.end());
}

} // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ cc_test {
        "libsurfaceflinger_unittest_main.cpp",
        "AllowedDisplayConfigsTest.cpp",
        "CompositionTest.cpp",
        "DispSyncSourceTest.cpp",
        "DisplayIdentificationTest.cpp",
        "DisplayTransactionTest.cpp",
        "EventControlThreadTest.cpp",
+164 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"
#define LOG_NDEBUG 0

#include <inttypes.h>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <log/log.h>

#include "AsyncCallRecorder.h"
#include "Scheduler/DispSyncSource.h"
#include "mock/MockDispSync.h"

namespace android {
namespace {

using namespace std::chrono_literals;
using testing::Return;

class DispSyncSourceTest : public testing::Test, private VSyncSource::Callback {
protected:
    DispSyncSourceTest();
    ~DispSyncSourceTest() override;

    void createDispSync();
    void createDispSyncSource();

    void onVSyncEvent(nsecs_t when) override;

    std::unique_ptr<mock::DispSync> mDispSync;
    std::unique_ptr<DispSyncSource> mDispSyncSource;

    AsyncCallRecorder<void (*)(nsecs_t)> mVSyncEventCallRecorder;

    static constexpr std::chrono::nanoseconds mPhaseOffset = 6ms;
    static constexpr int mIterations = 100;
};

DispSyncSourceTest::DispSyncSourceTest() {
    const ::testing::TestInfo* const test_info =
            ::testing::UnitTest::GetInstance()->current_test_info();
    ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
}

DispSyncSourceTest::~DispSyncSourceTest() {
    const ::testing::TestInfo* const test_info =
            ::testing::UnitTest::GetInstance()->current_test_info();
    ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}

void DispSyncSourceTest::onVSyncEvent(nsecs_t when) {
    ALOGD("onVSyncEvent: %" PRId64, when);

    mVSyncEventCallRecorder.recordCall(when);
}

void DispSyncSourceTest::createDispSync() {
    mDispSync = std::make_unique<mock::DispSync>();
}

void DispSyncSourceTest::createDispSyncSource() {
    createDispSync();
    mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(), true,
                                                       "DispSyncSourceTest");
    mDispSyncSource->setCallback(this);
}

/* ------------------------------------------------------------------------
 * Test cases
 */

TEST_F(DispSyncSourceTest, createDispSync) {
    createDispSync();
    EXPECT_TRUE(mDispSync);
}

TEST_F(DispSyncSourceTest, createDispSyncSource) {
    createDispSyncSource();
    EXPECT_TRUE(mDispSyncSource);
}

TEST_F(DispSyncSourceTest, noCallbackAfterInit) {
    createDispSyncSource();
    EXPECT_TRUE(mDispSyncSource);

    // DispSyncSource starts with Vsync disabled
    mDispSync->triggerCallback();
    EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());
}

TEST_F(DispSyncSourceTest, waitForCallbacks) {
    createDispSyncSource();
    EXPECT_TRUE(mDispSyncSource);

    mDispSyncSource->setVSyncEnabled(true);
    EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count());

    for (int i = 0; i < mIterations; i++) {
        mDispSync->triggerCallback();
        EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value());
    }
}

TEST_F(DispSyncSourceTest, waitForCallbacksWithPhaseChange) {
    createDispSyncSource();
    EXPECT_TRUE(mDispSyncSource);

    mDispSyncSource->setVSyncEnabled(true);
    EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count());

    for (int i = 0; i < mIterations; i++) {
        mDispSync->triggerCallback();
        EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value());
    }

    EXPECT_CALL(*mDispSync, getPeriod()).Times(1).WillOnce(Return(16666666));
    mDispSyncSource->setPhaseOffset((mPhaseOffset / 2).count());

    EXPECT_EQ(mDispSync->getCallbackPhase(), (mPhaseOffset / 2).count());

    for (int i = 0; i < mIterations; i++) {
        mDispSync->triggerCallback();
        EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value());
    }
}

TEST_F(DispSyncSourceTest, pauseCallbacks) {
    createDispSyncSource();
    EXPECT_TRUE(mDispSyncSource);

    mDispSyncSource->setVSyncEnabled(true);
    EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count());
    mDispSync->triggerCallback();
    EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value());

    mDispSyncSource->pauseVsyncCallback(true);
    mDispSync->triggerCallback();
    EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());

    mDispSyncSource->pauseVsyncCallback(false);
    mDispSync->triggerCallback();
    EXPECT_TRUE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());
}

} // namespace
} // namespace android
+35 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#include "mock/MockDispSync.h"
#include <thread>

namespace android {
namespace mock {
@@ -23,5 +24,39 @@ namespace mock {
DispSync::DispSync() = default;
DispSync::~DispSync() = default;

status_t DispSync::addEventListener(const char* /*name*/, nsecs_t phase, Callback* callback,
                                    nsecs_t /*lastCallbackTime*/) {
    if (mCallback.callback != nullptr) {
        return BAD_VALUE;
    }

    mCallback = {callback, phase};
    return NO_ERROR;
}
status_t DispSync::removeEventListener(Callback* callback, nsecs_t* /*outLastCallback*/) {
    if (mCallback.callback != callback) {
        return BAD_VALUE;
    }

    mCallback = {nullptr, 0};
    return NO_ERROR;
}

status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) {
    if (mCallback.callback != callback) {
        return BAD_VALUE;
    }

    mCallback.phase = phase;
    return NO_ERROR;
}

void DispSync::triggerCallback() {
    if (mCallback.callback == nullptr) return;

    mCallback.callback->onDispSyncEvent(
            std::chrono::steady_clock::now().time_since_epoch().count());
}

} // namespace mock
} // namespace android
Loading