Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 422c21c5 authored by Jeremy Wu's avatar Jeremy Wu Committed by Gerrit Code Review
Browse files

Merge "floss: notify hfp/a2dp audio status via forwarded fd" into main

parents c35be7ca 39bd62f6
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -410,13 +410,16 @@ class FlossMediaClient(BluetoothMediaCallbacks):
        return True

    @utils.glib_call(False)
    def start_audio_request(self):
    def start_audio_request(self, connection_listener):
        """Starts audio request.

        Args:
            connection_listener: The file descriptor to write 1 (u8) on audio connection.

        Returns:
            True on success, False otherwise.
        """
        self.proxy().StartAudioRequest()
        self.proxy().StartAudioRequest(connection_listener)
        return True

    @utils.glib_call(None)
@@ -432,28 +435,32 @@ class FlossMediaClient(BluetoothMediaCallbacks):
        return self.proxy().GetA2dpAudioStarted(address)

    @utils.glib_call(False)
    def stop_audio_request(self):
    def stop_audio_request(self, connection_listener):
        """Stops audio request.

        Args:
            connection_listener: The file descriptor to write 0 (u8) on audio connection.

        Returns:
            True on success, False otherwise.
        """
        self.proxy().StopAudioRequest()
        self.proxy().StopAudioRequest(connection_listener)
        return True

    @utils.glib_call(False)
    def start_sco_call(self, address, sco_offload, force_cvsd):
    def start_sco_call(self, address, sco_offload, disabled_codecs, connection_listener):
        """Starts the SCO call.

        Args:
            address: Device address to make SCO call.
            sco_offload: Whether SCO offload is enabled.
            force_cvsd: True to force the stack to use CVSD even if mSBC is supported.
            disabled_codecs: The disabled codecs in bitmask form. CVSD=1, MSBC=2, LC3=4.
            connection_listener: The file descriptor to write the codec id on audio connection.

        Returns:
            True on success, False otherwise.
        """
        self.proxy().StartScoCall(address, sco_offload, force_cvsd)
        self.proxy().StartScoCall(address, sco_offload, disabled_codecs, connection_listener)
        return True

    @utils.glib_call(None)
@@ -470,16 +477,17 @@ class FlossMediaClient(BluetoothMediaCallbacks):
        return self.proxy().GetHfpAudioStarted(address)

    @utils.glib_call(False)
    def stop_sco_call(self, address):
    def stop_sco_call(self, address, connection_listener):
        """Stops the SCO call.

        Args:
            address: Device address to stop SCO call.
            connection_listener: The file descriptor to write 0 (u8) on audio disconnection.

        Returns:
            True on success, False otherwise.
        """
        self.proxy().StopScoCall(address)
        self.proxy().StopScoCall(address, connection_listener)
        return True

    @utils.glib_call(None)
+5 −3
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ use num_traits::{FromPrimitive, ToPrimitive};

use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::fs::File;
use std::sync::Arc;

