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

Android 16 Preview 1 cannot hear the audio output #5698

Closed
hannasun opened this issue Dec 23, 2024 · 7 comments
Closed

Android 16 Preview 1 cannot hear the audio output #5698

hannasun opened this issue Dec 23, 2024 · 7 comments

Comments

@hannasun
Copy link

hannasun commented Dec 23, 2024

Environment

  • OS: [Windows]
  • Scrcpy version: [ 3.1]
  • Installation method: [Windows release]
  • Device model: google Pixel 6 Pro
  • Android version: [Android 15](Flashed Android 16 preview 1 ROM)

Describe the bug

When I opened the scrcpy, the cmd line tool shown this error and I cannot hear the audio from the device.
[server] INFO: Device: [Google] google Pixel 6 Pro (Android 15)
[server] ERROR: Exception on thread Thread[audio-encoder,5,main]
java.lang.UnsupportedOperationException: Cannot create AudioRecord
at android.media.AudioRecord$Builder.build(AudioRecord.java:1059)
at com.genymobile.scrcpy.FakeContext$$ExternalSyntheticApiModelOutline0.m(D8$$SyntheticClass:0)
at com.genymobile.scrcpy.audio.AudioDirectCapture.createAudioRecord(AudioDirectCapture.java:65)
at com.genymobile.scrcpy.audio.AudioDirectCapture.startRecording(AudioDirectCapture.java:108)
at com.genymobile.scrcpy.audio.AudioDirectCapture.start(AudioDirectCapture.java:137)
at com.genymobile.scrcpy.audio.AudioEncoder.encode(AudioEncoder.java:204)
at com.genymobile.scrcpy.audio.AudioEncoder.lambda$start$0$com-genymobile-scrcpy-audio-AudioEncoder(AudioEncoder.java:133)
at com.genymobile.scrcpy.audio.AudioEncoder$$ExternalSyntheticLambda3.run(D8$$SyntheticClass:0)
at java.lang.Thread.run(Thread.java:1117)
INFO: Renderer: direct3d
WARN: Demuxer 'audio': stream explicitly disabled by the device
INFO: Texture: 1440x3120

I tried on this Android 15 before, it can work before, but after I upgraded to Android 16 preview 1, it threw the exception from the log.It looks like the security issue cause the failure. Could you please help to check and provide a solution to it? Thanks a lot.
log:

