diff options
author | Mathias Agopian <mathias@google.com> | 2010-03-15 18:15:20 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2010-03-15 18:15:20 -0700 |
commit | d343e3d5e3177806205b9452b0b43907e28afd9a (patch) | |
tree | a094c9ea996f2d1ceb872340a192741ea6395635 /libs/surfaceflinger/Layer.cpp | |
parent | 80586f4230f974c2a3fe2b8aa398ffd6764e3a3a (diff) | |
download | frameworks_native-d343e3d5e3177806205b9452b0b43907e28afd9a.zip frameworks_native-d343e3d5e3177806205b9452b0b43907e28afd9a.tar.gz frameworks_native-d343e3d5e3177806205b9452b0b43907e28afd9a.tar.bz2 |
fix [2515291] Native crash and runtime restart while trying to preview captured picture on Sapphire
if a buffer couldn't be allocated because of an OOM, SF could, in some case dereference
a null pointer.
Change-Id: I5321248c38a21e56d5278b6aada2694e64451378
Diffstat (limited to 'libs/surfaceflinger/Layer.cpp')
-rw-r--r-- | libs/surfaceflinger/Layer.cpp | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 7ca7875..4dc4a15 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -465,44 +465,61 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // for composition later in the loop return; } - + + // ouch, this really should never happen + if (uint32_t(buf)>=NUM_BUFFERS) { + LOGE("retireAndLock() buffer index (%d) out of range", buf); + mPostedDirtyRegion.clear(); + return; + } + // we retired a buffer, which becomes the new front buffer mFrontBufferIndex = buf; // get the dirty region sp<GraphicBuffer> newFrontBuffer(getBuffer(buf)); - const Region dirty(lcblk->getDirtyRegion(buf)); - mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() ); - - const Layer::State& front(drawingState()); - if (newFrontBuffer->getWidth() == front.requested_w && - newFrontBuffer->getHeight() == front.requested_h) - { - if ((front.w != front.requested_w) || - (front.h != front.requested_h)) + if (newFrontBuffer != NULL) { + // compute the posted region + const Region dirty(lcblk->getDirtyRegion(buf)); + mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() ); + + // update the layer size and release freeze-lock + const Layer::State& front(drawingState()); + if (newFrontBuffer->getWidth() == front.requested_w && + newFrontBuffer->getHeight() == front.requested_h) { - // Here we pretend the transaction happened by updating the - // current and drawing states. Drawing state is only accessed - // in this thread, no need to have it locked - Layer::State& editDraw(mDrawingState); - editDraw.w = editDraw.requested_w; - editDraw.h = editDraw.requested_h; - - // We also need to update the current state so that we don't - // end-up doing too much work during the next transaction. - // NOTE: We actually don't need hold the transaction lock here - // because State::w and State::h are only accessed from - // this thread - Layer::State& editTemp(currentState()); - editTemp.w = editDraw.w; - editTemp.h = editDraw.h; - - // recompute visible region - recomputeVisibleRegions = true; - } + if ((front.w != front.requested_w) || + (front.h != front.requested_h)) + { + // Here we pretend the transaction happened by updating the + // current and drawing states. Drawing state is only accessed + // in this thread, no need to have it locked + Layer::State& editDraw(mDrawingState); + editDraw.w = editDraw.requested_w; + editDraw.h = editDraw.requested_h; + + // We also need to update the current state so that we don't + // end-up doing too much work during the next transaction. + // NOTE: We actually don't need hold the transaction lock here + // because State::w and State::h are only accessed from + // this thread + Layer::State& editTemp(currentState()); + editTemp.w = editDraw.w; + editTemp.h = editDraw.h; + + // recompute visible region + recomputeVisibleRegions = true; + } - // we now have the correct size, unfreeze the screen - mFreezeLock.clear(); + // we now have the correct size, unfreeze the screen + mFreezeLock.clear(); + } + } else { + // this should not happen unless we ran out of memory while + // allocating the buffer. we're hoping that things will get back + // to normal the next time the app tries to draw into this buffer. + // meanwhile, pretend the screen didn't update. + mPostedDirtyRegion.clear(); } if (lcblk->getQueuedCount()) { |