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

Commit bdd08ccc authored by Peiyong Lin's avatar Peiyong Lin
Browse files

Unify hwc2_device_t and HWComposer.

HWComposer can already represent the built-in hardware composer capabilities, a
device notation is not needed. HWComposer now directly manages all displays and
owns the lifetime of all displays.  The next step is to explore whether we can
safely deprecate all hwcomposer2.h types inside SurfaceFlinger, move to HIDL
types and eventually use AIDL types.

BUG: b/77585359
Test: build, boot.
Change-Id: Id0f77b49aa441bdbf578302a04ae03b5573eb2aa
parent f7308542
Loading
Loading
Loading
Loading
+0 −182
Original line number Diff line number Diff line
@@ -42,8 +42,6 @@ using android::HdrMetadata;
using android::Rect;
using android::Region;
using android::sp;
using android::hardware::Return;
using android::hardware::Void;

namespace HWC2 {

@@ -60,188 +58,8 @@ inline bool hasMetadataKey(const std::set<Hwc2::PerFrameMetadataKey>& keys,
    return keys.find(key) != keys.end();
}

class ComposerCallbackBridge : public Hwc2::IComposerCallback {
public:
    ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId,
                           bool vsyncSwitchingSupported)
          : mCallback(callback),
            mSequenceId(sequenceId),
            mVsyncSwitchingSupported(vsyncSwitchingSupported) {}

    Return<void> onHotplug(Hwc2::Display display,
                           IComposerCallback::Connection conn) override
    {
        HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
        mCallback->onHotplugReceived(mSequenceId, display, connection);
        return Void();
    }

    Return<void> onRefresh(Hwc2::Display display) override
    {
        mCallback->onRefreshReceived(mSequenceId, display);
        return Void();
    }

    Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
    {
        if (!mVsyncSwitchingSupported) {
            mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
        } else {
            ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
        }
        return Void();
    }

    Return<void> onVsync_2_4(Hwc2::Display display, int64_t timestamp,
                             Hwc2::VsyncPeriodNanos vsyncPeriodNanos) override {
        if (mVsyncSwitchingSupported) {
            // TODO(b/140201379): use vsyncPeriodNanos in the new DispSync
            mCallback->onVsyncReceived(mSequenceId, display, timestamp,
                                       std::make_optional(vsyncPeriodNanos));
        } else {
            ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
        }
        return Void();
    }

    Return<void> onVsyncPeriodTimingChanged(
            Hwc2::Display display,
            const Hwc2::VsyncPeriodChangeTimeline& updatedTimeline) override {
        hwc_vsync_period_change_timeline_t timeline;
        timeline.newVsyncAppliedTimeNanos = updatedTimeline.newVsyncAppliedTimeNanos;
        timeline.refreshRequired = updatedTimeline.refreshRequired;
        timeline.refreshTimeNanos = updatedTimeline.refreshTimeNanos;
        mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, timeline);
        return Void();
    }

private:
    ComposerCallback* mCallback;
    int32_t mSequenceId;
    const bool mVsyncSwitchingSupported;
};

} // namespace anonymous


// Device methods

Device::Device(std::unique_ptr<android::Hwc2::Composer> composer) : mComposer(std::move(composer)) {
    loadCapabilities();
}

void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {
    if (mRegisteredCallback) {
        ALOGW("Callback already registered. Ignored extra registration "
                "attempt.");
        return;
    }
    mRegisteredCallback = true;
    sp<ComposerCallbackBridge> callbackBridge(
            new ComposerCallbackBridge(callback, sequenceId,
                                       mComposer->isVsyncPeriodSwitchSupported()));
    mComposer->registerCallback(callbackBridge);
}

// Required by HWC2 device

std::string Device::dump() const
{
    return mComposer->dumpDebugInfo();
}

uint32_t Device::getMaxVirtualDisplayCount() const
{
    return mComposer->getMaxVirtualDisplayCount();
}