2-23 10:52:37.482   938  5369 E AudioFlinger: Function: createRecord Line: 2485 Failed result (Status(-1, EX_SECURITY): 'static BinderResult<ValidatedAttributionSourceState> com::android::media::permission::ValidatedAttributionSourceState::createFromTrustedUidNoPackage(AttributionSourceState, const IPermissionProvider &): invalid attr AttributionSourceState{pid: 9959, uid: 2000, deviceId: 0, packageName: com.android.shell, attributionTag: (null), token: binder:0xb400007a2acbc4f0, renouncedPermissions: (null), next: []}')
12-23 10:52:37.482  9959  9974 E AudioRecord: createRecord_l(0): AudioFlinger could not create record track, status: -1
12-23 10:52:37.482  1517  3466 D DisplayManagerService: Virtual Display: creating DisplayDevice with VirtualDisplayAdapter
12-23 10:52:37.483  1517  3466 I DisplayDeviceRepository: Display device added: DisplayDeviceInfo{"scrcpy": uniqueId="virtual:com.android.shell,2000,scrcpy,1", 1440 x 3120, modeId 6, renderFrameRate 60.0, hasArrSupport false, defaultModeId 6, userPreferredModeId -1, supportedModes [{id=6, width=1440, height=3120, fps=60.0, vsync=60.0, synthetic=false, alternativeRefreshRates=[], supportedHdrTypes=[]}], colorMode 0, supportedColorModes [0], hdrCapabilities null, isForceSdr false, allmSupported false, gameContentTypeSupported false, density 1, 1.0 x 1.0 dpi, appVsyncOff 0, presDeadline 16666666, touch NONE, rotation 0, type VIRTUAL, deviceProductInfo null, state ON, committedState UNKNOWN, owner com.android.shell (uid 2000), frameRateOverride , brightnessMinimum 0.0, brightnessMaximum 0.0, brightnessDefault 0.0, hdrSdrRatio NaN, FLAG_PRIVATE, installOrientation 0, displayShape DisplayShape{ spec=2091232517 displayWidth=1440 displayHeight=3120 physicalPixelDisplaySizeRatio=1.0 rotation=0 offsetX=0 offsetY=0 scale=1.0}}
12-23 10:52:37.484  9959  9974 E AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1.
12-23 10:52:37.484  9970  9970 D nativeloader: InitDefaultPublicLibraries for_preload=1: libandroid.so:libaaudio.so:libamidi.so:libbinder_ndk.so:libc.so:libcamera2ndk.so:libdl.so:libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libicu.so:libicui18n.so:libicuuc.so:libjnigraphics.so:liblog.so:libmediandk.so:libm.so:libnativehelper.so:libnativewindow.so:libOpenMAXAL.so:libOpenSLES.so:libRS.so:libstdc++.so:libsync.so:libvulkan.so:libwebviewchromium_plat_support.so:libz.so
12-23 10:52:37.484  9959  9974 E android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.
12-23 10:52:37.485  1517  3466 I LogicalDisplayMapper: Applying layout: [{dispId: 0(ON), displayGroupName: , addr: {port=0, model=0x401ceccbbbeef1}, mThermalBrightnessThrottlingMapId: null, mRefreshRateZoneId: null, mLeadDisplayId: -1, mLeadDisplayAddress: null, mThermalRefreshRateThrottlingMapId: null, mPowerThrottlingMapId: null}], Previous layout: [{dispId: 0(ON), displayGroupName: , addr: {port=0, model=0x401ceccbbbeef1}, mThermalBrightnessThrottlingMapId: null, mRefreshRateZoneId: null, mLeadDisplayId: -1, mLeadDisplayAddress: null, mThermalRefreshRateThrottlingMapId: null, mPowerThrottlingMapId: null}]
12-23 10:52:37.485  1517  3466 I LogicalDisplayMapper: Setting new display group 0 for display 3, from previous group: null
--------- beginning of crash
12-23 10:52:37.485  9959  9974 E AndroidRuntime: FATAL EXCEPTION: audio-encoder
12-23 10:52:37.485  9959  9974 E AndroidRuntime: PID: 9959
12-23 10:52:37.485  9959  9974 E AndroidRuntime: java.lang.UnsupportedOperationException: Cannot create AudioRecord
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at android.media.AudioRecord$Builder.build(AudioRecord.java:1059)
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at com.genymobile.scrcpy.FakeContext$$ExternalSyntheticApiModelOutline0.m(D8$$SyntheticClass:0)
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at com.genymobile.scrcpy.audio.AudioDirectCapture.createAudioRecord(AudioDirectCapture.java:65)
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at com.genymobile.scrcpy.audio.AudioDirectCapture.startRecording(AudioDirectCapture.java:108)
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at com.genymobile.scrcpy.audio.AudioDirectCapture.start(AudioDirectCapture.java:137)
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at com.genymobile.scrcpy.audio.AudioEncoder.encode(AudioEncoder.java:204)
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at com.genymobile.scrcpy.audio.AudioEncoder.lambda$start$0$com-genymobile-scrcpy-audio-AudioEncoder(AudioEncoder.java:133)
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at com.genymobile.scrcpy.audio.AudioEncoder$$ExternalSyntheticLambda3.run(D8$$SyntheticClass:0)
12-23 10:52:37.485  9959  9974 E AndroidRuntime: 	at java.lang.Thread.run(Thread.java:1117)
12-23 10:52:37.485  9959  9974 E scrcpy  : Exception on thread Thread[audio-encoder,5,main]
12-23 10:52:37.485  9959  9974 E scrcpy  : java.lang.UnsupportedOperationException: Cannot create AudioRecord
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at android.media.AudioRecord$Builder.build(AudioRecord.java:1059)
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at com.genymobile.scrcpy.FakeContext$$ExternalSyntheticApiModelOutline0.m(D8$$SyntheticClass:0)
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at com.genymobile.scrcpy.audio.AudioDirectCapture.createAudioRecord(AudioDirectCapture.java:65)
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at com.genymobile.scrcpy.audio.AudioDirectCapture.startRecording(AudioDirectCapture.java:108)
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at com.genymobile.scrcpy.audio.AudioDirectCapture.start(AudioDirectCapture.java:137)
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at com.genymobile.scrcpy.audio.AudioEncoder.encode(AudioEncoder.java:204)
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at com.genymobile.scrcpy.audio.AudioEncoder.lambda$start$0$com-genymobile-scrcpy-audio-AudioEncoder(AudioEncoder.java:133)
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at com.genymobile.scrcpy.audio.AudioEncoder$$ExternalSyntheticLambda3.run(D8$$SyntheticClass:0)
12-23 10:52:37.485  9959  9974 E scrcpy  : 	at java.lang.Thread.run(Thread.java:1117)
@hannasun
Copy link
Author

