1use fidl_fuchsia_bluetooth_hfp::CallState;
6use packet_encoding::decodable_enum;
7use thiserror::Error;
8
9decodable_enum! {
10pub enum Call<i64, CallIndicatorError, InvalidValue> {
12 None = 0,
14 Some = 1,
16 }
17}
18
19#[derive(Debug, Error, PartialEq)]
20pub enum CallIndicatorError {
21 #[error("Invalid Call indicator value")]
22 InvalidValue,
23}
24
25impl Default for Call {
26 fn default() -> Self {
27 Self::None
28 }
29}
30
31impl From<&Call> for bool {
32 fn from(call: &Call) -> Self {
33 match call {
34 Call::None => false,
35 Call::Some => true,
36 }
37 }
38}
39
40impl From<bool> for Call {
41 fn from(call: bool) -> Self {
42 match call {
43 false => Self::None,
44 true => Self::Some,
45 }
46 }
47}
48
49impl Call {
50 pub fn find(mut iter: impl Iterator<Item = CallState>) -> Self {
52 iter.any(|state| {
53 [CallState::OngoingActive, CallState::OngoingHeld, CallState::TransferredToAg]
54 .contains(&state)
55 })
56 .into()
57 }
58}
59
60decodable_enum! {
61pub enum CallSetup<i64, CallSetupIndicatorError, InvalidValue> {
63 None = 0,
65 Incoming = 1,
67 OutgoingDialing = 2,
69 OutgoingAlerting = 3,
71 }
72}
73
74#[derive(Debug, Error, PartialEq)]
75pub enum CallSetupIndicatorError {
76 #[error("Invalid Call Setup indicator value.")]
77 InvalidValue,
78}
79
80impl Default for CallSetup {
81 fn default() -> Self {
82 Self::None
83 }
84}
85
86impl CallSetup {
87 pub fn find(mut iter: impl Iterator<Item = CallState>) -> Self {
89 iter.find(|state| {
90 [
91 CallState::IncomingRinging,
92 CallState::IncomingWaiting,
93 CallState::OutgoingAlerting,
94 CallState::OutgoingDialing,
95 ]
96 .contains(&state)
97 })
98 .map(CallSetup::from)
99 .unwrap_or(CallSetup::None)
100 }
101}
102
103impl From<CallState> for CallSetup {
104 fn from(state: CallState) -> Self {
105 match state {
106 CallState::IncomingRinging | CallState::IncomingWaiting => Self::Incoming,
107 CallState::OutgoingDialing => Self::OutgoingDialing,
108 CallState::OutgoingAlerting => Self::OutgoingAlerting,
109 _ => Self::None,
110 }
111 }
112}
113
114decodable_enum! {
115 pub enum CallHeld<i64, CallHeldIndicatorError, InvalidValue> {
117 None = 0,
119 HeldAndActive = 1,
122 Held = 2,
124 }
125}
126
127#[derive(Debug, Error, PartialEq)]
128pub enum CallHeldIndicatorError {
129 #[error("Invalid Call Held indicator value")]
130 InvalidValue,
131}
132
133impl Default for CallHeld {
134 fn default() -> Self {
135 Self::None
136 }
137}
138
139impl CallHeld {
140 pub fn find(mut iter: impl Iterator<Item = CallState> + Clone) -> Self {
142 let any_held = iter.clone().any(|state| state == CallState::OngoingHeld);
143 let any_active = iter.any(|state| state == CallState::OngoingActive);
144 match (any_held, any_active) {
145 (true, false) => CallHeld::Held,
146 (true, true) => CallHeld::HeldAndActive,
147 (false, _) => CallHeld::None,
148 }
149 }
150}
151
152#[derive(Clone, Copy, Debug, Default, PartialEq)]
153pub struct CallIndicators {
154 pub call: Call,
155 pub callsetup: CallSetup,
156 pub callheld: CallHeld,
157 pub callwaiting: bool,
160}
161
162impl CallIndicators {
163 pub fn find(mut iter: impl Iterator<Item = CallState> + Clone) -> Self {
165 let call = Call::find(iter.clone());
166 let callsetup = CallSetup::find(iter.clone());
167 let callheld = CallHeld::find(iter.clone());
168 let callwaiting = iter.any(|c| c == CallState::IncomingWaiting);
169 CallIndicators { call, callsetup, callheld, callwaiting }
170 }
171
172 pub fn difference(&self, other: Self) -> CallIndicatorsUpdates {
175 let mut changes = CallIndicatorsUpdates::default();
176 if other.call != self.call {
177 changes.call = Some(self.call);
178 }
179 if other.callsetup != self.callsetup {
180 changes.callsetup = Some(self.callsetup);
181 }
182 if other.callheld != self.callheld {
183 changes.callheld = Some(self.callheld);
184 }
185 if self.callwaiting && !other.callwaiting {
186 changes.callwaiting = true;
187 }
188 changes
189 }
190}
191
192#[derive(Clone, Copy, Debug, Default, PartialEq)]
193pub struct CallIndicatorsUpdates {
194 pub call: Option<Call>,
195 pub callsetup: Option<CallSetup>,
196 pub callheld: Option<CallHeld>,
197 pub callwaiting: bool,
199}
200
201impl CallIndicatorsUpdates {
202 pub fn is_empty(&self) -> bool {
204 self.call.is_none()
205 && self.callsetup.is_none()
206 && self.callheld.is_none()
207 && !self.callwaiting
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214
215 #[fuchsia::test]
216 fn find_call() {
217 let states = vec![];
218 let call = Call::find(states.into_iter());
219 assert_eq!(call, Call::None);
220
221 let states = vec![CallState::Terminated];
222 let call = Call::find(states.into_iter());
223 assert_eq!(call, Call::None);
224
225 let states = vec![CallState::OngoingActive];
226 let call = Call::find(states.into_iter());
227 assert_eq!(call, Call::Some);
228
229 let states = vec![CallState::OngoingHeld];
230 let call = Call::find(states.into_iter());
231 assert_eq!(call, Call::Some);
232
233 let states = vec![CallState::OngoingHeld, CallState::Terminated];
234 let call = Call::find(states.into_iter());
235 assert_eq!(call, Call::Some);
236
237 let states = vec![CallState::OngoingHeld, CallState::OngoingActive];
238 let call = Call::find(states.into_iter());
239 assert_eq!(call, Call::Some);
240 }
241
242 #[fuchsia::test]
243 fn find_callsetup() {
244 let states = vec![];
245 let setup = CallSetup::find(states.into_iter());
246 assert_eq!(setup, CallSetup::None);
247
248 let states = vec![CallState::Terminated];
249 let setup = CallSetup::find(states.into_iter());
250 assert_eq!(setup, CallSetup::None);
251
252 let states = vec![CallState::IncomingRinging];
253 let setup = CallSetup::find(states.into_iter());
254 assert_eq!(setup, CallSetup::Incoming);
255
256 let states = vec![CallState::IncomingWaiting];
257 let setup = CallSetup::find(states.into_iter());
258 assert_eq!(setup, CallSetup::Incoming);
259
260 let states = vec![CallState::OutgoingAlerting];
261 let setup = CallSetup::find(states.into_iter());
262 assert_eq!(setup, CallSetup::OutgoingAlerting);
263
264 let states = vec![CallState::OutgoingDialing];
265 let setup = CallSetup::find(states.into_iter());
266 assert_eq!(setup, CallSetup::OutgoingDialing);
267
268 let states = vec![CallState::OutgoingDialing, CallState::IncomingRinging];
270 let setup = CallSetup::find(states.into_iter());
271 assert_eq!(setup, CallSetup::OutgoingDialing);
272
273 let states = vec![CallState::Terminated, CallState::IncomingRinging];
275 let setup = CallSetup::find(states.into_iter());
276 assert_eq!(setup, CallSetup::Incoming);
277 }
278
279 #[fuchsia::test]
280 fn find_call_held() {
281 let states = vec![];
282 let held = CallHeld::find(states.into_iter());
283 assert_eq!(held, CallHeld::None);
284
285 let states = vec![CallState::OngoingHeld];
286 let held = CallHeld::find(states.into_iter());
287 assert_eq!(held, CallHeld::Held);
288
289 let states = vec![CallState::OngoingActive];
291 let held = CallHeld::find(states.into_iter());
292 assert_eq!(held, CallHeld::None);
293
294 let states = vec![CallState::OngoingHeld, CallState::Terminated];
296 let held = CallHeld::find(states.into_iter());
297 assert_eq!(held, CallHeld::Held);
298
299 let states = vec![CallState::OngoingHeld, CallState::OngoingActive];
301 let held = CallHeld::find(states.into_iter());
302 assert_eq!(held, CallHeld::HeldAndActive);
303
304 let states = vec![CallState::OngoingActive, CallState::OngoingHeld];
306 let held = CallHeld::find(states.into_iter());
307 assert_eq!(held, CallHeld::HeldAndActive);
308 }
309
310 #[fuchsia::test]
311 fn find_call_indicators() {
312 let states = vec![];
313 let ind = CallIndicators::find(states.into_iter());
314 assert_eq!(ind, CallIndicators::default());
315
316 let states = vec![CallState::OngoingHeld, CallState::IncomingRinging];
317 let ind = CallIndicators::find(states.into_iter());
318 let expected = CallIndicators {
319 call: Call::Some,
320 callsetup: CallSetup::Incoming,
321 callwaiting: false,
322 callheld: CallHeld::Held,
323 };
324 assert_eq!(ind, expected);
325 }
326
327 #[fuchsia::test]
328 fn call_indicators_differences() {
329 let a = CallIndicators::default();
330 let b = CallIndicators { ..a };
331 assert!(b.difference(a).is_empty());
332
333 let a = CallIndicators::default();
334 let b = CallIndicators { call: Call::Some, ..a };
335 let expected =
336 CallIndicatorsUpdates { call: Some(Call::Some), ..CallIndicatorsUpdates::default() };
337 assert_eq!(b.difference(a), expected);
338
339 let a = CallIndicators::default();
340 let b = CallIndicators { call: Call::Some, callheld: CallHeld::Held, ..a };
341 let expected = CallIndicatorsUpdates {
342 call: Some(Call::Some),
343 callheld: Some(CallHeld::Held),
344 ..CallIndicatorsUpdates::default()
345 };
346 assert_eq!(b.difference(a), expected);
347
348 let a = CallIndicators { call: Call::Some, ..CallIndicators::default() };
349 let b = CallIndicators { callsetup: CallSetup::Incoming, ..a };
350 let expected = CallIndicatorsUpdates {
351 callsetup: Some(CallSetup::Incoming),
352 ..CallIndicatorsUpdates::default()
353 };
354 assert_eq!(b.difference(a), expected);
355
356 let a = CallIndicators::default();
357 let b = CallIndicators { callsetup: CallSetup::Incoming, callwaiting: true, ..a };
358 let expected = CallIndicatorsUpdates {
359 callsetup: Some(CallSetup::Incoming),
360 callwaiting: true,
361 ..CallIndicatorsUpdates::default()
362 };
363 assert_eq!(b.difference(a), expected);
364
365 let expected = CallIndicatorsUpdates {
367 callsetup: Some(CallSetup::None),
368 callwaiting: false,
369 ..CallIndicatorsUpdates::default()
370 };
371 assert_eq!(a.difference(b), expected);
372 }
373
374 #[fuchsia::test]
375 fn call_indicator_updates_is_empty() {
376 let mut updates = CallIndicatorsUpdates::default();
377 assert!(updates.is_empty());
378
379 updates.call = Some(Call::Some);
380 assert!(!updates.is_empty());
381
382 let mut updates = CallIndicatorsUpdates::default();
383 updates.callsetup = Some(CallSetup::Incoming);
384 assert!(!updates.is_empty());
385
386 let mut updates = CallIndicatorsUpdates::default();
387 updates.callwaiting = true;
388 assert!(!updates.is_empty());
389
390 let mut updates = CallIndicatorsUpdates::default();
391 updates.callheld = Some(CallHeld::Held);
392 assert!(!updates.is_empty());
393 }
394}