1 /*
2  * Copyright (C) 2024 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.tools.flicker.legacy.runner
18 
19 import android.app.Instrumentation
20 import android.platform.test.rule.NavigationModeRule
21 import android.platform.test.rule.PressHomeRule
22 import android.platform.test.rule.UnlockScreenRule
23 import android.tools.Scenario
24 import android.tools.device.apphelpers.MessagingAppHelper
25 import android.tools.flicker.legacy.FlickerTestData
26 import android.tools.flicker.rules.ArtifactSaverRule
27 import android.tools.flicker.rules.ChangeDisplayOrientationRule
28 import android.tools.flicker.rules.LaunchAppRule
29 import android.tools.flicker.rules.RemoveAllTasksButHomeRule
30 import android.tools.rules.StopAllTracesRule
31 import android.tools.traces.io.IResultData
32 import android.tools.traces.io.ResultWriter
33 import android.tools.withTracing
34 import org.junit.rules.RuleChain
35 import org.junit.runner.Description
36 
37 /**
38  * Transition runner that executes a default device setup (based on [scenario]) as well as the
39  * flicker setup/transition/teardown
40  */
41 class TransitionRunner(
42     private val scenario: Scenario,
43     private val instrumentation: Instrumentation,
44     private val resultWriter: ResultWriter = android.tools.flicker.datastore.CachedResultWriter()
45 ) {
46     /** Executes [flicker] transition and returns the result */
executenull47     fun execute(flicker: FlickerTestData, description: Description?): IResultData {
48         return withTracing("TransitionRunner:execute") {
49             resultWriter.forScenario(scenario).withOutputDir(flicker.outputDir)
50 
51             val ruleChain = buildTestRuleChain(flicker)
52             try {
53                 ruleChain.apply(null, description).evaluate()
54                 resultWriter.setRunComplete()
55             } catch (e: Throwable) {
56                 resultWriter.setRunFailed(e)
57             }
58             resultWriter.write()
59         }
60     }
61 
62     /**
63      * Create the default flicker test setup rules. In order:
64      * - unlock device
65      * - change orientation
66      * - change navigation mode
67      * - launch an app
68      * - remove all apps
69      * - go home
70      *
71      * (b/186740751) An app should be launched because, after changing the navigation mode, the
72      * first app launch is handled as a screen size change (similar to a rotation), this causes
73      * different problems during testing (e.g. IME now shown on app launch)
74      */
buildTestRuleChainnull75     private fun buildTestRuleChain(flicker: FlickerTestData): RuleChain {
76         val errorRule = ArtifactSaverRule()
77         return RuleChain.outerRule(errorRule)
78             .around(StopAllTracesRule())
79             .around(errorRule)
80             .around(UnlockScreenRule())
81             .around(errorRule)
82             .around(NavigationModeRule(scenario.navBarMode.value, false))
83             .around(errorRule)
84             .around(
85                 LaunchAppRule(MessagingAppHelper(instrumentation), clearCacheAfterParsing = false)
86             )
87             .around(errorRule)
88             .around(RemoveAllTasksButHomeRule())
89             .around(errorRule)
90             .around(
91                 ChangeDisplayOrientationRule(
92                     scenario.startRotation,
93                     resetOrientationAfterTest = false,
94                     clearCacheAfterParsing = false
95                 )
96             )
97             .around(errorRule)
98             .around(PressHomeRule())
99             .around(errorRule)
100             .around(
101                 TraceMonitorRule(
102                     flicker.traceMonitors,
103                     scenario,
104                     flicker.wmHelper,
105                     resultWriter,
106                     instrumentation
107                 )
108             )
109             .around(errorRule)
110             .around(SetupTeardownRule(flicker, resultWriter, scenario, instrumentation))
111             .around(errorRule)
112             .around(TransitionExecutionRule(flicker, resultWriter, scenario, instrumentation))
113     }
114 }
115