Compare commits

...

18 Commits

Author SHA1 Message Date
valord577
7dd9bcaf60 Prevent error log interleaving
Between the calls to CONSOLE_ERR.print() and
printStackTrace(CONSOLE_ERR), logs from other threads may be inserted.

Synchronizing access to CONSOLE_ERR ensures that logs from different
threads do not mix.

PR #6487 <https://github.com/Genymobile/scrcpy/pull/6487>

Signed-off-by: valord577 <valord577@gmail.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
2025-11-18 11:17:17 +01:00
Romain Vimont
3530851071 Fix uncaught exception handler
The default handler was mistakenly retrieved after our custom handler
was set, causing it to reference itself. As a result, this led to
infinite recursion.

Bug introduced by eee3f24739.
2025-11-04 20:35:39 +01:00
Romain Vimont
d0047b2110 Do not fail when uniqueId field is missing
On some devices, DisplayInfo does not have a "uniqueId" field. This
field is only used for correct UHID behavior on virtual displays, so its
absence should not prevent scrcpy from working.

Refs #6009 <https://github.com/Genymobile/scrcpy/pull/6009>
Fixes #6461 <https://github.com/Genymobile/scrcpy/issues/6461>
2025-11-01 00:34:20 +01:00
Romain Vimont
3281fda6ef Set URL explicitly in dependency build scripts
Explicitly set the URL of each dependency at the beginning of its
script.

PROJECT_DIR and FILENAME are internal details.
2025-10-30 22:31:16 +01:00
Romain Vimont
925949d54a Refactor dependency build scripts initialization
Rename "common" to "_init" because it not only exposes common functions
but also initializes environment variables.

Call _init in a single line in all dependency build scripts.
2025-10-30 22:27:17 +01:00
Yan
f3d4fde15b Fix handling of non-integer ANDROID_PLATFORM
ANDROID_PLATFORM is not always an integer; it can also be a value like
"36.1". Handle such cases properly.

