diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java index 25e0ae0765b..aa58663556f 100644 --- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java @@ -23,9 +23,11 @@ import android.content.Context; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.Log; +import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; @@ -59,16 +61,25 @@ public class EnabledNetworkModePreferenceController extends private CarrierConfigManager mCarrierConfigManager; private PreferenceEntriesBuilder mBuilder; private SubscriptionsChangeListener mSubscriptionsListener; + private int mCallState = TelephonyManager.CALL_STATE_IDLE; + private PhoneCallStateTelephonyCallback mTelephonyCallback; public EnabledNetworkModePreferenceController(Context context, String key) { super(context, key); mSubscriptionsListener = new SubscriptionsChangeListener(context, this); mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); + if (mTelephonyCallback == null) { + mTelephonyCallback = new PhoneCallStateTelephonyCallback(); + } } @Override public int getAvailabilityStatus(int subId) { boolean visible; + if (!isCallStateIdle()) { + return AVAILABLE_UNSEARCHABLE; + } + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { visible = false; @@ -87,23 +98,28 @@ public class EnabledNetworkModePreferenceController extends return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; } + protected boolean isCallStateIdle() { + return mCallState == TelephonyManager.CALL_STATE_IDLE; + } @OnLifecycleEvent(ON_START) public void onStart() { mSubscriptionsListener.start(); - if (mAllowedNetworkTypesListener == null) { + if (mAllowedNetworkTypesListener == null || mTelephonyCallback == null) { return; } mAllowedNetworkTypesListener.register(mContext, mSubId); + mTelephonyCallback.register(mTelephonyManager, mSubId); } @OnLifecycleEvent(ON_STOP) public void onStop() { mSubscriptionsListener.stop(); - if (mAllowedNetworkTypesListener == null) { + if (mAllowedNetworkTypesListener == null || mTelephonyCallback == null) { return; } mAllowedNetworkTypesListener.unregister(mContext, mSubId); + mTelephonyCallback.unregister(); } @Override @@ -125,6 +141,7 @@ public class EnabledNetworkModePreferenceController extends listPreference.setEntryValues(mBuilder.getEntryValues()); listPreference.setValue(Integer.toString(mBuilder.getSelectedEntryValue())); listPreference.setSummary(mBuilder.getSummary()); + listPreference.setEnabled(isCallStateIdle()); } @Override @@ -157,7 +174,6 @@ public class EnabledNetworkModePreferenceController extends updatePreference(); }); } - lifecycle.addObserver(this); } @@ -828,6 +844,43 @@ public class EnabledNetworkModePreferenceController extends } + @VisibleForTesting + class PhoneCallStateTelephonyCallback extends TelephonyCallback implements + TelephonyCallback.CallStateListener { + + private TelephonyManager mTelephonyManager; + + @Override + public void onCallStateChanged(int state) { + Log.d(LOG_TAG, "onCallStateChanged:" + state); + mCallState = state; + mBuilder.updateConfig(); + updatePreference(); + } + + public void register(TelephonyManager telephonyManager, int subId) { + mTelephonyManager = telephonyManager; + + // assign current call state so that it helps to show correct preference state even + // before first onCallStateChanged() by initial registration. + mCallState = mTelephonyManager.getCallState(subId); + mTelephonyManager.registerTelephonyCallback( + mContext.getMainExecutor(), mTelephonyCallback); + } + + public void unregister() { + mCallState = TelephonyManager.CALL_STATE_IDLE; + if (mTelephonyManager != null) { + mTelephonyManager.unregisterTelephonyCallback(this); + } + } + } + + @VisibleForTesting + PhoneCallStateTelephonyCallback getTelephonyCallback() { + return mTelephonyCallback; + } + @Override public void onAirplaneModeChanged(boolean airplaneModeEnabled) { } diff --git a/tests/unit/src/com/android/settings/network/EnabledNetworkModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/EnabledNetworkModePreferenceControllerTest.java index 81841b73760..20f8a551db0 100644 --- a/tests/unit/src/com/android/settings/network/EnabledNetworkModePreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/EnabledNetworkModePreferenceControllerTest.java @@ -19,6 +19,7 @@ package com.android.settings.network.telephony; import static androidx.lifecycle.Lifecycle.Event.ON_START; import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; import static com.android.settings.network.telephony.MobileNetworkUtils.getRafFromNetworkType; import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA; @@ -32,6 +33,8 @@ import static com.android.settings.network.telephony.TelephonyConstants.RadioAcc import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -152,6 +155,30 @@ public class EnabledNetworkModePreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); } + @UiThreadTest + @Test + public void getAvailabilityStatus_callStateIsIdle_returnAvailable() { + mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA); + mController.getTelephonyCallback().onCallStateChanged(TelephonyManager.CALL_STATE_IDLE); + + mController.updateState(mPreference); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + assertTrue(mPreference.isEnabled()); + } + + @UiThreadTest + @Test + public void getAvailabilityStatus_duringCalling_returnAvailable() { + mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA); + mController.getTelephonyCallback().onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK); + + mController.updateState(mPreference); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); + assertFalse(mPreference.isEnabled()); + } + @UiThreadTest @Test public void updateState_LteWorldPhone_GlobalHasLte() {