Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scrcpy server does not restore Android settings in case of unexpected termination/ADB disconnection #5601

Open
oxwivi opened this issue Dec 4, 2024 · 30 comments

Comments

@oxwivi
Copy link

oxwivi commented Dec 4, 2024

Environment

  • OS: N/A
  • Scrcpy version: 3.0
  • Installation method: N/A
  • Device model: N/A
  • Android version: 15

Describe the bug

Whenever ADB disconnects (over Wi-Fi, probably because device changes frequency or roamed to different AP), server-side doesn't appear to restore settings as part of the exit cleanup. For example, when scrcpy is running with the--stay-awake and ADB unexpectedly terminates, the Stay awake option in Developer options remains toggled on. Any subsequent scrcpy connection takes this as a base setting and doesn't turn it off when properly exiting either. It has to be manually disabled in Developer options.

What is the server-side behavior for unexpected disconnections? Is the exit cleanup only possible with ADB commands from the client-side? I'm hoping it's possible for scrcpy server to detect abrupt disconnections and execute the cleanup routine independent of the client.

@oxwivi
Copy link
Author

oxwivi commented Dec 4, 2024

That also makes wonder, how is virtual displays handled when this happens. I hope it doesn't continue to exist and consume resources without recourse.

@rom1v
Copy link
Collaborator

rom1v commented Dec 4, 2024

Which device is it?

On unexpected disconnection, cleanup should still be executed.

For example, if I run scrcpy --show-touches, and I unplug the USB cable, "show touches" is immediately disabled on the phone.

I have a device (Nexus 5 with Android 6) where the cleanup process is killed before it completes, probably an Android bug. But in general, it works.

That also makes wonder, how is virtual displays handled when this happens

The virtual display is destroyed anyway. Currently, the content (the app launched in virtual display) is also destroyed. In future versions, it would be great to have a flag to keep the running app (moved to the main display for example). See #5563 (comment)

@oxwivi
Copy link
Author

oxwivi commented Dec 4, 2024

Which device is it?

On unexpected disconnection, cleanup should still be executed.

Pixel 8 Pro/GrapeheneOS, but I've observed it many times on my last phone, Motorola Edge 30/LineageOS. (That's why I've left device model as N/A)

Is there anything else I can provide to debug this, or is it being Android bug pretty much confirmed?

The virtual display is destroyed anyway. Currently, the content (the app launched in virtual display) is also destroyed. In future versions, it would be great to have a flag to keep the running app (moved to the main display for example). See #5563 (comment)

Oh, good. Yes, keeping the app running would be great.

@rom1v
Copy link
Collaborator

rom1v commented Dec 4, 2024

Can you reproduce the problem with scrcpy --show-touches?

@oxwivi
Copy link
Author

oxwivi commented Dec 4, 2024

I just realized, it might possibly a WONTFIX. When Android decides to roam to a different BSSID, ADB is automatically switched off... I'm guessing server cleanup doesn't have the chance to run before being killed alongside ADB. Perhaps if something like Shizuku was involved, it might be different? But Shizuku also depends on wireless ADB...

Can you reproduce the problem with scrcpy --show-touches?

I'll try tomorrow (past midnight here). Should be easy for me to reproduce by simply kicking off device from my AP.

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

I'm guessing server cleanup doesn't have the chance to run before being killed alongside ADB.

Yes, it can run when adb is killed. See https://github.com/Genymobile/scrcpy/blob/master/server/src/main/java/com/genymobile/scrcpy/CleanUp.java

@aprovera
Copy link

aprovera commented Dec 5, 2024

I have the same issue with the "Stay Awake" option remaining activated on the phone if the USB cable is yanked. Samsung Galaxy A7 (2018), running Android 10.

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

Can you reproduce with --show-touches (which is more obvious to test) 100%, or is it random?

https://github.com/Genymobile/scrcpy/blob/master/doc/device.md#show-touches

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

AFAIK, there are two possible problems:

  • on some devices, Android unexpectedly kills the clean up process at the same time as the scrcpy process;
  • currently, if scrcpy terminates before the cleanup process is started (race condition), typically due to an error, the initial state is not restored (can be easily reproduced with scrcpy --show-touches --video-encoder=fail)

I will fix the second problem soon.

@aprovera
Copy link

aprovera commented Dec 5, 2024

Can you reproduce with --show-touches (which is more obvious to test) 100%, or is it random?

Yes, I can reproduce the behaviour consistently with both.

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

It should work with:

