Merge "Add SpaEnvironmentFactory"

This commit is contained in:
Zekan Qian
2022-10-13 09:11:59 +00:00
committed by Android (Google) Code Review
10 changed files with 106 additions and 30 deletions

View File

@@ -18,12 +18,13 @@
package="com.android.settingslib.spa.gallery">
<application
android:name=".GalleryApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_label"
android:supportsRtl="true"
android:enableOnBackInvokedCallback="true">
<activity
android:name=".MainActivity"
android:name=".GalleryMainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.spa.gallery
import android.app.Application
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
class GalleryApplication : Application() {
override fun onCreate() {
super.onCreate()
SpaEnvironmentFactory.instance = GallerySpaEnvironment
}
}

View File

@@ -18,4 +18,4 @@ package com.android.settingslib.spa.gallery
import com.android.settingslib.spa.framework.DebugActivity
class GalleryDebugActivity : DebugActivity(GallerySpaEnvironment)
class GalleryDebugActivity : DebugActivity()

View File

@@ -18,4 +18,4 @@ package com.android.settingslib.spa.gallery
import com.android.settingslib.spa.framework.EntryProvider
class GalleryEntryProvider : EntryProvider(GallerySpaEnvironment)
class GalleryEntryProvider : EntryProvider()

View File

@@ -18,4 +18,4 @@ package com.android.settingslib.spa.gallery
import com.android.settingslib.spa.framework.BrowseActivity
class MainActivity : BrowseActivity(GallerySpaEnvironment)
class GalleryMainActivity : BrowseActivity()

View File

@@ -87,7 +87,7 @@ object GallerySpaEnvironment : SpaEnvironment() {
)
}
override val browseActivityClass = MainActivity::class.java
override val browseActivityClass = GalleryMainActivity::class.java
override val entryProviderAuthorities = "com.android.spa.gallery.provider"
}

View File

