1 /* 2 * Copyright (C) 2022 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 android.mediapc.cts.common; 18 19 import android.util.Log; 20 21 import androidx.annotation.Nullable; 22 23 import com.android.compatibility.common.util.ReportLog; 24 import com.android.compatibility.common.util.ResultType; 25 import com.android.compatibility.common.util.ResultUnit; 26 27 import com.google.common.annotations.VisibleForTesting; 28 import com.google.common.collect.ImmutableMap; 29 30 import java.util.HashMap; 31 import java.util.Map; 32 33 /** 34 * Performance Class Requirement maps and req id to a set of {@link RequiredMeasurement}. 35 */ 36 public abstract class Requirement { 37 private static final String TAG = Requirement.class.getSimpleName(); 38 39 protected final ImmutableMap<String, RequiredMeasurement<?>> mRequiredMeasurements; 40 public final String id; 41 public final String cddId; 42 public final @Nullable String configId; 43 public final @Nullable String variantId; 44 Requirement(String id, String cddId, RequiredMeasurement<?>[] reqs)45 protected Requirement(String id, String cddId, RequiredMeasurement<?>[] reqs) { 46 this(id, cddId, null, null, reqs); 47 } 48 Requirement( String id, String cddId, @Nullable String configId, @Nullable String variantId, RequiredMeasurement<?>[] reqs)49 protected Requirement( 50 String id, 51 String cddId, 52 @Nullable String configId, 53 @Nullable String variantId, 54 RequiredMeasurement<?>[] reqs) { 55 this.id = id; 56 this.cddId = cddId; 57 this.configId = configId; 58 this.variantId = variantId; 59 60 ImmutableMap.Builder<String, RequiredMeasurement<?>> reqBuilder = 61 ImmutableMap.<String, RequiredMeasurement<?>>builder(); 62 for (RequiredMeasurement<?> r: reqs) { 63 reqBuilder.put(r.id(), r); 64 } 65 this.mRequiredMeasurements = reqBuilder.build(); 66 } 67 id()68 public String id() { 69 return this.id; 70 } 71 allMeasuredValuesSet()72 boolean allMeasuredValuesSet() { 73 return mRequiredMeasurements.values().stream().allMatch(rm -> rm.isMeasuredValueSet()); 74 } 75 76 /** Returns id cddId with config and variant if available. */ toString()77 public String toString() { 78 if (configId == null && variantId == null) { 79 return "[%s]".formatted(cddId); 80 } 81 if (variantId == null) { 82 return "[%s] (config=\"%s\")".formatted(cddId, configId); 83 } 84 if (configId == null) { 85 return "[%s] (variant=\"%s\")".formatted(cddId, variantId); 86 } 87 return "[%s] (config=\"%s\", variant=\"%s\")".formatted(cddId, configId, variantId); 88 } 89 90 /** 91 * Finds the highest performance class where at least one RequiredMeasurement has result 92 * RequirementConstants.Result.MET and none have RequirementConstants.Result.UNMET 93 */ 94 @VisibleForTesting computePerformanceClass()95 protected int computePerformanceClass() { 96 Map<Integer, RequirementConstants.Result> overallPerfClassResults = new HashMap<>(); 97 98 for (RequiredMeasurement<?> rm: this.mRequiredMeasurements.values()) { 99 Map<Integer, RequirementConstants.Result> perfClassResults = rm.getPerformanceClass(); 100 101 for (Integer pc: perfClassResults.keySet()) { 102 RequirementConstants.Result res = perfClassResults.get(pc); 103 104 // if one or more results are UNMET, mark the performance class as UNMET 105 // otherwise if at least 1 of the results is MET, mark the performance class as MET 106 if (res == RequirementConstants.Result.UNMET) { 107 overallPerfClassResults.put(pc, RequirementConstants.Result.UNMET); 108 } else if (!overallPerfClassResults.containsKey(pc) && 109 res == RequirementConstants.Result.MET) { 110 overallPerfClassResults.put(pc, RequirementConstants.Result.MET); 111 } 112 } 113 } 114 115 // report the highest performance class that has been MET 116 int perfClass = 0; 117 for (int pc: overallPerfClassResults.keySet()) { 118 if (overallPerfClassResults.get(pc) == RequirementConstants.Result.MET) { 119 perfClass = Math.max(perfClass, pc); 120 } 121 } 122 return perfClass; 123 } 124 125 /** Is this requirement valid for the given performance class */ appliesToPerformanceClass(int pc)126 protected boolean appliesToPerformanceClass(int pc) { 127 return mRequiredMeasurements.values().stream() 128 .anyMatch(rm -> rm.appliesToPerformanceClass(pc)); 129 } 130 131 @VisibleForTesting checkPerformanceClass(int devicePerfClass)132 protected boolean checkPerformanceClass(int devicePerfClass) { 133 boolean noResultsUnment = true; 134 for (RequiredMeasurement<?> rm: this.mRequiredMeasurements.values()) { 135 RequirementConstants.Result res = rm.meetsPerformanceClass(devicePerfClass); 136 if (res == RequirementConstants.Result.UNMET) { 137 Log.w(Requirement.TAG, this + " " + rm.toString()); 138 noResultsUnment = false; 139 } else { 140 Log.i(Requirement.TAG, this + " " + rm.toString()); 141 } 142 } 143 return noResultsUnment; 144 } 145 setMeasuredValue(String measurement, T measuredValue)146 protected <T> void setMeasuredValue(String measurement, T measuredValue) { 147 RequiredMeasurement<T> rm = 148 (RequiredMeasurement<T>) this.mRequiredMeasurements.get(measurement); 149 rm.setMeasuredValue(measuredValue); 150 } 151 getMeasuredValue(String measurement, Class<T> clazz)152 protected <T> T getMeasuredValue(String measurement, Class<T> clazz) { 153 RequiredMeasurement<T> rm = 154 (RequiredMeasurement<T>) this.mRequiredMeasurements.get(measurement); 155 return clazz.cast(rm.getMeasuredValue()); 156 } 157 158 /** 159 * @return whether or not the requirement meets the device's specified performance class 160 */ writeLogAndCheck(ReportLog log, String testName)161 public boolean writeLogAndCheck(ReportLog log, String testName) { 162 163 int perfClass = this.computePerformanceClass(); 164 165 log.addValue(RequirementConstants.TN_FIELD_NAME, testName, ResultType.NEUTRAL, 166 ResultUnit.NONE); 167 for (RequiredMeasurement rm: this.mRequiredMeasurements.values()) { 168 rm.writeValue(log); 169 } 170 log.addValue(RequirementConstants.PC_FIELD_NAME, perfClass, ResultType.NEUTRAL, 171 ResultUnit.NONE); 172 173 return this.checkPerformanceClass(Utils.getPerfClass()); 174 } 175 } 176