1 /*
<lambda>null2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.settings.spa.network
18
19 import android.content.Context
20 import android.content.Intent
21 import android.os.UserManager
22 import android.telephony.SubscriptionInfo
23 import android.telephony.euicc.EuiccManager
24 import androidx.compose.foundation.layout.Column
25 import androidx.compose.material.icons.Icons
26 import androidx.compose.material.icons.outlined.Add
27 import androidx.compose.material.icons.outlined.SimCard
28 import androidx.compose.material.icons.outlined.SimCardDownload
29 import androidx.compose.runtime.Composable
30 import androidx.compose.runtime.State
31 import androidx.compose.runtime.getValue
32 import androidx.compose.runtime.remember
33 import androidx.compose.runtime.rememberCoroutineScope
34 import androidx.compose.ui.platform.LocalContext
35 import androidx.compose.ui.res.stringResource
36 import androidx.lifecycle.compose.collectAsStateWithLifecycle
37 import com.android.settings.R
38 import com.android.settings.Utils
39 import com.android.settings.network.SubscriptionUtil
40 import com.android.settings.network.telephony.MobileNetworkUtils
41 import com.android.settings.network.telephony.SubscriptionActivationRepository
42 import com.android.settings.network.telephony.SubscriptionRepository
43 import com.android.settings.network.telephony.phoneNumberFlow
44 import com.android.settingslib.spa.widget.preference.PreferenceModel
45 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
46 import com.android.settingslib.spa.widget.ui.SettingsIcon
47 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
48 import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference
49 import com.android.settingslib.spaprivileged.template.preference.RestrictedTwoTargetSwitchPreference
50 import kotlinx.coroutines.flow.flow
51 import kotlinx.coroutines.launch
52
53 @Composable
54 fun SimsSection(subscriptionInfoList: List<SubscriptionInfo>) {
55 Column {
56 for (subInfo in subscriptionInfoList) {
57 SimPreference(subInfo)
58 }
59
60 AddSim()
61 }
62 }
63
64 @Composable
SimPreferencenull65 private fun SimPreference(subInfo: SubscriptionInfo) {
66 val context = LocalContext.current
67 val checked = remember(subInfo.subscriptionId) {
68 SubscriptionRepository(context).isSubscriptionEnabledFlow(subInfo.subscriptionId)
69 }.collectAsStateWithLifecycle(initialValue = false)
70 val phoneNumber = phoneNumber(subInfo)
71 val isConvertedPsim by remember(subInfo) {
72 flow {
73 emit(SubscriptionUtil.isConvertedPsimSubscription(subInfo))
74 }
75 }.collectAsStateWithLifecycle(initialValue = false)
76 val subscriptionActivationRepository = remember { SubscriptionActivationRepository(context) }
77 val isActivationChangeable by remember {
78 subscriptionActivationRepository.isActivationChangeableFlow()
79 }.collectAsStateWithLifecycle(initialValue = false)
80 val coroutineScope = rememberCoroutineScope()
81 RestrictedTwoTargetSwitchPreference(
82 model = object : SwitchPreferenceModel {
83 override val title = subInfo.displayName.toString()
84 override val summary = {
85 if (isConvertedPsim) {
86 context.getString(R.string.sim_category_converted_sim)
87 } else {
88 phoneNumber.value ?: ""
89 }
90 }
91 override val icon = @Composable { SimIcon(subInfo.isEmbedded) }
92 override val changeable = { isActivationChangeable && !isConvertedPsim }
93 override val checked = { checked.value }
94 override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
95 coroutineScope.launch {
96 subscriptionActivationRepository.setActive(subInfo.subscriptionId, newChecked)
97 }
98 }
99 },
100 restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)),
101 primaryEnabled = { !isConvertedPsim },
102 ) {
103 MobileNetworkUtils.launchMobileNetworkSettings(context, subInfo)
104 }
105 }
106
107 @Composable
SimIconnull108 private fun SimIcon(isEmbedded: Boolean) {
109 SettingsIcon(if (isEmbedded) Icons.Outlined.SimCardDownload else Icons.Outlined.SimCard)
110 }
111
112 @Composable
phoneNumbernull113 fun phoneNumber(subInfo: SubscriptionInfo): State<String?> {
114 val context = LocalContext.current
115 return remember(subInfo) {
116 context.phoneNumberFlow(subInfo)
117 }.collectAsStateWithLifecycle(initialValue = null)
118 }
119
120 @Composable
AddSimnull121 private fun AddSim() {
122 val context = LocalContext.current
123 if (remember { MobileNetworkUtils.showEuiccSettings(context) }) {
124 RestrictedPreference(
125 model = object : PreferenceModel {
126 override val title = stringResource(id = R.string.mobile_network_list_add_more)
127 override val icon = @Composable { SettingsIcon(Icons.Outlined.Add) }
128 override val onClick = { startAddSimFlow(context) }
129 },
130 restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)),
131 )
132 }
133 }
134
startAddSimFlownull135 private fun startAddSimFlow(context: Context) {
136 val intent = Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION)
137 intent.setPackage(Utils.PHONE_PACKAGE_NAME)
138 intent.putExtra(EuiccManager.EXTRA_FORCE_PROVISION, true)
139 context.startActivity(intent)
140 }
141