hypfvieh / bluez-dbus

bluetooth library for linux OSes using DBus and bluez (http://www.bluez.org/).
MIT License
68 stars 20 forks source link

File descriptors in method returns #52

Closed raidenbeans closed 3 years ago

raidenbeans commented 3 years ago

Hi, I am not sure if this is a bug with the library or a mistake on my part. I am implementing a bluetooth A2DP Sink. A call to MediaTransport1#Acquire is made and the call is successful, however, the reply gives a null pointer exception because no file descriptors were obtained. I can see through the dbus-monitor command that a file descriptor and two ints are returned (as should happen).

Please let me know if this is an error on my part or a bug, thank you

example code:



public static void main(String[] args) {
    // obtain device manager, register media endpoints etc. I am 100% certain this code is correct, but it can be provided if needed for reproduction
    // deviceManager#registerPropertyHandler(new MediaPropertiesChangedHandler());
}

private class MediaPropertiesChangedHandler extends AbstractPropertiesChangedHandler {

    @Override
    public void handle(PropertiesChanged properties) {
        String path = properties.getPath();
        String interfaceName = properties.getInterfaceName();

        if (path.equals(transportPath) && interfaceName.equals("org.bluez.MediaTransport1")) {
            String state = (String) propertiesChanged.get("State").getValue();
            if (state != null && state.equalsIgnoreCase("pending")) {
                onStartStreaming();
            }
        }
    }
}

public void onStartStreaming() {
    MediaTransport1 mediaTransport = DbusHelper.getRemoteObject(deviceManager#getDbusConnection(), transportPath, MediaTransport1.class);
    mediaTransport.Acquire(); // here an exception is thrown:
    // Exception in thread "DBus Worker Thread-1" java.lang.NullPointerException: Cannot invoke "java.util.List.get(int)" because "this.filedescriptors" is null
    //     at org.freedesktop.dbus.messages.Message.extractOne(Message.java:993)
    //     at org.freedesktop.dbus.messages.Message.extract(Message.java:1156)
    //     at org.freedesktop.dbus.messages.Message.extract(Message.java:1133)
    //     at org.freedesktop.dbus.messages.Message.getParameters(Message.java:1264)
    //     at org.freedesktop.dbus.DBusAsyncReply.checkReply(DBusAsyncReply.java:74)
    //     at org.freedesktop.dbus.DBusAsyncReply.hasReply(DBusAsyncReply.java:95)
    //     at onStartStreaming(line number corresponds to the Acquire call)
    //     at org.freedesktop.dbus.connections.AbstractConnection$3.run(AbstractConnection.java:911)
    //     at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    //     at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    //     at java.base/java.lang.Thread.run(Thread.java:832)

}`
hypfvieh commented 3 years ago

Did you add dbus-java-nativefd to your project? Otherwise filedescriptors will not be supported by dbus-java and therefore not supported in bluez-dbus.

Also a complete sample showing this issue would be helpful.

raidenbeans commented 3 years ago

I added nativefd to my project and the issue was fixed. I guess reading the readme might be important, oops. Thank you very much.

However, I noticed that the ThreeTuple class does not have a constructor that takes three arguments, which caused a reflection error:

Exception in thread "DBus Worker Thread-3" org.freedesktop.dbus.exceptions.DBusExecutionException: wrong number of arguments
    at org.freedesktop.dbus.RemoteInvocationHandler.executeRemoteMethod(RemoteInvocationHandler.java:171)
    at org.freedesktop.dbus.RemoteInvocationhandler.invoke(RemoteInvocationHandler.java:228)
    at com.sun.proxy.$Acquire(Unknown Source)
    at (my method call to MediaTransport1#Acquire)

I fixed this by adding a constructor the ThreeTuple class:


import org.freedesktop.dbus.Tuple;
import org.freedesktop.dbus.annotations.Position;

public class ThreeTuple<A, B, C> extends Tuple {

    @Position(0)
    private A firstValue;
    @Position(1)
    private B secondValue;
    @Position(2)
    private C thirdValue;

    public ThreeTuple(A firstValue, B secondValue, C thirdValue) {
        this.firstValue = firstValue;
        this.secondValue = secondValue;
        this.thirdValue = thirdValue;
    }

    public A getFirstValue() {
        return firstValue;
    }

    public void setFirstValue(A _firstValue) {
        firstValue = _firstValue;
    }

    public B getSecondValue() {
        return secondValue;
    }

    public void setSecondValue(B _secondValue) {
        secondValue = _secondValue;
    }

    public C getThirdValue() {
        return thirdValue;
    }

    public void setThirdValue(C _thirdValue) {
        thirdValue = _thirdValue;
    }

}
hypfvieh commented 3 years ago

I added the missing constructors to TwoTuple and ThreeTuple. I'll close this ticket as the main issue (missing dependency) is fixed.