Skip to content

Commit

Permalink
Add SetRequiredSurfaces dbus message sniffing
Browse files Browse the repository at this point in the history
This commit adds sniffing of NativeGUIClient::SetRequiredSurfaces dbus method calls. It allows to react to losing video/input focus when CMU changes the front surface (call, SMS/text message and so on).
  • Loading branch information
mishaaq committed Sep 25, 2017
1 parent 820bcbe commit e05db16
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 16 deletions.
43 changes: 37 additions & 6 deletions mazda/callbacks.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include "callbacks.h"
#include "outputs.h"
#include "glib_utils.h"
#include "audio.h"
#include "main.h"
#include "bt/mzd_bluetooth.h"
#include <dbus/dbus-protocol.h>

#include "json/json.hpp"
using json = nlohmann::json;
Expand Down Expand Up @@ -142,14 +142,34 @@ void MazdaEventCallbacks::AudioFocusHappend(int chan, bool hasFocus) {
logd("Sent channel %i HU_PROTOCOL_MESSAGE::AudioFocusResponse %s\n", chan, HU::AudioFocusResponse::AUDIO_FOCUS_STATE_Name(response.focus_type()).c_str());
}

class SetRequiredSurfacesHandler : public DBus::Callback_Base<bool, const DBus::Message&> {
VideoManagerClient *videoManagerClient;

public:
SetRequiredSurfacesHandler(VideoManagerClient *ptr) : videoManagerClient(ptr) {}

bool call(const DBus::Message& param) const override {
DBus::MessageIter ri = param.reader();
std::string surfaces;
ri >> surfaces;
int16_t bFadeOpera;
ri >> bFadeOpera;
return videoManagerClient->requiredSurfacesCallback(surfaces, bFadeOpera);
}
};

VideoManagerClient::VideoManagerClient(MazdaEventCallbacks& callbacks, DBus::Connection& hmiBus)
: DBus::ObjectProxy(hmiBus, "/com/jci/bucpsa", "com.jci.bucpsa"), guiClient(hmiBus), callbacks(callbacks)
: DBus::ObjectProxy(hmiBus, "/com/jci/bucpsa", "com.jci.bucpsa"), guiClient(hmiBus), bthfClient(*this, hmiBus), callbacks(callbacks)
{
uint32_t currentDisplayMode;
int32_t returnValue;
// check if backup camera is not visible at the moment and get output only when not
GetDisplayMode(currentDisplayMode, returnValue);
allowedToGetFocus = !(bool)currentDisplayMode;
hmiBus.add_match("type='method_call',path='/com/jci/nativeguictrl',member='SetRequiredSurfaces'");
DBus::MessageSlot slot;
slot = new SetRequiredSurfacesHandler(this);
hmiBus.add_filter(slot);
}

VideoManagerClient::~VideoManagerClient() {
Expand Down Expand Up @@ -216,9 +236,12 @@ void VideoManagerClient::DisplayMode(const uint32_t &currentDisplayMode)
}
}

MazdaCommandServerCallbacks::MazdaCommandServerCallbacks()
{

bool VideoManagerClient::requiredSurfacesCallback(const std::string &surfaces, const int16_t &bFadeOpera) {
// handle callback
std::stringstream surfacesDebug;
std::copy(surfaces.begin(), surfaces.end(), std::ostream_iterator<int>(surfacesDebug, " "));
logd("CMU switches surfaces: %s", surfacesDebug.str().c_str());
return true;
}

bool MazdaCommandServerCallbacks::IsConnected() const
Expand Down Expand Up @@ -460,4 +483,12 @@ void AudioManagerClient::Notify(const std::string &signalName, const std::string
}
}


void BTHFClient::CallStatus(const uint32_t &bthfstate, const uint32_t &call1status, const uint32_t &call2status,
const ::DBus::Struct<std::vector<uint8_t> > &call1Number,
const ::DBus::Struct<std::vector<uint8_t> > &call2Number) {
if ((bool)bthfstate) {
videoMgrClient.releaseVideoFocus(VIDEO_FOCUS_REQUESTOR::BTHF);
} else {
videoMgrClient.requestVideoFocus(VIDEO_FOCUS_REQUESTOR::BTHF);
}
}
34 changes: 32 additions & 2 deletions mazda/callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,32 @@ class NativeGUICtrlClient : public com::jci::nativeguictrl_proxy,
}
};

class BTHFClient : public com::jci::bthf_proxy,
public DBus::ObjectProxy {
VideoManagerClient& videoMgrClient;

public:
BTHFClient(VideoManagerClient &videoMgrClient, DBus::Connection &connection)
: DBus::ObjectProxy(connection, "/com/jci/bthf", "com.jci.bthf"), videoMgrClient(videoMgrClient)
{
}
virtual void CallStatus(const uint32_t& bthfstate, const uint32_t& call1status, const uint32_t& call2status, const ::DBus::Struct< std::vector< uint8_t > >& call1Number, const ::DBus::Struct< std::vector< uint8_t > >& call2Number) override;
virtual void BatteryIndicator(const uint32_t& minValue, const uint32_t& maxValue, const uint32_t& currentValue) override {}
virtual void SignalStrength(const uint32_t& minValue, const uint32_t& maxValue, const uint32_t& currentValue) override {}
virtual void RoamIndicator(const uint32_t& value) override {}
virtual void NewServiceIndicator(const bool& value) override {}
virtual void PhoneChargeIndicator(const uint32_t& value) override {}
virtual void SmsPresentIndicator(const bool& value) override {}
virtual void VoiceMailIndicator(const bool& value) override {}
virtual void LowBatteryIndicator(const bool& value) override {}
virtual void BthfReadyStatus(const uint32_t& hftReady, const uint32_t& reasonCode) override {}
virtual void BthfBusyReason(const uint32_t& busyReason) override {}
virtual void MicStatus(const bool& isMicMuted) override {}
virtual void BargeinStatus(const bool& isBargeinActive) override {}
virtual void BthfSettingsResponse(const ::DBus::Struct< std::vector< uint8_t > >& callsettings) override {}
virtual void FailureReasonCodes(const uint32_t& errorType) override {}
};

