Open estan opened 8 years ago
Some more info: The phone is running Android 5.1.1 Lollipop, and I'm using client version 2.3.3.
Hey, can you do an adb logcat when connecting to see if there's any errors there ?
Here is the output from Linux/prebuilt/adb logcat
when I
During 4, the "Connecting to '127.0.0.1'... (Attempt 1/3)" and "Connected, loading first frame..." messages were looping fast in the black window.
Looking at the log, I can't see anything suspicious. Maybe you can see something? I only see a few messages mentioning "bbq" or "BBQ".
The logcat
output when not running the client, and doing just:
[estan@pyret android-sdk-linux]$ telnet 127.0.0.1 9876
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.
[estan@pyret android-sdk-linux]$
doesn't contain anything interesting either I think. Just a couple of
V/WindowManager( 860): Adding window Window{d302bf2 u0 android/com.android.internal.app.ResolverActivity} at 8 of 13 (after Window{c227200 u0 org.bbqdroid.bbqscreen/org.bbqdroid.bbqscreen.BBQScreenPreferencesActivity})
messages.
The output from adb forward --list
is:
[estan@pyret bbqscreen_client]$ Linux/prebuilts/adb forward --list
Linux/prebuilts/adb: /usr/lib32/libcrypto.so.1.0.0: no version information available (required by Linux/prebuilts/adb)
YT9112CUE1 tcp:9876 tcp:9876
[estan@pyret bbqscreen_client]$
So the forwarding is correctly set up.
I made an interesting find. I tried starting the USB service interactively from an adb shell, and got this:
shell@D5803:/ $ /data/local/tmp/bbqscreen -s 50 -720 -q 4500 -i
CANNOT LINK EXECUTABLE: cannot locate symbol "_ZN7android11AudioSourceC1E14audio_source_tjj" referenced by "/data/local/tmp/bbqscreen"...
So I'm suspecting the final command that the client tries to run when you press "Start USB Service" actually fails because of this. Any idea why it is missing that symbol?
I also realized I have to run BBQScreenClient2
with the Linux
directory as the current working directory, otherwise the adb
command is not found since the relative path prebuilt/adb
is used. So I think the adb
executable was not found and errors because of this are strangely supressed.
When running from within the Linux
directory, I finally get output in the log window. It's the same error as above:
CANNOT LINK EXECUTABLE: cannot locate symbol "_ZN7android11AudioSourceC1E14audio_source_tjj" referenced by "/data/local/tmp/bbqscreen"...
Repeated 20 times before it fails with an error dialog.
So the problem really seems to be that symbol that the bbqscreen
process is missing.
The missing symbol seems to be part of libmedia.so
, which is not part of the public API of NDK. So perhaps it is wrong of bbqscreen
to link against this? I'm guessing that the libmedia.so
that my device has is slightly different from the one you linked against when making the app, or maybe that root privileges are required for it to be accessible? (Or maybe the app needs more permissions for this to work on a non-rooted phone?).
A last update, which I think should help you fix this: Using nm
from the Android NDK on the various libmedia*.so
files I have in /system/lib
, I found that on my device the missing symbol is actually part of libmediaplayerservice.so
, not libmedia.so
:
[estan@pyret android-sdk-linux]$ ./platform-tools/adb pull /system/lib/libmediaplayerservice.so
2536 KB/s (582956 bytes in 0.224s)
and then:
[estan@pyret android-ndk-r10e]$ ./toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/arm-linux-androideabi/bin/nm -D ~/Blandat/android-sdk-linux/libmediaplayerservice.so | grep audio_source_tjji
U _ZN7android11AudioSourceC1E14audio_source_tjji
So I think you need to add -lmediaplayerservice
to the link command line when you link bbqscreen
for my device (or perhaps when you link the ffmpeg library).
Sorry. I misread the output from nm
. The 'U' means it's undefined, so libmediaplayerservice.so
is just a user of that symbol not the provider. But I finally found which library has it:
[estan@pyret phone_libs]$ ~/Nedladdat/android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/bin/nm -D libstagefright.so | grep tjji
00072590 T _ZN7android11AudioSourceC1E14audio_source_tjji
000722c0 T _ZN7android11AudioSourceC2E14audio_source_tjji
[estan@pyret phone_libs]$
So on my device, it's libstagefright.so
which has that symbol ('T' means it's in the text (code) section). So you probably need to add -lstagefright
to your link line.
And I'm wrong again. Running ndk-depends
on the bbqscreen
executable, I see that it's actually linked against libstagefright.so
, so that's not the problem. The problem is simply that in the version of libstagefright.so
that you linked to, the function has the signature
android::AudioSource::AudioSource(audio_source_t, unsigned int, unsigned int)
(corresponding to the mangled name _ZN7android11AudioSourceC1E14audio_source_tjj
), while in the version I have on my device, it's
android::AudioSource::AudioSource(audio_source_t, unsigned int, unsigned int, int)
(corresponding to the mangled name _ZN7android11AudioSourceC1E14audio_source_tjji
, note the extra 'i' on the end!). This is the reason the symbol is not found.
In the meantime I've come up with a workaround. It's quite ugly, but works.
What I did was to write a shim shared library containing an AudioSource
constructor with the signature that bbqscreen
expects. The shim constructor then loads the real constructor using dlsym(RTLD_NEXT, ...)
and calls it, passing a 0 for the fourth argument (I only hoped this would work, and it does). This shim library is then injected into the bbqscreen
process using LD_PRELOAD
.
The full shim library is:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <dlfcn.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE // For RTLD_NEXT
#endif
typedef enum {
AUDIO_SOURCE_DEFAULT = 0,
AUDIO_SOURCE_MIC = 1,
AUDIO_SOURCE_VOICE_UPLINK = 2,
AUDIO_SOURCE_VOICE_DOWNLINK = 3,
AUDIO_SOURCE_VOICE_CALL = 4,
AUDIO_SOURCE_CAMCORDER = 5,
AUDIO_SOURCE_VOICE_RECOGNITION = 6,
AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
AUDIO_SOURCE_CNT,
AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1,
} audio_source_t;
namespace android {
struct AudioSource {
AudioSource(
audio_source_t inputSource,
uint32_t sampleRate,
uint32_t channels = 1);
};
AudioSource::AudioSource(
audio_source_t inputSource,
uint32_t sampleRate,
uint32_t channels) {
typedef void (AudioSource::*Original)(audio_source_t, uint32_t, uint32_t, int);
static Original originalMethod = 0;
if (originalMethod == 0) {
// Save a pointer to the original constructor in originalMethod.
void *tmpPtr = dlsym(RTLD_NEXT, "_ZN7android11AudioSourceC1E14audio_source_tjji");
memcpy(&originalMethod, &tmpPtr, sizeof(void *));
}
// Call the original constructor with last argument hardcoded to 0.
printf("Calling original (originalMethod=%p)\n", originalMethod);
(this->*originalMethod)(inputSource, sampleRate, channels, 0);
}
} // namespace android
which I compiled with:
[estan@pyret Linux]$ ~/android-toolchain/bin/arm-linux-androideabi-g++ -shared -fPIC -ldl -o shim.so shim.cpp
I then updated mainwindow.cpp
in the client sources to first adb push
the shim library to the temp dir, and made sure that LD_PRELOAD
is set to its path when the client runs bbqscreen
using adb shell
:
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 3de035c..ca12dd2 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -447,8 +447,17 @@ void MainWindow::startUsbService()
return;
}
+ // Push shim library.
+ args.clear();
+ args << "push";
+ args << QDir(QCoreApplication::applicationDirPath()).absolutePath() + "/shim.so";
+ args << "/data/local/tmp/shim.so";
+ QProcess* pushShimProc = runAdb(args);
+ pushShimProc->waitForFinished();
+
args.clear();
args << "shell";
+ args << "export LD_PRELOAD=/data/local/tmp/shim.so ; ";
args << "/data/local/tmp/bbqscreen";
args << "-s";
args << "50";
The bbqscreen
process can now start and the client connects successfully:
While this workaround works, I wouldn't recommend it. As it seems Sony does not provide the sources for their (I think) modified libstagefright, I'm not sure what passing in 0 like that does. At least I haven't been able to find an AudioSource
constructor with the signature that my library has anywhere in the public Android sources.
The right fix is to not rely on libstagefright. It's not public API and not guaranteed to be stable across devices.
I'm keeping a fork here with my workaround until this is fixed, in case someone else has an Xperia Z3.
Hey! Thanks for the investigation and the workaround! I'll look into that and issue an official update soon.
:+1:
Hi,
I purchased the app hoping to use it on my non-rooted Sony Ericsson Xperia Z3 Compact. I'm running the client on an up-to-date Arch Linux.
Here's what I did:
master
Git branch.Linux/prebuilts/adb devices
shows my device.)Linux/BBQScreenClient2
.The result is that the black screen is shown, but the text message switches between
very very quickly, and "Connecting to "127.0.0.1"" is repeated in the terminal.
While the client is running and the USB service is running, the output from
netstat -tulpn
is:So it seems the forwarding of TCP port 9876 that the client sets up using
adb
is working. However, when I triedtelnet 127.0.0.1 9876
, the connection is established, buttelnet
is immediately disconnected again:I guess this is what's happening for
BBQScreenClient2
as well.Any idea what is going on? I would love to get this working.
The debug log window in the client shows nothing while this is happening. I've also tried the Legacy mode with same results.
Please let me know if you need more info or want me to try something, as I have some experience with Qt programming.
As a side note, I'm getting a warning about missing version information on
libcrypto.so.1.0.0
when running the prebuiltadb
:But I don't think that is related to this problem, since the device is found and the forwarding seems to work. Running
ldd
on theadb
executable gives:To double check, I also hacked the
MainWindow::runAdb
function to use anotheradb
that I have, which does not give this warning, and got the same problem as described in the beginning (immediate disconnect while trying to load the first frame).Thanks in advance.