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

Commit 75ea431c authored by Hsin-chen Chuang's avatar Hsin-chen Chuang
Browse files

floss: telephony: Support dialing operations from HF

Implemented the following functions and wired to btclient:
- SetMemoryCall
- SetLastCall

Added support of:
- Dialing a number from HF
- Dialing the last number from HF
- Dialing a number in the memory slot from HF

Bug: 214149380
Tag: #floss
Test: HFP/AG/OCM/BV-02-I, HFP/AG/OCL/BV-02-I
Change-Id: If109174a60fe13ebce0c6502ff5b33d516918ef6
parent 2c52b912
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -283,6 +283,7 @@ fn build_commands() -> HashMap<String, CommandOption> {
                String::from("telephony <enable|disable>"),
                String::from("telephony <incoming-call|dialing-call> <number>"),
                String::from("telephony <answer-call|hangup-call>"),
                String::from("telephony <set-memory-call|set-last-call> [<number>]"),
            ],
            description: String::from("Set device telephony status."),
            function_pointer: CommandHandler::cmd_telephony,
@@ -1631,6 +1632,32 @@ impl CommandHandler {
                    return Err("HangupCall failed".into());
                }
            }
            "set-memory-call" => {
                let success = self
                    .context
                    .lock()
                    .unwrap()
                    .telephony_dbus
                    .as_mut()
                    .unwrap()
                    .set_memory_call(get_arg(args, 1).ok().map(String::from));
                if !success {
                    return Err("SetMemoryCall failed".into());
                }
            }
            "set-last-call" => {
                let success = self
                    .context
                    .lock()
                    .unwrap()
                    .telephony_dbus
                    .as_mut()
                    .unwrap()
                    .set_last_call(get_arg(args, 1).ok().map(String::from));
                if !success {
                    return Err("SetLastCall failed".into());
                }
            }
            other => {
                return Err(format!("Invalid argument '{}'", other).into());
            }
+8 −0
Original line number Diff line number Diff line
@@ -1874,4 +1874,12 @@ impl IBluetoothTelephony for BluetoothTelephonyDBus {
    fn hangup_call(&mut self) -> bool {
        dbus_generated!()
    }
    #[dbus_method("SetMemoryCall")]
    fn set_memory_call(&mut self, number: Option<String>) -> bool {
        dbus_generated!()
    }
    #[dbus_method("SetLastCall")]
    fn set_last_call(&mut self, number: Option<String>) -> bool {
        dbus_generated!()
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -50,4 +50,12 @@ impl IBluetoothTelephony for IBluetoothTelephonyDBus {
    fn hangup_call(&mut self) -> bool {
        dbus_generated!()
    }
    #[dbus_method("SetMemoryCall")]
    fn set_memory_call(&mut self, number: Option<String>) -> bool {
        dbus_generated!()
    }
    #[dbus_method("SetLastCall")]
    fn set_last_call(&mut self, number: Option<String>) -> bool {
        dbus_generated!()
    }
}
+78 −11
Original line number Diff line number Diff line
@@ -165,6 +165,11 @@ pub trait IBluetoothTelephony {
    fn answer_call(&mut self) -> bool;
    /// Acts like hanging up an active/incoming/dialing call from the AG.
    fn hangup_call(&mut self) -> bool;
    /// Sets/unsets the memory slot. Note that we store at most one memory
    /// number and return it regardless of which slot is specified by HF.
    fn set_memory_call(&mut self, number: Option<String>) -> bool;
    /// Sets/unsets the last call.
    fn set_last_call(&mut self, number: Option<String>) -> bool;
}

/// Serializable device used in.
@@ -230,6 +235,8 @@ pub struct BluetoothMedia {
    phone_state: PhoneState,
    call_list: Vec<CallInfo>,
    phone_ops_enabled: bool,
    memory_dialing_number: Option<String>,
    last_dialing_number: Option<String>,
}

impl BluetoothMedia {
@@ -273,6 +280,8 @@ impl BluetoothMedia {
            phone_state: PhoneState { num_active: 0, num_held: 0, state: CallState::Idle },
            call_list: vec![],
            phone_ops_enabled: false,
            memory_dialing_number: None,
            last_dialing_number: None,
        }
    }

@@ -739,6 +748,27 @@ impl BluetoothMedia {
                }
                self.phone_state_change("".into());
            }
            HfpCallbacks::DialCall(number, addr) => {
                let number = if number == "" {
                    self.last_dialing_number.clone()
                } else if number.starts_with(">") {
                    self.memory_dialing_number.clone()
                } else {
                    Some(number)
                };

                let success = number.map_or(false, |num| self.dialing_call_impl(num));

                // Respond OK/ERROR to the HF which sent the command.
                // This should be called before calling phone_state_change.
                self.simple_at_response(success, addr.clone());
                if success {
                    // Success means the call state has changed. Inform the LibBluetooth stack.
                    self.phone_state_change("".into());
                } else {
                    warn!("[{}]: Unexpected dialing command from HF", addr.to_string());
                }
            }
        }
    }

