From b43938fa66bb854e45c97a76b4600edecdb0fb9b Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 19 Feb 2023 19:36:46 +0100 Subject: [PATCH] Do not print stacktraces when unnecessary User-friendly error messages are printed on specific configuration exceptions. In that case, do not print the stacktrace. Also handle the user-friendly error message directly where the error occurs, and print multiline messages in a single log call, to avoid confusing interleaving. --- .../scrcpy/ConfigurationException.java | 7 ++++ .../java/com/genymobile/scrcpy/Device.java | 18 +++++++++-- .../scrcpy/InvalidDisplayIdException.java | 21 ------------ .../scrcpy/InvalidEncoderException.java | 23 ------------- .../com/genymobile/scrcpy/ScreenEncoder.java | 20 +++++++++--- .../java/com/genymobile/scrcpy/Server.java | 32 ++++--------------- 6 files changed, 44 insertions(+), 77 deletions(-) create mode 100644 server/src/main/java/com/genymobile/scrcpy/ConfigurationException.java delete mode 100644 server/src/main/java/com/genymobile/scrcpy/InvalidDisplayIdException.java delete mode 100644 server/src/main/java/com/genymobile/scrcpy/InvalidEncoderException.java diff --git a/server/src/main/java/com/genymobile/scrcpy/ConfigurationException.java b/server/src/main/java/com/genymobile/scrcpy/ConfigurationException.java new file mode 100644 index 00000000..76c8f52e --- /dev/null +++ b/server/src/main/java/com/genymobile/scrcpy/ConfigurationException.java @@ -0,0 +1,7 @@ +package com.genymobile.scrcpy; + +public class ConfigurationException extends Exception { + public ConfigurationException(String message) { + super(message); + } +} diff --git a/server/src/main/java/com/genymobile/scrcpy/Device.java b/server/src/main/java/com/genymobile/scrcpy/Device.java index 30e64fd7..c7f7c1f8 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Device.java +++ b/server/src/main/java/com/genymobile/scrcpy/Device.java @@ -61,12 +61,12 @@ public final class Device { private final boolean supportsInputEvents; - public Device(Options options) { + public Device(Options options) throws ConfigurationException { displayId = options.getDisplayId(); DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId); if (displayInfo == null) { - int[] displayIds = ServiceManager.getDisplayManager().getDisplayIds(); - throw new InvalidDisplayIdException(displayId, displayIds); + Ln.e(buildUnknownDisplayIdMessage(displayId)); + throw new ConfigurationException("Unknown display id: " + displayId); } int displayInfoFlags = displayInfo.getFlags(); @@ -130,6 +130,18 @@ public final class Device { } } + private static String buildUnknownDisplayIdMessage(int displayId) { + StringBuilder msg = new StringBuilder("Display ").append(displayId).append(" not found"); + int[] displayIds = ServiceManager.getDisplayManager().getDisplayIds(); + if (displayIds != null && displayIds.length > 0) { + msg.append("\nTry to use one of the available display ids:"); + for (int id : displayIds) { + msg.append("\n scrcpy --display=").append(id); + } + } + return msg.toString(); + } + public synchronized void setMaxSize(int newMaxSize) { maxSize = newMaxSize; screenInfo = ScreenInfo.computeScreenInfo(screenInfo.getReverseVideoRotation(), deviceSize, crop, newMaxSize, lockVideoOrientation); diff --git a/server/src/main/java/com/genymobile/scrcpy/InvalidDisplayIdException.java b/server/src/main/java/com/genymobile/scrcpy/InvalidDisplayIdException.java deleted file mode 100644 index 81e3b903..00000000 --- a/server/src/main/java/com/genymobile/scrcpy/InvalidDisplayIdException.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.genymobile.scrcpy; - -public class InvalidDisplayIdException extends RuntimeException { - - private final int displayId; - private final int[] availableDisplayIds; - - public InvalidDisplayIdException(int displayId, int[] availableDisplayIds) { - super("There is no display having id " + displayId); - this.displayId = displayId; - this.availableDisplayIds = availableDisplayIds; - } - - public int getDisplayId() { - return displayId; - } - - public int[] getAvailableDisplayIds() { - return availableDisplayIds; - } -} diff --git a/server/src/main/java/com/genymobile/scrcpy/InvalidEncoderException.java b/server/src/main/java/com/genymobile/scrcpy/InvalidEncoderException.java deleted file mode 100644 index b38e29b1..00000000 --- a/server/src/main/java/com/genymobile/scrcpy/InvalidEncoderException.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.genymobile.scrcpy; - -import android.media.MediaCodecInfo; - -public class InvalidEncoderException extends RuntimeException { - - private final String name; - private final MediaCodecInfo[] availableEncoders; - - public InvalidEncoderException(String name, MediaCodecInfo[] availableEncoders) { - super("There is no encoder having name '" + name + "'"); - this.name = name; - this.availableEncoders = availableEncoders; - } - - public String getName() { - return name; - } - - public MediaCodecInfo[] getAvailableEncoders() { - return availableEncoders; - } -} diff --git a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java index fed6f6c3..44ba75d1 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java +++ b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java @@ -63,7 +63,7 @@ public class ScreenEncoder implements Device.RotationListener { return rotationChanged.getAndSet(false); } - public void streamScreen(Device device, Callbacks callbacks) throws IOException { + public void streamScreen(Device device, Callbacks callbacks) throws IOException, ConfigurationException { MediaCodec codec = createCodec(videoMimeType, encoderName); MediaFormat format = createFormat(videoMimeType, bitRate, maxFps, codecOptions); IBinder display = createDisplay(); @@ -207,14 +207,14 @@ public class ScreenEncoder implements Device.RotationListener { return result.toArray(new MediaCodecInfo[result.size()]); } - private static MediaCodec createCodec(String videoMimeType, String encoderName) throws IOException { + private static MediaCodec createCodec(String videoMimeType, String encoderName) throws IOException, ConfigurationException { if (encoderName != null) { Ln.d("Creating encoder by name: '" + encoderName + "'"); try { return MediaCodec.createByCodecName(encoderName); } catch (IllegalArgumentException e) { - MediaCodecInfo[] encoders = listEncoders(videoMimeType); - throw new InvalidEncoderException(encoderName, encoders); + Ln.e(buildUnknownEncoderMessage(videoMimeType, encoderName)); + throw new ConfigurationException("Unknown encoder: " + encoderName); } } MediaCodec codec = MediaCodec.createEncoderByType(videoMimeType); @@ -222,6 +222,18 @@ public class ScreenEncoder implements Device.RotationListener { return codec; } + private static String buildUnknownEncoderMessage(String videoMimeType, String encoderName) { + StringBuilder msg = new StringBuilder("Encoder '").append(encoderName).append("' not found"); + MediaCodecInfo[] encoders = listEncoders(videoMimeType); + if (encoders != null && encoders.length > 0) { + msg.append("\nTry to use one of the available encoders:"); + for (MediaCodecInfo encoder : encoders) { + msg.append("\n scrcpy --encoder='").append(encoder.getName()).append("'"); + } + } + return msg.toString(); + } + private static void setCodecOption(MediaFormat format, CodecOption codecOption) { String key = codecOption.getKey(); Object value = codecOption.getValue(); diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index 5a092061..027050af 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -1,7 +1,6 @@ package com.genymobile.scrcpy; import android.graphics.Rect; -import android.media.MediaCodecInfo; import android.os.BatteryManager; import android.os.Build; @@ -59,7 +58,7 @@ public final class Server { } } - private static void scrcpy(Options options) throws IOException { + private static void scrcpy(Options options) throws IOException, ConfigurationException { Ln.i("Device: " + Build.MANUFACTURER + " " + Build.MODEL + " (Android " + Build.VERSION.RELEASE + ")"); final Device device = new Device(options); List codecOptions = options.getCodecOptions(); @@ -299,38 +298,19 @@ public final class Server { return new Rect(x, y, x + width, y + height); } - private static void suggestFix(Throwable e) { - if (e instanceof InvalidDisplayIdException) { - InvalidDisplayIdException idie = (InvalidDisplayIdException) e; - int[] displayIds = idie.getAvailableDisplayIds(); - if (displayIds != null && displayIds.length > 0) { - Ln.e("Try to use one of the available display ids:"); - for (int id : displayIds) { - Ln.e(" scrcpy --display=" + id); - } - } - } else if (e instanceof InvalidEncoderException) { - InvalidEncoderException iee = (InvalidEncoderException) e; - MediaCodecInfo[] encoders = iee.getAvailableEncoders(); - if (encoders != null && encoders.length > 0) { - Ln.e("Try to use one of the available encoders:"); - for (MediaCodecInfo encoder : encoders) { - Ln.e(" scrcpy --encoder='" + encoder.getName() + "'"); - } - } - } - } - public static void main(String... args) throws Exception { Thread.setDefaultUncaughtExceptionHandler((t, e) -> { Ln.e("Exception on thread " + t, e); - suggestFix(e); }); Options options = createOptions(args); Ln.initLogLevel(options.getLogLevel()); - scrcpy(options); + try { + scrcpy(options); + } catch (ConfigurationException e) { + // Do not print stack trace, a user-friendly error-message has already been logged + } } }