Skip to content

Commit

Permalink
Fix search for MMS Message
Browse files Browse the repository at this point in the history
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
  • Loading branch information
wangchaohui committed Jul 30, 2024
1 parent 7477f4e commit 7009c00
Show file tree
Hide file tree
Showing 13 changed files with 593 additions and 147 deletions.
20 changes: 20 additions & 0 deletions protos/spa_search_landing.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,30 @@ package com.android.settings.spa;
message SpaSearchLandingKey {
oneof page {
SpaSearchLandingSpaPage spa_page = 1;
SpaSearchLandingFragment fragment = 2;
}
}

message SpaSearchLandingSpaPage {
/** The destination of SPA page. */
optional string destination = 1;
}

message SpaSearchLandingFragment {
/** The fragment class name. */
optional string fragment_name = 1;

/** The key of the preference to highlight the item. */
optional string preference_key = 2;

/** The arguments passed to the page. */
map<string, BundleValue> arguments = 3;
}

/** A value in an Android Bundle. */
message BundleValue {
oneof value {
/** A 32-bit signed integer value. */
int32 int_value = 1;
}
}
2 changes: 2 additions & 0 deletions res/xml/mobile_network_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,12 @@
android:selectable="false"
settings:searchable="false"/>

<!-- Settings search is handled by MmsMessageSearchItem. -->
<SwitchPreferenceCompat
android:key="mms_message"
android:title="@string/mms_message_title"
android:summary="@string/mms_message_summary"
settings:searchable="false"
settings:controller="com.android.settings.network.telephony.MmsMessagePreferenceController"/>

<SwitchPreferenceCompat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ object EmbeddedDeepLinkUtils {
private const val TAG = "EmbeddedDeepLinkUtils"

@JvmStatic
fun Activity.tryStartMultiPaneDeepLink(
fun Context.tryStartMultiPaneDeepLink(
intent: Intent,
highlightMenuKey: String? = null,
): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,46 +22,38 @@ import android.telephony.TelephonyManager
import android.telephony.data.ApnSetting
import androidx.lifecycle.LifecycleOwner
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.Settings.MobileNetworkActivity.EXTRA_MMS_MESSAGE
import com.android.settings.core.TogglePreferenceController
import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.flow.combine

/**
* Preference controller for "MMS messages"
*/
class MmsMessagePreferenceController @JvmOverloads constructor(
/** Preference controller for "MMS messages" */
class MmsMessagePreferenceController
@JvmOverloads
constructor(
context: Context,
key: String,
private val getDefaultDataSubId: () -> Int = {
SubscriptionManager.getDefaultDataSubscriptionId()
},
) : TelephonyTogglePreferenceController(context, key) {
) : TogglePreferenceController(context, key) {

private lateinit var telephonyManager: TelephonyManager
private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
private var telephonyManager: TelephonyManager =
context.getSystemService(TelephonyManager::class.java)!!

private var preferenceScreen: PreferenceScreen? = null

fun init(subId: Int) {
mSubId = subId
telephonyManager = mContext.getSystemService(TelephonyManager::class.java)!!
.createForSubscriptionId(subId)
this.subId = subId
telephonyManager = telephonyManager.createForSubscriptionId(subId)
}

override fun getAvailabilityStatus(subId: Int) =
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID &&
this::telephonyManager.isInitialized &&
!telephonyManager.isDataEnabled &&
telephonyManager.isApnMetered(ApnSetting.TYPE_MMS) &&
!isFallbackDataEnabled()
) AVAILABLE else CONDITIONALLY_UNAVAILABLE

private fun isFallbackDataEnabled(): Boolean {
val defaultDataSubId = getDefaultDataSubId()
return defaultDataSubId != mSubId &&
telephonyManager.createForSubscriptionId(defaultDataSubId).isDataEnabled &&
telephonyManager.isMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH
)
}
override fun getAvailabilityStatus() =
if (getAvailabilityStatus(telephonyManager, subId, getDefaultDataSubId)) AVAILABLE
else CONDITIONALLY_UNAVAILABLE

override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)
Expand All @@ -70,16 +62,20 @@ class MmsMessagePreferenceController @JvmOverloads constructor(

override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
combine(
MobileDataRepository(mContext).mobileDataEnabledChangedFlow(mSubId),
mContext.subscriptionsChangedFlow(), // Capture isMobileDataPolicyEnabled() changes
) { _, _ -> }.collectLatestWithLifecycle(viewLifecycleOwner) {
preferenceScreen?.let { super.displayPreference(it) }
}
MobileDataRepository(mContext).mobileDataEnabledChangedFlow(subId),
mContext.subscriptionsChangedFlow(), // Capture isMobileDataPolicyEnabled() changes
) { _, _ ->
}
.collectLatestWithLifecycle(viewLifecycleOwner) {
preferenceScreen?.let { super.displayPreference(it) }
}
}

override fun isChecked(): Boolean = telephonyManager.isMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED
)
override fun getSliceHighlightMenuRes() = NO_RES

override fun isChecked(): Boolean =
telephonyManager.isMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED)