Error Device::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
                                           std::vector<uint8_t>* outData) const {
    auto intError = mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
    return static_cast<Error>(intError);
}

Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
        PixelFormat* format, Display** outDisplay)
{
    ALOGI("Creating virtual display");

    hwc2_display_t displayId = 0;
    auto intError = mComposer->createVirtualDisplay(width, height,
            format, &displayId);
    auto error = static_cast<Error>(intError);
    if (error != Error::None) {
        return error;
    }

    auto display = std::make_unique<impl::Display>(*mComposer.get(), mCapabilities, displayId,
                                                   DisplayType::Virtual);
    display->setConnected(true);
    *outDisplay = display.get();
    mDisplays.emplace(displayId, std::move(display));
    ALOGI("Created virtual display");
    return Error::None;
}

void Device::destroyDisplay(hwc2_display_t displayId)
{
    ALOGI("Destroying display %" PRIu64, displayId);
    mDisplays.erase(displayId);
}

void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
    if (connection == Connection::Connected) {
        // If we get a hotplug connected event for a display we already have,
        // destroy the display and recreate it. This will force us to requery
        // the display params and recreate all layers on that display.
        auto oldDisplay = getDisplayById(displayId);
        if (oldDisplay != nullptr && oldDisplay->isConnected()) {
            ALOGI("Hotplug connecting an already connected display."
                    " Clearing old display state.");
        }
        mDisplays.erase(displayId);

        auto newDisplay = std::make_unique<impl::Display>(*mComposer.get(), mCapabilities,
                                                          displayId, DisplayType::Physical);
        newDisplay->setConnected(true);
        mDisplays.emplace(displayId, std::move(newDisplay));
    } else if (connection == Connection::Disconnected) {
        // The display will later be destroyed by a call to
        // destroyDisplay(). For now we just mark it disconnected.
        auto display = getDisplayById(displayId);
        if (display) {
            display->setConnected(false);
        } else {
            ALOGW("Attempted to disconnect unknown display %" PRIu64,
                  displayId);
        }
    }
}

// Other Device methods

Display* Device::getDisplayById(hwc2_display_t id) {
    auto iter = mDisplays.find(id);
    return iter == mDisplays.end() ? nullptr : iter->second.get();
}

// Device initialization methods

void Device::loadCapabilities()
{
    static_assert(sizeof(Capability) == sizeof(int32_t),
            "Capability size has changed");
    auto capabilities = mComposer->getCapabilities();
    for (auto capability : capabilities) {
        mCapabilities.emplace(static_cast<Capability>(capability));
    }
}

Error Device::flushCommands()
{
    return static_cast<Error>(mComposer->executeCommands());
}

// Display methods
Display::~Display() = default;

