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