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;
18 
19 import static org.junit.Assume.assumeTrue;
20 
21 import android.car.cts.app.PowerPolicyTestCommandStatus;
22 import android.car.cts.app.PowerPolicyTestCommandType;
23 import android.car.cts.powerpolicy.CpmsFrameworkLayerStateInfo;
24 import android.car.cts.powerpolicy.CpmsSystemLayerStateInfo;
25 import android.car.cts.powerpolicy.LocationInfo;
26 import android.car.cts.powerpolicy.PowerPolicyConstants;
27 import android.car.cts.powerpolicy.PowerPolicyDef;
28 import android.car.cts.powerpolicy.PowerPolicyGroups;
29 import android.car.cts.powerpolicy.PowerPolicyTestAnalyzer;
30 import android.car.cts.powerpolicy.PowerPolicyTestHelper;
31 import android.car.cts.powerpolicy.PowerPolicyTestResult;
32 import android.car.cts.powerpolicy.SilentModeInfo;
33 import android.car.cts.powerpolicy.SystemInfoParser;
34 import android.car.feature.Flags;
35 import android.platform.test.annotations.FlakyTest;
36 import android.platform.test.annotations.RequiresFlagsDisabled;
37 import android.platform.test.annotations.RequiresFlagsEnabled;
38 import android.platform.test.flag.junit.CheckFlagsRule;
39 import android.platform.test.flag.junit.host.HostFlagsValueProvider;
40 
41 import com.android.car.power.CarPowerDumpProto;
42 import com.android.compatibility.common.util.CommonTestUtils;
43 import com.android.compatibility.common.util.ProtoUtils;
44 import com.android.tradefed.log.LogUtil.CLog;
45 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
46 
47 import org.junit.After;
48 import org.junit.Before;
49 import org.junit.Rule;
50 import org.junit.Test;
51 import org.junit.runner.RunWith;
52 
53 import java.lang.reflect.Method;
54 
55 @RunWith(DeviceJUnit4ClassRunner.class)
56 public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
57     private static final int DEFAULT_TIMEOUT_SEC = 20;
58     private static final int BOOT_TIMEOUT_SEC = 60;
59     private static final String ANDROID_CLIENT_PKG = "android.car.cts.app";
60     private static final String ANDROID_CLIENT_ACTIVITY = ANDROID_CLIENT_PKG
61             + "/.PowerPolicyTestActivity";
62     private static final String TEST_COMMAND_HEADER =
63             "am start -n " + ANDROID_CLIENT_ACTIVITY + " --es powerpolicy ";
64     private static final String LEAVE_FORCED_SILENT_MODE_CMD =
65             "cmd car_service silent-mode forced-non-silent";
66 
67     private static final String ENTER_NON_FORCED_SILENT_MODE_CMD =
68             "cmd car_service silent-mode non-forced-silent-mode";
69     private static final int[] DEFAULT_STATE_MACHINE_AT_ON_VHAL_REQS = {
70             PowerPolicyConstants.VhalPowerStateReq.ON,
71             PowerPolicyConstants.VhalPowerStateReq.CANCEL_SHUTDOWN,
72             PowerPolicyConstants.VhalPowerStateReq.FINISHED
73     };
74     private static final String[] DEFAULT_STATE_MACHINE_AT_ON_STEP_NAMES = {
75             "trigger VHAL ON event",
76             "trigger VHAL CANCEL_SHUTDOWN",
77             "trigger VHAL FINISHED"
78     };
79 
80     private final PowerPolicyTestAnalyzer mTestAnalyzer = new PowerPolicyTestAnalyzer(this);
81     private boolean mUseProtoDump;
82 
83     @Rule
84     public final CheckFlagsRule mCheckFlagsRule =
85             HostFlagsValueProvider.createCheckFlagsRule(this::getDevice);
86 
87     @Before
checkPrecondition()88     public void checkPrecondition() throws Exception {
89         PowerPolicyTestHelper testHelper = new PowerPolicyTestHelper(
90                 /* testcase= */ "pre-condition", /* step= */ "testStep1",
91                 /* frameCpms= */ getCpmsFrameworkLayerStateInfo(),
92                 /* sysCpms= */ getCpmsSystemLayerStateInfo(), /* silentMode= */ null);
93         checkDefaultPowerPolicySet(testHelper);
94     }
95 
96     @After
restoreInitCondition()97     public void restoreInitCondition() throws Exception {
98         applyPowerPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
99     }
100 
101     @Test
102     @RequiresFlagsDisabled(Flags.FLAG_CAR_DUMP_TO_PROTO)
testPowerPolicySilentMode_textDump()103     public void testPowerPolicySilentMode_textDump() throws Exception {
104         setUseProtoDump(false);
105         waitForOnState();
106         testPowerPolicySilentMode();
107     }
108 
109     @Test
110     @RequiresFlagsEnabled(Flags.FLAG_CAR_DUMP_TO_PROTO)
testPowerPolicySilentMode_protoDump()111     public void testPowerPolicySilentMode_protoDump() throws Exception {
112         setUseProtoDump(true);
113         waitForOnState();
114         testPowerPolicySilentMode();
115     }
116 
117     /**
118      * Tests the error conditions for CPMS at the ON state.
119      *
120      * <p>All other VHAL events but {@code SHUTDOWN_PREPARE} shall not have any impact
121      * to CPMS power state. Text dump is used to get device state.
122      */
123     @Test
124     @RequiresFlagsDisabled(Flags.FLAG_CAR_DUMP_TO_PROTO)
testDefaultStateMachineAtONState_textDump()125     public void testDefaultStateMachineAtONState_textDump() throws Exception {
126         setUseProtoDump(false);
127         waitForOnState();
128         testDefaultStateMachineAtONState();
129     }
130 
131     /**
132      * Tests the error conditions for CPMS at the ON state.
133      *
134      * <p>All other VHAL events but {@code SHUTDOWN_PREPARE} shall not have any impact
135      * to CPMS power state. Proto dump is used to get device state.
136      */
137     @Test
138     @RequiresFlagsEnabled(Flags.FLAG_CAR_DUMP_TO_PROTO)
testDefaultStateMachineAtONState_protoDump()139     public void testDefaultStateMachineAtONState_protoDump() throws Exception {
140         setUseProtoDump(true);
141         waitForOnState();
142         testDefaultStateMachineAtONState();
143     }
144 
145     @FlakyTest(bugId = 327307932)
146     @Test
147     @RequiresFlagsDisabled(Flags.FLAG_CAR_DUMP_TO_PROTO)
testPowerPolicyChange_textDump()148     public void testPowerPolicyChange_textDump() throws Exception {
149         setUseProtoDump(false);
150         waitForOnState();
151         testPowerPolicyChange();
152     }
153 
154     @Test
155     @RequiresFlagsEnabled(Flags.FLAG_CAR_DUMP_TO_PROTO)
testPowerPolicyChange_protoDump()156     public void testPowerPolicyChange_protoDump() throws Exception {
157         setUseProtoDump(true);
158         waitForOnState();
159         testPowerPolicyChange();
160     }
161 
fetchActivityDumpsys()162     public String fetchActivityDumpsys() throws Exception {
163         return executeCommand("dumpsys activity %s", ANDROID_CLIENT_ACTIVITY);
164     }
165 
waitForOnState()166     private void waitForOnState() throws Exception {
167         CommonTestUtils.waitUntil("timed out (" + BOOT_TIMEOUT_SEC
168                         + "s) waiting for ON state", BOOT_TIMEOUT_SEC,
169                 () -> {
170                     CpmsFrameworkLayerStateInfo frameworkLayerStateInfo =
171                             getCpmsFrameworkLayerStateInfo();
172                     return frameworkLayerStateInfo != null
173                             && frameworkLayerStateInfo.getCurrentState()
174                             == PowerPolicyConstants.CarPowerState.ON;
175                 });
176     }
177 
setUseProtoDump(boolean useProtoDump)178     private void setUseProtoDump(boolean useProtoDump) {
179         mUseProtoDump = useProtoDump;
180     }
181 
getTestHelper(String testcase, int stepNo, String stepName)182     private PowerPolicyTestHelper getTestHelper(String testcase, int stepNo, String stepName)
183             throws Exception {
184         CpmsFrameworkLayerStateInfo cpmsFrameworkInfo = getCpmsFrameworkLayerStateInfo();
185         CpmsSystemLayerStateInfo cpmsSystemInfo = getCpmsSystemLayerStateInfo();
186         String normalizedStepName = String.format("%d. %s", stepNo, stepName);
187         return new PowerPolicyTestHelper(testcase, normalizedStepName, cpmsFrameworkInfo,
188                 cpmsSystemInfo, getSilentModeInfo());
189     }
190 
triggerVhalPowerStateReq(int reqNo, int param)191     private void triggerVhalPowerStateReq(int reqNo, int param) throws Exception {
192         executeCommand("cmd car_service inject-vhal-event %d %d,%d",
193                 PowerPolicyConstants.VHAL_POWER_STATE_REQ_PROPERTY_ID, reqNo, param);
194     }
195 
getSilentModeInfo()196     private SilentModeInfo getSilentModeInfo() throws Exception {
197         return executeAndParseCommand(new SystemInfoParser<SilentModeInfo>(SilentModeInfo.class),
198                 SilentModeInfo.COMMAND);
199     }
200 
checkSilentModeSupported()201     private void checkSilentModeSupported() throws Exception {
202         if (mUseProtoDump) {
203             CarPowerDumpProto proto = ProtoUtils.getProto(getDevice(), CarPowerDumpProto.parser(),
204                     CpmsFrameworkLayerStateInfo.COMMAND_PROTO);
205             CpmsFrameworkLayerStateInfo info = CpmsFrameworkLayerStateInfo.parseProto(proto);
206             assumeTrue("HW does not support silent mode. Skip the test",
207                     info.isSilentModeSupported());
208         } else {
209             SilentModeInfo smInfo = getSilentModeInfo();
210             assumeTrue("HW does not support silent mode. Skip the test",
211                     smInfo.isSilentModeSupported());
212         }
213     }
214 
getCpmsFrameworkLayerStateInfo()215     private CpmsFrameworkLayerStateInfo getCpmsFrameworkLayerStateInfo()
216             throws Exception {
217         if (mUseProtoDump) {
218             CarPowerDumpProto proto = ProtoUtils.getProto(getDevice(), CarPowerDumpProto.parser(),
219                     CpmsFrameworkLayerStateInfo.COMMAND_PROTO);
220             return CpmsFrameworkLayerStateInfo.parseProto(proto);
221         } else {
222             return executeAndParseCommand(new SystemInfoParser<CpmsFrameworkLayerStateInfo>(
223                     CpmsFrameworkLayerStateInfo.class), CpmsFrameworkLayerStateInfo.COMMAND);
224         }
225     }
226 
getCpmsSystemLayerStateInfo()227     private CpmsSystemLayerStateInfo getCpmsSystemLayerStateInfo() throws Exception {
228         return executeAndParseCommand(new SystemInfoParser<CpmsSystemLayerStateInfo>(
229                 CpmsSystemLayerStateInfo.class), CpmsSystemLayerStateInfo.COMMAND);
230     }
231 
rebootDevice()232     private void rebootDevice() throws Exception {
233         executeCommand("svc power reboot");
234         waitForDeviceAvailable();
235     }
236 
enterForcedSilentMode()237     private void enterForcedSilentMode() throws Exception {
238         executeCommand("cmd car_service silent-mode forced-silent");
239         waitUntilForcedSilentModeChangeTo(true);
240     }
241 
checkForcedSilentMode(PowerPolicyTestHelper testHelper)242     private void checkForcedSilentMode(PowerPolicyTestHelper testHelper) throws Exception {
243         testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
244         testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.NO_USER_INTERACTION);
245         testHelper.checkSilentModeStatus(true);
246         testHelper.checkSilentModeFull(SilentModeInfo.FORCED_SILENT);
247         testHelper.checkCurrentPowerComponents(PowerPolicyDef.PolicySet.NO_USER_INTERACT);
248     }
249 
leaveForcedSilentMode()250     private void leaveForcedSilentMode() throws Exception {
251         executeCommand(LEAVE_FORCED_SILENT_MODE_CMD);
252         executeCommand(ENTER_NON_FORCED_SILENT_MODE_CMD);
253         waitUntilForcedSilentModeChangeTo(false);
254     }
255 
checkLeaveForcedSilentMode(PowerPolicyTestHelper testHelper)256     private void checkLeaveForcedSilentMode(PowerPolicyTestHelper testHelper) throws Exception {
257         testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
258         testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
259         testHelper.checkSilentModeStatus(false);
260         testHelper.checkSilentModeFull(SilentModeInfo.NO_SILENT);
261         testHelper.checkCurrentPowerComponents(PowerPolicyDef.PolicySet.DEFAULT_ALL_ON);
262     }
263 
definePowerPolicy(String policyStr)264     private void definePowerPolicy(String policyStr) throws Exception {
265         CLog.d("definePowerPolicy: %s", policyStr);
266         executeCommand("cmd car_service define-power-policy %s", policyStr);
267     }
268 
applyPowerPolicy(String policyId)269     private void applyPowerPolicy(String policyId) throws Exception {
270         executeCommand("cmd car_service apply-power-policy %s", policyId);
271     }
272 
definePowerPolicyGroup(String policyGroupStr)273     private void definePowerPolicyGroup(String policyGroupStr) throws Exception {
274         executeCommand("cmd car_service define-power-policy-group %s", policyGroupStr);
275     }
276 
setPowerPolicyGroup(String policyGroupId)277     private void setPowerPolicyGroup(String policyGroupId) throws Exception {
278         executeCommand("cmd car_service set-power-policy-group %s", policyGroupId);
279     }
280 
setClientTestcase(String testcase, int userId)281     private void setClientTestcase(String testcase, int userId) throws Exception {
282         executeCommand("%s settest,%s --user %d", TEST_COMMAND_HEADER, testcase, userId);
283     }
284 
clearClientTestcase(int userId)285     private void clearClientTestcase(int userId) throws Exception {
286         executeCommand("%s cleartest --user %d", TEST_COMMAND_HEADER, userId);
287     }
288 
registerPowerPolicyListener(String componentName, int userId)289     private void registerPowerPolicyListener(String componentName, int userId) throws Exception {
290         executeCommand("%s addlistener,%s --user %d", TEST_COMMAND_HEADER, componentName, userId);
291     }
292 
unregisterPowerPolicyListener(String componentName, int userId)293     private void unregisterPowerPolicyListener(String componentName, int userId) throws Exception {
294         executeCommand("%s removelistener,%s --user %d",
295                 TEST_COMMAND_HEADER, componentName, userId);
296     }
297 
dumpPowerPolicyListener(String componentName, int userId)298     private void dumpPowerPolicyListener(String componentName, int userId) throws Exception {
299         executeCommand("%s dumplistener,%s --user %d", TEST_COMMAND_HEADER, componentName, userId);
300     }
301 
waitPowerPolicyListenersUpdated(PowerPolicyTestResult testResult, String clientTestcase, String clientAction, String component, int userId)302     private void waitPowerPolicyListenersUpdated(PowerPolicyTestResult testResult,
303             String clientTestcase, String clientAction, String component, int userId)
304             throws Exception {
305         CommonTestUtils.waitUntil("timed out (" + DEFAULT_TIMEOUT_SEC
306                 + "s) waiting  policy listeners updated", DEFAULT_TIMEOUT_SEC,
307                 () -> {
308                     return checkPowerPolicyListenersUpdated(testResult, clientTestcase,
309                             clientAction, component, userId);
310                 });
311     }
312 
checkPowerPolicyListenersUpdated(PowerPolicyTestResult testResult, String clientTestcase, String clientAction, String component, int userId)313     private boolean checkPowerPolicyListenersUpdated(PowerPolicyTestResult testResult,
314             String clientTestcase, String clientAction, String component, int userId)
315             throws Exception {
316         executeCommand("%s checklisteners --user %d", TEST_COMMAND_HEADER, userId);
317         return testResult.checkLastTestResultEntryData(clientTestcase, clientAction,
318                 component, PowerPolicyTestCommandStatus.PROPAGATED);
319     }
320 
resetPowerPolicyListeners(int userId)321     private void resetPowerPolicyListeners(int userId) throws Exception {
322         executeCommand("%s resetlisteners --user %d", TEST_COMMAND_HEADER, userId);
323     }
324 
waitResetPowerPolicyListenersComplete(PowerPolicyTestResult testResult, String clientTestcase, String clientAction, String component)325     private void waitResetPowerPolicyListenersComplete(PowerPolicyTestResult testResult,
326             String clientTestcase, String clientAction, String component) throws Exception {
327         CommonTestUtils.waitUntil("timed out (" + DEFAULT_TIMEOUT_SEC
328                 + "s) waiting resetPowerPolicyListenersComplete", DEFAULT_TIMEOUT_SEC,
329                 () -> {
330                     return testResult.checkLastTestResultEntryData(clientTestcase, clientAction,
331                             component, PowerPolicyTestCommandStatus.SUCCEED);
332                 });
333     }
334 
getNumberPolicyListeners()335     private int getNumberPolicyListeners() throws Exception {
336         return getCpmsFrameworkLayerStateInfo().getNumberPolicyListeners();
337     }
338 
waitUntilNumberPolicyListenersEquals(int numListeners)339     private void waitUntilNumberPolicyListenersEquals(int numListeners) throws Exception {
340         CommonTestUtils.waitUntil("timed out (" + DEFAULT_TIMEOUT_SEC
341                         + "s) getting number policy listeners", DEFAULT_TIMEOUT_SEC,
342                 () -> (getNumberPolicyListeners() == numListeners));
343     }
344 
testPowerPolicyListeners(String clientTestcase, String component, PowerPolicyTestResult testResult, String clientAction)345     private void testPowerPolicyListeners(String clientTestcase, String component,
346             PowerPolicyTestResult testResult, String clientAction) throws Exception {
347         setClientTestcase(clientTestcase, getTestRunningUserId());
348         int currentNumberListeners = getNumberPolicyListeners();
349         registerPowerPolicyListener(component, getTestRunningUserId());
350         waitUntilNumberPolicyListenersEquals(++currentNumberListeners);
351 
352         resetPowerPolicyListeners(getTestRunningUserId());
353         waitResetPowerPolicyListenersComplete(testResult, clientTestcase,
354                 PowerPolicyTestCommandType.RESET_LISTENERS.name(), component);
355         applyPowerPolicy(PowerPolicyDef.IdSet.LISTENER_TEST);
356         waitPowerPolicyListenersUpdated(testResult, clientTestcase,
357                 PowerPolicyTestCommandType.CHECK_LISTENERS.name(), component,
358                 getTestRunningUserId());
359 
360         dumpPowerPolicyListener(component, getTestRunningUserId());
361         testResult.checkLastTestResultEntry(clientTestcase, clientAction,
362                 component, PowerPolicyDef.PolicySet.LISTENER_TEST);
363 
364         unregisterPowerPolicyListener(component, getTestRunningUserId());
365         applyPowerPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
366         waitPowerPolicyListenersUpdated(testResult, clientTestcase,
367                 PowerPolicyTestCommandType.CHECK_LISTENERS.name(), component,
368                 getTestRunningUserId());
369 
370         dumpPowerPolicyListener(component, getTestRunningUserId());
371         testResult.checkLastTestResultEntry(clientTestcase, clientAction,
372                 component, "not_registered");
373         clearClientTestcase(getTestRunningUserId());
374     }
375 
waitUntilForcedSilentModeChangeTo(boolean expected)376     private void waitUntilForcedSilentModeChangeTo(boolean expected) throws Exception {
377         String timeoutMsg = String.format("timed out (%ds) waiting for forced silent mode "
378                 + "to be %b", DEFAULT_TIMEOUT_SEC, expected);
379         CommonTestUtils.waitUntil(timeoutMsg, DEFAULT_TIMEOUT_SEC,
380                 () -> {
381                     SilentModeInfo silentInfo = getSilentModeInfo();
382                     CpmsFrameworkLayerStateInfo cpmsInfo = getCpmsFrameworkLayerStateInfo();
383                     return (silentInfo.getForcedSilentMode() == expected)
384                             && (cpmsInfo.getForcedSilentMode() == expected);
385                 });
386     }
387 
waitForDeviceAvailable()388     private void waitForDeviceAvailable() throws Exception {
389         try {
390             getDevice().waitForDeviceAvailable();
391         } catch (Exception e) {
392             CLog.w("device is not available, trying one more time");
393             getDevice().waitForDeviceAvailable();
394         }
395     }
396 
checkDefaultPowerPolicySet(PowerPolicyTestHelper testHelper)397     private void checkDefaultPowerPolicySet(PowerPolicyTestHelper testHelper) throws Exception {
398         testHelper.checkRegisteredPolicy(PowerPolicyDef.PolicySet.INITIAL_ALL_ON);
399         testHelper.checkRegisteredPolicy(PowerPolicyDef.PolicySet.DEFAULT_ALL_ON);
400     }
401 
defineAndCheckPolicy(PowerPolicyDef policyDef, String testcase, int stepNo, int expectedTotalPolicies)402     private void defineAndCheckPolicy(PowerPolicyDef policyDef, String testcase, int stepNo,
403             int expectedTotalPolicies) throws Exception {
404         String teststep = stepNo + ". define a new power policy with ID(" + policyDef.getPolicyId()
405                 + ")";
406         PowerPolicyTestHelper testHelper = getTestHelper(testcase, stepNo, teststep);
407         if (testHelper.isPowerPolicyIdDefined(policyDef)) {
408             CLog.i("Policy(ID: " + policyDef.getPolicyId() + ") is already defined");
409             return;
410         }
411         definePowerPolicy(policyDef.toString());
412         testHelper = getTestHelper(testcase, stepNo, teststep);
413         testHelper.checkRegisteredPolicy(policyDef);
414         testHelper.checkTotalRegisteredPolicies(expectedTotalPolicies);
415     }
416 
testPowerPolicyAndComponentUserSetting()417     private void testPowerPolicyAndComponentUserSetting() throws Exception {
418         ComponentTestHelper[] testHelpers = {
419             new ComponentTestHelper<LocationInfo>(this, "LOCATION", LocationInfo.class),
420         };
421 
422         for (int i = 0; i < testHelpers.length; i++) {
423             testComponent(testHelpers[i]);
424         }
425     }
426 
testPowerPolicySilentMode()427     private void testPowerPolicySilentMode() throws Exception {
428         checkSilentModeSupported();
429         String testcase = "testPowerPolicySilentModeFull:";
430 
431         String teststep = "switch to forced silent";
432         enterForcedSilentMode();
433         PowerPolicyTestHelper testHelper = getTestHelper(testcase, 1, teststep);
434         // Test starts in ON state, state shouldn't change between test start and this check
435         checkForcedSilentMode(testHelper);
436 
437         teststep = "restore to normal mode";
438         leaveForcedSilentMode();
439         testHelper = getTestHelper(testcase, 2, teststep);
440         // Test starts in ON state, state shouldn't change between test start and this check
441         checkLeaveForcedSilentMode(testHelper);
442     }
443 
testDefaultStateMachineAtONState()444     private void testDefaultStateMachineAtONState() throws Exception {
445         String testcase = "testDefaultStateMachineAtONState:";
446 
447         for (int i = 0; i < DEFAULT_STATE_MACHINE_AT_ON_STEP_NAMES.length; i++) {
448             triggerVhalPowerStateReq(DEFAULT_STATE_MACHINE_AT_ON_VHAL_REQS[i],
449                     PowerPolicyConstants.ShutdownParam.NOT_USED);
450             PowerPolicyTestHelper testHelper = getTestHelper(testcase, i + 1,
451                     DEFAULT_STATE_MACHINE_AT_ON_STEP_NAMES[i]);
452             // power state shouldn't change
453             testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
454             testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
455         }
456     }
457 
testPowerPolicyChange()458     private void testPowerPolicyChange() throws Exception {
459         String testcase = "testPowerPolicyChange:";
460         int stepNo = 0;
461 
462         String teststep = "check the initial power policies";
463         PowerPolicyTestHelper testHelper = getTestHelper(testcase, stepNo++, teststep);
464         // Test starts in ON state, state shouldn't change between test start and this check
465         testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
466         // save number of device power policies
467         int registeredPoliciesNumber = testHelper.getNumberOfRegisteredPolicies();
468         int expectedTotalPolicies = registeredPoliciesNumber;
469 
470         // create two power policies, test1 and test2, for power policy change test
471         defineAndCheckPolicy(PowerPolicyDef.PolicySet.TEST1, testcase, stepNo++,
472                 ++expectedTotalPolicies);
473         defineAndCheckPolicy(PowerPolicyDef.PolicySet.TEST2, testcase, stepNo++,
474                 ++expectedTotalPolicies);
475 
476         teststep = "apply power policy test1";
477         applyPowerPolicy(PowerPolicyDef.IdSet.TEST1);
478         testHelper = getTestHelper(testcase, stepNo++, teststep);
479         testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.TEST1);
480 
481         teststep = "apply power policy test2";
482         applyPowerPolicy(PowerPolicyDef.IdSet.TEST2);
483         testHelper = getTestHelper(testcase, stepNo++, teststep);
484         testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.TEST2);
485 
486         teststep = "revert power policy back to the default";
487         applyPowerPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
488         testHelper = getTestHelper(testcase, stepNo++, teststep);
489         testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
490 
491         // add "test power policy listener" here so that one reboot clears all
492         defineAndCheckPolicy(PowerPolicyDef.PolicySet.LISTENER_TEST, testcase, stepNo++,
493                 ++expectedTotalPolicies);
494         String clientTestcase = "PowerPolicyListenerTest";
495         String component = "AUDIO";
496         PowerPolicyTestResult testResult = new PowerPolicyTestResult(mTestAnalyzer);
497         String clientAction = PowerPolicyTestCommandType.DUMP_LISTENER.name();
498 
499         testPowerPolicyListeners(clientTestcase, component, testResult, clientAction);
500 
501         // add respect to user setting test case here to utilize a single device reboot
502         testPowerPolicyAndComponentUserSetting();
503 
504         // add power policy group test here to utilize added test1 and test2 policies
505         teststep = "check default power policy group";
506         PowerPolicyGroups emptyGroups = new PowerPolicyGroups();
507         testHelper = getTestHelper(testcase, stepNo++, teststep);
508         testHelper.checkCurrentPolicyGroupId(null, mUseProtoDump);
509         testHelper.checkPowerPolicyGroups(emptyGroups);
510 
511         teststep = "define power policy group";
512         definePowerPolicyGroup(PowerPolicyGroups.TestSet.POLICY_GROUP_DEF1.toShellCommandString());
513         definePowerPolicyGroup(PowerPolicyGroups.TestSet.POLICY_GROUP_DEF2.toShellCommandString());
514         testHelper = getTestHelper(testcase, stepNo++, teststep);
515         // check that device policy groups, include just added groups as well
516         testHelper.checkPowerPolicyGroupsDefined(PowerPolicyGroups.TestSet.POLICY_GROUPS1);
517 
518         teststep = "set power policy group";
519         setPowerPolicyGroup(PowerPolicyGroups.TestSet.GROUP_ID1);
520         testHelper = getTestHelper(testcase, stepNo++, teststep);
521         testHelper.checkCurrentPolicyGroupId(PowerPolicyGroups.TestSet.GROUP_ID1, mUseProtoDump);
522 
523         // reboot device to clear created TEST1 and TEST2 test cases.
524         // need to find a way to move reboot device into AfterAll
525         rebootDevice();
526         teststep = "reboot to clear added test power policies";
527         // device was restarted, need to wait for ON state
528         waitForOnState();
529         testHelper = getTestHelper(testcase, stepNo++, teststep);
530         testHelper.checkTotalRegisteredPolicies(registeredPoliciesNumber);
531     }
532 
533     private static final class ComponentTestHelper<T> {
534         private final PowerPolicyHostTest mHostTest;
535         private final String mComponentName;
536         private final String mInfoRetrieveCommand;
537         private final String[] mEnableCommands;
538         private final String[] mDisableCommands;
539         private final Class mTypeClass;
540 
ComponentTestHelper(PowerPolicyHostTest hostTest, String componentName, Class typeClass)541         ComponentTestHelper(PowerPolicyHostTest hostTest, String componentName, Class typeClass)
542                 throws Exception {
543             mHostTest = hostTest;
544             mComponentName = componentName;
545             mTypeClass = typeClass;
546             mInfoRetrieveCommand = (String) mTypeClass.getField("COMMAND").get(null);
547             mEnableCommands = (String[]) mTypeClass.getField("ENABLE_COMMANDS").get(null);
548             mDisableCommands = (String[]) mTypeClass.getField("DISABLE_COMMANDS").get(null);
549         }
550 
turnOnComponent()551         private void turnOnComponent() throws Exception {
552             for (int i = 0; i < mEnableCommands.length; i++) {
553                 mHostTest.executeCommand(mEnableCommands[i]);
554             }
555         }
556 
turnOffComponent()557         private void turnOffComponent() throws Exception {
558             for (int i = 0; i < mDisableCommands.length; i++) {
559                 mHostTest.executeCommand(mDisableCommands[i]);
560             }
561         }
562 
tryGetComponentInfo()563         private T tryGetComponentInfo() throws Exception {
564             return mHostTest.executeAndParseCommand(new SystemInfoParser<T>(mTypeClass),
565                     mInfoRetrieveCommand);
566         }
567 
waitUntilPowerStateChangeTo(boolean expected)568         private void waitUntilPowerStateChangeTo(boolean expected) throws Exception {
569             CommonTestUtils.waitUntil("timed out with " + mComponentName
570                     + "enabled expected: " + expected, DEFAULT_TIMEOUT_SEC,
571                     () -> {
572                         T info = tryGetComponentInfo();
573                         if (info != null) {
574                             Method isPowerOn = mTypeClass.getMethod("isPowerOn");
575                             Boolean result = (Boolean) isPowerOn.invoke(info);
576                             return result.booleanValue() == expected;
577                         }
578                         return false;
579                     });
580         }
581     }
582 
testComponent(ComponentTestHelper testHelper)583     private void testComponent(ComponentTestHelper testHelper)
584             throws Exception {
585         PowerPolicyDef powerOffPolicy =
586                 PowerPolicyDef.createWithComponentOff(testHelper.mComponentName);
587         definePowerPolicy(powerOffPolicy.toString());
588 
589         testHelper.turnOffComponent();
590         testHelper.waitUntilPowerStateChangeTo(false);
591 
592         testHelper.turnOnComponent();
593         testHelper.waitUntilPowerStateChangeTo(true);
594 
595         applyPowerPolicy(powerOffPolicy.getPolicyId());
596         testHelper.turnOnComponent();
597         testHelper.waitUntilPowerStateChangeTo(true);
598 
599         testHelper.turnOffComponent();
600         testHelper.waitUntilPowerStateChangeTo(false);
601     }
602 }
603