Show category when search "Mobile data"

The displayed category is "SIMs".

Bug: 346776183
Flag: EXEMPT bug fix
Test: manual - search "Mobile data"
Test: unit test
Change-Id: If3c395281e96603193e7476a9e76d1f9e9213531
This commit is contained in:
Chaohui Wang
2024-07-26 14:51:33 +08:00
parent 50a18d9e85
commit 7477f4ea9a
8 changed files with 93 additions and 56 deletions

View File

@@ -82,12 +82,10 @@ android_library {
"android.hardware.dumpstate-V1-java", "android.hardware.dumpstate-V1-java",
"android.hardware.dumpstate-V1.0-java", "android.hardware.dumpstate-V1.0-java",
"android.hardware.dumpstate-V1.1-java", "android.hardware.dumpstate-V1.1-java",
"android.view.accessibility.flags-aconfig-java",
"com_android_server_accessibility_flags_lib", "com_android_server_accessibility_flags_lib",
"net-utils-framework-common", "net-utils-framework-common",
"notification_flags_lib", "notification_flags_lib",
"securebox", "securebox",
"android.os.flags-aconfig-java",
"//frameworks/libs/systemui:com_android_systemui_shared_flags_lib", "//frameworks/libs/systemui:com_android_systemui_shared_flags_lib",
"WindowManager-Shell-shared-desktopMode", "WindowManager-Shell-shared-desktopMode",
@@ -103,12 +101,9 @@ android_library {
"contextualcards", "contextualcards",
"development_settings_flag_lib", "development_settings_flag_lib",
"factory_reset_flags_lib", "factory_reset_flags_lib",
"fuelgauge-log-protos-lite", "settings-protos-lite",
"fuelgauge-protos-lite", "fuelgauge-protos-lite",
"settings-contextual-card-protos-lite",
"settings-log-bridge-protos-lite",
"settings-logtags", "settings-logtags",
"settings-telephony-protos-lite",
"statslog-settings", "statslog-settings",
"telephony_flags_core_java_lib", "telephony_flags_core_java_lib",
"setupdesign-lottie-loading-layout", "setupdesign-lottie-loading-layout",

View File

@@ -1,44 +1,12 @@
package { package {
default_team: "trendy_team_android_settings_app", default_team: "trendy_team_android_settings_app",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "packages_apps_Settings_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["packages_apps_Settings_license"], default_applicable_licenses: ["packages_apps_Settings_license"],
} }
java_library_static {
name: "settings-contextual-card-protos-lite",
host_supported: true,
proto: {
type: "lite",
},
srcs: ["contextual_card_list.proto"],
}
java_library_static {
name: "settings-log-bridge-protos-lite",
host_supported: true,
proto: {
type: "lite",
},
srcs: ["settings_log_bridge.proto"],
}
java_library_static {
name: "settings-telephony-protos-lite",
host_supported: true,
proto: {
type: "lite",
},
srcs: ["network_mode_choices.proto"],
}
java_library { java_library {
name: "fuelgauge-log-protos-lite", name: "settings-protos-lite",
proto: { proto: {
type: "lite", type: "lite",
}, },
srcs: ["fuelgauge_log.proto"], srcs: ["*.proto"],
} }

View File

@@ -0,0 +1,14 @@
syntax = "proto2";
package com.android.settings.spa;
message SpaSearchLandingKey {
oneof page {
SpaSearchLandingSpaPage spa_page = 1;
}
}
message SpaSearchLandingSpaPage {
/** The destination of SPA page. */
optional string destination = 1;
}

View File

@@ -197,6 +197,9 @@ open class NetworkCellularGroupProvider : SettingsPageProvider, SearchablePage {
// Do nothing // Do nothing
} }
override fun getPageTitleForSearch(context: Context): String =
context.getString(R.string.provider_network_settings_title)
override fun getSearchableTitles(context: Context): List<String> { override fun getSearchableTitles(context: Context): List<String> {
if (!isPageSearchable(context)) return emptyList() if (!isPageSearchable(context)) return emptyList()
return buildList { return buildList {

View File

@@ -20,6 +20,9 @@ import android.content.Context
interface SearchablePage { interface SearchablePage {
/** Gets the searchable titles at the current moment. */ /** Gets the title of the page. */
fun getPageTitleForSearch(context: Context): String = ""
/** Gets the titles of the searchable items at the current moment. */
fun getSearchableTitles(context: Context): List<String> fun getSearchableTitles(context: Context): List<String>
} }

View File

@@ -18,25 +18,45 @@ package com.android.settings.spa.search
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import android.util.Log
import com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY import com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import com.android.settings.password.PasswordUtils import com.android.settings.password.PasswordUtils
import com.android.settings.spa.SpaDestination import com.android.settings.spa.SpaDestination
import com.android.settings.spa.SpaSearchLanding
import com.google.protobuf.ByteString
import com.google.protobuf.InvalidProtocolBufferException
class SpaSearchLandingActivity : Activity() { class SpaSearchLandingActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (!isValidCall()) return if (!isValidCall()) return
val destination = intent.getStringExtra(EXTRA_FRAGMENT_ARG_KEY) val keyString = intent.getStringExtra(EXTRA_FRAGMENT_ARG_KEY)
if (destination.isNullOrBlank()) return 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) SpaDestination(destination = destination, highlightMenuKey = null)
.startFromExportedActivity(this) .startFromExportedActivity(this)
}
}
finish() finish()
} }
private fun isValidCall() = private fun isValidCall() =
PasswordUtils.getCallingAppPackageName(activityToken) == PasswordUtils.getCallingAppPackageName(activityToken) ==
featureFactory.searchFeatureProvider.getSettingsIntelligencePkgName(this) featureFactory.searchFeatureProvider.getSettingsIntelligencePkgName(this)
private companion object {
private const val TAG = "SpaSearchLandingActivity"
}
} }

