Loading src/com/android/settings/network/telephony/CallingPreferenceCategoryController.java→src/com/android/settings/network/telephony/CallingPreferenceCategoryController.kt +48 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * Copyright (C) 2023 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 @@ -14,18 +14,35 @@ * limitations under the License. */ package com.android.settings.network.telephony; package com.android.settings.network.telephony import android.content.Context; import com.android.settings.widget.PreferenceCategoryController; import android.content.Context import androidx.preference.Preference import androidx.preference.PreferenceScreen import com.android.settings.core.BasePreferenceController /** * Preference controller for "Calling" category */ public class CallingPreferenceCategoryController extends PreferenceCategoryController { class CallingPreferenceCategoryController(context: Context, key: String) : BasePreferenceController(context, key) { private val visibleChildren = mutableSetOf<String>() private var preference: Preference? = null override fun getAvailabilityStatus() = AVAILABLE public CallingPreferenceCategoryController(Context context, String key) { super(context, key); override fun displayPreference(screen: PreferenceScreen) { // Not call super here, to avoid preference.isVisible changed unexpectedly preference = screen.findPreference(preferenceKey) } fun updateChildVisible(key: String, isVisible: Boolean) { if (isVisible) { visibleChildren.add(key) } else { visibleChildren.remove(key) } preference?.isVisible = visibleChildren.isNotEmpty() } } src/com/android/settings/network/telephony/MobileNetworkSettings.java +6 −5 Original line number Diff line number Diff line Loading @@ -269,8 +269,10 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme use(Enable2gPreferenceController.class).init(mSubId); use(CarrierWifiTogglePreferenceController.class).init(getLifecycle(), mSubId); final WifiCallingPreferenceController wifiCallingPreferenceController = use(WifiCallingPreferenceController.class).init(mSubId); final CallingPreferenceCategoryController callingPreferenceCategoryController = use(CallingPreferenceCategoryController.class); use(WifiCallingPreferenceController.class) .init(mSubId, callingPreferenceCategoryController); final OpenNetworkSelectPagePreferenceController openNetworkSelectPagePreferenceController = use(OpenNetworkSelectPagePreferenceController.class).init(mSubId); Loading @@ -286,9 +288,8 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId); final VideoCallingPreferenceController videoCallingPreferenceController = use(VideoCallingPreferenceController.class).init(mSubId); use(CallingPreferenceCategoryController.class).setChildren( Arrays.asList(wifiCallingPreferenceController, videoCallingPreferenceController)); use(VideoCallingPreferenceController.class) .init(mSubId, callingPreferenceCategoryController); use(Enhanced4gLtePreferenceController.class).init(mSubId) .addListener(videoCallingPreferenceController); use(Enhanced4gCallingPreferenceController.class).init(mSubId) Loading src/com/android/settings/network/telephony/VideoCallingPreferenceController.java +9 −1 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ public class VideoCallingPreferenceController extends TelephonyTogglePreferenceC @VisibleForTesting Integer mCallState; private MobileDataEnabledListener mDataContentObserver; private CallingPreferenceCategoryController mCallingPreferenceCategoryController; public VideoCallingPreferenceController(Context context, String key) { super(context, key); Loading Loading @@ -97,6 +98,8 @@ public class VideoCallingPreferenceController extends TelephonyTogglePreferenceC final TwoStatePreference switchPreference = (TwoStatePreference) preference; final boolean videoCallEnabled = isVideoCallEnabled(mSubId); switchPreference.setVisible(videoCallEnabled); mCallingPreferenceCategoryController .updateChildVisible(getPreferenceKey(), videoCallEnabled); if (videoCallEnabled) { final boolean videoCallEditable = queryVoLteState(mSubId).isEnabledByUser() && queryImsState(mSubId).isAllowUserControl(); Loading Loading @@ -136,8 +139,13 @@ public class VideoCallingPreferenceController extends TelephonyTogglePreferenceC PackageManager.FEATURE_TELEPHONY_IMS); } public VideoCallingPreferenceController init(int subId) { /** * Init instance of VideoCallingPreferenceController. */ public VideoCallingPreferenceController init( int subId, CallingPreferenceCategoryController callingPreferenceCategoryController) { mSubId = subId; mCallingPreferenceCategoryController = callingPreferenceCategoryController; return this; } Loading src/com/android/settings/network/telephony/WifiCallingPreferenceController.javadeleted 100644 → 0 +0 −230 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.PersistableBundle; import android.provider.Settings; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.ims.ImsMmTelManager; import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.network.ims.WifiCallingQueryImsState; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; import java.util.List; /** * Preference controller for "Wifi Calling" */ //TODO: Remove the class once Provider Model is always enabled in the future. public class WifiCallingPreferenceController extends TelephonyBasePreferenceController implements LifecycleObserver, OnStart, OnStop { private static final String TAG = "WifiCallingPreference"; @VisibleForTesting Integer mCallState; @VisibleForTesting CarrierConfigManager mCarrierConfigManager; private ImsMmTelManager mImsMmTelManager; @VisibleForTesting PhoneAccountHandle mSimCallManager; private PhoneTelephonyCallback mTelephonyCallback; private Preference mPreference; private boolean mHasException; public WifiCallingPreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mTelephonyCallback = new PhoneTelephonyCallback(); } @Override public int getAvailabilityStatus(int subId) { return SubscriptionManager.isValidSubscriptionId(subId) && MobileNetworkUtils.isWifiCallingEnabled(mContext, subId, null) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } @Override public void onStart() { mTelephonyCallback.register(mContext, mSubId); } @Override public void onStop() { mTelephonyCallback.unregister(); } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); final Intent intent = mPreference.getIntent(); if (intent != null) { intent.putExtra(Settings.EXTRA_SUB_ID, mSubId); } } @Override public void updateState(Preference preference) { super.updateState(preference); if ((mCallState == null) || (preference == null)) { Log.d(TAG, "Skip update under mCallState=" + mCallState); return; } mHasException = false; CharSequence summaryText = null; if (mSimCallManager != null) { final Intent intent = MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, mSimCallManager); if (intent == null) { // Do nothing in this case since preference is invisible return; } final PackageManager pm = mContext.getPackageManager(); final List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0); preference.setTitle(resolutions.get(0).loadLabel(pm)); preference.setIntent(intent); } else { final String title = SubscriptionManager.getResourcesForSubId(mContext, mSubId) .getString(R.string.wifi_calling_settings_title); preference.setTitle(title); summaryText = getResourceIdForWfcMode(mSubId); } preference.setSummary(summaryText); preference.setEnabled(mCallState == TelephonyManager.CALL_STATE_IDLE && !mHasException); } private CharSequence getResourceIdForWfcMode(int subId) { int resId = com.android.internal.R.string.wifi_calling_off_summary; if (queryImsState(subId).isEnabledByUser()) { boolean useWfcHomeModeForRoaming = false; if (mCarrierConfigManager != null) { final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); if (carrierConfig != null) { useWfcHomeModeForRoaming = carrierConfig.getBoolean( CarrierConfigManager .KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL); } } final boolean isRoaming = getTelephonyManager(mContext, subId) .isNetworkRoaming(); int wfcMode = ImsMmTelManager.WIFI_MODE_UNKNOWN; try { wfcMode = (isRoaming && !useWfcHomeModeForRoaming) ? mImsMmTelManager.getVoWiFiRoamingModeSetting() : mImsMmTelManager.getVoWiFiModeSetting(); } catch (IllegalArgumentException e) { mHasException = true; Log.e(TAG, "getResourceIdForWfcMode: Exception", e); } switch (wfcMode) { case ImsMmTelManager.WIFI_MODE_WIFI_ONLY: resId = com.android.internal.R.string.wfc_mode_wifi_only_summary; break; case ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED: resId = com.android.internal.R.string .wfc_mode_cellular_preferred_summary; break; case ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED: resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary; break; default: break; } } return SubscriptionManager.getResourcesForSubId(mContext, subId).getText(resId); } public WifiCallingPreferenceController init(int subId) { mSubId = subId; mImsMmTelManager = getImsMmTelManager(mSubId); mSimCallManager = mContext.getSystemService(TelecomManager.class) .getSimCallManagerForSubscription(mSubId); return this; } @VisibleForTesting WifiCallingQueryImsState queryImsState(int subId) { return new WifiCallingQueryImsState(mContext, subId); } protected ImsMmTelManager getImsMmTelManager(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { return null; } return ImsMmTelManager.createForSubscriptionId(subId); } @VisibleForTesting TelephonyManager getTelephonyManager(Context context, int subId) { final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); if (!SubscriptionManager.isValidSubscriptionId(subId)) { return telephonyMgr; } final TelephonyManager subscriptionTelephonyMgr = telephonyMgr.createForSubscriptionId(subId); return (subscriptionTelephonyMgr == null) ? telephonyMgr : subscriptionTelephonyMgr; } private class PhoneTelephonyCallback extends TelephonyCallback implements TelephonyCallback.CallStateListener { private TelephonyManager mTelephonyManager; @Override public void onCallStateChanged(int state) { mCallState = state; updateState(mPreference); } public void register(Context context, int subId) { mTelephonyManager = getTelephonyManager(context, subId); // assign current call state so that it helps to show correct preference state even // before first onCallStateChanged() by initial registration. mCallState = mTelephonyManager.getCallStateForSubscription(); mTelephonyManager.registerTelephonyCallback(context.getMainExecutor(), this); } public void unregister() { mCallState = null; mTelephonyManager.unregisterTelephonyCallback(this); } } } src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt 0 → 100644 +140 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.provider.Settings import android.telecom.TelecomManager import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import android.telephony.ims.ImsMmTelManager import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.preference.Preference import androidx.preference.PreferenceScreen import com.android.settings.R import com.android.settings.network.telephony.ims.ImsMmTelRepository import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** * Preference controller for "Wifi Calling". * * TODO: Remove the class once Provider Model is always enabled in the future. */ open class WifiCallingPreferenceController @JvmOverloads constructor( context: Context, key: String, private val callStateFlowFactory: (subId: Int) -> Flow<Int> = context::callStateFlow, private val imsMmTelRepositoryFactory: (subId: Int) -> ImsMmTelRepository = { subId -> ImsMmTelRepositoryImpl(context, subId) }, ) : TelephonyBasePreferenceController(context, key) { private lateinit var preference: Preference private lateinit var callingPreferenceCategoryController: CallingPreferenceCategoryController private val resourcesForSub by lazy { SubscriptionManager.getResourcesForSubId(mContext, mSubId) } fun init( subId: Int, callingPreferenceCategoryController: CallingPreferenceCategoryController, ): WifiCallingPreferenceController { mSubId = subId this.callingPreferenceCategoryController = callingPreferenceCategoryController return this } /** * Note: Visibility also controlled by [onViewCreated]. */ override fun getAvailabilityStatus(subId: Int) = if (SubscriptionManager.isValidSubscriptionId(subId)) AVAILABLE else CONDITIONALLY_UNAVAILABLE override fun displayPreference(screen: PreferenceScreen) { // Not call super here, to avoid preference.isVisible changed unexpectedly preference = screen.findPreference(preferenceKey)!! preference.intent?.putExtra(Settings.EXTRA_SUB_ID, mSubId) } override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) { viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { val isVisible = withContext(Dispatchers.Default) { MobileNetworkUtils.isWifiCallingEnabled(mContext, mSubId, null) } preference.isVisible = isVisible callingPreferenceCategoryController.updateChildVisible(preferenceKey, isVisible) } } viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { update() } } callStateFlowFactory(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) { preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE) } } private suspend fun update() { val simCallManager = mContext.getSystemService(TelecomManager::class.java) ?.getSimCallManagerForSubscription(mSubId) if (simCallManager != null) { val intent = withContext(Dispatchers.Default) { MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, simCallManager) } ?: return // Do nothing in this case since preference is invisible val title = withContext(Dispatchers.Default) { mContext.packageManager.resolveActivity(intent, 0) ?.loadLabel(mContext.packageManager) } ?: return preference.intent = intent preference.title = title preference.summary = null } else { preference.title = resourcesForSub.getString(R.string.wifi_calling_settings_title) preference.summary = withContext(Dispatchers.Default) { getSummaryForWfcMode() } } } private fun getSummaryForWfcMode(): String { val resId = when (imsMmTelRepositoryFactory(mSubId).getWiFiCallingMode()) { ImsMmTelManager.WIFI_MODE_WIFI_ONLY -> com.android.internal.R.string.wfc_mode_wifi_only_summary ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED -> com.android.internal.R.string.wfc_mode_cellular_preferred_summary ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED -> com.android.internal.R.string.wfc_mode_wifi_preferred_summary else -> com.android.internal.R.string.wifi_calling_off_summary } return resourcesForSub.getString(resId) } } Loading
src/com/android/settings/network/telephony/CallingPreferenceCategoryController.java→src/com/android/settings/network/telephony/CallingPreferenceCategoryController.kt +48 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * Copyright (C) 2023 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 @@ -14,18 +14,35 @@ * limitations under the License. */ package com.android.settings.network.telephony; package com.android.settings.network.telephony import android.content.Context; import com.android.settings.widget.PreferenceCategoryController; import android.content.Context import androidx.preference.Preference import androidx.preference.PreferenceScreen import com.android.settings.core.BasePreferenceController /** * Preference controller for "Calling" category */ public class CallingPreferenceCategoryController extends PreferenceCategoryController { class CallingPreferenceCategoryController(context: Context, key: String) : BasePreferenceController(context, key) { private val visibleChildren = mutableSetOf<String>() private var preference: Preference? = null override fun getAvailabilityStatus() = AVAILABLE public CallingPreferenceCategoryController(Context context, String key) { super(context, key); override fun displayPreference(screen: PreferenceScreen) { // Not call super here, to avoid preference.isVisible changed unexpectedly preference = screen.findPreference(preferenceKey) } fun updateChildVisible(key: String, isVisible: Boolean) { if (isVisible) { visibleChildren.add(key) } else { visibleChildren.remove(key) } preference?.isVisible = visibleChildren.isNotEmpty() } }
src/com/android/settings/network/telephony/MobileNetworkSettings.java +6 −5 Original line number Diff line number Diff line Loading @@ -269,8 +269,10 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme use(Enable2gPreferenceController.class).init(mSubId); use(CarrierWifiTogglePreferenceController.class).init(getLifecycle(), mSubId); final WifiCallingPreferenceController wifiCallingPreferenceController = use(WifiCallingPreferenceController.class).init(mSubId); final CallingPreferenceCategoryController callingPreferenceCategoryController = use(CallingPreferenceCategoryController.class); use(WifiCallingPreferenceController.class) .init(mSubId, callingPreferenceCategoryController); final OpenNetworkSelectPagePreferenceController openNetworkSelectPagePreferenceController = use(OpenNetworkSelectPagePreferenceController.class).init(mSubId); Loading @@ -286,9 +288,8 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId); final VideoCallingPreferenceController videoCallingPreferenceController = use(VideoCallingPreferenceController.class).init(mSubId); use(CallingPreferenceCategoryController.class).setChildren( Arrays.asList(wifiCallingPreferenceController, videoCallingPreferenceController)); use(VideoCallingPreferenceController.class) .init(mSubId, callingPreferenceCategoryController); use(Enhanced4gLtePreferenceController.class).init(mSubId) .addListener(videoCallingPreferenceController); use(Enhanced4gCallingPreferenceController.class).init(mSubId) Loading
src/com/android/settings/network/telephony/VideoCallingPreferenceController.java +9 −1 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ public class VideoCallingPreferenceController extends TelephonyTogglePreferenceC @VisibleForTesting Integer mCallState; private MobileDataEnabledListener mDataContentObserver; private CallingPreferenceCategoryController mCallingPreferenceCategoryController; public VideoCallingPreferenceController(Context context, String key) { super(context, key); Loading Loading @@ -97,6 +98,8 @@ public class VideoCallingPreferenceController extends TelephonyTogglePreferenceC final TwoStatePreference switchPreference = (TwoStatePreference) preference; final boolean videoCallEnabled = isVideoCallEnabled(mSubId); switchPreference.setVisible(videoCallEnabled); mCallingPreferenceCategoryController .updateChildVisible(getPreferenceKey(), videoCallEnabled); if (videoCallEnabled) { final boolean videoCallEditable = queryVoLteState(mSubId).isEnabledByUser() && queryImsState(mSubId).isAllowUserControl(); Loading Loading @@ -136,8 +139,13 @@ public class VideoCallingPreferenceController extends TelephonyTogglePreferenceC PackageManager.FEATURE_TELEPHONY_IMS); } public VideoCallingPreferenceController init(int subId) { /** * Init instance of VideoCallingPreferenceController. */ public VideoCallingPreferenceController init( int subId, CallingPreferenceCategoryController callingPreferenceCategoryController) { mSubId = subId; mCallingPreferenceCategoryController = callingPreferenceCategoryController; return this; } Loading
src/com/android/settings/network/telephony/WifiCallingPreferenceController.javadeleted 100644 → 0 +0 −230 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.PersistableBundle; import android.provider.Settings; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.ims.ImsMmTelManager; import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.network.ims.WifiCallingQueryImsState; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; import java.util.List; /** * Preference controller for "Wifi Calling" */ //TODO: Remove the class once Provider Model is always enabled in the future. public class WifiCallingPreferenceController extends TelephonyBasePreferenceController implements LifecycleObserver, OnStart, OnStop { private static final String TAG = "WifiCallingPreference"; @VisibleForTesting Integer mCallState; @VisibleForTesting CarrierConfigManager mCarrierConfigManager; private ImsMmTelManager mImsMmTelManager; @VisibleForTesting PhoneAccountHandle mSimCallManager; private PhoneTelephonyCallback mTelephonyCallback; private Preference mPreference; private boolean mHasException; public WifiCallingPreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mTelephonyCallback = new PhoneTelephonyCallback(); } @Override public int getAvailabilityStatus(int subId) { return SubscriptionManager.isValidSubscriptionId(subId) && MobileNetworkUtils.isWifiCallingEnabled(mContext, subId, null) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } @Override public void onStart() { mTelephonyCallback.register(mContext, mSubId); } @Override public void onStop() { mTelephonyCallback.unregister(); } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); final Intent intent = mPreference.getIntent(); if (intent != null) { intent.putExtra(Settings.EXTRA_SUB_ID, mSubId); } } @Override public void updateState(Preference preference) { super.updateState(preference); if ((mCallState == null) || (preference == null)) { Log.d(TAG, "Skip update under mCallState=" + mCallState); return; } mHasException = false; CharSequence summaryText = null; if (mSimCallManager != null) { final Intent intent = MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, mSimCallManager); if (intent == null) { // Do nothing in this case since preference is invisible return; } final PackageManager pm = mContext.getPackageManager(); final List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0); preference.setTitle(resolutions.get(0).loadLabel(pm)); preference.setIntent(intent); } else { final String title = SubscriptionManager.getResourcesForSubId(mContext, mSubId) .getString(R.string.wifi_calling_settings_title); preference.setTitle(title); summaryText = getResourceIdForWfcMode(mSubId); } preference.setSummary(summaryText); preference.setEnabled(mCallState == TelephonyManager.CALL_STATE_IDLE && !mHasException); } private CharSequence getResourceIdForWfcMode(int subId) { int resId = com.android.internal.R.string.wifi_calling_off_summary; if (queryImsState(subId).isEnabledByUser()) { boolean useWfcHomeModeForRoaming = false; if (mCarrierConfigManager != null) { final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); if (carrierConfig != null) { useWfcHomeModeForRoaming = carrierConfig.getBoolean( CarrierConfigManager .KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL); } } final boolean isRoaming = getTelephonyManager(mContext, subId) .isNetworkRoaming(); int wfcMode = ImsMmTelManager.WIFI_MODE_UNKNOWN; try { wfcMode = (isRoaming && !useWfcHomeModeForRoaming) ? mImsMmTelManager.getVoWiFiRoamingModeSetting() : mImsMmTelManager.getVoWiFiModeSetting(); } catch (IllegalArgumentException e) { mHasException = true; Log.e(TAG, "getResourceIdForWfcMode: Exception", e); } switch (wfcMode) { case ImsMmTelManager.WIFI_MODE_WIFI_ONLY: resId = com.android.internal.R.string.wfc_mode_wifi_only_summary; break; case ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED: resId = com.android.internal.R.string .wfc_mode_cellular_preferred_summary; break; case ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED: resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary; break; default: break; } } return SubscriptionManager.getResourcesForSubId(mContext, subId).getText(resId); } public WifiCallingPreferenceController init(int subId) { mSubId = subId; mImsMmTelManager = getImsMmTelManager(mSubId); mSimCallManager = mContext.getSystemService(TelecomManager.class) .getSimCallManagerForSubscription(mSubId); return this; } @VisibleForTesting WifiCallingQueryImsState queryImsState(int subId) { return new WifiCallingQueryImsState(mContext, subId); } protected ImsMmTelManager getImsMmTelManager(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { return null; } return ImsMmTelManager.createForSubscriptionId(subId); } @VisibleForTesting TelephonyManager getTelephonyManager(Context context, int subId) { final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); if (!SubscriptionManager.isValidSubscriptionId(subId)) { return telephonyMgr; } final TelephonyManager subscriptionTelephonyMgr = telephonyMgr.createForSubscriptionId(subId); return (subscriptionTelephonyMgr == null) ? telephonyMgr : subscriptionTelephonyMgr; } private class PhoneTelephonyCallback extends TelephonyCallback implements TelephonyCallback.CallStateListener { private TelephonyManager mTelephonyManager; @Override public void onCallStateChanged(int state) { mCallState = state; updateState(mPreference); } public void register(Context context, int subId) { mTelephonyManager = getTelephonyManager(context, subId); // assign current call state so that it helps to show correct preference state even // before first onCallStateChanged() by initial registration. mCallState = mTelephonyManager.getCallStateForSubscription(); mTelephonyManager.registerTelephonyCallback(context.getMainExecutor(), this); } public void unregister() { mCallState = null; mTelephonyManager.unregisterTelephonyCallback(this); } } }
src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt 0 → 100644 +140 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.provider.Settings import android.telecom.TelecomManager import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import android.telephony.ims.ImsMmTelManager import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.preference.Preference import androidx.preference.PreferenceScreen import com.android.settings.R import com.android.settings.network.telephony.ims.ImsMmTelRepository import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** * Preference controller for "Wifi Calling". * * TODO: Remove the class once Provider Model is always enabled in the future. */ open class WifiCallingPreferenceController @JvmOverloads constructor( context: Context, key: String, private val callStateFlowFactory: (subId: Int) -> Flow<Int> = context::callStateFlow, private val imsMmTelRepositoryFactory: (subId: Int) -> ImsMmTelRepository = { subId -> ImsMmTelRepositoryImpl(context, subId) }, ) : TelephonyBasePreferenceController(context, key) { private lateinit var preference: Preference private lateinit var callingPreferenceCategoryController: CallingPreferenceCategoryController private val resourcesForSub by lazy { SubscriptionManager.getResourcesForSubId(mContext, mSubId) } fun init( subId: Int, callingPreferenceCategoryController: CallingPreferenceCategoryController, ): WifiCallingPreferenceController { mSubId = subId this.callingPreferenceCategoryController = callingPreferenceCategoryController return this } /** * Note: Visibility also controlled by [onViewCreated]. */ override fun getAvailabilityStatus(subId: Int) = if (SubscriptionManager.isValidSubscriptionId(subId)) AVAILABLE else CONDITIONALLY_UNAVAILABLE override fun displayPreference(screen: PreferenceScreen) { // Not call super here, to avoid preference.isVisible changed unexpectedly preference = screen.findPreference(preferenceKey)!! preference.intent?.putExtra(Settings.EXTRA_SUB_ID, mSubId) } override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) { viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { val isVisible = withContext(Dispatchers.Default) { MobileNetworkUtils.isWifiCallingEnabled(mContext, mSubId, null) } preference.isVisible = isVisible callingPreferenceCategoryController.updateChildVisible(preferenceKey, isVisible) } } viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { update() } } callStateFlowFactory(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) { preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE) } } private suspend fun update() { val simCallManager = mContext.getSystemService(TelecomManager::class.java) ?.getSimCallManagerForSubscription(mSubId) if (simCallManager != null) { val intent = withContext(Dispatchers.Default) { MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, simCallManager) } ?: return // Do nothing in this case since preference is invisible val title = withContext(Dispatchers.Default) { mContext.packageManager.resolveActivity(intent, 0) ?.loadLabel(mContext.packageManager) } ?: return preference.intent = intent preference.title = title preference.summary = null } else { preference.title = resourcesForSub.getString(R.string.wifi_calling_settings_title) preference.summary = withContext(Dispatchers.Default) { getSummaryForWfcMode() } } } private fun getSummaryForWfcMode(): String { val resId = when (imsMmTelRepositoryFactory(mSubId).getWiFiCallingMode()) { ImsMmTelManager.WIFI_MODE_WIFI_ONLY -> com.android.internal.R.string.wfc_mode_wifi_only_summary ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED -> com.android.internal.R.string.wfc_mode_cellular_preferred_summary ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED -> com.android.internal.R.string.wfc_mode_wifi_preferred_summary else -> com.android.internal.R.string.wifi_calling_off_summary } return resourcesForSub.getString(resId) } }