diff options
Diffstat (limited to 'cast/sender/cast_app_availability_tracker.cc')
-rw-r--r-- | cast/sender/cast_app_availability_tracker.cc | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/cast/sender/cast_app_availability_tracker.cc b/cast/sender/cast_app_availability_tracker.cc new file mode 100644 index 00000000..6c21c799 --- /dev/null +++ b/cast/sender/cast_app_availability_tracker.cc @@ -0,0 +1,165 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cast/sender/cast_app_availability_tracker.h" + +#include "util/logging.h" + +namespace openscreen { +namespace cast { + +CastAppAvailabilityTracker::CastAppAvailabilityTracker() = default; +CastAppAvailabilityTracker::~CastAppAvailabilityTracker() = default; + +std::vector<std::string> CastAppAvailabilityTracker::RegisterSource( + const CastMediaSource& source) { + if (registered_sources_.find(source.source_id()) != + registered_sources_.end()) { + return {}; + } + + registered_sources_.emplace(source.source_id(), source); + + std::vector<std::string> new_app_ids; + for (const std::string& app_id : source.app_ids()) { + if (++registration_count_by_app_id_[app_id] == 1) { + new_app_ids.push_back(app_id); + } + } + return new_app_ids; +} + +void CastAppAvailabilityTracker::UnregisterSource( + const CastMediaSource& source) { + UnregisterSource(source.source_id()); +} + +void CastAppAvailabilityTracker::UnregisterSource( + const std::string& source_id) { + auto it = registered_sources_.find(source_id); + if (it == registered_sources_.end()) { + return; + } + + for (const std::string& app_id : it->second.app_ids()) { + auto count_it = registration_count_by_app_id_.find(app_id); + OSP_DCHECK(count_it != registration_count_by_app_id_.end()); + if (--(count_it->second) == 0) { + registration_count_by_app_id_.erase(count_it); + } + } + + registered_sources_.erase(it); +} + +std::vector<CastMediaSource> CastAppAvailabilityTracker::UpdateAppAvailability( + const std::string& device_id, + const std::string& app_id, + AppAvailability availability) { + auto& availabilities = app_availabilities_[device_id]; + auto it = availabilities.find(app_id); + + AppAvailabilityResult old_availability = it == availabilities.end() + ? AppAvailabilityResult::kUnknown + : it->second.availability; + AppAvailabilityResult new_availability = availability.availability; + + // Updated if status changes from/to kAvailable. + bool updated = (old_availability == AppAvailabilityResult::kAvailable || + new_availability == AppAvailabilityResult::kAvailable) && + old_availability != new_availability; + availabilities[app_id] = availability; + + if (!updated) { + return {}; + } + + std::vector<CastMediaSource> affected_sources; + for (const auto& source : registered_sources_) { + if (source.second.ContainsAppId(app_id)) { + affected_sources.push_back(source.second); + } + } + return affected_sources; +} + +std::vector<CastMediaSource> CastAppAvailabilityTracker::RemoveResultsForDevice( + const std::string& device_id) { + auto affected_sources = GetSupportedSources(device_id); + app_availabilities_.erase(device_id); + return affected_sources; +} + +std::vector<CastMediaSource> CastAppAvailabilityTracker::GetSupportedSources( + const std::string& device_id) const { + auto it = app_availabilities_.find(device_id); + if (it == app_availabilities_.end()) { + return std::vector<CastMediaSource>(); + } + + // Find all app IDs that are available on the device. + std::vector<std::string> supported_app_ids; + for (const auto& availability : it->second) { + if (availability.second.availability == AppAvailabilityResult::kAvailable) { + supported_app_ids.push_back(availability.first); + } + } + + // Find all registered sources whose query results contain the device ID. + std::vector<CastMediaSource> sources; + for (const auto& source : registered_sources_) { + if (source.second.ContainsAnyAppIdFrom(supported_app_ids)) { + sources.push_back(source.second); + } + } + return sources; +} + +CastAppAvailabilityTracker::AppAvailability +CastAppAvailabilityTracker::GetAvailability(const std::string& device_id, + const std::string& app_id) const { + auto availabilities_it = app_availabilities_.find(device_id); + if (availabilities_it == app_availabilities_.end()) { + return {AppAvailabilityResult::kUnknown, Clock::time_point{}}; + } + + const auto& availability_map = availabilities_it->second; + auto availability_it = availability_map.find(app_id); + if (availability_it == availability_map.end()) { + return {AppAvailabilityResult::kUnknown, Clock::time_point{}}; + } + + return availability_it->second; +} + +std::vector<std::string> CastAppAvailabilityTracker::GetRegisteredApps() const { + std::vector<std::string> registered_apps; + for (const auto& app_ids_and_count : registration_count_by_app_id_) { + registered_apps.push_back(app_ids_and_count.first); + } + + return registered_apps; +} + +std::vector<std::string> CastAppAvailabilityTracker::GetAvailableDevices( + const CastMediaSource& source) const { + std::vector<std::string> device_ids; + // For each device, check if there is at least one available app in |source|. + for (const auto& availabilities : app_availabilities_) { + for (const std::string& app_id : source.app_ids()) { + const auto& availabilities_map = availabilities.second; + auto availability_it = availabilities_map.find(app_id); + if (availability_it != availabilities_map.end() && + availability_it->second.availability == + AppAvailabilityResult::kAvailable) { + device_ids.push_back(availabilities.first); + break; + } + } + } + return device_ids; +} + +} // namespace cast +} // namespace openscreen |