@@ -30,7 +30,7 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.android.settingslib.spa.R
import com.android.settingslib.spa.framework.common.SpaEnvironment
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
import com.android.settingslib.spa.framework.compose.LocalNavController
import com.android.settingslib.spa.framework.compose.NavControllerWrapperImpl
import com.android.settingslib.spa.framework.compose.localNavController
@@ -50,8 +50,8 @@ private const val NULL_PAGE_NAME = "NULL"
* $ adb shell am start -n <BrowseActivityComponent> -e spa:SpaActivity:destination HOME
* $ adb shell am start -n <BrowseActivityComponent> -e spa:SpaActivity:destination ARGUMENT/bar/5
*/
open class BrowseActivity(spaEnvironment: SpaEnvironment) : ComponentActivity() {
private val sppRepository by spaEnvironment.pageProviderRepository
open class BrowseActivity : ComponentActivity() {
private val spaEnvironment get() = SpaEnvironmentFactory.instance
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_SpaLib_DayNight)
@@ -67,6 +67,7 @@ open class BrowseActivity(spaEnvironment: SpaEnvironment) : ComponentActivity()
@Composable
private fun MainContent() {
val sppRepository by spaEnvironment.pageProviderRepository
val navController = rememberNavController()
CompositionLocalProvider(navController.localNavController()) {
NavHost(navController, NULL_PAGE_NAME) {
@@ -84,6 +85,7 @@ open class BrowseActivity(spaEnvironment: SpaEnvironment) : ComponentActivity()
@Composable
private fun InitialDestinationNavigator() {
val sppRepository by spaEnvironment.pageProviderRepository
val destinationNavigated = rememberSaveable { mutableStateOf(false) }
if (destinationNavigated.value) return
destinationNavigated.value = true

View File

@@ -37,7 +37,7 @@ import com.android.settingslib.spa.framework.BrowseActivity.Companion.KEY_DESTIN
import com.android.settingslib.spa.framework.BrowseActivity.Companion.KEY_HIGHLIGHT_ENTRY
import com.android.settingslib.spa.framework.common.SettingsEntry
import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SpaEnvironment
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
import com.android.settingslib.spa.framework.compose.localNavController
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.toState
@@ -63,8 +63,8 @@ private const val PARAM_NAME_ENTRY_ID = "eid"
* For gallery, Activity = com.android.settingslib.spa.gallery/.GalleryDebugActivity
* For SettingsGoogle, Activity = com.android.settings/.spa.SpaDebugActivity
*/
open class DebugActivity(private val spaEnvironment: SpaEnvironment) : ComponentActivity() {
private val entryRepository by spaEnvironment.entryRepository
open class DebugActivity : ComponentActivity() {
private val spaEnvironment get() = SpaEnvironmentFactory.instance
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_SpaLib_DayNight)
@@ -128,6 +128,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
@Composable
fun RootPage() {
val entryRepository by spaEnvironment.entryRepository
val allPageWithEntry = remember { entryRepository.getAllPageWithEntry() }
val allEntry = remember { entryRepository.getAllEntries() }
HomeScaffold(title = "Settings Debug") {
@@ -141,6 +142,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
})
Preference(object : PreferenceModel {
override val title = "Query EntryProvider"
override val enabled = isEntryProviderAvailable().toState()
override val onClick = { displayDebugMessage() }
})
}
@@ -148,6 +150,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
@Composable
fun AllPages() {
val entryRepository by spaEnvironment.entryRepository
val allPageWithEntry = remember { entryRepository.getAllPageWithEntry() }
RegularScaffold(title = "All Pages (${allPageWithEntry.size})") {
for (pageWithEntry in allPageWithEntry) {
@@ -164,6 +167,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
@Composable
fun AllEntries() {
val entryRepository by spaEnvironment.entryRepository
val allEntry = remember { entryRepository.getAllEntries() }
RegularScaffold(title = "All Entries (${allEntry.size})") {
EntryList(allEntry)
@@ -172,6 +176,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
@Composable
fun OnePage(arguments: Bundle?) {
val entryRepository by spaEnvironment.entryRepository
val id = arguments!!.getString(PARAM_NAME_PAGE_ID, "")
val pageWithEntry = entryRepository.getPageWithEntry(id)!!
RegularScaffold(title = "Page - ${pageWithEntry.page.displayName}") {
@@ -180,7 +185,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
Text(text = "Entry size: ${pageWithEntry.entries.size}")
Preference(model = object : PreferenceModel {
override val title = "open page"
override val enabled = (!pageWithEntry.page.hasRuntimeParam()).toState()
override val enabled = isPageClickable(pageWithEntry.page).toState()
override val onClick = openPage(pageWithEntry.page)
})
EntryList(pageWithEntry.entries)
@@ -189,13 +194,14 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
@Composable
fun OneEntry(arguments: Bundle?) {
val entryRepository by spaEnvironment.entryRepository
val id = arguments!!.getString(PARAM_NAME_ENTRY_ID, "")
val entry = entryRepository.getEntry(id)!!
val entryContent = remember { entry.formatContent() }
RegularScaffold(title = "Entry - ${entry.displayTitle()}") {
Preference(model = object : PreferenceModel {
override val title = "open entry"
override val enabled = (!entry.containerPage().hasRuntimeParam()).toState()
override val enabled = isEntryClickable(entry).toState()
override val onClick = openEntry(entry)
})
Text(text = entryContent)
@@ -216,7 +222,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
@Composable
private fun openPage(page: SettingsPage): (() -> Unit)? {
if (page.hasRuntimeParam()) return null
if (!isPageClickable(page)) return null
val context = LocalContext.current
val route = page.buildRoute()
val intent = Intent(context, spaEnvironment.browseActivityClass).apply {
@@ -230,7 +236,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
@Composable
private fun openEntry(entry: SettingsEntry): (() -> Unit)? {
if (entry.containerPage().hasRuntimeParam()) return null
if (!isEntryClickable(entry)) return null
val context = LocalContext.current
val route = entry.containerPage().buildRoute()
val intent = Intent(context, spaEnvironment.browseActivityClass).apply {
@@ -242,4 +248,17 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
context.startActivity(intent)
}
}
private fun isEntryProviderAvailable(): Boolean {
return spaEnvironment.entryProviderAuthorities != null
}
private fun isPageClickable(page: SettingsPage): Boolean {
return spaEnvironment.browseActivityClass != null && !page.hasRuntimeParam()
}
private fun isEntryClickable(entry: SettingsEntry): Boolean {
return spaEnvironment.browseActivityClass != null &&
!entry.containerPage().hasRuntimeParam()
}
}

View File

@@ -30,7 +30,7 @@ import android.net.Uri
import android.util.Log
import com.android.settingslib.spa.framework.common.SettingsEntry
import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SpaEnvironment
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
private const val TAG = "EntryProvider"
@@ -49,9 +49,8 @@ private const val TAG = "EntryProvider"
* $ adb shell content query --uri content://<AuthorityPath>/search_static
* $ adb shell content query --uri content://<AuthorityPath>/search_dynamic
*/
open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
private val entryRepository by spaEnvironment.entryRepository
private val browseActivityClass = spaEnvironment.browseActivityClass
open class EntryProvider : ContentProvider() {
private val spaEnvironment get() = SpaEnvironmentFactory.instance
/**
* Enum to define all column names in provider.
@@ -221,6 +220,7 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
}
private fun queryPageDebug(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.PAGE_DEBUG_QUERY.getColumns())
for (pageWithEntry in entryRepository.getAllPageWithEntry()) {
val command = createBrowsePageAdbCommand(pageWithEntry.page)
@@ -232,6 +232,7 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
}
private fun queryEntryDebug(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.ENTRY_DEBUG_QUERY.getColumns())
for (entry in entryRepository.getAllEntries()) {
val command = createBrowsePageAdbCommand(entry.containerPage(), entry.id)
@@ -243,6 +244,7 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
}
private fun queryPageInfo(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.PAGE_INFO_QUERY.getColumns())
for (pageWithEntry in entryRepository.getAllPageWithEntry()) {
val page = pageWithEntry.page
@@ -261,6 +263,7 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
}
private fun queryEntryInfo(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.ENTRY_INFO_QUERY.getColumns())
for (entry in entryRepository.getAllEntries()) {
cursor.newRow()
@@ -276,6 +279,7 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
}
private fun querySearchSitemap(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.SEARCH_SITEMAP_QUERY.getColumns())
for (entry in entryRepository.getAllEntries()) {
if (!entry.isAllowSearch) continue
@@ -287,6 +291,7 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
}
private fun querySearchStaticData(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.SEARCH_STATIC_DATA_QUERY.getColumns())
for (entry in entryRepository.getAllEntries()) {
if (!entry.isAllowSearch || entry.isSearchDataDynamic) continue
@@ -296,6 +301,7 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
}
private fun querySearchDynamicData(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.SEARCH_DYNAMIC_DATA_QUERY.getColumns())
for (entry in entryRepository.getAllEntries()) {
if (!entry.isAllowSearch || !entry.isSearchDataDynamic) continue
@@ -317,26 +323,31 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
}
private fun createBrowsePageIntent(page: SettingsPage, entryId: String? = null): Intent {
if (context == null || page.hasRuntimeParam())
return Intent()
return Intent().setComponent(ComponentName(context!!, browseActivityClass)).apply {
putExtra(BrowseActivity.KEY_DESTINATION, page.buildRoute())
if (entryId != null) {
putExtra(BrowseActivity.KEY_HIGHLIGHT_ENTRY, entryId)
if (!isPageBrowsable(page)) return Intent()
return Intent().setComponent(ComponentName(context!!, spaEnvironment.browseActivityClass!!))
.apply {
putExtra(BrowseActivity.KEY_DESTINATION, page.buildRoute())
if (entryId != null) {
putExtra(BrowseActivity.KEY_HIGHLIGHT_ENTRY, entryId)
}
}
}
}
private fun createBrowsePageAdbCommand(page: SettingsPage, entryId: String? = null): String? {
if (context == null || page.hasRuntimeParam()) return null
if (!isPageBrowsable(page)) return null
val packageName = context!!.packageName
val activityName = browseActivityClass.name.replace(packageName, "")
val activityName = spaEnvironment.browseActivityClass!!.name.replace(packageName, "")
val destinationParam = " -e ${BrowseActivity.KEY_DESTINATION} ${page.buildRoute()}"
val highlightParam =
if (entryId != null) " -e ${BrowseActivity.KEY_HIGHLIGHT_ENTRY} $entryId" else ""
return "adb shell am start -n $packageName/$activityName$destinationParam$highlightParam"
}
private fun isPageBrowsable(page: SettingsPage): Boolean {
return context != null &&
spaEnvironment.browseActivityClass != null &&
!page.hasRuntimeParam()
}
}
fun EntryProvider.QueryEnum.getColumns(): Array<String> {

View File

@@ -18,12 +18,28 @@ package com.android.settingslib.spa.framework.common
import android.app.Activity
object SpaEnvironmentFactory {
private var spaEnvironment: SpaEnvironment? = null
var instance: SpaEnvironment
get() {
if (spaEnvironment == null)
throw UnsupportedOperationException("Spa environment is not set")
return spaEnvironment!!
}
set(env: SpaEnvironment) {
if (spaEnvironment != null)
throw UnsupportedOperationException("Spa environment is already set")
spaEnvironment = env
}
}
abstract class SpaEnvironment {
abstract val pageProviderRepository: Lazy<SettingsPageProviderRepository>
val entryRepository = lazy { SettingsEntryRepository(pageProviderRepository.value) }
abstract val browseActivityClass: Class<out Activity>
open val browseActivityClass: Class<out Activity>? = null
open val entryProviderAuthorities: String? = null