class AudioManagerClient : public com::xsembedded::ServiceProvider_proxy,
public DBus::ObjectProxy
{
Expand Down Expand Up @@ -88,7 +114,8 @@ class AudioManagerClient : public com::xsembedded::ServiceProvider_proxy,
enum class VIDEO_FOCUS_REQUESTOR : u_int8_t {
HEADUNIT, // headunit (we) has requested video focus
ANDROID_AUTO, // AA phone app has requested video focus
BACKUP_CAMERA // CMU requested screen for backup camera
BACKUP_CAMERA, // CMU requested screen for backup camera
BTHF // CMU requested screen for Call app
};

class VideoManagerClient : public com::jci::bucpsa_proxy,
Expand All @@ -98,13 +125,16 @@ class VideoManagerClient : public com::jci::bucpsa_proxy,

MazdaEventCallbacks& callbacks;
NativeGUICtrlClient guiClient;
BTHFClient bthfClient;
public:
VideoManagerClient(MazdaEventCallbacks& callbacks, DBus::Connection &hmiBus);
~VideoManagerClient();

void requestVideoFocus(VIDEO_FOCUS_REQUESTOR requestor);
void releaseVideoFocus(VIDEO_FOCUS_REQUESTOR requestor);

bool requiredSurfacesCallback(const std::string &surfaces, const int16_t &bFadeOpera);

virtual void CommandResponse(const uint32_t& cmdResponse) override {}
virtual void DisplayMode(const uint32_t& currentDisplayMode) override;
virtual void ReverseStatusChanged(const int32_t& reverseStatus) override {}
Expand Down Expand Up @@ -150,7 +180,7 @@ class MazdaEventCallbacks : public IHUConnectionThreadEventCallbacks {
class MazdaCommandServerCallbacks : public ICommandServerCallbacks
{
public:
MazdaCommandServerCallbacks();
MazdaCommandServerCallbacks() = default;

MazdaEventCallbacks* eventCallbacks = nullptr;

Expand Down
8 changes: 0 additions & 8 deletions mazda/main.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <dbus/dbus.h>
#include <poll.h>
#include <inttypes.h>
#include <cmath>
#include <functional>
Expand All @@ -25,7 +18,6 @@
#include "nm/mzd_nightmode.h"
#include "gps/mzd_gps.h"

#include "audio.h"
#include "main.h"
#include "command_server.h"
#include "callbacks.h"
Expand Down

7 comments on commit e05db16

@Trevelopment
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey tested this, headunit runs up until you connect the phone then it crashes. Was late to work so didn't pick up the dumps but the headunit.log file ends like this:

W: /home/mazda/headunit/hu/hu_ssl.cpp:235: hu_handle_SSLHandshake : SSL_do_handshake() ret: 1
W: /home/mazda/headunit/hu/hu_ssl.cpp:261: hu_handle_SSLHandshake :   SET: iaap_state: 2 (hu_STATE_STARTED)
W: /home/mazda/headunit/hu/hu_aap.cpp:1132: hu_aap_start : Starting HU thread
Starting Android Auto...
Error: signal Segmentation fault context 0x7ed51e58 :
(0) 0x2ac51f58:GPS thread started... (dbus_connection_dispatch+0x34c)
(1) 0x2aeabc14:Nightmode service connection established.
 (g_main_context_dispatch+0x184)

so not much there, I don't know if you can get anything from that.
I am going to try tweaking it a little bit and see if I can get it working

@mishaaq
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, As I said I haven't tested it. I'm not a C++ guru also, so probably there is some stupid mistake in my code. In another commit I removed unnecessary BTHFClient stuff and added some more logging to narrow down the problem.

@lmagder
Copy link

@lmagder lmagder commented on e05db16 Sep 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really promising @mishaaq it seems like the DBus::Callback API does just what we need. I've never used the API before but I don't see any obvious C++ fail in the code. I'm going to try and debug more too as soon as I get a chance. Debugging on the car sucks though :(

@lmagder
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried hacking around a bunch here: lmagder@4ab38ce

I was able to log out the callbacks without it crashing and with no matcher specified. However I was only getting the "NameAcquired" signal and nothing else, which makes me think we are not registering the filter on the right connection or that it only sees messages traveling through the connection, like we can't filter stuff between two other processes.

@mishaaq
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lmagder regarding your "hacking" commit: I'm sure you need to call add_match before setting up filtering, because the D-BUS specification states that only messages with DESTINATION attribute explicitly set to your D-BUS service path will be delivered to your service without matching. Another thing: "SetRequiredSurfaces" is a D-BUS method, so you don't need to check for a signal with that name. When it comes to the lack of messages probably we need to conform to this thing: https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-routing-eavesdropping.

@lmagder
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mishaaq Thanks! I had it wrong. I assumed removing the match would show all the messages and I could filter in the callback for better debugging. Same reason why I was logging the signals. I need to try again then.

@mishaaq
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lmagder Probably matching against empty rule (add_match("")) should do the work. Alternatively need to add this "eavesdropping" thing.

Please sign in to comment.