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

fix freeze and thaw rotation for Android 15 preview #4740

Closed

Conversation

ssalenik
Copy link

@ssalenik ssalenik commented Mar 7, 2024

On a device with Android 15 developer preview (and I think this also impacts the 14 QPR3 Beta) we get an error when trying to rotate the device:

scrcpy 2.3.1 <https://github.com/Genymobile/scrcpy>
INFO: ADB device found:
INFO:     --> (tcpip)  26101FDF6003UC           device  Pixel_6
x/server/scrcpy-server: 1 file pushed, 0 skipped. 3.1 MB/s (66691 bytes in 0.020s)
[server] INFO: Device: [Google] google Pixel 6 (Android 14)
INFO: Renderer: metal
INFO: Texture: 360x800
[server] INFO: Device rotation requested: landscape
[server] ERROR: Could not invoke method
java.lang.NoSuchMethodException: android.view.IWindowManager$Stub$Proxy.freezeRotation [int]
        at java.lang.Class.getMethod(Class.java:2950)
        at java.lang.Class.getMethod(Class.java:2450)
        at com.genymobile.scrcpy.wrappers.WindowManager.getFreezeRotationMethod(WindowManager.java:48)
        at com.genymobile.scrcpy.wrappers.WindowManager.freezeRotation(WindowManager.java:111)
        at com.genymobile.scrcpy.Device.rotateDevice(Device.java:372)
        at com.genymobile.scrcpy.Controller.handleEvent(Controller.java:183)
        at com.genymobile.scrcpy.Controller.control(Controller.java:85)
        at com.genymobile.scrcpy.Controller.lambda$start$0$com-genymobile-scrcpy-Controller(Controller.java:93)
        at com.genymobile.scrcpy.Controller$$ExternalSyntheticLambda1.run(Unknown Source:4)
        at java.lang.Thread.run(Thread.java:1012)

The source code is not out yet, but using reflection we can see that the freeze and thaw rotation methods all have a new signature with a String parameter added:

public void android.view.IWindowManager$Stub$Proxy.thawRotation(java.lang.String) throws android.os.RemoteException
public void android.view.IWindowManager$Stub$Proxy.thawDisplayRotation(int,java.lang.String) throws android.os.RemoteException
public void android.view.IWindowManager$Stub$Proxy.freezeRotation(int,java.lang.String) throws android.os.RemoteException
public void android.view.IWindowManager$Stub$Proxy.freezeDisplayRotation(int,int,java.lang.String) throws android.os.RemoteException

I tried passing an empty String and it works.

This PR adds these new method signatures to try first.

@rom1v
Copy link
Collaborator

rom1v commented Mar 7, 2024

Thank you.

Could you please post your framework.jar please?

adb pull /system/framework/framework.jar

@ssalenik
Copy link
Author

ssalenik commented Mar 7, 2024

framework.jar.tar.gz

@rom1v
Copy link
Collaborator

rom1v commented Mar 7, 2024

jadx.plugins.input.dex.DexException: Bad checksum: 0x6dca9986, expected: 0x962f5582

🤔

@ssalenik
Copy link
Author

ssalenik commented Mar 7, 2024

I got the same thing. You can ignore the checksum with jadx -Pdex-input.verify-checksum=no but I didn't find these methods nor the WindowManager class in the decompiled code after, though it had a few errors in decompilation.

@ssalenik
Copy link
Author

ssalenik commented Mar 8, 2024

Looks like they published the source for this change in master now:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/IWindowManager.aidl#345
The parameter is String caller, though they don't describe the parameter:

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/IWindowManager.aidl#345

@ssalenik
Copy link
Author

ssalenik commented Mar 8, 2024

Ah, thanks. Makes sense. I guess we can add "scrcpy" or "scrcpy#setRotation" and "scrcpy#restoreRotationStateLocked" to follow their lead.

rom1v added a commit that referenced this pull request Apr 1, 2024
Select the available method to invoke the same way as in other wrappers
(using a version field).

Refs d894e27
Refs #4740 <#4740>
@rom1v
Copy link
Collaborator

rom1v commented Apr 1, 2024

Thank you 👍

I added a preliminary commit to refactor the current codebase: 4623927.
Then I rebased your PR on this commit (using the new version field): 803a7e0

I pushed to branch pr4740. Please review and test 😉

@ssalenik
Copy link
Author

ssalenik commented Apr 4, 2024

@rom1v tested pr4740 and works on Android 15 preview

@rom1v
Copy link
Collaborator

rom1v commented Apr 6, 2024

Btw, it seems the change has landed in Android 14 (stable, not preview), on a Pixel 8 without this PR I get the error on rotation with MOD+r.

$ git tag --contains 670fb7f5c0d23cf51ead25538bcb017e03ed73ac
android-14.0.0_r29
android-14.0.0_r30
android-14.0.0_r31

rom1v added a commit that referenced this pull request Apr 6, 2024
Select the available method to invoke the same way as in other wrappers
(using a version field).

