On the server side, several components are started, stopped and joined.
Extract an interface to handle them generically.
This will help to support both encoded and raw audio stream, because
they will be two different concrete components, but implementing the
same interface.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
On Android 11, it is possible to start the capture only when the running
app is in foreground. But scrcpy is not an app, it's a Java application
started from shell.
As a workaround, start an existing Android shell existing activity just
to start the capture, then close it immediately.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
When audio capture fails on the device, scrcpy continues mirroring the
video stream. This allows to enable audio by default only when
supported.
However, if an audio configuration occurs (for example the user
explicitly selected an unknown audio encoder), this must be treated as
an error and scrcpy must exit.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
The permission "android.permission.RECORD_AUDIO" has been added for
shell in Android 11.
Moreover, on lower versions, it may make the server segfault on the
device (happened on a Nexus 5 with Android 6.0.1).
Refs <4feeee8891%5E%21/>
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
By default, audio is enabled (--no-audio must be explicitly passed to
disable it).
However, some devices may not support audio capture (typically devices
below Android 11, or Android 11 when the shell application is not
foreground on start).
In that case, make the server notify the client to dynamically disable
audio forwarding so that it does not wait indefinitely for an audio
stream.
Also disable audio on unknown codec or missing decoder on the
client-side, for the same reasons.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
For OPUS codec, FFmpeg expects the raw extradata, but MediaCodec wraps
it in some structure.
Fix the config packet to send only the raw extradata.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
Create an AudioRecorder to capture the audio source REMOTE_SUBMIX.
For now, the captured packets are just logged into the console.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
When audio is enabled, open a new socket to send the audio stream from
the device to the client.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Audio will be enabled by default (when supported). Add an option to
disable it.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Remove USER_ID from ServiceManager, and replace it by a constant in
FakeContext.
This is the same as android.os.Process.ROOT_UID, but this constant has
been introduced in API 29.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
Since scrcpy-server is not an Android application (it's a java
executable), it has no Context.
Some features will require a Context instance to get the package name
and the UID. Add a FakeContext for this purpose.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
The Callbacks interface notifies new packets. But in addition, the
screen encoder will need to write headers on start.
We could add a function onStart(), but for simplicity, just remove the
interface, which brings no value, and call the streamer directly.
Refs 87972e2022
On any error, all previously opened sockets must be closed.
Handle these errors in a single catch-block. Currently, there are only 2
sockets, but this will simplify even more with more sockets.
Note: this commit is better displayed with --ignore-space-change (-b).
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.
As reported by gradle:
> Setting the namespace via a source AndroidManifest.xml's package
> attribute is deprecated.
>
> Please instead set the namespace (or testNamespace) in the module's
> build.gradle file, as described here:
> https://developer.android.com/studio/build/configure-app-module#set-namespace
DesktopConnection implements Closeable, so it is implicitly closed after
its try-with-resources block. Closing the DesktopConnection shutdowns
the sockets, so it is necessary in particular to wake up blocking read()
calls from the controller.
But the controller thread was joined before the DesktopConnection was
closed, causing a deadlock. To fix the problem, join the controller
thread only after the DesktopConnection is closed.
Refs 400a1c69b1
On close, the client closes the socket. This wakes up socket blocking
calls on the server-side, by throwing an exception. Since this exception
is expected, it was not logged.
However, other IOExceptions might occur, which must not be ignored. For
that purpose, log only IOException when they are not caused by an EPIPE
error.