Merge "Add Private space Delete settings page inside PS settings page" into main
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index b5d0c59..a29e123 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -48,6 +48,23 @@
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"
settings:controller="com.android.settings.network.telephony.DataServiceSetupPreferenceController"
@@ -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"
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 29c3c62..62bc040 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -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"
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index d1bf808..8e583fd 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -56,28 +56,6 @@
}
@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);
if (!SubscriptionUtil.isSimHardwareVisible(mContext)) {
@@ -105,7 +83,7 @@
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 @@
}
@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 @@
@VisibleForTesting
protected Preference createNewPreference(Context context) {
- return new PhoneNumberSummaryPreference(context);
+ return new Preference(context);
}
}
diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
index 2045b96..ff55184 100644
--- a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
@@ -33,7 +33,6 @@
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 @@
multiImeiPreference.setKey(DEFAULT_KEY + (1 + simSlotNumber));
multiImeiPreference.setEnabled(true);
multiImeiPreference.setCopyingEnabled(true);
+
category.addPreference(multiImeiPreference);
}
}
@@ -112,11 +112,6 @@
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 @@
@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 @@
@VisibleForTesting
Preference createNewPreference(Context context) {
- return new PhoneNumberSummaryPreference(context);
+ return new Preference(context);
}
}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
index e0376dc..f765d8c 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
+++ b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
@@ -92,6 +92,7 @@
}
preference.title = title
preference.dialogTitle = title
+ preference.summary = eid
updateDialog()
}
}
@@ -130,9 +131,6 @@
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 {
diff --git a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
index 378d9a1..ef74a2e 100644
--- a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
+++ b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
@@ -42,6 +42,7 @@
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 @@
@Override
public int getAvailabilityStatus(int subId) {
- if (!SubscriptionManager.isValidSubscriptionId(subId)
+ if (Flags.isDualSimOnboardingEnabled()
+ || !SubscriptionManager.isValidSubscriptionId(subId)
|| SubscriptionManager.getDefaultDataSubscriptionId() == subId
|| (!hasMobileData())) {
return CONDITIONALLY_UNAVAILABLE;
diff --git a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java
index 206b3a9..03ce7f6 100644
--- a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java
+++ b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java
@@ -32,6 +32,7 @@
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 @@
@Override
public int getAvailabilityStatus(int subId) {
+ if (Flags.isDualSimOnboardingEnabled()) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
return AVAILABLE;
}
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index 06015d4..bec7ee7 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -34,6 +34,7 @@
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 @@
@Override
public int getAvailabilityStatus(int subId) {
+ if (Flags.isDualSimOnboardingEnabled()) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
? AVAILABLE
: AVAILABLE_UNSEARCHABLE;
diff --git a/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
new file mode 100644
index 0000000..907bab1
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
@@ -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
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
new file mode 100644
index 0000000..8ec313b
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
@@ -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"
+ }
+}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
new file mode 100644
index 0000000..65a4b7e
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
@@ -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)
+ }
+}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 4188f8d..2f2b20e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -85,6 +85,7 @@
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 @@
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 @@
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 @@
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) {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
new file mode 100644
index 0000000..ac055b0
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
@@ -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
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceControllerTest.kt
new file mode 100644
index 0000000..b035af5
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceControllerTest.kt
@@ -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()
+
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceControllerTest.kt
new file mode 100644
index 0000000..2f67846
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceControllerTest.kt
@@ -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()
+
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceControllerTest.kt
new file mode 100644
index 0000000..38c47c2
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceControllerTest.kt
@@ -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()
+
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceControllerTest.kt
new file mode 100644
index 0000000..f5592c1
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceControllerTest.kt
@@ -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()
+
+ }
+}
diff --git a/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
index 5f02b04..9a5399c 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
@@ -37,7 +37,6 @@
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,27 +88,10 @@
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 @@
@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 @@
@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 @@
@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 @@
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"));
}
}
diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
index 4d48025..11a490e 100644
--- a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
@@ -98,6 +98,7 @@
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 @@
mController.onPreferenceChange(mPreference, true);
- verify(mTelephonyManager).setDataEnabled(true);
+ verify(mTelephonyManager).setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER
+ ,true);
}
@Test
@@ -195,7 +197,8 @@
mController.onPreferenceChange(mPreference, true);
- verify(mTelephonyManager).setDataEnabled(true);
+ verify(mTelephonyManager).setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER
+ ,true);
}
@Test