Merge change 22011 into eclair

* changes:
  fix [2063336] Surface.lockSurface throws IllegalArgumentException when out of memory
This commit is contained in:
Android (Google) Code Review
2009-08-19 17:38:45 -07:00
3 changed files with 65 additions and 38 deletions

View File

@@ -246,7 +246,7 @@ public class Surface implements Parcelable {
}; };
/** /**
* Sets the display metrics used to provide canva's width/height in comaptibility mode. * Sets the display metrics used to provide canva's width/height in compatibility mode.
*/ */
void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) { void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) {
mCompatibleDisplayMetrics = metrics; mCompatibleDisplayMetrics = metrics;
@@ -275,7 +275,8 @@ public class Surface implements Parcelable {
public native void clear(); public native void clear();
/** draw into a surface */ /** draw into a surface */
public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException { public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException
{
/* the dirty rectangle may be expanded to the surface's size, if /* the dirty rectangle may be expanded to the surface's size, if
* for instance it has been resized or if the bits were lost, since * for instance it has been resized or if the bits were lost, since
* the last call. * the last call.

View File

@@ -96,13 +96,11 @@ status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
err = allocator.alloc(w, h, format, usage, &handle, &stride); err = allocator.alloc(w, h, format, usage, &handle, &stride);
if (err == NO_ERROR) {
if (err == NO_ERROR) { if (err == NO_ERROR) {
width = w; width = w;
height = h; height = h;
mVStride = 0; mVStride = 0;
} }
}
return err; return err;
} }

View File

@@ -64,12 +64,17 @@ SurfaceBuffer::SurfaceBuffer(const Parcel& data)
{ {
// we own the handle in this case // we own the handle in this case
width = data.readInt32(); width = data.readInt32();
if (width < 0) {
width = height = stride = format = usage = 0;
handle = 0;
} else {
height = data.readInt32(); height = data.readInt32();
stride = data.readInt32(); stride = data.readInt32();
format = data.readInt32(); format = data.readInt32();
usage = data.readInt32(); usage = data.readInt32();
handle = data.readNativeHandle(); handle = data.readNativeHandle();
} }
}
SurfaceBuffer::~SurfaceBuffer() SurfaceBuffer::~SurfaceBuffer()
{ {
@@ -108,16 +113,25 @@ status_t SurfaceBuffer::unlock()
status_t SurfaceBuffer::writeToParcel(Parcel* reply, status_t SurfaceBuffer::writeToParcel(Parcel* reply,
android_native_buffer_t const* buffer) android_native_buffer_t const* buffer)
{ {
if (buffer == NULL) { if (buffer == NULL)
return BAD_VALUE; return BAD_VALUE;
}
if (buffer->width < 0 || buffer->height < 0)
return BAD_VALUE;
status_t err = NO_ERROR;
if (buffer->handle == NULL) {
// this buffer doesn't have a handle
reply->writeInt32(NO_MEMORY);
} else {
reply->writeInt32(buffer->width); reply->writeInt32(buffer->width);
reply->writeInt32(buffer->height); reply->writeInt32(buffer->height);
reply->writeInt32(buffer->stride); reply->writeInt32(buffer->stride);
reply->writeInt32(buffer->format); reply->writeInt32(buffer->format);
reply->writeInt32(buffer->usage); reply->writeInt32(buffer->usage);
reply->writeNativeHandle(buffer->handle); err = reply->writeNativeHandle(buffer->handle);
return NO_ERROR; }
return err;
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@@ -434,7 +448,7 @@ Surface::~Surface()
// this is a client-side operation, the surface is destroyed, unmap // this is a client-side operation, the surface is destroyed, unmap
// its buffers in this process. // its buffers in this process.
for (int i=0 ; i<2 ; i++) { for (int i=0 ; i<2 ; i++) {
if (mBuffers[i] != 0) { if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) {
getBufferMapper().unregisterBuffer(mBuffers[i]->handle); getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
} }
} }
@@ -590,15 +604,22 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) { if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) {
mUsageChanged = false; mUsageChanged = false;
err = getBufferLocked(backIdx, mUsage); err = getBufferLocked(backIdx, mUsage);
if (err == NO_ERROR) {
// reset the width/height with the what we get from the buffer
const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
mWidth = uint32_t(backBuffer->width);
mHeight = uint32_t(backBuffer->height);
}
} }
if (err == NO_ERROR) { if (err == NO_ERROR) {
const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]); const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
// reset the width/height with the what we get from the buffer if (backBuffer != 0) {
mWidth = uint32_t(backBuffer->width);
mHeight = uint32_t(backBuffer->height);
mDirtyRegion.set(backBuffer->width, backBuffer->height); mDirtyRegion.set(backBuffer->width, backBuffer->height);
*buffer = backBuffer.get(); *buffer = backBuffer.get();
} else {
err = NO_MEMORY;
}
} }
return err; return err;
@@ -716,7 +737,8 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
} else { } else {
newDirtyRegion.andSelf(bounds); newDirtyRegion.andSelf(bounds);
const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]); const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
if (backBuffer->width == frontBuffer->width && if (frontBuffer !=0 &&
backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height && backBuffer->height == frontBuffer->height &&
!(lcblk->flags & eNoCopyBack)) !(lcblk->flags & eNoCopyBack))
{ {
@@ -788,20 +810,26 @@ status_t Surface::getBufferLocked(int index, int usage)
if (s == 0) return NO_INIT; if (s == 0) return NO_INIT;
status_t err = NO_MEMORY; status_t err = NO_MEMORY;
sp<SurfaceBuffer> buffer = s->getBuffer(usage);
LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL"); // free the current buffer
if (buffer != 0) {
sp<SurfaceBuffer>& currentBuffer(mBuffers[index]); sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
if (currentBuffer != 0) { if (currentBuffer != 0) {
getBufferMapper().unregisterBuffer(currentBuffer->handle); getBufferMapper().unregisterBuffer(currentBuffer->handle);
currentBuffer.clear(); currentBuffer.clear();
} }
sp<SurfaceBuffer> buffer = s->getBuffer(usage);
LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
if (buffer != 0) { // this should never happen by construction
if (buffer->handle != NULL) {
err = getBufferMapper().registerBuffer(buffer->handle); err = getBufferMapper().registerBuffer(buffer->handle);
LOGW_IF(err, "registerBuffer(...) failed %d (%s)", err, strerror(-err)); LOGW_IF(err, "registerBuffer(...) failed %d (%s)",
err, strerror(-err));
if (err == NO_ERROR) { if (err == NO_ERROR) {
currentBuffer = buffer; currentBuffer = buffer;
} }
} }
}
return err; return err;
} }