Device.java 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package org.las2mile.scrcpy;
  2. import android.graphics.Point;
  3. import android.os.Build;
  4. import android.os.RemoteException;
  5. import android.view.IRotationWatcher;
  6. import android.view.InputEvent;
  7. import org.las2mile.scrcpy.wrappers.ServiceManager;
  8. public final class Device {
  9. private final ServiceManager serviceManager = new ServiceManager();
  10. private ScreenInfo screenInfo;
  11. private RotationListener rotationListener;
  12. public Device(Options options) {
  13. screenInfo = computeScreenInfo(options.getMaxSize());
  14. registerRotationWatcher(new IRotationWatcher.Stub() {
  15. @Override
  16. public void onRotationChanged(int rotation) throws RemoteException {
  17. synchronized (Device.this) {
  18. screenInfo = screenInfo.withRotation(rotation);
  19. // notify
  20. if (rotationListener != null) {
  21. rotationListener.onRotationChanged(rotation);
  22. }
  23. }
  24. }
  25. });
  26. }
  27. public static String getDeviceName() {
  28. return Build.MODEL;
  29. }
  30. public synchronized ScreenInfo getScreenInfo() {
  31. return screenInfo;
  32. }
  33. @SuppressWarnings("checkstyle:MagicNumber")
  34. private ScreenInfo computeScreenInfo(int maxSize) {
  35. // Compute the video size and the padding of the content inside this video.
  36. // Principle:
  37. // - scale down the great side of the screen to maxSize (if necessary);
  38. // - scale down the other side so that the aspect ratio is preserved;
  39. // - round this value to the nearest multiple of 8 (H.264 only accepts multiples of 8)
  40. DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
  41. boolean rotated = (displayInfo.getRotation() & 1) != 0;
  42. Size deviceSize = displayInfo.getSize();
  43. int w = deviceSize.getWidth() & ~7; // in case it's not a multiple of 8
  44. int h = deviceSize.getHeight() & ~7;
  45. if (maxSize > 0) {
  46. if (BuildConfig.DEBUG && maxSize % 8 != 0) {
  47. throw new AssertionError("Max size must be a multiple of 8");
  48. }
  49. boolean portrait = h > w;
  50. int major = portrait ? h : w;
  51. int minor = portrait ? w : h;
  52. if (major > maxSize) {
  53. int minorExact = minor * maxSize / major;
  54. // +4 to round the value to the nearest multiple of 8
  55. minor = (minorExact + 4) & ~7;
  56. major = maxSize;
  57. }
  58. w = portrait ? minor : major;
  59. h = portrait ? major : minor;
  60. }
  61. Size videoSize = new Size(w, h);
  62. return new ScreenInfo(deviceSize, videoSize, rotated);
  63. }
  64. public Point getPhysicalPoint(Position position) {
  65. @SuppressWarnings("checkstyle:HiddenField") // it hides the field on purpose, to read it with a lock
  66. ScreenInfo screenInfo = getScreenInfo(); // read with synchronization
  67. Size videoSize = screenInfo.getVideoSize();
  68. Size clientVideoSize = position.getScreenSize();
  69. if (!videoSize.equals(clientVideoSize)) {
  70. // The client sends a click relative to a video with wrong dimensions,
  71. // the device may have been rotated since the event was generated, so ignore the event
  72. return null;
  73. }
  74. Size deviceSize = screenInfo.getDeviceSize();
  75. Point point = position.getPoint();
  76. int scaledX = point.x * deviceSize.getWidth() / videoSize.getWidth();
  77. int scaledY = point.y * deviceSize.getHeight() / videoSize.getHeight();
  78. return new Point(scaledX, scaledY);
  79. }
  80. public boolean injectInputEvent(InputEvent inputEvent, int mode) {
  81. return serviceManager.getInputManager().injectInputEvent(inputEvent, mode);
  82. }
  83. public boolean isScreenOn() {
  84. return serviceManager.getPowerManager().isScreenOn();
  85. }
  86. public void registerRotationWatcher(IRotationWatcher rotationWatcher) {
  87. serviceManager.getWindowManager().registerRotationWatcher(rotationWatcher);
  88. }
  89. public synchronized void setRotationListener(RotationListener rotationListener) {
  90. this.rotationListener = rotationListener;
  91. }
  92. public Point NewgetPhysicalPoint(Point point) {
  93. @SuppressWarnings("checkstyle:HiddenField") // it hides the field on purpose, to read it with a lock
  94. ScreenInfo screenInfo = getScreenInfo(); // read with synchronization
  95. Size videoSize = screenInfo.getVideoSize();
  96. // Size clientVideoSize = position.getScreenSize();
  97. Size deviceSize = screenInfo.getDeviceSize();
  98. // Point point = position.getPoint();
  99. int scaledX = point.x * deviceSize.getWidth() / videoSize.getWidth();
  100. int scaledY = point.y * deviceSize.getHeight() / videoSize.getHeight();
  101. return new Point(scaledX, scaledY);
  102. }
  103. public interface RotationListener {
  104. void onRotationChanged(int rotation);
  105. }
  106. }