Skip to content

Commit

Permalink
Fix crashes after HDMI disconnect
Browse files Browse the repository at this point in the history
The display was being removed from SurfaceFlinger's list before we
had a chance to reset HWComposer's layer list, so we were passing
stale data into the hardware composer (which has its own per-display
data).  This resulted in "invalid gralloc handle" complaints.
We now clear the layer list immediately after removing the display.

The display was being removed while its EGLSurface was still
"current", resulting in "cancelBuffer: BufferQueue has been
abandoned" complaints.  We now call makeCurrent on the primary
display before removing the external display.

Bug 7274254

Change-Id: Ia59e3a61d7ec46488b96bf93ec5e4ed3488b70e4
  • Loading branch information
fadden authored and The Android Automerger committed Oct 4, 2012
1 parent 5031729 commit eb1caae
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 0 deletions.
16 changes: 16 additions & 0 deletions services/surfaceflinger/DisplayHardware/HWComposer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,8 +540,13 @@ status_t HWComposer::prepare() {
// DO NOT reset the handle field to NULL, because it's possible
// that we have nothing to redraw (eg: eglSwapBuffers() not called)
// in which case, we should continue to use the same buffer.
LOG_FATAL_IF(disp.list == NULL);
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
}
if (!disp.connected && disp.list != NULL) {
ALOGW("WARNING: disp %d: connected, non-null list, layers=%d",
i, disp.list->numHwLayers);
}
mLists[i] = disp.list;
if (mLists[i]) {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
Expand Down Expand Up @@ -664,6 +669,17 @@ status_t HWComposer::acquire(int disp) const {
return NO_ERROR;
}

void HWComposer::disconnectDisplay(int disp) {
LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY ||
disp >= HWC_NUM_DISPLAY_TYPES);
DisplayData& dd(mDisplayData[disp]);
if (dd.list != NULL) {
free(dd.list);
dd.list = NULL;
dd.framebufferTarget = NULL; // points into dd.list
}
}

int HWComposer::getVisualID() const {
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
Expand Down
3 changes: 3 additions & 0 deletions services/surfaceflinger/DisplayHardware/HWComposer.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class HWComposer
// acquire hardware resources and unblank screen
status_t acquire(int disp) const;

// reset state when an external, non-virtual display is disconnected
void disconnectDisplay(int disp);

// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
status_t createWorkList(int32_t id, size_t numLayers);

Expand Down
6 changes: 6 additions & 0 deletions services/surfaceflinger/SurfaceFlinger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,13 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
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>& hw(getDefaultDisplayDevice());
DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
mDisplays.removeItem(draw.keyAt(i));
getHwComposer().disconnectDisplay(draw[i].type);
} else {
ALOGW("trying to remove the main display");
}
Expand Down

0 comments on commit eb1caae

Please sign in to comment.