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

Can no longer paste from Windows 10 to Android 13 (QPR Beta 1) #3497

Closed
Icarus3000 opened this issue Sep 13, 2022 · 22 comments
Closed

Can no longer paste from Windows 10 to Android 13 (QPR Beta 1) #3497

Icarus3000 opened this issue Sep 13, 2022 · 22 comments

Comments

@Icarus3000
Copy link

Icarus3000 commented Sep 13, 2022

Device: Pixel 6 Pro
Android OS: 13 QPR Beta 1
Windows 10
Scrcpy 1.24

Terminal output when I press CTRL-V in scrcpy window:

[server] ERROR: Could not invoke method
[server] ERROR: Could not invoke method
java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.getPrimaryClip [class java.lang.String, int]
        at java.lang.Class.getMethod(Class.java:2103)
        at java.lang.Class.getMethod(Class.java:1724)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.getGetPrimaryClipMethod(ClipboardManager.java:28)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.getText(ClipboardManager.java:63)
        at com.genymobile.scrcpy.Device.getClipboardText(Device.java:251)
        at com.genymobile.scrcpy.Device.setClipboardText(Device.java:264)
        at com.genymobile.scrcpy.Controller.setClipboard(Controller.java:300)
        at com.genymobile.scrcpy.Controller.handleEvent(Controller.java:124)
        at com.genymobile.scrcpy.Controller.control(Controller.java:75)
        at com.genymobile.scrcpy.Server$3.run(Server.java:133)
        at java.lang.Thread.run(Thread.java:1012)
java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.setPrimaryClip [class android.content.ClipData, class java.lang.String, int]
        at java.lang.Class.getMethod(Class.java:2103)
        at java.lang.Class.getMethod(Class.java:1724)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.getSetPrimaryClipMethod(ClipboardManager.java:39)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.setText(ClipboardManager.java:77)
        at com.genymobile.scrcpy.Device.setClipboardText(Device.java:274)
        at com.genymobile.scrcpy.Controller.setClipboard(Controller.java:300)
        at com.genymobile.scrcpy.Controller.handleEvent(Controller.java:124)
        at com.genymobile.scrcpy.Controller.control(Controller.java:75)
        at com.genymobile.scrcpy.Server$3.run(Server.java:133)
        at java.lang.Thread.run(Thread.java:1012)

EDIT by rom1v: Fixed in scrcpy v1.25.

@Icarus3000 Icarus3000 changed the title Can no longer past from Windows 10 to Android 13 (QPR Beta 1) Can no longer paste from Windows 10 to Android 13 (QPR Beta 1) Sep 13, 2022
@rom1v
Copy link
Collaborator

rom1v commented Sep 13, 2022

Please replace scrcpy-server in your v1.24 release, run scrcpy, then copy-paste the whole console output:

  • scrcpy-server SHA-256: 21546900831d0f6d0c2ba6debd8d04fb1fd9686527db65f9d10d0d94fd60e2b3
