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

Commit d4c5236f authored by Archie Pusaka's avatar Archie Pusaka
Browse files

floss: hcidoc: modify profile storing mechanism

The same ACL connection might have several parallel connections to
the profile. We need to differentiate between the connections.
Therefore, this CL introduces a ProfileId, which is a custom field
for this purpose. For profiles based on L2CAP, CID can be used as the
ProfileId, and for RFCOMM based profiles, one can use the dlci.

Bug: 306108678
Test: m -j
Test: Manually, check HFP detection doesn't regress.

Change-Id: I2bf40d65170f8ebfcbcbf44465eb0a446f79d086
parent 8e555b6a
Loading
Loading
Loading
Loading
+50 −32
Original line number Diff line number Diff line
@@ -185,7 +185,8 @@ struct AclInformation {
    end_time: NaiveDateTime,
    handle: ConnectionHandle,
    initiator: InitiatorType,
    profiles: HashMap<ProfileType, Vec<ProfileInformation>>,
    active_profiles: HashMap<ProfileId, ProfileInformation>,
    inactive_profiles: Vec<ProfileInformation>,
}

impl AclInformation {
@@ -195,20 +196,11 @@ impl AclInformation {
            end_time: INVALID_TS,
            handle: handle,
            initiator: InitiatorType::Unknown,
            profiles: HashMap::new(),
            active_profiles: HashMap::new(),
            inactive_profiles: vec![],
        }
    }

    fn get_or_allocate_profile(&mut self, profile_type: &ProfileType) -> &mut ProfileInformation {
        if !self.profiles.contains_key(profile_type)
            || self.profiles.get(profile_type).unwrap().last().unwrap().end_time != INVALID_TS
        {
            self.profiles.insert(*profile_type, vec![ProfileInformation::new(*profile_type)]);
        }

        return self.profiles.get_mut(profile_type).unwrap().last_mut().unwrap();
    }

    fn report_start(&mut self, initiator: InitiatorType, ts: NaiveDateTime) {
        self.initiator = initiator;
        self.start_time = ts;
@@ -216,13 +208,9 @@ impl AclInformation {

    fn report_end(&mut self, ts: NaiveDateTime) {
        // disconnect the active profiles
        let profile_types: Vec<ProfileType> = self.profiles.keys().cloned().collect();
        for profile_type in profile_types {
            if let Some(profile) = self.profiles.get(&profile_type).unwrap().last() {
                if profile.end_time == INVALID_TS {
                    self.report_profile_end(profile_type, ts);
                }
            }
        for (_, mut profile) in self.active_profiles.drain() {
            profile.report_end(ts);
            self.inactive_profiles.push(profile);
        }
        self.end_time = ts;
    }
@@ -230,20 +218,30 @@ impl AclInformation {
    fn report_profile_start(
        &mut self,
        profile_type: ProfileType,
        profile_id: ProfileId,
        initiator: InitiatorType,
        ts: NaiveDateTime,
    ) {
        let mut profile = ProfileInformation::new(profile_type);
        profile.report_start(initiator, ts);
        if !self.profiles.contains_key(&profile_type) {
            self.profiles.insert(profile_type, vec![]);
        let old_profile = self.active_profiles.insert(profile_id, profile);
        if let Some(profile) = old_profile {
            self.inactive_profiles.push(profile);
        }
        self.profiles.get_mut(&profile_type).unwrap().push(profile);
    }

    fn report_profile_end(&mut self, profile_type: ProfileType, ts: NaiveDateTime) {
        let profile = self.get_or_allocate_profile(&profile_type);
    fn report_profile_end(
        &mut self,
        profile_type: ProfileType,
        profile_id: ProfileId,
        ts: NaiveDateTime,
    ) {
        let mut profile = self
            .active_profiles
            .remove(&profile_id)
            .unwrap_or(ProfileInformation::new(profile_type));
        profile.report_end(ts);
        self.inactive_profiles.push(profile);
    }
}

@@ -257,10 +255,11 @@ impl fmt::Display for AclInformation {
            timestamp_info = print_start_end_timestamps(self.start_time, self.end_time)
        );

        for (_profile_type, profiles) in self.profiles.iter() {
            for profile in profiles {
        for profile in self.inactive_profiles.iter() {
            let _ = write!(f, "{}", profile);
        }
        for (_, profile) in self.active_profiles.iter() {
            let _ = write!(f, "{}", profile);
        }

        Ok(())
@@ -282,6 +281,14 @@ impl fmt::Display for ProfileType {
    }
}

// Use to distinguish between the same profiles within one ACL connection.
// Currently only for profiles that's guaranteed to be singular, i.e. HFP.
// Later we can add L2CAP's CID and RFCOMM's DLCI, for example.
#[derive(Eq, Hash, PartialEq)]
enum ProfileId {
    OnePerConnection(ProfileType),
}

struct ProfileInformation {
    start_time: NaiveDateTime,
    end_time: NaiveDateTime,
@@ -421,7 +428,12 @@ impl InformationalRule {
        let acl_handle = acl.handle;
        // We need to listen the HCI commands to determine the correct initiator.
        // Here we just assume host for simplicity.
        acl.report_profile_start(ProfileType::HFP, InitiatorType::Host, ts);
        acl.report_profile_start(
            ProfileType::HFP,
            ProfileId::OnePerConnection(ProfileType::HFP),
            InitiatorType::Host,
            ts,
        );

        self.sco_handles.insert(handle, acl_handle);
    }
@@ -431,7 +443,11 @@ impl InformationalRule {
        if self.sco_handles.contains_key(&handle) {
            let acl_handle = self.sco_handles[&handle];
            let conn = self.get_or_allocate_connection(&acl_handle);
            conn.report_profile_end(ProfileType::HFP, ts);
            conn.report_profile_end(
                ProfileType::HFP,
                ProfileId::OnePerConnection(ProfileType::HFP),
                ts,
            );
            return;
        }

@@ -465,21 +481,23 @@ impl InformationalRule {
        &mut self,
        handle: ConnectionHandle,
        profile_type: ProfileType,
        profile_id: ProfileId,
        initiator: InitiatorType,
        ts: NaiveDateTime,
    ) {
        let conn = self.get_or_allocate_connection(&handle);
        conn.report_profile_start(profile_type, initiator, ts);
        conn.report_profile_start(profile_type, profile_id, initiator, ts);
    }

    fn _report_profile_end(
        &mut self,
        handle: ConnectionHandle,
        profile_type: ProfileType,
        profile_id: ProfileId,
        ts: NaiveDateTime,
    ) {
        let conn = self.get_or_allocate_connection(&handle);
        conn.report_profile_end(profile_type, ts);
        conn.report_profile_end(profile_type, profile_id, ts);
    }

    fn process_gap_data(&mut self, address: &Address, data: &GapData) {