Merge "Add search related attributes of SettingsEntry. Add search related API in EntryProvider."
This commit is contained in:
@@ -55,6 +55,7 @@ object ArgumentPageProvider : SettingsPageProvider {
|
||||
createEntry(owner, EntryEnum.STRING_PARAM)
|
||||
// Set attributes
|
||||
.setIsAllowSearch(true)
|
||||
.setIsSearchDataDynamic(true)
|
||||
.setSearchDataFn { ArgumentPageModel.genStringParamSearchData() }
|
||||
.setUiLayoutFn {
|
||||
// Set ui rendering
|
||||
@@ -66,6 +67,7 @@ object ArgumentPageProvider : SettingsPageProvider {
|
||||
createEntry(owner, EntryEnum.INT_PARAM)
|
||||
// Set attributes
|
||||
.setIsAllowSearch(true)
|
||||
.setIsSearchDataDynamic(true)
|
||||
.setSearchDataFn { ArgumentPageModel.genIntParamSearchData() }
|
||||
.setUiLayoutFn {
|
||||
// Set ui rendering
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settingslib.spa.framework
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -36,7 +37,8 @@ import com.android.settingslib.spa.framework.compose.localNavController
|
||||
import com.android.settingslib.spa.framework.theme.SettingsTheme
|
||||
import com.android.settingslib.spa.framework.util.navRoute
|
||||
|
||||
const val NULL_PAGE_NAME = "NULL"
|
||||
private const val TAG = "BrowseActivity"
|
||||
private const val NULL_PAGE_NAME = "NULL"
|
||||
|
||||
/**
|
||||
* The Activity to render ALL SPA pages, and handles jumps between SPA pages.
|
||||
@@ -54,6 +56,7 @@ open class BrowseActivity(spaEnvironment: SpaEnvironment) : ComponentActivity()
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(R.style.Theme_SpaLib_DayNight)
|
||||
super.onCreate(savedInstanceState)
|
||||
Log.d(TAG, "onCreate")
|
||||
|
||||
setContent {
|
||||
SettingsTheme {
|
||||
@@ -72,8 +75,7 @@ open class BrowseActivity(spaEnvironment: SpaEnvironment) : ComponentActivity()
|
||||
composable(
|
||||
route = page.name + page.parameter.navRoute(),
|
||||
arguments = page.parameter,
|
||||
) { navBackStackEntry -> page.Page(navBackStackEntry.arguments)
|
||||
}
|
||||
) { navBackStackEntry -> page.Page(navBackStackEntry.arguments) }
|
||||
}
|
||||
}
|
||||
InitialDestinationNavigator()
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spa.widget.scaffold.HomeScaffold
|
||||
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
|
||||
|
||||
private const val TAG = "DebugActivity"
|
||||
private const val ROUTE_ROOT = "root"
|
||||
private const val ROUTE_All_PAGES = "pages"
|
||||
private const val ROUTE_All_ENTRIES = "entries"
|
||||
@@ -68,7 +69,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(R.style.Theme_SpaLib_DayNight)
|
||||
super.onCreate(savedInstanceState)
|
||||
displayDebugMessage()
|
||||
Log.d(TAG, "onCreate")
|
||||
|
||||
setContent {
|
||||
SettingsTheme {
|
||||
@@ -91,14 +92,13 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
|
||||
val entryCount = cursor.getInt(query, EntryProvider.ColumnEnum.PAGE_ENTRY_COUNT)
|
||||
val hasRuntimeParam =
|
||||
cursor.getBoolean(query, EntryProvider.ColumnEnum.HAS_RUNTIME_PARAM)
|
||||
Log.d(
|
||||
"DEBUG ACTIVITY", "Page Info: $route ($entryCount) " +
|
||||
(if (hasRuntimeParam) "with" else "no") + "-runtime-params"
|
||||
)
|
||||
val message = "Page Info: $route ($entryCount) " +
|
||||
(if (hasRuntimeParam) "with" else "no") + "-runtime-params"
|
||||
Log.d(TAG, message)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("DEBUG ACTIVITY", "Provider querying exception:", e)
|
||||
Log.e(TAG, "Provider querying exception:", e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +139,10 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
|
||||
override val title = "List All Entries (${allEntry.size})"
|
||||
override val onClick = navigator(route = ROUTE_All_ENTRIES)
|
||||
})
|
||||
Preference(object : PreferenceModel {
|
||||
override val title = "Query EntryProvider"
|
||||
override val onClick = { displayDebugMessage() }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +223,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
|
||||
putExtra(KEY_DESTINATION, route)
|
||||
}
|
||||
return {
|
||||
Log.d("DEBUG ACTIVITY", "Open page: $route")
|
||||
Log.d(TAG, "OpenPage: $route")
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
@@ -234,7 +238,7 @@ open class DebugActivity(private val spaEnvironment: SpaEnvironment) : Component
|
||||
putExtra(KEY_HIGHLIGHT_ENTRY, entry.id)
|
||||
}
|
||||
return {
|
||||
Log.d("DEBUG ACTIVITY", "Open entry: $route")
|
||||
Log.d(TAG, "OpenEntry: $route")
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,12 @@ import android.database.Cursor
|
||||
import android.database.MatrixCursor
|
||||
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
|
||||
|
||||
private const val TAG = "EntryProvider"
|
||||
|
||||
/**
|
||||
* The content provider to return entry related data, which can be used for search and hierarchy.
|
||||
* One can query the provider result by:
|
||||
@@ -39,8 +42,12 @@ import com.android.settingslib.spa.framework.common.SpaEnvironment
|
||||
* For SettingsGoogle, AuthorityPath = com.android.settings.spa.provider
|
||||
* Some examples:
|
||||
* $ adb shell content query --uri content://<AuthorityPath>/page_debug
|
||||
* $ adb shell content query --uri content://<AuthorityPath>/entry_debug
|
||||
* $ adb shell content query --uri content://<AuthorityPath>/page_info
|
||||
* $ adb shell content query --uri content://<AuthorityPath>/entry_info
|
||||
* $ adb shell content query --uri content://<AuthorityPath>/search_sitemap
|
||||
* $ 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
|
||||
@@ -63,6 +70,11 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
|
||||
ENTRY_ID("entryId"),
|
||||
ENTRY_NAME("entryName"),
|
||||
ENTRY_ROUTE("entryRoute"),
|
||||
ENTRY_INTENT_URI("entryIntent"),
|
||||
ENTRY_HIERARCHY_PATH("entryPath"),
|
||||
ENTRY_START_ADB("entryStartAdb"),
|
||||
|
||||
// Columns related to search
|
||||
ENTRY_TITLE("entryTitle"),
|
||||
ENTRY_SEARCH_KEYWORD("entrySearchKw"),
|
||||
}
|
||||
@@ -80,6 +92,10 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
|
||||
"page_debug", 1,
|
||||
listOf(ColumnEnum.PAGE_START_ADB)
|
||||
),
|
||||
ENTRY_DEBUG_QUERY(
|
||||
"entry_debug", 2,
|
||||
listOf(ColumnEnum.ENTRY_START_ADB)
|
||||
),
|
||||
|
||||
// page related queries.
|
||||
PAGE_INFO_QUERY(
|
||||
@@ -101,10 +117,34 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
|
||||
ColumnEnum.ENTRY_ID,
|
||||
ColumnEnum.ENTRY_NAME,
|
||||
ColumnEnum.ENTRY_ROUTE,
|
||||
ColumnEnum.ENTRY_INTENT_URI,
|
||||
)
|
||||
),
|
||||
|
||||
// Search related queries
|
||||
SEARCH_SITEMAP_QUERY(
|
||||
"search_sitemap", 300,
|
||||
listOf(
|
||||
ColumnEnum.ENTRY_ID,
|
||||
ColumnEnum.ENTRY_HIERARCHY_PATH,
|
||||
)
|
||||
),
|
||||
SEARCH_STATIC_DATA_QUERY(
|
||||
"search_static", 301,
|
||||
listOf(
|
||||
ColumnEnum.ENTRY_ID,
|
||||
ColumnEnum.ENTRY_TITLE,
|
||||
ColumnEnum.ENTRY_SEARCH_KEYWORD,
|
||||
)
|
||||
)
|
||||
),
|
||||
SEARCH_DYNAMIC_DATA_QUERY(
|
||||
"search_dynamic", 302,
|
||||
listOf(
|
||||
ColumnEnum.ENTRY_ID,
|
||||
ColumnEnum.ENTRY_TITLE,
|
||||
ColumnEnum.ENTRY_SEARCH_KEYWORD,
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH)
|
||||
@@ -137,14 +177,19 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
|
||||
}
|
||||
|
||||
override fun onCreate(): Boolean {
|
||||
Log.d(TAG, "onCreate")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun attachInfo(context: Context?, info: ProviderInfo?) {
|
||||
if (info != null) {
|
||||
addUri(info.authority, QueryEnum.PAGE_DEBUG_QUERY)
|
||||
addUri(info.authority, QueryEnum.ENTRY_DEBUG_QUERY)
|
||||
addUri(info.authority, QueryEnum.PAGE_INFO_QUERY)
|
||||
addUri(info.authority, QueryEnum.ENTRY_INFO_QUERY)
|
||||
addUri(info.authority, QueryEnum.SEARCH_SITEMAP_QUERY)
|
||||
addUri(info.authority, QueryEnum.SEARCH_STATIC_DATA_QUERY)
|
||||
addUri(info.authority, QueryEnum.SEARCH_DYNAMIC_DATA_QUERY)
|
||||
}
|
||||
super.attachInfo(context, info)
|
||||
}
|
||||
@@ -159,14 +204,18 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
|
||||
return try {
|
||||
when (uriMatcher.match(uri)) {
|
||||
QueryEnum.PAGE_DEBUG_QUERY.queryMatchCode -> queryPageDebug()
|
||||
QueryEnum.ENTRY_DEBUG_QUERY.queryMatchCode -> queryEntryDebug()
|
||||
QueryEnum.PAGE_INFO_QUERY.queryMatchCode -> queryPageInfo()
|
||||
QueryEnum.ENTRY_INFO_QUERY.queryMatchCode -> queryEntryInfo()
|
||||
QueryEnum.SEARCH_SITEMAP_QUERY.queryMatchCode -> querySearchSitemap()
|
||||
QueryEnum.SEARCH_STATIC_DATA_QUERY.queryMatchCode -> querySearchStaticData()
|
||||
QueryEnum.SEARCH_DYNAMIC_DATA_QUERY.queryMatchCode -> querySearchDynamicData()
|
||||
else -> throw UnsupportedOperationException("Unknown Uri $uri")
|
||||
}
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
Log.e("EntryProvider", "Provider querying exception:", e)
|
||||
Log.e(TAG, "Provider querying exception:", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -182,6 +231,17 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
|
||||
return cursor
|
||||
}
|
||||
|
||||
private fun queryEntryDebug(): Cursor {
|
||||
val cursor = MatrixCursor(QueryEnum.ENTRY_DEBUG_QUERY.getColumns())
|
||||
for (entry in entryRepository.getAllEntries()) {
|
||||
val command = createBrowsePageAdbCommand(entry.containerPage(), entry.id)
|
||||
if (command != null) {
|
||||
cursor.newRow().add(ColumnEnum.ENTRY_START_ADB.id, command)
|
||||
}
|
||||
}
|
||||
return cursor
|
||||
}
|
||||
|
||||
private fun queryPageInfo(): Cursor {
|
||||
val cursor = MatrixCursor(QueryEnum.PAGE_INFO_QUERY.getColumns())
|
||||
for (pageWithEntry in entryRepository.getAllPageWithEntry()) {
|
||||
@@ -203,36 +263,79 @@ open class EntryProvider(spaEnvironment: SpaEnvironment) : ContentProvider() {
|
||||
private fun queryEntryInfo(): Cursor {
|
||||
val cursor = MatrixCursor(QueryEnum.ENTRY_INFO_QUERY.getColumns())
|
||||
for (entry in entryRepository.getAllEntries()) {
|
||||
// We can add runtime arguments if necessary
|
||||
val searchData = entry.getSearchData()
|
||||
cursor.newRow()
|
||||
.add(ColumnEnum.ENTRY_ID.id, entry.id)
|
||||
.add(ColumnEnum.ENTRY_NAME.id, entry.displayName)
|
||||
.add(ColumnEnum.ENTRY_ROUTE.id, entry.containerPage().buildRoute())
|
||||
.add(ColumnEnum.ENTRY_TITLE.id, searchData?.title ?: "")
|
||||
.add(
|
||||
ColumnEnum.ENTRY_SEARCH_KEYWORD.id,
|
||||
searchData?.keyword ?: emptyList<String>()
|
||||
ColumnEnum.ENTRY_INTENT_URI.id,
|
||||
createBrowsePageIntent(entry.containerPage(), entry.id).toUri(URI_INTENT_SCHEME)
|
||||
)
|
||||
}
|
||||
return cursor
|
||||
}
|
||||
|
||||
private fun createBrowsePageIntent(page: SettingsPage): Intent {
|
||||
private fun querySearchSitemap(): Cursor {
|
||||
val cursor = MatrixCursor(QueryEnum.SEARCH_SITEMAP_QUERY.getColumns())
|
||||
for (entry in entryRepository.getAllEntries()) {
|
||||
if (!entry.isAllowSearch) continue
|
||||
cursor.newRow()
|
||||
.add(ColumnEnum.ENTRY_ID.id, entry.id)
|
||||
.add(ColumnEnum.ENTRY_HIERARCHY_PATH.id, entryRepository.getEntryPath(entry.id))
|
||||
}
|
||||
return cursor
|
||||
}
|
||||
|
||||
private fun querySearchStaticData(): Cursor {
|
||||
val cursor = MatrixCursor(QueryEnum.SEARCH_STATIC_DATA_QUERY.getColumns())
|
||||
for (entry in entryRepository.getAllEntries()) {
|
||||
if (!entry.isAllowSearch || entry.isSearchDataDynamic) continue
|
||||
fetchSearchData(entry, cursor)
|
||||
}
|
||||
return cursor
|
||||
}
|
||||
|
||||
private fun querySearchDynamicData(): Cursor {
|
||||
val cursor = MatrixCursor(QueryEnum.SEARCH_DYNAMIC_DATA_QUERY.getColumns())
|
||||
for (entry in entryRepository.getAllEntries()) {
|
||||
if (!entry.isAllowSearch || !entry.isSearchDataDynamic) continue
|
||||
fetchSearchData(entry, cursor)
|
||||
}
|
||||
return cursor
|
||||
}
|
||||
|
||||
private fun fetchSearchData(entry: SettingsEntry, cursor: MatrixCursor) {
|
||||
// Fetch search data. We can add runtime arguments later if necessary
|
||||
val searchData = entry.getSearchData()
|
||||
cursor.newRow()
|
||||
.add(ColumnEnum.ENTRY_ID.id, entry.id)
|
||||
.add(ColumnEnum.ENTRY_TITLE.id, searchData?.title ?: "")
|
||||
.add(
|
||||
ColumnEnum.ENTRY_SEARCH_KEYWORD.id,
|
||||
searchData?.keyword ?: emptyList<String>()
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createBrowsePageAdbCommand(page: SettingsPage): String? {
|
||||
private fun createBrowsePageAdbCommand(page: SettingsPage, entryId: String? = null): String? {
|
||||
if (context == null || page.hasRuntimeParam()) return null
|
||||
val packageName = context!!.packageName
|
||||
val activityName = browseActivityClass.name.replace(packageName, "")
|
||||
return "adb shell am start -n $packageName/$activityName" +
|
||||
" -e ${BrowseActivity.KEY_DESTINATION} ${page.buildRoute()}"
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ data class SettingsEntry(
|
||||
* ========================================
|
||||
*/
|
||||
val isAllowSearch: Boolean = false,
|
||||
val isSearchDataDynamic: Boolean = false,
|
||||
|
||||
/**
|
||||
* ========================================
|
||||
@@ -134,6 +135,7 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings
|
||||
|
||||
// Attributes
|
||||
private var isAllowSearch: Boolean = false
|
||||
private var isSearchDataDynamic: Boolean = false
|
||||
|
||||
// Functions
|
||||
private var searchDataFn: (arguments: Bundle?) -> EntrySearchData? = { null }
|
||||
@@ -152,6 +154,7 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings
|
||||
|
||||
// attributes
|
||||
isAllowSearch = isAllowSearch,
|
||||
isSearchDataDynamic = isSearchDataDynamic,
|
||||
|
||||
// functions
|
||||
searchDataImpl = searchDataFn,
|
||||
@@ -178,6 +181,11 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings
|
||||
return this
|
||||
}
|
||||
|
||||
fun setIsSearchDataDynamic(isDynamic: Boolean): SettingsEntryBuilder {
|
||||
this.isSearchDataDynamic = isDynamic
|
||||
return this
|
||||
}
|
||||
|
||||
fun setMacro(fn: (arguments: Bundle?) -> EntryMacro): SettingsEntryBuilder {
|
||||
setSearchDataFn { fn(it).getSearchData() }
|
||||
setUiLayoutFn {
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settingslib.spa.framework.common
|
||||
import android.util.Log
|
||||
import java.util.LinkedList
|
||||
|
||||
private const val TAG = "EntryRepository"
|
||||
private const val MAX_ENTRY_SIZE = 5000
|
||||
|
||||
data class SettingsPageWithEntry(
|
||||
@@ -37,7 +38,7 @@ class SettingsEntryRepository(sppRepository: SettingsPageProviderRepository) {
|
||||
private val pageWithEntryMap: Map<String, SettingsPageWithEntry>
|
||||
|
||||
init {
|
||||
logMsg("Initialize")
|
||||
Log.d(TAG, "Initialize")
|
||||
entryMap = mutableMapOf()
|
||||
pageWithEntryMap = mutableMapOf()
|
||||
|
||||
@@ -65,7 +66,10 @@ class SettingsEntryRepository(sppRepository: SettingsPageProviderRepository) {
|
||||
}
|
||||
}
|
||||
|
||||
logMsg("Initialize Completed: ${entryMap.size} entries in ${pageWithEntryMap.size} pages")
|
||||
Log.d(
|
||||
TAG,
|
||||
"Initialize Completed: ${entryMap.size} entries in ${pageWithEntryMap.size} pages"
|
||||
)
|
||||
}
|
||||
|
||||
fun getAllPageWithEntry(): Collection<SettingsPageWithEntry> {
|
||||
@@ -83,8 +87,8 @@ class SettingsEntryRepository(sppRepository: SettingsPageProviderRepository) {
|
||||
fun getEntry(entryId: String): SettingsEntry? {
|
||||
return entryMap[entryId]
|
||||
}
|
||||
}
|
||||
|
||||
private fun logMsg(message: String) {
|
||||
Log.d("EntryRepo", message)
|
||||
fun getEntryPath(entryId: String): String {
|
||||
return "TODO(path_of_$entryId)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.settingslib.spa.framework.common
|
||||
|
||||
import android.util.Log
|
||||
|
||||
private const val TAG = "SppRepository"
|
||||
|
||||
class SettingsPageProviderRepository(
|
||||
allPageProviders: List<SettingsPageProvider>,
|
||||
private val rootPages: List<SettingsPage> = emptyList(),
|
||||
@@ -27,7 +29,7 @@ class SettingsPageProviderRepository(
|
||||
|
||||
init {
|
||||
pageProviderMap = allPageProviders.associateBy { it.name }
|
||||
logMsg("Initialize Completed: ${pageProviderMap.size} spp")
|
||||
Log.d(TAG, "Initialize Completed: ${pageProviderMap.size} spp")
|
||||
}
|
||||
|
||||
fun getDefaultStartPage(): String {
|
||||
@@ -46,7 +48,3 @@ class SettingsPageProviderRepository(
|
||||
return pageProviderMap[name]
|
||||
}
|
||||
}
|
||||
|
||||
private fun logMsg(message: String) {
|
||||
Log.d("SppRepo", message)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user