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

Commit c741965f authored by WhaleChang's avatar WhaleChang
Browse files

Floss: Add relevant events for Bluetooth Telephony

Add relevant Bluetooth telephony events and notify CRAS
when these events occur.

This patch enhances the existing on_telephony_use callback to
on_telephony_event, expanding its functionality beyond signaling
uhid open/close events. The new callback can signal more telephony
events (e.g. active_call, answer, reject) to CRAS.

Note: this patch must be merged together with crrev/c/5541553 when
it is cherry-picked back to chromeos as this change affects the
D-Bus API between CRAS and Floss.

Bug: 329015732
Test: Conduct the following manual tests
  pair Bluetooth Headset
  login Ring Central and place an incoming-call
  answer the call on Ring Central
  hangup the call from headset
  check the log with cras_test_client --dump_bt
Test: atest bluetooth_test_gd
Tag: #floss
Flag: EXEMPT, no behavior change on Android; Floss-only changes
Change-Id: I1a3da58fa833fc212d2132b8dc83b4fa4824fe08
parent 160dae71
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1525,8 +1525,8 @@ impl TelephonyCallback {
}

impl IBluetoothTelephonyCallback for TelephonyCallback {
    fn on_telephony_use(&mut self, addr: String, state: bool) {
        print_info!("Telephony use changed: [{}] state: {}", addr, state);
    fn on_telephony_event(&mut self, addr: String, event: u8, call_state: u8) {
        print_info!("Telephony event changed: [{}] event {} state: {}", addr, event, call_state);
    }
}

+2 −2
Original line number Diff line number Diff line
@@ -2449,8 +2449,8 @@ impl RPCProxy for IBluetoothTelephonyCallbackDBus {}
    "org.chromium.bluetooth.BluetoothTelephonyCallback"
)]
impl IBluetoothTelephonyCallback for IBluetoothTelephonyCallbackDBus {
    #[dbus_method("OnTelephonyUse")]
    fn on_telephony_use(&mut self, addr: String, state: bool) {
    #[dbus_method("OnTelephonyEvent")]
    fn on_telephony_event(&mut self, addr: String, event: u8, call_state: u8) {
        dbus_generated!()
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -14,8 +14,8 @@ struct BluetoothTelephonyCallbackDBus {}

#[dbus_proxy_obj(BluetoothTelephonyCallback, "org.chromium.bluetooth.BluetoothTelephonyCallback")]
impl IBluetoothTelephonyCallback for BluetoothTelephonyCallbackDBus {
    #[dbus_method("OnTelephonyUse")]
    fn on_telephony_use(&mut self, addr: String, state: bool) {
    #[dbus_method("OnTelephonyEvent")]
    fn on_telephony_event(&mut self, addr: String, event: u8, call_state: u8) {
        dbus_generated!()
    }
}
+66 −2
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ use crate::uuid;
use crate::uuid::Profile;
use crate::{Message, RPCProxy};

use num_derive::FromPrimitive;

// The timeout we have to wait for all supported profiles to connect after we
// receive the first profile connected event. The host shall disconnect or
// force connect the potentially partially connected device after this many
@@ -337,7 +339,7 @@ pub trait IBluetoothTelephony {
}

pub trait IBluetoothTelephonyCallback: RPCProxy {
    fn on_telephony_use(&mut self, addr: String, state: bool);
    fn on_telephony_event(&mut self, addr: String, event: u8, state: u8);
}

/// Serializable device used in.
@@ -402,6 +404,34 @@ struct LEAAudioConf {
    pub avail_cont: u16,
}

#[derive(Debug, Copy, Clone, FromPrimitive)]
#[repr(u8)]
enum TelephonyEvent {
    UHidCreate = 0,
    UHidDestroy,
    UHidOpen,
    UHidClose,
    UHidIncomingCall,
    UHidAnswerCall,
    UHidHangupCall,
    UHidPlaceActiveCall,
    UHidMicMute,
    UHidMicUnmute,
    CRASPlaceActiveCall,
    CRASRemoveActiveCall,
    HFAnswerCall,
    HFHangupCall,
    HFMicMute,
    HFMicUnmute,
    HFCurrentCallsQuery,
}

impl From<TelephonyEvent> for u8 {
    fn from(telephony_event: TelephonyEvent) -> Self {
        telephony_event as u8
    }
}

pub struct BluetoothMedia {
    intf: Arc<Mutex<BluetoothInterface>>,
    battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
@@ -1394,6 +1424,7 @@ impl BluetoothMedia {
                            // This triggers a +CIEV command to set the call status for HFP devices.
                            // It is required for some devices to provide sound.
                            self.place_active_call();
                            self.notify_telephony_event(&addr, TelephonyEvent::CRASPlaceActiveCall);
                        }
                    }
                    BthfAudioState::Disconnected => {
@@ -1413,6 +1444,10 @@ impl BluetoothMedia {
                            self.call_list = vec![];
                            self.phone_state.num_active = 0;
                            self.phone_state_change("".into());
                            self.notify_telephony_event(
                                &addr,
                                TelephonyEvent::CRASRemoveActiveCall,
                            );
                        }

                        // Resume the A2DP stream when a phone call ended (per MPS v1.0).
@@ -1471,12 +1506,14 @@ impl BluetoothMedia {
                        // We expect the application to send back UHID output report and
                        // update uhid.mute in dispatch_uhid_hfp_output_callback later.
                        self.uhid_send_phone_mute_input_report(&addr, true);
                        self.notify_telephony_event(&addr, TelephonyEvent::HFMicMute);
                    } else if volume > 0 {
                        uhid.volume = volume;
                        if uhid.muted {
                            // We expect the application to send back UHID output report and
                            // update uhid.mute in dispatch_uhid_hfp_output_callback later.
                            self.uhid_send_phone_mute_input_report(&addr, false);
                            self.notify_telephony_event(&addr, TelephonyEvent::HFMicUnmute);
                        }
                    }
                }
@@ -1617,6 +1654,7 @@ impl BluetoothMedia {
                                status
                            );
                        }
                        self.notify_telephony_event(&addr, TelephonyEvent::HFCurrentCallsQuery);
                    }
                    None => warn!("Uninitialized HFP to notify telephony status"),
                };
@@ -1637,6 +1675,7 @@ impl BluetoothMedia {
                    // We expect the application to send back UHID output report and
                    // trigger dispatch_uhid_hfp_output_callback later.
                    self.uhid_send_hook_switch_input_report(&addr, true);
                    self.notify_telephony_event(&addr, TelephonyEvent::HFAnswerCall);
                }
            }
            HfpCallbacks::HangupCall(addr) => {
@@ -1655,6 +1694,7 @@ impl BluetoothMedia {
                    // We expect the application to send back UHID output report and
                    // trigger dispatch_uhid_hfp_output_callback later.
                    self.uhid_send_hook_switch_input_report(&addr, false);
                    self.notify_telephony_event(&addr, TelephonyEvent::HFHangupCall);
                }
            }
            HfpCallbacks::DialCall(number, addr) => {
@@ -1809,6 +1849,7 @@ impl BluetoothMedia {
                is_open: false,
            },
        );
        self.notify_telephony_event(&addr, TelephonyEvent::UHidCreate);
    }

    fn uhid_destroy(&mut self, addr: &RawAddress) {
@@ -1823,6 +1864,7 @@ impl BluetoothMedia {
                Ok(_) => (),
            };
            self.uhid.remove(addr);
            self.notify_telephony_event(&addr, TelephonyEvent::UHidDestroy);
        } else {
            debug!("[{}]: UHID destroy: not a UHID device", DisplayAddress(&addr));
        }
