To disable the preferred network mode UI during calling.

It is the modem limitation, so disable the preferred network mode UI
during calling.

Bug: 206973375
Test: atest EnabledNetworkModePreferenceControllerTest
Change-Id: Ibb2904b4c6ff6de82063862188cc57e5c14b3aa5
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index 25e0ae0..aa58663 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.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 @@
     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 @@
 
         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 @@
         listPreference.setEntryValues(mBuilder.getEntryValues());
         listPreference.setValue(Integer.toString(mBuilder.getSelectedEntryValue()));
         listPreference.setSummary(mBuilder.getSummary());
+        listPreference.setEnabled(isCallStateIdle());
     }
 
     @Override
@@ -157,7 +174,6 @@
                         updatePreference();
                     });
         }
-
         lifecycle.addObserver(this);
     }
 
@@ -828,6 +844,43 @@
 
     }
 
+    @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 81841b7..20f8a55 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 @@
 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.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;
@@ -154,6 +157,30 @@
 
     @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() {
         mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);