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
diff --git a/Android.bp b/Android.bp
index 4c472c8..8ca60b9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -82,12 +82,10 @@
         "android.hardware.dumpstate-V1-java",
         "android.hardware.dumpstate-V1.0-java",
         "android.hardware.dumpstate-V1.1-java",
-        "android.view.accessibility.flags-aconfig-java",
         "com_android_server_accessibility_flags_lib",
         "net-utils-framework-common",
         "notification_flags_lib",
         "securebox",
-        "android.os.flags-aconfig-java",
         "//frameworks/libs/systemui:com_android_systemui_shared_flags_lib",
         "WindowManager-Shell-shared-desktopMode",
 
@@ -103,12 +101,9 @@
         "contextualcards",
         "development_settings_flag_lib",
         "factory_reset_flags_lib",
-        "fuelgauge-log-protos-lite",
+        "settings-protos-lite",
         "fuelgauge-protos-lite",
-        "settings-contextual-card-protos-lite",
-        "settings-log-bridge-protos-lite",
         "settings-logtags",
-        "settings-telephony-protos-lite",
         "statslog-settings",
         "telephony_flags_core_java_lib",
         "setupdesign-lottie-loading-layout",
diff --git a/protos/Android.bp b/protos/Android.bp
index 560851a..4ab96a7 100644
--- a/protos/Android.bp
+++ b/protos/Android.bp
@@ -1,44 +1,12 @@
 package {
     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"],
 }
 
-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 {
-    name: "fuelgauge-log-protos-lite",
+    name: "settings-protos-lite",
     proto: {
         type: "lite",
     },
-    srcs: ["fuelgauge_log.proto"],
+    srcs: ["*.proto"],
 }
diff --git a/protos/spa_search_landing.proto b/protos/spa_search_landing.proto
new file mode 100644
index 0000000..4305554
--- /dev/null
+++ b/protos/spa_search_landing.proto
@@ -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;
+}
diff --git a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
index b9a375c..f76bba4 100644
--- a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
+++ b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
@@ -197,6 +197,9 @@
         // Do nothing
     }
 
+    override fun getPageTitleForSearch(context: Context): String =
+        context.getString(R.string.provider_network_settings_title)
+
     override fun getSearchableTitles(context: Context): List<String> {
         if (!isPageSearchable(context)) return emptyList()
         return buildList {
diff --git a/src/com/android/settings/spa/search/SearchablePage.kt b/src/com/android/settings/spa/search/SearchablePage.kt
index 2364514..f4a8795 100644
--- a/src/com/android/settings/spa/search/SearchablePage.kt
+++ b/src/com/android/settings/spa/search/SearchablePage.kt
@@ -20,6 +20,9 @@
 
 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>
 }
diff --git a/src/com/android/settings/spa/search/SpaSearchLandingActivity.kt b/src/com/android/settings/spa/search/SpaSearchLandingActivity.kt
index 8c2bc37..fb2af93 100644
--- a/src/com/android/settings/spa/search/SpaSearchLandingActivity.kt
+++ b/src/com/android/settings/spa/search/SpaSearchLandingActivity.kt
@@ -18,25 +18,45 @@
 
 import android.app.Activity
 import android.os.Bundle
+import android.util.Log
 import com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY
 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.google.protobuf.ByteString
+import com.google.protobuf.InvalidProtocolBufferException
 
 class SpaSearchLandingActivity : Activity() {
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         if (!isValidCall()) return
 
-        val destination = intent.getStringExtra(EXTRA_FRAGMENT_ARG_KEY)
-        if (destination.isNullOrBlank()) 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
+            }
 
-        SpaDestination(destination = destination, highlightMenuKey = null)
-            .startFromExportedActivity(this)
+        if (key.hasSpaPage()) {
+            val destination = key.spaPage.destination
+            if (destination.isNotEmpty()) {
+                SpaDestination(destination = destination, highlightMenuKey = null)
+                    .startFromExportedActivity(this)
+            }
+        }
         finish()
     }
 
     private fun isValidCall() =
         PasswordUtils.getCallingAppPackageName(activityToken) ==
             featureFactory.searchFeatureProvider.getSettingsIntelligencePkgName(this)