@@ -1937,22 +1979,28 @@ impl BluetoothMedia {
            if mute == UHID_OUTPUT_MUTE && !uhid.muted {
                uhid.muted = true;
                self.set_hfp_mic_volume(0, addr);
                self.notify_telephony_event(&addr, TelephonyEvent::UHidMicMute);
            } else if mute != UHID_OUTPUT_MUTE && uhid.muted {
                uhid.muted = false;
                let saved_volume = uhid.volume;
                self.set_hfp_mic_volume(saved_volume, addr);
                self.notify_telephony_event(&addr, TelephonyEvent::UHidMicUnmute);
            }

            let call_state = data & (UHID_OUTPUT_RING | UHID_OUTPUT_OFF_HOOK);
            if call_state == UHID_OUTPUT_NONE {
                self.hangup_call_impl();
                self.notify_telephony_event(&addr, TelephonyEvent::UHidHangupCall);
            } else if call_state == UHID_OUTPUT_RING {
                self.incoming_call_impl("".into());
                self.notify_telephony_event(&addr, TelephonyEvent::UHidIncomingCall);
            } else if call_state == UHID_OUTPUT_OFF_HOOK {
                if self.phone_state.state == CallState::Incoming {
                    self.answer_call_impl();
                    self.notify_telephony_event(&addr, TelephonyEvent::UHidAnswerCall);
                } else if self.phone_state.state == CallState::Idle {
                    self.place_active_call();
                    self.notify_telephony_event(&addr, TelephonyEvent::UHidPlaceActiveCall);
                }
                self.uhid_send_hook_switch_input_report(&addr, true);
            }
@@ -1989,8 +2037,24 @@ impl BluetoothMedia {
        //              HF layer in sync and not prevent A2DP streaming.
        self.hangup_call_impl();

        if state {
            self.notify_telephony_event(&addr, TelephonyEvent::UHidOpen);
        } else {
            self.notify_telephony_event(&addr, TelephonyEvent::UHidClose);
        }
    }

    fn notify_telephony_event(&mut self, addr: &RawAddress, event: TelephonyEvent) {
        // Simplified call status: Assumes at most one call in the list.
        // Defaults to Idle if no calls are present.
        // Revisit this logic if the system supports multiple concurrent calls in the future (e.g., three-way-call).
        let mut call_state = CallState::Idle;
        for c in self.call_list.iter() {
            call_state = c.state;
            break;
        }
        self.telephony_callbacks.lock().unwrap().for_all_callbacks(|callback| {
            callback.on_telephony_use(address.to_string(), state);
            callback.on_telephony_event(addr.to_string(), u8::from(event), u8::from(call_state));
        });
    }

+15 −0
Original line number Diff line number Diff line
@@ -282,6 +282,21 @@ pub type CallInfo = ffi::CallInfo;
pub type PhoneState = ffi::PhoneState;
pub type CallHoldCommand = ffi::CallHoldCommand;

// CallState (non-primitive) cannot be directly cast to u8.
impl From<CallState> for u8 {
    fn from(state: CallState) -> u8 {
        match state {
            CallState::Idle => 0,
            CallState::Incoming => 1,
            CallState::Dialing => 2,
            CallState::Alerting => 3,
            CallState::Active => 4,
            CallState::Held => 5,
            CallState { repr: 6_u8..=u8::MAX } => todo!(),
        }
    }
}

#[derive(Clone, Debug)]
pub enum HfpCallbacks {
    ConnectionState(BthfConnectionState, RawAddress),