Refs d894e27
Refs #4740 <#4740>
rom1v pushed a commit that referenced this pull request Apr 6, 2024
Changed since AOSP/framework_base commit
670fb7f5c0d23cf51ead25538bcb017e03ed73ac, included in tag
android-14.0.0_r29.

Refs <https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/>
PR #4740 <#4740>

Signed-off-by: Romain Vimont <[email protected]>
@rom1v
Copy link
Collaborator

rom1v commented Apr 7, 2024

Merged into dev: 7011dd1

@eiyooooo
Copy link
Contributor

eiyooooo commented Apr 12, 2024

private Method getFreezeDisplayRotationMethod() throws NoSuchMethodException {
if (freezeDisplayRotationMethod == null) {
try {
freezeDisplayRotationMethod = manager.getClass().getMethod("freezeRotation", int.class);
freezeDisplayRotationMethodVersion = 0;
} catch (NoSuchMethodException e) {
try {
// New method added by this commit:
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
freezeDisplayRotationMethod = manager.getClass().getMethod("freezeDisplayRotation", int.class, int.class);
freezeDisplayRotationMethodVersion = 1;
} catch (NoSuchMethodException e1) {
// Android 15 preview and 14 QPR3 Beta added a String caller parameter for debugging:
// <https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/>
freezeDisplayRotationMethod = manager.getClass().getMethod("freezeDisplayRotation", int.class, int.class, String.class);
freezeDisplayRotationMethodVersion = 2;
}
}
}
return freezeDisplayRotationMethod;
}
private Method getIsDisplayRotationFrozenMethod() throws NoSuchMethodException {
if (isDisplayRotationFrozenMethod == null) {
try {
isDisplayRotationFrozenMethod = manager.getClass().getMethod("isRotationFrozen");
isDisplayRotationFrozenMethodVersion = 0;
} catch (NoSuchMethodException e) {
// New method added by this commit:
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
isDisplayRotationFrozenMethod = manager.getClass().getMethod("isDisplayRotationFrozen", int.class);
isDisplayRotationFrozenMethodVersion = 1;
}
}
return isDisplayRotationFrozenMethod;
}
private Method getThawDisplayRotationMethod() throws NoSuchMethodException {
if (thawDisplayRotationMethod == null) {
try {
thawDisplayRotationMethod = manager.getClass().getMethod("thawRotation");
thawDisplayRotationMethodVersion = 0;
} catch (NoSuchMethodException e) {
try {
// New method added by this commit:
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
thawDisplayRotationMethod = manager.getClass().getMethod("thawDisplayRotation", int.class);
thawDisplayRotationMethodVersion = 1;
} catch (NoSuchMethodException e1) {
// Android 15 preview and 14 QPR3 Beta added a String caller parameter for debugging:
// <https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/>
thawDisplayRotationMethod = manager.getClass().getMethod("thawDisplayRotation", int.class, String.class);
thawDisplayRotationMethodVersion = 2;
}
}
}
return thawDisplayRotationMethod;
}

Should try the newest method first, then old method.

Because the old method still exists while the new method is introduced.

Seeing #4841

@rom1v
Copy link
Collaborator

rom1v commented Apr 12, 2024

Because the old method still exists while the new method is introduced.

Nope, it was replaced: https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/

@eiyooooo
Copy link
Contributor

eiyooooo commented Apr 12, 2024

Nope, it was replaced: https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/

While freezeDisplayRotation is introduced, freezeRotation still exists.

If try freezeRotation first, then could not rotate secondary display.

C:\q\software\scrcpy-win64-v2.4>scrcpy.exe --display-id 67
scrcpy 2.4 <https://github.com/Genymobile/scrcpy>
INFO: ADB device found:
INFO:     -->   (usb)  R5CN2100000                     device  SM_G986U1
C:\q\software\scrcpy-win64-v2.4\scrcpy-server: 1 file pushed, 0 skipped. 29.5 MB/s (69259 bytes in 0.002s)
[server] INFO: Device: [samsung] samsung SM-G986U1 (Android 13)
[server] WARN: Display doesn't have FLAG_SUPPORTS_PROTECTED_BUFFERS flag, mirroring can be restricted
INFO: Renderer: direct3d
INFO: Texture: 1080x1920
[server] ERROR: Secondary display rotation not supported on this device
[server] INFO: Device rotation requested: landscape
[server] ERROR: Secondary display rotation not supported on this device
[server] ERROR: Secondary display rotation not supported on this device

So try freezeDisplayRotation first, if freezeDisplayRotation not exists then freezeRotation.

C:\q\software\scrcpy-win64-v2.4>scrcpy.exe --display-id 67
scrcpy 2.4 <https://github.com/Genymobile/scrcpy>
INFO: ADB device found:
INFO:     -->   (usb)  R5CN2100000                     device  SM_G986U1
C:\q\software\scrcpy-win64-v2.4\scrcpy-server: 1 file pushed, 0 skipped. 84.4 MB/s (69223 bytes in 0.001s)
[server] INFO: Device: [samsung] samsung SM-G986U1 (Android 13)
[server] WARN: Display doesn't have FLAG_SUPPORTS_PROTECTED_BUFFERS flag, mirroring can be restricted
INFO: Renderer: direct3d
INFO: Texture: 1080x1920
[server] INFO: Device rotation requested: landscape
INFO: Texture: 1920x1080
[server] INFO: Device rotation requested: portrait
INFO: Texture: 1080x1920
WARN: Killing the server...

