Fix search for MMS Message

Also display multiple results when there are multiple MMS Message on
different SIMs.

When doing indexing, we not also log sub id as part of the key.
When user clicks the result, using SpaSearchLandingActivity to do the
redirection, set arguments to the fragment.

Fix: 352245817
Flag: EXEMPT bug fix
Test: manual - search mms
Test: unit test
Change-Id: Id47a1151cb418c18f68f97e3be33dcd21c5f5102
This commit is contained in:
Chaohui Wang
2024-07-29 15:04:31 +08:00
parent 7477f4ea9a
commit 7009c008f9
13 changed files with 594 additions and 148 deletions

View File

@@ -16,7 +16,7 @@
package com.android.settings.spa
import android.app.Activity
import android.content.Context
import android.content.Intent
import com.android.settings.activityembedding.ActivityEmbeddingUtils
import com.android.settings.activityembedding.EmbeddedDeepLinkUtils.tryStartMultiPaneDeepLink
@@ -27,16 +27,16 @@ data class SpaDestination(
val destination: String,
val highlightMenuKey: String?,
) {
fun startFromExportedActivity(activity: Activity) {
val intent = Intent(activity, SpaActivity::class.java)
fun startFromExportedActivity(context: Context) {
val intent = Intent(context, SpaActivity::class.java)
.appendSpaParams(
destination = destination,
sessionName = SESSION_EXTERNAL,
)
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(activity) ||
!activity.tryStartMultiPaneDeepLink(intent, highlightMenuKey)
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(context) ||
!context.tryStartMultiPaneDeepLink(intent, highlightMenuKey)
) {
activity.startActivity(intent)
context.startActivity(intent)
}
}
}

View File