+
+    private companion object {
+        private const val TAG = "SpaSearchLandingActivity"
+    }
 }
diff --git a/src/com/android/settings/spa/search/SpaSearchRepository.kt b/src/com/android/settings/spa/search/SpaSearchRepository.kt
index d37c50c..317c620 100644
--- a/src/com/android/settings/spa/search/SpaSearchRepository.kt
+++ b/src/com/android/settings/spa/search/SpaSearchRepository.kt
@@ -20,6 +20,8 @@
 import android.provider.SearchIndexableResource
 import android.util.Log
 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.SearchIndexableData
 import com.android.settingslib.search.SearchIndexableRaw
@@ -34,7 +36,8 @@
         Log.d(TAG, "getSearchIndexableDataList")
         return spaEnvironment.pageProviderRepository.value.getAllProviders().mapNotNull { page ->
             if (page is SearchablePage) {
-                page.createSearchIndexableData(page::getSearchableTitles)
+                page.createSearchIndexableData(
+                    page::getPageTitleForSearch, page::getSearchableTitles)
             } else null
         }
     }
@@ -44,6 +47,7 @@
 
         @VisibleForTesting
         fun SettingsPageProvider.createSearchIndexableData(
+            getPageTitleForSearch: (context: Context) -> String,
             titlesProvider: (context: Context) -> List<String>,
         ): SearchIndexableData {
             val searchIndexProvider =
@@ -61,23 +65,36 @@
                     override fun getDynamicRawDataToIndex(
                         context: Context,
                         enabled: Boolean,
-                    ): List<SearchIndexableRaw> =
-                        titlesProvider(context).map { title ->
-                            createSearchIndexableRaw(context, title)
+                    ): List<SearchIndexableRaw> {
+                        val pageTitle = getPageTitleForSearch(context)
+                        return titlesProvider(context).map { itemTitle ->
+                            createSearchIndexableRaw(context, itemTitle, pageTitle)
                         }
+                    }
 
                     override fun getNonIndexableKeys(context: Context): List<String> = emptyList()
                 }
             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 {
-                key = name
-                this.title = title
+                key =
+                    SpaSearchLandingKey.newBuilder()
+                        .setSpaPage(SpaSearchLandingSpaPage.newBuilder().setDestination(name))
+                        .build()
+                        .toByteString()
+                        .toStringUtf8()
+                title = itemTitle
                 intentAction = SEARCH_LANDING_ACTION
+                intentTargetClass = SpaSearchLandingActivity::class.qualifiedName
                 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"
diff --git a/tests/spa_unit/src/com/android/settings/spa/search/SpaSearchRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/spa/search/SpaSearchRepositoryTest.kt
index 911dfd2..c38f22f 100644
--- a/tests/spa_unit/src/com/android/settings/spa/search/SpaSearchRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/search/SpaSearchRepositoryTest.kt
@@ -18,9 +18,12 @@
 
 import android.content.Context
 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.settingslib.spa.framework.common.SettingsPageProvider
 import com.google.common.truth.Truth.assertThat
+import com.google.protobuf.ByteString
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.kotlin.mock
@@ -35,17 +38,31 @@
                 override val name = PAGE_NAME
             }
 
-        val searchIndexableData = pageProvider.createSearchIndexableData { listOf(TITLE) }
+        val searchIndexableData =
+            pageProvider.createSearchIndexableData({ PAGE_TITLE }) { listOf(ITEM_TITLE) }
         val dynamicRawDataToIndex =
             searchIndexableData.searchIndexProvider.getDynamicRawDataToIndex(mock<Context>(), true)
 
         assertThat(searchIndexableData.targetClass).isEqualTo(pageProvider::class.java)
         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 {
         const val PAGE_NAME = "PageName"
-        const val TITLE = "Title"
+        const val PAGE_TITLE = "Page Title"
+        const val ITEM_TITLE = "Item Title"
     }
 }