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

Commit 2ae2b3bd authored by Lloyd Pique's avatar Lloyd Pique
Browse files

Allow a primary display disconnect

This patch forwards the primary display disconnect event to the
Framework, and otherwise ensures that SurfaceFlinger does not crash
while there is no primary display.

Note that the Framework does not yet accept this change. In particular
the ActivityManager ActivityStackSupervisor code promptly asserts that
one cannot remove the primary display. With this assertion disabled, the
framework does not crash (surprisingly). And if the Framework
subsequently receives a primary display connect event, it does not seem
to do anything useful -- the display remains in a default off state, and
no layer stack/viewport/etc is set on it.

Bug: 38464421
Test: Works (with workarounds as noted) on a Chromebook
Test: Added Unit test passes on Pixel 1 XL

Change-Id: Ia11439030efdc53bc17474b71a0ffb3d3085bb49
parent 715a2c13
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -76,6 +76,10 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
            SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
}

void FramebufferSurface::resizeBuffers(const uint32_t width, const uint32_t height) {
    mConsumer->setDefaultBufferSize(width, height);
}

status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
    return NO_ERROR;
}
+1 −3
Original line number Diff line number Diff line
@@ -46,9 +46,7 @@ public:
    virtual void onFrameCommitted();
    virtual void dumpAsString(String8& result) const;

    // Cannot resize a buffers in a FramebufferSurface. Only works with virtual
    // displays.
    virtual void resizeBuffers(const uint32_t /*w*/, const uint32_t /*h*/) { };
    virtual void resizeBuffers(const uint32_t width, const uint32_t height);

    virtual const sp<Fence>& getClientTargetAcquireFence() const override;

+29 −25
Original line number Diff line number Diff line
@@ -798,7 +798,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,

            // TODO: this needs to go away (currently needed only by webkit)
            sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
            info.orientation = hw->getOrientation();
            info.orientation = hw ? hw->getOrientation() : 0;
        } else {
            // TODO: where should this value come from?
            static const int TV_DENSITY = 213;
@@ -1596,7 +1596,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)

    getBE().mGlCompositionDoneTimeline.updateSignalTimes();
    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
    if (getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
    if (hw && getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
        glCompositionDoneFenceTime =
                std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
        getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
@@ -1641,7 +1641,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    }

    if (!hasSyncFramework) {
        if (hw->isDisplayOn()) {
        if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && hw->isDisplayOn()) {
            enableHardwareVsync();
        }
    }
@@ -1652,7 +1652,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
        if (presentFenceTime->isValid()) {
            mAnimFrameTracker.setActualPresentFence(
                    std::move(presentFenceTime));
        } else {
        } else if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
            // The HWC doesn't support present fences, so use the refresh
            // timestamp instead.
            nsecs_t presentTime =
@@ -1662,7 +1662,8 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
        mAnimFrameTracker.advanceFrame();
    }

    if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
    if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) &&
            hw->getPowerMode() == HWC_POWER_MODE_OFF) {
        return;
    }

@@ -2005,11 +2006,13 @@ void SurfaceFlinger::postFramebuffer()
    mDebugInSwapBuffers = 0;

    // |mStateLock| not needed as we are on the main thread
    if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
        uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
        if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
            logFrameStats();
        }
    }
}

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
@@ -2129,20 +2132,16 @@ void SurfaceFlinger::processDisplayChangesLocked() {
            const ssize_t j = curr.indexOfKey(draw.keyAt(i));
            if (j < 0) {
                // in drawing state but not in current state
                if (!draw[i].isMainDisplay()) {
                // Call makeCurrent() on the primary display so we can
                // be sure that nothing associated with this display
                // is current.
                const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
                    defaultDisplay->makeCurrent();
                if (defaultDisplay != nullptr) defaultDisplay->makeCurrent();
                sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
                if (hw != nullptr) hw->disconnect(getHwComposer());
                if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
                    mEventThread->onHotplugReceived(draw[i].type, false);
                mDisplays.removeItem(draw.keyAt(i));
                } else {
                    ALOGW("trying to remove the main display");
                }
            } else {
                // this display is in both lists. see if something changed.
                const DisplayDeviceState& state(curr[j]);
@@ -2377,6 +2376,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
                }
                layer->updateTransformHint(disp);
            }
            if (disp != nullptr) {
                layer->updateTransformHint(disp);
            }

            first = false;
        });
@@ -3912,9 +3914,11 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,

    getBE().mRenderEngine->dump(result);

    if (hw) {
        hw->undefinedRegion.dump(result, "undefinedRegion");
        result.appendFormat("  orientation=%d, isDisplayOn=%d\n",
                hw->getOrientation(), hw->isDisplayOn());
    }
    result.appendFormat(
            "  last eglSwapBuffers() time: %f us\n"
            "  last transaction time     : %f us\n"
+6 −0
Original line number Diff line number Diff line
@@ -181,6 +181,12 @@ void FakeComposerClient::hotplugDisplay(Display display, IComposerCallback::Conn
    }
}

void FakeComposerClient::refreshDisplay(Display display) {
    if (mCallbacksOn) {
        mClient->onRefresh(display);
    }
}

uint32_t FakeComposerClient::getMaxVirtualDisplayCount() {
    ALOGV("getMaxVirtualDisplayCount");
    return 1;
+1 −0
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ public:
    Layer getLayer(size_t index) const;

    void hotplugDisplay(Display display, IComposerCallback::Connection state);
    void refreshDisplay(Display display);

private:
    LayerImpl& getLayerImpl(Layer handle);
Loading