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 com.android.compatibility.common.util.ReportLog; 22 import com.android.compatibility.common.util.ResultType; 23 import com.android.compatibility.common.util.ResultUnit; 24 25 import com.google.common.annotations.VisibleForTesting; 26 import com.google.common.collect.ImmutableMap; 27 28 import java.util.HashMap; 29 import java.util.Map; 30 31 /** 32 * Performance Class Requirement maps and req id to a set of {@link RequiredMeasurement}. 33 */ 34 public abstract class Requirement { 35 private static final String TAG = Requirement.class.getSimpleName(); 36 37 protected final ImmutableMap<String, RequiredMeasurement<?>> mRequiredMeasurements; 38 protected final String id; 39 Requirement(String id, RequiredMeasurement<?>[] reqs)40 protected Requirement(String id, RequiredMeasurement<?>[] reqs) { 41 this.id = id; 42 43 ImmutableMap.Builder<String, RequiredMeasurement<?>> reqBuilder = 44 ImmutableMap.<String, RequiredMeasurement<?>>builder(); 45 for (RequiredMeasurement<?> r: reqs) { 46 reqBuilder.put(r.id(), r); 47 } 48 this.mRequiredMeasurements = reqBuilder.build(); 49 } 50 id()51 public String id() { 52 return this.id; 53 } 54 55 /** 56 * Finds the highest performance class where at least one RequiremdMeasurement has result 57 * RequirementConstants.Result.MET and none have RequirementConstants.Result.UNMET 58 */ 59 @VisibleForTesting computePerformanceClass()60 protected int computePerformanceClass() { 61 Map<Integer, RequirementConstants.Result> overallPerfClassResults = new HashMap<>(); 62 63 for (RequiredMeasurement<?> rm: this.mRequiredMeasurements.values()) { 64 Map<Integer, RequirementConstants.Result> perfClassResults = rm.getPerformanceClass(); 65 66 for (Integer pc: perfClassResults.keySet()) { 67 RequirementConstants.Result res = perfClassResults.get(pc); 68 69 // if one or more results are UNMET, mark the performance class as UNMET 70 // otherwise if at least 1 of the results is MET, mark the performance class as MET 71 if (res == RequirementConstants.Result.UNMET) { 72 overallPerfClassResults.put(pc, RequirementConstants.Result.UNMET); 73 } else if (!overallPerfClassResults.containsKey(pc) && 74 res == RequirementConstants.Result.MET) { 75 overallPerfClassResults.put(pc, RequirementConstants.Result.MET); 76 } 77 } 78 } 79 80 // report the highest performance class that has been MET 81 int perfClass = 0; 82 for (int pc: overallPerfClassResults.keySet()) { 83 if (overallPerfClassResults.get(pc) == RequirementConstants.Result.MET) { 84 perfClass = Math.max(perfClass, pc); 85 } 86 } 87 return perfClass; 88 } 89 90 @VisibleForTesting checkPerformanceClass(int devicePerfClass)91 protected boolean checkPerformanceClass(int devicePerfClass) { 92 boolean noResultsUnment = true; 93 for (RequiredMeasurement<?> rm: this.mRequiredMeasurements.values()) { 94 RequirementConstants.Result res = rm.meetsPerformanceClass(devicePerfClass); 95 if (res == RequirementConstants.Result.UNMET) { 96 Log.w(Requirement.TAG, rm.toString()); 97 noResultsUnment = false; 98 } else { 99 Log.i(Requirement.TAG, rm.toString()); 100 } 101 } 102 return noResultsUnment; 103 } 104 setMeasuredValue(String measurement, T measuredValue)105 protected <T> void setMeasuredValue(String measurement, T measuredValue) { 106 RequiredMeasurement<T> rm = 107 (RequiredMeasurement<T>)this.mRequiredMeasurements.get(measurement); 108 rm.setMeasuredValue(measuredValue); 109 } 110 111 /** 112 * @return whether or not the requirement meets the device's specified performance class 113 */ writeLogAndCheck(ReportLog log, String testName)114 public boolean writeLogAndCheck(ReportLog log, String testName) { 115 if (this.id == RequirementConstants.RTBD) { 116 // skip upload on any requirement without a specified id 117 Log.i(this.TAG, testName + "has requirement without set requirement id and test " + 118 "results were not uploaded"); 119 return this.checkPerformanceClass(Utils.getPerfClass()); 120 } 121 122 int perfClass = this.computePerformanceClass(); 123 124 log.addValue(RequirementConstants.TN_FIELD_NAME, testName, ResultType.NEUTRAL, 125 ResultUnit.NONE); 126 for (RequiredMeasurement rm: this.mRequiredMeasurements.values()) { 127 rm.writeValue(log); 128 } 129 log.addValue(RequirementConstants.PC_FIELD_NAME, perfClass, ResultType.NEUTRAL, 130 ResultUnit.NONE); 131 132 return this.checkPerformanceClass(Utils.getPerfClass()); 133 } 134 } 135