diff
diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
index e25b6e99..b178d18d 100644
--- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
+++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
@@ -18,6 +18,9 @@ public class ClipboardManager {
 
     public ClipboardManager(IInterface manager) {
         this.manager = manager;
+        for (Method m : manager.getClass().getDeclaredMethods()) {
+            Ln.i("=== " + m);
+        }
     }
 
     private Method getGetPrimaryClipMethod() throws NoSuchMethodException {

@Icarus3000
Copy link
Author

Icarus3000 commented Sep 13, 2022

scrcpy 1.24 <https://github.com/Genymobile/scrcpy>
C:\Users\cschneider\scrcpy\scrcpy-server: 1 file pushed, 0 skipped. 38.9 MB/s (61134 bytes in 0.002s)
[server] INFO: Device: Google Pixel 6 Pro (Android 13)
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.addPrimaryClipChangedListener(android.content.IOnPrimaryClipChangedListener,java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public android.os.IBinder android.content.IClipboard$Stub$Proxy.asBinder()
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.clearPrimaryClip(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public java.lang.String android.content.IClipboard$Stub$Proxy.getInterfaceDescriptor()
[server] INFO: === public android.content.ClipData android.content.IClipboard$Stub$Proxy.getPrimaryClip(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public android.content.ClipDescription android.content.IClipboard$Stub$Proxy.getPrimaryClipDescription(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public java.lang.String android.content.IClipboard$Stub$Proxy.getPrimaryClipSource(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public boolean android.content.IClipboard$Stub$Proxy.hasClipboardText(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public boolean android.content.IClipboard$Stub$Proxy.hasPrimaryClip(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.removePrimaryClipChangedListener(android.content.IOnPrimaryClipChangedListener,java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.setPrimaryClip(android.content.ClipData,java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.setPrimaryClipAsPackage(android.content.ClipData,java.lang.String,java.lang.String,int,java.lang.String) throws android.os.RemoteException
[server] ERROR: Could not invoke method
java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.addPrimaryClipChangedListener [interface android.content.IOnPrimaryClipChangedListener, class java.lang.String, int]
        at java.lang.Class.getMethod(Class.java:2103)
        at java.lang.Class.getMethod(Class.java:1724)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.getAddPrimaryClipChangedListener(ClipboardManager.java:106)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.addPrimaryClipChangedListener(ClipboardManager.java:114)
        at com.genymobile.scrcpy.Device.<init>(Device.java:103)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:65)
        at com.genymobile.scrcpy.Server.main(Server.java:335)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:355)
INFO: Renderer: direct3d
INFO: Initial texture: 1440x3120

@rom1v
Copy link
Collaborator

rom1v commented Sep 14, 2022

public android.content.ClipData android.content.IClipboard$Stub$Proxy.getPrimaryClip(java.lang.String,java.lang.String,int) throws android.os.RemoteException

OK, the function signature has changed on your device, but this does not match the AOSP source code on tag android-13.0.0_r6.

So they probably changed something whose source code is not published yet, so I don't know what is the meaning of this additional String parameter.

Let's try to pass the package name twice:

diff
diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
index e25b6e99..916a690c 100644
--- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
+++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
@@ -15,6 +15,8 @@ public class ClipboardManager {
     private Method getPrimaryClipMethod;
     private Method setPrimaryClipMethod;
     private Method addPrimaryClipChangedListener;
+    private boolean alternativeGetMethod;
+    private boolean alternativeSetMethod;
 
     public ClipboardManager(IInterface manager) {
         this.manager = manager;
@@ -25,7 +27,12 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
             } else {
-                getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                try {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, String.class, int.class);
+                    alternativeGetMethod = true;
+                }
             }
         }
         return getPrimaryClipMethod;
@@ -36,23 +43,33 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
             } else {
-                setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                try {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, String.class, int.class);
+                    alternativeSetMethod = true;
+                }
             }
         }
         return setPrimaryClipMethod;
     }
 
-    private static ClipData getPrimaryClip(Method method, IInterface manager) throws InvocationTargetException, IllegalAccessException {
+    private static ClipData getPrimaryClip(Method method, boolean alternativeMethod, IInterface manager) throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME);
         }
+        if (alternativeMethod) {
+            return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
+        }
         return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
     }
 
-    private static void setPrimaryClip(Method method, IInterface manager, ClipData clipData)
+    private static void setPrimaryClip(Method method, boolean alternativeMethod, IInterface manager, ClipData clipData)
             throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME);
+        } else if (alternativeMethod) {
+            method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
         } else {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
         }