use btstack::bluetooth_qa::IBluetoothQACallback;
@@ -2742,7 +2743,7 @@ impl IBluetoothMedia for BluetoothMediaDBus {
    }

    #[dbus_method("StartAudioRequest")]
    fn start_audio_request(&mut self) -> bool {
    fn start_audio_request(&mut self, connection_listener: File) -> bool {
        dbus_generated!()
    }

@@ -2752,7 +2753,7 @@ impl IBluetoothMedia for BluetoothMediaDBus {
    }

    #[dbus_method("StopAudioRequest")]
    fn stop_audio_request(&mut self) {
    fn stop_audio_request(&mut self, connection_listener: File) {
        dbus_generated!()
    }

@@ -2762,6 +2763,7 @@ impl IBluetoothMedia for BluetoothMediaDBus {
        address: RawAddress,
        sco_offload: bool,
        disabled_codecs: HfpCodecBitId,
        connection_listener: File,
    ) -> bool {
        dbus_generated!()
    }
@@ -2772,7 +2774,7 @@ impl IBluetoothMedia for BluetoothMediaDBus {
    }

    #[dbus_method("StopScoCall")]
    fn stop_sco_call(&mut self, address: RawAddress) {
    fn stop_sco_call(&mut self, address: RawAddress, connection_listener: File) {
        dbus_generated!()
    }

+5 −3
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ use crate::dbus_arg::{DBusArg, DBusArgError, RefArgToRust};
use num_traits::{FromPrimitive, ToPrimitive};

use std::convert::{TryFrom, TryInto};
use std::fs::File;
use std::sync::Arc;

#[allow(dead_code)]
@@ -360,7 +361,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus {
    }

    #[dbus_method("StartAudioRequest")]
    fn start_audio_request(&mut self) -> bool {
    fn start_audio_request(&mut self, connection_listener: File) -> bool {
        dbus_generated!()
    }

@@ -370,7 +371,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus {
    }

    #[dbus_method("StopAudioRequest", DBusLog::Disable)]
    fn stop_audio_request(&mut self) {
    fn stop_audio_request(&mut self, connection_listener: File) {
        dbus_generated!()
    }

@@ -380,6 +381,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus {
        address: RawAddress,
        sco_offload: bool,
        disabled_codecs: HfpCodecBitId,
        connection_listener: File,
    ) -> bool {
        dbus_generated!()
    }
@@ -390,7 +392,7 @@ impl IBluetoothMedia for IBluetoothMediaDBus {
    }

    #[dbus_method("StopScoCall")]
    fn stop_sco_call(&mut self, address: RawAddress) {
    fn stop_sco_call(&mut self, address: RawAddress, connection_listener: File) {
        dbus_generated!()
    }

+75 −6
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ use itertools::Itertools;
use log::{debug, info, warn};
use std::collections::{HashMap, HashSet};
use std::convert::{TryFrom, TryInto};
use std::fs::File;
use std::io::Write;
use std::sync::Arc;
use std::sync::Mutex;

@@ -151,8 +153,8 @@ pub trait IBluetoothMedia {
    // Set the HFP speaker volume. Valid volume specified by the HFP spec should
    // be in the range of 0-15.
    fn set_hfp_volume(&mut self, volume: u8, address: RawAddress);
    fn start_audio_request(&mut self) -> bool;
    fn stop_audio_request(&mut self);
    fn start_audio_request(&mut self, connection_listener: File) -> bool;
    fn stop_audio_request(&mut self, connection_listener: File);

    /// Returns true iff A2DP audio has started.
    fn get_a2dp_audio_started(&mut self, address: RawAddress) -> bool;
@@ -169,8 +171,9 @@ pub trait IBluetoothMedia {
        address: RawAddress,
        sco_offload: bool,
        disabled_codecs: HfpCodecBitId,
        connection_listener: File,
    ) -> bool;
    fn stop_sco_call(&mut self, address: RawAddress);
    fn stop_sco_call(&mut self, address: RawAddress, connection_listener: File);

    /// Set the current playback status: e.g., playing, paused, stopped, etc. The method is a copy
    /// of the existing CRAS API, hence not following Floss API conventions.
@@ -492,6 +495,8 @@ pub struct BluetoothMedia {
    csis: Option<CsisClient>,
    csis_states: HashMap<RawAddress, BtCsisConnectionState>,
    is_le_audio_only_enabled: bool, // TODO: remove this once there is dual mode.
    hfp_audio_connection_listener: Option<File>,
    a2dp_audio_connection_listener: Option<File>,
}

impl BluetoothMedia {
@@ -557,6 +562,8 @@ impl BluetoothMedia {
            csis: None,
            csis_states: HashMap::new(),
            is_le_audio_only_enabled: false,
            hfp_audio_connection_listener: None,
            a2dp_audio_connection_listener: None,
        }
    }

@@ -638,6 +645,19 @@ impl BluetoothMedia {
        }
    }

    fn write_data_to_listener(&self, mut listener: File, data: Vec<u8>) {
        match listener.write(&data) {
            Ok(nwritten) => {
                if nwritten != data.len() {
                    warn!("Did not write full data into the event listener.");
                }
            }
            Err(e) => {
                warn!("Cannot write data into the event listener: {}", e);
            }
        }
    }

    pub fn set_adapter(&mut self, adapter: Arc<Mutex<Box<Bluetooth>>>) {
        self.adapter = Some(adapter);
    }
@@ -1227,11 +1247,13 @@ impl BluetoothMedia {
                match state {
                    BtavConnectionState::Connected => {
                        info!("[{}]: a2dp connected.", DisplayAddress(&addr));

                        self.a2dp_states.insert(addr, state);
                        self.add_connected_profile(addr, Profile::A2dpSink);
                    }
                    BtavConnectionState::Disconnected => {
                        info!("[{}]: a2dp disconnected.", DisplayAddress(&addr));

                        self.a2dp_states.remove(&addr);
                        self.a2dp_caps.remove(&addr);
                        self.a2dp_audio_state.remove(&addr);
@@ -1244,6 +1266,18 @@ impl BluetoothMedia {
            }
            A2dpCallbacks::AudioState(addr, state) => {
                info!("[{}]: a2dp audio state: {:?}", DisplayAddress(&addr), state);

                let started: u8 = match state {
                    BtavAudioState::Started => 1,
                    _ => 0,
                };

                if self.a2dp_audio_connection_listener.is_some() {
                    let listener = self.a2dp_audio_connection_listener.take().unwrap();
                    let data: Vec<u8> = vec![started];
                    self.write_data_to_listener(listener, data);
                }

                self.a2dp_audio_state.insert(addr, state);
            }
            A2dpCallbacks::AudioConfig(addr, _config, _local_caps, a2dp_caps) => {
@@ -1480,6 +1514,13 @@ impl BluetoothMedia {

                        self.hfp_audio_state.insert(addr, state);

                        if self.hfp_audio_connection_listener.is_some() {
                            let listener = self.hfp_audio_connection_listener.take().unwrap();
                            let codec = self.get_hfp_audio_final_codecs(addr);
                            let data: Vec<u8> = vec![codec];
                            self.write_data_to_listener(listener, data);
                        }

                        if self.should_insert_call_when_sco_start(addr) {
                            // This triggers a +CIEV command to set the call status for HFP devices.
                            // It is required for some devices to provide sound.
@@ -1490,6 +1531,12 @@ impl BluetoothMedia {
                    BthfAudioState::Disconnected => {
                        info!("[{}]: hfp audio disconnected.", DisplayAddress(&addr));

                        if self.hfp_audio_connection_listener.is_some() {
                            let listener = self.hfp_audio_connection_listener.take().unwrap();
                            let data: Vec<u8> = vec![0];
                            self.write_data_to_listener(listener, data);
                        }

                        // Ignore disconnected -> disconnected
                        if let Some(BthfAudioState::Connected) =
                            self.hfp_audio_state.insert(addr, state)
@@ -3822,13 +3869,24 @@ impl IBluetoothMedia for BluetoothMedia {
        };
    }

    fn start_audio_request(&mut self) -> bool {
    fn start_audio_request(&mut self, connection_listener: File) -> bool {
        if self.a2dp_audio_connection_listener.is_some() {
            warn!("start_audio_request: replacing an unresolved listener");
        }

        self.a2dp_audio_connection_listener = Some(connection_listener);
        self.start_audio_request_impl()
    }

    fn stop_audio_request(&mut self) {
    fn stop_audio_request(&mut self, connection_listener: File) {
        debug!("Stop audio request");

        if self.a2dp_audio_connection_listener.is_some() {
            warn!("stop_audio_request: replacing an unresolved listener");
        }

        self.a2dp_audio_connection_listener = Some(connection_listener);

        match self.a2dp.as_mut() {
            Some(a2dp) => a2dp.stop_audio_request(),
            None => warn!("Uninitialized A2DP to stop audio request"),
@@ -3840,11 +3898,22 @@ impl IBluetoothMedia for BluetoothMedia {
        address: RawAddress,
        sco_offload: bool,
        disabled_codecs: HfpCodecBitId,
        connection_listener: File,
    ) -> bool {
        if self.hfp_audio_connection_listener.is_some() {
            warn!("start_sco_call: replacing an unresolved listener");
        }

        self.hfp_audio_connection_listener = Some(connection_listener);
        self.start_sco_call_impl(address, sco_offload, disabled_codecs)
    }

    fn stop_sco_call(&mut self, address: RawAddress) {
    fn stop_sco_call(&mut self, address: RawAddress, listener: File) {
        if self.hfp_audio_connection_listener.is_some() {
            warn!("stop_sco_call: replacing an unresolved listener");
        }

        self.hfp_audio_connection_listener = Some(listener);
        self.stop_sco_call_impl(address)
    }