Commit Graph

594 Commits

Author SHA1 Message Date
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 07983d914f Accept prebuilt server
Expose a 'prebuilt_server' option to pass the path of the prebuilt
binary, so that the build does not require Android SDK.

Usage:

    meson builddir -Dprebuilt_server=/tmp/my_prebuilt_server.jar
2018-02-14 16:28:21 +01:00
Romain Vimont 4c49b27e9f Always invoke gradle except as root
The custom target used to invoke Gradle from Meson should always
be built, otherwise, the server would not be rebuilt on source changes.

However, when enabling "build_always", gradle is invoked as root on
"sudo ninja install" after "ninja", so it downloads the whole Gradle
world into /root/.gradle.

To avoid the problem, just do not call gradle if the effective user id
is 0.
2018-02-14 14:03:56 +01:00
Romain Vimont ff94462d8a Refactor build system
The client was built with Meson, the server with Gradle, and were run by
a Makefile.

Add a Meson script for the server (which delegates to Gradle), and a
parent script to build and install both the client and the server to the
system, typically with:

    meson --buildtype release build
    cd build
    ninja
    sudo ninja install

In addition, use a separate Makefile to build a "portable" version of
the application (where the client expects the server to be in the
current directory). Typically:

    make release-portable
    cd dist/scrcpy
    ./scrcpy

This is especially useful for Windows builds, which are not "installed".
2018-02-14 09:23:14 +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 1eaa27ed9e Remove instrumented test dependencies
The server is not a real Android application, it's just a jar with a
main method. Instrumented tests are meaningless in this context.
2018-02-07 16:47:31 +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 dca53ff931 Add missing source files in server Makefile
All classes were still built, but make was not able to detect changes on
missing files.
2018-01-25 17:15:40 +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
Romain Vimont cabb102a04 Implement keyboard/mouse control
To control the device from the computer:
 - retrieve mouse and keyboard SDL events;
 - convert them to Android events;
 - serialize them;
 - send them on the same socket used by the video stream (but in the
 opposite direction);
 - deserialize the events on the Android side;
 - inject them using the InputManager.
2018-01-18 17:25:13 +01:00
Romain Vimont 6605ab8e23 Log to android logger and stdout/stderr 2018-01-18 16:53:20 +01:00
Romain Vimont 1a71c4ab1d Implement framework wrappers separately
Move the DeviceUtil internal static classes to public classes, in a
separate package (".wrappers").

This paves the way to implement InputManager properly.
2017-12-14 11:41:08 +01:00
Romain Vimont 39fd6ce518 Send device name on the socket
Make the server send the device name along with the width and height, so
that the client may use it as the window title.
2017-12-13 10:02:07 +01:00
Romain Vimont 54d9148a36 Initial commit
Start a new clean history from here.
2017-12-12 15:25:15 +01:00