diff --git a/app/src/screen.c b/app/src/screen.c index d5142dfb..4b7200d1 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -14,6 +14,7 @@ #include "lockutil.h" #include "netutil.h" +#define DEVICE_NAME_FIELD_LENGTH 64 #define SOCKET_NAME "scrcpy" #define DISPLAY_MARGINS 96 #define MIN(X,Y) (X) < (Y) ? (X) : (Y) @@ -58,13 +59,18 @@ static void stop_server(process_t server) { } } -SDL_bool read_initial_device_size(TCPsocket socket, struct size *size) { - unsigned char buf[4]; +// name must be at least DEVICE_NAME_FIELD_LENGTH bytes +SDL_bool read_initial_device_info(TCPsocket socket, char *device_name, struct size *size) { + unsigned char buf[DEVICE_NAME_FIELD_LENGTH + 4]; if (SDLNet_TCP_Recv(socket, buf, sizeof(buf)) <= 0) { return SDL_FALSE; } - size->width = (buf[0] << 8) | buf[1]; - size->height = (buf[2] << 8) | buf[3]; + buf[DEVICE_NAME_FIELD_LENGTH - 1] = '\0'; // in case the client sends garbage + // scrcpy is safe here, since name contains at least DEVICE_NAME_FIELD_LENGTH bytes + // and strlen(buf) < DEVICE_NAME_FIELD_LENGTH + strcpy(device_name, (char *) buf); + size->width = (buf[DEVICE_NAME_FIELD_LENGTH] << 8) | buf[DEVICE_NAME_FIELD_LENGTH + 1]; + size->height = (buf[DEVICE_NAME_FIELD_LENGTH + 2] << 8) | buf[DEVICE_NAME_FIELD_LENGTH + 3]; return SDL_TRUE; } @@ -252,11 +258,12 @@ int show_screen(const char *serial, Uint16 local_port) { } struct size frame_size; + char device_name[DEVICE_NAME_FIELD_LENGTH]; // screenrecord does not send frames when the screen content does not change // therefore, we transmit the screen size before the video stream, to be able // to init the window immediately - if (!read_initial_device_size(device_socket, &frame_size)) { + if (!read_initial_device_info(device_socket, device_name, &frame_size)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not retrieve initial screen size"); ret = -1; SDLNet_TCP_Close(device_socket); @@ -297,7 +304,7 @@ int show_screen(const char *serial, Uint16 local_port) { } struct size window_size = get_initial_optimal_size(frame_size); - SDL_Window *window = SDL_CreateWindow("scrcpy", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + SDL_Window *window = SDL_CreateWindow(device_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_size.width, window_size.height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); if (!window) { SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "Could not create window: %s", SDL_GetError()); diff --git a/server/Makefile b/server/Makefile index efa41dcf..a648405e 100644 --- a/server/Makefile +++ b/server/Makefile @@ -18,10 +18,10 @@ ANDROID_JAR := $(ANDROID_HOME)/platforms/android-26/android.jar AIDL_SRC := android/view/IRotationWatcher.aidl SRC := com/genymobile/scrcpy/ScrCpyServer.java \ com/genymobile/scrcpy/DesktopConnection.java \ + com/genymobile/scrcpy/DeviceUtil.java \ com/genymobile/scrcpy/ScreenInfo.java \ com/genymobile/scrcpy/ScreenStreamer.java \ com/genymobile/scrcpy/ScreenStreamerSession.java \ - com/genymobile/scrcpy/ScreenUtil.java \ JAR := scrcpy-server.jar MAIN := com.genymobile.scrcpy.ScrCpyServer diff --git a/server/src/com/genymobile/scrcpy/DesktopConnection.java b/server/src/com/genymobile/scrcpy/DesktopConnection.java index 07a8dd4a..f0f557a8 100644 --- a/server/src/com/genymobile/scrcpy/DesktopConnection.java +++ b/server/src/com/genymobile/scrcpy/DesktopConnection.java @@ -5,9 +5,12 @@ import android.net.LocalSocketAddress; import java.io.Closeable; import java.io.IOException; +import java.nio.charset.StandardCharsets; public class DesktopConnection implements Closeable { + private static final int DEVICE_NAME_FIELD_LENGTH = 64; + private static final String SOCKET_NAME = "scrcpy"; private final LocalSocket socket; @@ -22,9 +25,9 @@ public class DesktopConnection implements Closeable { return localSocket; } - public static DesktopConnection open(int width, int height) throws IOException { + public static DesktopConnection open(String deviceName, int width, int height) throws IOException { LocalSocket socket = connect(SOCKET_NAME); - send(socket, width, height); + send(socket, deviceName, width, height); return new DesktopConnection(socket); } @@ -34,15 +37,21 @@ public class DesktopConnection implements Closeable { socket.close(); } - private static void send(LocalSocket socket, int width, int height) throws IOException { + private static void send(LocalSocket socket, String deviceName, int width, int height) throws IOException { assert width < 0x10000 : "width may not be stored on 16 bits"; assert height < 0x10000 : "height may not be stored on 16 bits"; - byte[] buffer = new byte[4]; - buffer[0] = (byte) (width >> 8); - buffer[1] = (byte) width; - buffer[2] = (byte) (height >> 8); - buffer[3] = (byte) height; - socket.getOutputStream().write(buffer, 0, 4); + byte[] buffer = new byte[DEVICE_NAME_FIELD_LENGTH + 4]; + + byte[] deviceNameBytes = deviceName.getBytes(StandardCharsets.UTF_8); + int len = Math.min(DEVICE_NAME_FIELD_LENGTH - 1, deviceNameBytes.length); + System.arraycopy(deviceNameBytes, 0, buffer, 0, len); + // byte[] are always 0-initialized in java, no need to set '\0' explicitly + + buffer[DEVICE_NAME_FIELD_LENGTH] = (byte) (width >> 8); + buffer[DEVICE_NAME_FIELD_LENGTH + 1] = (byte) width; + buffer[DEVICE_NAME_FIELD_LENGTH + 2] = (byte) (height >> 8); + buffer[DEVICE_NAME_FIELD_LENGTH + 3] = (byte) height; + socket.getOutputStream().write(buffer, 0, buffer.length); } public void sendVideoStream(byte[] videoStreamBuffer, int len) throws IOException { diff --git a/server/src/com/genymobile/scrcpy/ScreenUtil.java b/server/src/com/genymobile/scrcpy/DeviceUtil.java similarity index 97% rename from server/src/com/genymobile/scrcpy/ScreenUtil.java rename to server/src/com/genymobile/scrcpy/DeviceUtil.java index 29e2d5c2..03e83126 100644 --- a/server/src/com/genymobile/scrcpy/ScreenUtil.java +++ b/server/src/com/genymobile/scrcpy/DeviceUtil.java @@ -1,12 +1,13 @@ package com.genymobile.scrcpy; +import android.os.Build; import android.os.IBinder; import android.os.IInterface; import android.view.IRotationWatcher; import java.lang.reflect.Method; -public class ScreenUtil { +public class DeviceUtil { private static final ServiceManager serviceManager = new ServiceManager(); @@ -18,6 +19,10 @@ public class ScreenUtil { serviceManager.getWindowManager().registerRotationWatcher(rotationWatcher); } + public static String getDeviceName() { + return Build.MODEL; + } + private static class ServiceManager { private Method getServiceMethod; diff --git a/server/src/com/genymobile/scrcpy/ScrCpyServer.java b/server/src/com/genymobile/scrcpy/ScrCpyServer.java index d31fd244..ff217771 100644 --- a/server/src/com/genymobile/scrcpy/ScrCpyServer.java +++ b/server/src/com/genymobile/scrcpy/ScrCpyServer.java @@ -5,10 +5,11 @@ import java.io.IOException; public class ScrCpyServer { public static void scrcpy() throws IOException { - ScreenInfo initialScreenInfo = ScreenUtil.getScreenInfo(); + String deviceName = DeviceUtil.getDeviceName(); + ScreenInfo initialScreenInfo = DeviceUtil.getScreenInfo(); int width = initialScreenInfo.getLogicalWidth(); int height = initialScreenInfo.getLogicalHeight(); - try (DesktopConnection connection = DesktopConnection.open(width, height)) { + try (DesktopConnection connection = DesktopConnection.open(deviceName, width, height)) { try { new ScreenStreamer(connection).streamScreen(); } catch (IOException e) { diff --git a/server/src/com/genymobile/scrcpy/ScreenStreamer.java b/server/src/com/genymobile/scrcpy/ScreenStreamer.java index c85cea7e..4da18b75 100644 --- a/server/src/com/genymobile/scrcpy/ScreenStreamer.java +++ b/server/src/com/genymobile/scrcpy/ScreenStreamer.java @@ -13,7 +13,7 @@ public class ScreenStreamer { public ScreenStreamer(DesktopConnection connection) { this.connection = connection; - ScreenUtil.registerRotationWatcher(new IRotationWatcher.Stub() { + DeviceUtil.registerRotationWatcher(new IRotationWatcher.Stub() { @Override public void onRotationChanged(int rotation) throws RemoteException { reset();