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

Commit 0a2a0175 authored by WhaleChang's avatar WhaleChang
Browse files

Floss: Fix RingCentral microphone mute desync with headset

When sending a 0x09, 0x2f (Phone Mute) input report to RingCentral,
if the value is 0 (meaning unmute), RingCentral will not react.

The root cause is RingCentral treats 0x09, 0x2f (Phone Mute) as a
toggle event instead of OOC (on/off) control. Only sending 1 with 0x09,
0x2f (Phone Mute) can toggle the microphone status on RingCentral.
phone_mute=0 will be treated as no-ops.

We also found that USB resolving this issue by sending additional
phone_mute=1 event during unmute, so we follow this behavior in bt telephony.

Bug: 333847153
Bug: 329280858
Test: Conduct the following manual tests
  pair Bluetooth Headset
  Google Meet: headset is able mute/unmute via headset and the mute status sync with Meet
  RingCentral: headset is able mute/unmute via headset and the mute status sync with RingCentral
Test: atest bluetooth_test_gd
Tag: #floss
Flag: EXEMPT, no behavior change on Android; Floss-only changes

Change-Id: I6bd95681c9f58b426aef4fe630a0952c5ffaad44
parent ba2e6728
Loading
Loading
Loading
Loading
+38 −29
Original line number Diff line number Diff line
@@ -1208,6 +1208,29 @@ impl BluetoothMedia {
        }
    }

    fn uhid_send_input_event_report(&mut self, addr: &RawAddress, data: u8) {
        if !self.phone_ops_enabled {
            return;
        }
        if let Some(uhid) = self.uhid.get_mut(addr) {
            info!(
                "[{}]: UHID: Send telephony hid input report. hook_switch({}), mute({}), drop({})",
                DisplayAddress(&addr),
                (data & UHID_INPUT_HOOK_SWITCH) != 0,
                (data & UHID_INPUT_PHONE_MUTE) != 0,
                (data & UHID_INPUT_DROP) != 0,
            );
            match uhid.handle.send_input(data) {
                Err(e) => log::error!(
                    "[{}]: UHID: Fail to send hid input report. err:{}",
                    DisplayAddress(&addr),
                    e
                ),
                Ok(_) => (),
            };
        }
    }

    fn uhid_send_hook_switch_input_report(&mut self, addr: &RawAddress, hook: bool) {
        if !self.phone_ops_enabled {
            return;
@@ -1223,22 +1246,7 @@ impl BluetoothMedia {
            if uhid.muted {
                data |= UHID_INPUT_PHONE_MUTE;
            }
            info!(
                "[{}]: UHID: Send hook-switch({}) hid input report. phone_mute({})",
                DisplayAddress(&addr),
                hook,
                uhid.muted
            );
            match uhid.handle.send_input(data) {
                Err(e) => log::error!(
                    "[{}]: UHID: Fail to send hook-switch({}) hid input report. phone_mute({}) err:{}",
                    DisplayAddress(&addr),
                    hook,
                    uhid.muted,
                    e
                ),
                Ok(_) => (),
            };
            self.uhid_send_input_event_report(&addr, data);
        };
    }
    fn uhid_send_phone_mute_input_report(&mut self, addr: &RawAddress, muted: bool) {
@@ -1252,25 +1260,26 @@ impl BluetoothMedia {
            if call_active {
                data |= UHID_INPUT_HOOK_SWITCH;
            }
            if muted {
                data |= UHID_INPUT_PHONE_MUTE;
            }
            info!(
                "[{}]: UHID: Send phone_mute({}) hid input report. hook-switch({})",
                DisplayAddress(&addr),
                muted,
                call_active
            );
            match uhid.handle.send_input(data) {
                Err(e) => log::error!(
                    "[{}]: UHID: Fail to send phone_mute({}) hid input report. hook-switch({}) err:{}",
                    DisplayAddress(&addr),
                    muted,
                    call_active,
                    e
                ),
                Ok(_) => (),
            };
            if muted {
                data |= UHID_INPUT_PHONE_MUTE;
                self.uhid_send_input_event_report(&addr, data);
            } else {
                // We follow the same pattern as the USB headset, which sends an
                // additional phone mute=1 event when unmuting the microphone.
                // Based on our testing, Some applications do not respond to phone
                // mute=0 and treat the phone mute=1 event as a toggle rather than
                // an on off control.
                data |= UHID_INPUT_PHONE_MUTE;
                self.uhid_send_input_event_report(&addr, data);
                data &= !UHID_INPUT_PHONE_MUTE;
                self.uhid_send_input_event_report(&addr, data);
            }
        };
    }