Uploaded the complete log
audio.log

@yume-chan
Copy link
Contributor

See #5693

12-23 10:52:37.482 938 5369 E AudioFlinger: Function: createRecord Line: 2485 Failed result (Status(-1, EX_SECURITY): 'static BinderResult com::android::media::permission::ValidatedAttributionSourceState::createFromTrustedUidNoPackage(AttributionSourceState, const IPermissionProvider &): invalid attr AttributionSourceState{pid: 9959, uid: 2000, deviceId: 0, packageName: com.android.shell, attributionTag: (null), token: binder:0xb400007a2acbc4f0, renouncedPermissions: (null), next: []}')

https://cs.android.com/android/platform/superproject/main/+/main:frameworks/av/services/audiopolicy/permission/NativePermissionController.cpp;l=133-136;drc=b4d6320e2ae398b36f0aaafb2ecd83609d2d99af

It needs packageName to be shell. Please try scrcpy-server.zip

Diff
diff --git a/server/src/main/java/com/genymobile/scrcpy/FakeContext.java b/server/src/main/java/com/genymobile/scrcpy/FakeContext.java
index 2b83e397..22fc6d49 100644
--- a/server/src/main/java/com/genymobile/scrcpy/FakeContext.java
+++ b/server/src/main/java/com/genymobile/scrcpy/FakeContext.java
@@ -72,7 +72,7 @@ public final class FakeContext extends ContextWrapper {
     @Override
     public AttributionSource getAttributionSource() {
         AttributionSource.Builder builder = new AttributionSource.Builder(Process.SHELL_UID);
-        builder.setPackageName(PACKAGE_NAME);
+        builder.setPackageName("shell");
         return builder.build();
     }
 

@hannasun
Copy link
Author

@yume-chan Thanks a lot. It can work now.

@rom1v rom1v reopened this Dec 23, 2024
@rom1v
Copy link
Collaborator

rom1v commented Dec 23, 2024

Thank you 👍

Do you think we can change the package name to shell for everything?

diff --git server/src/main/java/com/genymobile/scrcpy/FakeContext.java server/src/main/java/com/genymobile/scrcpy/FakeContext.java
index 2b83e3972..6a8a2b6f6 100644
--- server/src/main/java/com/genymobile/scrcpy/FakeContext.java
+++ server/src/main/java/com/genymobile/scrcpy/FakeContext.java
@@ -13,7 +13,7 @@ import android.os.Process;
 
 public final class FakeContext extends ContextWrapper {
 
-    public static final String PACKAGE_NAME = "com.android.shell";
+    public static final String PACKAGE_NAME = "shell";
     public static final int ROOT_UID = 0; // Like android.os.Process.ROOT_UID, but before API 29
 
     private static final FakeContext INSTANCE = new FakeContext();

@yume-chan
Copy link
Contributor

Do you think we can change the package name to shell for everything?

No. Other PackageManager based permission checks must use com.android.shell, for example with --new-display:

> ./scrcpy -s 192.168.50.101:34699 --new-display
scrcpy 3.1 <https://github.com/Genymobile/scrcpy>
INFO: ADB device found:
INFO:           (usb)  73294bba                        device  M2011K2C
INFO:     --> (tcpip)  192.168.50.101:34699            device  23117RK66C
D:\dev\yume-chan\scrcpy-devcontainer\scrcpy\server\build\o...file pushed, 0 skipped. 102.9 MB/s (90988 bytes in 0.001s)
[server] INFO: Device: [Xiaomi] Redmi 23117RK66C (Android 14)
INFO: Renderer: direct3d
INFO: Texture: 1440x3200
[server] ERROR: Could not create display
java.lang.SecurityException: packageName must match the calling uid
        at android.os.Parcel.createExceptionOrNull(Parcel.java:3057)
        at android.os.Parcel.createException(Parcel.java:3041)
        at android.os.Parcel.readException(Parcel.java:3024)
        at android.os.Parcel.readException(Parcel.java:2966)
        at android.hardware.display.IDisplayManager$Stub$Proxy.createVirtualDisplay(IDisplayManager.java:1425)
        at android.hardware.display.DisplayManagerGlobal.createVirtualDisplay(DisplayManagerGlobal.java:643)
        at android.hardware.display.DisplayManager.createVirtualDisplay(DisplayManager.java:1176)
        at android.hardware.display.DisplayManager.createVirtualDisplay(DisplayManager.java:1137)
        at android.hardware.display.DisplayManager.createVirtualDisplay(DisplayManager.java:1085)
        at android.hardware.display.DisplayManager.createVirtualDisplay(DisplayManager.java:1025)
        at com.genymobile.scrcpy.wrappers.DisplayManager.createNewVirtualDisplay(DisplayManager.java:164)
        at com.genymobile.scrcpy.video.NewDisplayCapture.startNew(NewDisplayCapture.java:190)
        at com.genymobile.scrcpy.video.NewDisplayCapture.start(NewDisplayCapture.java:211)
        at com.genymobile.scrcpy.video.SurfaceEncoder.streamCapture(SurfaceEncoder.java:95)
        at com.genymobile.scrcpy.video.SurfaceEncoder.lambda$start$0$com-genymobile-scrcpy-video-SurfaceEncoder(SurfaceEncoder.java:296)
        at com.genymobile.scrcpy.video.SurfaceEncoder$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
        at java.lang.Thread.run(Thread.java:1012)
Caused by: android.os.RemoteException: Remote stack trace:
        at com.android.server.display.DisplayManagerService.createVirtualDisplayInternal(DisplayManagerService.java:1463)
        at com.android.server.display.DisplayManagerService.-$$Nest$mcreateVirtualDisplayInternal(Unknown Source:0)
        at com.android.server.display.DisplayManagerService$BinderService.createVirtualDisplay(DisplayManagerService.java:3859)
        at android.hardware.display.IDisplayManager$Stub.onTransact(IDisplayManager.java:730)
        at com.android.server.display.DisplayManagerService$BinderService.onTransact(DisplayManagerService.java:4445)

[server] ERROR: Exception on thread Thread[video,5,main]
java.lang.AssertionError: Could not create display
        at com.genymobile.scrcpy.video.NewDisplayCapture.startNew(NewDisplayCapture.java:197)
        at com.genymobile.scrcpy.video.NewDisplayCapture.start(NewDisplayCapture.java:211)
        at com.genymobile.scrcpy.video.SurfaceEncoder.streamCapture(SurfaceEncoder.java:95)
        at com.genymobile.scrcpy.video.SurfaceEncoder.lambda$start$0$com-genymobile-scrcpy-video-SurfaceEncoder(SurfaceEncoder.java:296)
        at com.genymobile.scrcpy.video.SurfaceEncoder$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
        at java.lang.Thread.run(Thread.java:1012)
ERROR: Demuxer 'audio': stream disabled due to connection error
WARN: Device disconnected

I didn't investigate why this check uses shell. shell is a user name, not a package name. Maybe this code path is only intended to be used internally.

To my knowledge, Context.getAttributionSource is only used in creating AudioRecord. I quickly tested changing it to shell on Android 13 and 14, and everything seems to continue to work. If it breaks something, we can create another fake Context with packageName equals to shell when creating AudioRecord.

@rom1v
Copy link
Collaborator

rom1v commented Dec 23, 2024

@yume-chan I created this commit under your name: 330a9b1. Will merge it soon.

@rom1v
Copy link
Collaborator

rom1v commented Dec 23, 2024

Merged: c27d116

@rom1v rom1v closed this as completed Dec 23, 2024
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

3 participants