Merge "[Sim UI enhancement] MobileNetworkSettings UI enhancement" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
35b3ad939c
@@ -47,6 +47,23 @@
|
||||
android:enabled="false"
|
||||
settings:controller="com.android.settings.network.telephony.SmsDefaultSubscriptionController"/>
|
||||
|
||||
<Preference
|
||||
android:key="mobile_network_spn"
|
||||
android:title="@string/mobile_network_spn_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:selectable="false"
|
||||
settings:controller="com.android.settings.network.telephony.MobileNetworkSpnPreferenceController"
|
||||
settings:allowDividerAbove="true" />
|
||||
|
||||
<Preference
|
||||
android:key="phone_number"
|
||||
android:title="@string/status_number"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:selectable="false"
|
||||
settings:controller="com.android.settings.network.telephony.MobileNetworkPhoneNumberPreferenceController"
|
||||
settings:allowDividerBelow="true"
|
||||
settings:enableCopying="true"/>
|
||||
|
||||
<Preference
|
||||
android:key="cdma_lte_data_service_key"
|
||||
android:title="@string/cdma_lte_data_service"
|
||||
@@ -162,6 +179,24 @@
|
||||
settings:controller="com.android.settings.network.telephony.CarrierSettingsVersionPreferenceController"
|
||||
settings:enableCopying="true"/>
|
||||
|
||||
<!-- IMEI -->
|
||||
<Preference
|
||||
android:key="network_mode_imei_info"
|
||||
android:title="@string/status_imei"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:keywords="@string/keywords_imei_info"
|
||||
settings:enableCopying="true"
|
||||
settings:controller="com.android.settings.network.telephony.MobileNetworkImeiPreferenceController"/>
|
||||
<!-- EID -->
|
||||
<com.android.settingslib.CustomDialogPreferenceCompat
|
||||
android:key="network_mode_eid_info"
|
||||
android:title="@string/status_eid"
|
||||
android:summary="@string/device_info_protected_single_press"
|
||||
android:positiveButtonText="@string/dlg_ok"
|
||||
android:dialogLayout="@layout/dialog_eid_status"
|
||||
settings:enableCopying="true"
|
||||
settings:controller="com.android.settings.network.telephony.MobileNetworkEidPreferenceController"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="calling_category"
|
||||
android:title="@string/call_category"
|
||||
|
@@ -42,6 +42,7 @@ import androidx.preference.TwoStatePreference;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.datausage.DataUsageUtils;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.network.MobileDataContentObserver;
|
||||
import com.android.settings.network.ProxySubscriptionManager;
|
||||
import com.android.settings.network.SubscriptionsChangeListener;
|
||||
@@ -194,7 +195,8 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus(int subId) {
|
||||
if (!SubscriptionManager.isValidSubscriptionId(subId)
|
||||
if (Flags.isDualSimOnboardingEnabled()
|
||||
|| !SubscriptionManager.isValidSubscriptionId(subId)
|
||||
|| SubscriptionManager.getDefaultDataSubscriptionId() == subId
|
||||
|| (!hasMobileData())) {
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
|
@@ -32,6 +32,7 @@ import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.network.DefaultSubscriptionReceiver;
|
||||
import com.android.settings.network.MobileNetworkRepository;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
@@ -88,6 +89,9 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus(int subId) {
|
||||
if (Flags.isDualSimOnboardingEnabled()) {
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
|
@@ -34,6 +34,7 @@ import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.TwoStatePreference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.network.MobileNetworkRepository;
|
||||
import com.android.settings.wifi.WifiPickerTrackerHelper;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
@@ -83,6 +84,9 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus(int subId) {
|
||||
if (Flags.isDualSimOnboardingEnabled()) {
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||
? AVAILABLE
|
||||
: AVAILABLE_UNSEARCHABLE;
|
||||
|
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager
|
||||
import android.telephony.TelephonyManager
|
||||
import android.telephony.euicc.EuiccManager
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.R
|
||||
import com.android.settings.deviceinfo.PhoneNumberUtil
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.network.SubscriptionInfoListViewModel
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.android.settingslib.CustomDialogPreferenceCompat
|
||||
import com.android.settingslib.Utils
|
||||
import com.android.settingslib.qrcode.QrCodeGenerator
|
||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Preference controller for "EID"
|
||||
*/
|
||||
open class MobileNetworkEidPreferenceController(context: Context, key: String) :
|
||||
TelephonyBasePreferenceController(context, key) {
|
||||
|
||||
private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
|
||||
private lateinit var preference: CustomDialogPreferenceCompat
|
||||
private lateinit var fragment: Fragment
|
||||
private var coroutineScope: CoroutineScope? = null
|
||||
private var title = String()
|
||||
private var eid = String()
|
||||
|
||||
fun init(fragment: Fragment, subId: Int) {
|
||||
this.fragment = fragment
|
||||
lazyViewModel = fragment.viewModels()
|
||||
mSubId = subId
|
||||
}
|
||||
|
||||
override fun getAvailabilityStatus(subId: Int): Int = when {
|
||||
!Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
|
||||
SubscriptionManager.isValidSubscriptionId(subId)
|
||||
&& eid.isNotEmpty()
|
||||
&& mContext.userManager.isAdminUser -> AVAILABLE
|
||||
|
||||
else -> CONDITIONALLY_UNAVAILABLE
|
||||
}
|
||||
|
||||
override fun displayPreference(screen: PreferenceScreen) {
|
||||
super.displayPreference(screen)
|
||||
preference = screen.findPreference(preferenceKey)!!
|
||||
}
|
||||
|
||||
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
|
||||
preference.isVisible = false
|
||||
|
||||
val viewModel by lazyViewModel
|
||||
coroutineScope = viewLifecycleOwner.lifecycleScope
|
||||
viewModel.subscriptionInfoListFlow
|
||||
.map { subscriptionInfoList ->
|
||||
subscriptionInfoList
|
||||
.firstOrNull { subInfo ->
|
||||
subInfo.subscriptionId == mSubId && subInfo.isEmbedded
|
||||
}
|
||||
}
|
||||
.collectLatestWithLifecycle(viewLifecycleOwner) { subscriptionInfo ->
|
||||
subscriptionInfo?.let {
|
||||
coroutineScope?.launch {
|
||||
refreshData(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
suspend fun refreshData(subscriptionInfo: SubscriptionInfo) {
|
||||
withContext(Dispatchers.Default) {
|
||||
eid = getEid(subscriptionInfo)
|
||||
if (eid.isEmpty()) {
|
||||
Log.d(TAG, "EID is empty.")
|
||||
}
|
||||
title = getTitle()
|
||||
}
|
||||
refreshUi()
|
||||
}
|
||||
|
||||
fun refreshUi() {
|
||||
preference.title = title
|
||||
preference.dialogTitle = title
|
||||
preference.summary = eid
|
||||
preference.isVisible = eid.isNotEmpty()
|
||||
}
|
||||
|
||||
override fun handlePreferenceTreeClick(preference: Preference): Boolean {
|
||||
if (preference.key != preferenceKey) return false
|
||||
this.preference.setOnShowListener {
|
||||
coroutineScope?.launch { updateDialog() }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getTitle(): String {
|
||||
return mContext.getString(R.string.status_eid)
|
||||
}
|
||||
|
||||
private suspend fun updateDialog() {
|
||||
val dialog = preference.dialog ?: return
|
||||
dialog.window?.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_SECURE,
|
||||
WindowManager.LayoutParams.FLAG_SECURE
|
||||
)
|
||||
dialog.setCanceledOnTouchOutside(false)
|
||||
val textView = dialog.requireViewById<TextView>(R.id.esim_id_value)
|
||||
textView.text = PhoneNumberUtil.expandByTts(eid)
|
||||
|
||||
val qrCodeView = dialog.requireViewById<ImageView>(R.id.esim_id_qrcode)
|
||||
|
||||
qrCodeView.setImageBitmap(getEidQrCode(eid))
|
||||
}
|
||||
|
||||
protected fun getTelephonyManager(context: Context): TelephonyManager? {
|
||||
return context.getSystemService(TelephonyManager::class.java)
|
||||
}
|
||||
|
||||
protected fun getEuiccManager(context: Context): EuiccManager? {
|
||||
return context.getSystemService(EuiccManager::class.java)
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun getEid(subscriptionInfo: SubscriptionInfo): String {
|
||||
val euiccMgr = getEuiccManager(mContext)
|
||||
val telMgr = getTelephonyManager(mContext)
|
||||
if(euiccMgr==null || telMgr==null) return String()
|
||||
|
||||
var eid = getEidPerSlot(telMgr, euiccMgr, subscriptionInfo)
|
||||
return eid.ifEmpty {
|
||||
getDefaultEid(euiccMgr)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEidPerSlot(
|
||||
telMgr: TelephonyManager,
|
||||
euiccMgr: EuiccManager,
|
||||
subscriptionInfo: SubscriptionInfo
|
||||
): String {
|
||||
val uiccCardInfoList = telMgr.uiccCardsInfo
|
||||
val cardId = subscriptionInfo.cardId
|
||||
|
||||
/**
|
||||
* Find EID from first slot which contains an eSIM and with card ID within
|
||||
* the eSIM card ID provided by SubscriptionManager.
|
||||
*/
|
||||
return uiccCardInfoList.firstOrNull { cardInfo -> cardInfo.isEuicc && cardInfo.cardId == cardId }
|
||||
?.let { cardInfo ->
|
||||
var eid = cardInfo.getEid()
|
||||
if (TextUtils.isEmpty(eid)) {
|
||||
eid = euiccMgr.createForCardId(cardInfo.cardId).getEid()
|
||||
}
|
||||
eid
|
||||
} ?: String()
|
||||
}
|
||||
|
||||
private fun getDefaultEid(euiccMgr: EuiccManager?): String {
|
||||
return if (euiccMgr == null || !euiccMgr.isEnabled) {
|
||||
String()
|
||||
} else euiccMgr.getEid() ?: String()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MobileNetworkEidPreferenceController"
|
||||
private const val QR_CODE_SIZE = 600
|
||||
|
||||
/**
|
||||
* Gets the QR code for EID
|
||||
* @param eid is the EID string
|
||||
* @return a Bitmap of QR code
|
||||
*/
|
||||
private suspend fun getEidQrCode(eid: String): Bitmap? = withContext(Dispatchers.Default) {
|
||||
try {
|
||||
Log.d(TAG, "updateDialog. getEidQrCode $eid")
|
||||
QrCodeGenerator.encodeQrCode(contents = eid, size = QR_CODE_SIZE)
|
||||
} catch (exception: Exception) {
|
||||
Log.w(TAG, "Error when creating QR code width $QR_CODE_SIZE", exception)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.os.UserManager
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager
|
||||
import android.telephony.TelephonyManager
|
||||
import android.util.Log
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.R
|
||||
import com.android.settings.deviceinfo.imei.ImeiInfoDialogFragment
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.network.SubscriptionInfoListViewModel
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.android.settingslib.Utils
|
||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Preference controller for "IMEI"
|
||||
*/
|
||||
class MobileNetworkImeiPreferenceController(context: Context, key: String) :
|
||||
TelephonyBasePreferenceController(context, key) {
|
||||
|
||||
private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
|
||||
private lateinit var preference: Preference
|
||||
private lateinit var fragment: Fragment
|
||||
private lateinit var mTelephonyManager: TelephonyManager
|
||||
private var simSlot = -1
|
||||
private var imei = String()
|
||||
private var title = String()
|
||||
|
||||
fun init(fragment: Fragment, subId: Int) {
|
||||
this.fragment = fragment
|
||||
lazyViewModel = fragment.viewModels()
|
||||
mSubId = subId
|
||||
mTelephonyManager = mContext.getSystemService(TelephonyManager::class.java)
|
||||
?.createForSubscriptionId(mSubId)!!
|
||||
}
|
||||
|
||||
override fun getAvailabilityStatus(subId: Int): Int = when {
|
||||
!Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
|
||||
SubscriptionManager.isValidSubscriptionId(subId)
|
||||
&& SubscriptionUtil.isSimHardwareVisible(mContext)
|
||||
&& mContext.userManager.isAdminUser
|
||||
&& !Utils.isWifiOnly(mContext) -> AVAILABLE
|
||||
else -> CONDITIONALLY_UNAVAILABLE
|
||||
}
|
||||
|
||||
override fun displayPreference(screen: PreferenceScreen) {
|
||||
super.displayPreference(screen)
|
||||
preference = screen.findPreference(preferenceKey)!!
|
||||
}
|
||||
|
||||
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
|
||||
val viewModel by lazyViewModel
|
||||
val coroutineScope = viewLifecycleOwner.lifecycleScope
|
||||
|
||||
viewModel.subscriptionInfoListFlow
|
||||
.collectLatestWithLifecycle(viewLifecycleOwner) { subscriptionInfoList ->
|
||||
subscriptionInfoList
|
||||
.firstOrNull { subInfo -> subInfo.subscriptionId == mSubId }
|
||||
?.let {
|
||||
coroutineScope.launch {
|
||||
refreshData(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
suspend fun refreshData(subscription:SubscriptionInfo){
|
||||
withContext(Dispatchers.Default) {
|
||||
title = getTitle()
|
||||
imei = getImei()
|
||||
simSlot = subscription.simSlotIndex
|
||||
}
|
||||
refreshUi()
|
||||
}
|
||||
|
||||
private fun refreshUi(){
|
||||
preference.title = title
|
||||
preference.summary = imei
|
||||
preference.isVisible = true
|
||||
}
|
||||
|
||||
override fun handlePreferenceTreeClick(preference: Preference): Boolean {
|
||||
if (preference.key != preferenceKey) return false
|
||||
|
||||
Log.d(TAG, "handlePreferenceTreeClick:")
|
||||
ImeiInfoDialogFragment.show(fragment, simSlot, preference.title.toString())
|
||||
return true
|
||||
}
|
||||
private fun getImei(): String {
|
||||
val phoneType = getPhoneType()
|
||||
return if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) mTelephonyManager.meid?: String()
|
||||
else mTelephonyManager.imei?: String()
|
||||
}
|
||||
private fun getTitleForGsmPhone(): String {
|
||||
return mContext.getString(R.string.status_imei)
|
||||
}
|
||||
|
||||
private fun getTitleForCdmaPhone(): String {
|
||||
return mContext.getString(R.string.status_meid_number)
|
||||
}
|
||||
|
||||
private fun getTitle(): String {
|
||||
val phoneType = getPhoneType()
|
||||
return if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) getTitleForCdmaPhone()
|
||||
else getTitleForGsmPhone()
|
||||
}
|
||||
|
||||
fun getPhoneType(): Int {
|
||||
return mTelephonyManager.currentPhoneType
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MobileNetworkImeiPreferenceController"
|
||||
}
|
||||
}
|
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.R
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.network.SubscriptionInfoListViewModel
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Preference controller for "Phone number"
|
||||
*/
|
||||
class MobileNetworkPhoneNumberPreferenceController(context: Context, key: String) :
|
||||
TelephonyBasePreferenceController(context, key) {
|
||||
|
||||
private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
|
||||
private lateinit var preference: Preference
|
||||
|
||||
private var phoneNumber = String()
|
||||
|
||||
fun init(fragment: Fragment, subId: Int) {
|
||||
lazyViewModel = fragment.viewModels()
|
||||
mSubId = subId
|
||||
}
|
||||
|
||||
override fun getAvailabilityStatus(subId: Int): Int = when {
|
||||
!Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
|
||||
SubscriptionManager.isValidSubscriptionId(subId)
|
||||
&& SubscriptionUtil.isSimHardwareVisible(mContext) -> AVAILABLE
|
||||
else -> CONDITIONALLY_UNAVAILABLE
|
||||
}
|
||||
|
||||
override fun displayPreference(screen: PreferenceScreen) {
|
||||
super.displayPreference(screen)
|
||||
preference = screen.findPreference(preferenceKey)!!
|
||||
}
|
||||
|
||||
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
|
||||
val viewModel by lazyViewModel
|
||||
val coroutineScope = viewLifecycleOwner.lifecycleScope
|
||||
|
||||
viewModel.subscriptionInfoListFlow
|
||||
.map { subscriptionInfoList ->
|
||||
subscriptionInfoList
|
||||
.firstOrNull { subInfo -> subInfo.subscriptionId == mSubId }
|
||||
}
|
||||
.flowOn(Dispatchers.Default)
|
||||
.collectLatestWithLifecycle(viewLifecycleOwner) {
|
||||
it?.let {
|
||||
coroutineScope.launch {
|
||||
refreshData(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
suspend fun refreshData(subscriptionInfo: SubscriptionInfo){
|
||||
withContext(Dispatchers.Default) {
|
||||
phoneNumber = getFormattedPhoneNumber(subscriptionInfo)
|
||||
}
|
||||
refreshUi()
|
||||
}
|
||||
|
||||
private fun refreshUi(){
|
||||
preference.summary = phoneNumber
|
||||
}
|
||||
|
||||
private fun getFormattedPhoneNumber(subscriptionInfo: SubscriptionInfo?): String {
|
||||
val phoneNumber = SubscriptionUtil.getBidiFormattedPhoneNumber(
|
||||
mContext,
|
||||
subscriptionInfo
|
||||
)
|
||||
return phoneNumber
|
||||
?.let { return it.ifEmpty { getStringUnknown() } }
|
||||
?: getStringUnknown()
|
||||
}
|
||||
|
||||
private fun getStringUnknown(): String {
|
||||
return mContext.getString(R.string.device_info_default)
|
||||
}
|
||||
}
|
@@ -85,6 +85,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
|
||||
private static final String KEY_SMS_PREF = "sms_preference";
|
||||
private static final String KEY_MOBILE_DATA_PREF = "mobile_data_enable";
|
||||
private static final String KEY_CONVERT_TO_ESIM_PREF = "convert_to_esim";
|
||||
private static final String KEY_EID_KEY = "network_mode_eid_info";
|
||||
|
||||
//String keys for preference lookup
|
||||
private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
|
||||
@@ -171,6 +172,10 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
|
||||
String.valueOf(mSubId));
|
||||
});
|
||||
|
||||
MobileNetworkEidPreferenceController eid = new MobileNetworkEidPreferenceController(context,
|
||||
KEY_EID_KEY);
|
||||
eid.init(this, mSubId);
|
||||
|
||||
return Arrays.asList(
|
||||
new DataUsageSummaryPreferenceController(context, mSubId),
|
||||
new RoamingPreferenceController(context, KEY_ROAMING_PREF, getSettingsLifecycle(),
|
||||
@@ -182,7 +187,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
|
||||
new MobileDataPreferenceController(context, KEY_MOBILE_DATA_PREF,
|
||||
getSettingsLifecycle(), this, mSubId),
|
||||
new ConvertToEsimPreferenceController(context, KEY_CONVERT_TO_ESIM_PREF,
|
||||
getSettingsLifecycle(), this, mSubId));
|
||||
getSettingsLifecycle(), this, mSubId), eid);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -239,6 +244,10 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
|
||||
use(DisableSimFooterPreferenceController.class).init(mSubId);
|
||||
use(NrDisabledInDsdsFooterPreferenceController.class).init(mSubId);
|
||||
|
||||
use(MobileNetworkSpnPreferenceController.class).init(this, mSubId);
|
||||
use(MobileNetworkPhoneNumberPreferenceController.class).init(this, mSubId);
|
||||
use(MobileNetworkImeiPreferenceController.class).init(this, mSubId);
|
||||
|
||||
final MobileDataPreferenceController mobileDataPreferenceController =
|
||||
use(MobileDataPreferenceController.class);
|
||||
if (mobileDataPreferenceController != null) {
|
||||
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.network.SubscriptionInfoListViewModel
|
||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||
|
||||
/**
|
||||
* Preference controller for "Mobile network" and showing the SPN.
|
||||
*/
|
||||
class MobileNetworkSpnPreferenceController(context: Context, key: String) :
|
||||
TelephonyBasePreferenceController(context, key) {
|
||||
|
||||
private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
|
||||
private lateinit var preference: Preference
|
||||
|
||||
private var spn = String()
|
||||
|
||||
fun init(fragment: Fragment, subId: Int) {
|
||||
lazyViewModel = fragment.viewModels()
|
||||
mSubId = subId
|
||||
}
|
||||
|
||||
override fun getAvailabilityStatus(subId: Int): Int = when {
|
||||
!Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
|
||||
SubscriptionManager.isValidSubscriptionId(subId)-> AVAILABLE
|
||||
else -> CONDITIONALLY_UNAVAILABLE
|
||||
}
|
||||
|
||||
override fun displayPreference(screen: PreferenceScreen) {
|
||||
super.displayPreference(screen)
|
||||
preference = screen.findPreference(preferenceKey)!!
|
||||
}
|
||||
|
||||
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
|
||||
val viewModel by lazyViewModel
|
||||
|
||||
viewModel.subscriptionInfoListFlow
|
||||
.collectLatestWithLifecycle(viewLifecycleOwner) { subscriptionInfoList ->
|
||||
refreshData(subscriptionInfoList)
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun refreshData(subscriptionInfoList: List<SubscriptionInfo>){
|
||||
spn = subscriptionInfoList
|
||||
.firstOrNull { subInfo -> subInfo.subscriptionId == mSubId }
|
||||
?.let { info -> info.carrierName.toString() }
|
||||
?: String()
|
||||
|
||||
refreshUi()
|
||||
}
|
||||
|
||||
private fun refreshUi(){
|
||||
preference.summary = spn
|
||||
}
|
||||
}
|
@@ -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 android.content.Context
|
||||
import android.platform.test.flag.junit.SetFlagsRule
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.TelephonyManager
|
||||
import android.telephony.euicc.EuiccManager
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito
|
||||
import com.android.settings.core.BasePreferenceController
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.network.SubscriptionInfoListViewModel
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.android.settingslib.CustomDialogPreferenceCompat
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.MockitoSession
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.stub
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.mockito.quality.Strictness
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MobileNetworkEidPreferenceControllerTest {
|
||||
@get:Rule val setFlagsRule: SetFlagsRule = SetFlagsRule()
|
||||
|
||||
private lateinit var mockSession: MockitoSession
|
||||
|
||||
private val mockViewModels = mock<Lazy<SubscriptionInfoListViewModel>>()
|
||||
private val mockFragment = mock<Fragment>{
|
||||
val viewmodel = mockViewModels
|
||||
}
|
||||
|
||||
private var mockEid = String()
|
||||
private val mockTelephonyManager = mock<TelephonyManager> {
|
||||
on {uiccCardsInfo} doReturn listOf()
|
||||
on { createForSubscriptionId(any()) } doReturn mock
|
||||
}
|
||||
private val mockEuiccManager = mock<EuiccManager> {
|
||||
on {isEnabled} doReturn true
|
||||
on {eid} doReturn mockEid
|
||||
}
|
||||
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||
on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
|
||||
on { getSystemService(EuiccManager::class.java) } doReturn mockEuiccManager
|
||||
}
|
||||
|
||||
private val controller = MobileNetworkEidPreferenceController(context, TEST_KEY)
|
||||
private val preference = CustomDialogPreferenceCompat(context).apply { key = TEST_KEY }
|
||||
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.mockStatic(SubscriptionUtil::class.java)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking()
|
||||
|
||||
preferenceScreen.addPreference(preference)
|
||||
controller.displayPreference(preferenceScreen)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
mockSession.finishMocking()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun refreshData_getEmptyEid_preferenceIsNotVisible() = runBlocking {
|
||||
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
|
||||
whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
|
||||
listOf(
|
||||
SUB_INFO_1,
|
||||
SUB_INFO_2
|
||||
)
|
||||
)
|
||||
var mockSubId = 2
|
||||
controller.init(mockFragment, mockSubId)
|
||||
mockEid = String()
|
||||
|
||||
controller.refreshData(SUB_INFO_2)
|
||||
|
||||
assertThat(preference.isVisible).isEqualTo(false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun refreshData_getEmptyEid_preferenceSummaryIsExpected() = runBlocking {
|
||||
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
|
||||
whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
|
||||
listOf(
|
||||
SUB_INFO_1,
|
||||
SUB_INFO_2
|
||||
)
|
||||
)
|
||||
var mockSubId = 2
|
||||
controller.init(mockFragment, mockSubId)
|
||||
mockEid = "test eid"
|
||||
mockEuiccManager.stub {
|
||||
on {eid} doReturn mockEid
|
||||
}
|
||||
|
||||
controller.refreshData(SUB_INFO_2)
|
||||
|
||||
assertThat(preference.summary).isEqualTo(mockEid)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getAvailabilityStatus_notSimHardwareVisible() {
|
||||
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
|
||||
|
||||
val availabilityStatus = controller.availabilityStatus
|
||||
|
||||
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TEST_KEY = "test_key"
|
||||
const val DISPLAY_NAME_1 = "Sub 1"
|
||||
const val DISPLAY_NAME_2 = "Sub 2"
|
||||
|
||||
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||
setId(1)
|
||||
setDisplayName(DISPLAY_NAME_1)
|
||||
}.build()
|
||||
|
||||
val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||
setId(2)
|
||||
setDisplayName(DISPLAY_NAME_2)
|
||||
}.build()
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.TelephonyManager
|
||||
import android.telephony.euicc.EuiccManager
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito
|
||||
import com.android.internal.telephony.PhoneConstants
|
||||
import com.android.settings.core.BasePreferenceController
|
||||
import com.android.settings.network.SubscriptionInfoListViewModel
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.android.settingslib.CustomDialogPreferenceCompat
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.MockitoSession
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.stub
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.mockito.quality.Strictness
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MobileNetworkImeiPreferenceControllerTest {
|
||||
private lateinit var mockSession: MockitoSession
|
||||
|
||||
private val mockViewModels = mock<Lazy<SubscriptionInfoListViewModel>>()
|
||||
private val mockFragment = mock<Fragment>{
|
||||
val viewmodel = mockViewModels
|
||||
}
|
||||
|
||||
private var mockImei = String()
|
||||
private val mockTelephonyManager = mock<TelephonyManager> {
|
||||
on { uiccCardsInfo } doReturn listOf()
|
||||
on { createForSubscriptionId(any()) } doReturn mock
|
||||
on { currentPhoneType } doReturn TelephonyManager.PHONE_TYPE_GSM
|
||||
on { imei } doReturn mockImei
|
||||
on { meid } doReturn mockImei
|
||||
}
|
||||
|
||||
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||
on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
|
||||
}
|
||||
|
||||
private val controller = MobileNetworkImeiPreferenceController(context, TEST_KEY)
|
||||
private val preference = Preference(context).apply { key = TEST_KEY }
|
||||
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.mockStatic(SubscriptionUtil::class.java)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking()
|
||||
|
||||
preferenceScreen.addPreference(preference)
|
||||
controller.displayPreference(preferenceScreen)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
mockSession.finishMocking()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun refreshData_getPhoneNumber_preferenceSummaryIsExpected() = runBlocking {
|
||||
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
|
||||
whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
|
||||
listOf(
|
||||
SUB_INFO_1,
|
||||
SUB_INFO_2
|
||||
)
|
||||
)
|
||||
var mockSubId = 2
|
||||
controller.init(mockFragment, mockSubId)
|
||||
mockImei = "test imei"
|
||||
mockTelephonyManager.stub {
|
||||
on { imei } doReturn mockImei
|
||||
}
|
||||
|
||||
controller.refreshData(SUB_INFO_2)
|
||||
|
||||
assertThat(preference.summary).isEqualTo(mockImei)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getAvailabilityStatus_notSimHardwareVisible() {
|
||||
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
|
||||
|
||||
val availabilityStatus = controller.availabilityStatus
|
||||
|
||||
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TEST_KEY = "test_key"
|
||||
const val DISPLAY_NAME_1 = "Sub 1"
|
||||
const val DISPLAY_NAME_2 = "Sub 2"
|
||||
|
||||
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||
setId(1)
|
||||
setDisplayName(DISPLAY_NAME_1)
|
||||
}.build()
|
||||
|
||||
val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||
setId(2)
|
||||
setDisplayName(DISPLAY_NAME_2)
|
||||
}.build()
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.SubscriptionInfo
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito
|
||||
import com.android.settings.R
|
||||
import com.android.settings.core.BasePreferenceController
|
||||
import com.android.settings.network.SubscriptionInfoListViewModel
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.MockitoSession
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.mockito.quality.Strictness
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MobileNetworkPhoneNumberPreferenceControllerTest {
|
||||
private lateinit var mockSession: MockitoSession
|
||||
|
||||
private val mockViewModels = mock<Lazy<SubscriptionInfoListViewModel>>()
|
||||
private val mockFragment = mock<Fragment>{
|
||||
val viewmodel = mockViewModels
|
||||
}
|
||||
|
||||
private var mockPhoneNumber = String()
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
private val controller = MobileNetworkPhoneNumberPreferenceController(context, TEST_KEY)
|
||||
private val preference = Preference(context).apply { key = TEST_KEY }
|
||||
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.mockStatic(SubscriptionUtil::class.java)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking()
|
||||
|
||||
preferenceScreen.addPreference(preference)
|
||||
controller.displayPreference(preferenceScreen)
|
||||
|
||||
whenever(SubscriptionUtil.getBidiFormattedPhoneNumber(any(),any())).thenReturn(mockPhoneNumber)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
mockSession.finishMocking()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun refreshData_getEmptyPhoneNumber_preferenceIsNotVisible() = runBlocking {
|
||||
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
|
||||
whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
|
||||
listOf(
|
||||
SUB_INFO_1,
|
||||
SUB_INFO_2
|
||||
)
|
||||
)
|
||||
var mockSubId = 2
|
||||
controller.init(mockFragment, mockSubId)
|
||||
mockPhoneNumber = String()
|
||||
|
||||
controller.refreshData(SUB_INFO_2)
|
||||
|
||||
assertThat(preference.summary).isEqualTo(
|
||||
context.getString(R.string.device_info_default))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun refreshData_getPhoneNumber_preferenceSummaryIsExpected() = runBlocking {
|
||||
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
|
||||
whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
|
||||
listOf(
|
||||
SUB_INFO_1,
|
||||
SUB_INFO_2
|
||||
)
|
||||
)
|
||||
var mockSubId = 2
|
||||
controller.init(mockFragment, mockSubId)
|
||||
mockPhoneNumber = "test phone number"
|
||||
whenever(SubscriptionUtil.getBidiFormattedPhoneNumber(any(),any())).thenReturn(mockPhoneNumber)
|
||||
|
||||
controller.refreshData(SUB_INFO_2)
|
||||
|
||||
assertThat(preference.summary).isEqualTo(mockPhoneNumber)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getAvailabilityStatus_notSimHardwareVisible() {
|
||||
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
|
||||
|
||||
val availabilityStatus = controller.availabilityStatus
|
||||
|
||||
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TEST_KEY = "test_key"
|
||||
const val DISPLAY_NAME_1 = "Sub 1"
|
||||
const val DISPLAY_NAME_2 = "Sub 2"
|
||||
|
||||
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||
setId(1)
|
||||
setDisplayName(DISPLAY_NAME_1)
|
||||
}.build()
|
||||
|
||||
val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||
setId(2)
|
||||
setDisplayName(DISPLAY_NAME_2)
|
||||
}.build()
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.TelephonyManager
|
||||
import android.telephony.euicc.EuiccManager
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito
|
||||
import com.android.settings.core.BasePreferenceController
|
||||
import com.android.settings.network.SubscriptionInfoListViewModel
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.MockitoSession
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.mockito.quality.Strictness
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MobileNetworkSpnPreferenceControllerTest {
|
||||
private lateinit var mockSession: MockitoSession
|
||||
|
||||
private val mockViewModels = mock<Lazy<SubscriptionInfoListViewModel>>()
|
||||
private val mockFragment = mock<Fragment>{
|
||||
val viewmodel = mockViewModels
|
||||
}
|
||||
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
private val controller = MobileNetworkSpnPreferenceController(context, TEST_KEY)
|
||||
private val preference = Preference(context).apply { key = TEST_KEY }
|
||||
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.mockStatic(SubscriptionUtil::class.java)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking()
|
||||
|
||||
preferenceScreen.addPreference(preference)
|
||||
controller.displayPreference(preferenceScreen)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
mockSession.finishMocking()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun refreshData_getCarrierName_preferenceSummaryIsExpected() = runBlocking {
|
||||
var testList = listOf(
|
||||
SUB_INFO_1,
|
||||
SUB_INFO_2
|
||||
)
|
||||
whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(testList)
|
||||
var mockSubId = 2
|
||||
controller.init(mockFragment, mockSubId)
|
||||
|
||||
controller.refreshData(testList)
|
||||
|
||||
assertThat(preference.summary).isEqualTo(CARRIER_NAME_2)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TEST_KEY = "test_key"
|
||||
const val CARRIER_NAME_1 = "Sub 1"
|
||||
const val CARRIER_NAME_2 = "Sub 2"
|
||||
|
||||
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||
setId(1)
|
||||
setCarrierName(CARRIER_NAME_1)
|
||||
}.build()
|
||||
|
||||
val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||
setId(2)
|
||||
setCarrierName(CARRIER_NAME_2)
|
||||
}.build()
|
||||
|
||||
}
|
||||
}
|
@@ -98,6 +98,7 @@ public class MobileDataPreferenceControllerTest {
|
||||
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
|
||||
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager);
|
||||
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
|
||||
doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
@@ -182,7 +183,8 @@ public class MobileDataPreferenceControllerTest {
|
||||
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
|
||||
verify(mTelephonyManager).setDataEnabled(true);
|
||||
verify(mTelephonyManager).setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER
|
||||
,true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -195,7 +197,8 @@ public class MobileDataPreferenceControllerTest {
|
||||
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
|
||||
verify(mTelephonyManager).setDataEnabled(true);
|
||||
verify(mTelephonyManager).setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER
|
||||
,true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Reference in New Issue
Block a user