@@ -61,7 +78,7 @@ public class ClipboardManager {
     public CharSequence getText() {
         try {
             Method method = getGetPrimaryClipMethod();
-            ClipData clipData = getPrimaryClip(method, manager);
+            ClipData clipData = getPrimaryClip(method, alternativeGetMethod, manager);
             if (clipData == null || clipData.getItemCount() == 0) {
                 return null;
             }
@@ -76,7 +93,7 @@ public class ClipboardManager {
         try {
             Method method = getSetPrimaryClipMethod();
             ClipData clipData = ClipData.newPlainText(null, text);
-            setPrimaryClip(method, manager, clipData);
+            setPrimaryClip(method, alternativeSetMethod, manager, clipData);
             return true;
         } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
             Ln.e("Could not invoke method", e);
  • scrcpy-server SHA-256: b22d8354e3792f88afa2697d45e3dcf9c77724337392683d99c8941c7b824b73

@Icarus3000
Copy link
Author

Icarus3000 commented Sep 14, 2022

It works again!

The console output still shows an error, but i don't know if that's important;

scrcpy 1.24 <https://github.com/Genymobile/scrcpy>
C:\Users\cschneider\scrcpy\scrcpy-server: 1 file pushed, 0 skipped. 52.1 MB/s (71762 bytes in 0.001s)
[server] INFO: Device: Google Pixel 6 Pro (Android 13)
[server] ERROR: Could not invoke method
java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.addPrimaryClipChangedListener [interface android.content.IOnPrimaryClipChangedListener, class java.lang.String, int]
        at java.lang.Class.getMethod(Class.java:2103)
        at java.lang.Class.getMethod(Class.java:1724)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.getAddPrimaryClipChangedListener(ClipboardManager.java:120)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.addPrimaryClipChangedListener(ClipboardManager.java:128)
        at com.genymobile.scrcpy.Device.<init>(Device.java:103)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:65)
        at com.genymobile.scrcpy.Server.main(Server.java:335)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:355)
INFO: Renderer: direct3d
INFO: Initial texture: 1440x3120
[server] INFO: Device clipboard set

@rom1v
Copy link
Collaborator

rom1v commented Sep 14, 2022

java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.addPrimaryClipChangedListener [interface android.content.IOnPrimaryClipChangedListener, class java.lang.String, int]

Oh, they also added a String parameter to addPrimaryClipChangedListener().

but i don't know if that's important;

Yes, it's to synchronize the clipboard from Android to the computer.

Here is a version with a fix for this method too:

diff
diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
index e25b6e99..bfed7442 100644
--- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
+++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
@@ -15,6 +15,9 @@ public class ClipboardManager {
     private Method getPrimaryClipMethod;
     private Method setPrimaryClipMethod;
     private Method addPrimaryClipChangedListener;
+    private boolean alternativeGetMethod;
+    private boolean alternativeSetMethod;
+    private boolean alternativeAddListenerMethod;
 
     public ClipboardManager(IInterface manager) {
         this.manager = manager;
@@ -25,7 +28,12 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
             } else {
-                getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                try {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, String.class, int.class);
+                    alternativeGetMethod = true;
+                }
             }
         }
         return getPrimaryClipMethod;
@@ -36,23 +44,34 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
             } else {
-                setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                try {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, String.class, int.class);
+                    alternativeSetMethod = true;
+                }
             }
         }
         return setPrimaryClipMethod;
     }
 
-    private static ClipData getPrimaryClip(Method method, IInterface manager) throws InvocationTargetException, IllegalAccessException {
+    private static ClipData getPrimaryClip(Method method, boolean alternativeMethod, IInterface manager)
+            throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME);
         }
+        if (alternativeMethod) {
+            return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
+        }
         return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
     }
 
-    private static void setPrimaryClip(Method method, IInterface manager, ClipData clipData)
+    private static void setPrimaryClip(Method method, boolean alternativeMethod, IInterface manager, ClipData clipData)
             throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME);
+        } else if (alternativeMethod) {
+            method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
         } else {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
         }
@@ -61,7 +80,7 @@ public class ClipboardManager {
     public CharSequence getText() {
         try {
             Method method = getGetPrimaryClipMethod();
-            ClipData clipData = getPrimaryClip(method, manager);
+            ClipData clipData = getPrimaryClip(method, alternativeGetMethod, manager);
             if (clipData == null || clipData.getItemCount() == 0) {
                 return null;
             }
@@ -76,7 +95,7 @@ public class ClipboardManager {
         try {
             Method method = getSetPrimaryClipMethod();
             ClipData clipData = ClipData.newPlainText(null, text);
-            setPrimaryClip(method, manager, clipData);
+            setPrimaryClip(method, alternativeSetMethod, manager, clipData);
             return true;
         } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
             Ln.e("Could not invoke method", e);
@@ -84,13 +103,14 @@ public class ClipboardManager {
         }
     }
 
-    private static void addPrimaryClipChangedListener(Method method, IInterface manager, IOnPrimaryClipChangedListener listener)
-            throws InvocationTargetException, IllegalAccessException {
+    private static void addPrimaryClipChangedListener(Method method, boolean alternativeMethod, IInterface manager,
+            IOnPrimaryClipChangedListener listener) throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             method.invoke(manager, listener, ServiceManager.PACKAGE_NAME);
-        } else {
+        } else if (alternativeMethod) {
+            method.invoke(manager, listener, ServiceManager.PACKAGE_NAME, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
+        } else
             method.invoke(manager, listener, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
-        }
     }
 
     private Method getAddPrimaryClipChangedListener() throws NoSuchMethodException {
@@ -99,8 +119,14 @@ public class ClipboardManager {
                 addPrimaryClipChangedListener = manager.getClass()
                         .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class);
             } else {
-                addPrimaryClipChangedListener = manager.getClass()
-                        .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, int.class);
+                try {
+                    addPrimaryClipChangedListener = manager.getClass()
+                            .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    addPrimaryClipChangedListener = manager.getClass()
+                            .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, String.class, int.class);
+                    alternativeAddListenerMethod = true;
+                }
             }
         }
         return addPrimaryClipChangedListener;
