Commit Graph

55 Commits

Author SHA1 Message Date
Romain Vimont b882322f73 Work around Os.write() not updating position
ByteBuffer position is not updated as expected by Os.write() on old
Android versions. Count the remaining bytes manually.

Fixes <https://github.com/Genymobile/scrcpy/issues/291>.
2018-10-09 08:43:17 +02:00
Romain Vimont 66def38b73 Avoid additional buffer copy in userspace
Directly send the data from MediaCodec buffers to the LocalSocket,
without an intermediate copy in userspace.
2018-09-09 15:05:06 +02:00
Romain Vimont caa9e30004 Add crop feature
Add an option to crop the screen on the server. This allows to mirror
only part of the device screen.
2018-08-09 19:12:27 +02:00
Romain Vimont e85010fbc2 Move annotation comment
This confused the Android Studio code formatter.
2018-08-09 18:23:38 +02:00
Romain Vimont 820cd2bb54 Extract video size computation
One method, one thing.
2018-08-09 18:22:52 +02:00
Romain Vimont 16a3de1796 Make checkstyle happy
Reorder the imports to remove checkstyle warnings.
2018-03-28 22:05:34 +02:00
Romain Vimont c530d95881 Immediately close the server socket on the device
In "adb forward" mode, close the server socket as soon as the client is
connected.

Even if unlikely to be useful, it allows to run several instances of
scrcpy also in "adb forward" mode.
2018-03-14 09:28:25 +01:00
Romain Vimont 1038bad385 Make it work over tcpip
"adb reverse" currently does not work over tcpip (i.e. on a device
connected by "adb connect"):
<https://issuetracker.google.com/issues/37066218>

To work around the problem, if the call to "adb reverse" fails, then
fallback to "adb forward", and reverse the client/server roles.

Keep the "adb reverse" mode as the default because it does not involve
connection retries: when using "adb forward", the client must try to
connect successively until the server listens.

Due to the tunnel, every connect() will succeed, so the client must
attempt to read() to detect a connection failure. For this purpose, when
using the "adb forward" mode, the server initially writes a dummy byte,
read by the client.

Fixes <https://github.com/Genymobile/scrcpy/issues/5>.
2018-03-12 14:10:32 +01:00
Romain Vimont c075ad0a1e Fix mouse clicks on LG devices
Use default values (0) for some fields of PointerCoords so that mouse
clicks work correctly on LG devices.

Fixes <https://github.com/Genymobile/scrcpy/issues/18>.
2018-03-11 14:11:43 +01:00
Romain Vimont dac7196bd6 Support screens with dimensions not divisible by 8
The codec only supports dimensions which are multiple of 8.

Thus, when --max-size is specified, the value is always rounded down to
the nearest multiple of 8.

However, it was wrongly assumed that the physical size is always a
multiple of 8. To support such devices, also round down the physical
screen dimensions.

Fixes <https://github.com/Genymobile/scrcpy/issues/39>.
2018-03-11 14:09:25 +01:00
Romain Vimont 675704c71c Map right-click to BACK if screen is on
Right-click was used to turn the screen on. It did nothing when the
screen was already on.

Instead, in that case, press BACK (like Vysor).

Suggested by: <https://www.reddit.com/r/Android/comments/834zmr/introducing_scrcpy_an_app_to_display_and_control/dvfueft/>
2018-03-10 00:16:29 +01:00
Romain Vimont 9396ea6d42 Fix text input event segfault
The text input control_event was initially designed for mapping
SDL_TextInputEvent, limited to 32 characters.

For simplicity, the copy/paste feature was implemented using the same
control_event: it just sends the text to paste.

However, the pasted text might have a length breaking some assumptions:
 - on the client, the event max-size was smaller than the text
   max-length,
 - on the server, the raw buffer storing the events was smaller than the
   max event size.

Fix these inconsistencies, and encode the length on 2 bytes, to accept
more than 256 characters.

Fixes <https://github.com/Genymobile/scrcpy/issues/10>.
2018-03-09 22:30:10 +01:00
Romain Vimont e2a7abcd53 Implement clipboard paste
Paste computer clipboard to the device on Ctrl+v.