View File

@@ -20,6 +20,8 @@ import android.content.Context
import android.provider.SearchIndexableResource import android.provider.SearchIndexableResource
import android.util.Log import android.util.Log
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingSpaPage
import com.android.settingslib.search.Indexable import com.android.settingslib.search.Indexable
import com.android.settingslib.search.SearchIndexableData import com.android.settingslib.search.SearchIndexableData
import com.android.settingslib.search.SearchIndexableRaw import com.android.settingslib.search.SearchIndexableRaw
@@ -34,7 +36,8 @@ class SpaSearchRepository(
Log.d(TAG, "getSearchIndexableDataList") Log.d(TAG, "getSearchIndexableDataList")
return spaEnvironment.pageProviderRepository.value.getAllProviders().mapNotNull { page -> return spaEnvironment.pageProviderRepository.value.getAllProviders().mapNotNull { page ->
if (page is SearchablePage) { if (page is SearchablePage) {
page.createSearchIndexableData(page::getSearchableTitles) page.createSearchIndexableData(
page::getPageTitleForSearch, page::getSearchableTitles)
} else null } else null
} }
} }
@@ -44,6 +47,7 @@ class SpaSearchRepository(
@VisibleForTesting @VisibleForTesting
fun SettingsPageProvider.createSearchIndexableData( fun SettingsPageProvider.createSearchIndexableData(
getPageTitleForSearch: (context: Context) -> String,
titlesProvider: (context: Context) -> List<String>, titlesProvider: (context: Context) -> List<String>,
): SearchIndexableData { ): SearchIndexableData {
val searchIndexProvider = val searchIndexProvider =
@@ -61,9 +65,11 @@ class SpaSearchRepository(
override fun getDynamicRawDataToIndex( override fun getDynamicRawDataToIndex(
context: Context, context: Context,
enabled: Boolean, enabled: Boolean,
): List<SearchIndexableRaw> = ): List<SearchIndexableRaw> {
titlesProvider(context).map { title -> val pageTitle = getPageTitleForSearch(context)
createSearchIndexableRaw(context, title) return titlesProvider(context).map { itemTitle ->
createSearchIndexableRaw(context, itemTitle, pageTitle)
}
} }
override fun getNonIndexableKeys(context: Context): List<String> = emptyList() override fun getNonIndexableKeys(context: Context): List<String> = emptyList()
@@ -71,13 +77,24 @@ class SpaSearchRepository(
return SearchIndexableData(this::class.java, searchIndexProvider) return SearchIndexableData(this::class.java, searchIndexProvider)
} }
private fun SettingsPageProvider.createSearchIndexableRaw(context: Context, title: String) = private fun SettingsPageProvider.createSearchIndexableRaw(
context: Context,
itemTitle: String,
pageTitle: String,
) =
SearchIndexableRaw(context).apply { SearchIndexableRaw(context).apply {
key = name key =
this.title = title SpaSearchLandingKey.newBuilder()
.setSpaPage(SpaSearchLandingSpaPage.newBuilder().setDestination(name))
.build()
.toByteString()
.toStringUtf8()
title = itemTitle
intentAction = SEARCH_LANDING_ACTION intentAction = SEARCH_LANDING_ACTION
intentTargetClass = SpaSearchLandingActivity::class.qualifiedName
packageName = context.packageName packageName = context.packageName
className = SpaSearchLandingActivity::class.qualifiedName className = this@createSearchIndexableRaw::class.java.name
screenTitle = pageTitle
} }
private const val SEARCH_LANDING_ACTION = "android.settings.SPA_SEARCH_LANDING" private const val SEARCH_LANDING_ACTION = "android.settings.SPA_SEARCH_LANDING"

View File

@@ -18,9 +18,12 @@ package com.android.settings.spa.search
import android.content.Context import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingSpaPage
import com.android.settings.spa.search.SpaSearchRepository.Companion.createSearchIndexableData import com.android.settings.spa.search.SpaSearchRepository.Companion.createSearchIndexableData
import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import com.google.protobuf.ByteString
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.kotlin.mock import org.mockito.kotlin.mock
@@ -35,17 +38,31 @@ class SpaSearchRepositoryTest {
override val name = PAGE_NAME override val name = PAGE_NAME
} }
val searchIndexableData = pageProvider.createSearchIndexableData { listOf(TITLE) } val searchIndexableData =
pageProvider.createSearchIndexableData({ PAGE_TITLE }) { listOf(ITEM_TITLE) }
val dynamicRawDataToIndex = val dynamicRawDataToIndex =
searchIndexableData.searchIndexProvider.getDynamicRawDataToIndex(mock<Context>(), true) searchIndexableData.searchIndexProvider.getDynamicRawDataToIndex(mock<Context>(), true)
assertThat(searchIndexableData.targetClass).isEqualTo(pageProvider::class.java) assertThat(searchIndexableData.targetClass).isEqualTo(pageProvider::class.java)
assertThat(dynamicRawDataToIndex).hasSize(1) assertThat(dynamicRawDataToIndex).hasSize(1)
assertThat(dynamicRawDataToIndex[0].title).isEqualTo(TITLE) val rawData = dynamicRawDataToIndex[0]
val key = SpaSearchLandingKey.parseFrom(ByteString.copyFromUtf8(rawData.key))
assertThat(key)
.isEqualTo(
SpaSearchLandingKey.newBuilder()
.setSpaPage(SpaSearchLandingSpaPage.newBuilder().setDestination(PAGE_NAME))
.build())
assertThat(rawData.title).isEqualTo(ITEM_TITLE)
assertThat(rawData.intentAction).isEqualTo("android.settings.SPA_SEARCH_LANDING")
assertThat(rawData.intentTargetClass)
.isEqualTo(SpaSearchLandingActivity::class.qualifiedName)
assertThat(rawData.className).isEqualTo(pageProvider::class.java.name)
assertThat(rawData.screenTitle).isEqualTo(PAGE_TITLE)
} }
private companion object { private companion object {
const val PAGE_NAME = "PageName" const val PAGE_NAME = "PageName"
const val TITLE = "Title" const val PAGE_TITLE = "Page Title"
const val ITEM_TITLE = "Item Title"
} }
} }