+0 −51
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ namespace android {

namespace HWC2 {

class Display;
class Layer;
using VsyncPeriodChangeConstraints = hwc_vsync_period_change_constraints_t;
using VsyncPeriodChangeTimeline = hwc_vsync_period_change_timeline_t;
@@ -81,56 +80,6 @@ class ComposerCallback {
    virtual ~ComposerCallback() = default;
};

// C++ Wrapper around hwc2_device_t. Load all functions pointers
// and handle callback registration.
class Device
{
public:
    explicit Device(std::unique_ptr<android::Hwc2::Composer> composer);

    void registerCallback(ComposerCallback* callback, int32_t sequenceId);

    // Required by HWC2

    std::string dump() const;

    const std::unordered_set<Capability>& getCapabilities() const {
        return mCapabilities;
    };

    uint32_t getMaxVirtualDisplayCount() const;
    Error getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
                                       std::vector<uint8_t>* outData) const;

    Error createVirtualDisplay(uint32_t width, uint32_t height,
            android::ui::PixelFormat* format, Display** outDisplay);
    void destroyDisplay(hwc2_display_t displayId);

    void onHotplug(hwc2_display_t displayId, Connection connection);

    // Other Device methods

    Display* getDisplayById(hwc2_display_t id);

    android::Hwc2::Composer* getComposer() { return mComposer.get(); }

    // We buffer most state changes and flush them implicitly with
    // Display::validate, Display::present, and Display::presentOrValidate.
    // This method provides an explicit way to flush state changes to HWC.
    Error flushCommands();

private:
    // Initialization methods

    void loadCapabilities();

    // Member variables
    std::unique_ptr<android::Hwc2::Composer> mComposer;
    std::unordered_set<Capability> mCapabilities;
    std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
    bool mRegisteredCallback = false;
};

// Convenience C++ class to access hwc2_device_t Display functions directly.
class Display {
public:
+141 −30
Original line number Diff line number Diff line
@@ -65,14 +65,88 @@
#define RETURN_IF_HWC_ERROR(error, displayId, ...) \
    RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)

namespace {

using android::hardware::Return;
using android::hardware::Void;

class ComposerCallbackBridge : public android::Hwc2::IComposerCallback {
public:
    ComposerCallbackBridge(HWC2::ComposerCallback* callback, int32_t sequenceId,
                           bool vsyncSwitchingSupported)
          : mCallback(callback),
            mSequenceId(sequenceId),
            mVsyncSwitchingSupported(vsyncSwitchingSupported) {}

    android::hardware::Return<void> onHotplug(
            android::Hwc2::Display display,
            android::Hwc2::IComposerCallback::Connection conn) override {
        HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
        mCallback->onHotplugReceived(mSequenceId, display, connection);
        return android::hardware::Void();
    }

    android::hardware::Return<void> onRefresh(android::Hwc2::Display display) override {
        mCallback->onRefreshReceived(mSequenceId, display);
        return android::hardware::Void();
    }

    android::hardware::Return<void> onVsync(android::Hwc2::Display display,
                                            int64_t timestamp) override {
        if (!mVsyncSwitchingSupported) {
            mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
        } else {
            ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
        }
        return android::hardware::Void();
    }

    android::hardware::Return<void> onVsync_2_4(
            android::Hwc2::Display display, int64_t timestamp,
            android::Hwc2::VsyncPeriodNanos vsyncPeriodNanos) override {
        if (mVsyncSwitchingSupported) {
            // TODO(b/140201379): use vsyncPeriodNanos in the new DispSync
            mCallback->onVsyncReceived(mSequenceId, display, timestamp,
                                       std::make_optional(vsyncPeriodNanos));
        } else {
            ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
        }
        return android::hardware::Void();
    }

    android::hardware::Return<void> onVsyncPeriodTimingChanged(
            android::Hwc2::Display display,
            const android::Hwc2::VsyncPeriodChangeTimeline& updatedTimeline) override {
        hwc_vsync_period_change_timeline_t timeline;
        timeline.newVsyncAppliedTimeNanos = updatedTimeline.newVsyncAppliedTimeNanos;
        timeline.refreshRequired = updatedTimeline.refreshRequired;
        timeline.refreshTimeNanos = updatedTimeline.refreshTimeNanos;
        mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, timeline);
        return android::hardware::Void();
    }

private:
    HWC2::ComposerCallback* mCallback;
    const int32_t mSequenceId;
    const bool mVsyncSwitchingSupported;
};

} // namespace

