Merge "Add the UI of dual sim onboarding" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
4601261f81
@@ -11538,7 +11538,7 @@
|
|||||||
<!-- Button on the dual sim onboarding to go to next page. [CHAR LIMIT=30] -->
|
<!-- Button on the dual sim onboarding to go to next page. [CHAR LIMIT=30] -->
|
||||||
<string name="sim_onboarding_next">Next</string>
|
<string name="sim_onboarding_next">Next</string>
|
||||||
<!-- Text on the progressbar of dual sim onboarding for turning sim on. [CHAR LIMIT=30] -->
|
<!-- Text on the progressbar of dual sim onboarding for turning sim on. [CHAR LIMIT=30] -->
|
||||||
<string name="sim_onboarding_profressbar_turning_sim_on">Turning on <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>…</string>
|
<string name="sim_onboarding_progressbar_turning_sim_on">Turning on <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>…</string>
|
||||||
<!-- Title of service provider name(SPN) at mobile network settings page. [CHAR LIMIT=30] -->
|
<!-- Title of service provider name(SPN) at mobile network settings page. [CHAR LIMIT=30] -->
|
||||||
<string name="mobile_network_spn_title">Mobile network</string>
|
<string name="mobile_network_spn_title">Mobile network</string>
|
||||||
<!-- Title of phone number at mobile network settings page. [CHAR LIMIT=30] -->
|
<!-- Title of phone number at mobile network settings page. [CHAR LIMIT=30] -->
|
||||||
|
126
src/com/android/settings/network/SimOnboardingService.kt
Normal file
126
src/com/android/settings/network/SimOnboardingService.kt
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.telephony.SubscriptionInfo
|
||||||
|
import android.telephony.SubscriptionManager
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
|
import android.telephony.UiccCardInfo
|
||||||
|
import android.telephony.UiccSlotInfo
|
||||||
|
import android.util.Log
|
||||||
|
import com.android.settingslib.utils.ThreadUtils
|
||||||
|
|
||||||
|
|
||||||
|
private const val TAG = "SimOnboardingService"
|
||||||
|
private const val INVALID = -1
|
||||||
|
|
||||||
|
class SimOnboardingService {
|
||||||
|
var subscriptionManager:SubscriptionManager? = null
|
||||||
|
var telephonyManager:TelephonyManager? = null
|
||||||
|
|
||||||
|
var targetSubId: Int = INVALID
|
||||||
|
var targetSubInfo: SubscriptionInfo? = null
|
||||||
|
var availableSubInfoList: List<SubscriptionInfo> = listOf()
|
||||||
|
var activeSubInfoList: List<SubscriptionInfo> = listOf()
|
||||||
|
var slotInfoList: List<UiccSlotInfo> = listOf()
|
||||||
|
var uiccCardInfoList: List<UiccCardInfo> = listOf()
|
||||||
|
var selectedSubInfoList: MutableList<SubscriptionInfo> = mutableListOf()
|
||||||
|
var targetPrimarySimCalls: Int = -1
|
||||||
|
var targetPrimarySimTexts: Int = -1
|
||||||
|
var targetPrimarySimMobileData: Int = -1
|
||||||
|
var isMultipleEnabledProfilesSupported: Boolean = false
|
||||||
|
get() {
|
||||||
|
if (uiccCardInfoList.isEmpty()) {
|
||||||
|
Log.w(TAG, "UICC cards info list is empty.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return uiccCardInfoList.stream()
|
||||||
|
.anyMatch { cardInfo: UiccCardInfo -> cardInfo.isMultipleEnabledProfilesSupported }
|
||||||
|
}
|
||||||
|
var renameMutableMap : MutableMap<Int, String> = mutableMapOf()
|
||||||
|
|
||||||
|
fun isValid(): Boolean {
|
||||||
|
return targetSubId != INVALID
|
||||||
|
&& targetSubInfo != null
|
||||||
|
&& activeSubInfoList.isNotEmpty()
|
||||||
|
&& slotInfoList.isNotEmpty()
|
||||||
|
&& selectedSubInfoList.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
targetSubId = -1
|
||||||
|
targetSubInfo = null
|
||||||
|
availableSubInfoList = listOf()
|
||||||
|
activeSubInfoList = listOf()
|
||||||
|
slotInfoList = listOf()
|
||||||
|
uiccCardInfoList = listOf()
|
||||||
|
selectedSubInfoList = mutableListOf()
|
||||||
|
targetPrimarySimCalls = -1
|
||||||
|
targetPrimarySimTexts = -1
|
||||||
|
targetPrimarySimMobileData = -1
|
||||||
|
renameMutableMap.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun initData(inputTargetSubId:Int,context: Context) {
|
||||||
|
targetSubId = inputTargetSubId
|
||||||
|
subscriptionManager = context.getSystemService(SubscriptionManager::class.java)
|
||||||
|
telephonyManager = context.getSystemService(TelephonyManager::class.java)
|
||||||
|
|
||||||
|
ThreadUtils.postOnBackgroundThread {
|
||||||
|
activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
|
||||||
|
availableSubInfoList = SubscriptionUtil.getAvailableSubscriptions(context)
|
||||||
|
targetSubInfo = availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
|
||||||
|
Log.d(
|
||||||
|
TAG, "targetSubId: $targetSubId" + ", targetSubInfo: $targetSubInfo" +
|
||||||
|
". activeSubInfoList: $activeSubInfoList"
|
||||||
|
)
|
||||||
|
slotInfoList = telephonyManager?.uiccSlotsInfo?.toList() ?: listOf()
|
||||||
|
Log.d(TAG, "slotInfoList: $slotInfoList.")
|
||||||
|
uiccCardInfoList = telephonyManager?.uiccCardsInfo!!
|
||||||
|
Log.d(TAG, "uiccCardInfoList: $uiccCardInfoList")
|
||||||
|
|
||||||
|
Log.d(TAG, "isMultipleEnabledProfilesSupported: $isMultipleEnabledProfilesSupported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSelectableSubscriptionInfo(): List<SubscriptionInfo> {
|
||||||
|
var list: MutableList<SubscriptionInfo> = mutableListOf()
|
||||||
|
list.addAll(activeSubInfoList)
|
||||||
|
if (!list.contains(targetSubInfo)) {
|
||||||
|
targetSubInfo?.let { list.add(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "list: $list")
|
||||||
|
return list.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addItemForRenaming(subInfo: SubscriptionInfo, newName: String) {
|
||||||
|
if (subInfo.displayName == newName) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
renameMutableMap[subInfo.subscriptionId] = newName
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSubscriptionInfoDisplayName(subInfo: SubscriptionInfo): String {
|
||||||
|
return renameMutableMap[subInfo.subscriptionId] ?: subInfo.displayName.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startActivatingSim(callback:() -> Unit){
|
||||||
|
// TODO: start to activate sim
|
||||||
|
}
|
||||||
|
}
|
@@ -42,12 +42,14 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.internal.telephony.MccTable;
|
import com.android.internal.telephony.MccTable;
|
||||||
import com.android.internal.telephony.flags.Flags;
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.flags.Flags;
|
||||||
import com.android.settings.network.helper.SelectableSubscriptions;
|
import com.android.settings.network.helper.SelectableSubscriptions;
|
||||||
import com.android.settings.network.helper.SubscriptionAnnotation;
|
import com.android.settings.network.helper.SubscriptionAnnotation;
|
||||||
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
|
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
|
||||||
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
|
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
|
||||||
|
import com.android.settings.spa.SpaActivity;
|
||||||
|
import com.android.settings.spa.network.SimOnboardingPageProvider;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -543,6 +545,11 @@ public class SubscriptionUtil {
|
|||||||
Log.i(TAG, "Unable to toggle subscription due to invalid subscription ID.");
|
Log.i(TAG, "Unable to toggle subscription due to invalid subscription ID.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (enable && Flags.isDualSimOnboardingEnabled()) {
|
||||||
|
String route = SimOnboardingPageProvider.INSTANCE.getRoute(subId);
|
||||||
|
SpaActivity.startSpaActivity(context, route);
|
||||||
|
return;
|
||||||
|
}
|
||||||
context.startActivity(ToggleSubscriptionDialogActivity.getIntent(context, subId, enable));
|
context.startActivity(ToggleSubscriptionDialogActivity.getIntent(context, subId, enable));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -822,7 +829,7 @@ public class SubscriptionUtil {
|
|||||||
private static boolean isEmbeddedSubscriptionVisible(@NonNull SubscriptionInfo subInfo) {
|
private static boolean isEmbeddedSubscriptionVisible(@NonNull SubscriptionInfo subInfo) {
|
||||||
if (subInfo.isEmbedded()
|
if (subInfo.isEmbedded()
|
||||||
&& (subInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING
|
&& (subInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING
|
||||||
|| (Flags.oemEnabledSatelliteFlag()
|
|| (com.android.internal.telephony.flags.Flags.oemEnabledSatelliteFlag()
|
||||||
&& subInfo.isOnlyNonTerrestrialNetwork()))) {
|
&& subInfo.isOnlyNonTerrestrialNetwork()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -47,6 +47,7 @@ import com.android.settings.spa.development.UsageStatsPageProvider
|
|||||||
import com.android.settings.spa.development.compat.PlatformCompatAppListPageProvider
|
import com.android.settings.spa.development.compat.PlatformCompatAppListPageProvider
|
||||||
import com.android.settings.spa.home.HomePageProvider
|
import com.android.settings.spa.home.HomePageProvider
|
||||||
import com.android.settings.spa.network.NetworkAndInternetPageProvider
|
import com.android.settings.spa.network.NetworkAndInternetPageProvider
|
||||||
|
import com.android.settings.spa.network.SimOnboardingPageProvider
|
||||||
import com.android.settings.spa.notification.AppListNotificationsPageProvider
|
import com.android.settings.spa.notification.AppListNotificationsPageProvider
|
||||||
import com.android.settings.spa.notification.NotificationMainPageProvider
|
import com.android.settings.spa.notification.NotificationMainPageProvider
|
||||||
import com.android.settings.spa.system.AppLanguagesPageProvider
|
import com.android.settings.spa.system.AppLanguagesPageProvider
|
||||||
@@ -114,6 +115,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
|
|||||||
StorageAppListPageProvider.Apps,
|
StorageAppListPageProvider.Apps,
|
||||||
StorageAppListPageProvider.Games,
|
StorageAppListPageProvider.Games,
|
||||||
ApnEditPageProvider,
|
ApnEditPageProvider,
|
||||||
|
SimOnboardingPageProvider,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val logger = if (FeatureFlagUtils.isEnabled(
|
override val logger = if (FeatureFlagUtils.isEnabled(
|
||||||
|
113
src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
Normal file
113
src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* 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.spa.network
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.SignalCellularAlt
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.network.SimOnboardingService
|
||||||
|
import com.android.settings.network.SubscriptionUtil
|
||||||
|
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||||
|
import com.android.settingslib.spa.widget.dialog.AlertDialogButton
|
||||||
|
import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
|
||||||
|
import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField
|
||||||
|
|
||||||
|
import com.android.settingslib.spa.widget.preference.Preference
|
||||||
|
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||||
|
import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
|
||||||
|
import com.android.settingslib.spa.widget.scaffold.SuwScaffold
|
||||||
|
import com.android.settingslib.spa.widget.ui.SettingsBody
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the sim onboarding label compose
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun SimOnboardingLabelSimImpl(
|
||||||
|
nextAction: () -> Unit,
|
||||||
|
cancelAction: () -> Unit,
|
||||||
|
onboardingService: SimOnboardingService
|
||||||
|
) {
|
||||||
|
SuwScaffold(
|
||||||
|
imageVector = Icons.Outlined.SignalCellularAlt,
|
||||||
|
title = stringResource(R.string.sim_onboarding_label_sim_title),
|
||||||
|
actionButton = BottomAppBarButton(
|
||||||
|
stringResource(R.string.sim_onboarding_next),
|
||||||
|
nextAction
|
||||||
|
),
|
||||||
|
dismissButton = BottomAppBarButton(
|
||||||
|
stringResource(R.string.cancel),
|
||||||
|
cancelAction
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
labelSimBody(onboardingService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun labelSimBody(onboardingService: SimOnboardingService) {
|
||||||
|
Column(Modifier.padding(SettingsDimension.itemPadding)) {
|
||||||
|
SettingsBody(stringResource(R.string.sim_onboarding_label_sim_msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (subInfo in onboardingService.getSelectableSubscriptionInfo()) {
|
||||||
|
var titleSimName by remember {
|
||||||
|
mutableStateOf(
|
||||||
|
onboardingService.getSubscriptionInfoDisplayName(subInfo)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var summaryNumber = subInfo.number
|
||||||
|
// TODO using the SubscriptionUtil.getFormattedPhoneNumber
|
||||||
|
val alertDialogPresenter = rememberAlertDialogPresenter(
|
||||||
|
confirmButton = AlertDialogButton(
|
||||||
|
stringResource(R.string.mobile_network_sim_name_rename)
|
||||||
|
) {
|
||||||
|
onboardingService.addItemForRenaming(subInfo, titleSimName)
|
||||||
|
},
|
||||||
|
dismissButton = AlertDialogButton(stringResource(R.string.cancel)) {
|
||||||
|
titleSimName = onboardingService.getSubscriptionInfoDisplayName(subInfo)
|
||||||
|
},
|
||||||
|
title = stringResource(R.string.sim_onboarding_label_sim_dialog_title),
|
||||||
|
text = {
|
||||||
|
Text(summaryNumber)
|
||||||
|
SettingsOutlinedTextField(
|
||||||
|
value = titleSimName,
|
||||||
|
label = stringResource(R.string.sim_onboarding_label_sim_dialog_label),
|
||||||
|
enabled = true
|
||||||
|
) {
|
||||||
|
titleSimName = it
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Preference(object : PreferenceModel {
|
||||||
|
override val title = titleSimName
|
||||||
|
override val summary: () -> String
|
||||||
|
get() = { summaryNumber }
|
||||||
|
override val onClick = alertDialogPresenter::open
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.spa.network
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.ContextWrapper
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
|
import androidx.navigation.NavType
|
||||||
|
import androidx.navigation.compose.NavHost
|
||||||
|
import androidx.navigation.compose.composable
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import androidx.navigation.navArgument
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.network.SimOnboardingService
|
||||||
|
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||||
|
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||||
|
import com.android.settingslib.spa.framework.common.createSettingsPage
|
||||||
|
import com.android.settingslib.spa.framework.compose.navigator
|
||||||
|
|
||||||
|
import com.android.settingslib.spa.widget.preference.Preference
|
||||||
|
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||||
|
|
||||||
|
const val SUB_ID = "subId"
|
||||||
|
|
||||||
|
enum class SimOnboardingScreen(val stringResId: Int) {
|
||||||
|
LabelSim(R.string.sim_onboarding_label_sim_title),
|
||||||
|
SelectSim(R.string.sim_onboarding_select_sim_title),
|
||||||
|
PrimarySim(R.string.sim_onboarding_primary_sim_title)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Showing the sim onboarding which is the process flow of sim switching on.
|
||||||
|
*/
|
||||||
|
object SimOnboardingPageProvider : SettingsPageProvider {
|
||||||
|
override val name = "SimOnboardingPageProvider"
|
||||||
|
override val parameter = listOf(
|
||||||
|
navArgument(SUB_ID) { type = NavType.IntType },
|
||||||
|
)
|
||||||
|
|
||||||
|
private val owner = createSettingsPage()
|
||||||
|
@VisibleForTesting
|
||||||
|
var onboardingService: SimOnboardingService = SimOnboardingService()
|
||||||
|
|
||||||
|
fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = owner)
|
||||||
|
.setUiLayoutFn {
|
||||||
|
// never using
|
||||||
|
Preference(object : PreferenceModel {
|
||||||
|
override val title = name
|
||||||
|
override val onClick = navigator(getRoute(-1))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Page(arguments: Bundle?) {
|
||||||
|
initServiceData(arguments!!.getInt(SUB_ID))
|
||||||
|
PageImpl(onboardingService,rememberNavController())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRoute(
|
||||||
|
subId: Int
|
||||||
|
): String = "${name}/$subId"
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun initServiceData(targetSubId: Int) {
|
||||||
|
onboardingService.initData(targetSubId, LocalContext.current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Context.getActivity(): Activity? = when (this) {
|
||||||
|
is Activity -> this
|
||||||
|
is ContextWrapper -> baseContext.getActivity()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PageImpl(onboardingService:SimOnboardingService,navHostController: NavHostController) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
var previousPageOfOnboarding: () -> Unit = { context.getActivity()?.finish() }
|
||||||
|
|
||||||
|
NavHost(
|
||||||
|
navController = navHostController,
|
||||||
|
startDestination = SimOnboardingScreen.LabelSim.name
|
||||||
|
) {
|
||||||
|
composable(route = SimOnboardingScreen.LabelSim.name) {
|
||||||
|
val nextPage =
|
||||||
|
// Adding more conditions
|
||||||
|
if (onboardingService.isMultipleEnabledProfilesSupported) {
|
||||||
|
SimOnboardingScreen.SelectSim.name
|
||||||
|
} else {
|
||||||
|
SimOnboardingScreen.PrimarySim.name
|
||||||
|
}
|
||||||
|
SimOnboardingLabelSimImpl(
|
||||||
|
nextAction = { navHostController.navigate(nextPage) },
|
||||||
|
cancelAction = previousPageOfOnboarding,
|
||||||
|
onboardingService = onboardingService
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable(route = SimOnboardingScreen.PrimarySim.name) {
|
||||||
|
SimOnboardingPrimarySimImpl(
|
||||||
|
nextAction = {
|
||||||
|
//go back and activate sim
|
||||||
|
},
|
||||||
|
cancelAction = previousPageOfOnboarding,
|
||||||
|
onboardingService = onboardingService
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable(route = SimOnboardingScreen.SelectSim.name) {
|
||||||
|
SimOnboardingSelectSimImpl(
|
||||||
|
nextAction = { navHostController.navigate(SimOnboardingScreen.PrimarySim.name) },
|
||||||
|
cancelAction = previousPageOfOnboarding,
|
||||||
|
onboardingService = onboardingService
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
160
src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
Normal file
160
src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
Normal 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.spa.network
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.outlined.Message
|
||||||
|
import androidx.compose.material.icons.outlined.DataUsage
|
||||||
|
import androidx.compose.material.icons.outlined.SignalCellularAlt
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.MutableIntState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.res.vectorResource
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.network.SimOnboardingService
|
||||||
|
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||||
|
import com.android.settingslib.spa.widget.preference.ListPreference
|
||||||
|
import com.android.settingslib.spa.widget.preference.ListPreferenceModel
|
||||||
|
import com.android.settingslib.spa.widget.preference.ListPreferenceOption
|
||||||
|
import com.android.settingslib.spa.widget.preference.SwitchPreference
|
||||||
|
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
|
||||||
|
import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
|
||||||
|
import com.android.settingslib.spa.widget.scaffold.SuwScaffold
|
||||||
|
import com.android.settingslib.spa.widget.ui.SettingsBody
|
||||||
|
import com.android.settingslib.spa.widget.ui.SettingsIcon
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the sim onboarding primary sim compose
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun SimOnboardingPrimarySimImpl(
|
||||||
|
nextAction: () -> Unit,
|
||||||
|
cancelAction: () -> Unit,
|
||||||
|
onboardingService: SimOnboardingService
|
||||||
|
) {
|
||||||
|
SuwScaffold(
|
||||||
|
imageVector = Icons.Outlined.SignalCellularAlt,
|
||||||
|
title = stringResource(id = R.string.sim_onboarding_primary_sim_title),
|
||||||
|
actionButton = BottomAppBarButton(
|
||||||
|
stringResource(id = R.string.done),
|
||||||
|
nextAction
|
||||||
|
),
|
||||||
|
dismissButton = BottomAppBarButton(
|
||||||
|
stringResource(id = R.string.cancel),
|
||||||
|
cancelAction
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
primarySimBody(onboardingService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun primarySimBody(onboardingService: SimOnboardingService) {
|
||||||
|
//TODO: Load the status from the frameworks
|
||||||
|
var callsSelectedId = rememberSaveable { mutableIntStateOf(1) }
|
||||||
|
var textsSelectedId = rememberSaveable { mutableIntStateOf(1) }
|
||||||
|
var mobileDataSelectedId = rememberSaveable { mutableIntStateOf(1) }
|
||||||
|
var automaticDataChecked by rememberSaveable { mutableStateOf(true) }
|
||||||
|
|
||||||
|
Column(Modifier.padding(SettingsDimension.itemPadding)) {
|
||||||
|
SettingsBody(stringResource(id = R.string.sim_onboarding_primary_sim_msg))
|
||||||
|
}
|
||||||
|
var selectableSubscriptionInfo = onboardingService.getSelectableSubscriptionInfo()
|
||||||
|
var list = listOf(ListPreferenceOption(id = -1, text = "Loading"))
|
||||||
|
if (selectableSubscriptionInfo.size >= 2) {
|
||||||
|
list = listOf(
|
||||||
|
ListPreferenceOption(
|
||||||
|
id = selectableSubscriptionInfo[0].subscriptionId,
|
||||||
|
text = "${selectableSubscriptionInfo[0].displayName}"
|
||||||
|
),
|
||||||
|
ListPreferenceOption(
|
||||||
|
id = selectableSubscriptionInfo[1].subscriptionId,
|
||||||
|
text = "${selectableSubscriptionInfo[1].displayName}"
|
||||||
|
),
|
||||||
|
ListPreferenceOption(
|
||||||
|
id = -1,
|
||||||
|
text = stringResource(id = R.string.sim_calls_ask_first_prefs_title)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// set all of primary sim items' enable as false and showing that sim.
|
||||||
|
}
|
||||||
|
createPrimarySimListPreference(
|
||||||
|
stringResource(id = R.string.primary_sim_calls_title),
|
||||||
|
list,
|
||||||
|
callsSelectedId,
|
||||||
|
ImageVector.vectorResource(R.drawable.ic_phone),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
createPrimarySimListPreference(
|
||||||
|
stringResource(id = R.string.primary_sim_texts_title),
|
||||||
|
list,
|
||||||
|
textsSelectedId,
|
||||||
|
Icons.AutoMirrored.Outlined.Message,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
createPrimarySimListPreference(
|
||||||
|
stringResource(id = R.string.mobile_data_settings_title),
|
||||||
|
list,
|
||||||
|
mobileDataSelectedId,
|
||||||
|
Icons.Outlined.DataUsage,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
val autoDataTitle = stringResource(id = R.string.primary_sim_automatic_data_title)
|
||||||
|
val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
|
||||||
|
SwitchPreference(remember {
|
||||||
|
object : SwitchPreferenceModel {
|
||||||
|
override val title = autoDataTitle
|
||||||
|
override val summary = { autoDataSummary }
|
||||||
|
override val checked = { automaticDataChecked }
|
||||||
|
override val onCheckedChange =
|
||||||
|
{ newChecked: Boolean -> automaticDataChecked = newChecked }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun createPrimarySimListPreference(
|
||||||
|
title: String,
|
||||||
|
list: List<ListPreferenceOption>,
|
||||||
|
selectedId: MutableIntState,
|
||||||
|
icon: ImageVector,
|
||||||
|
enable: Boolean
|
||||||
|
) = ListPreference(remember {
|
||||||
|
object : ListPreferenceModel {
|
||||||
|
override val title = title
|
||||||
|
override val options = list
|
||||||
|
override val selectedId = selectedId
|
||||||
|
override val onIdSelected: (id: Int) -> Unit = { selectedId.intValue = it }
|
||||||
|
override val icon = @Composable {
|
||||||
|
SettingsIcon(icon)
|
||||||
|
}
|
||||||
|
override val enabled: () -> Boolean
|
||||||
|
get() = { enable }
|
||||||
|
}
|
||||||
|
})
|
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* 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.spa.network
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.SignalCellularAlt
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.network.SimOnboardingService
|
||||||
|
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||||
|
import com.android.settingslib.spa.widget.preference.CheckboxPreference
|
||||||
|
import com.android.settingslib.spa.widget.preference.CheckboxPreferenceModel
|
||||||
|
|
||||||
|
import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
|
||||||
|
import com.android.settingslib.spa.widget.scaffold.SuwScaffold
|
||||||
|
import com.android.settingslib.spa.widget.ui.SettingsBody
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the sim onboarding select sim compose
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun SimOnboardingSelectSimImpl(
|
||||||
|
nextAction: () -> Unit,
|
||||||
|
cancelAction: () -> Unit,
|
||||||
|
onboardingService: SimOnboardingService
|
||||||
|
) {
|
||||||
|
SuwScaffold(
|
||||||
|
imageVector = Icons.Outlined.SignalCellularAlt,
|
||||||
|
title = stringResource(id = R.string.sim_onboarding_select_sim_title),
|
||||||
|
actionButton = BottomAppBarButton(
|
||||||
|
stringResource(id = R.string.sim_onboarding_next),
|
||||||
|
nextAction
|
||||||
|
),
|
||||||
|
dismissButton = BottomAppBarButton(
|
||||||
|
stringResource(id = R.string.cancel),
|
||||||
|
cancelAction
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
selectSimBody(onboardingService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun selectSimBody(onboardingService: SimOnboardingService) {
|
||||||
|
Column(Modifier.padding(SettingsDimension.itemPadding)) {
|
||||||
|
SettingsBody(stringResource(id = R.string.sim_onboarding_select_sim_msg))
|
||||||
|
}
|
||||||
|
for (subInfo in onboardingService.getSelectableSubscriptionInfo()) {
|
||||||
|
var title = onboardingService.getSubscriptionInfoDisplayName(subInfo)
|
||||||
|
var summaryNumber =
|
||||||
|
subInfo.number // TODO using the SubscriptionUtil.getFormattedPhoneNumber
|
||||||
|
var changeable = subInfo.isActive
|
||||||
|
var checked by rememberSaveable { mutableStateOf(!subInfo.isActive) }
|
||||||
|
|
||||||
|
CheckboxPreference(remember {
|
||||||
|
object : CheckboxPreferenceModel {
|
||||||
|
override val title = title
|
||||||
|
override val summary: () -> String
|
||||||
|
get() = { summaryNumber }
|
||||||
|
override val checked = { checked }
|
||||||
|
override val changeable = { changeable }
|
||||||
|
override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* 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.spa.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.telephony.SubscriptionInfo
|
||||||
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performClick
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.network.SimOnboardingService
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.stub
|
||||||
|
import org.mockito.kotlin.verify
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class SimOnboardingLabelSimTest {
|
||||||
|
@get:Rule
|
||||||
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
private var mockSimOnboardingService = mock<SimOnboardingService> {
|
||||||
|
on { targetSubId }.doReturn(-1)
|
||||||
|
on { targetSubInfo }.doReturn(null)
|
||||||
|
on { availableSubInfoList }.doReturn(listOf())
|
||||||
|
on { activeSubInfoList }.doReturn(listOf())
|
||||||
|
on { slotInfoList }.doReturn(listOf())
|
||||||
|
on { uiccCardInfoList }.doReturn(listOf())
|
||||||
|
on { selectedSubInfoList }.doReturn(mutableListOf())
|
||||||
|
|
||||||
|
on { targetPrimarySimCalls }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
on { targetPrimarySimTexts }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
on { targetPrimarySimMobileData }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val nextAction: () -> Unit = mock()
|
||||||
|
private val cancelAction: () -> Unit = mock()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingLabelSimImpl_showTitle() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_label_sim_title))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingLabelSimImpl_showSubTitle() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_label_sim_msg))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingLabelSimImpl_clickNextAction_verifyNextAction() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_next))
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
verify(nextAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingLabelSimImpl_clickCancelAction_verifyCancelAction() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.cancel))
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
verify(cancelAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingLabelSimImpl_showItem_show3Items() {
|
||||||
|
mockSimOnboardingService.stub {
|
||||||
|
on { targetSubId }.doReturn(SUB_ID_1)
|
||||||
|
on { targetSubInfo }.doReturn(SUB_INFO_1)
|
||||||
|
on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
|
||||||
|
on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
|
||||||
|
on { getSelectableSubscriptionInfo() }.doReturn(
|
||||||
|
listOf(
|
||||||
|
SUB_INFO_1,
|
||||||
|
SUB_INFO_2,
|
||||||
|
SUB_INFO_3
|
||||||
|
)
|
||||||
|
)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_1) }.doReturn(DISPLAY_NAME_1)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_2) }.doReturn(DISPLAY_NAME_2)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_3) }.doReturn(DISPLAY_NAME_3)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(DISPLAY_NAME_1).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(NUMBER_1).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(DISPLAY_NAME_2).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(NUMBER_2).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(DISPLAY_NAME_3).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(NUMBER_3).assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingLabelSimImpl_showDialog_checkTitle() {
|
||||||
|
mockSimOnboardingService.stub {
|
||||||
|
on { targetSubId }.doReturn(SUB_ID_1)
|
||||||
|
on { targetSubInfo }.doReturn(SUB_INFO_1)
|
||||||
|
on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
|
||||||
|
on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
|
||||||
|
on { getSelectableSubscriptionInfo() }.doReturn(
|
||||||
|
listOf(
|
||||||
|
SUB_INFO_1,
|
||||||
|
SUB_INFO_2,
|
||||||
|
SUB_INFO_3
|
||||||
|
)
|
||||||
|
)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_1) }.doReturn(DISPLAY_NAME_1)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_2) }.doReturn(DISPLAY_NAME_2)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_3) }.doReturn(DISPLAY_NAME_3)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingLabelSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(DISPLAY_NAME_1).performClick()
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(
|
||||||
|
context.getString(R.string.sim_onboarding_label_sim_dialog_title)
|
||||||
|
)
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val SUB_ID_1 = 1
|
||||||
|
const val SUB_ID_2 = 2
|
||||||
|
const val SUB_ID_3 = 3
|
||||||
|
const val DISPLAY_NAME_1 = "Sub 1"
|
||||||
|
const val DISPLAY_NAME_2 = "Sub 2"
|
||||||
|
const val DISPLAY_NAME_3 = "Sub 3"
|
||||||
|
const val NUMBER_1 = "000000001"
|
||||||
|
const val NUMBER_2 = "000000002"
|
||||||
|
const val NUMBER_3 = "000000003"
|
||||||
|
const val PRIMARY_SIM_ASK_EVERY_TIME = -1
|
||||||
|
|
||||||
|
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_1)
|
||||||
|
setDisplayName(DISPLAY_NAME_1)
|
||||||
|
setNumber(NUMBER_1)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_2)
|
||||||
|
setDisplayName(DISPLAY_NAME_2)
|
||||||
|
setNumber(NUMBER_2)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_3: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_3)
|
||||||
|
setDisplayName(DISPLAY_NAME_3)
|
||||||
|
setNumber(NUMBER_3)
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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.spa.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performClick
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.network.SimOnboardingService
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.stub
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class SimOnboardingPageProviderTest {
|
||||||
|
@get:Rule
|
||||||
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
private var mockSimOnboardingService = mock<SimOnboardingService> {
|
||||||
|
on { targetSubId }.doReturn(SUB_ID)
|
||||||
|
on { targetSubInfo }.doReturn(null)
|
||||||
|
on { availableSubInfoList }.doReturn(listOf())
|
||||||
|
on { activeSubInfoList }.doReturn(listOf())
|
||||||
|
on { slotInfoList }.doReturn(listOf())
|
||||||
|
on { uiccCardInfoList }.doReturn(listOf())
|
||||||
|
on { selectedSubInfoList }.doReturn(mutableListOf())
|
||||||
|
|
||||||
|
on { targetPrimarySimCalls }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
on { targetPrimarySimTexts }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
on { targetPrimarySimMobileData }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingPageProvider_name() {
|
||||||
|
assertThat(SimOnboardingPageProvider.name).isEqualTo("SimOnboardingPageProvider")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingPage_labelSim() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
val navHostController = rememberNavController()
|
||||||
|
PageImpl(mockSimOnboardingService, navHostController)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_label_sim_title))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingPage_nextAction_fromLabelSimToPrimarySim() {
|
||||||
|
mockSimOnboardingService.stub {
|
||||||
|
on { isMultipleEnabledProfilesSupported }.thenReturn(false)
|
||||||
|
}
|
||||||
|
composeTestRule.setContent {
|
||||||
|
val navHostController = rememberNavController()
|
||||||
|
PageImpl(mockSimOnboardingService, navHostController)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_next))
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_primary_sim_title))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingPage_nextAction_fromLabelSimToSelectSim() {
|
||||||
|
mockSimOnboardingService.stub {
|
||||||
|
on { isMultipleEnabledProfilesSupported }.thenReturn(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.setContent {
|
||||||
|
val navHostController = rememberNavController()
|
||||||
|
PageImpl(mockSimOnboardingService, navHostController)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_next))
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_select_sim_title))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingPage_nextAction_fromSelectSimToPrimarySim() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
val navHostController = rememberNavController()
|
||||||
|
PageImpl(mockSimOnboardingService, navHostController)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_next))
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_primary_sim_title))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val SUB_ID = 1
|
||||||
|
const val PRIMARY_SIM_ASK_EVERY_TIME = -1
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* 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.spa.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.telephony.SubscriptionInfo
|
||||||
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performClick
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.network.SimOnboardingService
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.stub
|
||||||
|
import org.mockito.kotlin.verify
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class SimOnboardingPrimarySimTest {
|
||||||
|
@get:Rule
|
||||||
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
private var mockSimOnboardingService = mock<SimOnboardingService> {
|
||||||
|
on { targetSubId }.doReturn(-1)
|
||||||
|
on { targetSubInfo }.doReturn(null)
|
||||||
|
on { availableSubInfoList }.doReturn(listOf())
|
||||||
|
on { activeSubInfoList }.doReturn(listOf())
|
||||||
|
on { slotInfoList }.doReturn(listOf())
|
||||||
|
on { uiccCardInfoList }.doReturn(listOf())
|
||||||
|
on { selectedSubInfoList }.doReturn(mutableListOf())
|
||||||
|
|
||||||
|
on { targetPrimarySimCalls }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
on { targetPrimarySimTexts }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
on { targetPrimarySimMobileData }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val nextAction: () -> Unit = mock()
|
||||||
|
private val cancelAction: () -> Unit = mock()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingPrimarySimImpl_showTitle() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingPrimarySimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_primary_sim_title))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingPrimarySimImpl_showSubTitle() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingPrimarySimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_primary_sim_msg))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingPrimarySimImpl_clickCancelAction_verifyCancelAction() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingPrimarySimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.cancel))
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
verify(cancelAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val SUB_ID_1 = 1
|
||||||
|
const val SUB_ID_2 = 2
|
||||||
|
const val SUB_ID_3 = 3
|
||||||
|
const val DISPLAY_NAME_1 = "Sub 1"
|
||||||
|
const val DISPLAY_NAME_2 = "Sub 2"
|
||||||
|
const val DISPLAY_NAME_3 = "Sub 3"
|
||||||
|
const val NUMBER_1 = "000000001"
|
||||||
|
const val NUMBER_2 = "000000002"
|
||||||
|
const val NUMBER_3 = "000000003"
|
||||||
|
const val PRIMARY_SIM_ASK_EVERY_TIME = -1
|
||||||
|
|
||||||
|
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_1)
|
||||||
|
setDisplayName(DISPLAY_NAME_1)
|
||||||
|
setNumber(NUMBER_1)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_2)
|
||||||
|
setDisplayName(DISPLAY_NAME_2)
|
||||||
|
setNumber(NUMBER_2)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_3: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_3)
|
||||||
|
setDisplayName(DISPLAY_NAME_3)
|
||||||
|
setNumber(NUMBER_3)
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* 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.spa.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.telephony.SubscriptionInfo
|
||||||
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performClick
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.network.SimOnboardingService
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.stub
|
||||||
|
import org.mockito.kotlin.verify
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class SimOnboardingSelectSimTest {
|
||||||
|
@get:Rule
|
||||||
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
private var mockSimOnboardingService = mock<SimOnboardingService> {
|
||||||
|
on { targetSubId }.doReturn(-1)
|
||||||
|
on { targetSubInfo }.doReturn(null)
|
||||||
|
on { availableSubInfoList }.doReturn(listOf())
|
||||||
|
on { activeSubInfoList }.doReturn(listOf())
|
||||||
|
on { slotInfoList }.doReturn(listOf())
|
||||||
|
on { uiccCardInfoList }.doReturn(listOf())
|
||||||
|
on { selectedSubInfoList }.doReturn(mutableListOf())
|
||||||
|
|
||||||
|
on { targetPrimarySimCalls }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
on { targetPrimarySimTexts }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
on { targetPrimarySimMobileData }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val nextAction: () -> Unit = mock()
|
||||||
|
private val cancelAction: () -> Unit = mock()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingSelectSimImpl_showTitle() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingSelectSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_select_sim_title))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingSelectSimImpl_showSubTitle() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingSelectSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_select_sim_msg))
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingSelectSimImpl_clickNextAction_verifyNextAction() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingSelectSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.sim_onboarding_next))
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
verify(nextAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingSelectSimImpl_clickCancelAction_verifyCancelAction() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingSelectSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.cancel))
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
verify(cancelAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simOnboardingSelectSimImpl_showItem_show3Items() {
|
||||||
|
mockSimOnboardingService.stub {
|
||||||
|
on { targetSubId }.doReturn(SUB_ID_1)
|
||||||
|
on { targetSubInfo }.doReturn(SUB_INFO_1)
|
||||||
|
on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
|
||||||
|
on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
|
||||||
|
on { getSelectableSubscriptionInfo() }.doReturn(
|
||||||
|
listOf(
|
||||||
|
SUB_INFO_1,
|
||||||
|
SUB_INFO_2,
|
||||||
|
SUB_INFO_3
|
||||||
|
)
|
||||||
|
)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_1) }.doReturn(DISPLAY_NAME_1)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_2) }.doReturn(DISPLAY_NAME_2)
|
||||||
|
on { getSubscriptionInfoDisplayName(SUB_INFO_3) }.doReturn(DISPLAY_NAME_3)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.setContent {
|
||||||
|
SimOnboardingSelectSimImpl(nextAction, cancelAction, mockSimOnboardingService)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(DISPLAY_NAME_1).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(NUMBER_1).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(DISPLAY_NAME_2).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(NUMBER_2).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(DISPLAY_NAME_3).assertIsDisplayed()
|
||||||
|
composeTestRule.onNodeWithText(NUMBER_3).assertIsDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val SUB_ID_1 = 1
|
||||||
|
const val SUB_ID_2 = 2
|
||||||
|
const val SUB_ID_3 = 3
|
||||||
|
const val DISPLAY_NAME_1 = "Sub 1"
|
||||||
|
const val DISPLAY_NAME_2 = "Sub 2"
|
||||||
|
const val DISPLAY_NAME_3 = "Sub 3"
|
||||||
|
const val NUMBER_1 = "000000001"
|
||||||
|
const val NUMBER_2 = "000000002"
|
||||||
|
const val NUMBER_3 = "000000003"
|
||||||
|
const val PRIMARY_SIM_ASK_EVERY_TIME = -1
|
||||||
|
|
||||||
|
val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_1)
|
||||||
|
setDisplayName(DISPLAY_NAME_1)
|
||||||
|
setNumber(NUMBER_1)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_2)
|
||||||
|
setDisplayName(DISPLAY_NAME_2)
|
||||||
|
setNumber(NUMBER_2)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
val SUB_INFO_3: SubscriptionInfo = SubscriptionInfo.Builder().apply {
|
||||||
|
setId(SUB_ID_3)
|
||||||
|
setDisplayName(DISPLAY_NAME_3)
|
||||||
|
setNumber(NUMBER_3)
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user