@@ -17,37 +17,26 @@
package com.android.settings.spa.search
import android.app.Activity
import android.app.settings.SettingsEnums
import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY
import com.android.settings.core.SubSettingLauncher
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import com.android.settings.password.PasswordUtils
import com.android.settings.spa.SpaDestination
import com.android.settings.spa.SpaSearchLanding
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey
import com.google.protobuf.ByteString
import com.google.protobuf.InvalidProtocolBufferException
class SpaSearchLandingActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (!isValidCall()) return
val keyString = intent.getStringExtra(EXTRA_FRAGMENT_ARG_KEY)
val key =
try {
SpaSearchLanding.SpaSearchLandingKey.parseFrom(ByteString.copyFromUtf8(keyString))
} catch (e: InvalidProtocolBufferException) {
Log.w(TAG, "arg key ($keyString) invalid", e)
finish()
return
}
if (key.hasSpaPage()) {
val destination = key.spaPage.destination
if (destination.isNotEmpty()) {
SpaDestination(destination = destination, highlightMenuKey = null)
.startFromExportedActivity(this)
}
if (!keyString.isNullOrEmpty() && isValidCall()) {
tryLaunch(this, keyString)
}
finish()
}
@@ -56,7 +45,40 @@ class SpaSearchLandingActivity : Activity() {
PasswordUtils.getCallingAppPackageName(activityToken) ==
featureFactory.searchFeatureProvider.getSettingsIntelligencePkgName(this)
private companion object {
companion object {
@VisibleForTesting
fun tryLaunch(context: Context, keyString: String) {
val key =
try {
SpaSearchLandingKey.parseFrom(ByteString.copyFromUtf8(keyString))
} catch (e: InvalidProtocolBufferException) {
Log.w(TAG, "arg key ($keyString) invalid", e)
return
}
if (key.hasSpaPage()) {
val destination = key.spaPage.destination
if (destination.isNotEmpty()) {
SpaDestination(destination = destination, highlightMenuKey = null)
.startFromExportedActivity(context)
}
}
if (key.hasFragment()) {
val arguments =
Bundle().apply {
key.fragment.argumentsMap.forEach { (k, v) ->
if (v.hasIntValue()) putInt(k, v.intValue)
}
putString(EXTRA_FRAGMENT_ARG_KEY, key.fragment.preferenceKey)
}
SubSettingLauncher(context)
.setDestination(key.fragment.fragmentName)
.setArguments(arguments)
.setSourceMetricsCategory(SettingsEnums.PAGE_UNKNOWN)
.launch()
}
}
private const val TAG = "SpaSearchLandingActivity"
}
}

View File

@@ -20,6 +20,7 @@ import android.content.Context
import android.provider.SearchIndexableResource
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingSpaPage
import com.android.settingslib.search.Indexable
@@ -39,7 +40,7 @@ class SpaSearchRepository(
page.createSearchIndexableData(
page::getPageTitleForSearch, page::getSearchableTitles)
} else null
}
} + MobileNetworkSettingsSearchIndex().createSearchIndexableData()
}
companion object {
@@ -50,50 +51,56 @@ class SpaSearchRepository(
getPageTitleForSearch: (context: Context) -> String,
titlesProvider: (context: Context) -> List<String>,
): SearchIndexableData {
val searchIndexProvider =
object : Indexable.SearchIndexProvider {
override fun getXmlResourcesToIndex(
context: Context,
enabled: Boolean,
): List<SearchIndexableResource> = emptyList()
override fun getRawDataToIndex(
context: Context,
enabled: Boolean,
): List<SearchIndexableRaw> = emptyList()
override fun getDynamicRawDataToIndex(
context: Context,
enabled: Boolean,
): List<SearchIndexableRaw> {
val pageTitle = getPageTitleForSearch(context)
return titlesProvider(context).map { itemTitle ->
createSearchIndexableRaw(context, itemTitle, pageTitle)
}
}
override fun getNonIndexableKeys(context: Context): List<String> = emptyList()
val key =
SpaSearchLandingKey.newBuilder()
.setSpaPage(SpaSearchLandingSpaPage.newBuilder().setDestination(name))
.build()
val indexableClass = this::class.java
val searchIndexProvider = searchIndexProviderOf { context ->
val pageTitle = getPageTitleForSearch(context)
titlesProvider(context).map { itemTitle ->
createSearchIndexableRaw(context, key, itemTitle, indexableClass, pageTitle)
}
return SearchIndexableData(this::class.java, searchIndexProvider)
}
return SearchIndexableData(indexableClass, searchIndexProvider)
}
private fun SettingsPageProvider.createSearchIndexableRaw(
fun searchIndexProviderOf(
getDynamicRawDataToIndex: (context: Context) -> List<SearchIndexableRaw>,
) =
object : Indexable.SearchIndexProvider {
override fun getXmlResourcesToIndex(
context: Context,
enabled: Boolean,
): List<SearchIndexableResource> = emptyList()
override fun getRawDataToIndex(
context: Context,
enabled: Boolean,
): List<SearchIndexableRaw> = emptyList()
override fun getDynamicRawDataToIndex(
context: Context,
enabled: Boolean,
): List<SearchIndexableRaw> = getDynamicRawDataToIndex(context)
override fun getNonIndexableKeys(context: Context): List<String> = emptyList()
}
fun createSearchIndexableRaw(
context: Context,
spaSearchLandingKey: SpaSearchLandingKey,
itemTitle: String,
indexableClass: Class<*>,
pageTitle: String,
) =
SearchIndexableRaw(context).apply {
key =
SpaSearchLandingKey.newBuilder()
.setSpaPage(SpaSearchLandingSpaPage.newBuilder().setDestination(name))
.build()
.toByteString()
.toStringUtf8()
key = spaSearchLandingKey.toByteString().toStringUtf8()
title = itemTitle
intentAction = SEARCH_LANDING_ACTION
intentTargetClass = SpaSearchLandingActivity::class.qualifiedName
packageName = context.packageName
className = this@createSearchIndexableRaw::class.java.name
className = indexableClass.name
screenTitle = pageTitle
}