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