Merge 25Q1 (ab/12770256) to aosp-main-future

Bug: 385190204
Merged-In: Iaee6792d1a27be8fa4b443f783a47a3715b6d3a1
Change-Id: I0ac29cecfec526a38cf4a120b8ef704ee7bc01b3
This commit is contained in:
Xin Li
2025-02-26 11:59:26 -08:00
1291 changed files with 58828 additions and 22728 deletions

View File

@@ -0,0 +1,47 @@
/*
* 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
import android.content.Context
import com.android.settings.R
import com.android.settings.flags.Flags
import com.android.settingslib.metadata.ProvidePreferenceScreen
import com.android.settingslib.metadata.preferenceHierarchy
import com.android.settingslib.preference.PreferenceScreenCreator
@ProvidePreferenceScreen
class AdaptiveConnectivityScreen : PreferenceScreenCreator {
override val key
get() = KEY
override val title
get() = R.string.adaptive_connectivity_title
override fun isFlagEnabled(context: Context) = Flags.catalystAdaptiveConnectivity()
override fun fragmentClass() = AdaptiveConnectivitySettings::class.java
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {
+AdaptiveConnectivityTogglePreference()
}
override fun hasCompleteHierarchy() = false
companion object {
const val KEY = "adaptive_connectivity"
}
}

View File

@@ -16,6 +16,10 @@
package com.android.settings.network;
import android.app.settings.SettingsEnums;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -30,8 +34,6 @@ public class AdaptiveConnectivitySettings extends DashboardFragment {
private static final String TAG = "AdaptiveConnectivitySettings";
private static final String KEY_ADAPTIVE_CONNECTIVITY_PREFERENCE = "adaptive_connectivity";
@Override
public int getMetricsCategory() {
return SettingsEnums.ADAPTIVE_CONNECTIVITY_CATEGORY;
@@ -49,4 +51,9 @@ public class AdaptiveConnectivitySettings extends DashboardFragment {
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.adaptive_connectivity_settings);
@Override
public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
return AdaptiveConnectivityScreen.KEY;
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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
import android.content.Context
import android.net.wifi.WifiManager
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED
import com.android.settings.R
import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.datastore.KeyedObservableDelegate
import com.android.settingslib.datastore.SettingsSecureStore
import com.android.settingslib.datastore.SettingsStore
import com.android.settingslib.metadata.MainSwitchPreference
import com.android.settingslib.metadata.ReadWritePermit
import com.android.settingslib.metadata.SensitivityLevel
// LINT.IfChange
class AdaptiveConnectivityTogglePreference :
MainSwitchPreference(KEY, R.string.adaptive_connectivity_main_switch_title) {
override fun storage(context: Context): KeyValueStore =
AdaptiveConnectivityToggleStorage(context, SettingsSecureStore.get(context))
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override val sensitivityLevel
get() = SensitivityLevel.NO_SENSITIVITY
@Suppress("UNCHECKED_CAST")
private class AdaptiveConnectivityToggleStorage(
private val context: Context,
private val settingsStore: SettingsStore,
) : KeyedObservableDelegate<String>(settingsStore), KeyValueStore {
override fun contains(key: String) = settingsStore.contains(KEY)
override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) =
DEFAULT_VALUE as T
override fun <T : Any> getValue(key: String, valueType: Class<T>) =
(settingsStore.getBoolean(key) ?: DEFAULT_VALUE) as T
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
settingsStore.setBoolean(key, value as Boolean)
context.getSystemService(WifiManager::class.java)?.setWifiScoringEnabled(value)
}
}
companion object {
const val KEY = ADAPTIVE_CONNECTIVITY_ENABLED
const val DEFAULT_VALUE = true
}
}
// LINT.ThenChange(AdaptiveConnectivityTogglePreferenceController.java)

View File

@@ -29,6 +29,7 @@ import com.android.settings.widget.SettingsMainSwitchPreferenceController;
* {@link SettingsMainSwitchPreferenceController}
* that controls whether Adaptive connectivity option is enabled.
*/
// LINT.IfChange
public class AdaptiveConnectivityTogglePreferenceController extends
SettingsMainSwitchPreferenceController {
@@ -69,3 +70,4 @@ public class AdaptiveConnectivityTogglePreferenceController extends
return R.string.menu_key_network;
}
}
// LINT.ThenChange(AdaptiveConnectivityTogglePreference.kt)

View File

@@ -0,0 +1,203 @@
/*
* 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
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Looper
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
import android.telephony.PhoneStateListener
import android.telephony.TelephonyManager
import android.util.Log
import androidx.annotation.DrawableRes
import androidx.preference.Preference
import com.android.settings.AirplaneModeEnabler
import com.android.settings.PreferenceRestrictionMixin
import com.android.settings.R
import com.android.settings.Utils
import com.android.settingslib.RestrictedSwitchPreference
import com.android.settingslib.datastore.AbstractKeyedDataObservable
import com.android.settingslib.datastore.DataChangeReason
import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.datastore.SettingsGlobalStore
import com.android.settingslib.datastore.SettingsStore
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceLifecycleContext
import com.android.settingslib.metadata.PreferenceLifecycleProvider
import com.android.settingslib.metadata.ReadWritePermit
import com.android.settingslib.metadata.SensitivityLevel
import com.android.settingslib.metadata.SwitchPreference
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
// LINT.IfChange
class AirplaneModePreference :
SwitchPreference(KEY, R.string.airplane_mode),
PreferenceAvailabilityProvider,
PreferenceLifecycleProvider,
PreferenceRestrictionMixin {
override val icon: Int
@DrawableRes get() = R.drawable.ic_airplanemode_active
override fun isAvailable(context: Context) =
(context.resources.getBoolean(R.bool.config_show_toggle_airplane) &&
!context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context)
override val restrictionKeys
get() = arrayOf(UserManager.DISALLOW_AIRPLANE_MODE)
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
when {
isSatelliteOn(context) || isInEcmMode(context) -> ReadWritePermit.DISALLOW
else -> ReadWritePermit.ALLOW
}
override val sensitivityLevel
get() = SensitivityLevel.HIGH_SENSITIVITY
override fun storage(context: Context): KeyValueStore =
AirplaneModeStorage(context, SettingsGlobalStore.get(context))
@Suppress("DEPRECATION", "MissingPermission", "UNCHECKED_CAST")
private class AirplaneModeStorage(
private val context: Context,
private val settingsStore: SettingsStore,
) : AbstractKeyedDataObservable<String>(), KeyValueStore {
private var phoneStateListener: PhoneStateListener? = null
override fun contains(key: String) =
settingsStore.contains(KEY) &&
context.getSystemService(TelephonyManager::class.java) != null
override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) =
DEFAULT_VALUE as T
override fun <T : Any> getValue(key: String, valueType: Class<T>): T =
(settingsStore.getBoolean(key) ?: DEFAULT_VALUE) as T
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
if (value is Boolean) {
settingsStore.setBoolean(key, value)
val intent = Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED)
intent.putExtra("state", value)
context.sendBroadcastAsUser(intent, UserHandle.ALL)
}
}
override fun onFirstObserverAdded() {
context.getSystemService(TelephonyManager::class.java)?.let {
phoneStateListener =
object : PhoneStateListener(Looper.getMainLooper()) {
@Deprecated("Deprecated in Java")
override fun onRadioPowerStateChanged(state: Int) {
Log.d(TAG, "onRadioPowerStateChanged(), state=$state")
notifyChange(KEY, DataChangeReason.UPDATE)
}
}
it.listen(phoneStateListener, PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED)
}
}
override fun onLastObserverRemoved() {
context
.getSystemService(TelephonyManager::class.java)
?.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
}
}
override fun onCreate(context: PreferenceLifecycleContext) {
context.requirePreference<RestrictedSwitchPreference>(KEY).onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _: Preference, _: Any ->
if (isInEcmMode(context)) {
showEcmDialog(context)
return@OnPreferenceChangeListener false
}
if (isSatelliteOn(context)) {
showSatelliteDialog(context)
return@OnPreferenceChangeListener false
}
return@OnPreferenceChangeListener true
}
}
override fun onActivityResult(
context: PreferenceLifecycleContext,
requestCode: Int,
resultCode: Int,
data: Intent?,
): Boolean {
if (requestCode == REQUEST_CODE_EXIT_ECM && resultCode == Activity.RESULT_OK) {
context.getKeyValueStore(KEY)?.setBoolean(KEY, true)
}
return true
}
private fun isInEcmMode(context: Context) =
AirplaneModeEnabler.isInEcmMode(
context,
context.getSystemService(TelephonyManager::class.java),
)
private fun isSatelliteOn(context: Context): Boolean {
try {
return SatelliteRepository(context)
.requestIsSessionStarted(Executors.newSingleThreadExecutor())
.get(2000, TimeUnit.MILLISECONDS)
} catch (e: Exception) {
Log.e(TAG, "Error to get satellite status : $e")
}
return false
}
private fun showEcmDialog(context: PreferenceLifecycleContext) {
val intent =
Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null)
.setPackage(Utils.PHONE_PACKAGE_NAME)
context.startActivityForResult(intent, REQUEST_CODE_EXIT_ECM, null)
}
private fun showSatelliteDialog(context: PreferenceLifecycleContext) {
val intent =
Intent(context, SatelliteWarningDialogActivity::class.java)
.putExtra(
SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG,
SatelliteWarningDialogActivity.TYPE_IS_AIRPLANE_MODE,
)
context.startActivity(intent)
}
companion object {
const val TAG = "AirplaneModePreference"
const val KEY = Settings.Global.AIRPLANE_MODE_ON
const val DEFAULT_VALUE = false
const val REQUEST_CODE_EXIT_ECM = 1
fun Context.isAirplaneModeOn() = SettingsGlobalStore.get(this).getBoolean(KEY) == true
}
}
// LINT.ThenChange(AirplaneModePreferenceController.java)

View File

@@ -15,8 +15,6 @@
*/
package com.android.settings.network;
import static android.provider.SettingsSlicesContract.KEY_AIRPLANE_MODE;
import static com.android.settings.network.SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG;
import static com.android.settings.network.SatelliteWarningDialogActivity.TYPE_IS_AIRPLANE_MODE;
@@ -52,6 +50,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
// LINT.IfChange
public class AirplaneModePreferenceController extends TogglePreferenceController
implements LifecycleObserver, OnStart, OnResume, OnStop, OnDestroy,
AirplaneModeEnabler.OnAirplaneModeChangedListener {
@@ -94,7 +93,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && isAvailable()) {
if (AirplaneModePreference.KEY.equals(preference.getKey()) && isAvailable()) {
// In ECM mode launch ECM app dialog
if (mAirplaneModeEnabler.isInEcmMode()) {
if (mFragment != null) {
@@ -217,3 +216,4 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
}
}
}
// LINT.ThenChange(AirplaneModePreference.kt)

View File

@@ -88,10 +88,10 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll
} catch (UnsupportedOperationException e) {
Log.i(LOG_TAG, "Null cipher enablement is unsupported, hiding divider: "
+ e.getMessage());
} catch (Exception e) {
} catch (IllegalStateException e) {
Log.e(LOG_TAG,
"Failed isNullCipherAndIntegrityEnabled. Setting availability to "
+ "CONDITIONALLY_UNAVAILABLE. Exception: "
+ "UNSUPPORTED_ON_DEVICE. Exception: "
+ e.getMessage());
}
@@ -104,6 +104,12 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll
} catch (UnsupportedOperationException e) {
Log.i(LOG_TAG, "Cellular security notifications are unsupported, hiding divider: "
+ e.getMessage());
} catch (IllegalStateException e) {
Log.e(LOG_TAG,
"Failed isNullCipherNotificationsEnabled, "
+ "isCellularIdentifierDisclosureNotificationsEnabled. "
+ "Setting availability to UNSUPPORTED_ON_DEVICE. Exception: "
+ e.getMessage());
}
if (isNullCipherDisablementAvailable || areCellSecNotificationsAvailable) {
@@ -119,7 +125,7 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll
return super.handlePreferenceTreeClick(preference);
}
boolean isSafetyCenterSupported = isSafetyCenterSupported();
if (isSafetyCenterSupported) {
if (isSafetyCenterSupported && areNotificationsEnabled()) {
Intent safetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
safetyCenterIntent.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID,
"AndroidCellularNetworkSecuritySources");

View File

@@ -16,7 +16,6 @@
package com.android.settings.network;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -27,13 +26,14 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.system.ResetDashboardFragment;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.system.ResetDashboardFragment;
public class EraseEuiccDataDialogFragment extends InstrumentedDialogFragment implements
DialogInterface.OnClickListener {

View File

@@ -0,0 +1,78 @@
/*
* 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
import android.content.Context
import android.telephony.SubscriptionManager
import com.android.settings.R
import com.android.settings.network.telephony.MobileDataRepository
import com.android.settings.network.telephony.SubscriptionRepository
import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.datastore.NoOpKeyedObservable
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.ReadWritePermit
import com.android.settingslib.metadata.SensitivityLevel
import com.android.settingslib.metadata.SwitchPreference
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
class MobileDataPreference :
SwitchPreference(
KEY,
R.string.mobile_data_settings_title,
R.string.mobile_data_settings_summary,
),
PreferenceAvailabilityProvider {
override fun isAvailable(context: Context) =
SubscriptionRepository(context).getSelectableSubscriptionInfoList().any {
it.simSlotIndex > -1
}
override fun storage(context: Context): KeyValueStore = MobileDataStorage(context)
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override val sensitivityLevel
get() = SensitivityLevel.LOW_SENSITIVITY
@Suppress("UNCHECKED_CAST")
private class MobileDataStorage(private val context: Context) :
NoOpKeyedObservable<String>(), KeyValueStore {
override fun contains(key: String) = key == KEY
override fun <T : Any> getValue(key: String, valueType: Class<T>): T {
val subId = SubscriptionManager.getDefaultDataSubscriptionId()
val flow = MobileDataRepository(context).isMobileDataEnabledFlow(subId)
return runBlocking { flow.first() } as T
}
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
val subId = SubscriptionManager.getDefaultDataSubscriptionId()
MobileDataRepository(context).setMobileDataEnabled(subId, value as Boolean)
}
}
companion object {
const val KEY = "mobile_data"
}
}

View File

@@ -92,4 +92,6 @@ class MobileNetworkListFragment : DashboardFragment() {
simRepositoryFactory(context).canEnterMobileNetworkPage()
}
}
override fun getPreferenceScreenBindingKey(context: Context) = MobileNetworkListScreen.KEY
}

View File

@@ -0,0 +1,168 @@
/*
* 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
import android.content.Context
import android.os.UserManager
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener
import androidx.preference.Preference
import androidx.preference.Preference.OnPreferenceClickListener
import com.android.settings.PreferenceRestrictionMixin
import com.android.settings.R
import com.android.settings.flags.Flags
import com.android.settings.network.AirplaneModePreference.Companion.isAirplaneModeOn
import com.android.settings.network.SubscriptionUtil.getUniqueSubscriptionDisplayName
import com.android.settings.network.telephony.SimRepository
import com.android.settings.network.telephony.SubscriptionRepository
import com.android.settings.network.telephony.euicc.EuiccRepository
import com.android.settings.spa.network.getAddSimIntent
import com.android.settings.spa.network.startAddSimFlow
import com.android.settingslib.RestrictedPreference
import com.android.settingslib.datastore.HandlerExecutor
import com.android.settingslib.datastore.KeyedObserver
import com.android.settingslib.datastore.SettingsGlobalStore
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceLifecycleContext
import com.android.settingslib.metadata.PreferenceLifecycleProvider
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.metadata.ProvidePreferenceScreen
import com.android.settingslib.metadata.preferenceHierarchy
import com.android.settingslib.preference.PreferenceScreenBinding
import com.android.settingslib.preference.PreferenceScreenCreator
@ProvidePreferenceScreen
class MobileNetworkListScreen :
PreferenceScreenCreator,
PreferenceScreenBinding,
PreferenceAvailabilityProvider,
PreferenceSummaryProvider,
PreferenceLifecycleProvider,
PreferenceRestrictionMixin,
OnPreferenceClickListener {
private var airplaneModeObserver: KeyedObserver<String>? = null
private var subscriptionInfoList: List<SubscriptionInfo>? = null
private var onSubscriptionsChangedListener: OnSubscriptionsChangedListener? = null
override val key: String
get() = KEY
override val title: Int
get() = R.string.provider_network_settings_title
override val icon: Int
get() = R.drawable.ic_sim_card
override val keywords: Int
get() = R.string.keywords_more_mobile_networks
override fun intent(context: Context) = getAddSimIntent()
override fun getSummary(context: Context): CharSequence? {
val list = getSelectableSubscriptionInfoList(context)
return when {
list.isNotEmpty() ->
list
.map { getUniqueSubscriptionDisplayName(it, context).toString() }
.distinct()
.joinToString(", ")
EuiccRepository(context).showEuiccSettings() ->
context.getString(R.string.mobile_network_summary_add_a_network)
else -> null
}
}
override fun isAvailable(context: Context) =
SimRepository(context).showMobileNetworkPageEntrance()
override fun isEnabled(context: Context) =
super<PreferenceRestrictionMixin>.isEnabled(context) &&
!context.isAirplaneModeOn() &&
(getSelectableSubscriptionInfoList(context).isNotEmpty() ||
EuiccRepository(context).showEuiccSettings())
private fun getSelectableSubscriptionInfoList(context: Context): List<SubscriptionInfo> =
subscriptionInfoList
?: SubscriptionRepository(context).getSelectableSubscriptionInfoList().also {
subscriptionInfoList = it
}
override val restrictionKeys
get() = arrayOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)
override val useAdminDisabledSummary
get() = true
override fun createWidget(context: Context) = RestrictedPreference(context)
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
preference.onPreferenceClickListener = this
}
override fun onPreferenceClick(preference: Preference): Boolean {
val summary = preference.summary ?: return true // no-op
val context = preference.context
if (summary == context.getString(R.string.mobile_network_summary_add_a_network)) {
startAddSimFlow(context) // start intent
return true
}
return false // start fragment
}
override fun onCreate(context: PreferenceLifecycleContext) {
val executor = HandlerExecutor.main
val observer = KeyedObserver<String> { _, _ -> context.notifyPreferenceChange(KEY) }
airplaneModeObserver = observer
SettingsGlobalStore.get(context).addObserver(AirplaneModePreference.KEY, observer, executor)
context.getSystemService(SubscriptionManager::class.java)?.let {
val listener =
object : OnSubscriptionsChangedListener() {
override fun onSubscriptionsChanged() {
subscriptionInfoList = null // invalid cache
context.notifyPreferenceChange(KEY)
}
}
it.addOnSubscriptionsChangedListener(executor, listener)
onSubscriptionsChangedListener = listener
}
}
override fun onDestroy(context: PreferenceLifecycleContext) {
airplaneModeObserver?.let {
SettingsGlobalStore.get(context).removeObserver(AirplaneModePreference.KEY, it)
}
context.getSystemService(SubscriptionManager::class.java)?.apply {
onSubscriptionsChangedListener?.let { removeOnSubscriptionsChangedListener(it) }
}
}
override fun isFlagEnabled(context: Context) = Flags.catalystMobileNetworkList()
override fun hasCompleteHierarchy() = false
override fun fragmentClass() = MobileNetworkListFragment::class.java
override fun getPreferenceHierarchy(context: Context) =
preferenceHierarchy(this) { +MobileDataPreference() }
companion object {
const val KEY = "mobile_network_list"
}
}

View File

@@ -41,6 +41,7 @@ import kotlinx.coroutines.flow.Flow
* - Has subscriptions: click action takes you to a page listing the subscriptions, and the summary
* text gives the count of SIMs
*/
// LINT.IfChange
class MobileNetworkSummaryController
@JvmOverloads
constructor(
@@ -119,3 +120,4 @@ constructor(
)
}
}
// LINT.ThenChange(MobileNetworkListScreen.kt)

View File

@@ -19,6 +19,7 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.R;
@@ -58,7 +59,9 @@ public class NetworkDashboardFragment extends DashboardFragment implements
public void onAttach(Context context) {
super.onAttach(context);
use(AirplaneModePreferenceController.class).setFragment(this);
if (isCatalystEnabled()) {
use(AirplaneModePreferenceController.class).setFragment(this);
}
use(NetworkProviderCallsSmsController.class).init(this);
}
@@ -101,8 +104,10 @@ public class NetworkDashboardFragment extends DashboardFragment implements
switch (requestCode) {
case AirplaneModePreferenceController.REQUEST_CODE_EXIT_ECM:
use(AirplaneModePreferenceController.class)
.onActivityResult(requestCode, resultCode, data);
if (isCatalystEnabled()) {
use(AirplaneModePreferenceController.class)
.onActivityResult(requestCode, resultCode, data);
}
break;
}
}
@@ -115,4 +120,9 @@ public class NetworkDashboardFragment extends DashboardFragment implements
return buildPreferenceControllers(context, null /* lifecycle */);
}
};
@Override
public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
return NetworkDashboardScreen.KEY;
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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
import android.content.Context
import com.android.settings.R
import com.android.settings.datausage.DataSaverScreen
import com.android.settings.flags.Flags
import com.android.settingslib.metadata.PreferenceIconProvider
import com.android.settingslib.metadata.ProvidePreferenceScreen
import com.android.settingslib.metadata.preferenceHierarchy
import com.android.settingslib.preference.PreferenceScreenCreator
@ProvidePreferenceScreen
class NetworkDashboardScreen : PreferenceScreenCreator, PreferenceIconProvider {
override val key: String
get() = KEY
override val title: Int
get() = R.string.network_dashboard_title
override fun getIcon(context: Context) =
when {
Flags.homepageRevamp() -> R.drawable.ic_settings_wireless_filled
else -> R.drawable.ic_settings_wireless
}
override fun isFlagEnabled(context: Context) = Flags.catalystNetworkProviderAndInternetScreen()
override fun hasCompleteHierarchy() = false
override fun fragmentClass() = NetworkDashboardFragment::class.java
override fun getPreferenceHierarchy(context: Context) =
preferenceHierarchy(this) {
+MobileNetworkListScreen.KEY order -15
+AirplaneModePreference() order -5
+DataSaverScreen.KEY order 10
}
companion object {
const val KEY = "network_provider_and_internet_screen"
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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
import android.content.Context
import android.os.UserManager
import com.android.settings.PreferenceRestrictionMixin
import com.android.settings.R
import com.android.settings.flags.Flags
import com.android.settings.wifi.WifiSwitchPreference
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.ProvidePreferenceScreen
import com.android.settingslib.metadata.preferenceHierarchy
import com.android.settingslib.preference.PreferenceScreenCreator
@ProvidePreferenceScreen
class NetworkProviderScreen :
PreferenceScreenCreator, PreferenceAvailabilityProvider, PreferenceRestrictionMixin {
override val key: String
get() = KEY
override val title: Int
get() = R.string.provider_internet_settings
override val icon: Int
get() = R.drawable.ic_settings_wireless
override val keywords: Int
get() = R.string.keywords_internet
override fun isAvailable(context: Context) =
context.resources.getBoolean(R.bool.config_show_internet_settings)
override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context)
override val restrictionKeys
get() = arrayOf(UserManager.DISALLOW_CONFIG_WIFI)
override fun isFlagEnabled(context: Context) = Flags.catalystInternetSettings()
override fun hasCompleteHierarchy() = false
override fun fragmentClass() = NetworkProviderSettings::class.java
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {
+WifiSwitchPreference()
}
companion object {
const val KEY = "internet_settings"
}
}

View File

@@ -64,8 +64,8 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.AirplaneModeEnabler;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.datausage.DataUsagePreference;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.location.WifiScanningFragment;
@@ -104,7 +104,7 @@ import java.util.Optional;
* UI for Mobile network and Wi-Fi network settings.
*/
@SearchIndexable
public class NetworkProviderSettings extends RestrictedSettingsFragment
public class NetworkProviderSettings extends RestrictedDashboardFragment
implements Indexable, WifiPickerTracker.WifiPickerTrackerCallback,
WifiDialog2.WifiDialog2Listener, DialogInterface.OnDismissListener,
AirplaneModeEnabler.OnAirplaneModeChangedListener, InternetUpdater.InternetChangeListener {
@@ -356,9 +356,17 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
mIsGuest = userManager.isGuestUser();
}
private void addPreferences() {
addPreferencesFromResource(R.xml.network_provider_settings);
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.network_provider_settings;
}
private void addPreferences() {
mAirplaneModeMsgPreference = findPreference(PREF_KEY_AIRPLANE_MODE_MSG);
updateAirplaneModeMsgPreference(mAirplaneModeEnabler.isAirplaneModeOn() /* visible */);
mConnectedWifiEntryPreferenceCategory = findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS);
@@ -421,6 +429,10 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
}
private void addWifiSwitchPreferenceController() {
if (isCatalystEnabled()) {
Log.i(TAG, "WifiSwitchPreferenceController bypassed since Catalyst is enabled!");
return;
}
if (!hasWifiManager()) return;
if (mWifiSwitchPreferenceController == null) {
mWifiSwitchPreferenceController =
@@ -1500,4 +1512,9 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
return android.R.attr.colorControlNormal;
}
}
@Override
public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
return NetworkProviderScreen.KEY;
}
}

