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.material.icons.Icons
25 import androidx.compose.material.icons.outlined.Add
26 import androidx.compose.material.icons.outlined.SimCard
27 import androidx.compose.material.icons.outlined.SimCardDownload
28 import androidx.compose.runtime.Composable
29 import androidx.compose.runtime.State
30 import androidx.compose.runtime.getValue
31 import androidx.compose.runtime.remember
32 import androidx.compose.runtime.rememberCoroutineScope
33 import androidx.compose.ui.platform.LocalContext
34 import androidx.compose.ui.res.stringResource
35 import androidx.lifecycle.compose.collectAsStateWithLifecycle
36 import com.android.settings.R
37 import com.android.settings.Utils
38 import com.android.settings.network.SatelliteWarningDialogActivity
39 import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_BUTTON_NAME
40 import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_DESCRIPTION
41 import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_TITLE
42 import com.android.settings.network.SubscriptionUtil
43 import com.android.settings.network.telephony.MobileNetworkUtils
44 import com.android.settings.network.telephony.SubscriptionActivationRepository
45 import com.android.settings.network.telephony.SubscriptionRepository
46 import com.android.settings.network.telephony.euicc.EuiccRepository
47 import com.android.settings.network.telephony.phoneNumberFlow
48 import com.android.settingslib.spa.widget.preference.PreferenceModel
49 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
50 import com.android.settingslib.spa.widget.ui.Category
51 import com.android.settingslib.spa.widget.ui.SettingsIcon
52 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
53 import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference
54 import com.android.settingslib.spaprivileged.template.preference.RestrictedTwoTargetSwitchPreference
55 import kotlinx.coroutines.flow.flow
56 import kotlinx.coroutines.launch
57
58 @Composable
59 fun SimsSection(subscriptionInfoList: List<SubscriptionInfo>) {
60 Category {
61 for (subInfo in subscriptionInfoList) {
62 SimPreference(subInfo)
63 }
64
65 AddSim()
66 }
67 }
68
69 @Composable
SimPreferencenull70 private fun SimPreference(subInfo: SubscriptionInfo) {
71 val context = LocalContext.current
72 val checked = remember(subInfo.subscriptionId) {
73 SubscriptionRepository(context).isSubscriptionEnabledFlow(subInfo.subscriptionId)
74 }.collectAsStateWithLifecycle(initialValue = false)
75 val phoneNumber = phoneNumber(subInfo)
76 val isConvertedPsim by remember(subInfo) {
77 flow {
78 emit(SubscriptionUtil.isConvertedPsimSubscription(subInfo))
79 }
80 }.collectAsStateWithLifecycle(initialValue = false)
81 val subscriptionActivationRepository = remember { SubscriptionActivationRepository(context) }
82 val isActivationChangeable by remember {
83 subscriptionActivationRepository.isActivationChangeableFlow()
84 }.collectAsStateWithLifecycle(initialValue = false)
85 val coroutineScope = rememberCoroutineScope()
86 RestrictedTwoTargetSwitchPreference(
87 model = object : SwitchPreferenceModel {
88 override val title = subInfo.displayName.toString()
89 override val summary = {
90 if (isConvertedPsim) {
91 context.getString(R.string.sim_category_converted_sim)
92 } else {
93 phoneNumber.value ?: ""
94 }
95 }
96 override val icon = @Composable { SimIcon(subInfo.isEmbedded) }
97 override val changeable = { isActivationChangeable && !isConvertedPsim }
98 override val checked = { checked.value }
99 override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
100 coroutineScope.launch {
101 subscriptionActivationRepository.setActive(subInfo.subscriptionId, newChecked)
102 }
103 }
104 },
105 restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)),
106 primaryEnabled = { !isConvertedPsim },
107 ) {
108 MobileNetworkUtils.launchMobileNetworkSettings(context, subInfo)
109 }
110 }
111
112 @Composable
SimIconnull113 private fun SimIcon(isEmbedded: Boolean) {
114 SettingsIcon(if (isEmbedded) Icons.Outlined.SimCardDownload else Icons.Outlined.SimCard)
115 }
116
117 @Composable
phoneNumbernull118 fun phoneNumber(subInfo: SubscriptionInfo): State<String?> {
119 val context = LocalContext.current
120 return remember(subInfo) {
121 context.phoneNumberFlow(subInfo)
122 }.collectAsStateWithLifecycle(initialValue = null)
123 }
124
125 @Composable
AddSimnull126 private fun AddSim() {
127 val context = LocalContext.current
128 val isShow by
129 remember { EuiccRepository(context).showEuiccSettingsFlow() }
130 .collectAsStateWithLifecycle(initialValue = false)
131 if (isShow) {
132 RestrictedPreference(
133 model =
134 object : PreferenceModel {
135 override val title = stringResource(id = R.string.mobile_network_list_add_more)
136 override val icon = @Composable { SettingsIcon(Icons.Outlined.Add) }
137 override val onClick = { startAddSimFlow(context) }
138 },
139 restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)),
140 )
141 }
142 }
143
startAddSimFlownull144 fun startAddSimFlow(context: Context) = context.startActivity(getAddSimIntent())
145
146 fun getAddSimIntent() = Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION).apply {
147 setPackage(Utils.PHONE_PACKAGE_NAME)
148 putExtra(EuiccManager.EXTRA_FORCE_PROVISION, true)
149 }
150
startSatelliteWarningDialogFlownull151 fun startSatelliteWarningDialogFlow(context: Context) = context.startActivity(getSatelliteWarningDialogIntent(context))
152
153 fun getSatelliteWarningDialogIntent(context: Context) = Intent(context,
154 SatelliteWarningDialogActivity::class.java).apply {
155 val content = HashMap<Int, String>()
156 content.put(CUSTOM_CONTENT_TITLE, context.getString(R.string.title_satellite_dialog_for_sim_restriction))
157 content.put(CUSTOM_CONTENT_DESCRIPTION, context.getString(R.string.description_satellite_dialog_for_sim_restriction))
158 content.put(CUSTOM_CONTENT_BUTTON_NAME, context.getString(R.string.okay))
159 putExtra(SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_CUSTOMIZED_CONTENT, content)
160 }
161