Loading android/app/src/com/android/bluetooth/bass_client/BassClientService.java +3 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ public class BassClientService extends ProfileService { private static final int STATUS_LOCAL_STREAM_REQUESTED = 0; private static final int STATUS_LOCAL_STREAM_STREAMING = 1; private static final int STATUS_LOCAL_STREAM_SUSPENDED = 2; private static final int STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE = 3; // Do not modify without updating the HAL bt_le_audio.h files. // Match up with BroadcastState enum of bt_le_audio.h Loading Loading @@ -2308,6 +2309,8 @@ public class BassClientService extends ProfileService { } } else if (status == STATUS_LOCAL_STREAM_STREAMING) { Log.d(TAG, "Ignore STREAMING source status"); } else if (status == STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE) { suspendAllReceiversSourceSynchronization(); } } Loading android/app/src/com/android/bluetooth/le_audio/LeAudioStackEvent.java +3 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ public class LeAudioStackEvent { static final int STATUS_LOCAL_STREAM_REQUESTED = 0; static final int STATUS_LOCAL_STREAM_STREAMING = 1; static final int STATUS_LOCAL_STREAM_SUSPENDED = 2; static final int STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE = 3; // Do not modify without updating le_audio_types.h // Match up with defines of le_audio_types.h Loading Loading @@ -307,6 +308,8 @@ public class LeAudioStackEvent { return "STATUS_LOCAL_STREAM_STREAMING"; case STATUS_LOCAL_STREAM_SUSPENDED: return "STATUS_LOCAL_STREAM_SUSPENDED"; case STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE: return "STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE"; default: return "UNKNOWN"; } Loading system/bta/le_audio/client.cc +10 −0 Original line number Diff line number Diff line Loading @@ -3967,6 +3967,16 @@ class LeAudioClientImpl : public LeAudioClient { if (!remote_contexts.sink.any() && !remote_contexts.source.any()) { log::warn("Requested context type not available on the remote side"); if (com::android::bluetooth::flags::leaudio_no_context_validate_streaming_request() && source_monitor_mode_) { callbacks_->OnUnicastMonitorModeStatus( bluetooth::le_audio::types::kLeAudioDirectionSource, UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE); return false; } if (leAudioHealthStatus_) { leAudioHealthStatus_->AddStatisticForGroup( group, LeAudioHealthGroupStatType::STREAM_CONTEXT_NOT_AVAILABLE); Loading system/bta/le_audio/le_audio_client_test.cc +71 −0 Original line number Diff line number Diff line Loading @@ -10590,4 +10590,75 @@ TEST_F(UnicastTestHandoverMode, SetAllowedContextMask) { Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_); } TEST_F_WITH_FLAGS(UnicastTest, NoContextvalidateStreamingRequest, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG( TEST_BT, leaudio_no_context_validate_streaming_request))) { const RawAddress test_address0 = GetTestAddress(0); int group_id = bluetooth::groups::kGroupUnknown; available_snk_context_types_ = (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA) .value(); available_src_context_types_ = available_snk_context_types_; supported_snk_context_types_ = types::kLeAudioContextAllTypes.value(); supported_src_context_types_ = (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED) .value(); SetSampleDatabaseEarbudsValid( 1, test_address0, codec_spec_conf::kLeAudioLocationStereo, codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnConnectionState(ConnectionState::CONNECTED, test_address0)) .Times(1); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED)) .WillOnce(DoAll(SaveArg<1>(&group_id))); ConnectLeAudio(test_address0); ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); types::BidirectionalPair<types::AudioContexts> metadata = { .sink = types::AudioContexts(), .source = types::AudioContexts()}; EXPECT_CALL( mock_state_machine_, StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, metadata, _)) .Times(0); LeAudioClient::Get()->GroupSetActive(group_id); // Imitate activation of monitor mode do_in_main_thread( FROM_HERE, base::BindOnce(&LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()), bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */)); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); SyncOnMainLoop(); // Stop streaming and expect Service to be informed about straming suspension EXPECT_CALL( mock_audio_hal_client_callbacks_, OnUnicastMonitorModeStatus( bluetooth::le_audio::types::kLeAudioDirectionSource, UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE)) .Times(1); StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID, false, false); SyncOnMainLoop(); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_); } } // namespace bluetooth::le_audio system/include/hardware/bt_le_audio.h +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ enum class UnicastMonitorModeStatus { STREAMING_REQUESTED = 0, STREAMING, STREAMING_SUSPENDED, STREAMING_REQUESTED_NO_CONTEXT_VALIDATE, }; typedef enum { Loading Loading
android/app/src/com/android/bluetooth/bass_client/BassClientService.java +3 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ public class BassClientService extends ProfileService { private static final int STATUS_LOCAL_STREAM_REQUESTED = 0; private static final int STATUS_LOCAL_STREAM_STREAMING = 1; private static final int STATUS_LOCAL_STREAM_SUSPENDED = 2; private static final int STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE = 3; // Do not modify without updating the HAL bt_le_audio.h files. // Match up with BroadcastState enum of bt_le_audio.h Loading Loading @@ -2308,6 +2309,8 @@ public class BassClientService extends ProfileService { } } else if (status == STATUS_LOCAL_STREAM_STREAMING) { Log.d(TAG, "Ignore STREAMING source status"); } else if (status == STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE) { suspendAllReceiversSourceSynchronization(); } } Loading
android/app/src/com/android/bluetooth/le_audio/LeAudioStackEvent.java +3 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ public class LeAudioStackEvent { static final int STATUS_LOCAL_STREAM_REQUESTED = 0; static final int STATUS_LOCAL_STREAM_STREAMING = 1; static final int STATUS_LOCAL_STREAM_SUSPENDED = 2; static final int STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE = 3; // Do not modify without updating le_audio_types.h // Match up with defines of le_audio_types.h Loading Loading @@ -307,6 +308,8 @@ public class LeAudioStackEvent { return "STATUS_LOCAL_STREAM_STREAMING"; case STATUS_LOCAL_STREAM_SUSPENDED: return "STATUS_LOCAL_STREAM_SUSPENDED"; case STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE: return "STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE"; default: return "UNKNOWN"; } Loading
system/bta/le_audio/client.cc +10 −0 Original line number Diff line number Diff line Loading @@ -3967,6 +3967,16 @@ class LeAudioClientImpl : public LeAudioClient { if (!remote_contexts.sink.any() && !remote_contexts.source.any()) { log::warn("Requested context type not available on the remote side"); if (com::android::bluetooth::flags::leaudio_no_context_validate_streaming_request() && source_monitor_mode_) { callbacks_->OnUnicastMonitorModeStatus( bluetooth::le_audio::types::kLeAudioDirectionSource, UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE); return false; } if (leAudioHealthStatus_) { leAudioHealthStatus_->AddStatisticForGroup( group, LeAudioHealthGroupStatType::STREAM_CONTEXT_NOT_AVAILABLE); Loading
system/bta/le_audio/le_audio_client_test.cc +71 −0 Original line number Diff line number Diff line Loading @@ -10590,4 +10590,75 @@ TEST_F(UnicastTestHandoverMode, SetAllowedContextMask) { Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_); } TEST_F_WITH_FLAGS(UnicastTest, NoContextvalidateStreamingRequest, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG( TEST_BT, leaudio_no_context_validate_streaming_request))) { const RawAddress test_address0 = GetTestAddress(0); int group_id = bluetooth::groups::kGroupUnknown; available_snk_context_types_ = (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA) .value(); available_src_context_types_ = available_snk_context_types_; supported_snk_context_types_ = types::kLeAudioContextAllTypes.value(); supported_src_context_types_ = (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED) .value(); SetSampleDatabaseEarbudsValid( 1, test_address0, codec_spec_conf::kLeAudioLocationStereo, codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnConnectionState(ConnectionState::CONNECTED, test_address0)) .Times(1); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED)) .WillOnce(DoAll(SaveArg<1>(&group_id))); ConnectLeAudio(test_address0); ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); types::BidirectionalPair<types::AudioContexts> metadata = { .sink = types::AudioContexts(), .source = types::AudioContexts()}; EXPECT_CALL( mock_state_machine_, StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, metadata, _)) .Times(0); LeAudioClient::Get()->GroupSetActive(group_id); // Imitate activation of monitor mode do_in_main_thread( FROM_HERE, base::BindOnce(&LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()), bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */)); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); SyncOnMainLoop(); // Stop streaming and expect Service to be informed about straming suspension EXPECT_CALL( mock_audio_hal_client_callbacks_, OnUnicastMonitorModeStatus( bluetooth::le_audio::types::kLeAudioDirectionSource, UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE)) .Times(1); StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID, false, false); SyncOnMainLoop(); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_); } } // namespace bluetooth::le_audio
system/include/hardware/bt_le_audio.h +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ enum class UnicastMonitorModeStatus { STREAMING_REQUESTED = 0, STREAMING, STREAMING_SUSPENDED, STREAMING_REQUESTED_NO_CONTEXT_VALIDATE, }; typedef enum { Loading