diff --git a/server/src/main/java/com/genymobile/scrcpy/CleanUp.java b/server/src/main/java/com/genymobile/scrcpy/CleanUp.java
index f372855bf..3df2199de 100644
--- a/server/src/main/java/com/genymobile/scrcpy/CleanUp.java
+++ b/server/src/main/java/com/genymobile/scrcpy/CleanUp.java
@@ -108,6 +108,7 @@ public final class CleanUp {
     private void run(int displayId, int restoreStayOn, boolean disableShowTouches, boolean powerOffScreen, int restoreScreenOffTimeout)
             throws IOException {
         String[] cmd = {
+                "setsid",
                 "app_process",
                 "/",
                 CleanUp.class.getName(),

But I think setsid is not available everywhere.

However, this might work:

diff --git server/src/main/java/com/genymobile/scrcpy/CleanUp.java server/src/main/java/com/genymobile/scrcpy/CleanUp.java
index f372855bf..f81b5c183 100644
--- server/src/main/java/com/genymobile/scrcpy/CleanUp.java
+++ server/src/main/java/com/genymobile/scrcpy/CleanUp.java
@@ -108,6 +108,8 @@ public final class CleanUp {
     private void run(int displayId, int restoreStayOn, boolean disableShowTouches, boolean powerOffScreen, int restoreScreenOffTimeout)
             throws IOException {
         String[] cmd = {
+                "/system/bin/sh",
+                "-c",
                 "app_process",
                 "/",
                 CleanUp.class.getName(),
@@ -116,6 +118,7 @@ public final class CleanUp {
                 String.valueOf(disableShowTouches),
                 String.valueOf(powerOffScreen),
                 String.valueOf(restoreScreenOffTimeout),
+                "&",
         };
 
         ProcessBuilder builder = new ProcessBuilder(cmd);

Please test this binary (to replace in 3.0.2):

  • scrcpy-server SHA-256: df21e420edd7b723fb6ca70a98846f87c04d5719698d21af9eefea27f0b037b

@aprovera
Copy link

aprovera commented Dec 5, 2024

No change, at least on my device. Yanked the cable and I still get visible touches, and stay awake remains active.

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

It fixes the problem on my Nexus 5 ("show touches" must be disabled when scrcpy starts, because it restores the initial value).

adb shell settings put system show_touches 0
scrcpy --show-touches
# unplug USB cable

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

Oh no, sorry, it's only the setsid version which works for my Nexus 5. Try:

  • scrcpy-server SHA-256: d325a23eba4d14c01a7adfc7a705f4f1a8cc2b0a009f817bf970ee2f30a19fb

@aprovera
Copy link

aprovera commented Dec 5, 2024

No dice with this one either, on my device I still get the same behaviour (of course I reset both show touches and stay awake to off before trying, like I did when I tried the other test binary).

Maybe @oxwivi will have better luck with theirs.

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

Maybe your device does not have setsid. What is the result of adb shell which setsid? And adb shell which nohup?

@aprovera
Copy link

aprovera commented Dec 5, 2024

Looks like it has both:

$ adb shell which setsid
/system/bin/setsid
$ adb shell which nohup
/system/bin/nohup

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

And with:

  • scrcpy-server SHA-256: 09a7caf75fb694ee08214a415f1a0712ea8fb821a06f9b0d1301351b93ca495

?

@aprovera
Copy link

aprovera commented Dec 5, 2024

Still no change. Perhaps with some devices it's just inevitable...

@aprovera
Copy link

aprovera commented Dec 5, 2024

I've done some experimenting on another computer, using the standard 3.0.2 scrcpy-server, running a logcat viewer on the phone.

In my case, it looks like the server doesn't even recognise the USB cable being yanked, and instead it runs the cleanup process when USB is plugged back in.

In the following screen recording, I start out with USB connected (as confirmed by the message in notification panel), then start scrcpy --show-touches, which is reflected in the logcat.

I tap around and open the notification panel again, then I disconnect the USB cable, but nothing appears in the log.

At around 0:28 in the video, I open the notification panel yet again to show USB is no longer connected, then tap around the screen some more and touches are still shown.

At 0:53, I reconnect the cable, and only then does the cleanup process run, and touches are no longer shown.

Screen_Recording_20241205-202558_Logcat.Extreme.mp4

Hope this helps.

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

Weird. If instead of disconnecting the USB cable you execute adb kill-server, what's the behavior?

@aprovera
Copy link

aprovera commented Dec 5, 2024

Same behaviour: nothing in logcat after doing adb kill-server on the computer. Then, when I start scrcpy again on the computer, it runs the cleanup process.

@rom1v
Copy link
Collaborator

rom1v commented Dec 5, 2024

Looks like a device bug, the read() does not wake up if the parent process terminates:

while ((msg = System.in.read()) != -1) {

(or maybe the parent process does not terminate properly?)

@sishgupta
Copy link

sishgupta commented Dec 6, 2024

I can confirm this bug on a pixel 9 running latest android 15 QPR1. Not sure when it started for me, maybe after moving to A15? Also I think this problem was occurring with 2.7.
But for a month or so now I've noticed my phone screen staying awake all night on my bed while its been plugged in.

I thought maybe it was a fluke after reading the /doc/device.md and I manually used adb to restore the value. But I just checked again and it's the same problem.

My usecase is that i normally setup a tcpip connection via usb, and most of the time i just yank the cable to go wireless. From there on i launch a direct tcpip connection via hostname. Connecting via hostname and exiting does not seem to create this problem.

I would say that this issue is large enough for me that i would avoid --stay-awake since it's caused my phone screen to stay on while charging overnight several times.

Please let me know if i can provide more information to assist with diagnostics.

@rom1v
Copy link
Collaborator

rom1v commented Dec 6, 2024

Please test #5613, which solves some of the problems (but not #5601 (comment)).

@sishgupta
Copy link

Please test #5613, which solves some of the problems (but not #5601 (comment)).

Thanks, I am now testing this. I tried to re-produce with my usecase and it seems ok but i was not necessarily able to consistently reproduce the issue before this test. I will continue testing over the weekend and report back.

@oxwivi
Copy link
Author

oxwivi commented Dec 6, 2024

Can you reproduce the problem with scrcpy --show-touches?

Can reproduce. Very sorry about my radio silence yesterday, I was far more busy than I expected.

Please test #5613, which solves some of the problems (but not #5601 (comment)).

Sorry, how do you specify different server bins?

@rom1v
Copy link
Collaborator

rom1v commented Dec 6, 2024

Sorry, how do you specify different server bins?

Either set the SCRCPY_SERVER_PATH environment variable to the scrcpy-server you want to use. Or just make a backup and replace scrcpy-server in your release folder.

@oxwivi
Copy link
Author

oxwivi commented Dec 6, 2024

Please test #5613, which solves some of the problems (but not #5601 (comment)).

Still the same. stdout shows that it has picked up the downloaded scrcpy-server, but the settings remains toggled after I kick my phone off of Wi-Fi while scrcpy is running:

$ scrcpy -wb 896M --audio-codec=flac --disable-screensaver --power-off-on-close --new-display=1920x1080 --video-codec=av1
scrcpy 3.0.2 <https://github.com/Genymobile/scrcpy>
INFO: FLAC audio: audio buffer increased to 120 ms (use --audio-buffer to set a custom value)
WARN: Could not disable minimize on focus loss
INFO: ADB device found:
INFO:     -->   (usb)  adb-3A090DLJG000YG-lDVe9W._adb-tls-connect._tcp            device  Pixel_8_Pro
/home/$USER/Downloads/scrcpy-server: 1 file pushed, 0 skipped. 141.0 MB/s (90504 bytes in 0.001s)
[server] INFO: Device: [Google] google Pixel 8 Pro (Android 15)
INFO: Renderer: opengl
INFO: OpenGL version: 4.6 (Compatibility Profile) Mesa 24.2.8
INFO: Trilinear filtering enabled
INFO: Texture: 1920x1080
[server] INFO: New display: 1920x1080/308 (id=7)
WARN: Device disconnected

rom1v added a commit that referenced this issue Dec 8, 2024
Some options, such as --show-touches or --stay-awake, modify Android
settings and must be restored upon exit.

If scrcpy terminates (e.g. due to an early error) in the middle of the
clean up configuration, the device may be left in an inconsistent state
(some settings might be changed but not restored).

This issue can be reproduced with high probability by forcing scrcpy to
fail:

    scrcpy --show-touches --video-encoder=fail

To prevent this problem, ensure that the clean up thread is not
interrupted until the clean up process is started.

Refs #5601 <#5601>
PR #5613 <#5613>
rom1v added a commit that referenced this issue Dec 8, 2024
If available, start the cleanup process in a new session to reduce the
likelihood of it being terminated along with the scrcpy server process
on some devices.

The binaries setsid and nohup are often available, but it is not
guaranteed.

Refs #5601 <#5601>
PR #5613 <#5613>
@sishgupta
Copy link

My situation has definitely improved, I am not able to re-produce as consistently. I did have one time where the flag did not reset, and I am not sure what I did to cause this. If I can narrow down the steps to re-produce I will present them here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants