Compare commits

..

1 Commits

Author SHA1 Message Date
Romain Vimont
3c7a6d363e Disable default stdout/stderr for Xiaomi devices
Xiaomi device ROMs print internal errors using e.printStackTRace(),
flooding the console with irrelevant errors.

To get rid of them, on Xiaomi devices, trash the messages printed to the
console by direct calls to System.out and System.err.

Refs #994 <https://github.com/Genymobile/scrcpy/issues/994>
Refs #4213 <https://github.com/Genymobile/scrcpy/pull/4213>
2023-11-01 00:35:42 +01:00
14 changed files with 102 additions and 71 deletions

1
.gitignore vendored
View File

@@ -7,4 +7,3 @@ build/
.gradle/ .gradle/
/x/ /x/
local.properties local.properties
/scrcpy-server

View File

@@ -6,10 +6,10 @@ cd "$DIR"
mkdir -p "$PREBUILT_DATA_DIR" mkdir -p "$PREBUILT_DATA_DIR"
cd "$PREBUILT_DATA_DIR" cd "$PREBUILT_DATA_DIR"
DEP_DIR=platform-tools-34.0.5 DEP_DIR=platform-tools-34.0.3
FILENAME=platform-tools_r34.0.5-windows.zip FILENAME=platform-tools_r34.0.3-windows.zip
SHA256SUM=3f8320152704377de150418a3c4c9d07d16d80a6c0d0d8f7289c22c499e33571 SHA256SUM=fce992e93eb786fc9f47df93d83a7b912c46742d45c39d712c02e06d05b72e2b
if [[ -d "$DEP_DIR" ]] if [[ -d "$DEP_DIR" ]]
then then

View File

@@ -6,10 +6,10 @@ cd "$DIR"
mkdir -p "$PREBUILT_DATA_DIR" mkdir -p "$PREBUILT_DATA_DIR"
cd "$PREBUILT_DATA_DIR" cd "$PREBUILT_DATA_DIR"
DEP_DIR=SDL2-2.28.4 DEP_DIR=SDL2-2.28.0
FILENAME=SDL2-devel-2.28.4-mingw.tar.gz FILENAME=SDL2-devel-2.28.0-mingw.tar.gz
SHA256SUM=779d091072cf97291f80030f5232d97aa3d48ab0f2c14fe0b9d9a33c593cdc35 SHA256SUM=b91ce59eeacd4a9db403f976fd2337d9360b21ada374124417d716065c380e20
if [[ -d "$DEP_DIR" ]] if [[ -d "$DEP_DIR" ]]
then then

View File

@@ -13,7 +13,7 @@ BEGIN
VALUE "LegalCopyright", "Romain Vimont, Genymobile" VALUE "LegalCopyright", "Romain Vimont, Genymobile"
VALUE "OriginalFilename", "scrcpy.exe" VALUE "OriginalFilename", "scrcpy.exe"
VALUE "ProductName", "scrcpy" VALUE "ProductName", "scrcpy"
VALUE "ProductVersion", "v2.2" VALUE "ProductVersion", "2.1.1"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@@ -17,5 +17,5 @@ endian = 'little'
[properties] [properties]
prebuilt_ffmpeg = 'ffmpeg-6.0-scrcpy-4/win32' prebuilt_ffmpeg = 'ffmpeg-6.0-scrcpy-4/win32'
prebuilt_sdl2 = 'SDL2-2.28.4/i686-w64-mingw32' prebuilt_sdl2 = 'SDL2-2.28.0/i686-w64-mingw32'
prebuilt_libusb = 'libusb-1.0.26/libusb-MinGW-Win32' prebuilt_libusb = 'libusb-1.0.26/libusb-MinGW-Win32'

View File

@@ -17,5 +17,5 @@ endian = 'little'
[properties] [properties]
prebuilt_ffmpeg = 'ffmpeg-6.0-scrcpy-4/win64' prebuilt_ffmpeg = 'ffmpeg-6.0-scrcpy-4/win64'
prebuilt_sdl2 = 'SDL2-2.28.4/x86_64-w64-mingw32' prebuilt_sdl2 = 'SDL2-2.28.0/x86_64-w64-mingw32'
prebuilt_libusb = 'libusb-1.0.26/libusb-MinGW-x64' prebuilt_libusb = 'libusb-1.0.26/libusb-MinGW-x64'

View File

@@ -1,5 +1,5 @@
project('scrcpy', 'c', project('scrcpy', 'c',
version: 'v2.2', version: '2.1.1',
meson_version: '>= 0.48', meson_version: '>= 0.48',
default_options: [ default_options: [
'c_std=c11', 'c_std=c11',

View File

@@ -98,10 +98,10 @@ dist-win32: build-server build-win32
cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win32/bin/avcodec-60.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win32/bin/avcodec-60.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win32/bin/avformat-60.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win32/bin/avformat-60.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win32/bin/swresample-4.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win32/bin/swresample-4.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-34.0.5/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-34.0.3/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-34.0.5/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-34.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-34.0.5/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-34.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/SDL2-2.28.4/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/SDL2-2.28.0/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/libusb-1.0.26/libusb-MinGW-Win32/bin/msys-usb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/libusb-1.0.26/libusb-MinGW-Win32/bin/msys-usb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
dist-win64: build-server build-win64 dist-win64: build-server build-win64
@@ -116,10 +116,10 @@ dist-win64: build-server build-win64
cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win64/bin/avcodec-60.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win64/bin/avcodec-60.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win64/bin/avformat-60.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win64/bin/avformat-60.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win64/bin/swresample-4.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/ffmpeg-6.0-scrcpy-4/win64/bin/swresample-4.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-34.0.5/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-34.0.3/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-34.0.5/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-34.0.3/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-34.0.5/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-34.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/SDL2-2.28.4/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/SDL2-2.28.0/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/libusb-1.0.26/libusb-MinGW-x64/bin/msys-usb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/libusb-1.0.26/libusb-MinGW-x64/bin/msys-usb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
zip-win32: dist-win32 zip-win32: dist-win32

View File

@@ -7,8 +7,8 @@ android {
applicationId "com.genymobile.scrcpy" applicationId "com.genymobile.scrcpy"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 targetSdkVersion 33
versionCode 200 versionCode 20101
versionName "v2.2" versionName "2.1.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {

View File

@@ -12,7 +12,7 @@
set -e set -e
SCRCPY_DEBUG=false SCRCPY_DEBUG=false
SCRCPY_VERSION_NAME=v2.2 SCRCPY_VERSION_NAME=2.1.1
PLATFORM=${ANDROID_PLATFORM:-33} PLATFORM=${ANDROID_PLATFORM:-33}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-33.0.0} BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-33.0.0}

View File

@@ -132,29 +132,20 @@ public final class DesktopConnection implements Closeable {
return controlSocket; return controlSocket;
} }
public void shutdown() throws IOException { public void close() throws IOException {
if (videoSocket != null) { if (videoSocket != null) {
videoSocket.shutdownInput(); videoSocket.shutdownInput();
videoSocket.shutdownOutput(); videoSocket.shutdownOutput();
videoSocket.close();
} }
if (audioSocket != null) { if (audioSocket != null) {
audioSocket.shutdownInput(); audioSocket.shutdownInput();
audioSocket.shutdownOutput(); audioSocket.shutdownOutput();
audioSocket.close();
} }
if (controlSocket != null) { if (controlSocket != null) {
controlSocket.shutdownInput(); controlSocket.shutdownInput();
controlSocket.shutdownOutput(); controlSocket.shutdownOutput();
}
}
public void close() throws IOException {
if (videoSocket != null) {
videoSocket.close();
}
if (audioSocket != null) {
audioSocket.close();
}
if (controlSocket != null) {
controlSocket.close(); controlSocket.close();
} }
} }

View File

@@ -2,37 +2,33 @@ package com.genymobile.scrcpy;
import android.util.Log; import android.util.Log;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
/** /**
* Log both to Android logger (so that logs are visible in "adb logcat") and standard output/error (so that they are visible in the terminal * Log both to Android logger (so that logs are visible in "adb logcat") and standard output/error (so that they are visible in the terminal
* directly). * directly).
*/ */
public final class Ln { public final class Ln {
public interface ConsolePrinter {
void printOut(String message);
void printErr(String message, Throwable throwable);
}
private static final String TAG = "scrcpy"; private static final String TAG = "scrcpy";
private static final String PREFIX = "[server] "; private static final String PREFIX = "[server] ";
private static final PrintStream CONSOLE_OUT = new PrintStream(new FileOutputStream(FileDescriptor.out));
private static final PrintStream CONSOLE_ERR = new PrintStream(new FileOutputStream(FileDescriptor.err));
enum Level { enum Level {
VERBOSE, DEBUG, INFO, WARN, ERROR VERBOSE, DEBUG, INFO, WARN, ERROR
} }
private static ConsolePrinter consolePrinter = new DefaultConsolePrinter();
private static Level threshold = Level.INFO; private static Level threshold = Level.INFO;
private Ln() { private Ln() {
// not instantiable // not instantiable
} }
public static void disableSystemStreams() { public static void setConsolePrinter(ConsolePrinter consolePrinter) {
PrintStream nullStream = new PrintStream(new NullOutputStream()); Ln.consolePrinter = consolePrinter;
System.setOut(nullStream);
System.setErr(nullStream);
} }
/** /**
@@ -53,31 +49,28 @@ public final class Ln {
public static void v(String message) { public static void v(String message) {
if (isEnabled(Level.VERBOSE)) { if (isEnabled(Level.VERBOSE)) {
Log.v(TAG, message); Log.v(TAG, message);
CONSOLE_OUT.print(PREFIX + "VERBOSE: " + message + '\n'); consolePrinter.printOut(PREFIX + "VERBOSE: " + message + '\n');
} }
} }
public static void d(String message) { public static void d(String message) {
if (isEnabled(Level.DEBUG)) { if (isEnabled(Level.DEBUG)) {
Log.d(TAG, message); Log.d(TAG, message);
CONSOLE_OUT.print(PREFIX + "DEBUG: " + message + '\n'); consolePrinter.printOut(PREFIX + "DEBUG: " + message + '\n');
} }
} }
public static void i(String message) { public static void i(String message) {
if (isEnabled(Level.INFO)) { if (isEnabled(Level.INFO)) {
Log.i(TAG, message); Log.i(TAG, message);
CONSOLE_OUT.print(PREFIX + "INFO: " + message + '\n'); consolePrinter.printOut(PREFIX + "INFO: " + message + '\n');
} }
} }
public static void w(String message, Throwable throwable) { public static void w(String message, Throwable throwable) {
if (isEnabled(Level.WARN)) { if (isEnabled(Level.WARN)) {
Log.w(TAG, message, throwable); Log.w(TAG, message, throwable);
CONSOLE_ERR.print(PREFIX + "WARN: " + message + '\n'); consolePrinter.printErr(PREFIX + "WARN: " + message + '\n', throwable);
if (throwable != null) {
throwable.printStackTrace(CONSOLE_ERR);
}
} }
} }
@@ -88,10 +81,7 @@ public final class Ln {
public static void e(String message, Throwable throwable) { public static void e(String message, Throwable throwable) {
if (isEnabled(Level.ERROR)) { if (isEnabled(Level.ERROR)) {
Log.e(TAG, message, throwable); Log.e(TAG, message, throwable);
CONSOLE_ERR.print(PREFIX + "ERROR: " + message + '\n'); consolePrinter.printErr(PREFIX + "ERROR: " + message + '\n', throwable);
if (throwable != null) {
throwable.printStackTrace(CONSOLE_ERR);
}
} }
} }
@@ -99,20 +89,18 @@ public final class Ln {
e(message, null); e(message, null);
} }
static class NullOutputStream extends OutputStream { public static class DefaultConsolePrinter implements ConsolePrinter {
@Override @Override
public void write(byte[] b) { public void printOut(String message) {
// ignore System.out.print(message);
} }
@Override @Override
public void write(byte[] b, int off, int len) { public void printErr(String message, Throwable throwable) {
// ignore System.err.print(message);
} if (throwable != null) {
throwable.printStackTrace();
@Override }
public void write(int b) {
// ignore
} }
} }
} }

View File

@@ -163,8 +163,6 @@ public final class Server {
asyncProcessor.stop(); asyncProcessor.stop();
} }
connection.shutdown();
try { try {
initThread.join(); initThread.join();
for (AsyncProcessor asyncProcessor : asyncProcessors) { for (AsyncProcessor asyncProcessor : asyncProcessors) {
@@ -189,7 +187,7 @@ public final class Server {
try { try {
internalMain(args); internalMain(args);
} catch (Throwable t) { } catch (Throwable t) {
Ln.e(t.getMessage(), t); t.printStackTrace();
status = 1; status = 1;
} finally { } finally {
// By default, the Java process exits when all non-daemon threads are terminated. // By default, the Java process exits when all non-daemon threads are terminated.
@@ -206,7 +204,6 @@ public final class Server {
Options options = Options.parse(args); Options options = Options.parse(args);
Ln.disableSystemStreams();
Ln.initLogLevel(options.getLogLevel()); Ln.initLogLevel(options.getLogLevel());
Ln.i("Device: [" + Build.MANUFACTURER + "] " + Build.BRAND + " " + Build.MODEL + " (Android " + Build.VERSION.RELEASE + ")"); Ln.i("Device: [" + Build.MANUFACTURER + "] " + Build.BRAND + " " + Build.MODEL + " (Android " + Build.VERSION.RELEASE + ")");

View File

@@ -14,6 +14,12 @@ import android.os.Build;
import android.os.Looper; import android.os.Looper;
import android.os.Parcel; import android.os.Parcel;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@@ -55,6 +61,12 @@ public final class Workarounds {
mustFillAppInfo = true; mustFillAppInfo = true;
mustFillBaseContext = true; mustFillBaseContext = true;
mustFillAppContext = true; mustFillAppContext = true;
} else if (Build.MANUFACTURER.equalsIgnoreCase("xiaomi")) {
// Trash the messages printed to the console by direct calls to System.out and System.err.
// Xiaomi device ROMs may print internal errors using e.printStackTrace(), flooding the console with irrelevant errors.
ExclusiveConsolePrinter exclusiveConsolePrinter = new ExclusiveConsolePrinter();
exclusiveConsolePrinter.installNullSystemStreams();
Ln.setConsolePrinter(new ExclusiveConsolePrinter());
} }
if (audio && Build.VERSION.SDK_INT == Build.VERSION_CODES.R) { if (audio && Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
@@ -306,4 +318,48 @@ public final class Workarounds {
throw new RuntimeException("Cannot create AudioRecord"); throw new RuntimeException("Cannot create AudioRecord");
} }
} }
static class ExclusiveConsolePrinter implements Ln.ConsolePrinter {
static class NullOutputStream extends OutputStream {
@Override
public void write(byte[] b) {
// ignore
}
@Override
public void write(byte[] b, int off, int len) {
// ignore
}
@Override
public void write(int b) {
// ignore
}
}
private final PrintStream realOut = new PrintStream(new FileOutputStream(FileDescriptor.out));
private final PrintStream realErr = new PrintStream(new FileOutputStream(FileDescriptor.err));
void installNullSystemStreams() {
PrintStream nullStream = new PrintStream(new NullOutputStream());
System.setOut(nullStream);
System.setErr(nullStream);
}
@Override
public void printOut(String message) {
realOut.print(message);
}
@Override
public void printErr(String message, Throwable throwable) {
realErr.print(message);
if (throwable != null) {
StringWriter errors = new StringWriter();
throwable.printStackTrace(new PrintWriter(errors));
realErr.print(errors);
}
}
}
} }