Problem using MediaProjection/VirtualDispay/ImageReader to take screenshots an Android 9

已查看 463 次
跳至第一个未读帖子

Guillaume Stols

未读,
2020年8月20日 12:00:172020/8/20
收件人 andro...@googlegroups.com


Hi everybody,

I encounter an issue when taking screenshots using the "imagereader" method, but I get an exception, with the message "lock buffer failed for format 0x1" when calling image.getPlanes() (see below for the code). This does not happen on Android 7, nor on my phone's Android9 (ARM of course).

I alse tried different flags for pixelFormat, but had no luck, all the time I got an exception, saying  "The producer output buffer format 0x1 doesn't match the ImageReader's configured buffer format 0x4."

To reproduce the issue, you can clone https://github.com/omerjerk/Screenshotter, and replace mImageReader = ImageReader.newInstance(width, height, ImageFormat.RGB_565, 2); with mImageReader = ImageReader.newInstance(width, height, 1, 2);

Below, in the log, you can also see that there are a lot of xxx failed for display -1: Invalid display, which I think show more accurately the source of the issue.

08-20 15:12:24.427   495   495 I ScreenCaptureFragment: Setting up a VirtualDisplay: 765x664 (160)
08-20 15:12:24.430  1674  2384 I DisplayManagerService: Display device added: DisplayDeviceInfo{"ScreenCapture": uniqueId="virtual:com.example.android.screencapture,10065,ScreenCapture,0", 765 x 664, modeId 28, defaultModeId 28, supportedModes [{id=28, width=765, height=664, fps=60.0}], colorMode 0, supportedColorModes [0], HdrCapabilities null, density 160, 160.0 x 160.0 dpi, appVsyncOff 0, presDeadline 16666666, touch NONE, rotation 0, type VIRTUAL, state ON, owner com.example.android.screencapture (uid 10065), FLAG_PRIVATE, FLAG_PRESENTATION}
08-20 15:12:24.434  1674  1749 I InputReader: Reconfiguring input devices.  changes=0x00000004
08-20 15:12:24.437  1519  1519 E HWComposer: getHdrCapabilities failed for display -1: Invalid display
08-20 15:12:24.439  1519  1519 E HWComposer: getSupportedPerFrameMetadata failed for display -1: Invalid display
08-20 15:12:24.442  1519  1519 E SurfaceFlinger: setSharedBufferMode not supported on VirtualDisplaySurface
08-20 15:12:24.442  1519  1519 E Surface : IGraphicBufferProducer::setSharedBufferMode(0) returnedFunction not implemented
08-20 15:12:24.442  1519  1519 W EGL-MAIN: failed native_window_set_shared_buffer_mode(window=0x7f6a1aaae010, mode=0)
08-20 15:12:24.447   495  5377 D ScreenCaptureFragment: 'handleOnImageAvailable' called
08-20 15:12:24.448  1519  1519 E SurfaceFlinger: setSharedBufferMode not supported on VirtualDisplaySurface
08-20 15:12:24.448  1519  1519 E Surface : IGraphicBufferProducer::setSharedBufferMode(0) returnedFunction not implemented
08-20 15:12:24.448  1519  1519 W EGL-MAIN: failed native_window_set_shared_buffer_mode(window=0x7f6a1aaae010, mode=0)
08-20 15:12:24.448  1519  1519 E HWComposer: getLayerReleaseFence failed for display -1: Invalid display
08-20 15:12:24.448  1519  1519 E HWComposer: getLayerReleaseFence failed for display -1: Invalid display
08-20 15:12:24.454   495  5377 D ScreenCaptureFragment: Getting plane 0 byte buffer ...
08-20 15:12:24.454   495  5377 I GRALLOC-GBM: lock bo 0x716a0bf8b130, cnt=0, usage=3
08-20 15:12:24.454   495  5377 W GraphicBufferMapper: lock(0x7169fec86140, ...) failed: 3
08-20 15:12:24.454   495  5377 E AndroidMediaUtils: Lock buffer failed!
08-20 15:12:24.454   495  5377 E AndroidMediaUtils: lockImageFromBuffer: lock graphic buffer failed

