Add SpaIntent for all intent operator in Spa
Support Session Name in SpaIntent Add tests for SpaIntent Set proper Session Name in DebugActivity, SpaSearchProvider & SliceUtil Bug: 244122804 Test: unit-test & local build gallery Change-Id: Ia9c21e2f56dcf7b4437e5bb417bdfe05b7c85b77
This commit is contained in:
@@ -36,6 +36,7 @@ import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
|
||||
import com.android.settingslib.spa.framework.common.createSettingsPage
|
||||
import com.android.settingslib.spa.framework.compose.toState
|
||||
import com.android.settingslib.spa.framework.theme.SettingsTheme
|
||||
import com.android.settingslib.spa.framework.util.createIntent
|
||||
import com.android.settingslib.spa.gallery.R
|
||||
import com.android.settingslib.spa.gallery.SettingsPageProviderEnum
|
||||
import com.android.settingslib.spa.gallery.preference.PreferencePageModel.Companion.ASYNC_PREFERENCE_SUMMARY
|
||||
@@ -91,6 +92,7 @@ object PreferencePageProvider : SettingsPageProvider {
|
||||
spaLogger.message(TAG, "create macro for ${EntryEnum.SIMPLE_PREFERENCE}")
|
||||
SimplePreferenceMacro(title = SIMPLE_PREFERENCE_TITLE)
|
||||
}
|
||||
.setStatusDataFn { EntryStatusData(isDisabled = false) }
|
||||
.build()
|
||||
)
|
||||
entryList.add(
|
||||
@@ -103,6 +105,7 @@ object PreferencePageProvider : SettingsPageProvider {
|
||||
searchKeywords = SIMPLE_PREFERENCE_KEYWORDS,
|
||||
)
|
||||
}
|
||||
.setStatusDataFn { EntryStatusData(isDisabled = true) }
|
||||
.build()
|
||||
)
|
||||
entryList.add(singleLineSummaryEntry())
|
||||
@@ -269,7 +272,7 @@ object PreferencePageProvider : SettingsPageProvider {
|
||||
)
|
||||
}
|
||||
.setSliceDataFn { sliceUri, _ ->
|
||||
val intent = owner.createBrowseIntent()?.createBrowsePendingIntent()
|
||||
val intent = owner.createIntent()?.createBrowsePendingIntent()
|
||||
?: return@setSliceDataFn null
|
||||
return@setSliceDataFn object : EntrySliceData() {
|
||||
init {
|
||||
|
||||
@@ -39,7 +39,10 @@ import com.android.settingslib.spa.framework.compose.localNavController
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.framework.compose.toState
|
||||
import com.android.settingslib.spa.framework.theme.SettingsTheme
|
||||
import com.android.settingslib.spa.slice.appendSliceParams
|
||||
import com.android.settingslib.spa.framework.util.SESSION_BROWSE
|
||||
import com.android.settingslib.spa.framework.util.SESSION_SEARCH
|
||||
import com.android.settingslib.spa.framework.util.createIntent
|
||||
import com.android.settingslib.spa.slice.fromEntry
|
||||
import com.android.settingslib.spa.slice.presenter.SliceDemo
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
@@ -158,14 +161,13 @@ class DebugActivity : ComponentActivity() {
|
||||
remember { entryRepository.getAllEntries().filter { it.hasSliceSupport } }
|
||||
RegularScaffold(title = "All Slices (${allSliceEntry.size})") {
|
||||
for (entry in allSliceEntry) {
|
||||
SliceDemo(sliceUri = entry.createSliceUri(authority))
|
||||
SliceDemo(sliceUri = Uri.Builder().fromEntry(entry, authority).build())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun OnePage(arguments: Bundle?) {
|
||||
val context = LocalContext.current
|
||||
val entryRepository by spaEnvironment.entryRepository
|
||||
val id = arguments!!.getString(PARAM_NAME_PAGE_ID, "")
|
||||
val pageWithEntry = entryRepository.getPageWithEntry(id)!!
|
||||
@@ -176,8 +178,8 @@ class DebugActivity : ComponentActivity() {
|
||||
Text(text = "Entry size: ${pageWithEntry.entries.size}")
|
||||
Preference(model = object : PreferenceModel {
|
||||
override val title = "open page"
|
||||
override val enabled =
|
||||
page.isBrowsable(context, spaEnvironment.browseActivityClass).toState()
|
||||
override val enabled = (spaEnvironment.browseActivityClass != null &&
|
||||
page.isBrowsable()).toState()
|
||||
override val onClick = openPage(page)
|
||||
})
|
||||
EntryList(pageWithEntry.entries)
|
||||
@@ -186,7 +188,6 @@ class DebugActivity : ComponentActivity() {
|
||||
|
||||
@Composable
|
||||
fun OneEntry(arguments: Bundle?) {
|
||||
val context = LocalContext.current
|
||||
val entryRepository by spaEnvironment.entryRepository
|
||||
val id = arguments!!.getString(PARAM_NAME_ENTRY_ID, "")
|
||||
val entry = entryRepository.getEntry(id)!!
|
||||
@@ -194,9 +195,9 @@ class DebugActivity : ComponentActivity() {
|
||||
RegularScaffold(title = "Entry - ${entry.debugBrief()}") {
|
||||
Preference(model = object : PreferenceModel {
|
||||
override val title = "open entry"
|
||||
override val enabled =
|
||||
entry.containerPage().isBrowsable(context, spaEnvironment.browseActivityClass)
|
||||
.toState()
|
||||
override val enabled = (spaEnvironment.browseActivityClass != null &&
|
||||
entry.containerPage().isBrowsable())
|
||||
.toState()
|
||||
override val onClick = openEntry(entry)
|
||||
})
|
||||
Text(text = entryContent)
|
||||
@@ -219,7 +220,7 @@ class DebugActivity : ComponentActivity() {
|
||||
private fun openPage(page: SettingsPage): (() -> Unit)? {
|
||||
val context = LocalContext.current
|
||||
val intent =
|
||||
page.createBrowseIntent(context, spaEnvironment.browseActivityClass) ?: return null
|
||||
page.createIntent(SESSION_BROWSE) ?: return null
|
||||
val route = page.buildRoute()
|
||||
return {
|
||||
spaEnvironment.logger.message(
|
||||
@@ -232,8 +233,7 @@ class DebugActivity : ComponentActivity() {
|
||||
@Composable
|
||||
private fun openEntry(entry: SettingsEntry): (() -> Unit)? {
|
||||
val context = LocalContext.current
|
||||
val intent = entry.containerPage()
|
||||
.createBrowseIntent(context, spaEnvironment.browseActivityClass, entry.id)
|
||||
val intent = entry.createIntent(SESSION_SEARCH)
|
||||
?: return null
|
||||
val route = entry.containerPage().buildRoute()
|
||||
return {
|
||||
@@ -245,18 +245,6 @@ class DebugActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun SettingsEntry.createSliceUri(
|
||||
authority: String?,
|
||||
runtimeArguments: Bundle? = null
|
||||
): Uri {
|
||||
if (authority == null) return Uri.EMPTY
|
||||
return Uri.Builder().scheme("content").authority(authority).appendSliceParams(
|
||||
route = this.containerPage().buildRoute(),
|
||||
entryId = this.id,
|
||||
runtimeArguments = runtimeArguments,
|
||||
).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* A blank activity without any page.
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,12 @@ import com.android.settingslib.spa.framework.common.QueryEnum
|
||||
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
|
||||
import com.android.settingslib.spa.framework.common.addUri
|
||||
import com.android.settingslib.spa.framework.common.getColumns
|
||||
import com.android.settingslib.spa.framework.util.KEY_DESTINATION
|
||||
import com.android.settingslib.spa.framework.util.KEY_HIGHLIGHT_ENTRY
|
||||
import com.android.settingslib.spa.framework.util.KEY_SESSION_SOURCE_NAME
|
||||
import com.android.settingslib.spa.framework.util.SESSION_BROWSE
|
||||
import com.android.settingslib.spa.framework.util.SESSION_SEARCH
|
||||
import com.android.settingslib.spa.framework.util.createIntent
|
||||
|
||||
private const val TAG = "DebugProvider"
|
||||
|
||||
@@ -116,9 +122,11 @@ class DebugProvider : ContentProvider() {
|
||||
val entryRepository by spaEnvironment.entryRepository
|
||||
val cursor = MatrixCursor(QueryEnum.PAGE_DEBUG_QUERY.getColumns())
|
||||
for (pageWithEntry in entryRepository.getAllPageWithEntry()) {
|
||||
val command = pageWithEntry.page.createBrowseAdbCommand(
|
||||
context,
|
||||
spaEnvironment.browseActivityClass
|
||||
val page = pageWithEntry.page
|
||||
if (!page.isBrowsable()) continue
|
||||
val command = createBrowseAdbCommand(
|
||||
destination = page.buildRoute(),
|
||||
sessionName = SESSION_BROWSE
|
||||
)
|
||||
if (command != null) {
|
||||
cursor.newRow().add(ColumnEnum.PAGE_START_ADB.id, command)
|
||||
@@ -131,8 +139,13 @@ class DebugProvider : ContentProvider() {
|
||||
val entryRepository by spaEnvironment.entryRepository
|
||||
val cursor = MatrixCursor(QueryEnum.ENTRY_DEBUG_QUERY.getColumns())
|
||||
for (entry in entryRepository.getAllEntries()) {
|
||||
val command = entry.containerPage()
|
||||
.createBrowseAdbCommand(context, spaEnvironment.browseActivityClass, entry.id)
|
||||
val page = entry.containerPage()
|
||||
if (!page.isBrowsable()) continue
|
||||
val command = createBrowseAdbCommand(
|
||||
destination = page.buildRoute(),
|
||||
entryId = entry.id,
|
||||
sessionName = SESSION_SEARCH
|
||||
)
|
||||
if (command != null) {
|
||||
cursor.newRow().add(ColumnEnum.ENTRY_START_ADB.id, command)
|
||||
}
|
||||
@@ -145,8 +158,7 @@ class DebugProvider : ContentProvider() {
|
||||
val cursor = MatrixCursor(QueryEnum.PAGE_INFO_QUERY.getColumns())
|
||||
for (pageWithEntry in entryRepository.getAllPageWithEntry()) {
|
||||
val page = pageWithEntry.page
|
||||
val intent =
|
||||
page.createBrowseIntent(context, spaEnvironment.browseActivityClass) ?: Intent()
|
||||
val intent = page.createIntent(SESSION_BROWSE) ?: Intent()
|
||||
cursor.newRow()
|
||||
.add(ColumnEnum.PAGE_ID.id, page.id)
|
||||
.add(ColumnEnum.PAGE_NAME.id, page.displayName)
|
||||
@@ -162,17 +174,36 @@ class DebugProvider : ContentProvider() {
|
||||
val entryRepository by spaEnvironment.entryRepository
|
||||
val cursor = MatrixCursor(QueryEnum.ENTRY_INFO_QUERY.getColumns())
|
||||
for (entry in entryRepository.getAllEntries()) {
|
||||
val intent = entry.containerPage()
|
||||
.createBrowseIntent(context, spaEnvironment.browseActivityClass, entry.id)
|
||||
?: Intent()
|
||||
val intent = entry.createIntent(SESSION_SEARCH) ?: Intent()
|
||||
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, intent.toUri(URI_INTENT_SCHEME))
|
||||
.add(ColumnEnum.ENTRY_HIERARCHY_PATH.id,
|
||||
entryRepository.getEntryPathWithDisplayName(entry.id))
|
||||
.add(
|
||||
ColumnEnum.ENTRY_HIERARCHY_PATH.id,
|
||||
entryRepository.getEntryPathWithDisplayName(entry.id)
|
||||
)
|
||||
}
|
||||
return cursor
|
||||
}
|
||||
}
|
||||
|
||||
private fun createBrowseAdbCommand(
|
||||
destination: String? = null,
|
||||
entryId: String? = null,
|
||||
sessionName: String? = null,
|
||||
): String? {
|
||||
val context = SpaEnvironmentFactory.instance.appContext
|
||||
val browseActivityClass = SpaEnvironmentFactory.instance.browseActivityClass ?: return null
|
||||
val packageName = context.packageName
|
||||
val activityName = browseActivityClass.name.replace(packageName, "")
|
||||
val destinationParam =
|
||||
if (destination != null) " -e $KEY_DESTINATION $destination" else ""
|
||||
val highlightParam =
|
||||
if (entryId != null) " -e $KEY_HIGHLIGHT_ENTRY $entryId" else ""
|
||||
val sessionParam =
|
||||
if (sessionName != null) " -e $KEY_SESSION_SOURCE_NAME $sessionName" else ""
|
||||
return "adb shell am start -n $packageName/$activityName" +
|
||||
"$destinationParam$highlightParam$sessionParam"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,9 @@ import com.android.settingslib.spa.framework.compose.NavControllerWrapperImpl
|
||||
import com.android.settingslib.spa.framework.compose.localNavController
|
||||
import com.android.settingslib.spa.framework.theme.SettingsTheme
|
||||
import com.android.settingslib.spa.framework.util.PageEvent
|
||||
import com.android.settingslib.spa.framework.util.getDestination
|
||||
import com.android.settingslib.spa.framework.util.getEntryId
|
||||
import com.android.settingslib.spa.framework.util.getSessionName
|
||||
import com.android.settingslib.spa.framework.util.navRoute
|
||||
|
||||
private const val TAG = "BrowseActivity"
|
||||
@@ -78,12 +81,6 @@ open class BrowseActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_DESTINATION = "spaActivityDestination"
|
||||
const val KEY_HIGHLIGHT_ENTRY = "highlightEntry"
|
||||
const val KEY_SESSION_SOURCE_NAME = "sessionSource"
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -126,11 +123,10 @@ private fun NavControllerWrapperImpl.InitialDestination(
|
||||
if (destinationNavigated.value) return
|
||||
destinationNavigated.value = true
|
||||
|
||||
val initialDestination = initialIntent?.getStringExtra(BrowseActivity.KEY_DESTINATION)
|
||||
?: defaultDestination
|
||||
val initialDestination = initialIntent?.getDestination() ?: defaultDestination
|
||||
if (initialDestination.isEmpty()) return
|
||||
val initialEntryId = initialIntent?.getStringExtra(BrowseActivity.KEY_HIGHLIGHT_ENTRY)
|
||||
val sessionSourceName = initialIntent?.getStringExtra(BrowseActivity.KEY_SESSION_SOURCE_NAME)
|
||||
val initialEntryId = initialIntent?.getEntryId()
|
||||
val sessionSourceName = initialIntent?.getSessionName()
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
highlightId = initialEntryId
|
||||
|
||||
@@ -16,13 +16,8 @@
|
||||
|
||||
package com.android.settingslib.spa.framework.common
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.navigation.NamedNavArgument
|
||||
import com.android.settingslib.spa.framework.BrowseActivity
|
||||
import com.android.settingslib.spa.framework.util.isRuntimeParam
|
||||
import com.android.settingslib.spa.framework.util.navLink
|
||||
import com.android.settingslib.spa.framework.util.normalize
|
||||
@@ -95,45 +90,8 @@ data class SettingsPage(
|
||||
return false
|
||||
}
|
||||
|
||||
fun createBrowseIntent(entryId: String? = null): Intent? {
|
||||
val context = SpaEnvironmentFactory.instance.appContext
|
||||
val browseActivityClass = SpaEnvironmentFactory.instance.browseActivityClass
|
||||
return createBrowseIntent(context, browseActivityClass, entryId)
|
||||
}
|
||||
|
||||
fun createBrowseIntent(
|
||||
context: Context?,
|
||||
browseActivityClass: Class<out Activity>?,
|
||||
entryId: String? = null
|
||||
): Intent? {
|
||||
if (!isBrowsable(context, browseActivityClass)) return null
|
||||
return Intent().setComponent(ComponentName(context!!, browseActivityClass!!))
|
||||
.apply {
|
||||
putExtra(BrowseActivity.KEY_DESTINATION, buildRoute())
|
||||
if (entryId != null) {
|
||||
putExtra(BrowseActivity.KEY_HIGHLIGHT_ENTRY, entryId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createBrowseAdbCommand(
|
||||
context: Context?,
|
||||
browseActivityClass: Class<out Activity>?,
|
||||
entryId: String? = null
|
||||
): String? {
|
||||
if (!isBrowsable(context, browseActivityClass)) return null
|
||||
val packageName = context!!.packageName
|
||||
val activityName = browseActivityClass!!.name.replace(packageName, "")
|
||||
val destinationParam = " -e ${BrowseActivity.KEY_DESTINATION} ${buildRoute()}"
|
||||
val highlightParam =
|
||||
if (entryId != null) " -e ${BrowseActivity.KEY_HIGHLIGHT_ENTRY} $entryId" else ""
|
||||
return "adb shell am start -n $packageName/$activityName$destinationParam$highlightParam"
|
||||
}
|
||||
|
||||
fun isBrowsable(context: Context?, browseActivityClass: Class<out Activity>?): Boolean {
|
||||
return context != null &&
|
||||
browseActivityClass != null &&
|
||||
!isCreateBy(NULL_PAGE_NAME) &&
|
||||
fun isBrowsable(): Boolean {
|
||||
return !isCreateBy(NULL_PAGE_NAME) &&
|
||||
!hasRuntimeParam()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.util
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntry
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
|
||||
|
||||
const val SESSION_BROWSE = "browse"
|
||||
const val SESSION_SEARCH = "search"
|
||||
const val SESSION_SLICE = "slice"
|
||||
|
||||
const val KEY_DESTINATION = "spaActivityDestination"
|
||||
const val KEY_HIGHLIGHT_ENTRY = "highlightEntry"
|
||||
const val KEY_SESSION_SOURCE_NAME = "sessionSource"
|
||||
|
||||
val SPA_INTENT_RESERVED_KEYS = listOf(
|
||||
KEY_DESTINATION,
|
||||
KEY_HIGHLIGHT_ENTRY,
|
||||
KEY_SESSION_SOURCE_NAME
|
||||
)
|
||||
|
||||
private fun createBaseIntent(): Intent? {
|
||||
val context = SpaEnvironmentFactory.instance.appContext
|
||||
val browseActivityClass = SpaEnvironmentFactory.instance.browseActivityClass ?: return null
|
||||
return Intent().setComponent(ComponentName(context, browseActivityClass))
|
||||
}
|
||||
|
||||
fun SettingsPage.createIntent(sessionName: String? = null): Intent? {
|
||||
if (!isBrowsable()) return null
|
||||
return createBaseIntent()?.appendSpaParams(
|
||||
destination = buildRoute(),
|
||||
sessionName = sessionName
|
||||
)
|
||||
}
|
||||
|
||||
fun SettingsEntry.createIntent(sessionName: String? = null): Intent? {
|
||||
val sp = containerPage()
|
||||
if (!sp.isBrowsable()) return null
|
||||
return createBaseIntent()?.appendSpaParams(
|
||||
destination = sp.buildRoute(),
|
||||
entryId = id,
|
||||
sessionName = sessionName
|
||||
)
|
||||
}
|
||||
|
||||
fun Intent.appendSpaParams(
|
||||
destination: String? = null,
|
||||
entryId: String? = null,
|
||||
sessionName: String? = null
|
||||
): Intent {
|
||||
return apply {
|
||||
if (destination != null) putExtra(KEY_DESTINATION, destination)
|
||||
if (entryId != null) putExtra(KEY_HIGHLIGHT_ENTRY, entryId)
|
||||
if (sessionName != null) putExtra(KEY_SESSION_SOURCE_NAME, sessionName)
|
||||
}
|
||||
}
|
||||
|
||||
fun Intent.getDestination(): String? {
|
||||
return getStringExtra(KEY_DESTINATION)
|
||||
}
|
||||
|
||||
fun Intent.getEntryId(): String? {
|
||||
return getStringExtra(KEY_HIGHLIGHT_ENTRY)
|
||||
}
|
||||
|
||||
fun Intent.getSessionName(): String? {
|
||||
return getStringExtra(KEY_SESSION_SOURCE_NAME)
|
||||
}
|
||||
@@ -33,6 +33,8 @@ import com.android.settingslib.spa.framework.common.SettingsEntry
|
||||
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
|
||||
import com.android.settingslib.spa.framework.common.addUri
|
||||
import com.android.settingslib.spa.framework.common.getColumns
|
||||
import com.android.settingslib.spa.framework.util.SESSION_SEARCH
|
||||
import com.android.settingslib.spa.framework.util.createIntent
|
||||
|
||||
private const val TAG = "SpaSearchProvider"
|
||||
|
||||
@@ -162,20 +164,19 @@ class SpaSearchProvider : 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() ?: return
|
||||
val intent = entry.containerPage()
|
||||
.createBrowseIntent(context, browseActivityClass, entry.id)
|
||||
?: Intent()
|
||||
val intent = entry.createIntent(SESSION_SEARCH) ?: Intent()
|
||||
cursor.newRow()
|
||||
.add(ColumnEnum.ENTRY_ID.id, entry.id)
|
||||
.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.getEntryPathWithTitle(entry.id, searchData.title))
|
||||
.add(
|
||||
ColumnEnum.SEARCH_PATH.id,
|
||||
entryRepository.getEntryPathWithTitle(entry.id, searchData.title)
|
||||
)
|
||||
}
|
||||
|
||||
private fun fetchStatusData(entry: SettingsEntry, cursor: MatrixCursor) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.net.Uri
|
||||
import android.util.Log
|
||||
import com.android.settingslib.spa.framework.common.EntrySliceData
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryRepository
|
||||
import com.android.settingslib.spa.framework.util.getEntryId
|
||||
|
||||
private const val TAG = "SliceDataRepository"
|
||||
|
||||
|
||||
@@ -24,9 +24,15 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import com.android.settingslib.spa.framework.BrowseActivity.Companion.KEY_DESTINATION
|
||||
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.SpaEnvironmentFactory
|
||||
import com.android.settingslib.spa.framework.util.KEY_DESTINATION
|
||||
import com.android.settingslib.spa.framework.util.KEY_HIGHLIGHT_ENTRY
|
||||
import com.android.settingslib.spa.framework.util.SESSION_SLICE
|
||||
import com.android.settingslib.spa.framework.util.SPA_INTENT_RESERVED_KEYS
|
||||
import com.android.settingslib.spa.framework.util.appendSpaParams
|
||||
import com.android.settingslib.spa.framework.util.getDestination
|
||||
import com.android.settingslib.spa.framework.util.getEntryId
|
||||
|
||||
// Defines SliceUri, which contains special query parameters:
|
||||
// -- KEY_DESTINATION: The route that this slice is navigated to.
|
||||
@@ -35,11 +41,6 @@ import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
|
||||
// Use {entryId, runtimeParams} as the unique Id of this Slice.
|
||||
typealias SliceUri = Uri
|
||||
|
||||
val RESERVED_KEYS = listOf(
|
||||
KEY_DESTINATION,
|
||||
KEY_HIGHLIGHT_ENTRY
|
||||
)
|
||||
|
||||
fun SliceUri.getEntryId(): String? {
|
||||
return getQueryParameter(KEY_HIGHLIGHT_ENTRY)
|
||||
}
|
||||
@@ -51,7 +52,7 @@ fun SliceUri.getDestination(): String? {
|
||||
fun SliceUri.getRuntimeArguments(): Bundle {
|
||||
val params = Bundle()
|
||||
for (queryName in queryParameterNames) {
|
||||
if (RESERVED_KEYS.contains(queryName)) continue
|
||||
if (SPA_INTENT_RESERVED_KEYS.contains(queryName)) continue
|
||||
params.putString(queryName, getQueryParameter(queryName))
|
||||
}
|
||||
return params
|
||||
@@ -63,12 +64,12 @@ fun SliceUri.getSliceId(): String? {
|
||||
return "${entryId}_$params"
|
||||
}
|
||||
|
||||
fun Uri.Builder.appendSliceParams(
|
||||
route: String? = null,
|
||||
fun Uri.Builder.appendSpaParams(
|
||||
destination: String? = null,
|
||||
entryId: String? = null,
|
||||
runtimeArguments: Bundle? = null
|
||||
): Uri.Builder {
|
||||
if (route != null) appendQueryParameter(KEY_DESTINATION, route)
|
||||
if (destination != null) appendQueryParameter(KEY_DESTINATION, destination)
|
||||
if (entryId != null) appendQueryParameter(KEY_HIGHLIGHT_ENTRY, entryId)
|
||||
if (runtimeArguments != null) {
|
||||
for (key in runtimeArguments.keySet()) {
|
||||
@@ -78,6 +79,20 @@ fun Uri.Builder.appendSliceParams(
|
||||
return this
|
||||
}
|
||||
|
||||
fun Uri.Builder.fromEntry(
|
||||
entry: SettingsEntry,
|
||||
authority: String?,
|
||||
runtimeArguments: Bundle? = null
|
||||
): Uri.Builder {
|
||||
if (authority == null) return this
|
||||
val sp = entry.containerPage()
|
||||
return scheme("content").authority(authority).appendSpaParams(
|
||||
destination = sp.buildRoute(),
|
||||
entryId = entry.id,
|
||||
runtimeArguments = runtimeArguments
|
||||
)
|
||||
}
|
||||
|
||||
fun SliceUri.createBroadcastPendingIntent(): PendingIntent? {
|
||||
val context = SpaEnvironmentFactory.instance.appContext
|
||||
val sliceBroadcastClass =
|
||||
@@ -97,8 +112,8 @@ fun SliceUri.createBrowsePendingIntent(): PendingIntent? {
|
||||
fun Intent.createBrowsePendingIntent(): PendingIntent? {
|
||||
val context = SpaEnvironmentFactory.instance.appContext
|
||||
val browseActivityClass = SpaEnvironmentFactory.instance.browseActivityClass ?: return null
|
||||
val destination = getStringExtra(KEY_DESTINATION) ?: return null
|
||||
val entryId = getStringExtra(KEY_HIGHLIGHT_ENTRY)
|
||||
val destination = getDestination() ?: return null
|
||||
val entryId = getEntryId()
|
||||
return createBrowsePendingIntent(context, browseActivityClass, destination, entryId)
|
||||
}
|
||||
|
||||
@@ -109,15 +124,12 @@ private fun createBrowsePendingIntent(
|
||||
entryId: String?
|
||||
): PendingIntent {
|
||||
val intent = Intent().setComponent(ComponentName(context, browseActivityClass))
|
||||
.appendSpaParams(destination, entryId, SESSION_SLICE)
|
||||
.apply {
|
||||
// Set both extra and data (which is a Uri) in Slice Intent:
|
||||
// 1) extra is used in SPA navigation framework
|
||||
// 2) data is used in Slice framework
|
||||
putExtra(KEY_DESTINATION, destination)
|
||||
if (entryId != null) {
|
||||
putExtra(KEY_HIGHLIGHT_ENTRY, entryId)
|
||||
}
|
||||
data = Uri.Builder().appendSliceParams(destination, entryId).build()
|
||||
data = Uri.Builder().appendSpaParams(destination, entryId).build()
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
|
||||
@@ -130,7 +142,7 @@ private fun createBroadcastPendingIntent(
|
||||
entryId: String
|
||||
): PendingIntent {
|
||||
val intent = Intent().setComponent(ComponentName(context, sliceBroadcastClass))
|
||||
.apply { data = Uri.Builder().appendSliceParams(entryId = entryId).build() }
|
||||
.apply { data = Uri.Builder().appendSpaParams(entryId = entryId).build() }
|
||||
return PendingIntent.getBroadcast(
|
||||
context, 0 /* requestCode */, intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
|
||||
import com.android.settingslib.spa.tests.testutils.SppHome
|
||||
import com.android.settingslib.spa.tests.testutils.SppLayer1
|
||||
import com.android.settingslib.spa.tests.testutils.SppLayer2
|
||||
import com.android.settingslib.spa.tests.testutils.getUniqueEntryId
|
||||
import com.android.settingslib.spa.tests.testutils.getUniquePageId
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@@ -20,6 +20,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settingslib.spa.tests.testutils.getUniqueEntryId
|
||||
import com.android.settingslib.spa.tests.testutils.getUniquePageId
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
@@ -22,8 +22,8 @@ import androidx.navigation.NavType
|
||||
import androidx.navigation.navArgument
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settingslib.spa.tests.testutils.BlankActivity
|
||||
import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
|
||||
import com.android.settingslib.spa.tests.testutils.getUniquePageId
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -43,9 +43,7 @@ class SettingsPageTest {
|
||||
assertThat(page.isCreateBy("NULL")).isTrue()
|
||||
assertThat(page.isCreateBy("Spp")).isFalse()
|
||||
assertThat(page.hasRuntimeParam()).isFalse()
|
||||
assertThat(page.isBrowsable(context, BlankActivity::class.java)).isFalse()
|
||||
assertThat(page.createBrowseIntent(context, BlankActivity::class.java)).isNull()
|
||||
assertThat(page.createBrowseAdbCommand(context, BlankActivity::class.java)).isNull()
|
||||
assertThat(page.isBrowsable()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -58,11 +56,7 @@ class SettingsPageTest {
|
||||
assertThat(page.isCreateBy("NULL")).isFalse()
|
||||
assertThat(page.isCreateBy("mySpp")).isTrue()
|
||||
assertThat(page.hasRuntimeParam()).isFalse()
|
||||
assertThat(page.isBrowsable(context, BlankActivity::class.java)).isTrue()
|
||||
assertThat(page.createBrowseIntent(context, BlankActivity::class.java)).isNotNull()
|
||||
assertThat(page.createBrowseAdbCommand(context, BlankActivity::class.java)).contains(
|
||||
"-e spaActivityDestination mySpp"
|
||||
)
|
||||
assertThat(page.isBrowsable()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,11 +79,7 @@ class SettingsPageTest {
|
||||
assertThat(page.buildRoute()).isEqualTo("SppWithParam/myStr/10")
|
||||
assertThat(page.isCreateBy("SppWithParam")).isTrue()
|
||||
assertThat(page.hasRuntimeParam()).isFalse()
|
||||
assertThat(page.isBrowsable(context, BlankActivity::class.java)).isTrue()
|
||||
assertThat(page.createBrowseIntent(context, BlankActivity::class.java)).isNotNull()
|
||||
assertThat(page.createBrowseAdbCommand(context, BlankActivity::class.java)).contains(
|
||||
"-e spaActivityDestination SppWithParam/myStr/10"
|
||||
)
|
||||
assertThat(page.isBrowsable()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,8 +104,6 @@ class SettingsPageTest {
|
||||
assertThat(page.buildRoute()).isEqualTo("SppWithRtParam/myStr/10/rtStr")
|
||||
assertThat(page.isCreateBy("SppWithRtParam")).isTrue()
|
||||
assertThat(page.hasRuntimeParam()).isTrue()
|
||||
assertThat(page.isBrowsable(context, BlankActivity::class.java)).isFalse()
|
||||
assertThat(page.createBrowseIntent(context, BlankActivity::class.java)).isNull()
|
||||
assertThat(page.createBrowseAdbCommand(context, BlankActivity::class.java)).isNull()
|
||||
assertThat(page.isBrowsable()).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.util
|
||||
|
||||
import android.content.Context
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
|
||||
import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
|
||||
import com.google.common.truth.Truth
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SpaIntentTest {
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
private val spaEnvironment = SpaEnvironmentForTest(context)
|
||||
|
||||
@Before
|
||||
fun setEnvironment() {
|
||||
SpaEnvironmentFactory.reset(spaEnvironment)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateIntent() {
|
||||
val nullPage = SettingsPage.createNull()
|
||||
Truth.assertThat(nullPage.createIntent()).isNull()
|
||||
Truth.assertThat(SettingsEntryBuilder.createInject(nullPage).build().createIntent())
|
||||
.isNull()
|
||||
|
||||
val page = spaEnvironment.createPage("SppHome")
|
||||
val pageIntent = page.createIntent()
|
||||
Truth.assertThat(pageIntent).isNotNull()
|
||||
Truth.assertThat(pageIntent!!.getDestination()).isEqualTo(page.buildRoute())
|
||||
Truth.assertThat(pageIntent.getEntryId()).isNull()
|
||||
Truth.assertThat(pageIntent.getSessionName()).isNull()
|
||||
|
||||
val entry = SettingsEntryBuilder.createInject(page).build()
|
||||
val entryIntent = entry.createIntent(SESSION_SEARCH)
|
||||
Truth.assertThat(entryIntent).isNotNull()
|
||||
Truth.assertThat(entryIntent!!.getDestination()).isEqualTo(page.buildRoute())
|
||||
Truth.assertThat(entryIntent.getEntryId()).isEqualTo(entry.id)
|
||||
Truth.assertThat(entryIntent.getSessionName()).isEqualTo(SESSION_SEARCH)
|
||||
}
|
||||
}
|
||||
@@ -23,11 +23,11 @@ import androidx.slice.Slice
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settingslib.spa.framework.common.createSettingsPage
|
||||
import com.android.settingslib.spa.framework.common.getUniqueEntryId
|
||||
import com.android.settingslib.spa.testutils.InstantTaskExecutorRule
|
||||
import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
|
||||
import com.android.settingslib.spa.tests.testutils.SppHome
|
||||
import com.android.settingslib.spa.tests.testutils.SppLayer2
|
||||
import com.android.settingslib.spa.tests.testutils.getUniqueEntryId
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@@ -50,7 +50,7 @@ class SettingsSliceDataRepositoryTest {
|
||||
// Slice supported
|
||||
val page = SppLayer2.createSettingsPage()
|
||||
val entryId = getUniqueEntryId("Layer2Entry1", page)
|
||||
val sliceUri = Uri.Builder().appendSliceParams(page.buildRoute(), entryId).build()
|
||||
val sliceUri = Uri.Builder().appendSpaParams(page.buildRoute(), entryId).build()
|
||||
assertThat(sliceUri.getDestination()).isEqualTo("SppLayer2")
|
||||
assertThat(sliceUri.getSliceId()).isEqualTo("${entryId}_Bundle[{}]")
|
||||
val sliceData = sliceDataRepository.getOrBuildSliceData(sliceUri)
|
||||
@@ -59,7 +59,7 @@ class SettingsSliceDataRepositoryTest {
|
||||
|
||||
// Slice unsupported
|
||||
val entryId2 = getUniqueEntryId("Layer2Entry2", page)
|
||||
val sliceUri2 = Uri.Builder().appendSliceParams(page.buildRoute(), entryId2).build()
|
||||
val sliceUri2 = Uri.Builder().appendSpaParams(page.buildRoute(), entryId2).build()
|
||||
assertThat(sliceUri2.getDestination()).isEqualTo("SppLayer2")
|
||||
assertThat(sliceUri2.getSliceId()).isEqualTo("${entryId2}_Bundle[{}]")
|
||||
assertThat(sliceDataRepository.getOrBuildSliceData(sliceUri2)).isNull()
|
||||
@@ -69,7 +69,7 @@ class SettingsSliceDataRepositoryTest {
|
||||
fun getActiveSliceDataTest() {
|
||||
val page = SppLayer2.createSettingsPage()
|
||||
val entryId = getUniqueEntryId("Layer2Entry1", page)
|
||||
val sliceUri = Uri.Builder().appendSliceParams(page.buildRoute(), entryId).build()
|
||||
val sliceUri = Uri.Builder().appendSpaParams(page.buildRoute(), entryId).build()
|
||||
|
||||
// build slice data first
|
||||
val sliceData = sliceDataRepository.getOrBuildSliceData(sliceUri)
|
||||
|
||||
@@ -43,14 +43,14 @@ class SliceUtilTest {
|
||||
// valid slice uri
|
||||
val dest = "myRoute"
|
||||
val entryId = "myEntry"
|
||||
val sliceUriWithoutParams = Uri.Builder().appendSliceParams(dest, entryId).build()
|
||||
val sliceUriWithoutParams = Uri.Builder().appendSpaParams(dest, entryId).build()
|
||||
assertThat(sliceUriWithoutParams.getEntryId()).isEqualTo(entryId)
|
||||
assertThat(sliceUriWithoutParams.getDestination()).isEqualTo(dest)
|
||||
assertThat(sliceUriWithoutParams.getRuntimeArguments().size()).isEqualTo(0)
|
||||
assertThat(sliceUriWithoutParams.getSliceId()).isEqualTo("${entryId}_Bundle[{}]")
|
||||
|
||||
val sliceUriWithParams =
|
||||
Uri.Builder().appendSliceParams(dest, entryId, bundleOf("p1" to "v1")).build()
|
||||
Uri.Builder().appendSpaParams(dest, entryId, bundleOf("p1" to "v1")).build()
|
||||
assertThat(sliceUriWithParams.getEntryId()).isEqualTo(entryId)
|
||||
assertThat(sliceUriWithParams.getDestination()).isEqualTo(dest)
|
||||
assertThat(sliceUriWithParams.getRuntimeArguments().size()).isEqualTo(1)
|
||||
@@ -67,7 +67,7 @@ class SliceUtilTest {
|
||||
// Valid Slice Uri
|
||||
val dest = "myRoute"
|
||||
val entryId = "myEntry"
|
||||
val sliceUriWithoutParams = Uri.Builder().appendSliceParams(dest, entryId).build()
|
||||
val sliceUriWithoutParams = Uri.Builder().appendSpaParams(dest, entryId).build()
|
||||
val pendingIntent = sliceUriWithoutParams.createBroadcastPendingIntent()
|
||||
assertThat(pendingIntent).isNotNull()
|
||||
assertThat(pendingIntent!!.isBroadcast).isTrue()
|
||||
@@ -87,7 +87,7 @@ class SliceUtilTest {
|
||||
// Valid Slice Uri
|
||||
val dest = "myRoute"
|
||||
val entryId = "myEntry"
|
||||
val sliceUri = Uri.Builder().appendSliceParams(dest, entryId).build()
|
||||
val sliceUri = Uri.Builder().appendSpaParams(dest, entryId).build()
|
||||
val pendingIntent = sliceUri.createBrowsePendingIntent()
|
||||
assertThat(pendingIntent).isNotNull()
|
||||
assertThat(pendingIntent!!.isActivity).isTrue()
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settingslib.spa.framework.common
|
||||
package com.android.settingslib.spa.tests.testutils
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.navigation.NamedNavArgument
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.toHashId
|
||||
import com.android.settingslib.spa.framework.util.normalize
|
||||
|
||||
fun getUniquePageId(
|
||||
Reference in New Issue
Block a user