1 /*
2  * Copyright (C) 2023 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 com.android.systemui
18 
19 import android.os.Looper
20 import android.platform.test.flag.junit.SetFlagsRule
21 import android.testing.TestableLooper.RunWithLooper
22 import androidx.test.ext.junit.runners.AndroidJUnit4
23 import androidx.test.filters.SmallTest
24 import com.android.systemui.dagger.GlobalRootComponent
25 import com.android.systemui.dagger.SysUIComponent
26 import com.android.systemui.dump.dumpManager
27 import com.android.systemui.flags.systemPropertiesHelper
28 import com.android.systemui.kosmos.Kosmos
29 import com.android.systemui.process.processWrapper
30 import com.android.systemui.util.mockito.whenever
31 import com.google.common.truth.Truth.assertThat
32 import javax.inject.Provider
33 import org.junit.Before
34 import org.junit.Rule
35 import org.junit.Test
36 import org.junit.runner.RunWith
37 import org.mockito.Mock
38 import org.mockito.MockitoAnnotations
39 
40 @RunWith(AndroidJUnit4::class)
41 @SmallTest
42 @RunWithLooper
43 class SystemUIApplicationTest : SysuiTestCase() {
44 
45     private val app: SystemUIApplication = SystemUIApplication()
46     private lateinit var contextAvailableCallback:
47         SystemUIAppComponentFactoryBase.ContextAvailableCallback
48 
49     @get:Rule val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT)
50 
51     val kosmos = Kosmos()
52     @Mock private lateinit var initializer: SystemUIInitializer
53     @Mock private lateinit var rootComponent: GlobalRootComponent
54     @Mock private lateinit var sysuiComponent: SysUIComponent
55     @Mock private lateinit var bootCompleteCache: BootCompleteCacheImpl
56     @Mock private lateinit var initController: InitController
57 
58     class StartableA : TestableStartable()
59     class StartableB : TestableStartable()
60     class StartableC : TestableStartable()
61     class StartableD : TestableStartable()
62     class StartableE : TestableStartable()
63 
64     val dependencyMap: Map<Class<*>, Set<Class<out CoreStartable>>> =
65         mapOf(
66             StartableC::class.java to setOf(StartableA::class.java),
67             StartableD::class.java to setOf(StartableA::class.java, StartableB::class.java),
68             StartableE::class.java to setOf(StartableD::class.java, StartableB::class.java),
69         )
70 
71     private val startableA = StartableA()
72     private val startableB = StartableB()
73     private val startableC = StartableC()
74     private val startableD = StartableD()
75     private val startableE = StartableE()
76 
77     @Before
setUpnull78     fun setUp() {
79         MockitoAnnotations.initMocks(this)
80         app.attachBaseContext(context)
81         contextAvailableCallback =
82             SystemUIAppComponentFactoryBase.ContextAvailableCallback { initializer }
83         whenever(initializer.rootComponent).thenReturn(rootComponent)
84         whenever(initializer.sysUIComponent).thenReturn(sysuiComponent)
85         whenever(rootComponent.mainLooper).thenReturn(Looper.myLooper())
86         whenever(rootComponent.systemPropertiesHelper).thenReturn(kosmos.systemPropertiesHelper)
87         whenever(rootComponent.processWrapper).thenReturn(kosmos.processWrapper)
88         whenever(sysuiComponent.provideBootCacheImpl()).thenReturn(bootCompleteCache)
89         whenever(sysuiComponent.createDumpManager()).thenReturn(kosmos.dumpManager)
90         whenever(sysuiComponent.initController).thenReturn(initController)
91         whenever(sysuiComponent.startableDependencies).thenReturn(dependencyMap)
92         kosmos.processWrapper.systemUser = true
93 
94         app.setContextAvailableCallback(contextAvailableCallback)
95     }
96 
97     @Test
testAppOnCreatenull98     fun testAppOnCreate() {
99         app.onCreate()
100     }
101 
102     @Test
testStartServices_singleServicenull103     fun testStartServices_singleService() {
104         whenever(sysuiComponent.startables)
105             .thenReturn(mutableMapOf(StartableA::class.java to Provider { startableA }))
106         app.onCreate()
107         app.startSystemUserServicesIfNeeded()
108         assertThat(startableA.started).isTrue()
109     }
110 
111     @Test
testStartServices_twoServicesnull112     fun testStartServices_twoServices() {
113         whenever(sysuiComponent.startables)
114             .thenReturn(
115                 mutableMapOf(
116                     StartableA::class.java to Provider { startableA },
117                     StartableB::class.java to Provider { startableB }
118                 )
119             )
120         app.onCreate()
121         app.startSystemUserServicesIfNeeded()
122         assertThat(startableA.started).isTrue()
123         assertThat(startableB.started).isTrue()
124     }
125 
126     @Test
testStartServices_simpleDependencynull127     fun testStartServices_simpleDependency() {
128         whenever(sysuiComponent.startables)
129             .thenReturn(
130                 mutableMapOf(
131                     StartableC::class.java to Provider { startableC },
132                     StartableA::class.java to Provider { startableA },
133                     StartableB::class.java to Provider { startableB }
134                 )
135             )
136         app.onCreate()
137         app.startSystemUserServicesIfNeeded()
138         assertThat(startableA.started).isTrue()
139         assertThat(startableB.started).isTrue()
140         assertThat(startableC.started).isTrue()
141         assertThat(startableC.order).isGreaterThan(startableA.order)
142     }
143 
144     @Test
testStartServices_complexDependencynull145     fun testStartServices_complexDependency() {
146         whenever(sysuiComponent.startables)
147             .thenReturn(
148                 mutableMapOf(
149                     StartableE::class.java to Provider { startableE },
150                     StartableC::class.java to Provider { startableC },
151                     StartableD::class.java to Provider { startableD },
152                     StartableA::class.java to Provider { startableA },
153                     StartableB::class.java to Provider { startableB }
154                 )
155             )
156         app.onCreate()
157         app.startSystemUserServicesIfNeeded()
158         assertThat(startableA.started).isTrue()
159         assertThat(startableB.started).isTrue()
160         assertThat(startableC.started).isTrue()
161         assertThat(startableD.started).isTrue()
162         assertThat(startableE.started).isTrue()
163         assertThat(startableC.order).isGreaterThan(startableA.order)
164         assertThat(startableD.order).isGreaterThan(startableA.order)
165         assertThat(startableD.order).isGreaterThan(startableB.order)
166         assertThat(startableE.order).isGreaterThan(startableB.order)
167         assertThat(startableE.order).isGreaterThan(startableD.order)
168     }
169 
170     open class TestableStartable : CoreStartable {
171         companion object {
172             var startOrder = 0
173         }
174 
175         var started = false
176         var order = -1
177 
startnull178         override fun start() {
179             started = true
180             order = startOrder
181             startOrder++
182         }
183     }
184 }
185