Support search "Mobile data"

- Added SpaSearchRepository to index the SPA search data.
- Added SpaSearchLandingActivity, which can only be called by SI.

Fix: 346776183
Flag: EXEMPT bug fix
Test: manual - search "Mobile data"
Test: unit test
Change-Id: Icaff41fe085edd371fd75bc8101dd52028f90da5
This commit is contained in:
Chaohui Wang
2024-06-27 12:03:37 +08:00
parent bbd5d8885e
commit 50d9e342e8
8 changed files with 247 additions and 4 deletions

View File

@@ -22,11 +22,18 @@ import android.content.Intent
import android.net.Uri
import android.provider.Settings
import com.android.settings.search.SearchIndexableResourcesFactory.createSearchIndexableResources
import com.android.settings.spa.search.SpaSearchRepository
import com.android.settingslib.search.SearchIndexableResources
/** FeatureProvider for the refactored search code. */
open class SearchFeatureProviderImpl : SearchFeatureProvider {
private val lazySearchIndexableResources by lazy { createSearchIndexableResources() }
private val lazySearchIndexableResources by lazy {
createSearchIndexableResources().apply {
for (searchIndexableData in SpaSearchRepository().getSearchIndexableDataList()) {
addIndex(searchIndexableData)
}
}
}
override fun verifyLaunchSearchResultPageCaller(context: Context, callerPackage: String) {
require(callerPackage.isNotEmpty()) {

View File

@@ -46,10 +46,14 @@ import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.settings.R
import com.android.settings.flags.Flags
import com.android.settings.network.SubscriptionInfoListViewModel
import com.android.settings.network.SubscriptionUtil
import com.android.settings.network.telephony.DataSubscriptionRepository
import com.android.settings.network.telephony.MobileDataRepository
import com.android.settings.network.telephony.requireSubscriptionManager
import com.android.settings.spa.network.PrimarySimRepository.PrimarySimInfo
import com.android.settings.spa.search.SearchablePage
import com.android.settings.wifi.WifiPickerTrackerHelper
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPageProvider
@@ -62,6 +66,7 @@ import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category
import com.android.settingslib.spaprivileged.framework.common.broadcastReceiverFlow
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBooleanFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -78,7 +83,7 @@ import kotlinx.coroutines.withContext
/**
* Showing the sim onboarding which is the process flow of sim switching on.
*/
open class NetworkCellularGroupProvider : SettingsPageProvider {
open class NetworkCellularGroupProvider : SettingsPageProvider, SearchablePage {
override val name = fileName
override val metricsCategory = SettingsEnums.MOBILE_NETWORK_LIST
private val owner = createSettingsPage()
@@ -191,8 +196,24 @@ open class NetworkCellularGroupProvider : SettingsPageProvider {
open fun OtherSection(){
// Do nothing
}
override fun getSearchableTitles(context: Context): List<String> {
if (!isPageSearchable(context)) return emptyList()
return buildList {
if (context.requireSubscriptionManager().activeSubscriptionInfoCount > 0) {
add(context.getString(R.string.mobile_data_settings_title))
}
}
}
companion object {
const val fileName = "NetworkCellularGroupProvider"
private fun isPageSearchable(context: Context) =
Flags.isDualSimOnboardingEnabled() &&
SubscriptionUtil.isSimHardwareVisible(context) &&
!com.android.settingslib.Utils.isWifiOnly(context) &&
context.userManager.isAdminUser
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2024 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.settings.spa.search
import android.content.Context
interface SearchablePage {
/** Gets the searchable titles at the current moment. */
fun getSearchableTitles(context: Context): List<String>
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2024 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.settings.spa.search
import android.app.Activity
import android.os.Bundle
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
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
SpaDestination(destination = destination, highlightMenuKey = null)
.startFromExportedActivity(this)
finish()
}
private fun isValidCall() =
PasswordUtils.getCallingAppPackageName(activityToken) ==
featureFactory.searchFeatureProvider.getSettingsIntelligencePkgName(this)
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2024 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.settings.spa.search
import android.content.Context
import android.provider.SearchIndexableResource
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.settingslib.search.Indexable
import com.android.settingslib.search.SearchIndexableData
import com.android.settingslib.search.SearchIndexableRaw
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.common.SpaEnvironment
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
class SpaSearchRepository(
private val spaEnvironment: SpaEnvironment = SpaEnvironmentFactory.instance,
) {
fun getSearchIndexableDataList(): List<SearchIndexableData> {
Log.d(TAG, "getSearchIndexableDataList")
return spaEnvironment.pageProviderRepository.value.getAllProviders().mapNotNull { page ->
if (page is SearchablePage) {
page.createSearchIndexableData(page::getSearchableTitles)
} else null
}
}
companion object {
private const val TAG = "SpaSearchRepository"
@VisibleForTesting
fun SettingsPageProvider.createSearchIndexableData(
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> =
titlesProvider(context).map { title ->
createSearchIndexableRaw(context, title)
}
override fun getNonIndexableKeys(context: Context): List<String> = emptyList()
}
return SearchIndexableData(this::class.java, searchIndexProvider)
}
private fun SettingsPageProvider.createSearchIndexableRaw(context: Context, title: String) =
SearchIndexableRaw(context).apply {
key = name
this.title = title
intentAction = SEARCH_LANDING_ACTION
packageName = context.packageName
className = SpaSearchLandingActivity::class.qualifiedName
}
private const val SEARCH_LANDING_ACTION = "android.settings.SPA_SEARCH_LANDING"
}
}