The other direction (pasting the device clipboard to the computer) is
not implemented. It would require a communication channel from the
device to the computer, other than the socket used by the video stream.
2018-03-07 18:07:02 +01:00
Romain Vimont 633b18d786 Provide a better URL to document key decomposition
Directly link to the relevant subsection.
2018-03-07 18:07:02 +01:00
Romain Vimont e3f5d3b49b Double the default bitrate
Set the default video bitrate to 8Mbps. This greatly increase quality on
fast motion, without negative side effects.
2018-03-07 18:04:38 +01:00
Romain Vimont a7979e4e74 Rename rotation detection method name
The old name checkRotationChanged() did not suggest that the flag was
reset.
2018-03-07 18:04:38 +01:00
Romain Vimont b61310a257 Initialize eof flag from BufferInfo
Stop encoding if the codec signaled the end of stream.

The eof flag was read, but never written.
2018-02-28 15:40:52 +01:00
Romain Vimont 487cb10cf0 Rename ScrCpyServer to Server
The Server class is in package scrcpy, there is no need to repeat the
name in the classname.
2018-02-28 14:57:18 +01:00
Romain Vimont 37af0c8076 Terminate event controller thread on EOF
No exception was thrown on EOF, so the event controller did not
terminate. This leaded to a further InvocationTargetException.

Instead, terminate the event controller on EOF, so that the process
terminates properly.
2018-02-16 14:13:13 +01:00
Romain Vimont ad6209f6ff Terminate the device process gracefully
Call shutdown() on the device socket to make the device process finish
its execution quickly and gracefully, without killing it.
2018-02-16 11:47:42 +01:00
Romain Vimont a5b6c6cc2d Enable debug logs only for debug builds on server
Print the logs only if their level is not under the threshold, which is
defined to INFO in release mode and DEBUG in debug mode.
2018-02-12 17:19:52 +01:00
Romain Vimont 000c70a644 Decompose accented characters
Characters like 'é' or 'î' are not resolved by getEvents(). For example,
getEvents("é") returns null.

However, it is possible to decompose them. For example,
getEvents("\u0301e") returns the events generating "é".

Thank you Philippe! ;)
2018-02-12 14:17:10 +01:00
Romain Vimont 063cfd1326 Turn screen on in control()
Turning the screen on is semantically associated to control(): only
creating the EventController object should not turn the screen on.
2018-02-09 14:03:25 +01:00
Romain Vimont c683872bbc Avoid server stacktraces on close
On close, the socket is closed by the client, and the server process is
killed.

This leads to (expected) exceptions, that should not be printed.
2018-02-09 10:59:15 +01:00
Romain Vimont e55e42a442 Apply Genymobile rules for Android projects
Apply Genymobile checkstyle and gradle build files organization.
2018-02-07 20:58:18 +01:00
Romain Vimont 285fc97d02 Fix horizontal scrolling constant
Use AXIS_HSCROLL (available since API 12) instead of AXIS_SCROLL (since
API 26).
2018-02-07 20:50:58 +01:00
Romain Vimont c6d01331ed Simplify EventController
In handleEvent(), connection.receiveControlEvent() may never return
null: either it returns a valid ControlEvent, either it throws an
Exception.

Therefore, there is no need to propagate a flag to indicate whether it
returned a valid ControlEvent.
2018-02-07 17:48:21 +01:00
Romain Vimont 03c5f97e3f Extract control event parsing to separate methods
Use one parse method per control event type.
2018-02-07 17:45:28 +01:00
Romain Vimont 5f51d605c0 Recreate codec and display on rotation changed
On some devices, we can reuse the same codec and display, but on some
others (e.g. Nexus 5X with Android 7.1.2), it crashes on codec.stop()
with an IllegalStateException.

Therefore, always recreate the codec and display, so that it works on
all devices.
2018-02-07 16:32:16 +01:00
Romain Vimont d5acc8adc5 Always release output buffer
If rotation changed, the dequeued output buffer was never released. Move
it to a finally block to avoid the leak.
2018-02-07 15:50:38 +01:00
Romain Vimont 1ac37c4291 Hide services in Device
Expose useful methods directly in Device, without exposing the service
managers.
2018-02-02 17:06:57 +01:00
Romain Vimont 06333e1e08 Cache managers in ServiceManager
To guarantee that we instantiate services only one, cache the value the
first time.
2018-02-02 16:25:37 +01:00
Romain Vimont 3365460658 Turn screen on on start
When starting scrcpy, immediately turn the screen on.
2018-02-02 14:57:33 +01:00
Romain Vimont a139509f11 Turn screen on on right-click
The right-click is almost useless on Android, so use it to turn the
screen on.