View File

@@ -19,6 +19,7 @@ package com.android.settings.network
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.UserHandle;
import android.provider.Settings
import android.telephony.SubscriptionManager
import android.util.Log
@@ -55,6 +56,7 @@ import com.android.settings.R
import com.android.settings.SidecarFragment
import com.android.settings.network.telephony.SimRepository
import com.android.settings.network.telephony.SubscriptionActionDialogActivity
import com.android.settings.network.telephony.SubscriptionRepository
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity
import com.android.settings.network.telephony.requireSubscriptionManager
import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
@@ -78,8 +80,10 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull
class SimOnboardingActivity : SpaBaseDialogActivity() {
lateinit var scope: CoroutineScope
@@ -105,6 +109,12 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
}
var targetSubId = intent.getIntExtra(SUB_ID,SubscriptionManager.INVALID_SUBSCRIPTION_ID)
if (targetSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
targetSubId = intent.getIntExtra(
Settings.EXTRA_SUB_ID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID
)
}
initServiceData(this, targetSubId, callbackListener)
if (!onboardingService.isUsableTargetSubscriptionId) {
Log.e(TAG, "The subscription id is not usable.")
@@ -489,31 +499,25 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
}
}
suspend fun checkSimIsReadyAndGoNext() {
private suspend fun checkSimIsReadyAndGoNext() {
withContext(Dispatchers.Default) {
val isEnabled = context.requireSubscriptionManager()
.isSubscriptionEnabled(onboardingService.targetSubId)
if (!isEnabled) {
val latch = CountDownLatch(1)
val receiver = CarrierConfigChangedReceiver(latch)
try {
val waitingTimeMillis =
Settings.Global.getLong(
context.contentResolver,
Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS,
UiccSlotUtil.DEFAULT_WAIT_AFTER_SWITCH_TIMEOUT_MILLIS
)
receiver.registerOn(context)
Log.d(TAG, "Start waiting, waitingTime is $waitingTimeMillis")
latch.await(waitingTimeMillis, TimeUnit.MILLISECONDS)
} catch (e: InterruptedException) {
Thread.currentThread().interrupt()
Log.e(TAG, "Failed switching to physical slot.", e)
} finally {
context.unregisterReceiver(receiver)
}
}
Log.d(TAG, "Sim is ready then go to next")
val waitingTimeMillis =
Settings.Global.getLong(
context.contentResolver,
Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS,
UiccSlotUtil.DEFAULT_WAIT_AFTER_SWITCH_TIMEOUT_MILLIS,
)
Log.d(TAG, "Start waiting, waitingTime is $waitingTimeMillis")
val isTimeout =
withTimeoutOrNull(waitingTimeMillis) {
SubscriptionRepository(context)
.isSubscriptionEnabledFlow(onboardingService.targetSubId)
.firstOrNull { it }
} == null
Log.d(
TAG,
if (isTimeout) "Sim is not ready after timeout" else "Sim is ready then go to next",
)
callbackListener(CallbackType.CALLBACK_SETUP_NAME)
}
}
@@ -588,7 +592,7 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
}
context.startActivity(intent)
context.startActivityAsUser(intent, UserHandle.CURRENT)
}
var onboardingService:SimOnboardingService = SimOnboardingService()
@@ -610,4 +614,4 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
CALLBACK_FINISH(5)
}
}
}
}

View File

