From 7435b9a4e0ad8b8dbfdf8f78b3841d31b53b7c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Budnik?= Date: Wed, 5 Jul 2023 12:56:39 +0000 Subject: [PATCH] Optimize RouteListingPreference processing Also, avoid modifying input route lists. Bug: 192657812 Test: InfoMediaManagerTest Change-Id: I754e6f396e85628a844bd275c5be465f67018d9c --- .../settingslib/media/InfoMediaManager.java | 70 +++++++++++++++---- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index 832131c3462b9..7a48838ced91b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -66,11 +66,14 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; /** InfoMediaManager provide interface to get InfoMediaDevice list. */ @RequiresApi(Build.VERSION_CODES.R) @@ -693,25 +696,62 @@ public abstract class InfoMediaManager extends MediaManager { return filteredInfos; } + /** + * Returns an ordered list of available devices based on the provided {@code + * routeListingPreferenceItems}. + * + *

The result has the following order: + * + *

    + *
  1. Selected routes. + *
  2. Not-selected system routes. + *
  3. Not-selected, non-system, available routes sorted by route listing preference. + *
+ * + * @param selectedRoutes List of currently selected routes. + * @param availableRoutes List of available routes that match the app's requested route + * features. + * @param routeListingPreferenceItems Ordered list of {@link RouteListingPreference.Item} to + * sort routes with. + */ @DoNotInline static List arrangeRouteListByPreference( - List selectedRouteInfos, List infolist, - List preferenceRouteListing) { - final List sortedInfoList = new ArrayList<>(selectedRouteInfos); - infolist.removeAll(selectedRouteInfos); - sortedInfoList.addAll(infolist.stream().filter( - MediaRoute2Info::isSystemRoute).collect(Collectors.toList())); - for (RouteListingPreference.Item item : preferenceRouteListing) { - for (MediaRoute2Info info : infolist) { - if (item.getRouteId().equals(info.getId()) - && !selectedRouteInfos.contains(info) - && !info.isSystemRoute()) { - sortedInfoList.add(info); - break; - } + List selectedRoutes, + List availableRoutes, + List routeListingPreferenceItems) { + Set sortedRouteIds = new LinkedHashSet<>(); + + // Add selected routes first. + for (MediaRoute2Info selectedRoute : selectedRoutes) { + sortedRouteIds.add(selectedRoute.getId()); + } + + // Add not-yet-added system routes. + for (MediaRoute2Info availableRoute : availableRoutes) { + if (availableRoute.isSystemRoute()) { + sortedRouteIds.add(availableRoute.getId()); } } - return sortedInfoList; + + // Create a mapping from id to route to avoid a quadratic search. + Map idToRouteMap = + Stream.concat(selectedRoutes.stream(), availableRoutes.stream()) + .collect( + Collectors.toMap( + MediaRoute2Info::getId, + Function.identity(), + (route1, route2) -> route1)); + + // Add not-selected routes that match RLP items. All system routes have already been + // added at this point. + for (RouteListingPreference.Item item : routeListingPreferenceItems) { + MediaRoute2Info route = idToRouteMap.get(item.getRouteId()); + if (route != null) { + sortedRouteIds.add(route.getId()); + } + } + + return sortedRouteIds.stream().map(idToRouteMap::get).collect(Collectors.toList()); } @DoNotInline