1 /*
<lambda>null2  * 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 com.android.settingslib.spa.tests.testutils
18 
19 import android.app.Activity
20 import android.content.BroadcastReceiver
21 import android.content.Context
22 import android.content.Intent
23 import android.os.Bundle
24 import androidx.compose.material3.Text
25 import androidx.compose.runtime.Composable
26 import androidx.navigation.NavType
27 import androidx.navigation.navArgument
28 import com.android.settingslib.spa.framework.BrowseActivity
29 import com.android.settingslib.spa.framework.common.EntrySearchData
30 import com.android.settingslib.spa.framework.common.EntrySliceData
31 import com.android.settingslib.spa.framework.common.EntryStatusData
32 import com.android.settingslib.spa.framework.common.LogCategory
33 import com.android.settingslib.spa.framework.common.LogEvent
34 import com.android.settingslib.spa.framework.common.SettingsEntry
35 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
36 import com.android.settingslib.spa.framework.common.SettingsPage
37 import com.android.settingslib.spa.framework.common.SettingsPageProvider
38 import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository
39 import com.android.settingslib.spa.framework.common.SpaEnvironment
40 import com.android.settingslib.spa.framework.common.SpaLogger
41 import com.android.settingslib.spa.framework.common.createSettingsPage
42 import com.android.settingslib.spa.widget.preference.SimplePreferenceMacro
43 
44 class SpaLoggerForTest : SpaLogger {
45     data class MsgCountKey(val msg: String, val category: LogCategory)
46     data class EventCountKey(val id: String, val event: LogEvent, val category: LogCategory)
47 
48     private val messageCount: MutableMap<MsgCountKey, Int> = mutableMapOf()
49     private val eventCount: MutableMap<EventCountKey, Int> = mutableMapOf()
50 
51     override fun message(tag: String, msg: String, category: LogCategory) {
52         val key = MsgCountKey("[$tag]$msg", category)
53         messageCount[key] = (messageCount[key] ?: 0) + 1
54     }
55 
56     override fun event(id: String, event: LogEvent, category: LogCategory, extraData: Bundle) {
57         val key = EventCountKey(id, event, category)
58         eventCount[key] = (eventCount[key] ?: 0) + 1
59     }
60 
61     fun getMessageCount(tag: String, msg: String, category: LogCategory): Int {
62         val key = MsgCountKey("[$tag]$msg", category)
63         return messageCount[key] ?: 0
64     }
65 
66     fun getEventCount(id: String, event: LogEvent, category: LogCategory): Int {
67         val key = EventCountKey(id, event, category)
68         return eventCount[key] ?: 0
69     }
70 
71     fun reset() {
72         messageCount.clear()
73         eventCount.clear()
74     }
75 }
76 
77 class BlankActivity : BrowseActivity()
78 class BlankSliceBroadcastReceiver : BroadcastReceiver() {
onReceivenull79     override fun onReceive(p0: Context?, p1: Intent?) {}
80 }
81 
82 object SppHome : SettingsPageProvider {
83     override val name = "SppHome"
84 
getTitlenull85     override fun getTitle(arguments: Bundle?): String {
86         return "TitleHome"
87     }
88 
buildEntrynull89     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
90         val owner = this.createSettingsPage()
91         return listOf(
92             SppLayer1.buildInject().setLink(fromPage = owner).build(),
93             SppDialog.buildInject().setLink(fromPage = owner).build(),
94         )
95     }
96 }
97 
98 object SppDisabled : SettingsPageProvider {
99     override val name = "SppDisabled"
100 
isEnablednull101     override fun isEnabled(arguments: Bundle?): Boolean = false
102 
103     override fun getTitle(arguments: Bundle?): String {
104         return "TitleDisabled"
105     }
106 
buildEntrynull107     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
108         val owner = this.createSettingsPage()
109         return listOf(
110             SppLayer1.buildInject().setLink(fromPage = owner).build(),
111         )
112     }
113 }
114 
115 object SppLayer1 : SettingsPageProvider {
116     override val name = "SppLayer1"
117 
getTitlenull118     override fun getTitle(arguments: Bundle?): String {
119         return "TitleLayer1"
120     }
121 
buildInjectnull122     fun buildInject(): SettingsEntryBuilder {
123         return SettingsEntryBuilder.createInject(this.createSettingsPage())
124             .setMacro {
125                 SimplePreferenceMacro(
126                     title = "SppHome to Layer1",
127                     clickRoute = name
128                 )
129             }
130     }
131 
buildEntrynull132     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
133         val owner = this.createSettingsPage()
134         return listOf(
135             SettingsEntryBuilder.create(owner, "Layer1Entry1").build(),
136             SppLayer2.buildInject().setLink(fromPage = owner).build(),
137             SettingsEntryBuilder.create(owner, "Layer1Entry2").build(),
138         )
139     }
140 }
141 
142 object SppLayer2 : SettingsPageProvider {
143     override val name = "SppLayer2"
144 
buildInjectnull145     fun buildInject(): SettingsEntryBuilder {
146         return SettingsEntryBuilder.createInject(this.createSettingsPage())
147     }
148 
buildEntrynull149     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
150         val owner = this.createSettingsPage()
151         return listOf(
152             SettingsEntryBuilder.create(owner, "Layer2Entry1")
153                 .setSliceDataFn { _, _ ->
154                     return@setSliceDataFn object : EntrySliceData() {
155                         init {
156                             postValue(null)
157                         }
158                     }
159                 }
160                 .build(),
161             SettingsEntryBuilder.create(owner, "Layer2Entry2").build(),
162         )
163     }
164 }
165 
166 object SppDialog : SettingsPageProvider {
167     override val name = "SppDialog"
168     override val navType = SettingsPageProvider.NavType.Dialog
169 
170     const val CONTENT = "SppDialog Content"
171 
172     @Composable
Pagenull173     override fun Page(arguments: Bundle?) {
174         Text(CONTENT)
175     }
176 
buildInjectnull177     fun buildInject() = SettingsEntryBuilder.createInject(this.createSettingsPage())
178         .setMacro { SimplePreferenceMacro(title = name, clickRoute = name) }
179 }
180 
181 object SppForSearch : SettingsPageProvider {
182     override val name = "SppForSearch"
183 
buildEntrynull184     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
185         val owner = this.createSettingsPage()
186         return listOf(
187             SettingsEntryBuilder.create(owner, "SearchStaticWithNoStatus")
188                 .setSearchDataFn { EntrySearchData(title = "SearchStaticWithNoStatus") }
189                 .build(),
190             SettingsEntryBuilder.create(owner, "SearchStaticWithMutableStatus")
191                 .setHasMutableStatus(true)
192                 .setSearchDataFn { EntrySearchData(title = "SearchStaticWithMutableStatus") }
193                 .setStatusDataFn { EntryStatusData(isSwitchOff = true) }
194                 .build(),
195             SettingsEntryBuilder.create(owner, "SearchDynamicWithMutableStatus")
196                 .setIsSearchDataDynamic(true)
197                 .setHasMutableStatus(true)
198                 .setSearchDataFn { EntrySearchData(title = "SearchDynamicWithMutableStatus") }
199                 .setStatusDataFn { EntryStatusData(isDisabled = true) }
200                 .build(),
201             SettingsEntryBuilder.create(owner, "SearchDynamicWithImmutableStatus")
202                 .setIsSearchDataDynamic(true)
203                 .setSearchDataFn {
204                     EntrySearchData(
205                         title = "SearchDynamicWithImmutableStatus",
206                         keyword = listOf("kw1", "kw2")
207                     )
208                 }
209                 .setStatusDataFn { EntryStatusData(isDisabled = true) }
210                 .build(),
211         )
212     }
213 }
214 
215 class SpaEnvironmentForTest(
216     context: Context,
217     rootPages: List<SettingsPage> = emptyList(),
218     override val browseActivityClass: Class<out Activity>? = BlankActivity::class.java,
219     override val sliceBroadcastReceiverClass: Class<out BroadcastReceiver>? =
220         BlankSliceBroadcastReceiver::class.java,
221     override val logger: SpaLogger = object : SpaLogger {}
222 ) : SpaEnvironment(context) {
223 
<lambda>null224     override val pageProviderRepository = lazy {
225         SettingsPageProviderRepository(
226             listOf(
227                 SppHome, SppLayer1, SppLayer2,
228                 SppForSearch, SppDisabled,
229                 object : SettingsPageProvider {
230                     override val name = "SppWithParam"
231                     override val parameter = listOf(
232                         navArgument("string_param") { type = NavType.StringType },
233                         navArgument("int_param") { type = NavType.IntType },
234                     )
235                 },
236                 object : SettingsPageProvider {
237                     override val name = "SppWithRtParam"
238                     override val parameter = listOf(
239                         navArgument("string_param") { type = NavType.StringType },
240                         navArgument("int_param") { type = NavType.IntType },
241                         navArgument("rt_param") { type = NavType.StringType },
242                     )
243                 },
244                 SppDialog,
245             ),
246             rootPages
247         )
248     }
249 
createPagenull250     fun createPage(sppName: String, arguments: Bundle? = null): SettingsPage {
251         return pageProviderRepository.value
252             .getProviderOrNull(sppName)!!.createSettingsPage(arguments)
253     }
254 }
255