override fun setChecked(isChecked: Boolean): Boolean {
telephonyManager.setMobileDataPolicyEnabled(
Expand All @@ -88,4 +84,45 @@ class MmsMessagePreferenceController @JvmOverloads constructor(
)
return true
}

companion object {
private fun getAvailabilityStatus(
telephonyManager: TelephonyManager,
subId: Int,
getDefaultDataSubId: () -> Int,
): Boolean {
return SubscriptionManager.isValidSubscriptionId(subId) &&
!telephonyManager.isDataEnabled &&
telephonyManager.isApnMetered(ApnSetting.TYPE_MMS) &&
!isFallbackDataEnabled(telephonyManager, subId, getDefaultDataSubId())
}

private fun isFallbackDataEnabled(
telephonyManager: TelephonyManager,
subId: Int,
defaultDataSubId: Int,
): Boolean {
return defaultDataSubId != subId &&
telephonyManager.createForSubscriptionId(defaultDataSubId).isDataEnabled &&
telephonyManager.isMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)
}

class MmsMessageSearchItem(
context: Context,
private val getDefaultDataSubId: () -> Int = {
SubscriptionManager.getDefaultDataSubscriptionId()
},
) : MobileNetworkSettingsSearchItem {
private var telephonyManager: TelephonyManager =
context.getSystemService(TelephonyManager::class.java)!!

override val key: String = EXTRA_MMS_MESSAGE
override val title: String = context.getString(R.string.mms_message_title)

override fun isAvailable(subId: Int): Boolean =
getAvailabilityStatus(
telephonyManager.createForSubscriptionId(subId), subId, getDefaultDataSubId)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -467,14 +467,10 @@ public boolean onOptionsItemSelected(MenuItem menuItem) {

public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.mobile_network_settings) {

/** suppress full page if user is not admin */
@Override
protected boolean isPageSearchEnabled(Context context) {
boolean isAirplaneOff = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) == 0;
return isAirplaneOff && SubscriptionUtil.isSimHardwareVisible(context)
&& context.getSystemService(UserManager.class).isAdminUser();
return MobileNetworkSettingsSearchIndex
.isMobileNetworkSettingsSearchable(context);
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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.network.telephony

import android.content.Context
import android.provider.Settings
import android.telephony.SubscriptionInfo
import com.android.settings.R
import com.android.settings.network.SubscriptionUtil
import com.android.settings.network.telephony.MmsMessagePreferenceController.Companion.MmsMessageSearchItem
import com.android.settings.spa.SpaSearchLanding.BundleValue
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingFragment
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey
import com.android.settings.spa.search.SpaSearchRepository.Companion.createSearchIndexableRaw
import com.android.settings.spa.search.SpaSearchRepository.Companion.searchIndexProviderOf
import com.android.settingslib.search.SearchIndexableData
import com.android.settingslib.search.SearchIndexableRaw
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBoolean

class MobileNetworkSettingsSearchIndex(
private val searchItemsFactory: (context: Context) -> List<MobileNetworkSettingsSearchItem> =
::createSearchItems,
) {
interface MobileNetworkSettingsSearchItem {
val key: String

val title: String

fun isAvailable(subId: Int): Boolean
}

fun createSearchIndexableData(): SearchIndexableData {
val searchIndexProvider = searchIndexProviderOf { context ->
if (!isMobileNetworkSettingsSearchable(context)) {
return@searchIndexProviderOf emptyList()
}
val subInfos = context.requireSubscriptionManager().activeSubscriptionInfoList
if (subInfos.isNullOrEmpty()) {
return@searchIndexProviderOf emptyList()
}
searchItemsFactory(context).flatMap { searchItem ->
searchIndexableRawList(context, searchItem, subInfos)
}
}
return SearchIndexableData(MobileNetworkSettings::class.java, searchIndexProvider)
}

private fun searchIndexableRawList(
context: Context,
searchItem: MobileNetworkSettingsSearchItem,
subInfos: List<SubscriptionInfo>
): List<SearchIndexableRaw> =
subInfos
.filter { searchItem.isAvailable(it.subscriptionId) }
.map { subInfo -> searchIndexableRaw(context, searchItem, subInfo) }

private fun searchIndexableRaw(
context: Context,
searchItem: MobileNetworkSettingsSearchItem,
subInfo: SubscriptionInfo,
): SearchIndexableRaw {
val key =
SpaSearchLandingKey.newBuilder()
.setFragment(
SpaSearchLandingFragment.newBuilder()
.setFragmentName(MobileNetworkSettings::class.java.name)
.setPreferenceKey(searchItem.key)
.putArguments(
Settings.EXTRA_SUB_ID,
BundleValue.newBuilder().setIntValue(subInfo.subscriptionId).build()))
.build()
val simsTitle = context.getString(R.string.provider_network_settings_title)
return createSearchIndexableRaw(
context = context,
spaSearchLandingKey = key,
itemTitle = searchItem.title,
indexableClass = MobileNetworkSettings::class.java,
pageTitle = "$simsTitle > ${subInfo.displayName}",
)
}

companion object {
/** suppress full page if user is not admin */
@JvmStatic
fun isMobileNetworkSettingsSearchable(context: Context): Boolean {
val isAirplaneMode by context.settingsGlobalBoolean(Settings.Global.AIRPLANE_MODE_ON)
return SubscriptionUtil.isSimHardwareVisible(context) &&
!isAirplaneMode &&
context.userManager.isAdminUser
}

fun createSearchItems(context: Context): List<MobileNetworkSettingsSearchItem> =
listOf(
MmsMessageSearchItem(context),
)
}
}
12 changes: 6 additions & 6 deletions src/com/android/settings/spa/SpaDestination.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
}
}
Loading

0 comments on commit 7009c00

Please sign in to comment.