This fixes the following error:

    server/build_without_gradle.sh: line 89:
    [[: 36.1: syntax error: invalid arithmetic operator (error token is ".1")

PR #6408 <https://github.com/Genymobile/scrcpy/pull/6408>

Signed-off-by: Romain Vimont <rom@rom1v.com>
2025-10-19 21:00:05 +02:00
Romain Vimont
eee3f24739 Upgrade Gradle and use Android SDK 36 2025-10-19 21:00:05 +02:00
Romain Vimont
3e40b24737 Fix UHID_OUTPUT message parsing
The bounds check was incorrect.

Fixes #6415 <https://github.com/Genymobile/scrcpy/issues/6415>
2025-10-09 09:35:14 +02:00
Romain Vimont
9d7a4c88e0 Apply workarounds in the cleanup process
Accessing settings may require workarounds on certain devices.

Fixes #6405 <https://github.com/Genymobile/scrcpy/issues/6405>
2025-10-05 21:36:10 +02:00
Romain Vimont
e5e58b1b30 Upgrade links to 3.3.3 2025-09-27 16:10:10 +02:00
Romain Vimont
10a0974f43 Bump version to 3.3.3 2025-09-23 21:18:45 +02:00
Romain Vimont
be21e43be5 Fix frame leak on pending frame update
The previous pending frame was not unreferenced before referencing the
new one, causing frames to leak whenever a texture update failed
(typically on Windows when the window is minimized with D3D9).

Refs 6298ef095f
Fixes #4297 <https://github.com/Genymobile/scrcpy/issues/4297>
Fixes #6357 <https://github.com/Genymobile/scrcpy/issues/6357>
2025-09-23 21:18:45 +02:00
Romain Vimont
bfb0872493 Avoid resetting pending frame
The function update_texture() calls update_texture_internal() and falls
back to set_pending_frame() if it fails.

When the frame passed is the pending frame, call only the _internal()
version instead.

This will prevent issues with frame reference counts by ensuring the
source and destination frames are never the same.

Refs 6298ef095f
Refs #6357 <https://github.com/Genymobile/scrcpy/issues/6357>
2025-09-23 21:18:08 +02:00
Romain Vimont
e11399aff0 Ignore unknown methods in IDisplayWindowListener
New Android versions may add methods to IDisplayWindowListener.aidl.
When these methods are called by the system, they result in an
AbstractMethodError because they are not implemented on the scrcpy side.

To avoid releasing a new version for each newly added method, ignore
them at the Binder level.

Refs afaca80b37
Fixes #6362 <https://github.com/Genymobile/scrcpy/issues/6362>
2025-09-18 10:29:42 +02:00
David Griswold
9d56d26d45 Make virtual display presentable
With this flag, apps with baked in two-screen support can see the
virtual display as an external display they can present to.

PR #6344 <https://github.com/Genymobile/scrcpy/pull/6344>

Signed-off-by: Romain Vimont <rom@rom1v.com>
2025-09-11 21:02:13 +02:00
Romain Vimont
f663bbec12 Update links to 3.3.2 2025-09-06 14:54:36 +02:00
Romain Vimont
2506d1768b Bump version to 3.3.2 2025-09-06 14:36:37 +02:00
Romain Vimont
4ee94cb845 Workaround clipboard issue on Samsung devices
Fixes #6224 <https://github.com/Genymobile/scrcpy/issues/6224>

Co-authored-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
2025-09-06 14:36:33 +02:00
30 changed files with 145 additions and 152 deletions

View File

@@ -2,7 +2,7 @@
source for the project. Do not download releases from random websites, even if
their name contains `scrcpy`.**
# scrcpy (v3.3.1)
# scrcpy (v3.3.3)
<img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" />

View File

@@ -1,10 +1,9 @@
#!/usr/bin/env bash
# This file is intended to be sourced by other scripts, not executed
process_args() {
if [[ $# != 3 ]]
then
# <host>: win32 or win64
# <host>: linux, macos, win32 or win64
# <build_type>: native or cross
# <link_type>: static or shared
echo "Syntax: $0 <host> <build_type> <link_type>" >&2
@@ -12,8 +11,8 @@ process_args() {
fi
HOST="$1"
BUILD_TYPE="$2" # native or cross
LINK_TYPE="$3" # static or shared
BUILD_TYPE="$2"
LINK_TYPE="$3"
DIRNAME="$HOST-$BUILD_TYPE-$LINK_TYPE"
if [[ "$BUILD_TYPE" != native && "$BUILD_TYPE" != cross ]]

View File

@@ -1,21 +1,21 @@
#!/usr/bin/env bash
set -ex
DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DEPS_DIR"
. common
. $(dirname ${BASH_SOURCE[0]})/_init "$@"
VERSION=36.0.0
FILENAME=platform-tools_r$VERSION-linux.zip
PROJECT_DIR=platform-tools-$VERSION-linux
URL="https://dl.google.com/android/repository/platform-tools_r$VERSION-linux.zip"
SHA256SUM=0ead642c943ffe79701fccca8f5f1c69c4ce4f43df2eefee553f6ccb27cbfbe8
PROJECT_DIR="platform-tools-$VERSION-linux"
FILENAME="$PROJECT_DIR.zip"
cd "$SOURCES_DIR"
if [[ -d "$PROJECT_DIR" ]]
then
echo "$PWD/$PROJECT_DIR" found
else
get_file "https://dl.google.com/android/repository/$FILENAME" "$FILENAME" "$SHA256SUM"
get_file "$URL" "$FILENAME" "$SHA256SUM"
mkdir -p "$PROJECT_DIR"
cd "$PROJECT_DIR"
ZIP_PREFIX=platform-tools

View File

@@ -1,21 +1,21 @@
#!/usr/bin/env bash
set -ex
DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DEPS_DIR"
. common
. $(dirname ${BASH_SOURCE[0]})/_init "$@"
VERSION=36.0.0
FILENAME=platform-tools_r$VERSION-darwin.zip
PROJECT_DIR=platform-tools-$VERSION-darwin
URL="https://dl.google.com/android/repository/platform-tools_r$VERSION-darwin.zip"
SHA256SUM=d3e9fa1df3345cf728586908426615a60863d2632f73f1ce14f0f1349ef000fd
PROJECT_DIR="platform-tools-$VERSION-darwin"
FILENAME="$PROJECT_DIR.zip"
cd "$SOURCES_DIR"
if [[ -d "$PROJECT_DIR" ]]
then
echo "$PWD/$PROJECT_DIR" found
else
get_file "https://dl.google.com/android/repository/$FILENAME" "$FILENAME" "$SHA256SUM"
get_file "$URL" "$FILENAME" "$SHA256SUM"
mkdir -p "$PROJECT_DIR"
cd "$PROJECT_DIR"
ZIP_PREFIX=platform-tools

View File

@@ -1,21 +1,21 @@
#!/usr/bin/env bash
set -ex
DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DEPS_DIR"
. common
. $(dirname ${BASH_SOURCE[0]})/_init "$@"
VERSION=36.0.0
FILENAME=platform-tools_r$VERSION-win.zip
PROJECT_DIR=platform-tools-$VERSION-windows
URL="https://dl.google.com/android/repository/platform-tools_r$VERSION-win.zip"
SHA256SUM=12c2841f354e92a0eb2fd7bf6f0f9bf8538abce7bd6b060ac8349d6f6a61107c
PROJECT_DIR="platform-tools-$VERSION-windows"
FILENAME="$PROJECT_DIR.zip"
cd "$SOURCES_DIR"
if [[ -d "$PROJECT_DIR" ]]
then
echo "$PWD/$PROJECT_DIR" found
else
get_file "https://dl.google.com/android/repository/$FILENAME" "$FILENAME" "$SHA256SUM"
get_file "$URL" "$FILENAME" "$SHA256SUM"
mkdir -p "$PROJECT_DIR"
cd "$PROJECT_DIR"
ZIP_PREFIX=platform-tools

View File

@@ -1,22 +1,22 @@
#!/usr/bin/env bash
set -ex
DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DEPS_DIR"
. common
. $(dirname ${BASH_SOURCE[0]})/_init
process_args "$@"
VERSION=1.5.0
FILENAME=dav1d-$VERSION.tar.gz
PROJECT_DIR=dav1d-$VERSION
URL="https://code.videolan.org/videolan/dav1d/-/archive/$VERSION/dav1d-$VERSION.tar.gz"
SHA256SUM=78b15d9954b513ea92d27f39362535ded2243e1b0924fde39f37a31ebed5f76b
PROJECT_DIR="dav1d-$VERSION"
FILENAME="$PROJECT_DIR.tar.gz"
cd "$SOURCES_DIR"
if [[ -d "$PROJECT_DIR" ]]
then
echo "$PWD/$PROJECT_DIR" found
else
get_file "https://code.videolan.org/videolan/dav1d/-/archive/$VERSION/$FILENAME" "$FILENAME" "$SHA256SUM"
get_file "$URL" "$FILENAME" "$SHA256SUM"
tar xf "$FILENAME" # First level directory is "$PROJECT_DIR"
fi

View File

@@ -1,22 +1,22 @@
#!/usr/bin/env bash
set -ex
DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DEPS_DIR"
. common
. $(dirname ${BASH_SOURCE[0]})/_init
process_args "$@"
VERSION=7.1.1
FILENAME=ffmpeg-$VERSION.tar.xz
PROJECT_DIR=ffmpeg-$VERSION
URL="https://ffmpeg.org/releases/ffmpeg-$VERSION.tar.xz"
SHA256SUM=733984395e0dbbe5c046abda2dc49a5544e7e0e1e2366bba849222ae9e3a03b1
PROJECT_DIR="ffmpeg-$VERSION"
FILENAME="$PROJECT_DIR.tar.xz"
cd "$SOURCES_DIR"
if [[ -d "$PROJECT_DIR" ]]
then
echo "$PWD/$PROJECT_DIR" found
else
get_file "https://ffmpeg.org/releases/$FILENAME" "$FILENAME" "$SHA256SUM"
get_file "$URL" "$FILENAME" "$SHA256SUM"
tar xf "$FILENAME" # First level directory is "$PROJECT_DIR"
fi

View File

@@ -1,22 +1,22 @@
#!/usr/bin/env bash
set -ex
DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DEPS_DIR"
. common
. $(dirname ${BASH_SOURCE[0]})/_init
process_args "$@"
VERSION=1.0.29
FILENAME=libusb-$VERSION.tar.gz
PROJECT_DIR=libusb-$VERSION
URL="https://github.com/libusb/libusb/archive/refs/tags/v$VERSION.tar.gz"
SHA256SUM=7c2dd39c0b2589236e48c93247c986ae272e27570942b4163cb00a060fcf1b74
PROJECT_DIR="libusb-$VERSION"
FILENAME="$PROJECT_DIR.tar.gz"
cd "$SOURCES_DIR"
if [[ -d "$PROJECT_DIR" ]]
then
echo "$PWD/$PROJECT_DIR" found
else
get_file "https://github.com/libusb/libusb/archive/refs/tags/v$VERSION.tar.gz" "$FILENAME" "$SHA256SUM"
get_file "$URL" "$FILENAME" "$SHA256SUM"
tar xf "$FILENAME" # First level directory is "$PROJECT_DIR"
fi

View File

@@ -1,23 +1,24 @@
#!/usr/bin/env bash
set -ex
DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DEPS_DIR"
. common
. $(dirname ${BASH_SOURCE[0]})/_init
process_args "$@"
VERSION=2.32.8
FILENAME=SDL-$VERSION.tar.gz
PROJECT_DIR=SDL-release-$VERSION
URL="https://github.com/libsdl-org/SDL/archive/refs/tags/release-$VERSION.tar.gz"
SHA256SUM=dd35e05644ae527848d02433bec24dd0ea65db59faecf1a0e5d1880c533dac2c
PROJECT_DIR="sdl-$VERSION"
FILENAME="$PROJECT_DIR.tar.gz"
cd "$SOURCES_DIR"
if [[ -d "$PROJECT_DIR" ]]
then
echo "$PWD/$PROJECT_DIR" found
else
get_file "https://github.com/libsdl-org/SDL/archive/refs/tags/release-$VERSION.tar.gz" "$FILENAME" "$SHA256SUM"
tar xf "$FILENAME" # First level directory is "$PROJECT_DIR"
get_file "$URL" "$FILENAME" "$SHA256SUM"
tar xf "$FILENAME" # First level directory is "SDL-release-$VERSION"
mv "SDL-release-$VERSION" "$PROJECT_DIR"
fi
mkdir -p "$BUILD_DIR/$PROJECT_DIR"

View File

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

View File

@@ -53,7 +53,7 @@ sc_device_msg_deserialize(const uint8_t *buf, size_t len,
}
uint16_t id = sc_read16be(&buf[1]);
size_t size = sc_read16be(&buf[3]);
if (size < len - 5) {
if (size > len - 5) {
return 0; // not available
}
uint8_t *data = malloc(size);

View File

@@ -170,6 +170,7 @@ sc_display_set_pending_frame(struct sc_display *display, const AVFrame *frame) {
}
}
av_frame_unref(display->pending.frame);
int r = av_frame_ref(display->pending.frame, frame);
if (r) {
LOGE("Could not ref frame: %d", r);
@@ -181,6 +182,11 @@ sc_display_set_pending_frame(struct sc_display *display, const AVFrame *frame) {
return true;
}
// Forward declaration
static bool
sc_display_update_texture_internal(struct sc_display *display,
const AVFrame *frame);
static bool
sc_display_apply_pending(struct sc_display *display) {
if (display->pending.flags & SC_DISPLAY_PENDING_FLAG_SIZE) {
@@ -196,7 +202,8 @@ sc_display_apply_pending(struct sc_display *display) {
if (display->pending.flags & SC_DISPLAY_PENDING_FLAG_FRAME) {
assert(display->pending.frame);
bool ok = sc_display_update_texture(display, display->pending.frame);
bool ok = sc_display_update_texture_internal(display,
display->pending.frame);
if (!ok) {
return false;
}

View File

@@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.7.1'
classpath 'com.android.tools.build:gradle:8.13.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@@ -233,10 +233,10 @@ install` must be run as root)._
#### Option 2: Use prebuilt server
- [`scrcpy-server-v3.3.1`][direct-scrcpy-server]
<sub>SHA-256: `a0f70b20aa4998fbf658c94118cd6c8dab6abbb0647a3bdab344d70bc1ebcbb8`</sub>
- [`scrcpy-server-v3.3.3`][direct-scrcpy-server]
<sub>SHA-256: `7e70323ba7f259649dd4acce97ac4fefbae8102b2c6d91e2e7be613fd5354be0`</sub>
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-server-v3.3.1
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.3/scrcpy-server-v3.3.3
Download the prebuilt server somewhere, and specify its path during the Meson
configuration:

View File

@@ -6,11 +6,11 @@
Download a static build of the [latest release]:
- [`scrcpy-linux-x86_64-v3.3.1.tar.gz`][direct-linux-x86_64] (x86_64)
<sub>SHA-256: `bbfe54c6b178adafeaffbbfbbc1548a74486553170c63e63bdd41863ad123422`</sub>
- [`scrcpy-linux-x86_64-v3.3.3.tar.gz`][direct-linux-x86_64] (x86_64)
<sub>SHA-256: `9b30e813e8191329ba8025dc80cb0f198fb0a318960a3b5c15395cf675c9c638`</sub>
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
[direct-linux-x86_64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-linux-x86_64-v3.3.1.tar.gz
[direct-linux-x86_64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.3/scrcpy-linux-x86_64-v3.3.3.tar.gz
and extract it.

View File

@@ -6,15 +6,15 @@
Download a static build of the [latest release]:
- [`scrcpy-macos-aarch64-v3.3.1.tar.gz`][direct-macos-aarch64] (aarch64)
<sub>SHA-256: `907b925900ebd8499c1e47acc9689a95bd3a6f9930eb1d7bdfbca8375ae4f139`</sub>
- [`scrcpy-macos-aarch64-v3.3.3.tar.gz`][direct-macos-aarch64] (aarch64)
<sub>SHA-256: `b93299468f19ae89ac70f7c1453914c41f1f2bcd31f6ab530038da885c19581f`</sub>
- [`scrcpy-macos-x86_64-v3.3.1.tar.gz`][direct-macos-x86_64] (x86_64)
<sub>SHA-256: `69772491dad718eea82fc65c8e89febff7d41c4ce6faff02f4789a588d10fd7d`</sub>
- [`scrcpy-macos-x86_64-v3.3.3.tar.gz`][direct-macos-x86_64] (x86_64)
<sub>SHA-256: `c767fc1d41e4ae26e40558656570962f474739924fd22ee023d8754889ee4366`</sub>
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
[direct-macos-aarch64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-macos-aarch64-v3.3.1.tar.gz
[direct-macos-x86_64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-macos-x86_64-v3.3.1.tar.gz
[direct-macos-aarch64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.3/scrcpy-macos-aarch64-v3.3.3.tar.gz
[direct-macos-x86_64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.3/scrcpy-macos-x86_64-v3.3.3.tar.gz
and extract it.

View File

@@ -6,14 +6,14 @@
Download the [latest release]:
- [`scrcpy-win64-v3.3.1.zip`][direct-win64] (64-bit)
<sub>SHA-256: `4fcad494772a3ae5de9a133149f8856d2fc429b41795f7cf7c754e0c1bb6fbc0`</sub>
- [`scrcpy-win32-v3.3.1.zip`][direct-win32] (32-bit)
<sub>SHA-256: `ccdf1b4f5d19dfe760446a107e55b0a010a00e097d46533a161499c9333a20a6`</sub>
- [`scrcpy-win64-v3.3.3.zip`][direct-win64] (64-bit)
<sub>SHA-256: `4b458d33d0436688c69875cd267cae6fa8be08aa3c17772edf3a940a3dc4b17e`</sub>
- [`scrcpy-win32-v3.3.3.zip`][direct-win32] (32-bit)
<sub>SHA-256: `e3d43e21c0bd6e070381c390c1e4cccd48a1e71ae73a8c217e6e6b8506598c79`</sub>
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-win64-v3.3.1.zip
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-win32-v3.3.1.zip
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.3/scrcpy-win64-v3.3.3.zip
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.3/scrcpy-win32-v3.3.3.zip
and extract it.

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
# https://gradle.org/release-checksums/
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -2,8 +2,8 @@
set -e
BUILDDIR=build-auto
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-server-v3.3.1
PREBUILT_SERVER_SHA256=a0f70b20aa4998fbf658c94118cd6c8dab6abbb0647a3bdab344d70bc1ebcbb8
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v3.3.3/scrcpy-server-v3.3.3
PREBUILT_SERVER_SHA256=7e70323ba7f259649dd4acce97ac4fefbae8102b2c6d91e2e7be613fd5354be0
echo "[scrcpy] Downloading prebuilt server..."
wget "$PREBUILT_SERVER_URL" -O scrcpy-server

View File

@@ -1,5 +1,5 @@
project('scrcpy', 'c',
version: '3.3.1',
version: '3.3.3',
meson_version: '>= 0.49',
default_options: [
'c_std=c11',

View File

@@ -1,15 +1,15 @@
apply plugin: 'com.android.application'
android {
namespace 'com.genymobile.scrcpy'
compileSdk 35
namespace = 'com.genymobile.scrcpy'
compileSdk 36
defaultConfig {
applicationId "com.genymobile.scrcpy"
applicationId = "com.genymobile.scrcpy"
minSdkVersion 21
targetSdkVersion 35
versionCode 30301
versionName "3.3.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
targetSdkVersion 36
versionCode 30303
versionName "3.3.3"
testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
@@ -18,8 +18,11 @@ android {
}
}
buildFeatures {
buildConfig true
aidl true
buildConfig = true
aidl = true
}
lint {
disable 'UseRequiresApi'
}
}

View File

@@ -12,10 +12,10 @@
set -e
SCRCPY_DEBUG=false
SCRCPY_VERSION_NAME=3.3.1
SCRCPY_VERSION_NAME=3.3.3
PLATFORM=${ANDROID_PLATFORM:-35}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-35.0.0}
PLATFORM=${ANDROID_PLATFORM:-36}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-36.0.0}
PLATFORM_TOOLS="$ANDROID_HOME/platforms/android-$PLATFORM"
BUILD_TOOLS_DIR="$ANDROID_HOME/build-tools/$BUILD_TOOLS"
@@ -86,7 +86,7 @@ javac -encoding UTF-8 -bootclasspath "$ANDROID_JAR" \
echo "Dexing..."
cd "$CLASSES_DIR"
if [[ $PLATFORM -lt 31 ]]
if [[ "${PLATFORM%%.*}" -lt 31 ]]
then
# use dx
"$BUILD_TOOLS_DIR/dx" --dex --output "$BUILD_DIR/classes.dex" \

View File

@@ -48,27 +48,4 @@ oneway interface IDisplayWindowListener {
* Called when a display is removed from the hierarchy.
*/
void onDisplayRemoved(int displayId);
/**
* Called when fixed rotation is started on a display.
*/
void onFixedRotationStarted(int displayId, int newRotation);
/**
* Called when the previous fixed rotation on a display is finished.
*/
void onFixedRotationFinished(int displayId);
/**
* Called when the keep clear ares on a display have changed.
*/
void onKeepClearAreasChanged(int displayId, in List<Rect> restricted, in List<Rect> unrestricted);
/**
* Called when the eligibility of the desktop mode for a display have changed.
*/
void onDesktopModeEligibleChanged(int displayId);
void onDisplayAddSystemDecorations(int displayId);
void onDisplayRemoveSystemDecorations(int displayId);
}

View File

@@ -196,6 +196,7 @@ public final class CleanUp {
// Needed for workarounds
prepareMainLooper();
Workarounds.apply();
int displayId = Integer.parseInt(args[0]);
int restoreStayOn = Integer.parseInt(args[1]);

View File

@@ -5,7 +5,6 @@ import com.genymobile.scrcpy.wrappers.ServiceManager;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.AttributionSource;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -91,6 +90,11 @@ public final class FakeContext extends ContextWrapper {
return this;
}
@Override
public Context createPackageContext(String packageName, int flags) {
return this;
}
@Override
public ContentResolver getContentResolver() {
return contentResolver;
@@ -104,9 +108,11 @@ public final class FakeContext extends ContextWrapper {
return null;
}
if (Context.CLIPBOARD_SERVICE.equals(name)) {
// "semclipboard" is a Samsung-internal service
// See <https://github.com/Genymobile/scrcpy/issues/6224>
if (Context.CLIPBOARD_SERVICE.equals(name) || "semclipboard".equals(name)) {
try {
Field field = ClipboardManager.class.getDeclaredField("mContext");
Field field = service.getClass().getDeclaredField("mContext");
field.setAccessible(true);
field.set(service, this);
} catch (ReflectiveOperationException e) {

View File

@@ -225,8 +225,12 @@ public final class Server {
}
private static void internalMain(String... args) throws Exception {
Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
Ln.e("Exception on thread " + t, e);
if (defaultHandler != null) {
defaultHandler.uncaughtException(t, e);
}
});
prepareMainLooper();

View File

@@ -74,9 +74,11 @@ public final class Ln {
public static void w(String message, Throwable throwable) {
if (isEnabled(Level.WARN)) {
Log.w(TAG, message, throwable);
CONSOLE_ERR.print(PREFIX + "WARN: " + message + '\n');
if (throwable != null) {
throwable.printStackTrace(CONSOLE_ERR);
synchronized (CONSOLE_ERR) {
CONSOLE_ERR.print(PREFIX + "WARN: " + message + '\n');
if (throwable != null) {
throwable.printStackTrace(CONSOLE_ERR);
}
}
}
}
@@ -88,9 +90,11 @@ public final class Ln {
public static void e(String message, Throwable throwable) {
if (isEnabled(Level.ERROR)) {
Log.e(TAG, message, throwable);
CONSOLE_ERR.print(PREFIX + "ERROR: " + message + '\n');
if (throwable != null) {
throwable.printStackTrace(CONSOLE_ERR);
synchronized (CONSOLE_ERR) {
CONSOLE_ERR.print(PREFIX + "ERROR: " + message + '\n');
if (throwable != null) {
throwable.printStackTrace(CONSOLE_ERR);
}
}
}
}

View File

@@ -25,6 +25,7 @@ public class NewDisplayCapture extends SurfaceCapture {
// Internal fields copied from android.hardware.display.DisplayManager
private static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
private static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
private static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
private static final int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 1 << 6;
private static final int VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT = 1 << 7;
@@ -169,6 +170,7 @@ public class NewDisplayCapture extends SurfaceCapture {
int virtualDisplayId;
try {
int flags = VIRTUAL_DISPLAY_FLAG_PUBLIC
| VIRTUAL_DISPLAY_FLAG_PRESENTATION
| VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
| VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
| VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;

View File

@@ -139,7 +139,13 @@ public final class DisplayManager {
int layerStack = cls.getDeclaredField("layerStack").getInt(displayInfo);
int flags = cls.getDeclaredField("flags").getInt(displayInfo);
int dpi = cls.getDeclaredField("logicalDensityDpi").getInt(displayInfo);
String uniqueId = (String) cls.getDeclaredField("uniqueId").get(displayInfo);
String uniqueId;
try {
uniqueId = (String) cls.getDeclaredField("uniqueId").get(displayInfo);
} catch (NoSuchFieldException e) {
// This field might not exist: <https://github.com/Genymobile/scrcpy/issues/6461>
uniqueId = null;
}
return new DisplayInfo(displayId, new Size(width, height), rotation, layerStack, flags, dpi, uniqueId);
} catch (ReflectiveOperationException e) {
throw new AssertionError(e);

View File

@@ -1,10 +1,11 @@
package com.genymobile.scrcpy.wrappers;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.view.IDisplayWindowListener;
import com.genymobile.scrcpy.util.Ln;
import java.util.List;
import android.content.res.Configuration;
import android.os.Parcel;
import android.os.RemoteException;
import android.view.IDisplayWindowListener;
public class DisplayWindowListener extends IDisplayWindowListener.Stub {
@Override
@@ -23,32 +24,14 @@ public class DisplayWindowListener extends IDisplayWindowListener.Stub {
}
@Override
public void onFixedRotationStarted(int displayId, int newRotation) {
// empty default implementation
}
@Override
public void onFixedRotationFinished(int displayId) {
// empty default implementation
}
@Override
public void onKeepClearAreasChanged(int displayId, List<Rect> restricted, List<Rect> unrestricted) {
// empty default implementation
}
@Override
public void onDesktopModeEligibleChanged(int displayId) {
// empty default implementation
}
@Override
public void onDisplayAddSystemDecorations(int displayId) {
// empty default implementation
}
@Override
public void onDisplayRemoveSystemDecorations(int displayId) {
// empty default implementation
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
try {
return super.onTransact(code, data, reply, flags);
} catch (AbstractMethodError e) {
Ln.v("Ignoring AbstractMethodError: " + e.getMessage());
// Ignore unknown methods, write default response to reply parcel
reply.writeNoException();
return true;
}
}
}