Loading include/gui/ISurfaceComposer.h +2 −10 Original line number Original line Diff line number Diff line Loading @@ -95,14 +95,6 @@ public: virtual bool authenticateSurfaceTexture( virtual bool authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& surface) const = 0; const sp<IGraphicBufferProducer>& surface) const = 0; /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ virtual status_t captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap, uint32_t* width, uint32_t* height, PixelFormat* format, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) = 0; /* triggers screen off and waits for it to complete /* triggers screen off and waits for it to complete * requires ACCESS_SURFACE_FLINGER permission. * requires ACCESS_SURFACE_FLINGER permission. */ */ Loading @@ -123,7 +115,8 @@ public: virtual status_t captureScreen(const sp<IBinder>& display, virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) = 0; uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer) = 0; }; }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading @@ -141,7 +134,6 @@ public: GET_BUILT_IN_DISPLAY, GET_BUILT_IN_DISPLAY, SET_TRANSACTION_STATE, SET_TRANSACTION_STATE, AUTHENTICATE_SURFACE, AUTHENTICATE_SURFACE, CAPTURE_SCREEN_DEPRECATED, BLANK, BLANK, UNBLANK, UNBLANK, GET_DISPLAY_INFO, GET_DISPLAY_INFO, Loading include/gui/SurfaceComposerClient.h +6 −5 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <ui/PixelFormat.h> #include <ui/PixelFormat.h> #include <gui/CpuConsumer.h> #include <gui/SurfaceControl.h> #include <gui/SurfaceControl.h> namespace android { namespace android { Loading @@ -38,7 +39,6 @@ namespace android { class DisplayInfo; class DisplayInfo; class Composer; class Composer; class IMemoryHeap; class ISurfaceComposerClient; class ISurfaceComposerClient; class IGraphicBufferProducer; class IGraphicBufferProducer; class Region; class Region; Loading Loading @@ -164,10 +164,9 @@ public: uint32_t minLayerZ, uint32_t maxLayerZ); uint32_t minLayerZ, uint32_t maxLayerZ); private: private: sp<IMemoryHeap> mHeap; mutable sp<CpuConsumer> mCpuConsumer; uint32_t mWidth; CpuConsumer::LockedBuffer mBuffer; uint32_t mHeight; bool mHaveBuffer; PixelFormat mFormat; public: public: ScreenshotClient(); ScreenshotClient(); Loading @@ -180,6 +179,8 @@ public: uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ); uint32_t minLayerZ, uint32_t maxLayerZ); sp<CpuConsumer> getCpuConsumer() const; // release memory occupied by the screenshot // release memory occupied by the screenshot void release(); void release(); Loading libs/gui/ISurfaceComposer.cpp +6 −41 Original line number Original line Diff line number Diff line Loading @@ -102,31 +102,11 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } } virtual status_t captureScreen( const sp<IBinder>& display, sp<IMemoryHeap>* heap, uint32_t* width, uint32_t* height, PixelFormat* format, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); data.writeInt32(reqWidth); data.writeInt32(reqHeight); data.writeInt32(minLayerZ); data.writeInt32(maxLayerZ); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_DEPRECATED, data, &reply); *heap = interface_cast<IMemoryHeap>(reply.readStrongBinder()); *width = reply.readInt32(); *height = reply.readInt32(); *format = reply.readInt32(); return reply.readInt32(); } virtual status_t captureScreen(const sp<IBinder>& display, virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer) { { Parcel data, reply; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); Loading @@ -136,6 +116,7 @@ public: data.writeInt32(reqHeight); data.writeInt32(reqHeight); data.writeInt32(minLayerZ); data.writeInt32(minLayerZ); data.writeInt32(maxLayerZ); data.writeInt32(maxLayerZ); data.writeInt32(isCpuConsumer); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); return reply.readInt32(); return reply.readInt32(); } } Loading Loading @@ -285,24 +266,6 @@ status_t BnSurfaceComposer::onTransact( CHECK_INTERFACE(ISurfaceComposer, data, reply); CHECK_INTERFACE(ISurfaceComposer, data, reply); bootFinished(); bootFinished(); } break; } break; case CAPTURE_SCREEN_DEPRECATED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = data.readStrongBinder(); uint32_t reqWidth = data.readInt32(); uint32_t reqHeight = data.readInt32(); uint32_t minLayerZ = data.readInt32(); uint32_t maxLayerZ = data.readInt32(); sp<IMemoryHeap> heap; uint32_t w, h; PixelFormat f; status_t res = captureScreen(display, &heap, &w, &h, &f, reqWidth, reqHeight, minLayerZ, maxLayerZ); reply->writeStrongBinder(heap->asBinder()); reply->writeInt32(w); reply->writeInt32(h); reply->writeInt32(f); reply->writeInt32(res); } break; case CAPTURE_SCREEN: { case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = data.readStrongBinder(); sp<IBinder> display = data.readStrongBinder(); Loading @@ -312,8 +275,10 @@ status_t BnSurfaceComposer::onTransact( uint32_t reqHeight = data.readInt32(); uint32_t reqHeight = data.readInt32(); uint32_t minLayerZ = data.readInt32(); uint32_t minLayerZ = data.readInt32(); uint32_t maxLayerZ = data.readInt32(); uint32_t maxLayerZ = data.readInt32(); bool isCpuConsumer = data.readInt32(); status_t res = captureScreen(display, producer, status_t res = captureScreen(display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); reqWidth, reqHeight, minLayerZ, maxLayerZ, isCpuConsumer); reply->writeInt32(res); reply->writeInt32(res); } break; } break; case AUTHENTICATE_SURFACE: { case AUTHENTICATE_SURFACE: { Loading libs/gui/SurfaceComposerClient.cpp +49 −29 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <ui/DisplayInfo.h> #include <ui/DisplayInfo.h> #include <gui/CpuConsumer.h> #include <gui/IGraphicBufferProducer.h> #include <gui/IGraphicBufferProducer.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposerClient.h> #include <gui/ISurfaceComposerClient.h> Loading Loading @@ -617,30 +618,21 @@ status_t ScreenshotClient::capture( sp<ISurfaceComposer> s(ComposerService::getComposerService()); sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; if (s == NULL) return NO_INIT; return s->captureScreen(display, producer, return s->captureScreen(display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); reqWidth, reqHeight, minLayerZ, maxLayerZ, false); } } ScreenshotClient::ScreenshotClient() ScreenshotClient::ScreenshotClient() : mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) { : mHaveBuffer(false) { memset(&mBuffer, 0, sizeof(mBuffer)); } } status_t ScreenshotClient::update(const sp<IBinder>& display) { sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (mCpuConsumer == NULL) { if (s == NULL) return NO_INIT; mCpuConsumer = new CpuConsumer(1); mHeap = 0; mCpuConsumer->setName(String8("ScreenshotClient")); return s->captureScreen(display, &mHeap, &mWidth, &mHeight, &mFormat, 0, 0, 0, -1UL); } } return mCpuConsumer; status_t ScreenshotClient::update(const sp<IBinder>& display, uint32_t reqWidth, uint32_t reqHeight) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; mHeap = 0; return s->captureScreen(display, &mHeap, &mWidth, &mHeight, &mFormat, reqWidth, reqHeight, 0, -1UL); } } status_t ScreenshotClient::update(const sp<IBinder>& display, status_t ScreenshotClient::update(const sp<IBinder>& display, Loading @@ -648,38 +640,66 @@ status_t ScreenshotClient::update(const sp<IBinder>& display, uint32_t minLayerZ, uint32_t maxLayerZ) { uint32_t minLayerZ, uint32_t maxLayerZ) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; if (s == NULL) return NO_INIT; mHeap = 0; sp<CpuConsumer> cpuConsumer = getCpuConsumer(); return s->captureScreen(display, &mHeap, &mWidth, &mHeight, &mFormat, reqWidth, reqHeight, if (mHaveBuffer) { minLayerZ, maxLayerZ); mCpuConsumer->unlockBuffer(mBuffer); memset(&mBuffer, 0, sizeof(mBuffer)); mHaveBuffer = false; } status_t err = s->captureScreen(display,cpuConsumer->getBufferQueue(), reqWidth, reqHeight, minLayerZ, maxLayerZ, true); if (err == NO_ERROR) { err = mCpuConsumer->lockNextBuffer(&mBuffer); if (err == NO_ERROR) { mHaveBuffer = true; } } return err; } status_t ScreenshotClient::update(const sp<IBinder>& display) { return ScreenshotClient::update(display, 0, 0, 0, -1UL); } status_t ScreenshotClient::update(const sp<IBinder>& display, uint32_t reqWidth, uint32_t reqHeight) { return ScreenshotClient::update(display, reqWidth, reqHeight, 0, -1UL); } } void ScreenshotClient::release() { void ScreenshotClient::release() { mHeap = 0; if (mHaveBuffer) { mCpuConsumer->unlockBuffer(mBuffer); memset(&mBuffer, 0, sizeof(mBuffer)); mHaveBuffer = false; } mCpuConsumer.clear(); } } void const* ScreenshotClient::getPixels() const { void const* ScreenshotClient::getPixels() const { return mHeap->getBase(); return mBuffer.data; } } uint32_t ScreenshotClient::getWidth() const { uint32_t ScreenshotClient::getWidth() const { return mWidth; return mBuffer.width; } } uint32_t ScreenshotClient::getHeight() const { uint32_t ScreenshotClient::getHeight() const { return mHeight; return mBuffer.height; } } PixelFormat ScreenshotClient::getFormat() const { PixelFormat ScreenshotClient::getFormat() const { return mFormat; return mBuffer.format; } } uint32_t ScreenshotClient::getStride() const { uint32_t ScreenshotClient::getStride() const { return mWidth; return mBuffer.stride; } } size_t ScreenshotClient::getSize() const { size_t ScreenshotClient::getSize() const { return mHeap->getSize(); return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading services/surfaceflinger/SurfaceFlinger.cpp +80 −95 Original line number Original line Diff line number Diff line Loading @@ -2416,7 +2416,6 @@ status_t SurfaceFlinger::onTransact( break; break; } } case CAPTURE_SCREEN: case CAPTURE_SCREEN: case CAPTURE_SCREEN_DEPRECATED: { { // codes that require permission check // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); IPCThreadState* ipc = IPCThreadState::self(); Loading Loading @@ -2511,7 +2510,8 @@ void SurfaceFlinger::repaintEverything() { status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) { uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer) { if (CC_UNLIKELY(display == 0)) if (CC_UNLIKELY(display == 0)) return BAD_VALUE; return BAD_VALUE; Loading @@ -2525,16 +2525,18 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<IGraphicBufferProducer> producer; sp<IGraphicBufferProducer> producer; uint32_t reqWidth, reqHeight; uint32_t reqWidth, reqHeight; uint32_t minLayerZ,maxLayerZ; uint32_t minLayerZ,maxLayerZ; bool isCpuConsumer; status_t result; status_t result; public: public: MessageCaptureScreen(SurfaceFlinger* flinger, MessageCaptureScreen(SurfaceFlinger* flinger, const sp<IBinder>& display, const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer) : flinger(flinger), display(display), producer(producer), : flinger(flinger), display(display), producer(producer), reqWidth(reqWidth), reqHeight(reqHeight), reqWidth(reqWidth), reqHeight(reqHeight), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), isCpuConsumer(isCpuConsumer), result(PERMISSION_DENIED) result(PERMISSION_DENIED) { { } } Loading @@ -2544,14 +2546,24 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, virtual bool handler() { virtual bool handler() { Mutex::Autolock _l(flinger->mStateLock); Mutex::Autolock _l(flinger->mStateLock); sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); result = flinger->captureScreenImplLocked(hw, producer, // TODO: if we know the GL->CPU path works, we can call reqWidth, reqHeight, minLayerZ, maxLayerZ); // captureScreenImplLocked() directly, instead of using the // "CpuConsumer" version, which is much less efficient -- it is // however needed by some older drivers. if (isCpuConsumer) { result = flinger->captureScreenImplCpuConsumerLocked(hw, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); } else { result = flinger->captureScreenImplLocked(hw, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); } return true; return true; } } }; }; sp<MessageBase> msg = new MessageCaptureScreen(this, sp<MessageBase> msg = new MessageCaptureScreen(this, display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ, isCpuConsumer); status_t res = postMessageSync(msg); status_t res = postMessageSync(msg); if (res == NO_ERROR) { if (res == NO_ERROR) { res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult(); res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult(); Loading Loading @@ -2655,18 +2667,15 @@ status_t SurfaceFlinger::captureScreenImplLocked( } } eglDestroySurface(mEGLDisplay, eglSurface); eglDestroySurface(mEGLDisplay, eglSurface); return NO_ERROR; return NO_ERROR; } } // --------------------------------------------------------------------------- // Capture screen into an IMemoryHeap (legacy) // --------------------------------------------------------------------------- status_t SurfaceFlinger::captureScreenImplLocked( status_t SurfaceFlinger::captureScreenImplCpuConsumerLocked( const sp<const DisplayDevice>& hw, const sp<const DisplayDevice>& hw, sp<IMemoryHeap>* heap, const sp<IGraphicBufferProducer>& producer, uint32_t* w, uint32_t* h, PixelFormat* f, uint32_t reqWidth, uint32_t reqHeight, uint32_t sw, uint32_t sh, uint32_t minLayerZ, uint32_t maxLayerZ) uint32_t minLayerZ, uint32_t maxLayerZ) { { ATRACE_CALL(); ATRACE_CALL(); Loading @@ -2689,7 +2698,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( // call the new screenshot taking code, passing a BufferQueue to it // call the new screenshot taking code, passing a BufferQueue to it status_t result = captureScreenImplLocked(hw, status_t result = captureScreenImplLocked(hw, consumer->getBufferQueue(), sw, sh, minLayerZ, maxLayerZ); consumer->getBufferQueue(), reqWidth, reqHeight, minLayerZ, maxLayerZ); if (result == NO_ERROR) { if (result == NO_ERROR) { result = consumer->updateTexImage(); result = consumer->updateTexImage(); Loading @@ -2701,31 +2710,64 @@ status_t SurfaceFlinger::captureScreenImplLocked( glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); sp<GraphicBuffer> buf(consumer->getCurrentBuffer()); reqWidth = consumer->getCurrentBuffer()->getWidth(); sw = buf->getWidth(); reqHeight = consumer->getCurrentBuffer()->getHeight(); sh = buf->getHeight(); size_t size = sw * sh * 4; { // in this block we render the screenshot into the // allocate shared memory large enough to hold the // CpuConsumer using glReadPixels from our GLConsumer, // screen capture // Some older drivers don't support the GL->CPU path so sp<MemoryHeapBase> base( // have to wrap it with a CPU->CPU path, which is what new MemoryHeapBase(size, 0, "screen-capture") ); // glReadPixels essentially is void* const ptr = base->getBase(); if (ptr != MAP_FAILED) { sp<Surface> sur = new Surface(producer); // capture the screen with glReadPixels() ANativeWindow* window = sur.get(); ScopedTrace _t(ATRACE_TAG, "glReadPixels"); ANativeWindowBuffer* buffer; glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr); void* vaddr; if (glGetError() == GL_NO_ERROR) { *heap = base; if (native_window_api_connect(window, *w = sw; NATIVE_WINDOW_API_CPU) == NO_ERROR) { *h = sh; int err = 0; *f = PIXEL_FORMAT_RGBA_8888; err = native_window_set_buffers_dimensions(window, result = NO_ERROR; reqWidth, reqHeight); } else { err |= native_window_set_buffers_format(window, result = NO_MEMORY; HAL_PIXEL_FORMAT_RGBA_8888); err |= native_window_set_usage(window, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); if (err == NO_ERROR) { if (native_window_dequeue_buffer_and_wait(window, &buffer) == NO_ERROR) { sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer); if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) { if (buffer->stride != int(reqWidth)) { // we're unlucky here, glReadPixels is // not able to deal with a stride not // equal to the width. uint32_t* tmp = new uint32_t[reqWidth*reqHeight]; if (tmp != NULL) { glReadPixels(0, 0, reqWidth, reqHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmp); for (size_t y=0 ; y<reqHeight ; y++) { memcpy((uint32_t*)vaddr + y*buffer->stride, tmp + y*reqWidth, reqWidth*4); } delete [] tmp; } } } else { } else { result = NO_MEMORY; glReadPixels(0, 0, reqWidth, reqHeight, GL_RGBA, GL_UNSIGNED_BYTE, vaddr); } buf->unlock(); } window->queueBuffer(window, buffer, -1); } } native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU); } } } // back to main framebuffer // back to main framebuffer Loading @@ -2742,63 +2784,6 @@ status_t SurfaceFlinger::captureScreenImplLocked( return result; return result; } } status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap, uint32_t* outWidth, uint32_t* outHeight, PixelFormat* outFormat, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) { if (CC_UNLIKELY(display == 0)) return BAD_VALUE; class MessageCaptureScreen : public MessageBase { SurfaceFlinger* flinger; sp<IBinder> display; sp<IMemoryHeap>* heap; uint32_t* outWidth; uint32_t* outHeight; PixelFormat* outFormat; uint32_t reqWidth; uint32_t reqHeight; uint32_t minLayerZ; uint32_t maxLayerZ; status_t result; public: MessageCaptureScreen(SurfaceFlinger* flinger, const sp<IBinder>& display, sp<IMemoryHeap>* heap, uint32_t* outWidth, uint32_t* outHeight, PixelFormat* outFormat, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) : flinger(flinger), display(display), heap(heap), outWidth(outWidth), outHeight(outHeight), outFormat(outFormat), reqWidth(reqWidth), reqHeight(reqHeight), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), result(PERMISSION_DENIED) { } status_t getResult() const { return result; } virtual bool handler() { Mutex::Autolock _l(flinger->mStateLock); sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); result = flinger->captureScreenImplLocked(hw, heap, outWidth, outHeight, outFormat, reqWidth, reqHeight, minLayerZ, maxLayerZ); return true; } }; sp<MessageBase> msg = new MessageCaptureScreen(this, display, heap, outWidth, outHeight, outFormat, reqWidth, reqHeight, minLayerZ, maxLayerZ); status_t res = postMessageSync(msg); if (res == NO_ERROR) { res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult(); } return res; } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- SurfaceFlinger::LayerVector::LayerVector() { SurfaceFlinger::LayerVector::LayerVector() { Loading Loading
include/gui/ISurfaceComposer.h +2 −10 Original line number Original line Diff line number Diff line Loading @@ -95,14 +95,6 @@ public: virtual bool authenticateSurfaceTexture( virtual bool authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& surface) const = 0; const sp<IGraphicBufferProducer>& surface) const = 0; /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ virtual status_t captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap, uint32_t* width, uint32_t* height, PixelFormat* format, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) = 0; /* triggers screen off and waits for it to complete /* triggers screen off and waits for it to complete * requires ACCESS_SURFACE_FLINGER permission. * requires ACCESS_SURFACE_FLINGER permission. */ */ Loading @@ -123,7 +115,8 @@ public: virtual status_t captureScreen(const sp<IBinder>& display, virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) = 0; uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer) = 0; }; }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading @@ -141,7 +134,6 @@ public: GET_BUILT_IN_DISPLAY, GET_BUILT_IN_DISPLAY, SET_TRANSACTION_STATE, SET_TRANSACTION_STATE, AUTHENTICATE_SURFACE, AUTHENTICATE_SURFACE, CAPTURE_SCREEN_DEPRECATED, BLANK, BLANK, UNBLANK, UNBLANK, GET_DISPLAY_INFO, GET_DISPLAY_INFO, Loading
include/gui/SurfaceComposerClient.h +6 −5 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <ui/PixelFormat.h> #include <ui/PixelFormat.h> #include <gui/CpuConsumer.h> #include <gui/SurfaceControl.h> #include <gui/SurfaceControl.h> namespace android { namespace android { Loading @@ -38,7 +39,6 @@ namespace android { class DisplayInfo; class DisplayInfo; class Composer; class Composer; class IMemoryHeap; class ISurfaceComposerClient; class ISurfaceComposerClient; class IGraphicBufferProducer; class IGraphicBufferProducer; class Region; class Region; Loading Loading @@ -164,10 +164,9 @@ public: uint32_t minLayerZ, uint32_t maxLayerZ); uint32_t minLayerZ, uint32_t maxLayerZ); private: private: sp<IMemoryHeap> mHeap; mutable sp<CpuConsumer> mCpuConsumer; uint32_t mWidth; CpuConsumer::LockedBuffer mBuffer; uint32_t mHeight; bool mHaveBuffer; PixelFormat mFormat; public: public: ScreenshotClient(); ScreenshotClient(); Loading @@ -180,6 +179,8 @@ public: uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ); uint32_t minLayerZ, uint32_t maxLayerZ); sp<CpuConsumer> getCpuConsumer() const; // release memory occupied by the screenshot // release memory occupied by the screenshot void release(); void release(); Loading
libs/gui/ISurfaceComposer.cpp +6 −41 Original line number Original line Diff line number Diff line Loading @@ -102,31 +102,11 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } } virtual status_t captureScreen( const sp<IBinder>& display, sp<IMemoryHeap>* heap, uint32_t* width, uint32_t* height, PixelFormat* format, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); data.writeInt32(reqWidth); data.writeInt32(reqHeight); data.writeInt32(minLayerZ); data.writeInt32(maxLayerZ); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_DEPRECATED, data, &reply); *heap = interface_cast<IMemoryHeap>(reply.readStrongBinder()); *width = reply.readInt32(); *height = reply.readInt32(); *format = reply.readInt32(); return reply.readInt32(); } virtual status_t captureScreen(const sp<IBinder>& display, virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer) { { Parcel data, reply; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); Loading @@ -136,6 +116,7 @@ public: data.writeInt32(reqHeight); data.writeInt32(reqHeight); data.writeInt32(minLayerZ); data.writeInt32(minLayerZ); data.writeInt32(maxLayerZ); data.writeInt32(maxLayerZ); data.writeInt32(isCpuConsumer); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); return reply.readInt32(); return reply.readInt32(); } } Loading Loading @@ -285,24 +266,6 @@ status_t BnSurfaceComposer::onTransact( CHECK_INTERFACE(ISurfaceComposer, data, reply); CHECK_INTERFACE(ISurfaceComposer, data, reply); bootFinished(); bootFinished(); } break; } break; case CAPTURE_SCREEN_DEPRECATED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = data.readStrongBinder(); uint32_t reqWidth = data.readInt32(); uint32_t reqHeight = data.readInt32(); uint32_t minLayerZ = data.readInt32(); uint32_t maxLayerZ = data.readInt32(); sp<IMemoryHeap> heap; uint32_t w, h; PixelFormat f; status_t res = captureScreen(display, &heap, &w, &h, &f, reqWidth, reqHeight, minLayerZ, maxLayerZ); reply->writeStrongBinder(heap->asBinder()); reply->writeInt32(w); reply->writeInt32(h); reply->writeInt32(f); reply->writeInt32(res); } break; case CAPTURE_SCREEN: { case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = data.readStrongBinder(); sp<IBinder> display = data.readStrongBinder(); Loading @@ -312,8 +275,10 @@ status_t BnSurfaceComposer::onTransact( uint32_t reqHeight = data.readInt32(); uint32_t reqHeight = data.readInt32(); uint32_t minLayerZ = data.readInt32(); uint32_t minLayerZ = data.readInt32(); uint32_t maxLayerZ = data.readInt32(); uint32_t maxLayerZ = data.readInt32(); bool isCpuConsumer = data.readInt32(); status_t res = captureScreen(display, producer, status_t res = captureScreen(display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); reqWidth, reqHeight, minLayerZ, maxLayerZ, isCpuConsumer); reply->writeInt32(res); reply->writeInt32(res); } break; } break; case AUTHENTICATE_SURFACE: { case AUTHENTICATE_SURFACE: { Loading
libs/gui/SurfaceComposerClient.cpp +49 −29 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <ui/DisplayInfo.h> #include <ui/DisplayInfo.h> #include <gui/CpuConsumer.h> #include <gui/IGraphicBufferProducer.h> #include <gui/IGraphicBufferProducer.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposerClient.h> #include <gui/ISurfaceComposerClient.h> Loading Loading @@ -617,30 +618,21 @@ status_t ScreenshotClient::capture( sp<ISurfaceComposer> s(ComposerService::getComposerService()); sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; if (s == NULL) return NO_INIT; return s->captureScreen(display, producer, return s->captureScreen(display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); reqWidth, reqHeight, minLayerZ, maxLayerZ, false); } } ScreenshotClient::ScreenshotClient() ScreenshotClient::ScreenshotClient() : mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) { : mHaveBuffer(false) { memset(&mBuffer, 0, sizeof(mBuffer)); } } status_t ScreenshotClient::update(const sp<IBinder>& display) { sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (mCpuConsumer == NULL) { if (s == NULL) return NO_INIT; mCpuConsumer = new CpuConsumer(1); mHeap = 0; mCpuConsumer->setName(String8("ScreenshotClient")); return s->captureScreen(display, &mHeap, &mWidth, &mHeight, &mFormat, 0, 0, 0, -1UL); } } return mCpuConsumer; status_t ScreenshotClient::update(const sp<IBinder>& display, uint32_t reqWidth, uint32_t reqHeight) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; mHeap = 0; return s->captureScreen(display, &mHeap, &mWidth, &mHeight, &mFormat, reqWidth, reqHeight, 0, -1UL); } } status_t ScreenshotClient::update(const sp<IBinder>& display, status_t ScreenshotClient::update(const sp<IBinder>& display, Loading @@ -648,38 +640,66 @@ status_t ScreenshotClient::update(const sp<IBinder>& display, uint32_t minLayerZ, uint32_t maxLayerZ) { uint32_t minLayerZ, uint32_t maxLayerZ) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; if (s == NULL) return NO_INIT; mHeap = 0; sp<CpuConsumer> cpuConsumer = getCpuConsumer(); return s->captureScreen(display, &mHeap, &mWidth, &mHeight, &mFormat, reqWidth, reqHeight, if (mHaveBuffer) { minLayerZ, maxLayerZ); mCpuConsumer->unlockBuffer(mBuffer); memset(&mBuffer, 0, sizeof(mBuffer)); mHaveBuffer = false; } status_t err = s->captureScreen(display,cpuConsumer->getBufferQueue(), reqWidth, reqHeight, minLayerZ, maxLayerZ, true); if (err == NO_ERROR) { err = mCpuConsumer->lockNextBuffer(&mBuffer); if (err == NO_ERROR) { mHaveBuffer = true; } } return err; } status_t ScreenshotClient::update(const sp<IBinder>& display) { return ScreenshotClient::update(display, 0, 0, 0, -1UL); } status_t ScreenshotClient::update(const sp<IBinder>& display, uint32_t reqWidth, uint32_t reqHeight) { return ScreenshotClient::update(display, reqWidth, reqHeight, 0, -1UL); } } void ScreenshotClient::release() { void ScreenshotClient::release() { mHeap = 0; if (mHaveBuffer) { mCpuConsumer->unlockBuffer(mBuffer); memset(&mBuffer, 0, sizeof(mBuffer)); mHaveBuffer = false; } mCpuConsumer.clear(); } } void const* ScreenshotClient::getPixels() const { void const* ScreenshotClient::getPixels() const { return mHeap->getBase(); return mBuffer.data; } } uint32_t ScreenshotClient::getWidth() const { uint32_t ScreenshotClient::getWidth() const { return mWidth; return mBuffer.width; } } uint32_t ScreenshotClient::getHeight() const { uint32_t ScreenshotClient::getHeight() const { return mHeight; return mBuffer.height; } } PixelFormat ScreenshotClient::getFormat() const { PixelFormat ScreenshotClient::getFormat() const { return mFormat; return mBuffer.format; } } uint32_t ScreenshotClient::getStride() const { uint32_t ScreenshotClient::getStride() const { return mWidth; return mBuffer.stride; } } size_t ScreenshotClient::getSize() const { size_t ScreenshotClient::getSize() const { return mHeap->getSize(); return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading
services/surfaceflinger/SurfaceFlinger.cpp +80 −95 Original line number Original line Diff line number Diff line Loading @@ -2416,7 +2416,6 @@ status_t SurfaceFlinger::onTransact( break; break; } } case CAPTURE_SCREEN: case CAPTURE_SCREEN: case CAPTURE_SCREEN_DEPRECATED: { { // codes that require permission check // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); IPCThreadState* ipc = IPCThreadState::self(); Loading Loading @@ -2511,7 +2510,8 @@ void SurfaceFlinger::repaintEverything() { status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) { uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer) { if (CC_UNLIKELY(display == 0)) if (CC_UNLIKELY(display == 0)) return BAD_VALUE; return BAD_VALUE; Loading @@ -2525,16 +2525,18 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<IGraphicBufferProducer> producer; sp<IGraphicBufferProducer> producer; uint32_t reqWidth, reqHeight; uint32_t reqWidth, reqHeight; uint32_t minLayerZ,maxLayerZ; uint32_t minLayerZ,maxLayerZ; bool isCpuConsumer; status_t result; status_t result; public: public: MessageCaptureScreen(SurfaceFlinger* flinger, MessageCaptureScreen(SurfaceFlinger* flinger, const sp<IBinder>& display, const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer) : flinger(flinger), display(display), producer(producer), : flinger(flinger), display(display), producer(producer), reqWidth(reqWidth), reqHeight(reqHeight), reqWidth(reqWidth), reqHeight(reqHeight), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), isCpuConsumer(isCpuConsumer), result(PERMISSION_DENIED) result(PERMISSION_DENIED) { { } } Loading @@ -2544,14 +2546,24 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, virtual bool handler() { virtual bool handler() { Mutex::Autolock _l(flinger->mStateLock); Mutex::Autolock _l(flinger->mStateLock); sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); result = flinger->captureScreenImplLocked(hw, producer, // TODO: if we know the GL->CPU path works, we can call reqWidth, reqHeight, minLayerZ, maxLayerZ); // captureScreenImplLocked() directly, instead of using the // "CpuConsumer" version, which is much less efficient -- it is // however needed by some older drivers. if (isCpuConsumer) { result = flinger->captureScreenImplCpuConsumerLocked(hw, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); } else { result = flinger->captureScreenImplLocked(hw, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); } return true; return true; } } }; }; sp<MessageBase> msg = new MessageCaptureScreen(this, sp<MessageBase> msg = new MessageCaptureScreen(this, display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ, isCpuConsumer); status_t res = postMessageSync(msg); status_t res = postMessageSync(msg); if (res == NO_ERROR) { if (res == NO_ERROR) { res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult(); res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult(); Loading Loading @@ -2655,18 +2667,15 @@ status_t SurfaceFlinger::captureScreenImplLocked( } } eglDestroySurface(mEGLDisplay, eglSurface); eglDestroySurface(mEGLDisplay, eglSurface); return NO_ERROR; return NO_ERROR; } } // --------------------------------------------------------------------------- // Capture screen into an IMemoryHeap (legacy) // --------------------------------------------------------------------------- status_t SurfaceFlinger::captureScreenImplLocked( status_t SurfaceFlinger::captureScreenImplCpuConsumerLocked( const sp<const DisplayDevice>& hw, const sp<const DisplayDevice>& hw, sp<IMemoryHeap>* heap, const sp<IGraphicBufferProducer>& producer, uint32_t* w, uint32_t* h, PixelFormat* f, uint32_t reqWidth, uint32_t reqHeight, uint32_t sw, uint32_t sh, uint32_t minLayerZ, uint32_t maxLayerZ) uint32_t minLayerZ, uint32_t maxLayerZ) { { ATRACE_CALL(); ATRACE_CALL(); Loading @@ -2689,7 +2698,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( // call the new screenshot taking code, passing a BufferQueue to it // call the new screenshot taking code, passing a BufferQueue to it status_t result = captureScreenImplLocked(hw, status_t result = captureScreenImplLocked(hw, consumer->getBufferQueue(), sw, sh, minLayerZ, maxLayerZ); consumer->getBufferQueue(), reqWidth, reqHeight, minLayerZ, maxLayerZ); if (result == NO_ERROR) { if (result == NO_ERROR) { result = consumer->updateTexImage(); result = consumer->updateTexImage(); Loading @@ -2701,31 +2710,64 @@ status_t SurfaceFlinger::captureScreenImplLocked( glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); sp<GraphicBuffer> buf(consumer->getCurrentBuffer()); reqWidth = consumer->getCurrentBuffer()->getWidth(); sw = buf->getWidth(); reqHeight = consumer->getCurrentBuffer()->getHeight(); sh = buf->getHeight(); size_t size = sw * sh * 4; { // in this block we render the screenshot into the // allocate shared memory large enough to hold the // CpuConsumer using glReadPixels from our GLConsumer, // screen capture // Some older drivers don't support the GL->CPU path so sp<MemoryHeapBase> base( // have to wrap it with a CPU->CPU path, which is what new MemoryHeapBase(size, 0, "screen-capture") ); // glReadPixels essentially is void* const ptr = base->getBase(); if (ptr != MAP_FAILED) { sp<Surface> sur = new Surface(producer); // capture the screen with glReadPixels() ANativeWindow* window = sur.get(); ScopedTrace _t(ATRACE_TAG, "glReadPixels"); ANativeWindowBuffer* buffer; glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr); void* vaddr; if (glGetError() == GL_NO_ERROR) { *heap = base; if (native_window_api_connect(window, *w = sw; NATIVE_WINDOW_API_CPU) == NO_ERROR) { *h = sh; int err = 0; *f = PIXEL_FORMAT_RGBA_8888; err = native_window_set_buffers_dimensions(window, result = NO_ERROR; reqWidth, reqHeight); } else { err |= native_window_set_buffers_format(window, result = NO_MEMORY; HAL_PIXEL_FORMAT_RGBA_8888); err |= native_window_set_usage(window, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); if (err == NO_ERROR) { if (native_window_dequeue_buffer_and_wait(window, &buffer) == NO_ERROR) { sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer); if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) { if (buffer->stride != int(reqWidth)) { // we're unlucky here, glReadPixels is // not able to deal with a stride not // equal to the width. uint32_t* tmp = new uint32_t[reqWidth*reqHeight]; if (tmp != NULL) { glReadPixels(0, 0, reqWidth, reqHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmp); for (size_t y=0 ; y<reqHeight ; y++) { memcpy((uint32_t*)vaddr + y*buffer->stride, tmp + y*reqWidth, reqWidth*4); } delete [] tmp; } } } else { } else { result = NO_MEMORY; glReadPixels(0, 0, reqWidth, reqHeight, GL_RGBA, GL_UNSIGNED_BYTE, vaddr); } buf->unlock(); } window->queueBuffer(window, buffer, -1); } } native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU); } } } // back to main framebuffer // back to main framebuffer Loading @@ -2742,63 +2784,6 @@ status_t SurfaceFlinger::captureScreenImplLocked( return result; return result; } } status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap, uint32_t* outWidth, uint32_t* outHeight, PixelFormat* outFormat, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) { if (CC_UNLIKELY(display == 0)) return BAD_VALUE; class MessageCaptureScreen : public MessageBase { SurfaceFlinger* flinger; sp<IBinder> display; sp<IMemoryHeap>* heap; uint32_t* outWidth; uint32_t* outHeight; PixelFormat* outFormat; uint32_t reqWidth; uint32_t reqHeight; uint32_t minLayerZ; uint32_t maxLayerZ; status_t result; public: MessageCaptureScreen(SurfaceFlinger* flinger, const sp<IBinder>& display, sp<IMemoryHeap>* heap, uint32_t* outWidth, uint32_t* outHeight, PixelFormat* outFormat, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) : flinger(flinger), display(display), heap(heap), outWidth(outWidth), outHeight(outHeight), outFormat(outFormat), reqWidth(reqWidth), reqHeight(reqHeight), minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), result(PERMISSION_DENIED) { } status_t getResult() const { return result; } virtual bool handler() { Mutex::Autolock _l(flinger->mStateLock); sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); result = flinger->captureScreenImplLocked(hw, heap, outWidth, outHeight, outFormat, reqWidth, reqHeight, minLayerZ, maxLayerZ); return true; } }; sp<MessageBase> msg = new MessageCaptureScreen(this, display, heap, outWidth, outHeight, outFormat, reqWidth, reqHeight, minLayerZ, maxLayerZ); status_t res = postMessageSync(msg); if (res == NO_ERROR) { res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult(); } return res; } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- SurfaceFlinger::LayerVector::LayerVector() { SurfaceFlinger::LayerVector::LayerVector() { Loading