rust/bt-bass: Apply BIS_Sync to new subgroups

Process bis_map after metadata_map in modify_broadcast_source so that
BIS_Sync settings for newly added subgroups are applied rather than
left at NO_PREFERENCE.

Bug: 539983871
Test: cargo test
Change-Id: Iea912a103ade5bac8ed8d2f31eb7de486b93cc7b
Reviewed-on: https://bluetooth-review.googlesource.com/c/bluetooth/+/3341
diff --git a/rust/bt-bass/src/client.rs b/rust/bt-bass/src/client.rs
index 62531ac..8970b1e 100644
--- a/rust/bt-bass/src/client.rs
+++ b/rust/bt-bass/src/client.rs
@@ -317,13 +317,6 @@
             .get_broadcast_source_state(&broadcast_id)
             .ok_or(Error::UnknownBroadcastSource(broadcast_id))?;
 
-        // Update BIS_Sync param for BIGs if applicable.
-        for (big_index, group) in state.subgroups.iter_mut().enumerate() {
-            if let Some(bis_sync) = bis_map.get(&(big_index as u8)) {
-                group.bis_sync = bis_sync.clone();
-            }
-        }
-
         // Update metadata for BIGs if applicable.
         if let Some(mut m) = metadata_map {
             for (big_index, group) in state.subgroups.iter_mut().enumerate() {
@@ -347,6 +340,13 @@
             }
         }
 
+        // Update BIS_Sync param for BIGs if applicable.
+        for (big_index, group) in state.subgroups.iter_mut().enumerate() {
+            if let Some(bis_sync) = bis_map.get(&(big_index as u8)) {
+                group.bis_sync = bis_sync.clone();
+            }
+        }
+
         let op = ModifySourceOperation::new(
             state.source_id,
             pa_sync,
@@ -819,7 +819,7 @@
                 0xFF, 0xFF, 0x02,                    // pa sync, pa interval, num of subgroups
                 0x15, 0x00, 0x00, 0x00,              // bis sync (0th subgroup)
                 0x02, 0x01, 0x09,                    // metadata len, metadata
-                0xFF, 0xFF, 0xFF, 0xFF,              // bis sync (1th subgroup)
+                0xFF, 0xFF, 0xFF, 0xFF,              // bis sync (1st subgroup)
                 0x05, 0x04, 0x04, 0x65, 0x6E, 0x67,  // metadata len, metadata
             ],
         );
@@ -842,6 +842,56 @@
     }
 
     #[test]
+    fn modify_broadcast_source_applies_bis_sync_to_new_subgroups() {
+        let (client, mut fake_peer_service) = setup_client();
+
+        client.broadcast_sources.lock().update_state(
+            RECEIVE_STATE_1_HANDLE,
+            BroadcastReceiveState::NonEmpty(ReceiveState {
+                source_id: 0x11,
+                source_address_type: AddressType::Public,
+                source_address: [1, 2, 3, 4, 5, 6],
+                source_adv_sid: AdvertisingSetId(1),
+                broadcast_id: BroadcastId::try_from(0x11).unwrap(),
+                pa_sync_state: PaSyncState::Synced,
+                big_encryption: EncryptionStatus::BroadcastCodeRequired,
+                subgroups: vec![BigSubgroup::new(None)],
+            }),
+        );
+
+        #[rustfmt::skip]
+        fake_peer_service.expect_characteristic_value(
+            &AUDIO_SCAN_CONTROL_POINT_HANDLE,
+            vec![
+                0x03, 0x11, 0x00,                    // opcode, source id, pa sync
+                0xFF, 0xFF, 0x02,                    // pa sync, pa interval, num of subgroups
+                0x15, 0x00, 0x00, 0x00,              // bis sync (0th subgroup)
+                0x02, 0x01, 0x09,                    // metadata len, metadata
+                0x0A, 0x00, 0x00, 0x00,              // bis sync for 1st subgroup (BIS index 2 and 4 = 0b00001010)
+                0x05, 0x04, 0x04, 0x65, 0x6E, 0x67,  // metadata len, metadata
+            ],
+        );
+
+        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
+        let op_fut = client.modify_broadcast_source(
+            BroadcastId::try_from(0x11).unwrap(),
+            PaSync::DoNotSync,
+            None,
+            HashMap::from([
+                (0, BisSync::sync(vec![1, 3, 5]).unwrap()),
+                (1, BisSync::sync(vec![2, 4]).unwrap()),
+            ]),
+            Some(HashMap::from([
+                (0, vec![Metadata::BroadcastAudioImmediateRenderingFlag]),
+                (1, vec![Metadata::Language("eng".to_string())]),
+            ])),
+        );
+        pin_mut!(op_fut);
+        let polled: Poll<Result<(), Error>> = op_fut.poll_unpin(&mut noop_cx);
+        assert_matches!(polled, Poll::Ready(Ok(_)));
+    }
+
+    #[test]
     fn modify_broadcast_source_fail() {
         let (client, _fake_peer_service) = setup_client();