@@ -74,8 +74,11 @@ class SimOnboardingService {
}
var isEsimProfileEnabled: Boolean = false
get() {
activeSubInfoList.stream().anyMatch { it.isEmbedded }
return false
return activeSubInfoList.stream().anyMatch { it.isEmbedded }
}
var isRemovableSimProfileEnabled: Boolean = false
get() {
return activeSubInfoList.stream().anyMatch { !it.isEmbedded }
}
var doesTargetSimActive = false
get() {
@@ -288,8 +291,8 @@ class SimOnboardingService {
Log.d(TAG, "Hardware does not support DSDS.")
return false
}
val isActiveSim = activeSubInfoList.isNotEmpty()
if (isMultipleEnabledProfilesSupported && isActiveSim) {
val anyActiveSim = activeSubInfoList.isNotEmpty()
if (isMultipleEnabledProfilesSupported && anyActiveSim) {
Log.d(TAG,
"Device supports MEP and eSIM operation and eSIM profile is enabled."
+ " DSDS condition satisfied."
@@ -297,15 +300,13 @@ class SimOnboardingService {
return true
}
if (doesTargetSimHaveEsimOperation) {
if (UiccSlotRepository(telephonyManager).anyRemovablePhysicalSimEnabled()) {
Log.d(
TAG,
"eSIM operation and removable PSIM is enabled. DSDS condition satisfied."
)
return true
}
} else if (isEsimProfileEnabled) {
if (doesTargetSimHaveEsimOperation && isRemovableSimProfileEnabled) {
Log.d(TAG,
"eSIM operation and removable PSIM is enabled. DSDS condition satisfied."
)
return true
}
if (!doesTargetSimHaveEsimOperation && isEsimProfileEnabled) {
Log.d(TAG,
"Removable SIM operation and eSIM profile is enabled. DSDS condition"
+ " satisfied."

View File

@@ -35,19 +35,35 @@ import com.android.settingslib.TetherUtil
import com.android.settingslib.Utils
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class TetherPreferenceController(context: Context, key: String) :
BasePreferenceController(context, key) {
class TetherPreferenceController(
context: Context,
key: String,
private val tetheredRepository: TetheredRepository = TetheredRepository(context),
) : BasePreferenceController(context, key) {
private val tetheredRepository = TetheredRepository(context)
private val tetheringManager = mContext.getSystemService(TetheringManager::class.java)!!
private var preference: Preference? = null
override fun getAvailabilityStatus() =
if (TetherUtil.isTetherAvailable(mContext)) AVAILABLE else CONDITIONALLY_UNAVAILABLE
private val isTetherAvailableFlow =
flow { emit(TetherUtil.isTetherAvailable(mContext)) }
.distinctUntilChanged()
.conflate()
.flowOn(Dispatchers.Default)
/**
* Always returns available here to avoid ANR.
* - Actual UI visibility is handled in [onViewCreated].
* - Search visibility is handled in [updateNonIndexableKeys].
*/
override fun getAvailabilityStatus() = AVAILABLE
override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)
@@ -55,6 +71,9 @@ class TetherPreferenceController(context: Context, key: String) :
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
isTetherAvailableFlow.collectLatestWithLifecycle(viewLifecycleOwner) {
preference?.isVisible = it
}
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
getTitleResId()?.let { preference?.setTitle(it) }
@@ -84,6 +103,12 @@ class TetherPreferenceController(context: Context, key: String) :
}
}
override fun updateNonIndexableKeys(keys: MutableList<String>) {
if (!TetherUtil.isTetherAvailable(mContext)) {
keys += preferenceKey
}
}
companion object {
@JvmStatic
fun isTetherConfigDisallowed(context: Context?): Boolean =

View File

@@ -26,7 +26,6 @@ import android.net.VpnManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.SettingsSlicesContract;
import android.security.Credentials;
import android.security.LegacyVpnProfileStore;
import android.util.Log;
@@ -39,7 +38,6 @@ import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.vpn2.VpnInfoPreference;
import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -50,7 +48,6 @@ import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.utils.ThreadUtils;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class VpnPreferenceController extends AbstractPreferenceController
@@ -87,7 +84,7 @@ public class VpnPreferenceController extends AbstractPreferenceController
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
// Manually set dependencies for Wifi when not toggleable.
if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIFI)) {
preference.setDependency(SettingsSlicesContract.KEY_AIRPLANE_MODE);
preference.setDependency(Settings.Global.AIRPLANE_MODE_ON);
}
return preference;
}

View File

@@ -38,6 +38,7 @@ import com.google.common.annotations.VisibleForTesting;
/**
* This controller helps to manage the state of wifi switch preference.
*/
// LINT.IfChange
public class WifiSwitchPreferenceController extends AbstractPreferenceController implements
LifecycleObserver {
@@ -125,3 +126,4 @@ public class WifiSwitchPreferenceController extends AbstractPreferenceController
return wifiManager.isWifiEnabled();
}
}
// LINT.ThenChange(WifiSwitchPreference.kt)

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,6 @@ import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -34,7 +33,6 @@ import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.data.ApnSetting;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -51,7 +49,6 @@ import androidx.preference.PreferenceGroup;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.flags.Flags;
import com.android.settings.network.telephony.SubscriptionRepository;
import com.android.settings.spa.SpaActivity;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -59,6 +56,7 @@ import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import kotlin.Unit;
import java.util.ArrayList;
import java.util.List;
/** Handle each different apn setting. */
public class ApnSettings extends RestrictedSettingsFragment
@@ -68,16 +66,12 @@ public class ApnSettings extends RestrictedSettingsFragment
public static final String APN_ID = "apn_id";
public static final String APN_LIST = "apn_list";
public static final String SUB_ID = "sub_id";
public static final String MVNO_TYPE = "mvno_type";
public static final String MVNO_MATCH_DATA = "mvno_match_data";
private static final String[] CARRIERS_PROJECTION = new String[] {
Telephony.Carriers._ID,
Telephony.Carriers.NAME,
Telephony.Carriers.APN,
Telephony.Carriers.TYPE,
Telephony.Carriers.MVNO_TYPE,
Telephony.Carriers.MVNO_MATCH_DATA,
Telephony.Carriers.EDITED_STATUS,
};
@@ -85,9 +79,7 @@ public class ApnSettings extends RestrictedSettingsFragment
private static final int NAME_INDEX = 1;
private static final int APN_INDEX = 2;
private static final int TYPES_INDEX = 3;
private static final int MVNO_TYPE_INDEX = 4;
private static final int MVNO_MATCH_DATA_INDEX = 5;
private static final int EDITED_INDEX = 6;
private static final int EDITED_INDEX = 4;
private static final int MENU_NEW = Menu.FIRST;
private static final int MENU_RESTORE = Menu.FIRST + 1;
@@ -101,8 +93,6 @@ public class ApnSettings extends RestrictedSettingsFragment
private PreferredApnRepository mPreferredApnRepository;
@Nullable
private String mPreferredApnKey;
private String mMvnoType;
private String mMvnoMatchData;
private boolean mUnavailable;
@@ -135,10 +125,9 @@ public class ApnSettings extends RestrictedSettingsFragment
mHideImsApn = b.getBoolean(CarrierConfigManager.KEY_HIDE_IMS_APN_BOOL);
mAllowAddingApns = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
if (mAllowAddingApns) {
final String[] readOnlyApnTypes = b.getStringArray(
CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
final List<String> readOnlyApnTypes = ApnTypes.getReadOnlyApnTypes(b);
// if no apn type can be edited, do not allow adding APNs
if (ApnEditor.hasAllApns(readOnlyApnTypes)) {
if (ApnTypes.hasAllApnTypes(readOnlyApnTypes)) {
Log.d(TAG, "not allowing adding APN because all APN types are read only");
mAllowAddingApns = false;
}
@@ -242,8 +231,6 @@ public class ApnSettings extends RestrictedSettingsFragment
final String key = cursor.getString(ID_INDEX);
final String type = cursor.getString(TYPES_INDEX);
final int edited = cursor.getInt(EDITED_INDEX);
mMvnoType = cursor.getString(MVNO_TYPE_INDEX);
mMvnoMatchData = cursor.getString(MVNO_MATCH_DATA_INDEX);
final ApnPreference pref = new ApnPreference(getPrefContext());
@@ -311,20 +298,9 @@ public class ApnSettings extends RestrictedSettingsFragment
}
private void addNewApn() {
if (Flags.newApnPageEnabled()) {
String route = ApnEditPageProvider.INSTANCE.getRoute(
INSERT_URL, Telephony.Carriers.CONTENT_URI, mSubId);
SpaActivity.startSpaActivity(getContext(), route);
} else {
final Intent intent = new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI);
intent.putExtra(SUB_ID, mSubId);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (!TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData)) {
intent.putExtra(MVNO_TYPE, mMvnoType);
intent.putExtra(MVNO_MATCH_DATA, mMvnoMatchData);
}
startActivity(intent);
}
String route = ApnEditPageProvider.INSTANCE.getRoute(
INSERT_URL, Telephony.Carriers.CONTENT_URI, mSubId);
SpaActivity.startSpaActivity(getContext(), route);
}
@Override

View File

@@ -25,6 +25,7 @@ import android.telephony.CarrierConfigManager
import android.util.Log
import com.android.settings.R
import com.android.settings.network.apn.ApnTypes.getPreSelectedApnType
import com.android.settings.network.apn.ApnTypes.getReadOnlyApnTypes
private const val TAG = "ApnStatus"
@@ -204,9 +205,7 @@ fun getCarrierCustomizedConfig(
CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL
)
val customizedConfig = CustomizedConfig(
readOnlyApnTypes = b.getStringArray(
CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY
)?.toList() ?: emptyList(),
readOnlyApnTypes = b.getReadOnlyApnTypes(),
readOnlyApnFields = b.getStringArray(
CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY
)?.toList() ?: emptyList(),

View File

@@ -17,6 +17,8 @@
package com.android.settings.network.apn
import android.content.Context
import android.os.PersistableBundle
import android.telephony.CarrierConfigManager
import android.telephony.data.ApnSetting
import android.util.Log
import android.widget.Toast
@@ -45,13 +47,13 @@ object ApnTypes {
ApnSetting.TYPE_VSIM_STRING,
ApnSetting.TYPE_BIP_STRING,
ApnSetting.TYPE_ENTERPRISE_STRING,
ApnSetting.TYPE_OEM_PAID_STRING,
ApnSetting.TYPE_OEM_PRIVATE_STRING,
)
private fun splitToList(apnType: String): List<String> {
val types = apnType.split(',').map { it.trim().toLowerCase(Locale.current) }
if (ApnSetting.TYPE_ALL_STRING in types || APN_TYPES.all { it in types }) {
return listOf(ApnSetting.TYPE_ALL_STRING)
}
if (hasAllApnTypes(types)) return listOf(ApnSetting.TYPE_ALL_STRING)
return APN_TYPES.filter { it in types }
}
@@ -130,4 +132,32 @@ object ApnTypes {
private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) =
if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList()
else PreSelectedTypes.filterNot { it in readOnlyApnTypes }
/** Array of APN types that are never user-editable */
private val ALWAYS_READ_ONLY_APN_TYPES =
arrayOf(ApnSetting.TYPE_OEM_PAID_STRING, ApnSetting.TYPE_OEM_PRIVATE_STRING)
/**
* Fetch complete list of read only APN types.
*
* The list primarily comes from carrier config, but is also supplied by APN types which are
* always read only.
*/
@JvmStatic
fun PersistableBundle.getReadOnlyApnTypes(): List<String> {
val carrierReadOnlyApnTypes =
getStringArray(CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY)?.toList()
?: emptyList()
return carrierReadOnlyApnTypes + ALWAYS_READ_ONLY_APN_TYPES
}
/**
* Check if passed in array of APN types indicates all APN types
*
* @param apnTypes array of APN types. "*" indicates all types.
* @return true if all apn types are included in the array, false otherwise
*/
@JvmStatic
fun hasAllApnTypes(apnTypes: List<String>): Boolean =
ApnSetting.TYPE_ALL_STRING in apnTypes || APN_TYPES.all { it in apnTypes }
}

View File

@@ -224,7 +224,10 @@ class CarrierConfigRepository(private val context: Context) {
}
private val BooleanKeysWhichNotFollowingsNamingConventions =
listOf(CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
listOf(
CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS,
CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL,
)
private fun checkBooleanKey(key: String) {
check(key.endsWith("_bool") || key in BooleanKeysWhichNotFollowingsNamingConventions) {

View File

@@ -16,29 +16,31 @@
package com.android.settings.network.telephony;
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.getNetworkModePreferenceType;
import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.setAllowedNetworkTypes;
import static com.android.settings.network.telephony.mode.NetworkModes.addNrToLteNetworkMode;
import static com.android.settings.network.telephony.mode.NetworkModes.reduceNrToLteNetworkMode;
import android.content.Context;
import android.content.res.Resources;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.RadioAccessFamily;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteModemStateCallback;
import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.ListPreference;
import androidx.preference.ListPreferenceDialogFragmentCompat;
import androidx.preference.Preference;
@@ -52,7 +54,6 @@ import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.SubscriptionsChangeListener;
import com.android.settings.network.telephony.NetworkModeChoicesProto.EnabledNetworks;
import com.android.settings.network.telephony.NetworkModeChoicesProto.UiOptions;
import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants;
import java.util.ArrayList;
import java.util.Arrays;
@@ -65,7 +66,7 @@ import java.util.stream.Stream;
*/
public class EnabledNetworkModePreferenceController extends
BasePreferenceController implements
ListPreference.OnPreferenceChangeListener, LifecycleObserver,
ListPreference.OnPreferenceChangeListener, DefaultLifecycleObserver,
SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
private static final String LOG_TAG = "EnabledNetworkMode";
@@ -81,6 +82,43 @@ public class EnabledNetworkModePreferenceController extends
private PhoneCallStateTelephonyCallback mTelephonyCallback;
private FragmentManager mFragmentManager;
private LifecycleOwner mViewLifecycleOwner;
private SatelliteManager mSatelliteManager;
private boolean mIsSatelliteSessionStarted = false;
private boolean mIsCurrentSubscriptionForSatellite = false;
@VisibleForTesting
final SelectedNbIotSatelliteSubscriptionCallback mSelectedNbIotSatelliteSubscriptionCallback =
new SelectedNbIotSatelliteSubscriptionCallback() {
@Override
public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
mIsCurrentSubscriptionForSatellite = selectedSubId == mSubId;
updatePreference();
}
};
@VisibleForTesting
final SatelliteModemStateCallback mSatelliteModemStateCallback =
new SatelliteModemStateCallback() {
@Override
public void onSatelliteModemStateChanged(int state) {
switch (state) {
case SatelliteManager.SATELLITE_MODEM_STATE_OFF:
case SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE:
case SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN:
if (mIsSatelliteSessionStarted) {
mIsSatelliteSessionStarted = false;
updatePreference();
}
break;
default:
if (!mIsSatelliteSessionStarted) {
mIsSatelliteSessionStarted = true;
updatePreference();
}
break;
}
}
};
public EnabledNetworkModePreferenceController(Context context, String key) {
super(context, key);
@@ -88,6 +126,7 @@ public class EnabledNetworkModePreferenceController extends
if (mTelephonyCallback == null) {
mTelephonyCallback = new PhoneCallStateTelephonyCallback();
}
mSatelliteManager = context.getSystemService(SatelliteManager.class);
}
@Override
@@ -101,8 +140,22 @@ public class EnabledNetworkModePreferenceController extends
return mCallState == TelephonyManager.CALL_STATE_IDLE;
}
@OnLifecycleEvent(ON_START)
public void onStart() {
@Override
public void onStart(@NonNull LifecycleOwner owner) {
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
if (mSatelliteManager != null) {
try {
mSatelliteManager.registerForModemStateChanged(
mContext.getMainExecutor(), mSatelliteModemStateCallback);
mSatelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
mContext.getMainExecutor(),
mSelectedNbIotSatelliteSubscriptionCallback);
} catch (IllegalStateException e) {
Log.w(LOG_TAG, "IllegalStateException : " + e);
}
}
}
mSubscriptionsListener.start();
if (mAllowedNetworkTypesListener == null || mTelephonyCallback == null) {
return;
@@ -111,9 +164,21 @@ public class EnabledNetworkModePreferenceController extends
mTelephonyCallback.register(mTelephonyManager, mSubId);
}
@OnLifecycleEvent(ON_STOP)
public void onStop() {
@Override
public void onStop(@NonNull LifecycleOwner owner) {
mSubscriptionsListener.stop();
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
if (mSatelliteManager != null) {
try {
mSatelliteManager.unregisterForModemStateChanged(mSatelliteModemStateCallback);
mSatelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
mSelectedNbIotSatelliteSubscriptionCallback);
} catch (IllegalStateException e) {
Log.w(LOG_TAG, "IllegalStateException : " + e);
}
}
}
if (mAllowedNetworkTypesListener == null || mTelephonyCallback == null) {
return;
}
@@ -145,7 +210,7 @@ public class EnabledNetworkModePreferenceController extends
listPreference.setEntryValues(mBuilder.getEntryValues());
listPreference.setValue(Integer.toString(mBuilder.getSelectedEntryValue()));
listPreference.setSummary(mBuilder.getSummary());
boolean listPreferenceEnabled = isCallStateIdle();
boolean listPreferenceEnabled = isPreferenceShallEnabled();
listPreference.setEnabled(listPreferenceEnabled);
if (!listPreferenceEnabled) {
// If dialog is already opened when ListPreference disabled, dismiss them.
@@ -201,6 +266,14 @@ public class EnabledNetworkModePreferenceController extends
}
}
private boolean isPreferenceShallEnabled() {
Log.d(LOG_TAG, "isPreferenceShallEnabled, mIsSatelliteSessionStarted : "
+ mIsSatelliteSessionStarted + " / mIsCurrentSubscriptionForSatellite : "
+ mIsCurrentSubscriptionForSatellite);
return isCallStateIdle()
&& !(mIsSatelliteSessionStarted && mIsCurrentSubscriptionForSatellite);
}
private final class PreferenceEntriesBuilder {
private CarrierConfigCache mCarrierConfigCache;
private Context mContext;
@@ -252,7 +325,7 @@ public class EnabledNetworkModePreferenceController extends
if (flagHidePrefer3gItem) {
mDisplay3gOptions = carrierConfig.getBoolean(
CarrierConfigManager.KEY_PREFER_3G_VISIBILITY_BOOL);
CarrierConfigManager.KEY_PREFER_3G_VISIBILITY_BOOL);
} else {
mDisplay3gOptions = getResourcesForSubId().getBoolean(
R.bool.config_display_network_mode_3g_option);
@@ -428,14 +501,14 @@ public class EnabledNetworkModePreferenceController extends
addLteEntry(entryValuesInt[entryIndex]);
break;
case add5gEntry:
add5gEntry(addNrToLteNetworkType(entryValuesInt[entryIndex]));
add5gEntry(addNrToLteNetworkMode(entryValuesInt[entryIndex]));
break;
case add5gAnd4gEntry:
add5gEntry(addNrToLteNetworkType(entryValuesInt[entryIndex]));
add5gEntry(addNrToLteNetworkMode(entryValuesInt[entryIndex]));
add4gEntry(entryValuesInt[entryIndex]);
break;
case add5gAndLteEntry:
add5gEntry(addNrToLteNetworkType(entryValuesInt[entryIndex]));
add5gEntry(addNrToLteNetworkMode(entryValuesInt[entryIndex]));
addLteEntry(entryValuesInt[entryIndex]);
break;
default:
@@ -445,12 +518,12 @@ public class EnabledNetworkModePreferenceController extends
}
private int getPreferredNetworkMode() {
int networkMode = MobileNetworkUtils.getNetworkTypeFromRaf(
int networkMode = RadioAccessFamily.getNetworkTypeFromRaf(
(int) mTelephonyManager.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
if (!showNrList()) {
Log.d(LOG_TAG, "Network mode :" + networkMode + " reduce NR");
networkMode = reduceNrToLteNetworkType(networkMode);
networkMode = reduceNrToLteNetworkMode(networkMode);
}
Log.d(LOG_TAG, "getPreferredNetworkMode: " + networkMode);
return networkMode;
@@ -471,16 +544,16 @@ public class EnabledNetworkModePreferenceController extends
enabledNetworkType = EnabledNetworks.ENABLED_NETWORKS_CDMA_CHOICES;
} else {
switch (settingsNetworkMode) {
case TelephonyManagerConstants.NETWORK_MODE_CDMA_EVDO:
case TelephonyManagerConstants.NETWORK_MODE_CDMA_NO_EVDO:
case TelephonyManagerConstants.NETWORK_MODE_EVDO_NO_CDMA:
case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
enabledNetworkType =
EnabledNetworks.ENABLED_NETWORKS_CDMA_NO_LTE_CHOICES;
break;
case TelephonyManagerConstants.NETWORK_MODE_GLOBAL:
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO:
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY:
case TelephonyManager.NETWORK_MODE_GLOBAL:
case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_ONLY:
enabledNetworkType =
EnabledNetworks.ENABLED_NETWORKS_CDMA_ONLY_LTE_CHOICES;
break;
@@ -538,46 +611,42 @@ public class EnabledNetworkModePreferenceController extends
void setPreferenceValueAndSummary(int networkMode) {
setSelectedEntry(networkMode);
switch (networkMode) {
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM:
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA);
case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
setSelectedEntry(TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA);
setSummary(R.string.network_3G);
break;
case TelephonyManagerConstants.NETWORK_MODE_WCDMA_ONLY:
case TelephonyManagerConstants.NETWORK_MODE_GSM_UMTS:
case TelephonyManagerConstants.NETWORK_MODE_WCDMA_PREF:
case TelephonyManager.NETWORK_MODE_WCDMA_ONLY:
case TelephonyManager.NETWORK_MODE_GSM_UMTS:
case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
if (!mIsGlobalCdma) {
setSelectedEntry(TelephonyManagerConstants.NETWORK_MODE_WCDMA_PREF);
setSelectedEntry(TelephonyManager.NETWORK_MODE_WCDMA_PREF);
setSummary(R.string.network_3G);
} else {
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
setSelectedEntry(TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
setSummary(R.string.network_global);
}
break;
case TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY:
case TelephonyManager.NETWORK_MODE_GSM_ONLY:
if (!mIsGlobalCdma) {
setSelectedEntry(TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY);
setSelectedEntry(TelephonyManager.NETWORK_MODE_GSM_ONLY);
setSummary(R.string.network_2G);
} else {
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
setSelectedEntry(TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
setSummary(R.string.network_global);
}
break;
case TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
if (MobileNetworkUtils.isWorldMode(mContext, mSubId)) {
setSummary(
R.string.preferred_network_mode_lte_gsm_umts_summary);
break;
}
case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY:
case TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_ONLY:
case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
if (!mIsGlobalCdma) {
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA);
setSelectedEntry(TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA);
if (is5gEntryDisplayed()) {
setSummary(mShow4gForLTE
? R.string.network_4G_pure : R.string.network_lte_pure);
@@ -586,55 +655,52 @@ public class EnabledNetworkModePreferenceController extends
? R.string.network_4G : R.string.network_lte);
}
} else {
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
setSelectedEntry(TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
setSummary(R.string.network_global);
}
break;
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO:
case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
if (MobileNetworkUtils.isWorldMode(mContext, mSubId)) {
setSummary(
R.string.preferred_network_mode_lte_cdma_summary);
} else {
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO);
setSelectedEntry(TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO);
setSummary(is5gEntryDisplayed()
? R.string.network_lte_pure : R.string.network_lte);
}
break;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
setSelectedEntry(TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
setSummary(R.string.network_3G);
break;
case TelephonyManagerConstants.NETWORK_MODE_CDMA_EVDO:
case TelephonyManagerConstants.NETWORK_MODE_EVDO_NO_CDMA:
case TelephonyManagerConstants.NETWORK_MODE_GLOBAL:
setSelectedEntry(TelephonyManagerConstants.NETWORK_MODE_CDMA_EVDO);
case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
case TelephonyManager.NETWORK_MODE_GLOBAL:
setSelectedEntry(TelephonyManager.NETWORK_MODE_CDMA_EVDO);
setSummary(R.string.network_3G);
break;
case TelephonyManagerConstants.NETWORK_MODE_CDMA_NO_EVDO:
setSelectedEntry(TelephonyManagerConstants.NETWORK_MODE_CDMA_NO_EVDO);
case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
setSelectedEntry(TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO);
setSummary(R.string.network_1x);
break;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_ONLY:
setSelectedEntry(TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_ONLY);
case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
setSelectedEntry(TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY);
setSummary(R.string.network_3G);
break;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM:
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA:
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
if (MobileNetworkUtils.isTdscdmaSupported(mContext, mSubId)) {
setSelectedEntry(TelephonyManagerConstants
.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
setSelectedEntry(
TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
setSummary(is5gEntryDisplayed()
? R.string.network_lte_pure : R.string.network_lte);
} else {
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA
|| mIsGlobalCdma
|| MobileNetworkUtils.isWorldMode(mContext, mSubId)) {
@@ -651,30 +717,28 @@ public class EnabledNetworkModePreferenceController extends
}
break;
case TelephonyManagerConstants.NETWORK_MODE_NR_ONLY:
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE:
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_ONLY:
case TelephonyManager.NETWORK_MODE_NR_LTE:
case TelephonyManager.NETWORK_MODE_NR_LTE_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_WCDMA:
setSelectedEntry(TelephonyManager.NETWORK_MODE_NR_LTE_GSM_WCDMA);
setSummary(getResourcesForSubId().getString(R.string.network_5G_recommended));
break;
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA);
TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
setSummary(getResourcesForSubId().getString(R.string.network_5G_recommended));
break;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA:
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM:
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA:
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
setSelectedEntry(TelephonyManagerConstants
.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
case TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO:
setSelectedEntry(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO);
setSummary(getResourcesForSubId().getString(R.string.network_5G_recommended));
break;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO:
setSelectedEntry(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO);
setSummary(getResourcesForSubId().getString(R.string.network_5G_recommended));
break;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA:
setSelectedEntry(
TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA);
case TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA:
setSelectedEntry(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA);
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA
|| mIsGlobalCdma
|| MobileNetworkUtils.isWorldMode(mContext, mSubId)) {
@@ -691,74 +755,6 @@ public class EnabledNetworkModePreferenceController extends
}
}
/**
* Transform LTE network mode to 5G network mode.
*
* @param networkType an LTE network mode without 5G.
* @return the corresponding network mode with 5G.
*/
private int addNrToLteNetworkType(int networkType) {
switch (networkType) {
case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE;
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO;
case TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
return TelephonyManagerConstants
.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
default:
return networkType; // not LTE
}
}
/**
* Transform NR5G network mode to LTE network mode.
*
* @param networkType an 5G network mode.
* @return the corresponding network mode without 5G.
*/
private int reduceNrToLteNetworkType(int networkType) {
switch (networkType) {
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE:
return TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO:
return TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA:
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM:
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
return TelephonyManagerConstants
.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
default:
return networkType; // do nothing
}
}
private void setPreferenceValueAndSummary() {
setPreferenceValueAndSummary(getPreferredNetworkMode());
}
@@ -771,7 +767,7 @@ public class EnabledNetworkModePreferenceController extends
* Add 5G option. Only show the UI when device supported 5G and allowed 5G.
*/
private void add5gEntry(int value) {
boolean isNRValue = value >= TelephonyManagerConstants.NETWORK_MODE_NR_ONLY;
boolean isNRValue = value >= TelephonyManager.NETWORK_MODE_NR_ONLY;
if (showNrList() && isNRValue) {
mEntries.add(getResourcesForSubId().getString(R.string.network_5G_recommended));
mEntriesValue.add(value);
@@ -791,7 +787,7 @@ public class EnabledNetworkModePreferenceController extends
+ " allowed5GNetworkType: " + mAllowed5gNetworkType);
mEntries.add(getResourcesForSubId().getString(R.string.network_global));
if (showNrList()) {
value = addNrToLteNetworkType(value);
value = addNrToLteNetworkMode(value);
}
mEntriesValue.add(value);
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.network.telephony
import android.content.Context
import android.telephony.CarrierConfigManager
import android.telephony.RadioAccessFamily
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import androidx.lifecycle.LifecycleOwner
@@ -35,7 +36,7 @@ fun TelephonyManager.setAllowedNetworkTypes(
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) {
setAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
MobileNetworkUtils.getRafFromNetworkType(newPreferredNetworkMode),
RadioAccessFamily.getRafFromNetworkType(newPreferredNetworkMode).toLong(),
)
}
}

View File

@@ -17,6 +17,7 @@
package com.android.settings.network.telephony
import android.content.Context
import android.telephony.CarrierConfigManager
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.data.ApnSetting
@@ -45,7 +46,7 @@ constructor(
private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
private var telephonyManager: TelephonyManager =
context.getSystemService(TelephonyManager::class.java)!!
private val carrierConfigRepository = CarrierConfigRepository(context)
private var preferenceScreen: PreferenceScreen? = null
fun init(subId: Int) {
@@ -54,7 +55,13 @@ constructor(
}
override fun getAvailabilityStatus() =
if (getAvailabilityStatus(telephonyManager, subId, getDefaultDataSubId)) AVAILABLE
if (getAvailabilityStatus(
telephonyManager,
subId,
getDefaultDataSubId,
carrierConfigRepository
)
) AVAILABLE
else CONDITIONALLY_UNAVAILABLE
override fun displayPreference(screen: PreferenceScreen) {
@@ -92,11 +99,14 @@ constructor(
telephonyManager: TelephonyManager,
subId: Int,
getDefaultDataSubId: () -> Int,
carrierConfigRepository: CarrierConfigRepository,
): Boolean {
return SubscriptionManager.isValidSubscriptionId(subId) &&
!telephonyManager.isDataEnabled &&
telephonyManager.isApnMetered(ApnSetting.TYPE_MMS) &&
!isFallbackDataEnabled(telephonyManager, subId, getDefaultDataSubId())
!isFallbackDataEnabled(telephonyManager, subId, getDefaultDataSubId()) &&
carrierConfigRepository.getBoolean(
subId, CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL)
}
private fun isFallbackDataEnabled(
@@ -118,11 +128,16 @@ constructor(
) : MobileNetworkSettingsSearchItem {
private var telephonyManager: TelephonyManager =
context.getSystemService(TelephonyManager::class.java)!!
private val carrierConfigRepository = CarrierConfigRepository(context)
@VisibleForTesting
fun isAvailable(subId: Int): Boolean =
getAvailabilityStatus(
telephonyManager.createForSubscriptionId(subId), subId, getDefaultDataSubId)
telephonyManager.createForSubscriptionId(subId),
subId,
getDefaultDataSubId,
carrierConfigRepository
)
override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {
if (!isAvailable(subId)) return null

View File

@@ -277,11 +277,18 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
if (roamingPreferenceController != null) {
roamingPreferenceController.init(getParentFragmentManager(), mSubId);
}
final SatelliteSettingsPreferenceCategoryController
satelliteSettingsPreferenceCategoryController =
use(SatelliteSettingsPreferenceCategoryController.class);
if (satelliteSettingsPreferenceCategoryController != null) {
satelliteSettingsPreferenceCategoryController.init(mSubId);
}
final SatelliteSettingPreferenceController satelliteSettingPreferenceController = use(
SatelliteSettingPreferenceController.class);
if (satelliteSettingPreferenceController != null) {
satelliteSettingPreferenceController.init(mSubId);
}
use(ApnPreferenceController.class).init(mSubId);
use(CarrierPreferenceController.class).init(mSubId);
use(DataUsagePreferenceController.class).init(mSubId);
@@ -327,12 +334,10 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
convertToEsimPreferenceController.init(mSubId, mSubscriptionInfoEntity);
}
List<AbstractSubscriptionPreferenceController> subscriptionPreferenceControllers =
useAll(AbstractSubscriptionPreferenceController.class);
for (AbstractSubscriptionPreferenceController controller :
subscriptionPreferenceControllers) {
controller.init(mSubId);
}
List<AbstractPreferenceController> subscriptionPreferenceControllers =
useGroup(AbstractSubscriptionPreferenceController.class);
subscriptionPreferenceControllers.forEach(
controller -> ((AbstractSubscriptionPreferenceController) controller).init(mSubId));
}
@Override

View File

@@ -18,19 +18,6 @@ package com.android.settings.network.telephony;
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.EVDO;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.LTE;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.NR;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_UNKNOWN;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA;
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO;
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA;
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO;
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
@@ -56,11 +43,11 @@ import android.provider.Settings;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsRcsManager;
import android.telephony.ims.ProvisioningManager;
@@ -83,15 +70,12 @@ import com.android.settings.core.SubSettingLauncher;
import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.network.ims.WifiCallingQueryImsState;
import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants;
import com.android.settings.network.telephony.wificalling.WifiCallingRepository;
import com.android.settingslib.core.instrumentation.Instrumentable;
import com.android.settingslib.graph.SignalDrawable;
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MobileNetworkUtils {
@@ -334,14 +318,14 @@ public class MobileNetworkUtils {
}
if (isWorldMode(context, subId)) {
final int settingsNetworkMode = getNetworkTypeFromRaf(
final int settingsNetworkMode = RadioAccessFamily.getNetworkTypeFromRaf(
(int) telephonyManager.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
if (settingsNetworkMode == NETWORK_MODE_LTE_GSM_WCDMA
|| settingsNetworkMode == NETWORK_MODE_LTE_CDMA_EVDO
|| settingsNetworkMode == NETWORK_MODE_NR_LTE_GSM_WCDMA
|| settingsNetworkMode == NETWORK_MODE_NR_LTE_CDMA_EVDO) {
if (settingsNetworkMode == TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA
|| settingsNetworkMode == TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO
|| settingsNetworkMode == TelephonyManager.NETWORK_MODE_NR_LTE_GSM_WCDMA
|| settingsNetworkMode == TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO) {
return true;
}
@@ -365,14 +349,14 @@ public class MobileNetworkUtils {
}
final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
.createForSubscriptionId(subId);
final int networkMode = getNetworkTypeFromRaf(
final int networkMode = RadioAccessFamily.getNetworkTypeFromRaf(
(int) telephonyManager.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
if (isWorldMode(context, subId)) {
if (networkMode == NETWORK_MODE_LTE_CDMA_EVDO
|| networkMode == NETWORK_MODE_LTE_GSM_WCDMA
|| networkMode == NETWORK_MODE_NR_LTE_CDMA_EVDO
|| networkMode == NETWORK_MODE_NR_LTE_GSM_WCDMA) {
if (networkMode == TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO
|| networkMode == TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA
|| networkMode == TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO
|| networkMode == TelephonyManager.NETWORK_MODE_NR_LTE_GSM_WCDMA) {
return true;
} else if (shouldSpeciallyUpdateGsmCdma(context, subId)) {
return true;
@@ -433,17 +417,17 @@ public class MobileNetworkUtils {
}
if (isWorldMode(context, subId)) {
final int networkMode = getNetworkTypeFromRaf(
final int networkMode = RadioAccessFamily.getNetworkTypeFromRaf(
(int) telephonyManager.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO) {
if (networkMode == TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO) {
return false;
}
if (shouldSpeciallyUpdateGsmCdma(context, subId)) {
return false;
}
if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA) {
if (networkMode == TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA) {
return true;
}
}
@@ -548,16 +532,16 @@ public class MobileNetworkUtils {
}
final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
.createForSubscriptionId(subId);
final int networkMode = getNetworkTypeFromRaf(
final int networkMode = RadioAccessFamily.getNetworkTypeFromRaf(
(int) telephonyManager.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM
|| networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA
|| networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA
|| networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA
if (networkMode == TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM
|| networkMode == TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA
|| networkMode == TelephonyManager.NETWORK_MODE_LTE_TDSCDMA
|| networkMode == TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA
|| networkMode
== TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
|| networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA) {
== TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
|| networkMode == TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA) {
if (!isTdscdmaSupported(context, subId)) {
return true;
}
@@ -610,12 +594,8 @@ public class MobileNetworkUtils {
}
public static CharSequence getCurrentCarrierNameForDisplay(Context context) {
final SubscriptionInfo subInfo = getSubscriptionInfo(context,
return getCurrentCarrierNameForDisplay(context,
SubscriptionManager.getDefaultSubscriptionId());
if (subInfo != null) {
return subInfo.getCarrierName();
}
return getOperatorNameFromTelephonyManager(context);
}
private static @Nullable SubscriptionInfo getSubscriptionInfo(Context context, int subId) {
@@ -651,197 +631,6 @@ public class MobileNetworkUtils {
return activeSubIds;
}
/**
* Loop through all the device logical slots to check whether the user's current country
* supports eSIM.
*/
private static boolean isCurrentCountrySupported(Context context) {
final EuiccManager em = (EuiccManager) context.getSystemService(EuiccManager.class);
final TelephonyManager tm =
(TelephonyManager) context.getSystemService(TelephonyManager.class);
Set<String> countrySet = new HashSet<>();
for (int i = 0; i < tm.getPhoneCount(); i++) {
String countryCode = tm.getNetworkCountryIso(i);
if (!TextUtils.isEmpty(countryCode)) {
countrySet.add(countryCode);
}
}
boolean isSupported = countrySet.stream().anyMatch(em::isSupportedCountry);
Log.i(TAG, "isCurrentCountrySupported countryCodes: " + countrySet
+ " eSIMSupported: " + isSupported);
return isSupported;
}
/**
* Imported from {@link android.telephony.RadioAccessFamily}
*/
public static long getRafFromNetworkType(int type) {
switch (type) {
case TelephonyManagerConstants.NETWORK_MODE_WCDMA_PREF:
return GSM | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY:
return GSM;
case TelephonyManagerConstants.NETWORK_MODE_WCDMA_ONLY:
return WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_GSM_UMTS:
return GSM | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_CDMA_EVDO:
return CDMA | EVDO;
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO:
return LTE | CDMA | EVDO;
case TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA:
return LTE | GSM | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
return LTE | CDMA | EVDO | GSM | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY:
return LTE;
case TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA:
return LTE | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_CDMA_NO_EVDO:
return CDMA;
case TelephonyManagerConstants.NETWORK_MODE_EVDO_NO_CDMA:
return EVDO;
case TelephonyManagerConstants.NETWORK_MODE_GLOBAL:
return GSM | WCDMA | CDMA | EVDO;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_ONLY:
return RAF_TD_SCDMA;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_WCDMA:
return RAF_TD_SCDMA | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA:
return LTE | RAF_TD_SCDMA;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM:
return RAF_TD_SCDMA | GSM;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM:
return LTE | RAF_TD_SCDMA | GSM;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
return RAF_TD_SCDMA | GSM | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
return LTE | RAF_TD_SCDMA | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
return LTE | RAF_TD_SCDMA | GSM | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
return RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
return LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
case (TelephonyManagerConstants.NETWORK_MODE_NR_ONLY):
return NR;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE):
return NR | LTE;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO):
return NR | LTE | CDMA | EVDO;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA):
return NR | LTE | GSM | WCDMA;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA):
return NR | LTE | CDMA | EVDO | GSM | WCDMA;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA):
return NR | LTE | WCDMA;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA):
return NR | LTE | RAF_TD_SCDMA;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM):
return NR | LTE | RAF_TD_SCDMA | GSM;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA):
return NR | LTE | RAF_TD_SCDMA | WCDMA;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA):
return NR | LTE | RAF_TD_SCDMA | GSM | WCDMA;
case (TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA):
return NR | LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
default:
return RAF_UNKNOWN;
}
}
/**
* Imported from {@link android.telephony.RadioAccessFamily}
*/
public static int getNetworkTypeFromRaf(int raf) {
raf = getAdjustedRaf(raf);
switch (raf) {
case (GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_WCDMA_PREF;
case GSM:
return TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY;
case WCDMA:
return TelephonyManagerConstants.NETWORK_MODE_WCDMA_ONLY;
case (CDMA | EVDO):
return TelephonyManagerConstants.NETWORK_MODE_CDMA_EVDO;
case (LTE | CDMA | EVDO):
return TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO;
case (LTE | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA;
case (LTE | CDMA | EVDO | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
case LTE:
return TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY;
case (LTE | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA;
case CDMA:
return TelephonyManagerConstants.NETWORK_MODE_CDMA_NO_EVDO;
case EVDO:
return TelephonyManagerConstants.NETWORK_MODE_EVDO_NO_CDMA;
case (GSM | WCDMA | CDMA | EVDO):
return TelephonyManagerConstants.NETWORK_MODE_GLOBAL;
case RAF_TD_SCDMA:
return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_ONLY;
case (RAF_TD_SCDMA | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_WCDMA;
case (LTE | RAF_TD_SCDMA):
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA;
case (RAF_TD_SCDMA | GSM):
return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM;
case (LTE | RAF_TD_SCDMA | GSM):
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
case (RAF_TD_SCDMA | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
case (LTE | RAF_TD_SCDMA | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
case (LTE | RAF_TD_SCDMA | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
case (RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
case (LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
case (NR):
return TelephonyManagerConstants.NETWORK_MODE_NR_ONLY;
case (NR | LTE):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE;
case (NR | LTE | CDMA | EVDO):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO;
case (NR | LTE | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
case (NR | LTE | CDMA | EVDO | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA;
case (NR | LTE | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA;
case (NR | LTE | RAF_TD_SCDMA):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA;
case (NR | LTE | RAF_TD_SCDMA | GSM):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM;
case (NR | LTE | RAF_TD_SCDMA | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA;
case (NR | LTE | RAF_TD_SCDMA | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA;
case (NR | LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
default:
return TelephonyManagerConstants.NETWORK_MODE_UNKNOWN;
}
}
/**
* Imported from {@link android.telephony.RadioAccessFamily}
*/
private static int getAdjustedRaf(int raf) {
raf = ((GSM & raf) > 0) ? (GSM | raf) : raf;
raf = ((WCDMA & raf) > 0) ? (WCDMA | raf) : raf;
raf = ((CDMA & raf) > 0) ? (CDMA | raf) : raf;
raf = ((EVDO & raf) > 0) ? (EVDO | raf) : raf;
raf = ((LTE & raf) > 0) ? (LTE | raf) : raf;
raf = ((NR & raf) > 0) ? (NR | raf) : raf;
return raf;
}
/**
* Copied from SubscriptionsPreferenceController#activeNetworkIsCellular()
*/

View File

@@ -22,6 +22,7 @@ import android.telephony.CarrierConfigManager
import android.telephony.NetworkRegistrationInfo
import android.telephony.TelephonyManager
import android.telephony.satellite.SatelliteManager
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
@@ -92,6 +93,11 @@ class NetworkSelectRepository(context: Context, private val subId: Int) {
* Update satellite PLMNs from the satellite framework.
*/
private fun getSatellitePlmns(): List<String> {
if (satelliteManager == null) {
Log.d(TAG, "SatelliteManager is null")
return emptyList()
}
val config = carrierConfigManager.getConfigForSubId(
subId,
CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL
@@ -104,7 +110,11 @@ class NetworkSelectRepository(context: Context, private val subId: Int) {
return if (shouldFilter) {
satelliteManager.getSatellitePlmnsForCarrier(subId)
} else {
emptyList();
emptyList()
}
}
private companion object {
private const val TAG = "NetworkSelectRepository"
}
}

View File

@@ -21,33 +21,81 @@ import static com.android.settings.network.telephony.EnabledNetworkModePreferenc
import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.RadioAccessFamily;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteModemStateCallback;
import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants;
import com.android.settings.network.telephony.mode.NetworkModes;
/**
* Preference controller for "Preferred network mode"
*/
public class PreferredNetworkModePreferenceController extends BasePreferenceController
implements ListPreference.OnPreferenceChangeListener {
implements ListPreference.OnPreferenceChangeListener, DefaultLifecycleObserver {
private static final String TAG = "PrefNetworkModeCtrl";
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private CarrierConfigCache mCarrierConfigCache;
private TelephonyManager mTelephonyManager;
private boolean mIsGlobalCdma;
private SatelliteManager mSatelliteManager;
private Preference mPreference;
private boolean mIsSatelliteSessionStarted = false;
private boolean mIsCurrentSubscriptionForSatellite = false;
@VisibleForTesting
final SelectedNbIotSatelliteSubscriptionCallback mSelectedNbIotSatelliteSubscriptionCallback =
new SelectedNbIotSatelliteSubscriptionCallback() {
@Override
public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
mIsCurrentSubscriptionForSatellite = selectedSubId == mSubId;
updateState(mPreference);
}
};
@VisibleForTesting
final SatelliteModemStateCallback mSatelliteModemStateCallback =
new SatelliteModemStateCallback() {
@Override
public void onSatelliteModemStateChanged(int state) {
switch (state) {
case SatelliteManager.SATELLITE_MODEM_STATE_OFF:
case SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE:
case SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN:
if (mIsSatelliteSessionStarted) {
mIsSatelliteSessionStarted = false;
updateState(mPreference);
}
break;
default:
if (!mIsSatelliteSessionStarted) {
mIsSatelliteSessionStarted = true;
updateState(mPreference);
}
break;
}
}
};
public PreferredNetworkModePreferenceController(Context context, String key) {
super(context, key);
mCarrierConfigCache = CarrierConfigCache.getInstance(context);
mSatelliteManager = context.getSystemService(SatelliteManager.class);
}
@Override
@@ -57,9 +105,19 @@ public class PreferredNetworkModePreferenceController extends BasePreferenceCont
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public void updateState(Preference preference) {
if (preference == null) {
return;
}
super.updateState(preference);
preference.setEnabled(!(mIsCurrentSubscriptionForSatellite && mIsSatelliteSessionStarted));
final ListPreference listPreference = (ListPreference) preference;
final int networkMode = getPreferredNetworkMode();
listPreference.setValue(Integer.toString(networkMode));
@@ -72,11 +130,11 @@ public class PreferredNetworkModePreferenceController extends BasePreferenceCont
mTelephonyManager.setAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
MobileNetworkUtils.getRafFromNetworkType(newPreferredNetworkMode));
RadioAccessFamily.getRafFromNetworkType(newPreferredNetworkMode));
final ListPreference listPreference = (ListPreference) preference;
listPreference.setSummary(getPreferredNetworkModeSummaryResId(newPreferredNetworkMode));
return true;
final ListPreference listPreference = (ListPreference) preference;
listPreference.setSummary(getPreferredNetworkModeSummaryResId(newPreferredNetworkMode));
return true;
}
public void init(int subId) {
@@ -89,57 +147,89 @@ public class PreferredNetworkModePreferenceController extends BasePreferenceCont
&& carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL);
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
if (mSatelliteManager != null) {
try {
mSatelliteManager.registerForModemStateChanged(
mContext.getMainExecutor(), mSatelliteModemStateCallback);
mSatelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
mContext.getMainExecutor(),
mSelectedNbIotSatelliteSubscriptionCallback);
} catch (IllegalStateException e) {
Log.w(TAG, "IllegalStateException : " + e);
}
}
}
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
if (mSatelliteManager != null) {
try {
mSatelliteManager.unregisterForModemStateChanged(mSatelliteModemStateCallback);
mSatelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
mSelectedNbIotSatelliteSubscriptionCallback);
} catch (IllegalStateException e) {
Log.w(TAG, "IllegalStateException : " + e);
}
}
}
}
private int getPreferredNetworkMode() {
if (mTelephonyManager == null) {
Log.w(TAG, "TelephonyManager is null");
return TelephonyManagerConstants.NETWORK_MODE_UNKNOWN;
return NetworkModes.NETWORK_MODE_UNKNOWN;
}
return MobileNetworkUtils.getNetworkTypeFromRaf(
return RadioAccessFamily.getNetworkTypeFromRaf(
(int) mTelephonyManager.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
}
private int getPreferredNetworkModeSummaryResId(int NetworkMode) {
switch (NetworkMode) {
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
private int getPreferredNetworkModeSummaryResId(int networkMode) {
switch (networkMode) {
case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
return R.string.preferred_network_mode_tdscdma_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM:
case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM:
return R.string.preferred_network_mode_tdscdma_gsm_summary;
case TelephonyManagerConstants.NETWORK_MODE_WCDMA_PREF:
case TelephonyManager.NETWORK_MODE_WCDMA_PREF:
return R.string.preferred_network_mode_wcdma_perf_summary;
case TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY:
case TelephonyManager.NETWORK_MODE_GSM_ONLY:
return R.string.preferred_network_mode_gsm_only_summary;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_WCDMA:
case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
return R.string.preferred_network_mode_tdscdma_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_WCDMA_ONLY:
case TelephonyManager.NETWORK_MODE_WCDMA_ONLY:
return R.string.preferred_network_mode_wcdma_only_summary;
case TelephonyManagerConstants.NETWORK_MODE_GSM_UMTS:
case TelephonyManager.NETWORK_MODE_GSM_UMTS:
return R.string.preferred_network_mode_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_CDMA_EVDO:
case TelephonyManager.NETWORK_MODE_CDMA_EVDO:
return mTelephonyManager.isLteCdmaEvdoGsmWcdmaEnabled()
? R.string.preferred_network_mode_cdma_summary
: R.string.preferred_network_mode_cdma_evdo_summary;
case TelephonyManagerConstants.NETWORK_MODE_CDMA_NO_EVDO:
case TelephonyManager.NETWORK_MODE_CDMA_NO_EVDO:
return R.string.preferred_network_mode_cdma_only_summary;
case TelephonyManagerConstants.NETWORK_MODE_EVDO_NO_CDMA:
case TelephonyManager.NETWORK_MODE_EVDO_NO_CDMA:
return R.string.preferred_network_mode_evdo_only_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA:
return R.string.preferred_network_mode_lte_tdscdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY:
case TelephonyManager.NETWORK_MODE_LTE_ONLY:
return R.string.preferred_network_mode_lte_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM:
return R.string.preferred_network_mode_lte_tdscdma_gsm_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
return R.string.preferred_network_mode_lte_tdscdma_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA:
return R.string.preferred_network_mode_lte_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO:
case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO:
return R.string.preferred_network_mode_lte_cdma_evdo_summary;
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_ONLY:
case TelephonyManager.NETWORK_MODE_TDSCDMA_ONLY:
return R.string.preferred_network_mode_tdscdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
return R.string.preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA
|| mIsGlobalCdma
|| MobileNetworkUtils.isWorldMode(mContext, mSubId)) {
@@ -147,35 +237,35 @@ public class PreferredNetworkModePreferenceController extends BasePreferenceCont
} else {
return R.string.preferred_network_mode_lte_summary;
}
case TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
return R.string.preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_GLOBAL:
case TelephonyManager.NETWORK_MODE_GLOBAL:
return R.string.preferred_network_mode_cdma_evdo_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
return R.string.preferred_network_mode_lte_tdscdma_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA:
case TelephonyManager.NETWORK_MODE_LTE_WCDMA:
return R.string.preferred_network_mode_lte_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_ONLY:
case TelephonyManager.NETWORK_MODE_NR_ONLY:
return R.string.preferred_network_mode_nr_only_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE:
case TelephonyManager.NETWORK_MODE_NR_LTE:
return R.string.preferred_network_mode_nr_lte_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO:
case TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO:
return R.string.preferred_network_mode_nr_lte_cdma_evdo_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_GSM_WCDMA:
return R.string.preferred_network_mode_nr_lte_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA:
return R.string.preferred_network_mode_global_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_WCDMA:
return R.string.preferred_network_mode_nr_lte_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA:
return R.string.preferred_network_mode_nr_lte_tdscdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM:
return R.string.preferred_network_mode_nr_lte_tdscdma_gsm_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA:
return R.string.preferred_network_mode_nr_lte_tdscdma_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA:
return R.string.preferred_network_mode_nr_lte_tdscdma_gsm_wcdma_summary;
case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
case TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
return R.string.preferred_network_mode_nr_lte_tdscdma_cdma_evdo_gsm_wcdma_summary;
default:
return R.string.preferred_network_mode_global_summary;

View File

@@ -56,20 +56,26 @@ import java.util.Set;
/** Handle Satellite Setting Preference Layout. */
public class SatelliteSetting extends RestrictedDashboardFragment {
private static final String TAG = "SatelliteSetting";
public static final String PREF_KEY_ABOUT_SATELLITE_MESSAGING = "key_about_satellite_messaging";
public static final String PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN =
private static final String PREF_KEY_ABOUT_SATELLITE_MESSAGING =
"key_about_satellite_messaging";
private static final String PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN =
"key_category_your_satellite_plan";
public static final String PREF_KEY_YOUR_SATELLITE_PLAN = "key_your_satellite_plan";
public static final String PREF_KEY_CATEGORY_HOW_IT_WORKS = "key_category_how_it_works";
private static final String PREF_KEY_YOUR_SATELLITE_PLAN = "key_your_satellite_plan";
private static final String PREF_KEY_CATEGORY_HOW_IT_WORKS = "key_category_how_it_works";
private static final String PREF_KEY_YOUR_SATELLITE_DATA_PLAN = "key_your_satellite_data_plan";
private static final String PREF_KEY_CATEGORY_ABOUT_SATELLITE = "key_category_about_satellite";
private static final String KEY_FOOTER_PREFERENCE = "satellite_setting_extra_info_footer_pref";
public static final String SUB_ID = "sub_id";
static final String SUB_ID = "sub_id";
static final String EXTRA_IS_SERVICE_DATA_TYPE = "is_service_data_type";
private Activity mActivity;
private TelephonyManager mTelephonymanager;
private CarrierConfigManager mCarrierConfigManager;
private SatelliteManager mSatelliteManager;
private PersistableBundle mConfigBundle;
private int mSubId;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private String mSimOperatorName = "";
private boolean mIsServiceDataType = false;
public SatelliteSetting() {
super(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
@@ -111,13 +117,19 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
return;
}
mTelephonymanager = mActivity.getSystemService(TelephonyManager.class);
mIsServiceDataType = getIntent().getBooleanExtra(EXTRA_IS_SERVICE_DATA_TYPE, false);
mSimOperatorName = getSystemService(TelephonyManager.class).getSimOperatorName(mSubId);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
updateDynamicPreferenceViews();
boolean isSatelliteEligible = isSatelliteEligible();
updateTitle();
updateAboutSatelliteContent();
updateMobilePlan(isSatelliteEligible);
updateHowItWorksContent(isSatelliteEligible);
updateFooterContent();
}
@Override
@@ -130,31 +142,45 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
return R.xml.satellite_setting;
}
private void updateDynamicPreferenceViews() {
String operatorName = mTelephonymanager.getSimOperatorName(mSubId);
boolean isSatelliteEligible = isSatelliteEligible();
private void updateTitle() {
getActivity().setTitle(getSubjectString());
}
// About satellite content
private void updateAboutSatelliteContent() {
Preference categoryTitle = findPreference(PREF_KEY_CATEGORY_ABOUT_SATELLITE);
categoryTitle.setTitle(
getString(R.string.category_name_about_satellite_messaging,
getDescriptionString()));
// About satellite messaging
Preference preference = findPreference(PREF_KEY_ABOUT_SATELLITE_MESSAGING);
preference.setTitle(
getResources().getString(R.string.title_about_satellite_setting, operatorName));
getResources().getString(R.string.title_about_satellite_setting, mSimOperatorName));
}
private void updateMobilePlan(boolean isSatelliteEligible) {
// Your mobile plan
PreferenceCategory prefCategory = findPreference(PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN);
prefCategory.setTitle(getResources().getString(R.string.category_title_your_satellite_plan,
operatorName));
mSimOperatorName));
Preference messagingPreference = findPreference(PREF_KEY_YOUR_SATELLITE_PLAN);
preference = findPreference(PREF_KEY_YOUR_SATELLITE_PLAN);
Drawable icon;
Drawable icon = getContext().getDrawable(R.drawable.ic_check_circle_24px);
if (isSatelliteEligible) {
/* In case satellite is allowed by carrier's entitlement server, the page will show
the check icon with guidance that satellite is included in user's mobile plan */
preference.setTitle(R.string.title_have_satellite_plan);
icon = getContext().getDrawable(R.drawable.ic_check_circle_24px);
messagingPreference.setTitle(R.string.title_have_satellite_plan);
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
Preference connectivityPreference = findPreference(
PREF_KEY_YOUR_SATELLITE_DATA_PLAN);
connectivityPreference.setTitle(R.string.title_have_satellite_data_plan);
connectivityPreference.setIcon(icon);
connectivityPreference.setVisible(true);
}
} else {
/* Or, it will show the blocked icon with the guidance that satellite is not included
in user's mobile plan */
preference.setTitle(R.string.title_no_satellite_plan);
messagingPreference.setTitle(R.string.title_no_satellite_plan);
/* And, the link url provides more information via web page will be shown */
SpannableString spannable = new SpannableString(
getResources().getString(R.string.summary_add_satellite_setting));
@@ -162,9 +188,9 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, spannable.length(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
preference.setSummary(spannable);
messagingPreference.setSummary(spannable);
/* The link will lead users to a guide page */
preference.setOnPreferenceClickListener(pref -> {
messagingPreference.setOnPreferenceClickListener(pref -> {
String url = readSatelliteMoreInfoString(mSubId);
if (!url.isEmpty()) {
Uri uri = Uri.parse(url);
@@ -173,11 +199,13 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
}
return true;
});
icon = getResources().getDrawable(R.drawable.ic_block_24px);
icon = getResources().getDrawable(R.drawable.ic_block_24px, null);
}
icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary));
preference.setIcon(icon);
messagingPreference.setIcon(icon);
}
private void updateHowItWorksContent(boolean isSatelliteEligible) {
/* Composes "How it works" section, which guides how users can use satellite messaging, when
satellite messaging is included in user's mobile plan, or it'll will be grey out. */
if (!isSatelliteEligible) {
@@ -185,29 +213,32 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
category.setEnabled(false);
category.setShouldDisableView(true);
}
}
private void updateFooterContent() {
// More about satellite messaging
FooterPreference footerPreference = findPreference(KEY_FOOTER_PREFERENCE);
if (footerPreference != null) {
footerPreference.setSummary(
getResources().getString(R.string.satellite_setting_summary_more_information,
operatorName));
getSubjectString(), mSimOperatorName));
final String[] link = new String[1];
link[0] = readSatelliteMoreInfoString(mSubId);
footerPreference.setLearnMoreAction(view -> {
if (!link[0].isEmpty()) {
Intent helpIntent = HelpUtils.getHelpIntent(mActivity, link[0],
this.getClass().getName());
if (helpIntent != null) {
mActivity.startActivityForResult(helpIntent, /*requestCode=*/ 0);
if (link[0] != null && !link[0].isEmpty()) {
footerPreference.setLearnMoreAction(view -> {
if (!link[0].isEmpty()) {
Intent helpIntent = HelpUtils.getHelpIntent(mActivity, link[0],
this.getClass().getName());
if (helpIntent != null) {
mActivity.startActivityForResult(helpIntent, /*requestCode=*/ 0);
}
}
}
});
footerPreference.setLearnMoreText(
getResources().getString(R.string.more_about_satellite_messaging));
});
// TODO : b/320467418 add rounded rectangle border line to footer preference.
footerPreference.setLearnMoreText(
getString(R.string.more_about_satellite_messaging, getDescriptionString()));
}
}
}
@@ -245,6 +276,32 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
return bundle.getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
}
// This is for a word which first letter is uppercase. e.g. Satellite messaging.
private String getSubjectString() {
int result;
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
result = mIsServiceDataType
? R.string.title_satellite_setting_connectivity
: R.string.satellite_setting_title;
} else {
result = R.string.satellite_setting_title;
}
return getString(result);
}
// This is for a word without uppercase letter. e.g. satellite messaging.
private String getDescriptionString() {
int result;
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
result = mIsServiceDataType
? R.string.description_satellite_setting_connectivity
: R.string.description_satellite_setting_messaging;
} else {
result = R.string.satellite_setting_title;
}
return getString(result);
}
private static void loge(String message) {
Log.e(TAG, message);
}

View File

@@ -16,16 +16,25 @@
package com.android.settings.network.telephony;
import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
import android.content.Context;
import android.content.Intent;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -33,28 +42,34 @@ import com.android.internal.telephony.flags.Flags;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.network.CarrierConfigCache;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* Preference controller for "Satellite Setting"
*/
public class SatelliteSettingPreferenceController extends
TelephonyBasePreferenceController implements LifecycleObserver, OnStart, OnStop {
TelephonyBasePreferenceController implements DefaultLifecycleObserver {
private static final String TAG = "SatelliteSettingPreferenceController";
CarrierConfigCache mCarrierConfigCache;
SatelliteManager mSatelliteManager;
@Nullable private Boolean mIsSatelliteEligible = null;
private TelephonyManager mTelephonyManager = null;
@VisibleForTesting
final CarrierRoamingNtnModeCallback mCarrierRoamingNtnModeCallback =
new CarrierRoamingNtnModeCallback();
@Nullable
private Boolean mIsSatelliteEligible = null;
private boolean mIsServiceDataType = false;
public SatelliteSettingPreferenceController(@NonNull Context context, @NonNull String key) {
super(context, key);
mCarrierConfigCache = CarrierConfigCache.getInstance(context);
mSatelliteManager = context.getSystemService(SatelliteManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
}
@Override
@@ -76,22 +91,31 @@ public class SatelliteSettingPreferenceController extends
}
@Override
public void onStart() {
public void onResume(@NonNull LifecycleOwner owner) {
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(),
mCarrierRoamingNtnModeCallback);
}
}
@Override
public void onStop() {
public void onPause(@NonNull LifecycleOwner owner) {
if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) {
mTelephonyManager.unregisterTelephonyCallback(mCarrierRoamingNtnModeCallback);
}
}
@Override
public void displayPreference(@NonNull PreferenceScreen screen) {
super.displayPreference(screen);
updateState(screen.findPreference(getPreferenceKey()));
}
@Override
public void updateState(@Nullable Preference preference) {
super.updateState(preference);
if (preference != null) {
mCarrierRoamingNtnModeCallback.mPref = preference;
updateSummary(preference);
}
}
@@ -105,6 +129,7 @@ public class SatelliteSettingPreferenceController extends
// This will setup the Home and Search affordance
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, true);
intent.putExtra(SatelliteSetting.SUB_ID, mSubId);
intent.putExtra(SatelliteSetting.EXTRA_IS_SERVICE_DATA_TYPE, mIsServiceDataType);
mContext.startActivity(intent);
return true;
}
@@ -114,14 +139,20 @@ public class SatelliteSettingPreferenceController extends
/**
* Set subId for Satellite Settings page.
*
* @param subId subscription ID.
*/
public void init(int subId) {
logd("init(), subId=" + subId);
mSubId = subId;
mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
}
private void updateSummary(Preference preference) {
if (mSatelliteManager == null) {
logd("updateSummary - no SatelliteManager");
return;
}
try {
Set<Integer> restrictionReason =
mSatelliteManager.getAttachRestrictionReasonsForCarrier(mSubId);
@@ -147,4 +178,46 @@ public class SatelliteSettingPreferenceController extends
private static void loge(String message) {
Log.e(TAG, message);
}
@VisibleForTesting
class CarrierRoamingNtnModeCallback extends TelephonyCallback implements
TelephonyCallback.CarrierRoamingNtnModeListener {
Preference mPref = null;
@Override
public void onCarrierRoamingNtnAvailableServicesChanged(int[] availableServices) {
CarrierRoamingNtnModeListener.super.onCarrierRoamingNtnAvailableServicesChanged(
availableServices);
List<Integer> availableServicesList = Arrays.stream(availableServices).boxed().toList();
boolean isSmsAvailable = availableServicesList.contains(SERVICE_TYPE_SMS);
boolean isDataAvailable = availableServicesList.contains(SERVICE_TYPE_DATA);
logd("isSmsAvailable : " + isSmsAvailable
+ " / isDataAvailable " + isDataAvailable);
if (mPref == null) {
logd("Satellite preference is not initialized yet");
return;
}
if (isDataAvailable) {
mIsServiceDataType = true;
mPref.setTitle(R.string.title_satellite_setting_connectivity);
} else if (isSmsAvailable) {
mPref.setTitle(R.string.satellite_setting_title);
}
}
@Override
public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
// Do nothing
}
@Override
public void onCarrierRoamingNtnModeChanged(boolean active) {
// Do nothing
}
@Override
public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
// Do nothing
}
}
}

View File

@@ -0,0 +1,160 @@
/*
* 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 static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL;
import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settings.network.CarrierConfigCache;
import java.util.Arrays;
import java.util.List;
/** Preference controller for Satellite functions in mobile network settings. */
public class SatelliteSettingsPreferenceCategoryController
extends TelephonyBasePreferenceController implements DefaultLifecycleObserver {
private static final String TAG = "SatelliteSettingsPrefCategoryCon";
private CarrierConfigCache mCarrierConfigCache;
private SatelliteManager mSatelliteManager;
private PreferenceCategory mPreferenceCategory;
private TelephonyManager mTelephonyManager;
@VisibleForTesting
final CarrierRoamingNtnModeCallback mCarrierRoamingNtnModeCallback =
new CarrierRoamingNtnModeCallback();
public SatelliteSettingsPreferenceCategoryController(Context context, String key) {
super(context, key);
mCarrierConfigCache = CarrierConfigCache.getInstance(context);
mSatelliteManager = context.getSystemService(SatelliteManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
}
/**
* Set subId for Satellite Settings category .
*
* @param subId subscription ID.
*/
public void init(int subId) {
Log.d(TAG, "init(), subId=" + subId);
mSubId = subId;
mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceCategory = screen.findPreference(getPreferenceKey());
}
@Override
public int getAvailabilityStatus(int subId) {
if (!com.android.internal.telephony.flags.Flags.carrierEnabledSatelliteFlag()) {
return UNSUPPORTED_ON_DEVICE;
}
if (mSatelliteManager == null) {
return UNSUPPORTED_ON_DEVICE;
}
final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
final boolean isSatelliteAttachSupported = carrierConfig.getBoolean(
KEY_SATELLITE_ATTACH_SUPPORTED_BOOL);
boolean isSatelliteSosSupported = false;
if (Flags.satelliteOemSettingsUxMigration()) {
isSatelliteSosSupported = carrierConfig.getBoolean(
KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
}
return (isSatelliteAttachSupported || isSatelliteSosSupported)
? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public void onResume(@NonNull LifecycleOwner owner) {
if (Flags.satelliteOemSettingsUxMigration()) {
mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(),
mCarrierRoamingNtnModeCallback);
}
}
@Override
public void onPause(@NonNull LifecycleOwner owner) {
if (Flags.satelliteOemSettingsUxMigration()) {
mTelephonyManager.unregisterTelephonyCallback(mCarrierRoamingNtnModeCallback);
}
}
@VisibleForTesting
class CarrierRoamingNtnModeCallback extends TelephonyCallback implements
TelephonyCallback.CarrierRoamingNtnModeListener {
@Override
public void onCarrierRoamingNtnAvailableServicesChanged(int[] availableServices) {
CarrierRoamingNtnModeListener.super.onCarrierRoamingNtnAvailableServicesChanged(
availableServices);
List<Integer> availableServicesList = Arrays.stream(availableServices).boxed().toList();
boolean isSmsAvailable = availableServicesList.contains(SERVICE_TYPE_SMS);
boolean isDataAvailable = availableServicesList.contains(SERVICE_TYPE_DATA);
Log.i(TAG, "isSmsAvailable : " + isSmsAvailable
+ " / isDataAvailable " + isDataAvailable);
if (mPreferenceCategory == null) {
Log.d(TAG, "Satellite preference category is not initialized yet");
return;
}
if (isDataAvailable) {
mPreferenceCategory.setTitle(R.string.category_title_satellite_connectivity);
} else if (isSmsAvailable) {
mPreferenceCategory.setTitle(R.string.satellite_setting_title);
}
}
@Override
public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
// Do nothing
}
@Override
public void onCarrierRoamingNtnModeChanged(boolean active) {
// Do nothing
}
@Override
public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
// Do nothing
}
}
}

View File

@@ -23,188 +23,6 @@ import android.telephony.TelephonyManager;
*/
public class TelephonyConstants {
/**
* Copied from {@link android.telephony.TelephonyManager}
*/
public static class TelephonyManagerConstants {
// Network modes are in turn copied from RILConstants
// with one difference: NETWORK_MODE_CDMA is named NETWORK_MODE_CDMA_EVDO
public static final int NETWORK_MODE_UNKNOWN = -1;
/**
* GSM, WCDMA (WCDMA preferred)
*/
public static final int NETWORK_MODE_WCDMA_PREF = 0;
/**
* GSM only
*/
public static final int NETWORK_MODE_GSM_ONLY = 1;
/**
* WCDMA only
*/
public static final int NETWORK_MODE_WCDMA_ONLY = 2;
/**
* GSM, WCDMA (auto mode, according to PRL)
*/
public static final int NETWORK_MODE_GSM_UMTS = 3;
/**
* CDMA and EvDo (auto mode, according to PRL)
* this is NETWORK_MODE_CDMA in RILConstants.java
*/
public static final int NETWORK_MODE_CDMA_EVDO = 4;
/**
* CDMA only
*/
public static final int NETWORK_MODE_CDMA_NO_EVDO = 5;
/**
* EvDo only
*/
public static final int NETWORK_MODE_EVDO_NO_CDMA = 6;
/**
* GSM, WCDMA, CDMA, and EvDo (auto mode, according to PRL)
*/
public static final int NETWORK_MODE_GLOBAL = 7;
/**
* LTE, CDMA and EvDo
*/
public static final int NETWORK_MODE_LTE_CDMA_EVDO = 8;
/**
* LTE, GSM and WCDMA
*/
public static final int NETWORK_MODE_LTE_GSM_WCDMA = 9;
/**
* LTE, CDMA, EvDo, GSM, and WCDMA
*/
public static final int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = 10;
/**
* LTE only mode.
*/
public static final int NETWORK_MODE_LTE_ONLY = 11;
/**
* LTE and WCDMA
*/
public static final int NETWORK_MODE_LTE_WCDMA = 12;
/**
* TD-SCDMA only
*/
public static final int NETWORK_MODE_TDSCDMA_ONLY = 13;
/**
* TD-SCDMA and WCDMA
*/
public static final int NETWORK_MODE_TDSCDMA_WCDMA = 14;
/**
* LTE and TD-SCDMA
*/
public static final int NETWORK_MODE_LTE_TDSCDMA = 15;
/**
* TD-SCDMA and GSM
*/
public static final int NETWORK_MODE_TDSCDMA_GSM = 16;
/**
* TD-SCDMA, GSM and LTE
*/
public static final int NETWORK_MODE_LTE_TDSCDMA_GSM = 17;
/**
* TD-SCDMA, GSM and WCDMA
*/
public static final int NETWORK_MODE_TDSCDMA_GSM_WCDMA = 18;
/**
* LTE, TD-SCDMA and WCDMA
*/
public static final int NETWORK_MODE_LTE_TDSCDMA_WCDMA = 19;
/**
* LTE, TD-SCDMA, GSM, and WCDMA
*/
public static final int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA = 20;
/**
* TD-SCDMA, CDMA, EVDO, GSM and WCDMA
*/
public static final int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 21;
/**
* LTE, TDCSDMA, CDMA, EVDO, GSM and WCDMA
*/
public static final int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22;
/**
* NR 5G only mode
*/
public static final int NETWORK_MODE_NR_ONLY = 23;
/**
* NR 5G, LTE
*/
public static final int NETWORK_MODE_NR_LTE = 24;
/**
* NR 5G, LTE, CDMA and EvDo
*/
public static final int NETWORK_MODE_NR_LTE_CDMA_EVDO = 25;
/**
* NR 5G, LTE, GSM and WCDMA
*/
public static final int NETWORK_MODE_NR_LTE_GSM_WCDMA = 26;
/**
* NR 5G, LTE, CDMA, EvDo, GSM and WCDMA
*/
public static final int NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA = 27;
/**
* NR 5G, LTE and WCDMA
*/
public static final int NETWORK_MODE_NR_LTE_WCDMA = 28;
/**
* NR 5G, LTE and TDSCDMA
*/
public static final int NETWORK_MODE_NR_LTE_TDSCDMA = 29;
/**
* NR 5G, LTE, TD-SCDMA and GSM
*/
public static final int NETWORK_MODE_NR_LTE_TDSCDMA_GSM = 30;
/**
* NR 5G, LTE, TD-SCDMA, WCDMA
*/
public static final int NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA = 31;
/**
* NR 5G, LTE, TD-SCDMA, GSM and WCDMA
*/
public static final int NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA = 32;
/**
* NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA
*/
public static final int NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 33;
}
/**
* Copied from {@link android.telephony.RadioAccessFamily}
*/

View File

@@ -557,15 +557,17 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
Log.d(TAG, "Hardware does not support DSDS.");
return false;
}
boolean isActiveSim = SubscriptionUtil.getActiveSubscriptions(
boolean anyActiveSim = SubscriptionUtil.getActiveSubscriptions(
mSubscriptionManager).size() > 0;
if (isMultipleEnabledProfilesSupported() && isActiveSim) {
if (isMultipleEnabledProfilesSupported() && anyActiveSim) {
Log.d(TAG,
"Device supports MEP and eSIM operation and eSIM profile is enabled."
+ " DSDS condition satisfied.");
return true;
}
boolean isRemovableSimEnabled = isRemovableSimEnabled();
boolean isRemovableSimEnabled =
SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager).stream()
.anyMatch(subInfo-> !subInfo.isEmbedded());
if (mIsEsimOperation && isRemovableSimEnabled) {
Log.d(TAG, "eSIM operation and removable SIM is enabled. DSDS condition satisfied.");
return true;
@@ -583,7 +585,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
}
private boolean isRemovableSimEnabled() {
return new UiccSlotRepository(mTelMgr).anyRemovablePhysicalSimEnabled();
return new UiccSlotRepository(mTelMgr).anyRemovablePhysicalSimSlotActiveAndInserted();
}
private boolean isMultipleEnabledProfilesSupported() {

View File

@@ -22,17 +22,17 @@ import android.util.Log
class UiccSlotRepository(private val telephonyManager: TelephonyManager?) {
/** Returns whether any removable physical sim is enabled. */
fun anyRemovablePhysicalSimEnabled(): Boolean {
/** Returns whether any removable physical sim slot is active and the sim is inserted. */
fun anyRemovablePhysicalSimSlotActiveAndInserted(): Boolean {
val result =
telephonyManager?.uiccSlotsInfo?.any { uiccSlotInfo: UiccSlotInfo? ->
uiccSlotInfo.isRemovablePhysicalSimEnabled()
uiccSlotInfo.isRemovablePhysicalSimSlotActiveAndInserted()
} ?: false
Log.i(TAG, "anyRemovablePhysicalSimEnabled: $result")
return result
}
private fun UiccSlotInfo?.isRemovablePhysicalSimEnabled(): Boolean {
private fun UiccSlotInfo?.isRemovablePhysicalSimSlotActiveAndInserted(): Boolean {
return this != null &&
isRemovable &&
!isEuicc &&

View File

@@ -44,12 +44,12 @@ constructor(
context: Context,
key: String,
private val callStateRepository: CallStateRepository = CallStateRepository(context),
private val videoCallingRepository: VideoCallingRepository = VideoCallingRepository(context),
) : TogglePreferenceController(context, key), On4gLteUpdateListener {
private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
private var preference: TwoStatePreference? = null
private var callingPreferenceCategoryController: CallingPreferenceCategoryController? = null
private val repository = VideoCallingRepository(context)
private var videoCallEditable = false
private var isInCall = false
@@ -71,14 +71,18 @@ constructor(
override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)
preference = screen.findPreference(preferenceKey)
Log.d(TAG, "init ui")
preference?.isVisible = false
callingPreferenceCategoryController?.updateChildVisible(preferenceKey, false)
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
repository.isVideoCallReadyFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
isReady ->
preference?.isVisible = isReady
callingPreferenceCategoryController?.updateChildVisible(preferenceKey, isReady)
}
videoCallingRepository.isVideoCallReadyFlow(subId)
.collectLatestWithLifecycle(viewLifecycleOwner) { isReady ->
Log.d(TAG, "isVideoCallReadyFlow: update visible")
preference?.isVisible = isReady
callingPreferenceCategoryController?.updateChildVisible(preferenceKey, isReady)
}
callStateRepository.callStateFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
callState ->
isInCall = callState != TelephonyManager.CALL_STATE_IDLE
@@ -129,10 +133,10 @@ constructor(
class VideoCallingSearchItem(private val context: Context) :
MobileNetworkSettingsSearchItem {
private val repository = VideoCallingRepository(context)
private val videoCallingRepository = VideoCallingRepository(context)
private fun isAvailable(subId: Int): Boolean = runBlocking {
repository.isVideoCallReadyFlow(subId).first()
videoCallingRepository.isVideoCallReadyFlow(subId).first()
}
override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {

View File

@@ -16,20 +16,20 @@
package com.android.settings.network.telephony.cdma;
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA;
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_UNKNOWN;
import static android.telephony.TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA;
import static android.telephony.TelephonyManager.NETWORK_MODE_NR_LTE_GSM_WCDMA;
import static com.android.settings.network.telephony.mode.NetworkModes.NETWORK_MODE_UNKNOWN;
import android.content.Context;
import android.provider.Settings;
import android.telephony.RadioAccessFamily;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import com.android.settings.network.telephony.MobileNetworkUtils;
/**
* Preference controller for "System Select"
*/
@@ -65,7 +65,7 @@ public class CdmaSystemSelectPreferenceController extends CdmaBasePreferenceCont
}
final int settingsNetworkMode =
hasTelephonyMgr ? MobileNetworkUtils.getNetworkTypeFromRaf(
hasTelephonyMgr ? RadioAccessFamily.getNetworkTypeFromRaf(
(int) mTelephonyManager.getAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER))
: NETWORK_MODE_UNKNOWN;

View File

@@ -25,18 +25,22 @@ import android.telephony.CarrierConfigManager
import android.telephony.ServiceState
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.satellite.SatelliteManager
import android.telephony.satellite.SatelliteModemStateCallback
import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback
import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.Settings.NetworkSelectActivity
import com.android.settings.flags.Flags
import com.android.settings.network.CarrierConfigCache
import com.android.settings.network.telephony.MobileNetworkUtils
import com.android.settings.network.telephony.allowedNetworkTypesFlow
@@ -46,8 +50,6 @@ import com.android.settingslib.spa.framework.compose.OverridableFlow
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import kotlin.properties.Delegates.notNull
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
@@ -59,6 +61,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.time.Duration.Companion.seconds
/**
* Preference controller for "Auto Select Network"
@@ -73,9 +76,14 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
private val getConfigForSubId: (subId: Int) -> PersistableBundle = { subId ->
CarrierConfigCache.getInstance(context).getConfigForSubId(subId)
},
) : ComposePreferenceController(context, key) {
) : ComposePreferenceController(context, key), DefaultLifecycleObserver {
private var isSatelliteSessionStarted = false
private var isSelectedSubIdForSatellite = false
private lateinit var telephonyManager: TelephonyManager
private val satelliteManager: SatelliteManager? =
context.getSystemService(SatelliteManager::class.java)
private val listeners = mutableListOf<OnNetworkSelectModeListener>()
@VisibleForTesting
@@ -83,6 +91,21 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
val satelliteModemStateCallback = SatelliteModemStateCallback { state ->
isSatelliteSessionStarted = when (state) {
SatelliteManager.SATELLITE_MODEM_STATE_OFF,
SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE,
SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN -> false
else -> true
}
}
val selectedNbIotSatelliteSubscriptionCallback =
SelectedNbIotSatelliteSubscriptionCallback { selectedSubId ->
isSelectedSubIdForSatellite = selectedSubId == subId
}
/**
* Initialization based on given subscription id.
*/
@@ -90,7 +113,6 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
this.subId = subId
telephonyManager = mContext.getSystemService(TelephonyManager::class.java)!!
.createForSubscriptionId(subId)
return this
}
@@ -117,7 +139,10 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
SwitchPreference(object : SwitchPreferenceModel {
override val title = stringResource(R.string.select_automatically)
override val summary = { disallowedSummary }
override val changeable = { disallowedSummary.isEmpty() }
override val changeable = {
disallowedSummary.isEmpty()
&& !(isSatelliteSessionStarted && isSelectedSubIdForSatellite)
}
override val checked = { isAuto }
override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
if (newChecked) {
@@ -132,6 +157,38 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
})
}
override fun onStart(owner: LifecycleOwner) {
if (Flags.satelliteOemSettingsUxMigration()) {
if (satelliteManager != null) {
try {
satelliteManager.registerForModemStateChanged(
mContext.mainExecutor, satelliteModemStateCallback
)
satelliteManager.registerForSelectedNbIotSatelliteSubscriptionChanged(
mContext.mainExecutor, selectedNbIotSatelliteSubscriptionCallback
)
} catch (e: IllegalStateException) {
Log.w(TAG, "IllegalStateException $e")
}
}
}
}
override fun onStop(owner: LifecycleOwner) {
if (Flags.satelliteOemSettingsUxMigration()) {
if (satelliteManager != null) {
try {
satelliteManager.unregisterForModemStateChanged(satelliteModemStateCallback)
satelliteManager.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
selectedNbIotSatelliteSubscriptionCallback
)
} catch (e: IllegalStateException) {
Log.w(TAG, "IllegalStateException $e")
}
}
}
}
private suspend fun getDisallowedSummary(serviceState: ServiceState): String =
withContext(Dispatchers.Default) {
if (!serviceState.roaming && onlyAutoSelectInHome()) {
@@ -213,6 +270,8 @@ class AutoSelectPreferenceController @JvmOverloads constructor(
}
companion object {
private const val TAG = "AutoSelectPreferenceController"
private val MINIMUM_DIALOG_TIME = 1.seconds
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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.mode
import android.telephony.TelephonyManager
import com.google.common.collect.ImmutableBiMap
/** Network mode related utilities. */
object NetworkModes {
const val NETWORK_MODE_UNKNOWN = -1
private val LteToNrNetworkModeMap =
ImmutableBiMap.builder<Int, Int>()
.put(TelephonyManager.NETWORK_MODE_LTE_ONLY, TelephonyManager.NETWORK_MODE_NR_LTE)
.put(
TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO,
TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO,
)
.put(
TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA,
TelephonyManager.NETWORK_MODE_NR_LTE_GSM_WCDMA,
)
.put(
TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA,
TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA,
)
.put(
TelephonyManager.NETWORK_MODE_LTE_WCDMA,
TelephonyManager.NETWORK_MODE_NR_LTE_WCDMA,
)
.put(
TelephonyManager.NETWORK_MODE_LTE_TDSCDMA,
TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA,
)
.put(
TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM,
TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM,
)
.put(
TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_WCDMA,
TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA,
)
.put(
TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA,
TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA,
)
.put(
TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA,
TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA,
)
.build()
/**
* Transforms LTE network mode to 5G network mode.
*
* @param networkMode an LTE network mode without 5G.
* @return the corresponding network mode with 5G.
*/
@JvmStatic
fun addNrToLteNetworkMode(networkMode: Int): Int =
LteToNrNetworkModeMap.getOrElse(networkMode) { networkMode }
/**
* Transforms NR5G network mode to LTE network mode.
*
* @param networkMode an 5G network mode.
* @return the corresponding network mode without 5G.
*/
@JvmStatic
fun reduceNrToLteNetworkMode(networkMode: Int): Int =
LteToNrNetworkModeMap.inverse().getOrElse(networkMode) { networkMode }
}

View File

@@ -0,0 +1,226 @@
/*
* 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.tether
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothPan
import android.bluetooth.BluetoothProfile
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.TetheringManager
import android.os.Handler
import android.os.Looper
import com.android.settings.R
import com.android.settings.datausage.DataSaverBackend
import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.datastore.KeyedDataObservable
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceLifecycleContext
import com.android.settingslib.metadata.PreferenceLifecycleProvider
import com.android.settingslib.metadata.ReadWritePermit
import com.android.settingslib.metadata.SensitivityLevel
import com.android.settingslib.metadata.SwitchPreference
import java.util.concurrent.atomic.AtomicReference
// LINT.IfChange
@Suppress("DEPRECATION")
class BluetoothTetherSwitchPreference :
SwitchPreference(KEY, R.string.bluetooth_tether_checkbox_text),
PreferenceAvailabilityProvider,
PreferenceLifecycleProvider {
private var tetherChangeReceiver: BroadcastReceiver? = null
override val summary: Int
get() = R.string.bluetooth_tethering_subtext
override val keywords: Int
get() = R.string.keywords_hotspot_tethering
override fun storage(context: Context): KeyValueStore = BluetoothTetherStore(context)
override fun isAvailable(context: Context): Boolean {
BluetoothAdapter.getDefaultAdapter() ?: return false
val tetheringManager = context.getSystemService(TetheringManager::class.java)
val bluetoothRegexs = tetheringManager?.tetherableBluetoothRegexs
return bluetoothRegexs?.isNotEmpty() == true
}
override fun isEnabled(context: Context): Boolean {
val adapter = BluetoothAdapter.getDefaultAdapter() ?: return false
val btState = adapter.state
/* TODO: when bluetooth is off, btstate will be `state_turning_on` -> `state_off` ->
`state_turning_on` -> `state_on`, causing preference enable status incorrect. */
when (btState) {
BluetoothAdapter.STATE_TURNING_OFF,
BluetoothAdapter.STATE_TURNING_ON -> return false
else -> {}
}
val dataSaverBackend = DataSaverBackend(context)
return !dataSaverBackend.isDataSaverEnabled
}
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override val sensitivityLevel: Int
get() = SensitivityLevel.LOW_SENSITIVITY
override fun onCreate(context: PreferenceLifecycleContext) {
val receiver =
object : BroadcastReceiver() {
override fun onReceive(content: Context, intent: Intent) {
when (intent.action) {
TetheringManager.ACTION_TETHER_STATE_CHANGED,
Intent.ACTION_MEDIA_SHARED,
Intent.ACTION_MEDIA_UNSHARED,
BluetoothAdapter.ACTION_STATE_CHANGED,
BluetoothPan.ACTION_TETHERING_STATE_CHANGED ->
context.notifyPreferenceChange(KEY)
}
}
}
tetherChangeReceiver = receiver
var filter = IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)
val intent = context.registerReceiver(receiver, filter)
filter = IntentFilter()
filter.addAction(Intent.ACTION_MEDIA_SHARED)
filter.addAction(Intent.ACTION_MEDIA_UNSHARED)
filter.addDataScheme("file")
context.registerReceiver(receiver, filter)
filter = IntentFilter()
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
filter.addAction(BluetoothPan.ACTION_TETHERING_STATE_CHANGED)
context.registerReceiver(receiver, filter)
}
override fun onDestroy(context: PreferenceLifecycleContext) {
tetherChangeReceiver?.let {
context.unregisterReceiver(it)
tetherChangeReceiver = null
}
}
@Suppress("UNCHECKED_CAST")
private class BluetoothTetherStore(private val context: Context) :
KeyedDataObservable<String>(), KeyValueStore {
val bluetoothPan = AtomicReference<BluetoothPan>()
override fun contains(key: String) = key == KEY
override fun <T : Any> getValue(key: String, valueType: Class<T>): T? {
// TODO: support async operation in background thread
val adapter = BluetoothAdapter.getDefaultAdapter() ?: return false as T
if (bluetoothPan.get() == null) {
val profileServiceListener: BluetoothProfile.ServiceListener =
object : BluetoothProfile.ServiceListener {
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
if (bluetoothPan.get() == null) {
bluetoothPan.set(proxy as BluetoothPan)
notifyChange(KEY, 0)
}
}
override fun onServiceDisconnected(profile: Int) {
/* Do nothing */
}
}
// TODO: adapter.closeProfileProxy(bluetoothPan.get())
adapter.getProfileProxy(
context.applicationContext,
profileServiceListener,
BluetoothProfile.PAN,
)
}
val btState = adapter.state
val pan = bluetoothPan.get()
return ((btState == BluetoothAdapter.STATE_ON ||
btState == BluetoothAdapter.STATE_TURNING_OFF) && pan != null && pan.isTetheringOn)
as T?
}
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
if (value == null) return
val connectivityManager =
context.getSystemService(ConnectivityManager::class.java) ?: return
if (value as Boolean) {
val handler by lazy { Handler(Looper.getMainLooper()) }
val startTetheringCallback = OnStartTetheringCallback()
fun startTethering() {
connectivityManager.startTethering(
ConnectivityManager.TETHERING_BLUETOOTH,
true,
startTetheringCallback,
handler,
)
}
val adapter = BluetoothAdapter.getDefaultAdapter()
if (adapter.state == BluetoothAdapter.STATE_OFF) {
adapter.enable()
val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
val tetherChangeReceiver =
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (
intent.getIntExtra(
BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR,
) == BluetoothAdapter.STATE_ON
) {
startTethering()
context.unregisterReceiver(this)
}
}
}
val intent = context.registerReceiver(tetherChangeReceiver, filter)
if (intent != null) tetherChangeReceiver.onReceive(context, intent)
} else {
startTethering()
}
} else {
connectivityManager.stopTethering(ConnectivityManager.TETHERING_BLUETOOTH)
}
}
private inner class OnStartTetheringCallback :
ConnectivityManager.OnStartTetheringCallback() {
override fun onTetheringStarted() {
notifyChange(KEY, 0)
}
override fun onTetheringFailed() {
notifyChange(KEY, 0)
}
}
}
companion object {
const val KEY = "enable_bluetooth_tethering"
}
}
// LINT.ThenChange(TetherSettings.java)

View File

@@ -0,0 +1,87 @@
/*
* 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.tether
import android.content.Context
import android.net.TetheringManager
import android.os.UserManager
import com.android.settings.PreferenceRestrictionMixin
import com.android.settings.R
import com.android.settings.Settings.TetherSettingsActivity
import com.android.settings.datausage.DataSaverMainSwitchPreference
import com.android.settings.flags.Flags
import com.android.settings.network.TetherPreferenceController
import com.android.settings.utils.makeLaunchIntent
import com.android.settings.wifi.tether.WifiHotspotSwitchPreference
import com.android.settingslib.TetherUtil
import com.android.settingslib.Utils
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceTitleProvider
import com.android.settingslib.metadata.ProvidePreferenceScreen
import com.android.settingslib.metadata.preferenceHierarchy
import com.android.settingslib.preference.PreferenceScreenCreator
@ProvidePreferenceScreen
class TetherScreen :
PreferenceScreenCreator,
PreferenceTitleProvider,
PreferenceAvailabilityProvider,
PreferenceRestrictionMixin {
override val key: String
get() = KEY
override val icon: Int
get() = R.drawable.ic_wifi_tethering
override val keywords: Int
get() = R.string.keywords_hotspot_tethering
override fun getTitle(context: Context): CharSequence? =
if (TetherPreferenceController.isTetherConfigDisallowed(context)) {
context.getText(R.string.tether_settings_title_all)
} else {
val tetheringManager = context.getSystemService(TetheringManager::class.java)!!
context.getText(Utils.getTetheringLabel(tetheringManager))
}
override fun isAvailable(context: Context) = TetherUtil.isTetherAvailable(context)
override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context)
override val restrictionKeys
get() = arrayOf(UserManager.DISALLOW_CONFIG_TETHERING)
override fun isFlagEnabled(context: Context) = Flags.catalystTetherSettings()
override fun hasCompleteHierarchy() = false
override fun fragmentClass() = TetherSettings::class.java
override fun getLaunchIntent(context: Context, metadata: PreferenceMetadata?) =
makeLaunchIntent(context, TetherSettingsActivity::class.java, metadata?.key)
override fun getPreferenceHierarchy(context: Context) =
preferenceHierarchy(this) {
val dataSaverStore = DataSaverMainSwitchPreference.createDataStore(context)
+WifiHotspotSwitchPreference(context, dataSaverStore)
}
companion object {
const val KEY = "tether_settings"
}
}

View File

@@ -48,14 +48,15 @@ import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.ViewModelProvider;
import androidx.preference.Preference;
import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.Utils;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.datausage.DataSaverBackend;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.wifi.tether.WifiTetherPreferenceController;
@@ -71,11 +72,12 @@ import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
// LINT.IfChange
/**
* Displays preferences for Tethering.
*/
@SearchIndexable
public class TetherSettings extends RestrictedSettingsFragment
public class TetherSettings extends RestrictedDashboardFragment
implements DataSaverBackend.Listener {
@VisibleForTesting
@@ -143,11 +145,20 @@ public class TetherSettings extends RestrictedSettingsFragment
super(UserManager.DISALLOW_CONFIG_TETHERING);
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.tether_prefs;
}
@SuppressWarnings("NullAway")
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Even when the UI is restricted, addPreferencesFromResource cannot be omitted.
addPreferencesFromResource(R.xml.tether_prefs);
setIfOnlyAvailableForAdmins(true);
if (isUiRestricted()) {
return;
@@ -194,18 +205,23 @@ public class TetherSettings extends RestrictedSettingsFragment
getPreferenceScreen().removePreference(mUsbTether);
}
mWifiTetherPreferenceController.displayPreference(getPreferenceScreen());
if (!isCatalystEnabled() && mWifiTetherPreferenceController != null) {
mWifiTetherPreferenceController.displayPreference(getPreferenceScreen());
}
if (!bluetoothAvailable) {
getPreferenceScreen().removePreference(mBluetoothTether);
} else {
BluetoothPan pan = mBluetoothPan.get();
if (pan != null && pan.isTetheringOn()) {
mBluetoothTether.setChecked(true);
if (!isCatalystEnabled()) {
if (!bluetoothAvailable) {
mBluetoothTether.setVisible(false);
} else {
mBluetoothTether.setChecked(false);
BluetoothPan pan = mBluetoothPan.get();
if (pan != null && pan.isTetheringOn()) {
mBluetoothTether.setChecked(true);
} else {
mBluetoothTether.setChecked(false);
}
}
}
if (!ethernetAvailable) getPreferenceScreen().removePreference(mEthernetTether);
// Set initial state based on Data Saver mode.
onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled());
@@ -214,8 +230,10 @@ public class TetherSettings extends RestrictedSettingsFragment
@VisibleForTesting
void setupViewModel() {
TetheringManagerModel model = new ViewModelProvider(this).get(TetheringManagerModel.class);
mWifiTetherPreferenceController =
new WifiTetherPreferenceController(getContext(), getSettingsLifecycle(), model);
if (!isCatalystEnabled()) {
mWifiTetherPreferenceController =
new WifiTetherPreferenceController(getContext(), getSettingsLifecycle(), model);
}
mTm = model.getTetheringManager();
model.getTetheredInterfaces().observe(this, this::onTetheredInterfacesChanged);
}
@@ -252,9 +270,13 @@ public class TetherSettings extends RestrictedSettingsFragment
@Override
public void onDataSaverChanged(boolean isDataSaving) {
mDataSaverEnabled = isDataSaving;
mWifiTetherPreferenceController.setDataSaverEnabled(mDataSaverEnabled);
if (!isCatalystEnabled()) {
mWifiTetherPreferenceController.setDataSaverEnabled(mDataSaverEnabled);
}
mUsbTether.setEnabled(!mDataSaverEnabled);
mBluetoothTether.setEnabled(!mDataSaverEnabled);
if (!isCatalystEnabled()) {
mBluetoothTether.setEnabled(!mDataSaverEnabled);
}
mEthernetTether.setEnabled(!mDataSaverEnabled);
mDataSaverFooter.setVisible(mDataSaverEnabled);
}
@@ -504,6 +526,8 @@ public class TetherSettings extends RestrictedSettingsFragment
}
private void updateBluetoothState() {
if (isCatalystEnabled()) return;
final int btState = getBluetoothState();
if (DEBUG) {
Log.d(TAG, "updateBluetoothState() btState : " + btState);
@@ -559,7 +583,7 @@ public class TetherSettings extends RestrictedSettingsFragment
}
private void startTethering(int choice) {
if (choice == TETHERING_BLUETOOTH) {
if (choice == TETHERING_BLUETOOTH && !isCatalystEnabled()) {
// Turn on Bluetooth first.
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
@@ -581,7 +605,7 @@ public class TetherSettings extends RestrictedSettingsFragment
} else {
mCm.stopTethering(TETHERING_USB);
}
} else if (preference == mBluetoothTether) {
} else if (preference == mBluetoothTether && !isCatalystEnabled()) {
if (mBluetoothTether.isChecked()) {
startTethering(TETHERING_BLUETOOTH);
} else {
@@ -723,4 +747,10 @@ public class TetherSettings extends RestrictedSettingsFragment
}
updateBluetoothAndEthernetState();
}
@Override
public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
return TetherScreen.KEY;
}
}
// LINT.ThenChange(BluetoothTetherSwitchPreference.kt)