//Exception thrown

08-20 15:12:24.454   495  5377 D ScreenCaptureFragment: Screenshot exception 'lock buffer failed for format 0x1'
08-20 15:12:24.454   495  5377 D ScreenCaptureFragment: Screenshot exception 'Attempt to read from null array'
08-20 15:12:24.458  1519  1519 D SurfaceFlinger: duplicate layer name: changing Display Root to Display Root#10
08-20 15:12:24.460  1519  1519 E SurfaceFlinger: setSharedBufferMode not supported on VirtualDisplaySurface

//Then I get several

08-20 15:12:24.460  1519  1519 E Surface : IGraphicBufferProducer::setSharedBufferMode(0) returnedFunction not implemented
08-20 15:12:24.460  1519  1519 W EGL-MAIN: failed native_window_set_shared_buffer_mode(window=0x7f6a1aaae010, mode=0)
08-20 15:12:24.466   495  5377 D ScreenCaptureFragment: 'handleOnImageAvailable' called
08-20 15:12:24.467  1519  1519 E SurfaceFlinger: setSharedBufferMode not supported on VirtualDisplaySurface
08-20 15:12:24.467  1519  1519 E Surface : IGraphicBufferProducer::setSharedBufferMode(0) returnedFunction not implemented
08-20 15:12:24.467  1519  1519 W EGL-MAIN: failed native_window_set_shared_buffer_mode(window=0x7f6a1aaae010, mode=0)
08-20 15:12:24.467  1519  1519 E HWComposer: getLayerReleaseFence failed for display -1: Invalid display
08-20 15:12:24.467  1519  1519 E HWComposer: getLayerReleaseFence failed for display -1: Invalid display


The exception is thrown here:

private void handleOnImageAvailable(ImageReader reader)
{
 Image image=reader.acquireNextImage();
 [...]
 Image.Plane[] planes = null;
 try {
     planes = image.getPlanes();<-Throws an excaption with message "lock buffer failed for format 0x1"
     [...]
 }
}


Here is the setup function:


private void setUpVirtualDisplay() {

        final int pixelFormat=PixelFormat.RGBA_8888;
        final Bitmap.Config bitmapConfig=Bitmap.Config.ARGB_8888;
        final String label="TlmeMdmAgScreenCapture";

        DisplayMetrics metrics=new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int screenDensity=metrics.densityDpi;
        int screenWidth=metrics.widthPixels;
        int screenHeight=metrics.heightPixels;
Log.d(TAG,"VIRT DISPLAY");
        HandlerThread handlerThread=new HandlerThread(label);
        handlerThread.start();
        Handler handler=new Handler(handlerThread.getLooper());


        this.screenShotImageReaderAcquiredImage=null;

        this.screenShotImageReader=ImageReader.newInstance(screenWidth,screenHeight,pixelFormat,30);

        if(handler!=null)
        {
            this.screenShotImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener()
            {
                @Override
                public void onImageAvailable(ImageReader reader)
                {
                    handleOnImageAvailable(reader);
                }
            }, handler);
        }
        else
        {
            Log.e(TAG, "'getMediaProjection' no handler for 'onImageAvailable'");
        }

        mSurface=this.screenShotImageReader.getSurface();
        Log.i(TAG, "Setting up a VirtualDisplay: " +
                mSurfaceView.getWidth() + "x" + mSurfaceView.getHeight() +
                " (" + mScreenDensity + ")");
        mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenCapture",
                mSurfaceView.getWidth(), mSurfaceView.getHeight(), mScreenDensity,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mSurface, null, null);
        mButtonToggle.setText(R.string.stop);
    }
   
   
So, if anybody have any hint on how to fix it, any help is welcome !

Thanks and regards,

Guillaume

回复全部
回复作者
转发
0 个新帖子