1 /*
2  * Copyright (C) 2021 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.car.cts.powerpolicy;
18 
19 import com.android.tradefed.log.LogUtil.CLog;
20 
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.StringTokenizer;
26 
27 public final class PowerPolicyDef {
28     public static final String[] ENABLED_HEADERS =
29             {"enabledComponents", "Enabled components"};
30     public static final String[] DISABLED_HEADERS =
31             {"disabledComponents", "Disabled components"};
32     public static final int STRING_BUILDER_BUF_SIZE = 1024;
33 
34     private final String mPolicyId;
35     private final PowerComponent[] mEnables;
36     private final PowerComponent[] mDisables;
37 
PowerPolicyDef(String policyId, PowerComponent[] enables, PowerComponent[] disables)38     private PowerPolicyDef(String policyId, PowerComponent[] enables, PowerComponent[] disables) {
39         mPolicyId = policyId;
40         mEnables = enables;
41         mDisables = disables;
42     }
43 
getPolicyId()44     public String getPolicyId() {
45         return mPolicyId;
46     }
47 
getEnables()48     public PowerComponent[] getEnables() {
49         return mEnables;
50     }
51 
getDisables()52     public PowerComponent[] getDisables() {
53         return mDisables;
54     }
55 
56     @Override
toString()57     public String toString() {
58         String[] enables = Arrays.stream(mEnables).map(PowerComponent::getValue)
59                 .toArray(String[]::new);
60         String[] disables = Arrays.stream(mDisables).map(PowerComponent::getValue)
61                 .toArray(String[]::new);
62         StringBuilder str = new StringBuilder();
63         str.append(mPolicyId);
64         if (enables.length > 0) {
65             str.append(" --enable ").append(String.join(",", enables));
66         }
67         if (disables.length > 0) {
68             str.append(" --disable ").append(String.join(",", disables));
69         }
70         return str.toString();
71     }
72 
73     @Override
equals(Object o)74     public boolean equals(Object o) {
75         if (this == o) return true;
76         if (o == null || getClass() != o.getClass()) return false;
77         PowerPolicyDef that = (PowerPolicyDef) o;
78         return Objects.equals(mPolicyId, that.mPolicyId)
79                 && Arrays.equals(mEnables, that.mEnables)
80                 && Arrays.equals(mDisables, that.mDisables);
81     }
82 
83     @Override
hashCode()84     public int hashCode() {
85         int result = Objects.hash(mPolicyId);
86         result = 31 * result + Arrays.hashCode(mEnables);
87         result = 31 * result + Arrays.hashCode(mDisables);
88         return result;
89     }
90 
parse(String policyDefStr, boolean hasPolicyId, int offset)91     public static PowerPolicyDef parse(String policyDefStr, boolean hasPolicyId, int offset)
92             throws Exception {
93         if (policyDefStr == null) {
94             throw new IllegalArgumentException("null policyDefStr parameter");
95         }
96         CLog.d("policyDefStr: " + policyDefStr);
97 
98         StringTokenizer tokens = new StringTokenizer(policyDefStr, "():");
99         String policyId = hasPolicyId
100                 ? tokens.nextToken().trim().substring(offset).trim() : IdSet.NONE;
101 
102         if (!search(ENABLED_HEADERS, tokens.nextToken().trim())) {
103             throw new IllegalArgumentException("malformatted enabled headers string: "
104                     + policyDefStr);
105         }
106 
107         int idx = 0;
108         String[] enables = null;
109         String tmpStr = tokens.nextToken().trim();
110         CLog.d("enables: " + tmpStr);
111         for (String hdr : DISABLED_HEADERS) {
112             idx = tmpStr.indexOf(hdr);
113             if (idx >= 0) {
114                 tmpStr = tmpStr.substring(0, idx).trim();
115                 if (!tmpStr.isEmpty()) {
116                     enables = tmpStr.split(",\\s*");
117                 }
118                 break;
119             }
120         }
121         if (idx < 0) {
122             throw new IllegalArgumentException("malformatted disabled headers string: "
123                     + policyDefStr);
124         }
125         PowerComponent[] enabledComps = PowerComponent.asComponentArray(enables);
126 
127         String[] disables = null;
128         tmpStr = tokens.nextToken().trim();
129         CLog.d("disables: " + tmpStr);
130         if (!tmpStr.isEmpty()) {
131             disables = tmpStr.split(",\\s*");
132         }
133         PowerComponent[] disabledComps = PowerComponent.asComponentArray(disables);
134 
135         return new PowerPolicyDef(policyId, enabledComps, disabledComps);
136     }
137 
createWithComponentOff(String component)138     public static PowerPolicyDef createWithComponentOff(String component)
139             throws Exception {
140         PowerComponent removingComp = PowerComponent.valueOf(component);
141 
142         ArrayList<PowerComponent> enableList = new ArrayList<PowerComponent>(
143                 Arrays.asList(ComponentList.ALL_COMPONENTS));
144         if (!enableList.remove(removingComp)) {
145             throw new IllegalArgumentException(component + " is not in the all list");
146         }
147 
148         PowerComponent[] enables = enableList.toArray(new PowerComponent[0]);
149         PowerComponent[] disables = {removingComp};
150         String policyId = component + "_disable";
151 
152         return new PowerPolicyDef(policyId, enables, disables);
153     }
154 
search(String[] strList, String str)155     private static boolean search(String[] strList, String str) {
156         return Arrays.stream(strList).anyMatch(s -> str.contains(s));
157     }
158 
159     public static final class IdSet {
160         public static final String DEFAULT_ALL_ON = "system_power_policy_all_on";
161         public static final String INITIAL_ALL_ON = "system_power_policy_initiall_on";
162         public static final String NO_USER_INTERACTION = "system_power_policy_no_user_interaction";
163         public static final String NONE = "none";
164         public static final String TEST1 = "test1";
165         public static final String TEST2 = "test2";
166         public static final String ERROR_TEST1 = "error_test1";
167         public static final String ERROR_TEST2 = "error_test2";
168         public static final String LISTENER_TEST = "listener_test";
169     }
170 
171     public enum PowerComponent {
172         NONE("none"),
173         UNKNOWN("UNKNOWN"),
174         AUDIO("AUDIO"),
175         MEDIA("MEDIA"),
176         DISPLAY("DISPLAY"),
177         BLUETOOTH("BLUETOOTH"),
178         WIFI("WIFI"),
179         CELLULAR("CELLULAR"),
180         ETHERNET("ETHERNET"),
181         PROJECTION("PROJECTION"),
182         NFC("NFC"),
183         INPUT("INPUT"),
184         VOICE_INTERACTION("VOICE_INTERACTION"),
185         VISUAL_INTERACTION("VISUAL_INTERACTION"),
186         TRUSTED_DEVICE_DETECTION("TRUSTED_DEVICE_DETECTION"),
187         LOCATION("LOCATION"),
188         MICROPHONE("MICROPHONE"),
189         CPU("CPU");
190 
191         private final String mValue;
192 
PowerComponent(String v)193         PowerComponent(String v) {
194             mValue = v;
195         }
196 
getValue()197         public String getValue() {
198             return mValue;
199         }
200 
asComponentArray(String[] componentNames)201         public static PowerComponent[] asComponentArray(String[] componentNames) {
202             if (componentNames == null) {
203                 return new PowerComponent[0];
204             }
205             normalizeComponentName(componentNames);
206             PowerComponent[] compArray = Arrays.stream(componentNames).map(PowerComponent::valueOf)
207                     .filter(e -> e != NONE).toArray(PowerComponent[]::new);
208             Arrays.sort(compArray);
209             return compArray;
210         }
211 
asComponentArray(List<String> nameList)212         public static PowerComponent[] asComponentArray(List<String> nameList) {
213             if (nameList == null) {
214                 return new PowerComponent[0];
215             }
216             return asComponentArray(nameList.toArray(new String[0]));
217         }
218 
normalizeComponentName(String[] comps)219         private static void normalizeComponentName(String[] comps) {
220             for (int i = 0; i < comps.length; i++) {
221                 try {
222                     PowerComponent.valueOf(comps[i]);
223                 } catch (Exception e) {
224                     if (comps[i] != null && comps[i].equals("none")) {
225                         comps[i] = "NONE";
226                     }
227                 }
228             }
229         }
230     }
231 
232     private static final class ComponentList {
233         static final PowerComponent[] ALL_COMPONENTS = {
234             PowerComponent.AUDIO,
235             PowerComponent.MEDIA,
236             PowerComponent.DISPLAY,
237             PowerComponent.BLUETOOTH,
238             PowerComponent.WIFI,
239             PowerComponent.CELLULAR,
240             PowerComponent.ETHERNET,
241             PowerComponent.PROJECTION,
242             PowerComponent.NFC,
243             PowerComponent.INPUT,
244             PowerComponent.VOICE_INTERACTION,
245             PowerComponent.VISUAL_INTERACTION,
246             PowerComponent.TRUSTED_DEVICE_DETECTION,
247             PowerComponent.LOCATION,
248             PowerComponent.MICROPHONE,
249             PowerComponent.CPU
250         };
251 
252         static final PowerComponent[] INIT_ALL_ON_ENABLE = {
253             PowerComponent.AUDIO,
254             PowerComponent.DISPLAY,
255             PowerComponent.CPU
256         };
257 
258         static final PowerComponent[] INIT_ALL_ON_DISABLE = {
259             PowerComponent.MEDIA,
260             PowerComponent.BLUETOOTH,
261             PowerComponent.WIFI,
262             PowerComponent.CELLULAR,
263             PowerComponent.ETHERNET,
264             PowerComponent.PROJECTION,
265             PowerComponent.NFC,
266             PowerComponent.INPUT,
267             PowerComponent.VOICE_INTERACTION,
268             PowerComponent.VISUAL_INTERACTION,
269             PowerComponent.TRUSTED_DEVICE_DETECTION,
270             PowerComponent.LOCATION,
271             PowerComponent.MICROPHONE
272         };
273 
274         static final PowerComponent[] DEFAULT_ALL_ON_ENABLE = ALL_COMPONENTS;
275         static final PowerComponent[] DEFAULT_ALL_ON_DISABLE = {};
276 
277         static final PowerComponent[] NO_USER_INTERACT_ENABLE = {
278             PowerComponent.WIFI,
279             PowerComponent.CELLULAR,
280             PowerComponent.ETHERNET,
281             PowerComponent.TRUSTED_DEVICE_DETECTION,
282             PowerComponent.CPU
283         };
284 
285         static final PowerComponent[] NO_USER_INTERACT_DISABLE = {
286             PowerComponent.AUDIO,
287             PowerComponent.MEDIA,
288             PowerComponent.DISPLAY,
289             PowerComponent.BLUETOOTH,
290             PowerComponent.PROJECTION,
291             PowerComponent.NFC,
292             PowerComponent.INPUT,
293             PowerComponent.VOICE_INTERACTION,
294             PowerComponent.VISUAL_INTERACTION,
295             PowerComponent.LOCATION,
296             PowerComponent.MICROPHONE
297         };
298 
299         static final PowerComponent[] TEST1_ENABLE =  ALL_COMPONENTS;
300         static final PowerComponent[] TEST1_DISABLE = {};
301 
302         static final PowerComponent[] TEST2_ENABLE = {};
303         static final PowerComponent[] TEST2_DISABLE = ALL_COMPONENTS;
304 
305         static final PowerComponent[] ERROR_TEST1_ENABLE = ALL_COMPONENTS;
306         static final PowerComponent[] ERROR_TEST1_DISABLE = {PowerComponent.UNKNOWN};
307 
308         static final PowerComponent[] ERROR_TEST2_ENABLE = {
309             PowerComponent.AUDIO,
310             PowerComponent.MEDIA,
311             PowerComponent.DISPLAY,
312             PowerComponent.UNKNOWN,
313             PowerComponent.WIFI,
314             PowerComponent.CELLULAR,
315             PowerComponent.ETHERNET,
316             PowerComponent.PROJECTION,
317             PowerComponent.NFC,
318             PowerComponent.INPUT,
319             PowerComponent.VOICE_INTERACTION,
320             PowerComponent.VISUAL_INTERACTION,
321             PowerComponent.TRUSTED_DEVICE_DETECTION,
322             PowerComponent.LOCATION,
323             PowerComponent.MICROPHONE,
324             PowerComponent.CPU
325         };
326         static final PowerComponent[] ERROR_TEST2_DISABLE = {};
327 
328         static final PowerComponent[] RUNTIME_DEFAULT_ENABLE = ALL_COMPONENTS;
329         static final PowerComponent[] RUNTIME_DEFAULT_DISABLE = {};
330 
331         static final PowerComponent[] RUNTIME_SILENT_ENABLE = {
332             PowerComponent.AUDIO,
333             PowerComponent.MEDIA,
334             PowerComponent.DISPLAY,
335             PowerComponent.BLUETOOTH,
336             PowerComponent.WIFI,
337             PowerComponent.CELLULAR,
338             PowerComponent.ETHERNET,
339             PowerComponent.PROJECTION,
340             PowerComponent.NFC,
341             PowerComponent.INPUT,
342             PowerComponent.VOICE_INTERACTION,
343             PowerComponent.VISUAL_INTERACTION,
344             PowerComponent.TRUSTED_DEVICE_DETECTION,
345             PowerComponent.LOCATION,
346             PowerComponent.MICROPHONE,
347             PowerComponent.CPU
348         };
349         static final PowerComponent[] RUNTIME_SILENT_DISABLE = {};
350 
351         static final PowerComponent[] LISTENER_TEST_ENABLE = {
352             PowerComponent.MEDIA,
353             PowerComponent.DISPLAY,
354             PowerComponent.BLUETOOTH,
355             PowerComponent.WIFI,
356             PowerComponent.CELLULAR,
357             PowerComponent.ETHERNET,
358             PowerComponent.PROJECTION,
359             PowerComponent.NFC,
360             PowerComponent.INPUT,
361             PowerComponent.VOICE_INTERACTION,
362             PowerComponent.VISUAL_INTERACTION,
363             PowerComponent.TRUSTED_DEVICE_DETECTION,
364             PowerComponent.LOCATION,
365             PowerComponent.CPU
366         };
367 
368         static final PowerComponent[] LISTENER_TEST_DISABLE = {
369             PowerComponent.AUDIO,
370             PowerComponent.MICROPHONE
371         };
372     }
373 
374     public static final class PolicySet {
375         public static final int TOTAL_DEFAULT_REGISTERED_POLICIES = 2;
376 
377         public static final PowerPolicyDef
378                 INITIAL_ALL_ON = new PowerPolicyDef(IdSet.INITIAL_ALL_ON,
379                 ComponentList.INIT_ALL_ON_ENABLE, ComponentList.INIT_ALL_ON_DISABLE);
380 
381         public static final PowerPolicyDef
382                 DEFAULT_ALL_ON = new PowerPolicyDef(IdSet.DEFAULT_ALL_ON,
383                 ComponentList.DEFAULT_ALL_ON_ENABLE, ComponentList.DEFAULT_ALL_ON_DISABLE);
384 
385         public static final PowerPolicyDef
386                 NO_USER_INTERACT = new PowerPolicyDef(IdSet.NO_USER_INTERACTION,
387                 ComponentList.NO_USER_INTERACT_ENABLE, ComponentList.NO_USER_INTERACT_DISABLE);
388 
389         public static final PowerPolicyDef TEST1 = new PowerPolicyDef(IdSet.TEST1,
390                 ComponentList.TEST1_ENABLE, ComponentList.TEST1_DISABLE);
391 
392         public static final PowerPolicyDef TEST2 = new PowerPolicyDef(IdSet.TEST2,
393                 ComponentList.TEST2_ENABLE, ComponentList.TEST2_DISABLE);
394 
395         public static final PowerPolicyDef ERROR_TEST1 = new PowerPolicyDef(IdSet.ERROR_TEST1,
396                 ComponentList.ERROR_TEST1_ENABLE, ComponentList.ERROR_TEST1_DISABLE);
397 
398         public static final PowerPolicyDef ERROR_TEST2 = new PowerPolicyDef(IdSet.ERROR_TEST2,
399                 ComponentList.ERROR_TEST2_ENABLE, ComponentList.ERROR_TEST2_DISABLE);
400 
401         public static final PowerPolicyDef LISTENER_TEST = new PowerPolicyDef(IdSet.LISTENER_TEST,
402                 ComponentList.LISTENER_TEST_ENABLE, ComponentList.LISTENER_TEST_DISABLE);
403     }
404 
405     public static final class ComponentSet {
406         public static final PowerPolicyDef RUNTIME_DEFAULT = new PowerPolicyDef(null,
407                 ComponentList.RUNTIME_DEFAULT_ENABLE, ComponentList.RUNTIME_DEFAULT_DISABLE);
408 
409         public static final PowerPolicyDef RUNTIME_SILENT = new PowerPolicyDef(null,
410                 ComponentList.RUNTIME_SILENT_ENABLE, ComponentList.RUNTIME_SILENT_DISABLE);
411     }
412 }
413