You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
scrcpy/server/src/main/java/com/genymobile/scrcpy/Device.java

116 lines
4.5 KiB
Java

package com.genymobile.scrcpy;
import android.os.Build;
import android.os.RemoteException;
import android.view.IRotationWatcher;
import com.genymobile.scrcpy.wrappers.InputManager;
import com.genymobile.scrcpy.wrappers.ServiceManager;
public final class Device {
public interface RotationListener {
void onRotationChanged(int rotation);
}
private final ServiceManager serviceManager = new ServiceManager();
private ScreenInfo screenInfo;
private RotationListener rotationListener;
public Device(Options options) {
screenInfo = computeScreenInfo(options.getMaximumSize());
registerRotationWatcher(new IRotationWatcher.Stub() {
@Override
public void onRotationChanged(int rotation) throws RemoteException {
synchronized (Device.this) {
screenInfo = screenInfo.withRotation(rotation);
// notify
if (rotationListener != null) {
rotationListener.onRotationChanged(rotation);
}
}
}
});
}
public synchronized ScreenInfo getScreenInfo() {
return screenInfo;
}
private ScreenInfo computeScreenInfo(int maximumSize) {
// Compute the video size and the padding of the content inside this video.
// Principle:
// - scale down the great side of the screen to maximumSize (if necessary);
// - scale down the other side so that the aspect ratio is preserved;
// - ceil this value to the next multiple of 8 (H.264 only accepts multiples of 8)
// - this may introduce black bands, so store the padding (typically a few pixels)
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
boolean rotated = (displayInfo.getRotation() & 1) != 0;
Size deviceSize = displayInfo.getSize();
int w = deviceSize.getWidth();
int h = deviceSize.getHeight();
int padding = 0;
if (maximumSize > 0) {
assert maximumSize % 8 == 0;
boolean portrait = h > w;
int major = portrait ? h : w;
int minor = portrait ? w : h;
if (major > maximumSize) {
int minorExact = minor * maximumSize / major;
// +7 to ceil the value on rounding to the next multiple of 8,
// so that any necessary black bands to keep the aspect ratio are added to the smallest dimension
minor = (minorExact + 7) & ~7;
major = maximumSize;
padding = minor - minorExact;
}
w = portrait ? minor : major;
h = portrait ? major : minor;
}
return new ScreenInfo(deviceSize, new Size(w, h), padding, rotated);
}
public Point getPhysicalPoint(Position position) {
ScreenInfo screenInfo = getScreenInfo(); // read with synchronization
Size videoSize = screenInfo.getVideoSize();
Size clientVideoSize = position.getScreenSize();
if (!videoSize.equals(clientVideoSize)) {
// The client sends a click relative to a video with wrong dimensions,
// the device may have been rotated since the event was generated, so ignore the event
return null;
}
Size deviceSize = screenInfo.getDeviceSize();
int xPadding = screenInfo.getXPadding();
int yPadding = screenInfo.getYPadding();
int contentWidth = videoSize.getWidth() - xPadding;
int contentHeight = videoSize.getHeight() - yPadding;
Point point = position.getPoint();
int x = point.getX() - xPadding / 2;
int y = point.getY() - yPadding / 2;
if (x < 0 || x >= contentWidth || y < 0 || y >= contentHeight) {
// out of screen
return null;
}
int scaledX = x * deviceSize.getWidth() / videoSize.getWidth();
int scaledY = y * deviceSize.getHeight() / videoSize.getHeight();
return new Point(scaledX, scaledY);
}
public static String getDeviceName() {
return Build.MODEL;
}
public InputManager getInputManager() {
return serviceManager.getInputManager();
}
public void registerRotationWatcher(IRotationWatcher rotationWatcher) {
serviceManager.getWindowManager().registerRotationWatcher(rotationWatcher);
}
public synchronized void setRotationListener(RotationListener rotationListener) {
this.rotationListener = rotationListener;
}
}