aboutsummaryrefslogtreecommitdiff
path: root/cast/sender/cast_app_availability_tracker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cast/sender/cast_app_availability_tracker.cc')
-rw-r--r--cast/sender/cast_app_availability_tracker.cc165
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