@@ -109,7 +135,7 @@ public class ClipboardManager {
     public boolean addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener) {
         try {
             Method method = getAddPrimaryClipChangedListener();
-            addPrimaryClipChangedListener(method, manager, listener);
+            addPrimaryClipChangedListener(method, alternativeAddListenerMethod, manager, listener);
             return true;
         } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
             Ln.e("Could not invoke method", e);
  • scrcpy-server SHA-256: 9215973603e4e8210aef92527add4498ad4445167a71621c14576fa4d0b8f7ab

@Icarus3000
Copy link
Author

Perfect fix! no error message. Thank you so much!

@markusressel
Copy link

Having this fixed is great, thx!

However, I am not sure how I can access this fix without compiling the project myself.
Having to type in long and complex texts maually instead of c&p is a huge productivity stepping stone. Will there be a release that contains this fix anytime soon?

@rom1v
Copy link
Collaborator

rom1v commented Sep 26, 2022

However, I am not sure how I can access this fix without compiling the project myself.

Just take this binary: #3497 (comment) and replace it in your v1.24 release.

@markusressel
Copy link

Thx, it works.
It was a little tricky to find the path on a homebrew install, its located here: /usr/local/Cellar/scrcpy/1.24/share/scrcpy/scrcpy-server

@rom1v
Copy link
Collaborator

rom1v commented Sep 26, 2022

Just FYI, alternatively, you could download it anywhere, and set the environment variable SCRCPY_SERVER_PATH:

export SCRCPY_SERVER_PATH=/path/to/your/scrcpy-server

@alex310110
Copy link

Same issue here with Pixel 6 Pro. I don't work for Android team, but I may be running on an unreleased build. I got this issue after a security update, and it took some time to update, so I wonder if the changes were quite major. The date of the security update is a future time around early December 2022. I think that's all I can provide for now. :P Many thanks for your work including the fix in this thread, rom1v!

@Zettymaster
Copy link

Can we get this (or even better a true fix) as a proper release, please? makes installing and managing versions easier.

@GetOutOfMyBakery
Copy link

That last binary, #3497 (comment), and

export SCRCPY_SERVER_PATH=/path/to/your/scrcpy-server

also worked for me, thanks! Only stopped working with the latest Android security patch:

Phone: Pixel 4a
Android Version: 13
Security Update: 5 Dec 2022
Build Number: TQ1A.221205.011

Laptop: macOS Montery 12.6.1

@rom1v
Copy link
Collaborator

rom1v commented Dec 20, 2022

They finally published the change in AOSP: 0e3e509b.

A new parameter attributionTag has been added. We can probably pass null as a value.

Please test this new binary and confirm that it works.

diff
diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
index e25b6e99..aeb59357 100644
--- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
+++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
@@ -15,6 +15,9 @@ public class ClipboardManager {
     private Method getPrimaryClipMethod;
     private Method setPrimaryClipMethod;
     private Method addPrimaryClipChangedListener;
+    private boolean alternativeGetMethod;
+    private boolean alternativeSetMethod;
+    private boolean alternativeAddListenerMethod;
 
     public ClipboardManager(IInterface manager) {
         this.manager = manager;
@@ -25,7 +28,12 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
             } else {
-                getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                try {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, String.class, int.class);
+                    alternativeGetMethod = true;
+                }
             }
         }
         return getPrimaryClipMethod;
@@ -36,23 +44,34 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
             } else {
-                setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                try {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, String.class, int.class);
+                    alternativeSetMethod = true;
+                }
             }
         }
         return setPrimaryClipMethod;
     }
 
-    private static ClipData getPrimaryClip(Method method, IInterface manager) throws InvocationTargetException, IllegalAccessException {
+    private static ClipData getPrimaryClip(Method method, boolean alternativeMethod, IInterface manager)
+            throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME);
         }
+        if (alternativeMethod) {
+            return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, null, ServiceManager.USER_ID);
+        }
         return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
     }
 
-    private static void setPrimaryClip(Method method, IInterface manager, ClipData clipData)
+    private static void setPrimaryClip(Method method, boolean alternativeMethod, IInterface manager, ClipData clipData)
             throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME);
+        } else if (alternativeMethod) {
+            method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, null, ServiceManager.USER_ID);
         } else {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
         }
@@ -61,7 +80,7 @@ public class ClipboardManager {
     public CharSequence getText() {
         try {
             Method method = getGetPrimaryClipMethod();
-            ClipData clipData = getPrimaryClip(method, manager);
+            ClipData clipData = getPrimaryClip(method, alternativeGetMethod, manager);
             if (clipData == null || clipData.getItemCount() == 0) {
                 return null;
             }
@@ -76,7 +95,7 @@ public class ClipboardManager {
         try {
             Method method = getSetPrimaryClipMethod();
             ClipData clipData = ClipData.newPlainText(null, text);
-            setPrimaryClip(method, manager, clipData);
+            setPrimaryClip(method, alternativeSetMethod, manager, clipData);
             return true;
         } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
             Ln.e("Could not invoke method", e);
@@ -84,13 +103,14 @@ public class ClipboardManager {
         }
     }
 
-    private static void addPrimaryClipChangedListener(Method method, IInterface manager, IOnPrimaryClipChangedListener listener)
-            throws InvocationTargetException, IllegalAccessException {
+    private static void addPrimaryClipChangedListener(Method method, boolean alternativeMethod, IInterface manager,
+            IOnPrimaryClipChangedListener listener) throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             method.invoke(manager, listener, ServiceManager.PACKAGE_NAME);
-        } else {
+        } else if (alternativeMethod) {
+            method.invoke(manager, listener, ServiceManager.PACKAGE_NAME, null, ServiceManager.USER_ID);
+        } else
             method.invoke(manager, listener, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
-        }
     }
 
     private Method getAddPrimaryClipChangedListener() throws NoSuchMethodException {
@@ -99,8 +119,14 @@ public class ClipboardManager {
                 addPrimaryClipChangedListener = manager.getClass()
                         .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class);
             } else {
-                addPrimaryClipChangedListener = manager.getClass()
-                        .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, int.class);
+                try {
+                    addPrimaryClipChangedListener = manager.getClass()
+                            .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    addPrimaryClipChangedListener = manager.getClass()
+                            .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, String.class, int.class);
+                    alternativeAddListenerMethod = true;
+                }
             }
         }
         return addPrimaryClipChangedListener;
@@ -109,7 +135,7 @@ public class ClipboardManager {
     public boolean addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener) {
         try {
             Method method = getAddPrimaryClipChangedListener();
-            addPrimaryClipChangedListener(method, manager, listener);
+            addPrimaryClipChangedListener(method, alternativeAddListenerMethod, manager, listener);
             return true;
         } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
             Ln.e("Could not invoke method", e);

EDIT: new binary:

  • scrcpy-server SHA-256: f5e633584164bbd1105e58dedfd7bb1262e6a8a75553ec674737b8e7315dd2b2

rom1v added a commit that referenced this issue Dec 20, 2022
A new "attributionTag" parameter has been added to the methods
getPrimaryClip(), setPrimaryClip() and addPrimaryClipChangedListener()
of IClipboard.aidl.

Refs <https://android.googlesource.com/platform/frameworks/base.git/+/0e3e509b3bf4d561c26d87213387a290dfd688e3%5E%21/>

Fixes #3497 <#3497>
@drothenberger
Copy link

Please test this new binary and confirm that it works.

It's working fine here on Pixel 7. Thanks!

@alex310110
Copy link

Confirmed to be working for Pixel 6 Pro as well. Thanks!

@rom1v
Copy link
Collaborator

rom1v commented Dec 21, 2022

Merged into dev: 82cb8ab (will be in the next release)

@GetOutOfMyBakery
Copy link

Confirmed on Pixel 4a on Mac 👍 Thanks for the update!

@rom1v rom1v closed this as completed in 82cb8ab Dec 22, 2022
@rom1v
Copy link
Collaborator

rom1v commented Dec 22, 2022

Fixed in v1.25.

@CholoTook
Copy link

I'm seeing this error with the default packages on Linux Mint 21.1 Vera. Should I pester them to update the package? Where should I do that? Many thanks,

@rom1v
Copy link
Collaborator

rom1v commented Jul 18, 2023

Uninstall the package and install the latest version manually: https://github.com/Genymobile/scrcpy/blob/master/doc/linux.md#latest-version

@CholoTook
Copy link

Great, working. I'm just wondering when the deb / flatpak will be updated :-/

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

8 participants