BTW, watchRotation old version should check if displayId is 0.

public void registerRotationWatcher(IRotationWatcher rotationWatcher, int displayId) {
try {
Class<?> cls = manager.getClass();
try {
// display parameter added since this commit:
// https://android.googlesource.com/platform/frameworks/base/+/35fa3c26adcb5f6577849fd0df5228b1f67cf2c6%5E%21/#F1
cls.getMethod("watchRotation", IRotationWatcher.class, int.class).invoke(manager, rotationWatcher, displayId);
} catch (NoSuchMethodException e) {
// old version
cls.getMethod("watchRotation", IRotationWatcher.class).invoke(manager, rotationWatcher);
}
} catch (Exception e) {
Ln.e("Could not register rotation watcher", e);
}
}

@rom1v
Copy link
Collaborator

rom1v commented Apr 12, 2024

Oh ok, sorry, I've read the whole thing from my phone, I will check later from my computer.

@ssalenik
Copy link
Author

Oh, oups. I didn't notice that your refactor @rom1v changed this. Before we were trying the methods which allow to specify the display first and then falling back to the old one in the case that display == 0.

rom1v pushed a commit that referenced this pull request Apr 12, 2024
The version of the methods with the display id parameter must be tried
first, otherwise they will never be used (since the old versions without
the display id are still present).

Regression introduced by ee6620d.

Refs #4740 <#4740>
PR #4841 <#4841>

Signed-off-by: Romain Vimont <[email protected]>
rom1v added a commit that referenced this pull request Apr 12, 2024
Old Android versions may not be able to register a rotation watcher for
a secondary display. In that case, report the error instead of
registering a rotation watcher for the default display.

Refs <#4740 (comment)>

Suggested by: Kaiming Hu <[email protected]>
@rom1v
Copy link
Collaborator

rom1v commented Apr 12, 2024

LGTM, see #4841.

FreedomBen pushed a commit to FreedomBen/scrcpy that referenced this pull request Aug 2, 2024
Select the available method to invoke the same way as in other wrappers
(using a version field).

Refs d894e27
Refs Genymobile#4740 <Genymobile#4740>
FreedomBen pushed a commit to FreedomBen/scrcpy that referenced this pull request Aug 2, 2024
Changed since AOSP/framework_base commit
670fb7f5c0d23cf51ead25538bcb017e03ed73ac, included in tag
android-14.0.0_r29.

Refs <https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/>
PR Genymobile#4740 <Genymobile#4740>

Signed-off-by: Romain Vimont <[email protected]>
FreedomBen pushed a commit to FreedomBen/scrcpy that referenced this pull request Aug 2, 2024
The version of the methods with the display id parameter must be tried
first, otherwise they will never be used (since the old versions without
the display id are still present).

Regression introduced by ee6620d.

Refs Genymobile#4740 <Genymobile#4740>
PR Genymobile#4841 <Genymobile#4841>

Signed-off-by: Romain Vimont <[email protected]>
FreedomBen pushed a commit to FreedomBen/scrcpy that referenced this pull request Aug 2, 2024
Old Android versions may not be able to register a rotation watcher for
a secondary display. In that case, report the error instead of
registering a rotation watcher for the default display.

Refs <Genymobile#4740 (comment)>

Suggested by: Kaiming Hu <[email protected]>
Gottox pushed a commit to Gottox/scrcpy that referenced this pull request Sep 29, 2024
Select the available method to invoke the same way as in other wrappers
(using a version field).

Refs d894e27
Refs Genymobile#4740 <Genymobile#4740>
Gottox pushed a commit to Gottox/scrcpy that referenced this pull request Sep 29, 2024
Changed since AOSP/framework_base commit
670fb7f5c0d23cf51ead25538bcb017e03ed73ac, included in tag
android-14.0.0_r29.

Refs <https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/>
PR Genymobile#4740 <Genymobile#4740>

Signed-off-by: Romain Vimont <[email protected]>
Gottox pushed a commit to Gottox/scrcpy that referenced this pull request Sep 29, 2024
The version of the methods with the display id parameter must be tried
first, otherwise they will never be used (since the old versions without
the display id are still present).

Regression introduced by ee6620d.

Refs Genymobile#4740 <Genymobile#4740>
PR Genymobile#4841 <Genymobile#4841>

Signed-off-by: Romain Vimont <[email protected]>
Gottox pushed a commit to Gottox/scrcpy that referenced this pull request Sep 29, 2024
Old Android versions may not be able to register a rotation watcher for
a secondary display. In that case, report the error instead of
registering a rotation watcher for the default display.

Refs <Genymobile#4740 (comment)>

Suggested by: Kaiming Hu <[email protected]>
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

Successfully merging this pull request may close these issues.

4 participants