namespace android {

HWComposer::~HWComposer() = default;

namespace impl {

HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
      : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {}
HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) : mComposer(std::move(composer)) {
    loadCapabilities();
}

HWComposer::HWComposer(const std::string& composerServiceName)
      : mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {
    loadCapabilities();
}

HWComposer::~HWComposer() {
    mDisplayData.clear();
@@ -80,12 +154,21 @@ HWComposer::~HWComposer() {

void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
                                  int32_t sequenceId) {
    mHwcDevice->registerCallback(callback, sequenceId);
    if (mRegisteredCallback) {
        ALOGW("Callback already registered. Ignored extra registration attempt.");
        return;
    }
    mRegisteredCallback = true;
    sp<ComposerCallbackBridge> callbackBridge(
            new ComposerCallbackBridge(callback, sequenceId,
                                       mComposer->isVsyncPeriodSwitchSupported()));
    mComposer->registerCallback(callbackBridge);
}

bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
                                              DisplayIdentificationData* outData) const {
    const auto error = mHwcDevice->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
    const auto error = static_cast<HWC2::Error>(
            mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
    if (error != HWC2::Error::None) {
        if (error != HWC2::Error::Unsupported) {
            LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
@@ -95,9 +178,8 @@ bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8
    return true;
}

bool HWComposer::hasCapability(HWC2::Capability capability) const
{
    return mHwcDevice->getCapabilities().count(capability) > 0;
bool HWComposer::hasCapability(HWC2::Capability capability) const {
    return mCapabilities.count(capability) > 0;
}

bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId,
@@ -133,13 +215,33 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hw
          hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external",
          to_string(info->id).c_str(), hwcDisplayId);

    mHwcDevice->onHotplug(hwcDisplayId, connection);

    // Disconnect is handled through HWComposer::disconnectDisplay via
    // SurfaceFlinger's onHotplugReceived callback handling
    if (connection == HWC2::Connection::Connected) {
        mDisplayData[info->id].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId);
        auto& displayData = mDisplayData[info->id];
        // If we get a hotplug connected event for a display we already have,
        // destroy the display and recreate it. This will force us to requery
        // the display params and recreate all layers on that display.
        if (displayData.hwcDisplay != nullptr && displayData.hwcDisplay->isConnected()) {
            ALOGI("Hotplug connecting an already connected display."
                  " Clearing old display state.");
        }
        displayData.hwcDisplay.reset();
        auto newDisplay =
                std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
                                                      HWC2::DisplayType::Physical);
        newDisplay->setConnected(true);
        displayData.hwcDisplay = std::move(newDisplay);
        mPhysicalDisplayIdMap[hwcDisplayId] = info->id;
    } else if (connection == HWC2::Connection::Disconnected) {
        // The display will later be destroyed by a call to
        // destroyDisplay(). For now we just mark it disconnected.
        auto& displayData = mDisplayData[info->id];
        if (displayData.hwcDisplay) {
            displayData.hwcDisplay->setConnected(false);
        } else {
            ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
        }
        // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
        // via SurfaceFlinger's onHotplugReceived callback handling
    }

    return info;
@@ -197,14 +299,18 @@ std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint
              height, SurfaceFlinger::maxVirtualDisplaySize);
        return {};
    }
    HWC2::Display* display;
    auto error = mHwcDevice->createVirtualDisplay(width, height, format,
            &display);
    hwc2_display_t hwcDisplayId = 0;
    const auto error = static_cast<HWC2::Error>(
            mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
    if (error != HWC2::Error::None) {
        ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
        return {};
    }

    auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
                                                         hwcDisplayId, HWC2::DisplayType::Virtual);
    display->setConnected(true);

    DisplayId displayId;
    if (mFreeVirtualDisplayIds.empty()) {
        displayId = getVirtualDisplayId(mNextVirtualDisplayId++);
@@ -214,7 +320,7 @@ std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint
    }

    auto& displayData = mDisplayData[displayId];
    displayData.hwcDisplay = display;
    displayData.hwcDisplay = std::move(display);
    displayData.isVirtual = true;

    --mRemainingHwcVirtualDisplays;
@@ -224,9 +330,8 @@ std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint
HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
    RETURN_IF_INVALID_DISPLAY(displayId, nullptr);

    auto display = mDisplayData[displayId].hwcDisplay;
    HWC2::Layer* layer;
    auto error = display->createLayer(&layer);
    auto error = mDisplayData[displayId].hwcDisplay->createLayer(&layer);
    RETURN_IF_HWC_ERROR(error, displayId, nullptr);
    return layer;
}
@@ -234,8 +339,7 @@ HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) {
    RETURN_IF_INVALID_DISPLAY(displayId);

    auto display = mDisplayData[displayId].hwcDisplay;
    auto error = display->destroyLayer(layer);
    auto error = mDisplayData[displayId].hwcDisplay->destroyLayer(layer);
    RETURN_IF_HWC_ERROR(error, displayId);
}

@@ -484,8 +588,8 @@ status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {

    if (displayData.validateWasSkipped) {
        // explicitly flush all pending commands
        auto error = mHwcDevice->flushCommands();
        RETURN_IF_HWC_ERROR_FOR("flushCommands", error, displayId, UNKNOWN_ERROR);
        auto error = static_cast<HWC2::Error>(mComposer->executeCommands());
        RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
        RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
        return NO_ERROR;
    }
@@ -600,8 +704,6 @@ void HWComposer::disconnectDisplay(DisplayId displayId) {
    }

    const auto hwcDisplayId = displayData.hwcDisplay->getId();
    mPhysicalDisplayIdMap.erase(hwcDisplayId);
    mDisplayData.erase(displayId);

    // TODO(b/74619554): Select internal/external display from remaining displays.
    if (hwcDisplayId == mInternalHwcDisplayId) {
@@ -609,8 +711,8 @@ void HWComposer::disconnectDisplay(DisplayId displayId) {
    } else if (hwcDisplayId == mExternalHwcDisplayId) {
        mExternalHwcDisplayId.reset();
    }

    mHwcDevice->destroyDisplay(hwcDisplayId);
    mPhysicalDisplayIdMap.erase(hwcDisplayId);
    mDisplayData.erase(displayId);
}

status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
@@ -761,10 +863,7 @@ status_t HWComposer::setContentType(DisplayId displayId, HWC2::ContentType conte
}

void HWComposer::dump(std::string& result) const {
    // TODO: In order to provide a dump equivalent to HWC1, we need to shadow
    // all the state going into the layers. This is probably better done in
    // Layer itself, but it's going to take a bit of work to get there.
    result.append(mHwcDevice->dump());
    result.append(mComposer->dumpDebugInfo());
}

std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const {
@@ -830,5 +929,17 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_displ
                                                                           : "External display"};
}

void HWComposer::loadCapabilities() {
    static_assert(sizeof(HWC2::Capability) == sizeof(int32_t), "Capability size has changed");
    auto capabilities = mComposer->getCapabilities();
    for (auto capability : capabilities) {
        mCapabilities.emplace(static_cast<HWC2::Capability>(capability));
    }
}

uint32_t HWComposer::getMaxVirtualDisplayCount() const {
    return mComposer->getMaxVirtualDisplayCount();
}

} // namespace impl
} // namespace android
+9 −7
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ namespace impl {
class HWComposer final : public android::HWComposer {
public:
    explicit HWComposer(std::unique_ptr<Hwc2::Composer> composer);
    explicit HWComposer(const std::string& composerServiceName);

    ~HWComposer() override;

@@ -325,7 +326,7 @@ public:
    // for debugging ----------------------------------------------------------
    void dump(std::string& out) const override;

    Hwc2::Composer* getComposer() const override { return mHwcDevice->getComposer(); }
    Hwc2::Composer* getComposer() const override { return mComposer.get(); }

    // TODO(b/74619554): Remove special cases for internal/external display.
    std::optional<hwc2_display_t> getInternalHwcDisplayId() const override {
@@ -343,11 +344,12 @@ private:
    friend TestableSurfaceFlinger;

    std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId);
    void loadCapabilities();
    uint32_t getMaxVirtualDisplayCount() const;

    struct DisplayData {
        bool isVirtual = false;

        HWC2::Display* hwcDisplay = nullptr;
        std::unique_ptr<HWC2::Display> hwcDisplay;
        sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
        std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
        buffer_handle_t outbufHandle = nullptr;
@@ -369,9 +371,9 @@ private:

    std::unordered_map<DisplayId, DisplayData> mDisplayData;

    // This must be destroyed before mDisplayData, because destructor may call back into HWComposer
    // and look up DisplayData.
    std::unique_ptr<HWC2::Device> mHwcDevice;
    std::unique_ptr<android::Hwc2::Composer> mComposer;
    std::unordered_set<HWC2::Capability> mCapabilities;
    bool mRegisteredCallback = false;

    std::unordered_map<hwc2_display_t, DisplayId> mPhysicalDisplayIdMap;
    std::optional<hwc2_display_t> mInternalHwcDisplayId;
@@ -380,7 +382,7 @@ private:

    std::unordered_set<DisplayId> mFreeVirtualDisplayIds;
    uint32_t mNextVirtualDisplayId = 0;
    uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()};
    uint32_t mRemainingHwcVirtualDisplays{getMaxVirtualDisplayCount()};
};

} // namespace impl
+1 −2
Original line number Diff line number Diff line
@@ -52,8 +52,7 @@ std::unique_ptr<EventControlThread> DefaultFactory::createEventControlThread(
}

std::unique_ptr<HWComposer> DefaultFactory::createHWComposer(const std::string& serviceName) {
    return std::make_unique<android::impl::HWComposer>(
            std::make_unique<Hwc2::impl::Composer>(serviceName));
    return std::make_unique<android::impl::HWComposer>(serviceName);
}

std::unique_ptr<MessageQueue> DefaultFactory::createMessageQueue() {
Loading