@@ -1115,6 +1145,18 @@ impl BluetoothMedia {
            .expect("There must be an unoccupied index")
    }

    fn simple_at_response(&mut self, ok: bool, addr: RawAddress) {
        match self.hfp.as_mut() {
            Some(hfp) => {
                let status = hfp.simple_at_response(ok, addr.clone());
                if status != BtStatus::Success {
                    warn!("[{}]: AT response failed, status={:?}", addr.to_string(), status);
                }
            }
            None => warn!("Uninitialized HFP to send AT response"),
        }
    }

    fn answer_call_impl(&mut self) -> bool {
        if !self.phone_ops_enabled || self.phone_state.state == CallState::Idle {
            return false;
@@ -1153,6 +1195,23 @@ impl BluetoothMedia {
        });
        true
    }

    fn dialing_call_impl(&mut self, number: String) -> bool {
        if !self.phone_ops_enabled
            || self.phone_state.state != CallState::Idle
            || self.phone_state.num_active > 0
        {
            return false;
        }
        self.call_list.push(CallInfo {
            index: self.new_call_index(),
            dir_incoming: false,
            state: CallState::Dialing,
            number: number.clone(),
        });
        self.phone_state.state = CallState::Dialing;
        true
    }
}

fn get_a2dp_dispatcher(tx: Sender<Message>) -> A2dpCallbacksDispatcher {
@@ -1801,6 +1860,8 @@ impl IBluetoothTelephony for BluetoothMedia {
        self.phone_state.num_active = 0;
        self.phone_state.num_held = 0;
        self.phone_state.state = CallState::Idle;
        self.memory_dialing_number = None;
        self.last_dialing_number = None;

        if !enable {
            if self.hfp_states.values().any(|x| x == &BthfConnectionState::SlcConnected) {
@@ -1837,19 +1898,9 @@ impl IBluetoothTelephony for BluetoothMedia {
    }

    fn dialing_call(&mut self, number: String) -> bool {
        if !self.phone_ops_enabled
            || self.phone_state.state != CallState::Idle
            || self.phone_state.num_active > 0
        {
        if !self.dialing_call_impl(number) {
            return false;
        }
        self.call_list.push(CallInfo {
            index: self.new_call_index(),
            dir_incoming: false,
            state: CallState::Dialing,
            number: number.clone(),
        });
        self.phone_state.state = CallState::Dialing;
        self.phone_state_change("".into());
        true
    }
@@ -1869,6 +1920,22 @@ impl IBluetoothTelephony for BluetoothMedia {
        self.phone_state_change("".into());
        true
    }

    fn set_memory_call(&mut self, number: Option<String>) -> bool {
        if !self.phone_ops_enabled {
            return false;
        }
        self.memory_dialing_number = number;
        true
    }

    fn set_last_call(&mut self, number: Option<String>) -> bool {
        if !self.phone_ops_enabled {
            return false;
        }
        self.last_dialing_number = number;
        true
    }
}

struct BatteryProviderCallback {}
+12 −1
Original line number Diff line number Diff line
@@ -62,6 +62,10 @@ static void hangup_call_cb(RawAddress* addr) {
  rusty::hfp_hangup_call_callback(*addr);
}

static void dial_call_cb(char* number, RawAddress* addr) {
  rusty::hfp_dial_call_callback(::rust::String{number}, *addr);
}

static headset::bthf_call_state_t from_rust_call_state(rusty::CallState state) {
  switch (state) {
    case rusty::CallState::Idle:
@@ -118,7 +122,9 @@ class DBusHeadsetCallbacks : public headset::Callbacks {
    topshim::rust::internal::volume_update_cb(volume, bd_addr);
  }

  void DialCallCallback([[maybe_unused]] char* number, [[maybe_unused]] RawAddress* bd_addr) override {}
  void DialCallCallback(char* number, RawAddress* bd_addr) override {
    topshim::rust::internal::dial_call_cb(number, bd_addr);
  }

  void DtmfCmdCallback([[maybe_unused]] char tone, [[maybe_unused]] RawAddress* bd_addr) override {}

@@ -288,6 +294,11 @@ uint32_t HfpIntf::phone_state_change(
      &addr);
}

uint32_t HfpIntf::simple_at_response(bool ok, RawAddress addr) {
  return intf_->AtResponse(
      (ok ? headset::BTHF_AT_RESPONSE_OK : headset::BTHF_AT_RESPONSE_ERROR), 0, &addr);
}

void HfpIntf::cleanup() {}

std::unique_ptr<HfpIntf> GetHfpProfile(const unsigned char* btif) {
Loading