diff options
| -rw-r--r-- | include/surfaceflinger/IGraphicBufferAlloc.h | 2 | ||||
| -rw-r--r-- | include/utils/threads.h | 4 | ||||
| -rw-r--r-- | libs/gui/IGraphicBufferAlloc.cpp | 13 | ||||
| -rw-r--r-- | libs/gui/SurfaceTexture.cpp | 6 | ||||
| -rw-r--r-- | libs/gui/tests/Surface_test.cpp | 22 | ||||
| -rw-r--r-- | libs/utils/Threads.cpp | 19 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 32 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 7 |
9 files changed, 94 insertions, 16 deletions
diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h index e1b6b577b5..d3b2062233 100644 --- a/include/surfaceflinger/IGraphicBufferAlloc.h +++ b/include/surfaceflinger/IGraphicBufferAlloc.h @@ -37,7 +37,7 @@ public: /* Create a new GraphicBuffer for the client to use. */ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) = 0; + PixelFormat format, uint32_t usage, status_t* error) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/utils/threads.h b/include/utils/threads.h index 41f67e4058..c8e9c0413d 100644 --- a/include/utils/threads.h +++ b/include/utils/threads.h @@ -510,6 +510,10 @@ public: // that case. status_t requestExitAndWait(); + // Wait until this object's thread exits. Returns immediately if not yet running. + // Do not call from this object's thread; will return WOULD_BLOCK in that case. + status_t join(); + protected: // exitPending() returns true if requestExit() has been called. bool exitPending() const; diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp index 0cd51da539..30f8d003c8 100644 --- a/libs/gui/IGraphicBufferAlloc.cpp +++ b/libs/gui/IGraphicBufferAlloc.cpp @@ -43,7 +43,7 @@ public: } virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) { + PixelFormat format, uint32_t usage, status_t* error) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor()); data.writeInt32(w); @@ -52,14 +52,15 @@ public: data.writeInt32(usage); remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply); sp<GraphicBuffer> graphicBuffer; - bool nonNull = (bool)reply.readInt32(); - if (nonNull) { + status_t result = reply.readInt32(); + if (result == NO_ERROR) { graphicBuffer = new GraphicBuffer(); reply.read(*graphicBuffer); // reply.readStrongBinder(); // here we don't even have to read the BufferReference from // the parcel, it'll die with the parcel. } + *error = result; return graphicBuffer; } }; @@ -91,8 +92,10 @@ status_t BnGraphicBufferAlloc::onTransact( uint32_t h = data.readInt32(); PixelFormat format = data.readInt32(); uint32_t usage = data.readInt32(); - sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage)); - reply->writeInt32(result != 0); + status_t error; + sp<GraphicBuffer> result = + createGraphicBuffer(w, h, format, usage, &error); + reply->writeInt32(error); if (result != 0) { reply->write(*result); // We add a BufferReference to this parcel to make sure the diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 3bf6477cf2..886a3fb222 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -352,11 +352,13 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, ((uint32_t(buffer->usage) & usage) != usage)) { usage |= GraphicBuffer::USAGE_HW_TEXTURE; + status_t error; sp<GraphicBuffer> graphicBuffer( - mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage)); + mGraphicBufferAlloc->createGraphicBuffer( + w, h, format, usage, &error)); if (graphicBuffer == 0) { LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); - return NO_MEMORY; + return error; } if (updateFormat) { mPixelFormat = format; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 450cdf1f8f..ce587b3ccd 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -31,13 +31,13 @@ protected: ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); mSurfaceControl = mComposerClient->createSurface( - String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGB_888, 0); + String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGBA_8888, 0); ASSERT_TRUE(mSurfaceControl != NULL); ASSERT_TRUE(mSurfaceControl->isValid()); SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000)); + ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff)); ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); SurfaceComposerClient::closeGlobalTransaction(); @@ -84,7 +84,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { PixelFormat fmt=0; sp<ISurfaceComposer> sf(ComposerService::getComposerService()); ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0, - 40000)); + 0x7fffffff)); ASSERT_TRUE(heap != NULL); // Set the PROTECTED usage bit and verify that the screenshot fails. Note @@ -94,6 +94,18 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { GRALLOC_USAGE_PROTECTED)); ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); ANativeWindowBuffer* buf = 0; + + status_t err = anw->dequeueBuffer(anw.get(), &buf); + if (err) { + // we could fail if GRALLOC_USAGE_PROTECTED is not supported. + // that's okay as long as this is the reason for the failure. + // try again without the GRALLOC_USAGE_PROTECTED bit. + ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0)); + ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf)); + return; + } + ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf)); + for (int i = 0; i < 4; i++) { // Loop to make sure SurfaceFlinger has retired a protected buffer. ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf)); @@ -103,7 +115,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { heap = 0; w = h = fmt = 0; ASSERT_EQ(INVALID_OPERATION, sf->captureScreen(0, &heap, &w, &h, &fmt, - 64, 64, 0, 40000)); + 64, 64, 0, 0x7fffffff)); ASSERT_TRUE(heap == NULL); // XXX: This should not be needed, but it seems that the new buffers don't @@ -126,7 +138,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { heap = 0; w = h = fmt = 0; ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0, - 40000)); + 0x7fffffff)); ASSERT_TRUE(heap != NULL); } diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp index 71352a864f..50312e7bb7 100644 --- a/libs/utils/Threads.cpp +++ b/libs/utils/Threads.cpp @@ -846,6 +846,25 @@ status_t Thread::requestExitAndWait() return mStatus; } +status_t Thread::join() +{ + Mutex::Autolock _l(mLock); + if (mThread == getThreadId()) { + LOGW( + "Thread (this=%p): don't call join() from this " + "Thread object's thread. It's a guaranteed deadlock!", + this); + + return WOULD_BLOCK; + } + + while (mRunning == true) { + mThreadExitedCondition.wait(mLock); + } + + return mStatus; +} + bool Thread::exitPending() const { Mutex::Autolock _l(mLock); diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index a774841ddb..33125c487e 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -103,6 +103,11 @@ void DisplayHardware::init(uint32_t dpy) { mNativeWindow = new FramebufferNativeWindow(); framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); + if (!fbDev) { + LOGE("Display subsystem failed to initialize. check logs. exiting..."); + exit(0); + } + mDpiX = mNativeWindow->xdpi; mDpiY = mNativeWindow->ydpi; mRefreshRate = fbDev->fps; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 685613efef..cccab4a623 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -163,9 +163,34 @@ void SurfaceFlinger::bootFinished() const nsecs_t duration = now - mBootTime; LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); mBootFinished = true; + + // wait patiently for the window manager death + const String16 name("window"); + sp<IBinder> window(defaultServiceManager()->getService(name)); + if (window != 0) { + window->linkToDeath(this); + } + + // stop boot animation property_set("ctl.stop", "bootanim"); } +void SurfaceFlinger::binderDied(const wp<IBinder>& who) +{ + // the window manager died on us. prepare its eulogy. + + // unfreeze the screen in case it was... frozen + mFreezeDisplayTime = 0; + mFreezeCount = 0; + mFreezeDisplay = false; + + // reset screen orientation + setOrientation(0, eOrientationDefault, 0); + + // restart the boot-animation + property_set("ctl.start", "bootanim"); +} + void SurfaceFlinger::onFirstRef() { run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY); @@ -2470,11 +2495,14 @@ GraphicBufferAlloc::GraphicBufferAlloc() {} GraphicBufferAlloc::~GraphicBufferAlloc() {} sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) { + PixelFormat format, uint32_t usage, status_t* error) { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); status_t err = graphicBuffer->initCheck(); + *error = err; if (err != 0 || graphicBuffer->handle == 0) { - GraphicBuffer::dumpAllocationsToSystemLog(); + if (err == NO_MEMORY) { + GraphicBuffer::dumpAllocationsToSystemLog(); + } LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " "failed (%s), handle=%p", w, h, strerror(-err), graphicBuffer->handle); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b49fa363e6..15661f0129 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -96,7 +96,7 @@ public: GraphicBufferAlloc(); virtual ~GraphicBufferAlloc(); virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage); + PixelFormat format, uint32_t usage, status_t* error); }; // --------------------------------------------------------------------------- @@ -147,6 +147,7 @@ enum { class SurfaceFlinger : public BinderService<SurfaceFlinger>, public BnSurfaceComposer, + public IBinder::DeathRecipient, protected Thread { public: @@ -193,6 +194,10 @@ public: sp<Layer> getLayer(const sp<ISurface>& sur) const; private: + // DeathRecipient interface + virtual void binderDied(const wp<IBinder>& who); + +private: friend class Client; friend class LayerBase; friend class LayerBaseClient; |