Loading packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt +5 −3 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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. Loading @@ -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 { Loading @@ -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() Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt +12 −8 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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 { Loading @@ -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) " + 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) } } Loading Loading @@ -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() } }) } } Loading Loading @@ -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) } } Loading @@ -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) } } Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/EntryProvider.kt +114 −11 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -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 Loading @@ -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"), } Loading @@ -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( Loading @@ -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) Loading Loading @@ -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) } Loading @@ -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 } } Loading @@ -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()) { Loading @@ -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_INTENT_URI.id, createBrowsePageIntent(entry.containerPage(), entry.id).toUri(URI_INTENT_SCHEME) ) } return cursor } 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>() ) } return cursor } private fun createBrowsePageIntent(page: SettingsPage): Intent { 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" } } Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt +8 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ data class SettingsEntry( * ======================================== */ val isAllowSearch: Boolean = false, val isSearchDataDynamic: Boolean = false, /** * ======================================== Loading Loading @@ -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 } Loading @@ -152,6 +154,7 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings // attributes isAllowSearch = isAllowSearch, isSearchDataDynamic = isSearchDataDynamic, // functions searchDataImpl = searchDataFn, Loading @@ -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 { Loading Loading
packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt +5 −3 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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. Loading @@ -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 { Loading @@ -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() Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/DebugActivity.kt +12 −8 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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 { Loading @@ -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) " + 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) } } Loading Loading @@ -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() } }) } } Loading Loading @@ -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) } } Loading @@ -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) } } Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/EntryProvider.kt +114 −11 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -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 Loading @@ -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"), } Loading @@ -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( Loading @@ -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) Loading Loading @@ -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) } Loading @@ -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 } } Loading @@ -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()) { Loading @@ -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_INTENT_URI.id, createBrowsePageIntent(entry.containerPage(), entry.id).toUri(URI_INTENT_SCHEME) ) } return cursor } 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>() ) } return cursor } private fun createBrowsePageIntent(page: SettingsPage): Intent { 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" } } Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt +8 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ data class SettingsEntry( * ======================================== */ val isAllowSearch: Boolean = false, val isSearchDataDynamic: Boolean = false, /** * ======================================== Loading Loading @@ -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 } Loading @@ -152,6 +154,7 @@ class SettingsEntryBuilder(private val name: String, private val owner: Settings // attributes isAllowSearch = isAllowSearch, isSearchDataDynamic = isSearchDataDynamic, // functions searchDataImpl = searchDataFn, Loading @@ -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 { Loading