Add a new control event type (command) to request the server to turn the
screen on.
2018-02-02 14:56:03 +01:00
Romain Vimont 228545cefd Reformat EventController
Reformated by Android Studio.
2018-02-02 14:52:00 +01:00
Romain Vimont 6b546a87ab Add bit-rate command-line option
Add a command-line option (-b/--bit-rate) to customize the video
bit-rate.
2018-02-01 17:11:40 +01:00
Romain Vimont ee93f3f23a Rename maximum_size to max_size
The long option is --max-size, so for consistency, adapt the code
accordingly.
2018-02-01 17:11:40 +01:00
Romain Vimont 865ebb3862 Encode video using MediaCodec API
Replace screenrecord execution by manual screen encoding using the
MediaCodec API.

The "screenrecord" solution had several drawbacks:
 - screenrecord output is buffered, so tiny frames may not be accessible
   immediately;
 - it did not output a frame until the surface changed, leading to a
   black screen on start;
 - it is limited to 3 minutes recording, so it needed to be restarted;
 - screenrecord added black borders in the video when the requested
   dimensions did not preserve aspect-ratio exactly (sometimes
   unavoidable since video dimensions must be multiple of 8);
 - rotation handling was hacky (killing the process and starting a new
   one).

Handling the encoding manually allows to solve all these problems.
2018-01-31 19:51:43 +01:00
Romain Vimont 7ed334915e Register uncaught exception handler
Never miss an exception by using an uncaught exception handler.
2018-01-31 19:50:45 +01:00
Romain Vimont 8c4a454d68 Extract argument parsing
Move argument parsing to a separate method.
2018-01-31 19:49:49 +01:00
Romain Vimont 73831a0837 Use the Point class from the framework
Replace our custom Point class by android.graphics.Point.
2018-01-31 19:42:08 +01:00
Romain Vimont b67907e24e Convert server to an Android project
To simplify the device server-side build, use gradle to create an APK,
even if we use it as a simple jar, by running its main() method.
2018-01-30 12:01:36 +01:00
Romain Vimont 89f6a3cfe7 Handle resized video stream
Accept a parameter to limit the video size.

For instance, with "-m 960", the great side of the video will be scaled
down to 960 (if necessary), while the other side will be scaled down so
that the aspect ratio is preserved. Both dimensions must be a multiple
of 8, so black bands might be added, and the mouse positions must be
computed accordingly.
2018-01-29 15:40:33 +01:00
Romain Vimont 2c4ea6869e Do not use device as a singleton
The device instance should be able to store a state (e.g. the maximum
size requested by the user), so it should not be a singleton.
2018-01-29 15:00:15 +01:00
Romain Vimont 879941355d Swap position/point names
A point is a 2D vector. A position represent a point relative to the
screen size.
2018-01-29 14:52:22 +01:00
Romain Vimont f70359f14f Inject mouse events as touchscreen
As a mouse, some clicks on close prositions are sometimes not generated
on some devices.
2018-01-25 17:17:21 +01:00
Romain Vimont 1930c81062 Add toString() methods to java point classes
Useful for debugging.
2018-01-25 17:16:32 +01:00
Romain Vimont 8984c1a7c4 Scale mouse events
The video screen size on the client may differ from the real device
screen size (e.g. the video stream may be scaled down). As a
consequence, mouse events must be scaled to match the real device
coordinates.

For this purpose, make the client send the video screen size along with
the absolute pointer location, and the server scale the location to
match the real device size before injecting mouse events.
2018-01-23 16:44:59 +01:00
Romain Vimont 11a60e5767 Keep screen info in cache
Currently, we only use screen information (width, height, rotation)
once at initialization, to send the device size to the client.

To be able to scale mouse events, make it accessible in memory. For this
purpose, replace the "static" DeviceUtil to a singleton Device, and
update it on every screen rotation.
2018-01-23 16:44:59 +01:00
Romain Vimont 3078894d1f Add debug log on new screenrecord execution
To easily notice problems with screenrecord execution, log every new
instance started.
2018-01-23 16:20:03 +01:00