Snap for 11386701 from 5fa73d14ab to 24Q2-release

Change-Id: Icd51bcbe5c0742ca73fa13f04c486db8483d93ff
This commit is contained in:
Android Build Coastguard Worker
2024-02-01 00:20:42 +00:00
20 changed files with 1198 additions and 73 deletions

View File

@@ -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"

View File

@@ -52,11 +52,12 @@
settings:controller="com.android.settings.deviceinfo.BrandedAccountPreferenceController"/>
<!-- Phone number -->
<com.android.settings.deviceinfo.PhoneNumberSummaryPreference
<Preference
android:key="phone_number"
android:order="3"
android:title="@string/status_number"
android:summary="@string/summary_placeholder"
android:selectable="false"
settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:controller="com.android.settings.deviceinfo.PhoneNumberPreferenceController"
settings:enableCopying="true"/>
@@ -118,7 +119,6 @@
android:key="eid_info"
android:order="31"
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:isPreferenceVisible="@bool/config_show_sim_info"
@@ -126,7 +126,7 @@
settings:controller="com.android.settings.deviceinfo.simstatus.SimEidPreferenceController"/>
<!-- IMEI -->
<com.android.settings.deviceinfo.PhoneNumberSummaryPreference
<Preference
android:key="imei_info"
android:order="32"
android:title="@string/status_imei"

View File

@@ -176,6 +176,7 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
public void on16kPagesDialogDismissed() {}
private void installUpdate() {
// Check if there is any pending system update
SystemUpdateManager manager = mContext.getSystemService(SystemUpdateManager.class);
Bundle data = manager.retrieveSystemUpdateInfo();
int status = data.getInt(SystemUpdateManager.KEY_STATUS);
@@ -184,6 +185,10 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
throw new RuntimeException("System has pending update!");
}
// Publish system update info
PersistableBundle info = createUpdateInfo(SystemUpdateManager.STATUS_IN_PROGRESS);
manager.updateSystemUpdateInfo(info);
String updateFilePath = mEnable16k ? OTA_16K_PATH : OTA_4K_PATH;
try {
File updateFile = new File(updateFilePath);
@@ -315,10 +320,10 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
mEnable16k ? ENABLE_16K_PAGE_SIZE : ENABLE_4K_PAGE_SIZE);
// Publish system update info
SystemUpdateManager manager =
(SystemUpdateManager)
mContext.getSystemService(Context.SYSTEM_UPDATE_SERVICE);
manager.updateSystemUpdateInfo(getUpdateInfo());
SystemUpdateManager manager = mContext.getSystemService(SystemUpdateManager.class);
PersistableBundle info =
createUpdateInfo(SystemUpdateManager.STATUS_WAITING_REBOOT);
manager.updateSystemUpdateInfo(info);
// Restart device to complete update
PowerManager pm = mContext.getSystemService(PowerManager.class);
@@ -345,10 +350,9 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
return builder.create();
}
private PersistableBundle getUpdateInfo() {
private PersistableBundle createUpdateInfo(int status) {
PersistableBundle infoBundle = new PersistableBundle();
infoBundle.putInt(
SystemUpdateManager.KEY_STATUS, SystemUpdateManager.STATUS_WAITING_REBOOT);
infoBundle.putInt(SystemUpdateManager.KEY_STATUS, status);
infoBundle.putBoolean(SystemUpdateManager.KEY_IS_SECURITY_UPDATE, false);
infoBundle.putString(SystemUpdateManager.KEY_TITLE, EXPERIMENTAL_UPDATE_TITLE);
return infoBundle;

View File

@@ -55,28 +55,6 @@ public class PhoneNumberPreferenceController extends BasePreferenceController {
AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public CharSequence getSummary() {
return mContext.getString(R.string.device_info_protected_single_press);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
String prefKey = preference.getKey();
if (prefKey.startsWith(KEY_PHONE_NUMBER)) {
int simSlotNumber = 0;
if (!TextUtils.equals(prefKey, KEY_PHONE_NUMBER)) {
// Get multisim slot number from preference key.
// Multisim preference key is KEY_PHONE_NUMBER + simSlotNumber
simSlotNumber = Integer.parseInt(
prefKey.replaceAll("[^0-9]", ""));
}
final Preference simStatusPreference = mPreferenceList.get(simSlotNumber);
simStatusPreference.setSummary(getPhoneNumber(simSlotNumber));
}
return super.handlePreferenceTreeClick(preference);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
@@ -105,7 +83,7 @@ public class PhoneNumberPreferenceController extends BasePreferenceController {
for (int simSlotNumber = 0; simSlotNumber < mPreferenceList.size(); simSlotNumber++) {
final Preference simStatusPreference = mPreferenceList.get(simSlotNumber);
simStatusPreference.setTitle(getPreferenceTitle(simSlotNumber));
simStatusPreference.setSummary(getSummary());
simStatusPreference.setSummary(getPhoneNumber(simSlotNumber));
}
}
@@ -155,7 +133,7 @@ public class PhoneNumberPreferenceController extends BasePreferenceController {
}
@VisibleForTesting
protected CharSequence getFormattedPhoneNumber(SubscriptionInfo subscriptionInfo) {
protected String getFormattedPhoneNumber(SubscriptionInfo subscriptionInfo) {
final String phoneNumber = SubscriptionUtil.getBidiFormattedPhoneNumber(mContext,
subscriptionInfo);
return TextUtils.isEmpty(phoneNumber) ? mContext.getString(R.string.device_info_default)
@@ -164,6 +142,6 @@ public class PhoneNumberPreferenceController extends BasePreferenceController {
@VisibleForTesting
protected Preference createNewPreference(Context context) {
return new PhoneNumberSummaryPreference(context);
return new Preference(context);
}
}

View File

@@ -33,7 +33,6 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.deviceinfo.PhoneNumberSummaryPreference;
import com.android.settings.deviceinfo.simstatus.SlotSimStatus;
import com.android.settings.network.SubscriptionUtil;
import com.android.settingslib.Utils;
@@ -103,6 +102,7 @@ public class ImeiInfoPreferenceController extends BasePreferenceController {
multiImeiPreference.setKey(DEFAULT_KEY + (1 + simSlotNumber));
multiImeiPreference.setEnabled(true);
multiImeiPreference.setCopyingEnabled(true);
category.addPreference(multiImeiPreference);
}
}
@@ -112,11 +112,6 @@ public class ImeiInfoPreferenceController extends BasePreferenceController {
updatePreference(preference, keyToSlotIndex(preference.getKey()));
}
@Override
public CharSequence getSummary() {
return mContext.getString(R.string.device_info_protected_single_press);
}
private CharSequence getSummary(int simSlot) {
final int phoneType = getPhoneType(simSlot);
return phoneType == PHONE_TYPE_CDMA ? mTelephonyManager.getMeid(simSlot)
@@ -150,8 +145,12 @@ public class ImeiInfoPreferenceController extends BasePreferenceController {
@VisibleForTesting
protected void updatePreference(Preference preference, int simSlot) {
if (simSlot < 0) {
preference.setVisible(false);
return;
}
preference.setTitle(getTitle(simSlot));
preference.setSummary(getSummary());
preference.setSummary(getSummary(simSlot));
}
private CharSequence getTitleForGsmPhone(int simSlot, boolean isPrimaryImei) {
@@ -195,6 +194,6 @@ public class ImeiInfoPreferenceController extends BasePreferenceController {
@VisibleForTesting
Preference createNewPreference(Context context) {
return new PhoneNumberSummaryPreference(context);
return new Preference(context);
}
}

View File

@@ -92,6 +92,7 @@ class SimEidPreferenceController(context: Context, preferenceKey: String) :
}
preference.title = title
preference.dialogTitle = title
preference.summary = eid
updateDialog()
}
}
@@ -130,9 +131,6 @@ class SimEidPreferenceController(context: Context, preferenceKey: String) :
val qrCodeView = dialog.requireViewById<ImageView>(R.id.esim_id_qrcode)
qrCodeView.setImageBitmap(getEidQrCode(eid))
// After "Tap to show", eid is displayed on preference.
preference.summary = textView.text
}
override fun handlePreferenceTreeClick(preference: Preference): Boolean {

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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
}
}
}
}

View File

@@ -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"
}
}

View File

@@ -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)
}
}

View File

@@ -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) {

View File

@@ -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
}
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony
import 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()
}
}

View File

@@ -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()
}
}

View File

@@ -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()
}
}

View File

@@ -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()
}
}

View File

@@ -37,7 +37,6 @@ import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.ResourcesUtils;
import org.junit.Before;
@@ -89,26 +88,9 @@ public class PhoneNumberPreferenceControllerTest {
mCategory.setKey(categoryKey);
mScreen.addPreference(mCategory);
doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(anyInt());
doReturn(mSecondPreference).when(mController).createNewPreference(mContext);
}
@Test
public void getAvailabilityStatus_isVoiceCapable_shouldBeAVAILABLE() {
when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_isNotVoiceCapable_shouldBeUNSUPPORTED_ON_DEVICE() {
when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.UNSUPPORTED_ON_DEVICE);
}
@Test
public void displayPreference_multiSim_shouldAddSecondPreference() {
when(mTelephonyManager.getPhoneCount()).thenReturn(2);
@@ -123,6 +105,7 @@ public class PhoneNumberPreferenceControllerTest {
@Test
public void updateState_singleSim_shouldUpdateTitleAndPhoneNumber() {
final String phoneNumber = "1111111111";
doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(anyInt());
doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
when(mTelephonyManager.getPhoneCount()).thenReturn(1);
mController.displayPreference(mScreen);
@@ -136,6 +119,7 @@ public class PhoneNumberPreferenceControllerTest {
@Test
public void updateState_multiSim_shouldUpdateTitleAndPhoneNumberOfMultiplePreferences() {
final String phoneNumber = "1111111111";
doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(anyInt());
doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
when(mTelephonyManager.getPhoneCount()).thenReturn(2);
mController.displayPreference(mScreen);
@@ -153,11 +137,11 @@ public class PhoneNumberPreferenceControllerTest {
@Test
public void getSummary_cannotGetActiveSubscriptionInfo_shouldShowUnknown() {
when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
mController.displayPreference(mScreen);
CharSequence primaryNumber = mController.getSummary();
mController.updateState(mPreference);
assertThat(primaryNumber).isNotNull();
assertThat(primaryNumber).isEqualTo(ResourcesUtils.getResourcesString(
verify(mPreference).setSummary(ResourcesUtils.getResourcesString(
mContext, "device_info_default"));
}
@@ -166,9 +150,10 @@ public class PhoneNumberPreferenceControllerTest {
List<SubscriptionInfo> infos = new ArrayList<>();
when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(infos);
CharSequence primaryNumber = mController.getSummary();
mController.displayPreference(mScreen);
mController.updateState(mPreference);
assertThat(primaryNumber).isEqualTo(ResourcesUtils.getResourcesString(
verify(mPreference).setSummary(ResourcesUtils.getResourcesString(
mContext, "device_info_default"));
}
}

View File

@@ -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