• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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