Move screen-related features out of Device.java

Move the code related to screen size and rotation/fold to ScreenCapture.

For now, keep the ScreenInfo instance in the Device class to communicate
with the Controller, but it will be removed by further commits.

PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
This commit is contained in:
Romain Vimont
2024-10-12 09:23:31 +02:00
parent 14e5439dee
commit 874eaec487
5 changed files with 135 additions and 141 deletions

View File

@@ -1,9 +1,12 @@
package com.genymobile.scrcpy.video;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.device.ConfigurationException;
import com.genymobile.scrcpy.device.Device;
import com.genymobile.scrcpy.device.DisplayInfo;
import com.genymobile.scrcpy.device.Size;
import com.genymobile.scrcpy.util.Ln;
import com.genymobile.scrcpy.util.LogUtils;
import com.genymobile.scrcpy.wrappers.ServiceManager;
import com.genymobile.scrcpy.wrappers.SurfaceControl;
@@ -11,33 +14,104 @@ import android.graphics.Rect;
import android.hardware.display.VirtualDisplay;
import android.os.Build;
import android.os.IBinder;
import android.view.IDisplayFoldListener;
import android.view.IRotationWatcher;
import android.view.Surface;
public class ScreenCapture extends SurfaceCapture implements Device.RotationListener, Device.FoldListener {
public class ScreenCapture extends SurfaceCapture {
private final Device device;
private final int displayId;
private int maxSize;
private final Rect crop;
private final int lockVideoOrientation;
private int layerStack;
private Size deviceSize;
private ScreenInfo screenInfo;
private IBinder display;
private VirtualDisplay virtualDisplay;
public ScreenCapture(Device device) {
private IRotationWatcher rotationWatcher;
private IDisplayFoldListener displayFoldListener;
public ScreenCapture(Device device, int displayId, int maxSize, Rect crop, int lockVideoOrientation) {
this.device = device;
this.displayId = displayId;
this.maxSize = maxSize;
this.crop = crop;
this.lockVideoOrientation = lockVideoOrientation;
}
@Override
public void init() {
device.setRotationListener(this);
device.setFoldListener(this);
public void init() throws ConfigurationException {
DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId);
if (displayInfo == null) {
Ln.e("Display " + displayId + " not found\n" + LogUtils.buildDisplayListMessage());
throw new ConfigurationException("Unknown display id: " + displayId);
}
deviceSize = displayInfo.getSize();
ScreenInfo si = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation);
setScreenInfo(si);
layerStack = displayInfo.getLayerStack();
if (displayId == 0) {
rotationWatcher = new IRotationWatcher.Stub() {
@Override
public void onRotationChanged(int rotation) {
synchronized (ScreenCapture.this) {
ScreenInfo si = screenInfo.withDeviceRotation(rotation);
setScreenInfo(si);
}
requestReset();
}
};
ServiceManager.getWindowManager().registerRotationWatcher(rotationWatcher, displayId);
}
if (Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10) {
displayFoldListener = new IDisplayFoldListener.Stub() {
@Override
public void onDisplayFoldChanged(int displayId, boolean folded) {
if (ScreenCapture.this.displayId != displayId) {
// Ignore events related to other display ids
return;
}
synchronized (ScreenCapture.this) {
DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId);
if (displayInfo == null) {
Ln.e("Display " + displayId + " not found\n" + LogUtils.buildDisplayListMessage());
return;
}
deviceSize = displayInfo.getSize();
ScreenInfo si = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation);
setScreenInfo(si);
}
requestReset();
}
};
ServiceManager.getWindowManager().registerDisplayFoldListener(displayFoldListener);
}
if ((displayInfo.getFlags() & DisplayInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) == 0) {
Ln.w("Display doesn't have FLAG_SUPPORTS_PROTECTED_BUFFERS flag, mirroring can be restricted");
}
}
@Override
public void start(Surface surface) {
ScreenInfo screenInfo = device.getScreenInfo();
Rect contentRect = screenInfo.getContentRect();
// does not include the locked video orientation
Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect();
int videoRotation = screenInfo.getVideoRotation();
int layerStack = device.getLayerStack();
if (display != null) {
SurfaceControl.destroyDisplay(display);
@@ -51,7 +125,7 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
try {
Rect videoRect = screenInfo.getVideoSize().toRect();
virtualDisplay = ServiceManager.getDisplayManager()
.createVirtualDisplay("scrcpy", videoRect.width(), videoRect.height(), device.getDisplayId(), surface);
.createVirtualDisplay("scrcpy", videoRect.width(), videoRect.height(), displayId, surface);
Ln.d("Display: using DisplayManager API");
} catch (Exception displayManagerException) {
try {
@@ -68,8 +142,12 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
@Override
public void release() {
device.setRotationListener(null);
device.setFoldListener(null);
if (rotationWatcher != null) {
ServiceManager.getWindowManager().unregisterRotationWatcher(rotationWatcher);
}
if (Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10) {
ServiceManager.getWindowManager().unregisterDisplayFoldListener(displayFoldListener);
}
if (display != null) {
SurfaceControl.destroyDisplay(display);
display = null;
@@ -81,26 +159,18 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
}
@Override
public Size getSize() {
return device.getScreenInfo().getVideoSize();
public synchronized Size getSize() {
return screenInfo.getVideoSize();
}
@Override
public boolean setMaxSize(int maxSize) {
device.setMaxSize(maxSize);
public synchronized boolean setMaxSize(int newMaxSize) {
maxSize = newMaxSize;
ScreenInfo si = ScreenInfo.computeScreenInfo(screenInfo.getReverseVideoRotation(), deviceSize, crop, newMaxSize, lockVideoOrientation);
setScreenInfo(si);
return true;
}
@Override
public void onFoldChanged(int displayId, boolean folded) {
requestReset();
}
@Override
public void onRotationChanged(int rotation) {
requestReset();
}
private static IBinder createDisplay() throws Exception {
// Since Android 12 (preview), secure displays could not be created with shell permissions anymore.
// On Android 12 preview, SDK_INT is still R (not S), but CODENAME is "S".
@@ -119,4 +189,9 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
SurfaceControl.closeTransaction();
}
}
private void setScreenInfo(ScreenInfo si) {
screenInfo = si;
device.setScreenInfo(si);
}
}