Commit 5c4c4206 authored by Derek Cheng's avatar Derek Cheng Committed by Commit Bot

[Cast MRP] Implement capabilities filtering.

In addition to app availability, the CastAppDiscoveryService will now
check the required capabilities in the MediaSource against the
capabilities supported by a sink. A sink is only returned if both
conditions are satisfied.

Bug: 809249
Change-Id: I5c6f3685db44b28560c575892637117e9ad8d711
Reviewed-on: https://chromium-review.googlesource.com/1089461
Commit-Queue: Derek Cheng <imcheng@chromium.org>
Reviewed-by: default avatarTakumi Fujimoto <takumif@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566191}
parent ceda663f
...@@ -125,23 +125,4 @@ std::vector<std::string> CastAppAvailabilityTracker::GetRegisteredApps() const { ...@@ -125,23 +125,4 @@ std::vector<std::string> CastAppAvailabilityTracker::GetRegisteredApps() const {
return registered_apps; return registered_apps;
} }
base::flat_set<MediaSink::Id> CastAppAvailabilityTracker::GetAvailableSinks(
const CastMediaSource& source) const {
base::flat_set<MediaSink::Id> sink_ids;
// For each sink, check if there is at least one available app in |source|.
for (const auto& availabilities : app_availabilities_) {
for (const auto& app_info : source.app_infos()) {
const auto& availabilities_map = availabilities.second;
auto availability_it = availabilities_map.find(app_info.app_id);
if (availability_it != availabilities_map.end() &&
availability_it->second.first ==
GetAppAvailabilityResult::kAvailable) {
sink_ids.insert(availabilities.first);
break;
}
}
}
return sink_ids;
}
} // namespace media_router } // namespace media_router
...@@ -95,11 +95,6 @@ class CastAppAvailabilityTracker { ...@@ -95,11 +95,6 @@ class CastAppAvailabilityTracker {
// Returns a list of registered app IDs. // Returns a list of registered app IDs.
std::vector<std::string> GetRegisteredApps() const; std::vector<std::string> GetRegisteredApps() const;
// Returns a list of sink IDs compatible with |source|, using the current
// availability info.
base::flat_set<MediaSink::Id> GetAvailableSinks(
const CastMediaSource& source) const;
private: private:
// App ID to availability. // App ID to availability.
using AppAvailabilityMap = base::flat_map<std::string, AppAvailability>; using AppAvailabilityMap = base::flat_map<std::string, AppAvailability>;
......
...@@ -110,34 +110,21 @@ TEST_F(CastAppAvailabilityTrackerTest, UpdateAppAvailability) { ...@@ -110,34 +110,21 @@ TEST_F(CastAppAvailabilityTrackerTest, UpdateAppAvailability) {
"sinkId1", "AAAAAAAA", {GetAppAvailabilityResult::kAvailable, Now()}), "sinkId1", "AAAAAAAA", {GetAppAvailabilityResult::kAvailable, Now()}),
CastMediaSourcesEqual(std::vector<CastMediaSource>())); CastMediaSourcesEqual(std::vector<CastMediaSource>()));
base::flat_set<MediaSink::Id> sinks_1 = {"sinkId1"};
base::flat_set<MediaSink::Id> sinks_1_2 = {"sinkId1", "sinkId2"};
std::vector<CastMediaSource> sources_1 = {*source1}; std::vector<CastMediaSource> sources_1 = {*source1};
std::vector<CastMediaSource> sources_1_2 = {*source1, *source2}; std::vector<CastMediaSource> sources_1_2 = {*source1, *source2};
// Tracker returns available sinks even though sources aren't registered.
EXPECT_EQ(sinks_1, tracker_.GetAvailableSinks(*source1));
EXPECT_EQ(sinks_1, tracker_.GetAvailableSinks(*source2));
EXPECT_TRUE(tracker_.GetAvailableSinks(*source3).empty());
tracker_.RegisterSource(*source1); tracker_.RegisterSource(*source1);
// Only |source1| is registered for this app. // Only |source1| is registered for this app.
EXPECT_THAT( EXPECT_THAT(
tracker_.UpdateAppAvailability( tracker_.UpdateAppAvailability(
"sinkId2", "AAAAAAAA", {GetAppAvailabilityResult::kAvailable, Now()}), "sinkId2", "AAAAAAAA", {GetAppAvailabilityResult::kAvailable, Now()}),
CastMediaSourcesEqual(sources_1)); CastMediaSourcesEqual(sources_1));
EXPECT_EQ(sinks_1_2, tracker_.GetAvailableSinks(*source1));
EXPECT_EQ(sinks_1_2, tracker_.GetAvailableSinks(*source2));
EXPECT_TRUE(tracker_.GetAvailableSinks(*source3).empty());
tracker_.RegisterSource(*source2); tracker_.RegisterSource(*source2);
EXPECT_THAT(tracker_.UpdateAppAvailability( EXPECT_THAT(tracker_.UpdateAppAvailability(
"sinkId2", "AAAAAAAA", "sinkId2", "AAAAAAAA",
{GetAppAvailabilityResult::kUnavailable, Now()}), {GetAppAvailabilityResult::kUnavailable, Now()}),
CastMediaSourcesEqual(sources_1_2)); CastMediaSourcesEqual(sources_1_2));
EXPECT_EQ(sinks_1, tracker_.GetAvailableSinks(*source1));
EXPECT_EQ(sinks_1, tracker_.GetAvailableSinks(*source2));
EXPECT_TRUE(tracker_.GetAvailableSinks(*source3).empty());
} }
TEST_F(CastAppAvailabilityTrackerTest, RemoveResultsForSink) { TEST_F(CastAppAvailabilityTrackerTest, RemoveResultsForSink) {
...@@ -149,20 +136,14 @@ TEST_F(CastAppAvailabilityTrackerTest, RemoveResultsForSink) { ...@@ -149,20 +136,14 @@ TEST_F(CastAppAvailabilityTrackerTest, RemoveResultsForSink) {
EXPECT_EQ(GetAppAvailabilityResult::kAvailable, EXPECT_EQ(GetAppAvailabilityResult::kAvailable,
tracker_.GetAvailability("sinkId1", "AAAAAAAA").first); tracker_.GetAvailability("sinkId1", "AAAAAAAA").first);
base::flat_set<MediaSink::Id> expected_sink_ids = {"sinkId1"};
EXPECT_EQ(expected_sink_ids, tracker_.GetAvailableSinks(*source1));
// Unrelated sink ID. // Unrelated sink ID.
tracker_.RemoveResultsForSink("sinkId2"); tracker_.RemoveResultsForSink("sinkId2");
EXPECT_EQ(GetAppAvailabilityResult::kAvailable, EXPECT_EQ(GetAppAvailabilityResult::kAvailable,
tracker_.GetAvailability("sinkId1", "AAAAAAAA").first); tracker_.GetAvailability("sinkId1", "AAAAAAAA").first);
EXPECT_EQ(expected_sink_ids, tracker_.GetAvailableSinks(*source1));
expected_sink_ids.clear();
tracker_.RemoveResultsForSink("sinkId1"); tracker_.RemoveResultsForSink("sinkId1");
EXPECT_EQ(GetAppAvailabilityResult::kUnknown, EXPECT_EQ(GetAppAvailabilityResult::kUnknown,
tracker_.GetAvailability("sinkId1", "AAAAAAAA").first); tracker_.GetAvailability("sinkId1", "AAAAAAAA").first);
EXPECT_EQ(expected_sink_ids, tracker_.GetAvailableSinks(*source1));
} }
} // namespace media_router } // namespace media_router
...@@ -35,6 +35,12 @@ bool ShouldRefreshAppAvailability( ...@@ -35,6 +35,12 @@ bool ShouldRefreshAppAvailability(
return false; return false;
} }
bool HasAllRequiredCapabilities(int required_capabilities,
const MediaSinkInternal& sink) {
return (required_capabilities & sink.cast_data().capabilities) ==
required_capabilities;
}
} // namespace } // namespace
CastAppDiscoveryServiceImpl::CastAppDiscoveryServiceImpl( CastAppDiscoveryServiceImpl::CastAppDiscoveryServiceImpl(
...@@ -68,11 +74,10 @@ CastAppDiscoveryServiceImpl::StartObservingMediaSinks( ...@@ -68,11 +74,10 @@ CastAppDiscoveryServiceImpl::StartObservingMediaSinks(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const MediaSource::Id& source_id = source.source_id(); const MediaSource::Id& source_id = source.source_id();
// Returned cached results immediately, if available. // Return cached results immediately, if available.
base::flat_set<MediaSink::Id> cached_sink_ids = auto cached_sinks = GetAvailableSinks(source);
availability_tracker_.GetAvailableSinks(source); if (!cached_sinks.empty())
if (!cached_sink_ids.empty()) callback.Run(source_id, cached_sinks);
callback.Run(source_id, GetSinksByIds(cached_sink_ids));
auto& callback_list = sink_queries_[source_id]; auto& callback_list = sink_queries_[source_id];
if (!callback_list) { if (!callback_list) {
...@@ -214,21 +219,36 @@ void CastAppDiscoveryServiceImpl::UpdateSinkQueries( ...@@ -214,21 +219,36 @@ void CastAppDiscoveryServiceImpl::UpdateSinkQueries(
auto it = sink_queries_.find(source_id); auto it = sink_queries_.find(source_id);
if (it == sink_queries_.end()) if (it == sink_queries_.end())
continue; continue;
base::flat_set<MediaSink::Id> sink_ids = it->second->Notify(source_id, GetAvailableSinks(source));
availability_tracker_.GetAvailableSinks(source); }
it->second->Notify(source_id, GetSinksByIds(sink_ids)); }
bool CastAppDiscoveryServiceImpl::SinkSupportsSource(
const MediaSinkInternal& sink,
const CastMediaSource& source) const {
const auto& app_infos = source.app_infos();
for (const auto& app_info : app_infos) {
auto required_capabilities = app_info.required_capabilities;
auto availability =
availability_tracker_.GetAvailability(sink.sink().id(), app_info.app_id)
.first;
if (availability == cast_channel::GetAppAvailabilityResult::kAvailable &&
HasAllRequiredCapabilities(required_capabilities, sink)) {
return true;
}
} }
return false;
} }
std::vector<MediaSinkInternal> CastAppDiscoveryServiceImpl::GetSinksByIds( std::vector<MediaSinkInternal> CastAppDiscoveryServiceImpl::GetAvailableSinks(
const base::flat_set<MediaSink::Id>& sink_ids) const { const CastMediaSource& source) const {
std::vector<MediaSinkInternal> sinks; const auto& sinks = media_sink_service_->GetSinks();
for (const auto& sink_id : sink_ids) { std::vector<MediaSinkInternal> available_sinks;
const MediaSinkInternal* sink = media_sink_service_->GetSinkById(sink_id); for (const auto& sink : sinks) {
if (sink) if (SinkSupportsSource(sink.second, source))
sinks.push_back(*sink); available_sinks.push_back(sink.second);
} }
return sinks; return available_sinks;
} }
} // namespace media_router } // namespace media_router
...@@ -114,9 +114,14 @@ class CastAppDiscoveryServiceImpl : public CastAppDiscoveryService, ...@@ -114,9 +114,14 @@ class CastAppDiscoveryServiceImpl : public CastAppDiscoveryService,
// associated with |source|. // associated with |source|.
void MaybeRemoveSinkQueryEntry(const CastMediaSource& source); void MaybeRemoveSinkQueryEntry(const CastMediaSource& source);
// Gets a list of sinks corresponding to |sink_ids|. // Returns true if |sink| supports |source|, based on both app availability
std::vector<MediaSinkInternal> GetSinksByIds( // and required capabilities.
const base::flat_set<MediaSink::Id>& sink_ids) const; bool SinkSupportsSource(const MediaSinkInternal& sink,
const CastMediaSource& source) const;
// Returns a list of sinks that supports |source|.
std::vector<MediaSinkInternal> GetAvailableSinks(
const CastMediaSource& source) const;
// Registered sink queries and their associated callbacks. // Registered sink queries and their associated callbacks.
base::flat_map<MediaSource::Id, std::unique_ptr<SinkQueryCallbackList>> base::flat_map<MediaSource::Id, std::unique_ptr<SinkQueryCallbackList>>
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
using cast_channel::GetAppAvailabilityResult; using cast_channel::GetAppAvailabilityResult;
using testing::_; using testing::_;
using testing::Invoke; using testing::Invoke;
using testing::IsEmpty;
namespace media_router { namespace media_router {
...@@ -32,9 +33,13 @@ class CastAppDiscoveryServiceTest : public testing::Test { ...@@ -32,9 +33,13 @@ class CastAppDiscoveryServiceTest : public testing::Test {
&socket_service_, &socket_service_,
&media_sink_service_, &media_sink_service_,
&clock_)), &clock_)),
source_a_1_(*CastMediaSource::From("cast:AAAAAAAA?clientId=1")), source_a_1_(*CastMediaSource::From(
source_a_2_(*CastMediaSource::From("cast:AAAAAAAA?clientId=2")), "cast:AAAAAAAA?clientId=1&capabilities=video_out,audio_out")),
source_b_1_(*CastMediaSource::From("cast:BBBBBBBB?clientId=1")) { source_a_2_(*CastMediaSource::From(
"cast:AAAAAAAA?clientId=2&capabilities=video_out,audio_out")),
source_b_1_(*CastMediaSource::From(
"cast:BBBBBBBB?clientId=1&capabilities=video_out,audio_out")),
sink1_(CreateCastSink(1)) {
ON_CALL(socket_service_, GetSocket(_)) ON_CALL(socket_service_, GetSocket(_))
.WillByDefault(testing::Return(&socket_)); .WillByDefault(testing::Return(&socket_));
task_runner_->RunPendingTasks(); task_runner_->RunPendingTasks();
...@@ -75,6 +80,7 @@ class CastAppDiscoveryServiceTest : public testing::Test { ...@@ -75,6 +80,7 @@ class CastAppDiscoveryServiceTest : public testing::Test {
CastMediaSource source_a_1_; CastMediaSource source_a_1_;
CastMediaSource source_a_2_; CastMediaSource source_a_2_;
CastMediaSource source_b_1_; CastMediaSource source_b_1_;
MediaSinkInternal sink1_;
private: private:
DISALLOW_COPY_AND_ASSIGN(CastAppDiscoveryServiceTest); DISALLOW_COPY_AND_ASSIGN(CastAppDiscoveryServiceTest);
...@@ -85,7 +91,6 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinks) { ...@@ -85,7 +91,6 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinks) {
// Adding a sink after app registered causes app availability request to be // Adding a sink after app registered causes app availability request to be
// sent. // sent.
MediaSinkInternal sink1 = CreateCastSink(1);
cast_channel::GetAppAvailabilityCallback cb; cast_channel::GetAppAvailabilityCallback cb;
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)) EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _))
.WillOnce( .WillOnce(
...@@ -94,7 +99,7 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinks) { ...@@ -94,7 +99,7 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinks) {
cb = std::move(callback); cb = std::move(callback);
})); }));
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
// Same app ID should not trigger another request. // Same app ID should not trigger another request.
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, _, _)).Times(0); EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, _, _)).Times(0);
...@@ -103,7 +108,7 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinks) { ...@@ -103,7 +108,7 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinks) {
base::BindRepeating(&CastAppDiscoveryServiceTest::OnSinkQueryUpdated, base::BindRepeating(&CastAppDiscoveryServiceTest::OnSinkQueryUpdated,
base::Unretained(this))); base::Unretained(this)));
std::vector<MediaSinkInternal> sinks_1 = {sink1}; std::vector<MediaSinkInternal> sinks_1 = {sink1_};
EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1)); EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1));
EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_2_.source_id(), sinks_1)); EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_2_.source_id(), sinks_1));
std::move(cb).Run("AAAAAAAA", GetAppAvailabilityResult::kAvailable); std::move(cb).Run("AAAAAAAA", GetAppAvailabilityResult::kAvailable);
...@@ -111,9 +116,8 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinks) { ...@@ -111,9 +116,8 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinks) {
// No more updates for |source_a_1_|. // No more updates for |source_a_1_|.
subscription1.reset(); subscription1.reset();
EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), _)).Times(0); EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), _)).Times(0);
EXPECT_CALL(*this, EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_2_.source_id(), IsEmpty()));
OnSinkQueryUpdated(source_a_2_.source_id(), testing::IsEmpty())); RemoveSink(sink1_);
RemoveSink(sink1);
} }
TEST_F(CastAppDiscoveryServiceTest, SinkQueryUpdatedOnSinkUpdate) { TEST_F(CastAppDiscoveryServiceTest, SinkQueryUpdatedOnSinkUpdate) {
...@@ -121,7 +125,6 @@ TEST_F(CastAppDiscoveryServiceTest, SinkQueryUpdatedOnSinkUpdate) { ...@@ -121,7 +125,6 @@ TEST_F(CastAppDiscoveryServiceTest, SinkQueryUpdatedOnSinkUpdate) {
// Adding a sink after app registered causes app availability request to be // Adding a sink after app registered causes app availability request to be
// sent. // sent.
MediaSinkInternal sink1 = CreateCastSink(1);
cast_channel::GetAppAvailabilityCallback cb; cast_channel::GetAppAvailabilityCallback cb;
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)) EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _))
.WillOnce( .WillOnce(
...@@ -130,25 +133,24 @@ TEST_F(CastAppDiscoveryServiceTest, SinkQueryUpdatedOnSinkUpdate) { ...@@ -130,25 +133,24 @@ TEST_F(CastAppDiscoveryServiceTest, SinkQueryUpdatedOnSinkUpdate) {
cb = std::move(callback); cb = std::move(callback);
})); }));
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
// Query now includes |sink1|. // Query now includes |sink1_|.
std::vector<MediaSinkInternal> sinks_1 = {sink1}; std::vector<MediaSinkInternal> sinks_1 = {sink1_};
EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1)); EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1));
std::move(cb).Run("AAAAAAAA", GetAppAvailabilityResult::kAvailable); std::move(cb).Run("AAAAAAAA", GetAppAvailabilityResult::kAvailable);
// Updating |sink1| causes |source_a_1_| query to be updated. // Updating |sink1| causes |source_a_1_| query to be updated.
sink1.sink().set_name("Updated name"); sink1_.sink().set_name("Updated name");
sinks_1 = {sink1}; sinks_1 = {sink1_};
EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1)); EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1));
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
} }
TEST_F(CastAppDiscoveryServiceTest, Refresh) { TEST_F(CastAppDiscoveryServiceTest, Refresh) {
auto subscription1 = StartObservingMediaSinksInitially(source_a_1_); auto subscription1 = StartObservingMediaSinksInitially(source_a_1_);
auto subscription2 = StartObservingMediaSinksInitially(source_b_1_); auto subscription2 = StartObservingMediaSinksInitially(source_b_1_);
MediaSinkInternal sink1 = CreateCastSink(1);
EXPECT_CALL(*this, OnSinkQueryUpdated(_, _)); EXPECT_CALL(*this, OnSinkQueryUpdated(_, _));
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)) EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _))
.WillOnce(Invoke([](cast_channel::CastSocket*, const std::string& app_id, .WillOnce(Invoke([](cast_channel::CastSocket*, const std::string& app_id,
...@@ -160,7 +162,7 @@ TEST_F(CastAppDiscoveryServiceTest, Refresh) { ...@@ -160,7 +162,7 @@ TEST_F(CastAppDiscoveryServiceTest, Refresh) {
cast_channel::GetAppAvailabilityCallback& callback) { cast_channel::GetAppAvailabilityCallback& callback) {
std::move(callback).Run(app_id, GetAppAvailabilityResult::kUnknown); std::move(callback).Run(app_id, GetAppAvailabilityResult::kUnknown);
})); }));
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
MediaSinkInternal sink2 = CreateCastSink(2); MediaSinkInternal sink2 = CreateCastSink(2);
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)) EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _))
...@@ -196,9 +198,8 @@ TEST_F(CastAppDiscoveryServiceTest, Refresh) { ...@@ -196,9 +198,8 @@ TEST_F(CastAppDiscoveryServiceTest, Refresh) {
TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinksAfterSinkAdded) { TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinksAfterSinkAdded) {
// No registered apps. // No registered apps.
MediaSinkInternal sink1 = CreateCastSink(1);
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, _, _)).Times(0); EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, _, _)).Times(0);
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)); EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _));
auto subscription1 = app_discovery_service_->StartObservingMediaSinks( auto subscription1 = app_discovery_service_->StartObservingMediaSinks(
...@@ -225,7 +226,6 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinksCachedValue) { ...@@ -225,7 +226,6 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinksCachedValue) {
// Adding a sink after app registered causes app availability request to be // Adding a sink after app registered causes app availability request to be
// sent. // sent.
MediaSinkInternal sink1 = CreateCastSink(1);
cast_channel::GetAppAvailabilityCallback cb; cast_channel::GetAppAvailabilityCallback cb;
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)) EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _))
.WillOnce( .WillOnce(
...@@ -233,9 +233,9 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinksCachedValue) { ...@@ -233,9 +233,9 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinksCachedValue) {
cast_channel::GetAppAvailabilityCallback& callback) { cast_channel::GetAppAvailabilityCallback& callback) {
cb = std::move(callback); cb = std::move(callback);
})); }));
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
std::vector<MediaSinkInternal> sinks_1 = {sink1}; std::vector<MediaSinkInternal> sinks_1 = {sink1_};
EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1)); EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1));
std::move(cb).Run("AAAAAAAA", GetAppAvailabilityResult::kAvailable); std::move(cb).Run("AAAAAAAA", GetAppAvailabilityResult::kAvailable);
...@@ -249,7 +249,7 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinksCachedValue) { ...@@ -249,7 +249,7 @@ TEST_F(CastAppDiscoveryServiceTest, StartObservingMediaSinksCachedValue) {
base::Unretained(this))); base::Unretained(this)));
// Same source as |source_a_1_|. The callback will be invoked. // Same source as |source_a_1_|. The callback will be invoked.
auto source3 = CastMediaSource::From("cast:AAAAAAAA?clientId=1"); auto source3 = CastMediaSource::From(source_a_1_.source_id());
ASSERT_TRUE(source3); ASSERT_TRUE(source3);
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, _, _)).Times(0); EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, _, _)).Times(0);
EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1)); EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1));
...@@ -264,14 +264,13 @@ TEST_F(CastAppDiscoveryServiceTest, AvailabilityUnknownOrUnavailable) { ...@@ -264,14 +264,13 @@ TEST_F(CastAppDiscoveryServiceTest, AvailabilityUnknownOrUnavailable) {
// Adding a sink after app registered causes app availability request to be // Adding a sink after app registered causes app availability request to be
// sent. // sent.
MediaSinkInternal sink1 = CreateCastSink(1);
EXPECT_CALL(*this, OnSinkQueryUpdated(_, _)).Times(0); EXPECT_CALL(*this, OnSinkQueryUpdated(_, _)).Times(0);
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)) EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _))
.WillOnce(Invoke([](cast_channel::CastSocket*, const std::string&, .WillOnce(Invoke([](cast_channel::CastSocket*, const std::string&,
cast_channel::GetAppAvailabilityCallback& callback) { cast_channel::GetAppAvailabilityCallback& callback) {
std::move(callback).Run("AAAAAAAA", GetAppAvailabilityResult::kUnknown); std::move(callback).Run("AAAAAAAA", GetAppAvailabilityResult::kUnknown);
})); }));
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
// Sink updated and unknown app availability will cause request to be sent // Sink updated and unknown app availability will cause request to be sent
// again. // again.
...@@ -282,20 +281,43 @@ TEST_F(CastAppDiscoveryServiceTest, AvailabilityUnknownOrUnavailable) { ...@@ -282,20 +281,43 @@ TEST_F(CastAppDiscoveryServiceTest, AvailabilityUnknownOrUnavailable) {
std::move(callback).Run("AAAAAAAA", std::move(callback).Run("AAAAAAAA",
GetAppAvailabilityResult::kUnavailable); GetAppAvailabilityResult::kUnavailable);
})); }));
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
// Known availability -- no request sent. // Known availability -- no request sent.
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)) EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _))
.Times(0); .Times(0);
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
// Removing the sink will also remove previous availability information. // Removing the sink will also remove previous availability information.
// Next time sink is added, request will be sent. // Next time sink is added, request will be sent.
EXPECT_CALL(*this, OnSinkQueryUpdated(_, _)).Times(0); EXPECT_CALL(*this, OnSinkQueryUpdated(_, _)).Times(0);
RemoveSink(sink1); RemoveSink(sink1_);
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _)); EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _));
AddOrUpdateSink(sink1); AddOrUpdateSink(sink1_);
}
TEST_F(CastAppDiscoveryServiceTest, CapabilitiesFiltering) {
// Make |sink1_| an audio only device.
sink1_.cast_data().capabilities =
cast_channel::CastDeviceCapability::AUDIO_OUT;
AddOrUpdateSink(sink1_);
cast_channel::GetAppAvailabilityCallback cb;
EXPECT_CALL(message_handler_, DoRequestAppAvailability(_, "AAAAAAAA", _))
.WillOnce(testing::WithArg<2>(
[&cb](cast_channel::GetAppAvailabilityCallback& callback) {
cb = std::move(callback);
}));
auto subscription1 = app_discovery_service_->StartObservingMediaSinks(
source_a_1_,
base::BindRepeating(&CastAppDiscoveryServiceTest::OnSinkQueryUpdated,
base::Unretained(this)));
// Even though the app is available, the sink does not fulfill the required
// capabilities.
EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), IsEmpty()));
std::move(cb).Run("AAAAAAAA", GetAppAvailabilityResult::kAvailable);
} }
} // namespace media_router } // namespace media_router
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment