Snap for 12565212 from f201899e7c
to 25Q1-release
Change-Id: Id37b31cdeb0482a31e4b467c4d3a62a14a1992a9
This commit is contained in:
@@ -421,11 +421,13 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
|||||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||||
List<String> invisibleProfiles = List.of();
|
List<String> invisibleProfiles = List.of();
|
||||||
if (Flags.enableBluetoothDeviceDetailsPolish()) {
|
if (Flags.enableBluetoothDeviceDetailsPolish()) {
|
||||||
mFormatter =
|
if (mFormatter == null) {
|
||||||
FeatureFactory.getFeatureFactory()
|
mFormatter =
|
||||||
.getBluetoothFeatureProvider()
|
FeatureFactory.getFeatureFactory()
|
||||||
.getDeviceDetailsFragmentFormatter(
|
.getBluetoothFeatureProvider()
|
||||||
requireContext(), this, mBluetoothAdapter, mCachedDevice);
|
.getDeviceDetailsFragmentFormatter(
|
||||||
|
requireContext(), this, mBluetoothAdapter, mCachedDevice);
|
||||||
|
}
|
||||||
invisibleProfiles =
|
invisibleProfiles =
|
||||||
mFormatter.getInvisibleBluetoothProfiles(
|
mFormatter.getInvisibleBluetoothProfiles(
|
||||||
FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE);
|
FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE);
|
||||||
|
@@ -25,7 +25,6 @@ import android.media.Spatializer;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.LifecycleCoroutineScope;
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import com.android.settings.SettingsPreferenceFragment;
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
@@ -34,12 +33,12 @@ import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter;
|
|||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository;
|
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository;
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/** Provider for bluetooth related features. */
|
||||||
* Provider for bluetooth related features.
|
|
||||||
*/
|
|
||||||
public interface BluetoothFeatureProvider {
|
public interface BluetoothFeatureProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,26 +85,25 @@ public interface BluetoothFeatureProvider {
|
|||||||
/**
|
/**
|
||||||
* Gets the bluetooth profile preference keys which should be hidden in the device details page.
|
* Gets the bluetooth profile preference keys which should be hidden in the device details page.
|
||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param bluetoothDevice the bluetooth device
|
* @param bluetoothDevice the bluetooth device
|
||||||
* @return the profiles which should be hidden
|
* @return the profiles which should be hidden
|
||||||
*/
|
*/
|
||||||
Set<String> getInvisibleProfilePreferenceKeys(
|
Set<String> getInvisibleProfilePreferenceKeys(Context context, BluetoothDevice bluetoothDevice);
|
||||||
Context context, BluetoothDevice bluetoothDevice);
|
|
||||||
|
|
||||||
/** Gets DeviceSettingRepository. */
|
/** Gets DeviceSettingRepository. */
|
||||||
@NonNull
|
@NonNull
|
||||||
DeviceSettingRepository getDeviceSettingRepository(
|
DeviceSettingRepository getDeviceSettingRepository(
|
||||||
@NonNull Context context,
|
@NonNull Context context,
|
||||||
@NonNull BluetoothAdapter bluetoothAdapter,
|
@NonNull BluetoothAdapter bluetoothAdapter,
|
||||||
@NonNull LifecycleCoroutineScope scope);
|
@NonNull CoroutineScope scope);
|
||||||
|
|
||||||
/** Gets spatial audio interactor. */
|
/** Gets spatial audio interactor. */
|
||||||
@NonNull
|
@NonNull
|
||||||
SpatialAudioInteractor getSpatialAudioInteractor(
|
SpatialAudioInteractor getSpatialAudioInteractor(
|
||||||
@NonNull Context context,
|
@NonNull Context context,
|
||||||
@NonNull AudioManager audioManager,
|
@NonNull AudioManager audioManager,
|
||||||
@NonNull LifecycleCoroutineScope scope);
|
@NonNull CoroutineScope scope);
|
||||||
|
|
||||||
/** Gets device details fragment layout formatter. */
|
/** Gets device details fragment layout formatter. */
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@@ -22,6 +22,7 @@ import android.content.Context
|
|||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.media.Spatializer
|
import android.media.Spatializer
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
import androidx.lifecycle.LifecycleCoroutineScope
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import com.android.settings.SettingsPreferenceFragment
|
import com.android.settings.SettingsPreferenceFragment
|
||||||
@@ -37,6 +38,7 @@ import com.android.settingslib.media.data.repository.SpatializerRepositoryImpl
|
|||||||
import com.android.settingslib.media.domain.interactor.SpatializerInteractor
|
import com.android.settingslib.media.domain.interactor.SpatializerInteractor
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
/** Impl of [BluetoothFeatureProvider] */
|
/** Impl of [BluetoothFeatureProvider] */
|
||||||
@@ -76,14 +78,14 @@ open class BluetoothFeatureProviderImpl : BluetoothFeatureProvider {
|
|||||||
override fun getDeviceSettingRepository(
|
override fun getDeviceSettingRepository(
|
||||||
context: Context,
|
context: Context,
|
||||||
bluetoothAdapter: BluetoothAdapter,
|
bluetoothAdapter: BluetoothAdapter,
|
||||||
scope: LifecycleCoroutineScope
|
scope: CoroutineScope
|
||||||
): DeviceSettingRepository =
|
): DeviceSettingRepository =
|
||||||
DeviceSettingRepositoryImpl(context, bluetoothAdapter, scope, Dispatchers.IO)
|
DeviceSettingRepositoryImpl(context, bluetoothAdapter, scope, Dispatchers.IO)
|
||||||
|
|
||||||
override fun getSpatialAudioInteractor(
|
override fun getSpatialAudioInteractor(
|
||||||
context: Context,
|
context: Context,
|
||||||
audioManager: AudioManager,
|
audioManager: AudioManager,
|
||||||
scope: LifecycleCoroutineScope
|
scope: CoroutineScope,
|
||||||
): SpatialAudioInteractor {
|
): SpatialAudioInteractor {
|
||||||
return SpatialAudioInteractorImpl(
|
return SpatialAudioInteractorImpl(
|
||||||
context, audioManager,
|
context, audioManager,
|
||||||
|
@@ -147,7 +147,7 @@ class SpatialAudioInteractorImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "SpatialAudioInteractorImpl"
|
private const val TAG = "SpatialAudioInteractor"
|
||||||
private const val INDEX_SPATIAL_AUDIO_OFF = 0
|
private const val INDEX_SPATIAL_AUDIO_OFF = 0
|
||||||
private const val INDEX_SPATIAL_AUDIO_ON = 1
|
private const val INDEX_SPATIAL_AUDIO_ON = 1
|
||||||
private const val INDEX_HEAD_TRACKING_ENABLED = 2
|
private const val INDEX_HEAD_TRACKING_ENABLED = 2
|
||||||
|
@@ -19,11 +19,10 @@ package com.android.settings.bluetooth.ui.view
|
|||||||
import android.bluetooth.BluetoothAdapter
|
import android.bluetooth.BluetoothAdapter
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.media.AudioManager
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.expandVertically
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.shrinkVertically
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -33,14 +32,12 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.SettingsPreferenceFragment
|
import com.android.settings.SettingsPreferenceFragment
|
||||||
@@ -52,7 +49,6 @@ import com.android.settings.bluetooth.ui.model.FragmentTypeModel
|
|||||||
import com.android.settings.bluetooth.ui.view.DeviceDetailsMoreSettingsFragment.Companion.KEY_DEVICE_ADDRESS
|
import com.android.settings.bluetooth.ui.view.DeviceDetailsMoreSettingsFragment.Companion.KEY_DEVICE_ADDRESS
|
||||||
import com.android.settings.bluetooth.ui.viewmodel.BluetoothDeviceDetailsViewModel
|
import com.android.settings.bluetooth.ui.viewmodel.BluetoothDeviceDetailsViewModel
|
||||||
import com.android.settings.core.SubSettingLauncher
|
import com.android.settings.core.SubSettingLauncher
|
||||||
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
|
|
||||||
import com.android.settings.spa.preference.ComposePreference
|
import com.android.settings.spa.preference.ComposePreference
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingActionModel
|
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingActionModel
|
||||||
@@ -97,29 +93,17 @@ interface DeviceDetailsFragmentFormatter {
|
|||||||
class DeviceDetailsFragmentFormatterImpl(
|
class DeviceDetailsFragmentFormatterImpl(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val fragment: SettingsPreferenceFragment,
|
private val fragment: SettingsPreferenceFragment,
|
||||||
bluetoothAdapter: BluetoothAdapter,
|
private val bluetoothAdapter: BluetoothAdapter,
|
||||||
private val cachedDevice: CachedBluetoothDevice,
|
private val cachedDevice: CachedBluetoothDevice,
|
||||||
private val backgroundCoroutineContext: CoroutineContext,
|
private val backgroundCoroutineContext: CoroutineContext,
|
||||||
) : DeviceDetailsFragmentFormatter {
|
) : DeviceDetailsFragmentFormatter {
|
||||||
private val repository =
|
|
||||||
featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
|
|
||||||
fragment.requireActivity().application,
|
|
||||||
bluetoothAdapter,
|
|
||||||
fragment.lifecycleScope,
|
|
||||||
)
|
|
||||||
private val spatialAudioInteractor =
|
|
||||||
featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor(
|
|
||||||
fragment.requireActivity().application,
|
|
||||||
context.getSystemService(AudioManager::class.java),
|
|
||||||
fragment.lifecycleScope,
|
|
||||||
)
|
|
||||||
private val viewModel: BluetoothDeviceDetailsViewModel =
|
private val viewModel: BluetoothDeviceDetailsViewModel =
|
||||||
ViewModelProvider(
|
ViewModelProvider(
|
||||||
fragment,
|
fragment,
|
||||||
BluetoothDeviceDetailsViewModel.Factory(
|
BluetoothDeviceDetailsViewModel.Factory(
|
||||||
fragment.requireActivity().application,
|
fragment.requireActivity().application,
|
||||||
repository,
|
bluetoothAdapter,
|
||||||
spatialAudioInteractor,
|
|
||||||
cachedDevice,
|
cachedDevice,
|
||||||
backgroundCoroutineContext,
|
backgroundCoroutineContext,
|
||||||
),
|
),
|
||||||
@@ -224,8 +208,8 @@ class DeviceDetailsFragmentFormatterImpl(
|
|||||||
val settings = contents
|
val settings = contents
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = settings.isNotEmpty(),
|
visible = settings.isNotEmpty(),
|
||||||
enter = expandVertically(expandFrom = Alignment.Top),
|
enter = fadeIn(),
|
||||||
exit = shrinkVertically(shrinkTowards = Alignment.Top),
|
exit = fadeOut(),
|
||||||
) {
|
) {
|
||||||
Box {
|
Box {
|
||||||
Box(
|
Box(
|
||||||
|
@@ -120,13 +120,15 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
|
|||||||
finish()
|
finish()
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
formatter =
|
if (!this::formatter.isInitialized) {
|
||||||
featureFactory.bluetoothFeatureProvider.getDeviceDetailsFragmentFormatter(
|
formatter =
|
||||||
requireContext(),
|
featureFactory.bluetoothFeatureProvider.getDeviceDetailsFragmentFormatter(
|
||||||
this,
|
requireContext(),
|
||||||
bluetoothManager.adapter,
|
this,
|
||||||
cachedDevice,
|
bluetoothManager.adapter,
|
||||||
)
|
cachedDevice,
|
||||||
|
)
|
||||||
|
}
|
||||||
helpItem =
|
helpItem =
|
||||||
formatter
|
formatter
|
||||||
.getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
.getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
||||||
|
@@ -17,20 +17,22 @@
|
|||||||
package com.android.settings.bluetooth.ui.viewmodel
|
package com.android.settings.bluetooth.ui.viewmodel
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.bluetooth.BluetoothAdapter
|
||||||
|
import android.media.AudioManager
|
||||||
|
import android.util.Log
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor
|
|
||||||
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
|
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
|
||||||
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayoutColumn
|
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayoutColumn
|
||||||
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayoutRow
|
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayoutRow
|
||||||
import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel
|
import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel
|
||||||
import com.android.settings.bluetooth.ui.model.FragmentTypeModel
|
import com.android.settings.bluetooth.ui.model.FragmentTypeModel
|
||||||
|
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
||||||
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
|
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
|
||||||
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository
|
|
||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel
|
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel
|
||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
|
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
|
||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
|
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
|
||||||
@@ -47,12 +49,24 @@ import kotlinx.coroutines.flow.stateIn
|
|||||||
|
|
||||||
class BluetoothDeviceDetailsViewModel(
|
class BluetoothDeviceDetailsViewModel(
|
||||||
private val application: Application,
|
private val application: Application,
|
||||||
private val deviceSettingRepository: DeviceSettingRepository,
|
private val bluetoothAdapter: BluetoothAdapter,
|
||||||
private val spatialAudioInteractor: SpatialAudioInteractor,
|
|
||||||
private val cachedDevice: CachedBluetoothDevice,
|
private val cachedDevice: CachedBluetoothDevice,
|
||||||
backgroundCoroutineContext: CoroutineContext,
|
backgroundCoroutineContext: CoroutineContext,
|
||||||
) : AndroidViewModel(application) {
|
) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
private val deviceSettingRepository =
|
||||||
|
featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
|
||||||
|
application,
|
||||||
|
bluetoothAdapter,
|
||||||
|
viewModelScope,
|
||||||
|
)
|
||||||
|
private val spatialAudioInteractor =
|
||||||
|
featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor(
|
||||||
|
application,
|
||||||
|
application.getSystemService(AudioManager::class.java),
|
||||||
|
viewModelScope,
|
||||||
|
)
|
||||||
|
|
||||||
private val items =
|
private val items =
|
||||||
viewModelScope.async(backgroundCoroutineContext, start = CoroutineStart.LAZY) {
|
viewModelScope.async(backgroundCoroutineContext, start = CoroutineStart.LAZY) {
|
||||||
deviceSettingRepository.getDeviceSettingsConfig(cachedDevice)
|
deviceSettingRepository.getDeviceSettingsConfig(cachedDevice)
|
||||||
@@ -202,8 +216,7 @@ class BluetoothDeviceDetailsViewModel(
|
|||||||
|
|
||||||
class Factory(
|
class Factory(
|
||||||
private val application: Application,
|
private val application: Application,
|
||||||
private val deviceSettingRepository: DeviceSettingRepository,
|
private val bluetoothAdapter: BluetoothAdapter,
|
||||||
private val spatialAudioInteractor: SpatialAudioInteractor,
|
|
||||||
private val cachedDevice: CachedBluetoothDevice,
|
private val cachedDevice: CachedBluetoothDevice,
|
||||||
private val backgroundCoroutineContext: CoroutineContext,
|
private val backgroundCoroutineContext: CoroutineContext,
|
||||||
) : ViewModelProvider.Factory {
|
) : ViewModelProvider.Factory {
|
||||||
@@ -211,8 +224,7 @@ class BluetoothDeviceDetailsViewModel(
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return BluetoothDeviceDetailsViewModel(
|
return BluetoothDeviceDetailsViewModel(
|
||||||
application,
|
application,
|
||||||
deviceSettingRepository,
|
bluetoothAdapter,
|
||||||
spatialAudioInteractor,
|
|
||||||
cachedDevice,
|
cachedDevice,
|
||||||
backgroundCoroutineContext,
|
backgroundCoroutineContext,
|
||||||
)
|
)
|
||||||
|
@@ -74,8 +74,11 @@ class SimOnboardingService {
|
|||||||
}
|
}
|
||||||
var isEsimProfileEnabled: Boolean = false
|
var isEsimProfileEnabled: Boolean = false
|
||||||
get() {
|
get() {
|
||||||
activeSubInfoList.stream().anyMatch { it.isEmbedded }
|
return activeSubInfoList.stream().anyMatch { it.isEmbedded }
|
||||||
return false
|
}
|
||||||
|
var isRemovableSimProfileEnabled: Boolean = false
|
||||||
|
get() {
|
||||||
|
return activeSubInfoList.stream().anyMatch { !it.isEmbedded }
|
||||||
}
|
}
|
||||||
var doesTargetSimActive = false
|
var doesTargetSimActive = false
|
||||||
get() {
|
get() {
|
||||||
@@ -288,8 +291,8 @@ class SimOnboardingService {
|
|||||||
Log.d(TAG, "Hardware does not support DSDS.")
|
Log.d(TAG, "Hardware does not support DSDS.")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val isActiveSim = activeSubInfoList.isNotEmpty()
|
val anyActiveSim = activeSubInfoList.isNotEmpty()
|
||||||
if (isMultipleEnabledProfilesSupported && isActiveSim) {
|
if (isMultipleEnabledProfilesSupported && anyActiveSim) {
|
||||||
Log.d(TAG,
|
Log.d(TAG,
|
||||||
"Device supports MEP and eSIM operation and eSIM profile is enabled."
|
"Device supports MEP and eSIM operation and eSIM profile is enabled."
|
||||||
+ " DSDS condition satisfied."
|
+ " DSDS condition satisfied."
|
||||||
@@ -297,15 +300,13 @@ class SimOnboardingService {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doesTargetSimHaveEsimOperation) {
|
if (doesTargetSimHaveEsimOperation && isRemovableSimProfileEnabled) {
|
||||||
if (UiccSlotRepository(telephonyManager).anyRemovablePhysicalSimEnabled()) {
|
Log.d(TAG,
|
||||||
Log.d(
|
"eSIM operation and removable PSIM is enabled. DSDS condition satisfied."
|
||||||
TAG,
|
)
|
||||||
"eSIM operation and removable PSIM is enabled. DSDS condition satisfied."
|
return true
|
||||||
)
|
}
|
||||||
return true
|
if (!doesTargetSimHaveEsimOperation && isEsimProfileEnabled) {
|
||||||
}
|
|
||||||
} else if (isEsimProfileEnabled) {
|
|
||||||
Log.d(TAG,
|
Log.d(TAG,
|
||||||
"Removable SIM operation and eSIM profile is enabled. DSDS condition"
|
"Removable SIM operation and eSIM profile is enabled. DSDS condition"
|
||||||
+ " satisfied."
|
+ " satisfied."
|
||||||
|
@@ -557,15 +557,17 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
Log.d(TAG, "Hardware does not support DSDS.");
|
Log.d(TAG, "Hardware does not support DSDS.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean isActiveSim = SubscriptionUtil.getActiveSubscriptions(
|
boolean anyActiveSim = SubscriptionUtil.getActiveSubscriptions(
|
||||||
mSubscriptionManager).size() > 0;
|
mSubscriptionManager).size() > 0;
|
||||||
if (isMultipleEnabledProfilesSupported() && isActiveSim) {
|
if (isMultipleEnabledProfilesSupported() && anyActiveSim) {
|
||||||
Log.d(TAG,
|
Log.d(TAG,
|
||||||
"Device supports MEP and eSIM operation and eSIM profile is enabled."
|
"Device supports MEP and eSIM operation and eSIM profile is enabled."
|
||||||
+ " DSDS condition satisfied.");
|
+ " DSDS condition satisfied.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean isRemovableSimEnabled = isRemovableSimEnabled();
|
boolean isRemovableSimEnabled =
|
||||||
|
SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager).stream()
|
||||||
|
.anyMatch(subInfo-> !subInfo.isEmbedded());
|
||||||
if (mIsEsimOperation && isRemovableSimEnabled) {
|
if (mIsEsimOperation && isRemovableSimEnabled) {
|
||||||
Log.d(TAG, "eSIM operation and removable SIM is enabled. DSDS condition satisfied.");
|
Log.d(TAG, "eSIM operation and removable SIM is enabled. DSDS condition satisfied.");
|
||||||
return true;
|
return true;
|
||||||
@@ -583,7 +585,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isRemovableSimEnabled() {
|
private boolean isRemovableSimEnabled() {
|
||||||
return new UiccSlotRepository(mTelMgr).anyRemovablePhysicalSimEnabled();
|
return new UiccSlotRepository(mTelMgr).anyRemovablePhysicalSimSlotActiveAndInserted();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMultipleEnabledProfilesSupported() {
|
private boolean isMultipleEnabledProfilesSupported() {
|
||||||
|
@@ -22,17 +22,17 @@ import android.util.Log
|
|||||||
|
|
||||||
class UiccSlotRepository(private val telephonyManager: TelephonyManager?) {
|
class UiccSlotRepository(private val telephonyManager: TelephonyManager?) {
|
||||||
|
|
||||||
/** Returns whether any removable physical sim is enabled. */
|
/** Returns whether any removable physical sim slot is active and the sim is inserted. */
|
||||||
fun anyRemovablePhysicalSimEnabled(): Boolean {
|
fun anyRemovablePhysicalSimSlotActiveAndInserted(): Boolean {
|
||||||
val result =
|
val result =
|
||||||
telephonyManager?.uiccSlotsInfo?.any { uiccSlotInfo: UiccSlotInfo? ->
|
telephonyManager?.uiccSlotsInfo?.any { uiccSlotInfo: UiccSlotInfo? ->
|
||||||
uiccSlotInfo.isRemovablePhysicalSimEnabled()
|
uiccSlotInfo.isRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
} ?: false
|
} ?: false
|
||||||
Log.i(TAG, "anyRemovablePhysicalSimEnabled: $result")
|
Log.i(TAG, "anyRemovablePhysicalSimEnabled: $result")
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun UiccSlotInfo?.isRemovablePhysicalSimEnabled(): Boolean {
|
private fun UiccSlotInfo?.isRemovablePhysicalSimSlotActiveAndInserted(): Boolean {
|
||||||
return this != null &&
|
return this != null &&
|
||||||
isRemovable &&
|
isRemovable &&
|
||||||
!isEuicc &&
|
!isEuicc &&
|
||||||
|
@@ -40,6 +40,7 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.Utils;
|
||||||
import com.android.settingslib.PrimarySwitchPreference;
|
import com.android.settingslib.PrimarySwitchPreference;
|
||||||
import com.android.settingslib.notification.modes.ZenMode;
|
import com.android.settingslib.notification.modes.ZenMode;
|
||||||
import com.android.settingslib.notification.modes.ZenModesBackend;
|
import com.android.settingslib.notification.modes.ZenModesBackend;
|
||||||
@@ -108,7 +109,9 @@ class ZenModeTriggerUpdatePreferenceController extends AbstractZenModePreference
|
|||||||
tryParseScheduleConditionId(mode.getRule().getConditionId());
|
tryParseScheduleConditionId(mode.getRule().getConditionId());
|
||||||
if (schedule != null) {
|
if (schedule != null) {
|
||||||
preference.setTitle(SystemZenRules.getTimeSummary(mContext, schedule));
|
preference.setTitle(SystemZenRules.getTimeSummary(mContext, schedule));
|
||||||
preference.setSummary(SystemZenRules.getShortDaysSummary(mContext, schedule));
|
preference.setSummary(Utils.createAccessibleSequence(
|
||||||
|
SystemZenRules.getDaysOfWeekShort(mContext, schedule),
|
||||||
|
SystemZenRules.getDaysOfWeekFull(mContext, schedule)));
|
||||||
} else {
|
} else {
|
||||||
// Fallback, but shouldn't happen.
|
// Fallback, but shouldn't happen.
|
||||||
Log.wtf(TAG, "SCHEDULE_TIME mode without schedule: " + mode);
|
Log.wtf(TAG, "SCHEDULE_TIME mode without schedule: " + mode);
|
||||||
|
@@ -57,6 +57,9 @@ public class WifiTetherSwitchBarController implements
|
|||||||
private final ConnectivityManager mConnectivityManager;
|
private final ConnectivityManager mConnectivityManager;
|
||||||
private final WifiManager mWifiManager;
|
private final WifiManager mWifiManager;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean mIsSwitchBusy;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
DataSaverBackend mDataSaverBackend;
|
DataSaverBackend mDataSaverBackend;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -102,8 +105,8 @@ public class WifiTetherSwitchBarController implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
// Filter out unnecessary callbacks when switch is disabled.
|
// Filter out inappropriate callbacks when switch is busy.
|
||||||
if (!buttonView.isEnabled()) return;
|
if (mIsSwitchBusy) return;
|
||||||
|
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
startTether();
|
startTether();
|
||||||
@@ -115,14 +118,14 @@ public class WifiTetherSwitchBarController implements
|
|||||||
void stopTether() {
|
void stopTether() {
|
||||||
if (!isWifiApActivated()) return;
|
if (!isWifiApActivated()) return;
|
||||||
|
|
||||||
mSwitchBar.setEnabled(false);
|
mIsSwitchBusy = true;
|
||||||
mConnectivityManager.stopTethering(TETHERING_WIFI);
|
mConnectivityManager.stopTethering(TETHERING_WIFI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startTether() {
|
void startTether() {
|
||||||
if (isWifiApActivated()) return;
|
if (isWifiApActivated()) return;
|
||||||
|
|
||||||
mSwitchBar.setEnabled(false);
|
mIsSwitchBusy = true;
|
||||||
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
|
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
|
||||||
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
|
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
|
||||||
}
|
}
|
||||||
@@ -159,6 +162,7 @@ public class WifiTetherSwitchBarController implements
|
|||||||
|
|
||||||
private void updateWifiSwitch() {
|
private void updateWifiSwitch() {
|
||||||
mSwitchBar.setEnabled(!mDataSaverBackend.isDataSaverEnabled());
|
mSwitchBar.setEnabled(!mDataSaverBackend.isDataSaverEnabled());
|
||||||
|
mIsSwitchBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -19,6 +19,7 @@ package com.android.settings.bluetooth.ui.viewmodel
|
|||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.bluetooth.BluetoothAdapter
|
import android.bluetooth.BluetoothAdapter
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
|
import android.media.AudioManager
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor
|
import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor
|
||||||
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
|
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
|
||||||
@@ -46,7 +47,9 @@ import org.junit.Before
|
|||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentMatchers.eq
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.any
|
||||||
import org.mockito.Mockito.times
|
import org.mockito.Mockito.times
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.Mockito.`when`
|
import org.mockito.Mockito.`when`
|
||||||
@@ -76,11 +79,21 @@ class BluetoothDeviceDetailsViewModelTest {
|
|||||||
val application = ApplicationProvider.getApplicationContext<Application>()
|
val application = ApplicationProvider.getApplicationContext<Application>()
|
||||||
featureFactory = FakeFeatureFactory.setupForTest()
|
featureFactory = FakeFeatureFactory.setupForTest()
|
||||||
|
|
||||||
|
`when`(
|
||||||
|
featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
|
||||||
|
eq(application), eq(bluetoothAdapter), any()
|
||||||
|
))
|
||||||
|
.thenReturn(repository)
|
||||||
|
`when`(
|
||||||
|
featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor(
|
||||||
|
eq(application), any(AudioManager::class.java), any()
|
||||||
|
))
|
||||||
|
.thenReturn(spatialAudioInteractor)
|
||||||
|
|
||||||
underTest =
|
underTest =
|
||||||
BluetoothDeviceDetailsViewModel(
|
BluetoothDeviceDetailsViewModel(
|
||||||
application,
|
application,
|
||||||
repository,
|
bluetoothAdapter,
|
||||||
spatialAudioInteractor,
|
|
||||||
cachedDevice,
|
cachedDevice,
|
||||||
testScope.testScheduler)
|
testScope.testScheduler)
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,8 @@ import android.platform.test.annotations.EnableFlags;
|
|||||||
import android.platform.test.flag.junit.SetFlagsRule;
|
import android.platform.test.flag.junit.SetFlagsRule;
|
||||||
import android.service.notification.SystemZenRules;
|
import android.service.notification.SystemZenRules;
|
||||||
import android.service.notification.ZenModeConfig;
|
import android.service.notification.ZenModeConfig;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.style.TtsSpan;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
@@ -293,7 +295,14 @@ public class ZenModeTriggerUpdatePreferenceControllerTest {
|
|||||||
|
|
||||||
assertThat(mPreference.isVisible()).isTrue();
|
assertThat(mPreference.isVisible()).isTrue();
|
||||||
assertThat(mPreference.getTitle()).isEqualTo("1:00 AM - 3:00 PM");
|
assertThat(mPreference.getTitle()).isEqualTo("1:00 AM - 3:00 PM");
|
||||||
assertThat(mPreference.getSummary()).isEqualTo("Mon - Tue, Thu");
|
Spanned summary = (Spanned) mPreference.getSummary();
|
||||||
|
assertThat(summary.toString()).isEqualTo("Mon - Tue, Thu");
|
||||||
|
TtsSpan[] ttsSpans = summary.getSpans(0, summary.length(), TtsSpan.class);
|
||||||
|
assertThat(ttsSpans).hasLength(1);
|
||||||
|
assertThat(ttsSpans[0].getType()).isEqualTo(TtsSpan.TYPE_TEXT);
|
||||||
|
assertThat(ttsSpans[0].getArgs().getString(TtsSpan.ARG_TEXT)).isEqualTo(
|
||||||
|
"Monday to Tuesday, Thursday");
|
||||||
|
|
||||||
// Destination as written into the intent by SubSettingLauncher
|
// Destination as written into the intent by SubSettingLauncher
|
||||||
assertThat(
|
assertThat(
|
||||||
mPreference.getIntent().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
mPreference.getIntent().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||||
|
@@ -147,8 +147,8 @@ public class WifiTetherSwitchBarControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onSwitchChanged_switchNotEnabled_doNothingForTethering() {
|
public void onSwitchChanged_switchIsBusy_doNothingForTethering() {
|
||||||
when(mSwitch.isEnabled()).thenReturn(false);
|
mController.mIsSwitchBusy = true;
|
||||||
|
|
||||||
mController.onCheckedChanged(mSwitch, true);
|
mController.onCheckedChanged(mSwitch, true);
|
||||||
|
|
||||||
|
@@ -16,21 +16,55 @@
|
|||||||
|
|
||||||
package com.android.settings.network
|
package com.android.settings.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.telephony.SubscriptionInfo
|
import android.telephony.SubscriptionInfo
|
||||||
|
import android.telephony.SubscriptionManager
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
|
import android.telephony.UiccCardInfo
|
||||||
|
import android.telephony.UiccPortInfo
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import org.junit.Rule
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.spy
|
||||||
|
import org.mockito.kotlin.stub
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class SimOnboardingServiceTest {
|
class SimOnboardingServiceTest {
|
||||||
|
val simOnboardingService = SimOnboardingService()
|
||||||
|
|
||||||
|
private val mockTelephonyManager = mock<TelephonyManager> {
|
||||||
|
on { activeModemCount } doReturn 2
|
||||||
|
on { isMultiSimSupported } doReturn TelephonyManager.MULTISIM_ALLOWED
|
||||||
|
on { uiccCardsInfo } doReturn mepUiccCardInfoList
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mockSubscriptionManager = mock<SubscriptionManager> {
|
||||||
|
on { activeSubscriptionInfoList } doReturn listOf(
|
||||||
|
SUB_INFO_1,
|
||||||
|
SUB_INFO_2
|
||||||
|
)
|
||||||
|
on { availableSubscriptionInfoList } doReturn listOf(
|
||||||
|
SUB_INFO_1,
|
||||||
|
SUB_INFO_2,
|
||||||
|
SUB_INFO_3,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||||
|
on { getSystemService(SubscriptionManager::class.java) } doReturn mockSubscriptionManager
|
||||||
|
on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun addItemForRenaming_addItemWithNewName_findItem() {
|
fun addItemForRenaming_addItemWithNewName_findItem() {
|
||||||
val simOnboardingService = SimOnboardingService()
|
|
||||||
val newName = "NewName"
|
val newName = "NewName"
|
||||||
|
|
||||||
simOnboardingService.addItemForRenaming(SUB_INFO_1, newName)
|
simOnboardingService.addItemForRenaming(SUB_INFO_1, newName)
|
||||||
|
|
||||||
assertThat(simOnboardingService.renameMutableMap)
|
assertThat(simOnboardingService.renameMutableMap)
|
||||||
@@ -39,8 +73,6 @@ class SimOnboardingServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun addItemForRenaming_sameNameAndItemNotInList_removeItem() {
|
fun addItemForRenaming_sameNameAndItemNotInList_removeItem() {
|
||||||
val simOnboardingService = SimOnboardingService()
|
|
||||||
|
|
||||||
simOnboardingService.addItemForRenaming(SUB_INFO_1, DISPLAY_NAME_1)
|
simOnboardingService.addItemForRenaming(SUB_INFO_1, DISPLAY_NAME_1)
|
||||||
|
|
||||||
assertThat(simOnboardingService.renameMutableMap)
|
assertThat(simOnboardingService.renameMutableMap)
|
||||||
@@ -49,7 +81,6 @@ class SimOnboardingServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun addItemForRenaming_sameNameAndItemInList_removeItem() {
|
fun addItemForRenaming_sameNameAndItemInList_removeItem() {
|
||||||
val simOnboardingService = SimOnboardingService()
|
|
||||||
simOnboardingService.renameMutableMap[SUB_INFO_1.subscriptionId] = "NewName"
|
simOnboardingService.renameMutableMap[SUB_INFO_1.subscriptionId] = "NewName"
|
||||||
|
|
||||||
simOnboardingService.addItemForRenaming(SUB_INFO_1, DISPLAY_NAME_1)
|
simOnboardingService.addItemForRenaming(SUB_INFO_1, DISPLAY_NAME_1)
|
||||||
@@ -58,13 +89,205 @@ class SimOnboardingServiceTest {
|
|||||||
.doesNotContainKey(SUB_INFO_1.subscriptionId)
|
.doesNotContainKey(SUB_INFO_1.subscriptionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isDsdsConditionSatisfied_isMultiSimEnabled_returnFalse(){
|
||||||
|
simOnboardingService.initData(SUB_ID_3, context, {})
|
||||||
|
|
||||||
|
assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isDsdsConditionSatisfied_isNotMultiSimSupported_returnFalse() {
|
||||||
|
mockTelephonyManager.stub {
|
||||||
|
on { activeModemCount } doReturn 1
|
||||||
|
on {
|
||||||
|
isMultiSimSupported
|
||||||
|
} doReturn TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE
|
||||||
|
}
|
||||||
|
simOnboardingService.initData(SUB_ID_3, context, {})
|
||||||
|
|
||||||
|
assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isDsdsConditionSatisfied_mepAndOneActiveSim_returnTrue() = runBlocking {
|
||||||
|
mockTelephonyManager.stub {
|
||||||
|
on { activeModemCount } doReturn 1
|
||||||
|
}
|
||||||
|
simOnboardingService.initData(SUB_ID_3, context, {})
|
||||||
|
delay(100)
|
||||||
|
|
||||||
|
assertThat(simOnboardingService.isDsdsConditionSatisfied()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isDsdsConditionSatisfied_mepAndNoActiveSim_returnFalse() = runBlocking {
|
||||||
|
mockTelephonyManager.stub {
|
||||||
|
on { activeModemCount } doReturn 1
|
||||||
|
}
|
||||||
|
mockSubscriptionManager.stub {
|
||||||
|
on { activeSubscriptionInfoList } doReturn listOf()
|
||||||
|
}
|
||||||
|
simOnboardingService.initData(SUB_ID_3, context, {})
|
||||||
|
delay(100)
|
||||||
|
|
||||||
|
assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isDsdsConditionSatisfied_insertEsimAndOneActivePsimNoMep_returnTrue() = runBlocking {
|
||||||
|
mockTelephonyManager.stub {
|
||||||
|
on { getActiveModemCount() } doReturn 1
|
||||||
|
on { uiccCardsInfo } doReturn noMepUiccCardInfoList
|
||||||
|
}
|
||||||
|
simOnboardingService.initData(SUB_ID_3, context, {})
|
||||||
|
delay(100)
|
||||||
|
|
||||||
|
assertThat(simOnboardingService.isDsdsConditionSatisfied()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isDsdsConditionSatisfied_insertEsimAndNoPsimNoMep_returnFalse() = runBlocking {
|
||||||
|
mockTelephonyManager.stub {
|
||||||
|
on { getActiveModemCount() } doReturn 1
|
||||||
|
on { uiccCardsInfo } doReturn noMepUiccCardInfoList
|
||||||
|
}
|
||||||
|
mockSubscriptionManager.stub {
|
||||||
|
on { activeSubscriptionInfoList } doReturn listOf()
|
||||||
|
}
|
||||||
|
simOnboardingService.initData(SUB_ID_3, context, {})
|
||||||
|
delay(100)
|
||||||
|
|
||||||
|
assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isDsdsConditionSatisfied_insertPsimAndOneActiveEsimNoMep_returnTrue() = runBlocking {
|
||||||
|
mockTelephonyManager.stub {
|
||||||
|
on { getActiveModemCount() } doReturn 1
|
||||||
|
on { uiccCardsInfo } doReturn noMepUiccCardInfoList
|
||||||
|
}
|
||||||
|
mockSubscriptionManager.stub {
|
||||||
|
on { activeSubscriptionInfoList } doReturn listOf(
|
||||||
|
SUB_INFO_2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
simOnboardingService.initData(SUB_ID_1, context, {})
|
||||||
|
delay(100)
|
||||||
|
|
||||||
|
assertThat(simOnboardingService.isDsdsConditionSatisfied()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isDsdsConditionSatisfied_insertPsimAndNoEsimNoMep_returnFalse() = runBlocking {
|
||||||
|
mockTelephonyManager.stub {
|
||||||
|
on { getActiveModemCount() } doReturn 1
|
||||||
|
on { uiccCardsInfo } doReturn noMepUiccCardInfoList
|
||||||
|
}
|
||||||
|
mockSubscriptionManager.stub {
|
||||||
|
on { activeSubscriptionInfoList } doReturn listOf()
|
||||||
|
}
|
||||||
|
simOnboardingService.initData(SUB_ID_1, context, {})
|
||||||
|
delay(100)
|
||||||
|
|
||||||
|
assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val SUB_ID_1 = 1
|
const val SUB_ID_1 = 1
|
||||||
|
const val SUB_ID_2 = 2
|
||||||
|
const val SUB_ID_3 = 3
|
||||||
|
const val SUB_ID_4 = 4
|
||||||
const val DISPLAY_NAME_1 = "Sub 1"
|
const val DISPLAY_NAME_1 = "Sub 1"
|
||||||
|
|
||||||
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
setId(SUB_ID_1)
|
setId(SUB_ID_1)
|
||||||
setDisplayName(DISPLAY_NAME_1)
|
setDisplayName(DISPLAY_NAME_1)
|
||||||
}.build()
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_2)
|
||||||
|
setEmbedded(true)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_3: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_3)
|
||||||
|
setEmbedded(true)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_4: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_4)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
private const val REMOVABLE_CARD_ID_1: Int = 25
|
||||||
|
private const val REMOVABLE_CARD_ID_2: Int = 26
|
||||||
|
private const val EUICC_CARD_ID_3: Int = 27
|
||||||
|
private const val EUICC_CARD_ID_4: Int = 28
|
||||||
|
|
||||||
|
val noMepUiccCardInfoList: List<UiccCardInfo> = listOf(
|
||||||
|
createUiccCardInfo(
|
||||||
|
isEuicc = true,
|
||||||
|
cardId = EUICC_CARD_ID_3,
|
||||||
|
physicalSlotIndex = 0,
|
||||||
|
isRemovable = false,
|
||||||
|
isMultipleEnabledProfileSupported = false,
|
||||||
|
logicalSlotIndex = -1,
|
||||||
|
portIndex = -1
|
||||||
|
),
|
||||||
|
createUiccCardInfo(
|
||||||
|
isEuicc = false,
|
||||||
|
cardId = REMOVABLE_CARD_ID_1,
|
||||||
|
physicalSlotIndex = 1,
|
||||||
|
isRemovable = true,
|
||||||
|
isMultipleEnabledProfileSupported = false,
|
||||||
|
logicalSlotIndex = -1,
|
||||||
|
portIndex = -1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val mepUiccCardInfoList: List<UiccCardInfo> = listOf(
|
||||||
|
createUiccCardInfo(
|
||||||
|
isEuicc = true,
|
||||||
|
cardId = EUICC_CARD_ID_3,
|
||||||
|
physicalSlotIndex = 0,
|
||||||
|
isRemovable = false,
|
||||||
|
logicalSlotIndex = -1,
|
||||||
|
portIndex = -1
|
||||||
|
),
|
||||||
|
createUiccCardInfo(
|
||||||
|
isEuicc = false,
|
||||||
|
cardId = REMOVABLE_CARD_ID_1,
|
||||||
|
physicalSlotIndex = 1,
|
||||||
|
isRemovable = true,
|
||||||
|
logicalSlotIndex = -1,
|
||||||
|
portIndex = -1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun createUiccCardInfo(
|
||||||
|
isEuicc: Boolean,
|
||||||
|
cardId: Int,
|
||||||
|
physicalSlotIndex: Int,
|
||||||
|
isRemovable: Boolean,
|
||||||
|
logicalSlotIndex: Int,
|
||||||
|
portIndex: Int,
|
||||||
|
isMultipleEnabledProfileSupported:Boolean = true,
|
||||||
|
): UiccCardInfo {
|
||||||
|
return UiccCardInfo(
|
||||||
|
isEuicc, /* isEuicc */
|
||||||
|
cardId, /* cardId */
|
||||||
|
null, /* eid */
|
||||||
|
physicalSlotIndex, /* physicalSlotIndex */
|
||||||
|
isRemovable, /* isRemovable */
|
||||||
|
isMultipleEnabledProfileSupported, /* isMultipleEnabledProfileSupported */
|
||||||
|
listOf(
|
||||||
|
UiccPortInfo(
|
||||||
|
"123451234567890", /* iccId */
|
||||||
|
portIndex, /* portIdx */
|
||||||
|
logicalSlotIndex, /* logicalSlotIdx */
|
||||||
|
true /* isActive */
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -44,7 +44,7 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isFalse()
|
assertThat(result).isFalse()
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isFalse()
|
assertThat(result).isFalse()
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isTrue()
|
assertThat(result).isTrue()
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isTrue()
|
assertThat(result).isTrue()
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isFalse()
|
assertThat(result).isFalse()
|
||||||
}
|
}
|
||||||
@@ -137,13 +137,13 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isTrue()
|
assertThat(result).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun anyRemovablePhysicalSimEnabled_activePsim_returnsTrue() {
|
fun anyRemovablePhysicalSimSlotActiveAndInserted_activePsim_returnsTrue() {
|
||||||
mockTelephonyManager.stub {
|
mockTelephonyManager.stub {
|
||||||
on { uiccSlotsInfo } doReturn
|
on { uiccSlotsInfo } doReturn
|
||||||
arrayOf(
|
arrayOf(
|
||||||
@@ -152,13 +152,13 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isTrue()
|
assertThat(result).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun anyRemovablePhysicalSimEnabled_inactivePsim_returnsFalse() {
|
fun anyRemovablePhysicalSimSlotActiveAndInserted_inactivePsim_returnsFalse() {
|
||||||
mockTelephonyManager.stub {
|
mockTelephonyManager.stub {
|
||||||
on { uiccSlotsInfo } doReturn
|
on { uiccSlotsInfo } doReturn
|
||||||
arrayOf(
|
arrayOf(
|
||||||
@@ -167,13 +167,13 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isFalse()
|
assertThat(result).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun anyRemovablePhysicalSimEnabled_activeEsimAndActivePsim_returnsTrue() {
|
fun anyRemovablePhysicalSimSlotActiveAndInserted_activeEsimAndActivePsim_returnsTrue() {
|
||||||
mockTelephonyManager.stub {
|
mockTelephonyManager.stub {
|
||||||
on { uiccSlotsInfo } doReturn
|
on { uiccSlotsInfo } doReturn
|
||||||
arrayOf(
|
arrayOf(
|
||||||
@@ -184,13 +184,13 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isTrue()
|
assertThat(result).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun anyRemovablePhysicalSimEnabled_activeEsimAndInactivePsim_returnsFalse() {
|
fun anyRemovablePhysicalSimSlotActiveAndInserted_activeEsimAndInactivePsim_returnsFalse() {
|
||||||
mockTelephonyManager.stub {
|
mockTelephonyManager.stub {
|
||||||
on { uiccSlotsInfo } doReturn
|
on { uiccSlotsInfo } doReturn
|
||||||
arrayOf(
|
arrayOf(
|
||||||
@@ -201,16 +201,16 @@ class UiccSlotRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isFalse()
|
assertThat(result).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun anyRemovablePhysicalSimEnabled_uiccSlotInfoIsNull_returnsFalse() {
|
fun anyRemovablePhysicalSimSlotActiveAndInserted_uiccSlotInfoIsNull_returnsFalse() {
|
||||||
mockTelephonyManager.stub { on { uiccSlotsInfo } doReturn arrayOf(null) }
|
mockTelephonyManager.stub { on { uiccSlotsInfo } doReturn arrayOf(null) }
|
||||||
|
|
||||||
val result = repository.anyRemovablePhysicalSimEnabled()
|
val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
|
||||||
|
|
||||||
assertThat(result).isFalse()
|
assertThat(result).isFalse()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user