• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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.network.telephony
18 
19 import android.content.Context
20 import android.provider.Settings
21 import android.telecom.TelecomManager
22 import android.telephony.SubscriptionManager
23 import android.telephony.TelephonyManager
24 import android.telephony.ims.ImsMmTelManager
25 import androidx.lifecycle.LifecycleOwner
26 import androidx.preference.Preference
27 import androidx.preference.PreferenceScreen
28 import com.android.settings.R
29 import com.android.settings.core.BasePreferenceController
30 import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchResult
31 import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem
32 import com.android.settings.network.telephony.wificalling.WifiCallingRepository
33 import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
34 import kotlinx.coroutines.Dispatchers
35 import kotlinx.coroutines.flow.first
36 import kotlinx.coroutines.runBlocking
37 import kotlinx.coroutines.withContext
38 
39 /**
40  * Preference controller for "Wifi Calling".
41  *
42  * TODO: Remove the class once Provider Model is always enabled in the future.
43  */
44 open class WifiCallingPreferenceController @JvmOverloads constructor(
45     context: Context,
46     key: String,
47     private val callStateRepository: CallStateRepository = CallStateRepository(context),
48     private val wifiCallingRepositoryFactory: (subId: Int) -> WifiCallingRepository = { subId ->
49         WifiCallingRepository(context, subId)
50     },
51 ) : BasePreferenceController(context, key) {
52 
53     private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
54     private lateinit var preference: Preference
55     private lateinit var callingPreferenceCategoryController: CallingPreferenceCategoryController
56 
<lambda>null57     private val resourcesForSub by lazy {
58         SubscriptionManager.getResourcesForSubId(mContext, subId)
59     }
60 
initnull61     fun init(
62         subId: Int,
63         callingPreferenceCategoryController: CallingPreferenceCategoryController,
64     ): WifiCallingPreferenceController {
65         this.subId = subId
66         this.callingPreferenceCategoryController = callingPreferenceCategoryController
67         return this
68     }
69 
70     /**
71      * Note: Visibility also controlled by [onViewCreated].
72      */
getAvailabilityStatusnull73     override fun getAvailabilityStatus() =
74         if (SubscriptionManager.isValidSubscriptionId(subId)) AVAILABLE
75         else CONDITIONALLY_UNAVAILABLE
76 
77     override fun displayPreference(screen: PreferenceScreen) {
78         // Not call super here, to avoid preference.isVisible changed unexpectedly
79         preference = screen.findPreference(preferenceKey)!!
80         preference.intent?.putExtra(Settings.EXTRA_SUB_ID, subId)
81     }
82 
onViewCreatednull83     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
84         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
85             // Sub id could invalid, if this page is opened from external action and no sim is
86             // active.
87             // Ignore this case, since this page will be finished soon.
88             return
89         }
90         wifiCallingRepositoryFactory(subId).wifiCallingReadyFlow()
91             .collectLatestWithLifecycle(viewLifecycleOwner) { isReady ->
92                 preference.isVisible = isReady
93                 callingPreferenceCategoryController.updateChildVisible(preferenceKey, isReady)
94                 if (isReady) update()
95             }
96 
97         callStateRepository.callStateFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
98             preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE)
99         }
100     }
101 
updatenull102     private suspend fun update() {
103         val simCallManager = mContext.getSystemService(TelecomManager::class.java)
104             ?.getSimCallManagerForSubscription(subId)
105         if (simCallManager != null) {
106             val intent = withContext(Dispatchers.Default) {
107                 MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, simCallManager)
108             } ?: return // Do nothing in this case since preference is invisible
109             val title = withContext(Dispatchers.Default) {
110                 mContext.packageManager.resolveActivity(intent, 0)
111                     ?.loadLabel(mContext.packageManager)
112             } ?: return
113             preference.intent = intent
114             preference.title = title
115             preference.summary = null
116         } else {
117             preference.title = resourcesForSub.getString(R.string.wifi_calling_settings_title)
118             preference.summary = withContext(Dispatchers.Default) { getSummaryForWfcMode() }
119         }
120     }
121 
getSummaryForWfcModenull122     private fun getSummaryForWfcMode(): String {
123         val resId = when (wifiCallingRepositoryFactory(subId).getWiFiCallingMode()) {
124             ImsMmTelManager.WIFI_MODE_WIFI_ONLY ->
125                 com.android.internal.R.string.wfc_mode_wifi_only_summary
126 
127             ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED ->
128                 com.android.internal.R.string.wfc_mode_cellular_preferred_summary
129 
130             ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED ->
131                 com.android.internal.R.string.wfc_mode_wifi_preferred_summary
132 
133             else -> com.android.internal.R.string.wifi_calling_off_summary
134         }
135         return resourcesForSub.getString(resId)
136     }
137 
138     companion object {
139         class WifiCallingSearchItem(
140             private val context: Context,
141         ) : MobileNetworkSettingsSearchItem {
<lambda>null142             private fun isAvailable(subId: Int): Boolean = runBlocking {
143                 WifiCallingRepository(context, subId).wifiCallingReadyFlow().first()
144             }
145 
getSearchResultnull146             override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {
147                 if (!isAvailable(subId)) return null
148                 return MobileNetworkSettingsSearchResult(
149                     key = "wifi_calling",
150                     title = context.getString(R.string.wifi_calling_settings_title),
151                 )
152             }
153         }
154     }
155 }
156