• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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