Fix crashes after HDMI disconnect
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
This commit is contained in:
parent
5031729a37
commit
eb1caaea69
@ -540,8 +540,13 @@ status_t HWComposer::prepare() {
|
|||||||
// DO NOT reset the handle field to NULL, because it's possible
|
// DO NOT reset the handle field to NULL, because it's possible
|
||||||
// that we have nothing to redraw (eg: eglSwapBuffers() not called)
|
// that we have nothing to redraw (eg: eglSwapBuffers() not called)
|
||||||
// in which case, we should continue to use the same buffer.
|
// in which case, we should continue to use the same buffer.
|
||||||
|
LOG_FATAL_IF(disp.list == NULL);
|
||||||
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
|
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;
|
mLists[i] = disp.list;
|
||||||
if (mLists[i]) {
|
if (mLists[i]) {
|
||||||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
|
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
|
||||||
@ -664,6 +669,17 @@ status_t HWComposer::acquire(int disp) const {
|
|||||||
return NO_ERROR;
|
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 {
|
int HWComposer::getVisualID() const {
|
||||||
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||||
// FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
|
// FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
|
||||||
|
@ -97,6 +97,9 @@ public:
|
|||||||
// acquire hardware resources and unblank screen
|
// acquire hardware resources and unblank screen
|
||||||
status_t acquire(int disp) const;
|
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.
|
// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
|
||||||
status_t createWorkList(int32_t id, size_t numLayers);
|
status_t createWorkList(int32_t id, size_t numLayers);
|
||||||
|
|
||||||
|
@ -1123,7 +1123,13 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
|||||||
if (j < 0) {
|
if (j < 0) {
|
||||||
// in drawing state but not in current state
|
// in drawing state but not in current state
|
||||||
if (!draw[i].isMainDisplay()) {
|
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));
|
mDisplays.removeItem(draw.keyAt(i));
|
||||||
|
getHwComposer().disconnectDisplay(draw[i].type);
|
||||||
} else {
|
} else {
|
||||||
ALOGW("trying to remove the main display");
|
ALOGW("trying to remove the main display");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user