Loading src/com/android/settings/network/telephony/CallStateRepository.kt 0 → 100644 +64 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.network.telephony import android.content.Context import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import android.util.Log import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.onEach @OptIn(ExperimentalCoroutinesApi::class) class CallStateRepository(private val context: Context) { private val subscriptionManager = context.requireSubscriptionManager() /** Flow for call state of given [subId]. */ fun callStateFlow(subId: Int): Flow<Int> = context.telephonyCallbackFlow(subId) { object : TelephonyCallback(), TelephonyCallback.CallStateListener { override fun onCallStateChanged(state: Int) { trySend(state) } } } /** * Flow for in call state. * * @return true if any active subscription's call state is not idle. */ fun isInCallFlow(): Flow<Boolean> = context.subscriptionsChangedFlow() .flatMapLatest { val subIds = subscriptionManager.activeSubscriptionIdList combine(subIds.map(::callStateFlow)) { states -> states.any { it != TelephonyManager.CALL_STATE_IDLE } } } .conflate() .flowOn(Dispatchers.Default) .onEach { Log.d(TAG, "isInCallFlow: $it") } private companion object { private const val TAG = "CallStateRepository" } } src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.kt +4 −5 Original line number Diff line number Diff line Loading @@ -23,10 +23,8 @@ import android.telephony.TelephonyManager import androidx.lifecycle.LifecycleOwner import androidx.preference.Preference import androidx.preference.PreferenceScreen import com.android.settings.R import com.android.settings.core.BasePreferenceController import com.android.settings.network.SubscriptionUtil import com.android.settings.network.telephony.MobileNetworkUtils import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle /** This controls a preference allowing the user to delete the profile for an eSIM. */ Loading Loading @@ -57,7 +55,8 @@ class DeleteSimProfilePreferenceController(context: Context, preferenceKey: Stri } override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) { mContext.callStateFlow(subscriptionId).collectLatestWithLifecycle(viewLifecycleOwner) { CallStateRepository(mContext).callStateFlow(subscriptionId) .collectLatestWithLifecycle(viewLifecycleOwner) { preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE) } } Loading src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt +3 −11 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.settings.network.telephony import android.content.Context import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember Loading @@ -26,19 +25,17 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R import com.android.settings.network.SatelliteRepository import com.android.settings.network.SubscriptionUtil import com.android.settings.spa.preference.ComposePreferenceController import com.android.settingslib.spa.widget.preference.MainSwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map class MobileNetworkSwitchController @JvmOverloads constructor( context: Context, preferenceKey: String, private val subscriptionRepository: SubscriptionRepository = SubscriptionRepository(context), private val satelliteRepository: SatelliteRepository = SatelliteRepository(context) private val subscriptionActivationRepository: SubscriptionActivationRepository = SubscriptionActivationRepository(context), ) : ComposePreferenceController(context, preferenceKey) { private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID Loading @@ -57,12 +54,7 @@ class MobileNetworkSwitchController @JvmOverloads constructor( subscriptionRepository.isSubscriptionEnabledFlow(subId) }.collectAsStateWithLifecycle(initialValue = null) val changeable by remember { combine( context.callStateFlow(subId).map { it == TelephonyManager.CALL_STATE_IDLE }, satelliteRepository.getIsSessionStartedFlow() ) { isCallStateIdle, isSatelliteModemEnabled -> isCallStateIdle && !isSatelliteModemEnabled } subscriptionActivationRepository.isActivationChangeableFlow() }.collectAsStateWithLifecycle(initialValue = true) MainSwitchPreference(model = object : SwitchPreferenceModel { override val title = stringResource(R.string.mobile_network_use_sim_on) Loading src/com/android/settings/network/telephony/CallStateFlow.kt→src/com/android/settings/network/telephony/SubscriptionActivationRepository.kt +13 −10 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -17,16 +17,19 @@ package com.android.settings.network.telephony import android.content.Context import android.telephony.TelephonyCallback import com.android.settings.network.SatelliteRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine /** * Flow for call state. */ fun Context.callStateFlow(subId: Int): Flow<Int> = telephonyCallbackFlow(subId) { object : TelephonyCallback(), TelephonyCallback.CallStateListener { override fun onCallStateChanged(state: Int) { trySend(state) } class SubscriptionActivationRepository( private val context: Context, private val callStateRepository: CallStateRepository = CallStateRepository(context), private val satelliteRepository: SatelliteRepository = SatelliteRepository(context), ) { fun isActivationChangeableFlow(): Flow<Boolean> = combine( callStateRepository.isInCallFlow(), satelliteRepository.getIsSessionStartedFlow() ) { isInCall, isSatelliteModemEnabled -> !isInCall && !isSatelliteModemEnabled } } src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt +2 −3 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import com.android.settings.R import com.android.settings.network.telephony.wificalling.WifiCallingRepository import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.withContext /** Loading @@ -41,7 +40,7 @@ import kotlinx.coroutines.withContext open class WifiCallingPreferenceController @JvmOverloads constructor( context: Context, key: String, private val callStateFlowFactory: (subId: Int) -> Flow<Int> = context::callStateFlow, private val callStateRepository: CallStateRepository = CallStateRepository(context), private val wifiCallingRepositoryFactory: (subId: Int) -> WifiCallingRepository = { subId -> WifiCallingRepository(context, subId) }, Loading Loading @@ -91,7 +90,7 @@ open class WifiCallingPreferenceController @JvmOverloads constructor( if (isReady) update() } callStateFlowFactory(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) { callStateRepository.callStateFlow(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) { preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE) } } Loading Loading
src/com/android/settings/network/telephony/CallStateRepository.kt 0 → 100644 +64 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.network.telephony import android.content.Context import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import android.util.Log import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.onEach @OptIn(ExperimentalCoroutinesApi::class) class CallStateRepository(private val context: Context) { private val subscriptionManager = context.requireSubscriptionManager() /** Flow for call state of given [subId]. */ fun callStateFlow(subId: Int): Flow<Int> = context.telephonyCallbackFlow(subId) { object : TelephonyCallback(), TelephonyCallback.CallStateListener { override fun onCallStateChanged(state: Int) { trySend(state) } } } /** * Flow for in call state. * * @return true if any active subscription's call state is not idle. */ fun isInCallFlow(): Flow<Boolean> = context.subscriptionsChangedFlow() .flatMapLatest { val subIds = subscriptionManager.activeSubscriptionIdList combine(subIds.map(::callStateFlow)) { states -> states.any { it != TelephonyManager.CALL_STATE_IDLE } } } .conflate() .flowOn(Dispatchers.Default) .onEach { Log.d(TAG, "isInCallFlow: $it") } private companion object { private const val TAG = "CallStateRepository" } }
src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.kt +4 −5 Original line number Diff line number Diff line Loading @@ -23,10 +23,8 @@ import android.telephony.TelephonyManager import androidx.lifecycle.LifecycleOwner import androidx.preference.Preference import androidx.preference.PreferenceScreen import com.android.settings.R import com.android.settings.core.BasePreferenceController import com.android.settings.network.SubscriptionUtil import com.android.settings.network.telephony.MobileNetworkUtils import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle /** This controls a preference allowing the user to delete the profile for an eSIM. */ Loading Loading @@ -57,7 +55,8 @@ class DeleteSimProfilePreferenceController(context: Context, preferenceKey: Stri } override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) { mContext.callStateFlow(subscriptionId).collectLatestWithLifecycle(viewLifecycleOwner) { CallStateRepository(mContext).callStateFlow(subscriptionId) .collectLatestWithLifecycle(viewLifecycleOwner) { preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE) } } Loading
src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt +3 −11 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.settings.network.telephony import android.content.Context import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember Loading @@ -26,19 +25,17 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R import com.android.settings.network.SatelliteRepository import com.android.settings.network.SubscriptionUtil import com.android.settings.spa.preference.ComposePreferenceController import com.android.settingslib.spa.widget.preference.MainSwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map class MobileNetworkSwitchController @JvmOverloads constructor( context: Context, preferenceKey: String, private val subscriptionRepository: SubscriptionRepository = SubscriptionRepository(context), private val satelliteRepository: SatelliteRepository = SatelliteRepository(context) private val subscriptionActivationRepository: SubscriptionActivationRepository = SubscriptionActivationRepository(context), ) : ComposePreferenceController(context, preferenceKey) { private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID Loading @@ -57,12 +54,7 @@ class MobileNetworkSwitchController @JvmOverloads constructor( subscriptionRepository.isSubscriptionEnabledFlow(subId) }.collectAsStateWithLifecycle(initialValue = null) val changeable by remember { combine( context.callStateFlow(subId).map { it == TelephonyManager.CALL_STATE_IDLE }, satelliteRepository.getIsSessionStartedFlow() ) { isCallStateIdle, isSatelliteModemEnabled -> isCallStateIdle && !isSatelliteModemEnabled } subscriptionActivationRepository.isActivationChangeableFlow() }.collectAsStateWithLifecycle(initialValue = true) MainSwitchPreference(model = object : SwitchPreferenceModel { override val title = stringResource(R.string.mobile_network_use_sim_on) Loading
src/com/android/settings/network/telephony/CallStateFlow.kt→src/com/android/settings/network/telephony/SubscriptionActivationRepository.kt +13 −10 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -17,16 +17,19 @@ package com.android.settings.network.telephony import android.content.Context import android.telephony.TelephonyCallback import com.android.settings.network.SatelliteRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine /** * Flow for call state. */ fun Context.callStateFlow(subId: Int): Flow<Int> = telephonyCallbackFlow(subId) { object : TelephonyCallback(), TelephonyCallback.CallStateListener { override fun onCallStateChanged(state: Int) { trySend(state) } class SubscriptionActivationRepository( private val context: Context, private val callStateRepository: CallStateRepository = CallStateRepository(context), private val satelliteRepository: SatelliteRepository = SatelliteRepository(context), ) { fun isActivationChangeableFlow(): Flow<Boolean> = combine( callStateRepository.isInCallFlow(), satelliteRepository.getIsSessionStartedFlow() ) { isInCall, isSatelliteModemEnabled -> !isInCall && !isSatelliteModemEnabled } }
src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt +2 −3 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import com.android.settings.R import com.android.settings.network.telephony.wificalling.WifiCallingRepository import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.withContext /** Loading @@ -41,7 +40,7 @@ import kotlinx.coroutines.withContext open class WifiCallingPreferenceController @JvmOverloads constructor( context: Context, key: String, private val callStateFlowFactory: (subId: Int) -> Flow<Int> = context::callStateFlow, private val callStateRepository: CallStateRepository = CallStateRepository(context), private val wifiCallingRepositoryFactory: (subId: Int) -> WifiCallingRepository = { subId -> WifiCallingRepository(context, subId) }, Loading Loading @@ -91,7 +90,7 @@ open class WifiCallingPreferenceController @JvmOverloads constructor( if (isReady) update() } callStateFlowFactory(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) { callStateRepository.callStateFlow(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) { preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE) } } Loading