package com.javispedro.vndroid; import android.content.Context; import android.graphics.PixelFormat; import android.hardware.display.DisplayManager; import android.media.ImageReader; import android.media.projection.MediaProjection; import android.os.Handler; import android.support.annotation.NonNull; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; public class ScreenMirrorGrabber extends ScreenGrabber { private static final String TAG = ScreenMirrorGrabber.class.getSimpleName(); protected final MediaProjection projection; protected final Display realDisplay; protected final DisplayMetrics realDisplayMetrics; private float scale = 0.5f; public ScreenMirrorGrabber(Context context, @NonNull MediaProjection proj, @NonNull Display display) { super(context); projection = proj; realDisplay = display; realDisplayMetrics = new DisplayMetrics(); } private void initDisplay() { realDisplay.getRealMetrics(realDisplayMetrics); Log.d(TAG, "real display size: " + realDisplayMetrics.widthPixels + "x" + realDisplayMetrics.heightPixels); int width = Math.round(realDisplayMetrics.widthPixels * scale); int height = Math.round(realDisplayMetrics.heightPixels * scale); int dpi = realDisplayMetrics.densityDpi; Log.d(TAG, "starting mirror display with size: " + width + "x" + height + " dpi: " + dpi); reader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, MAX_IMAGES); reader.setOnImageAvailableListener(new ImageReaderCallback(), null); display = projection.createVirtualDisplay("vndroid", width, height, dpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, reader.getSurface(), new VirtualDisplayCallback(), null); } @Override public void start() { if (reader != null || display != null) { Log.w(TAG, "already started"); return; } initDisplay(); } @Override public void stop() { super.stop(); projection.stop(); } @Override public int scaleInputX(int x) { return Math.round(x / scale); } @Override public int scaleInputY(int y) { return Math.round(y / scale); } @Override public boolean hasSizeChanged() { DisplayMetrics metrics = new DisplayMetrics(); realDisplay.getRealMetrics(metrics); return metrics.widthPixels != realDisplayMetrics.widthPixels || metrics.heightPixels != realDisplayMetrics.heightPixels; } @Override public void updateScreenSize() { final ImageReader oldReader = reader; reader = null; if (display != null) { display.release(); display = null; } initDisplay(); Log.d(TAG, "new buffers set"); // Delay destruction of old image buffers to minimize multithread issues... if (oldReader != null) { new Handler().postDelayed(new Runnable() { @Override public void run() { Log.d(TAG, "old buffers closed"); oldReader.close(); } }, 1000); } } }