1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.vms; 18 19 import android.car.builtin.util.Slogf; 20 import android.car.vms.VmsAssociatedLayer; 21 import android.car.vms.VmsAvailableLayers; 22 import android.car.vms.VmsLayer; 23 import android.car.vms.VmsLayerDependency; 24 import android.car.vms.VmsLayersOffering; 25 import android.util.ArrayMap; 26 import android.util.ArraySet; 27 import android.util.Log; 28 29 import com.android.car.CarLog; 30 import com.android.internal.annotations.GuardedBy; 31 32 import java.util.Collection; 33 import java.util.Collections; 34 import java.util.Map; 35 import java.util.Set; 36 37 /** 38 * Manages VMS availability for layers. 39 * 40 * Each VMS publisher sets its layers offering which are a list of layers the publisher claims 41 * it might publish. VmsLayersAvailability calculates from all the offering what are the 42 * available layers. 43 */ 44 45 class VmsLayerAvailability { 46 private static final String TAG = CarLog.tagFor(VmsLayerAvailability.class); 47 private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG); 48 49 private final Object mLock = new Object(); 50 @GuardedBy("mLock") 51 private final Map<VmsLayer, Set<Set<VmsLayer>>> mPotentialLayersAndDependencies = 52 new ArrayMap<>(); 53 @GuardedBy("mLock") 54 private Set<VmsAssociatedLayer> mAvailableAssociatedLayers = Collections.emptySet(); 55 @GuardedBy("mLock") 56 private Map<VmsLayer, Set<Integer>> mPotentialLayersAndPublishers = new ArrayMap<>(); 57 @GuardedBy("mLock") 58 private int mSeq = 0; 59 60 /** 61 * Setting the current layers offerings as reported by publishers. 62 */ setPublishersOffering(Collection<VmsLayersOffering> publishersLayersOfferings)63 void setPublishersOffering(Collection<VmsLayersOffering> publishersLayersOfferings) { 64 synchronized (mLock) { 65 reset(); 66 67 for (VmsLayersOffering offering : publishersLayersOfferings) { 68 for (VmsLayerDependency dependency : offering.getDependencies()) { 69 VmsLayer layer = dependency.getLayer(); 70 71 // Associate publishers with layers. 72 mPotentialLayersAndPublishers.computeIfAbsent(layer, k -> new ArraySet<>()) 73 .add(offering.getPublisherId()); 74 75 // Add dependencies for availability calculation. 76 mPotentialLayersAndDependencies.computeIfAbsent(layer, k -> new ArraySet<>()) 77 .add(dependency.getDependencies()); 78 } 79 } 80 calculateLayers(); 81 } 82 } 83 84 /** 85 * Returns a collection of all the layers which may be published. 86 */ getAvailableLayers()87 VmsAvailableLayers getAvailableLayers() { 88 synchronized (mLock) { 89 return new VmsAvailableLayers(mAvailableAssociatedLayers, mSeq); 90 } 91 } 92 reset()93 private void reset() { 94 synchronized (mLock) { 95 mPotentialLayersAndDependencies.clear(); 96 mPotentialLayersAndPublishers.clear(); 97 mAvailableAssociatedLayers = Collections.emptySet(); 98 mSeq += 1; 99 } 100 } 101 calculateLayers()102 private void calculateLayers() { 103 synchronized (mLock) { 104 ArraySet<VmsLayer> availableLayersSet = new ArraySet<>(); 105 ArraySet<VmsLayer> cyclicAvoidanceAuxiliarySet = new ArraySet<>(); 106 107 for (VmsLayer layer : mPotentialLayersAndDependencies.keySet()) { 108 addLayerToAvailabilityCalculationLocked(layer, 109 availableLayersSet, 110 cyclicAvoidanceAuxiliarySet); 111 } 112 113 ArraySet<VmsAssociatedLayer> associatedLayerSet = new ArraySet<>(); 114 for (int index = 0; index < availableLayersSet.size(); index++) { 115 VmsLayer availableLayer = availableLayersSet.valueAt(index); 116 VmsAssociatedLayer associatedLayer = new VmsAssociatedLayer(availableLayer, 117 mPotentialLayersAndPublishers.get(availableLayer)); 118 associatedLayerSet.add(associatedLayer); 119 } 120 mAvailableAssociatedLayers = Collections.unmodifiableSet(associatedLayerSet); 121 } 122 } 123 124 @GuardedBy("mLock") addLayerToAvailabilityCalculationLocked(VmsLayer layer, Set<VmsLayer> currentAvailableLayers, Set<VmsLayer> cyclicAvoidanceSet)125 private void addLayerToAvailabilityCalculationLocked(VmsLayer layer, 126 Set<VmsLayer> currentAvailableLayers, 127 Set<VmsLayer> cyclicAvoidanceSet) { 128 if (DBG) { 129 Slogf.d(TAG, "addLayerToAvailabilityCalculationLocked: checking layer: " + layer); 130 } 131 // If we already know that this layer is supported then we are done. 132 if (currentAvailableLayers.contains(layer)) { 133 return; 134 } 135 // If there is no offering for this layer we're done. 136 if (!mPotentialLayersAndDependencies.containsKey(layer)) { 137 return; 138 } 139 // Avoid cyclic dependency. 140 if (cyclicAvoidanceSet.contains(layer)) { 141 Slogf.e(TAG, "Detected a cyclic dependency: " + cyclicAvoidanceSet + " -> " + layer); 142 return; 143 } 144 // A layer may have multiple dependency sets. The layer is available if any dependency 145 // set is satisfied 146 for (Set<VmsLayer> dependencies : mPotentialLayersAndDependencies.get(layer)) { 147 // If layer does not have any dependencies then add to supported. 148 if (dependencies == null || dependencies.isEmpty()) { 149 currentAvailableLayers.add(layer); 150 return; 151 } 152 // Add the layer to cyclic avoidance set 153 cyclicAvoidanceSet.add(layer); 154 155 boolean isSupported = true; 156 for (VmsLayer dependency : dependencies) { 157 addLayerToAvailabilityCalculationLocked(dependency, 158 currentAvailableLayers, 159 cyclicAvoidanceSet); 160 161 if (!currentAvailableLayers.contains(dependency)) { 162 isSupported = false; 163 break; 164 } 165 } 166 cyclicAvoidanceSet.remove(layer); 167 168 if (isSupported) { 169 currentAvailableLayers.add(layer); 170 return; 171 } 172 } 173 } 174 } 175