Add getStatusData API in entry.

Use this API to fetch status of entry, such as isDisabled / isSwitchOff
Add query_status in EntryProvider

Bug: 253981143
Test: manual - build gallery
Change-Id: I5ee3dfae59199c3efd169d163cbee5f39b3c451a
This commit is contained in:
Zekan Qian
2022-10-21 10:45:07 +08:00
parent d2b25e89a7
commit 1d98a8de68
8 changed files with 138 additions and 36 deletions

View File

@@ -27,6 +27,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.android.settingslib.spa.framework.common.EntrySearchData
import com.android.settingslib.spa.framework.common.EntryStatusData
import com.android.settingslib.spa.framework.common.SettingsEntry
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPageProvider
@@ -104,6 +105,7 @@ object PreferencePageProvider : SettingsPageProvider {
entryList.add(
createEntry(EntryEnum.DISABLED_PREFERENCE)
.setIsAllowSearch(true)
.setHasMutableStatus(true)
.setMacro {
spaLogger.message(TAG, "create macro for ${EntryEnum.DISABLED_PREFERENCE}")
SimplePreferenceMacro(
@@ -113,14 +115,17 @@ object PreferencePageProvider : SettingsPageProvider {
icon = Icons.Outlined.DisabledByDefault,
)
}
.setStatusDataFn { EntryStatusData(isDisabled = true) }
.build()
)
entryList.add(
createEntry(EntryEnum.ASYNC_SUMMARY_PREFERENCE)
.setIsAllowSearch(true)
.setHasMutableStatus(true)
.setSearchDataFn {
EntrySearchData(title = ASYNC_PREFERENCE_TITLE)
}
.setStatusDataFn { EntryStatusData(isDisabled = false) }
.setUiLayoutFn {
val model = PreferencePageModel.create()
val asyncSummary = remember { model.getAsyncSummary() }

View File

@@ -42,9 +42,10 @@ private const val TAG = "EntryProvider"
* For gallery, AuthorityPath = com.android.spa.gallery.provider
* For Settings, AuthorityPath = com.android.settings.spa.provider
* Some examples:
* $ 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
* $ adb shell content query --uri content://<AuthorityPath>/search_mutable_status
* $ adb shell content query --uri content://<AuthorityPath>/search_immutable_status
*/
open class EntryProvider : ContentProvider() {
private val spaEnvironment get() = SpaEnvironmentFactory.instance
@@ -81,9 +82,10 @@ open class EntryProvider : ContentProvider() {
override fun attachInfo(context: Context?, info: ProviderInfo?) {
if (info != null) {
QueryEnum.SEARCH_SITEMAP_QUERY.addUri(uriMatcher, info.authority)
QueryEnum.SEARCH_STATIC_DATA_QUERY.addUri(uriMatcher, info.authority)
QueryEnum.SEARCH_DYNAMIC_DATA_QUERY.addUri(uriMatcher, info.authority)
QueryEnum.SEARCH_MUTABLE_STATUS_DATA_QUERY.addUri(uriMatcher, info.authority)
QueryEnum.SEARCH_IMMUTABLE_STATUS_DATA_QUERY.addUri(uriMatcher, info.authority)
}
super.attachInfo(context, info)
}
@@ -97,9 +99,12 @@ open class EntryProvider : ContentProvider() {
): Cursor? {
return try {
when (uriMatcher.match(uri)) {
QueryEnum.SEARCH_SITEMAP_QUERY.queryMatchCode -> querySearchSitemap()
QueryEnum.SEARCH_STATIC_DATA_QUERY.queryMatchCode -> querySearchStaticData()
QueryEnum.SEARCH_DYNAMIC_DATA_QUERY.queryMatchCode -> querySearchDynamicData()
QueryEnum.SEARCH_MUTABLE_STATUS_DATA_QUERY.queryMatchCode ->
querySearchMutableStatusData()
QueryEnum.SEARCH_IMMUTABLE_STATUS_DATA_QUERY.queryMatchCode ->
querySearchImmutableStatusData()
else -> throw UnsupportedOperationException("Unknown Uri $uri")
}
} catch (e: UnsupportedOperationException) {
@@ -110,18 +115,22 @@ open class EntryProvider : ContentProvider() {
}
}
private fun querySearchSitemap(): Cursor {
private fun querySearchImmutableStatusData(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.SEARCH_SITEMAP_QUERY.getColumns())
val cursor = MatrixCursor(QueryEnum.SEARCH_IMMUTABLE_STATUS_DATA_QUERY.getColumns())
for (entry in entryRepository.getAllEntries()) {
if (!entry.isAllowSearch) continue
val intent = entry.containerPage()
.createBrowseIntent(context, spaEnvironment.browseActivityClass, entry.id)
?: Intent()
cursor.newRow()
.add(ColumnEnum.ENTRY_ID.id, entry.id)
.add(ColumnEnum.ENTRY_HIERARCHY_PATH.id, entryRepository.getEntryPath(entry.id))
.add(ColumnEnum.ENTRY_INTENT_URI.id, intent.toUri(Intent.URI_INTENT_SCHEME))
if (!entry.isAllowSearch || entry.mutableStatus) continue
fetchStatusData(entry, cursor)
}
return cursor
}
private fun querySearchMutableStatusData(): Cursor {
val entryRepository by spaEnvironment.entryRepository
val cursor = MatrixCursor(QueryEnum.SEARCH_MUTABLE_STATUS_DATA_QUERY.getColumns())
for (entry in entryRepository.getAllEntries()) {
if (!entry.isAllowSearch || !entry.mutableStatus) continue
fetchStatusData(entry, cursor)
}
return cursor
}
@@ -147,14 +156,27 @@ open class EntryProvider : ContentProvider() {
}
private fun fetchSearchData(entry: SettingsEntry, cursor: MatrixCursor) {
val entryRepository by spaEnvironment.entryRepository
val browseActivityClass = spaEnvironment.browseActivityClass
// Fetch search data. We can add runtime arguments later if necessary
val searchData = entry.getSearchData()
val searchData = entry.getSearchData() ?: return
val intent = entry.containerPage()
.createBrowseIntent(context, browseActivityClass, entry.id)
?: Intent()
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>()
)
.add(ColumnEnum.ENTRY_INTENT_URI.id, intent.toUri(Intent.URI_INTENT_SCHEME))
.add(ColumnEnum.SEARCH_TITLE.id, searchData.title)
.add(ColumnEnum.SEARCH_KEYWORD.id, searchData.keyword)
.add(ColumnEnum.SEARCH_PATH.id, entryRepository.getEntryPath(entry.id))
}
private fun fetchStatusData(entry: SettingsEntry, cursor: MatrixCursor) {
// Fetch status data. We can add runtime arguments later if necessary
val statusData = entry.getStatusData() ?: return
cursor.newRow()
.add(ColumnEnum.ENTRY_ID.id, entry.id)
.add(ColumnEnum.SEARCH_STATUS_DISABLED.id, statusData.isDisabled)
}
}

View File

@@ -26,4 +26,5 @@ interface EntryMacro {
@Composable
fun UiLayout() {}
fun getSearchData(): EntrySearchData? = null
fun getStatusData(): EntryStatusData? = null
}

View File

@@ -0,0 +1,25 @@
/*
* 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.framework.common
/**
* Defines the status data of one Settings entry, which could be changed frequently.
*/
data class EntryStatusData(
val isDisabled: Boolean = false,
val isSwitchOff: Boolean = false,
)

View File

@@ -40,8 +40,10 @@ enum class ColumnEnum(val id: String) {
ENTRY_START_ADB("entryStartAdb"),
// Columns related to search
ENTRY_TITLE("entryTitle"),
ENTRY_SEARCH_KEYWORD("entrySearchKw"),
SEARCH_TITLE("searchTitle"),
SEARCH_KEYWORD("searchKw"),
SEARCH_PATH("searchPath"),
SEARCH_STATUS_DISABLED("searchDisabled"),
}
/**
@@ -83,32 +85,42 @@ enum class QueryEnum(
ColumnEnum.ENTRY_NAME,
ColumnEnum.ENTRY_ROUTE,
ColumnEnum.ENTRY_INTENT_URI,
ColumnEnum.ENTRY_HIERARCHY_PATH,
)
),
// Search related queries
SEARCH_SITEMAP_QUERY(
"search_sitemap", 300,
listOf(
ColumnEnum.ENTRY_ID,
ColumnEnum.ENTRY_HIERARCHY_PATH,
ColumnEnum.ENTRY_INTENT_URI,
)
),
SEARCH_STATIC_DATA_QUERY(
"search_static", 301,
listOf(
ColumnEnum.ENTRY_ID,
ColumnEnum.ENTRY_TITLE,
ColumnEnum.ENTRY_SEARCH_KEYWORD,
ColumnEnum.ENTRY_INTENT_URI,
ColumnEnum.SEARCH_TITLE,
ColumnEnum.SEARCH_KEYWORD,
ColumnEnum.SEARCH_PATH,
)
),
SEARCH_DYNAMIC_DATA_QUERY(
"search_dynamic", 302,
listOf(
ColumnEnum.ENTRY_ID,
ColumnEnum.ENTRY_TITLE,
ColumnEnum.ENTRY_SEARCH_KEYWORD,
ColumnEnum.ENTRY_INTENT_URI,
ColumnEnum.SEARCH_TITLE,
ColumnEnum.SEARCH_KEYWORD,
ColumnEnum.SEARCH_PATH,
)
),
SEARCH_IMMUTABLE_STATUS_DATA_QUERY(
"search_immutable_status", 303,
listOf(
ColumnEnum.ENTRY_ID,
ColumnEnum.SEARCH_STATUS_DISABLED,
)
),
SEARCH_MUTABLE_STATUS_DATA_QUERY(
"search_mutable_status", 304,
listOf(
ColumnEnum.ENTRY_ID,
ColumnEnum.SEARCH_STATUS_DISABLED,
)
),
}

View File

@@ -65,8 +65,14 @@ data class SettingsEntry(
* ========================================
*/
val isAllowSearch: Boolean = false,
// Indicate whether the search indexing data of entry is dynamic.
val isSearchDataDynamic: Boolean = false,
// Indicate whether the status of entry is mutable.
// If so, for instance, we'll reindex its status for search.
val mutableStatus: Boolean = false,
/**
* ========================================
* Defines entry APIs to get data here.
@@ -74,8 +80,14 @@ data class SettingsEntry(
*/
/**
* API to get Search related data for this entry.
* Returns null if this entry is not available for the search at the moment.
* API to get the status data of the entry, such as isDisabled / isSwitchOff.
* Returns null if this entry do NOT have any status.
*/
private val statusDataImpl: (arguments: Bundle?) -> EntryStatusData? = { null },
/**
* API to get Search indexing data for this entry, such as title / keyword.
* Returns null if this entry do NOT support search.
*/
private val searchDataImpl: (arguments: Bundle?) -> EntrySearchData? = { null },
@@ -116,6 +128,10 @@ data class SettingsEntry(
return arguments
}
fun getStatusData(runtimeArguments: Bundle? = null): EntryStatusData? {
return statusDataImpl(fullArgument(runtimeArguments))
}
fun getSearchData(runtimeArguments: Bundle? = null): EntrySearchData? {
return searchDataImpl(fullArgument(runtimeArguments))
}
@@ -151,8 +167,10 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings
// Attributes
private var isAllowSearch: Boolean = false
private var isSearchDataDynamic: Boolean = false
private var mutableStatus: Boolean = false
// Functions
private var statusDataFn: (arguments: Bundle?) -> EntryStatusData? = { null }
private var searchDataFn: (arguments: Bundle?) -> EntrySearchData? = { null }
private var uiLayoutFn: (@Composable (arguments: Bundle?) -> Unit) = { }
@@ -170,8 +188,10 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings
// attributes
isAllowSearch = isAllowSearch,
isSearchDataDynamic = isSearchDataDynamic,
mutableStatus = mutableStatus,
// functions
statusDataImpl = statusDataFn,
searchDataImpl = searchDataFn,
uiLayoutImpl = uiLayoutFn,
)
@@ -201,7 +221,13 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings
return this
}
fun setHasMutableStatus(hasMutableStatus: Boolean): SettingsEntryBuilder {
this.mutableStatus = hasMutableStatus
return this
}
fun setMacro(fn: (arguments: Bundle?) -> EntryMacro): SettingsEntryBuilder {
setStatusDataFn { fn(it).getStatusData() }
setSearchDataFn { fn(it).getSearchData() }
setUiLayoutFn {
val macro = remember { fn(it) }
@@ -210,6 +236,11 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings
return this
}
fun setStatusDataFn(fn: (arguments: Bundle?) -> EntryStatusData?): SettingsEntryBuilder {
this.statusDataFn = fn
return this
}
fun setSearchDataFn(fn: (arguments: Bundle?) -> EntrySearchData?): SettingsEntryBuilder {
this.searchDataFn = fn
return this

View File

@@ -170,6 +170,7 @@ class DebugProvider : ContentProvider() {
.add(ColumnEnum.ENTRY_NAME.id, entry.displayName)
.add(ColumnEnum.ENTRY_ROUTE.id, entry.containerPage().buildRoute())
.add(ColumnEnum.ENTRY_INTENT_URI.id, intent.toUri(URI_INTENT_SCHEME))
.add(ColumnEnum.ENTRY_HIERARCHY_PATH.id, entryRepository.getEntryPath(entry.id))
}
return cursor
}

View File

@@ -24,6 +24,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import com.android.settingslib.spa.framework.common.EntryMacro
import com.android.settingslib.spa.framework.common.EntrySearchData
import com.android.settingslib.spa.framework.common.EntryStatusData
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spa.framework.util.wrapOnClickWithLog
@@ -55,6 +56,10 @@ data class SimplePreferenceMacro(
keyword = searchKeywords
)
}
override fun getStatusData(): EntryStatusData {
return EntryStatusData(isDisabled = false)
}
}
/**