Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 562f56bb authored by Chaohui Wang's avatar Chaohui Wang
Browse files

Use wifiCallingReadyFlow in WifiCallingSettingsForSub

Simply and unify the logic, and fixed a crash.

Fix: 348372605
Flag: EXEMPT bug fix
Test: manual on Wi-Fi calling
Change-Id: Idc7dff934323fbebb09137bbd0585575e65a7867
parent 14303484
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -21,14 +21,16 @@ import android.telephony.AccessNetworkConstants
import android.telephony.CarrierConfigManager
import android.telephony.CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.ims.ImsMmTelManager.WiFiCallingMode
import android.telephony.ims.feature.MmTelFeature
import android.telephony.ims.stub.ImsRegistrationImplBase
import androidx.lifecycle.LifecycleOwner
import com.android.settings.network.telephony.ims.ImsMmTelRepository
import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl
import com.android.settings.network.telephony.ims.imsFeatureProvisionedFlow
import com.android.settings.network.telephony.subscriptionsChangedFlow
import com.android.settings.network.telephony.telephonyManager
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
@@ -38,13 +40,19 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext

class WifiCallingRepository(
interface IWifiCallingRepository {
    /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
    fun collectIsWifiCallingReadyFlow(lifecycleOwner: LifecycleOwner, action: (Boolean) -> Unit)
}

class WifiCallingRepository
@JvmOverloads
constructor(
    private val context: Context,
    private val subId: Int,
    private val imsMmTelRepository: ImsMmTelRepository = ImsMmTelRepositoryImpl(context, subId)
) {
    private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!
        .createForSubscriptionId(subId)
) : IWifiCallingRepository {
    private val telephonyManager = context.telephonyManager(subId)

    private val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java)!!

@@ -59,6 +67,14 @@ class WifiCallingRepository(
            .getConfigForSubId(subId, KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL)
            .getBoolean(KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL)

    /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
    override fun collectIsWifiCallingReadyFlow(
        lifecycleOwner: LifecycleOwner,
        action: (Boolean) -> Unit,
    ) {
        wifiCallingReadyFlow().collectLatestWithLifecycle(lifecycleOwner, action = action)
    }

    @OptIn(ExperimentalCoroutinesApi::class)
    fun wifiCallingReadyFlow(): Flow<Boolean> {
        if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
+30 −59
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.ProvisioningManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -42,12 +41,14 @@ import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceScreen;

import com.android.ims.ImsConfig;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.flags.Flags;
@@ -57,8 +58,12 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.network.ims.WifiCallingQueryImsState;
import com.android.settings.network.telephony.wificalling.IWifiCallingRepository;
import com.android.settings.network.telephony.wificalling.WifiCallingRepository;
import com.android.settings.widget.SettingsMainSwitchPreference;

import kotlin.Unit;

import java.util.List;

/**
@@ -103,7 +108,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment

    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private ImsMmTelManager mImsMmTelManager;
    private ProvisioningManager mProvisioningManager;
    private TelephonyManager mTelephonyManager;

    private PhoneTelephonyCallback mTelephonyCallback;
@@ -188,19 +192,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
                return true;
            };

    private final ProvisioningManager.Callback mProvisioningCallback =
            new ProvisioningManager.Callback() {
                @Override
                public void onProvisioningIntChanged(int item, int value) {
                    if (item == ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED
                            || item == ImsConfig.ConfigConstants.VLT_SETTING_ENABLED) {
                        // The provisioning policy might have changed. Update the body to make sure
                        // this change takes effect if needed.
                        updateBody();
                    }
                }
            };

    @VisibleForTesting
    void showAlert(Intent intent) {
        final Context context = getActivity();
@@ -263,14 +254,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
        return new WifiCallingQueryImsState(getContext(), subId);
    }

    @VisibleForTesting
    ProvisioningManager getImsProvisioningManager() {
        if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
            return null;
        }
        return ProvisioningManager.createForSubscriptionId(mSubId);
    }

    @VisibleForTesting
    ImsMmTelManager getImsMmTelManager() {
        if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
@@ -294,7 +277,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
                    FRAGMENT_BUNDLE_SUBID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        }

        mProvisioningManager = getImsProvisioningManager();
        mImsMmTelManager = getImsMmTelManager();

        mSwitchBar = (SettingsMainSwitchPreference) findPreference(SWITCH_BAR);
@@ -336,19 +318,33 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        getWifiCallingRepository().collectIsWifiCallingReadyFlow(
                getLifecycleOwner(), (isWifiWifiCallingReadyFlow) -> {
                    if (!isWifiWifiCallingReadyFlow) {
                        // This screen is not allowed to be shown due to provisioning policy and
                        // should therefore be closed.
                        finish();
                    }
                    return Unit.INSTANCE;
                });
    }

    @VisibleForTesting
    boolean isWfcProvisionedOnDevice() {
        return queryImsState(mSubId).isWifiCallingProvisioned();
    @NonNull
    IWifiCallingRepository getWifiCallingRepository() {
        return new WifiCallingRepository(requireContext(), mSubId);
    }

    private void updateBody() {
        if (!isWfcProvisionedOnDevice()) {
            // This screen is not allowed to be shown due to provisioning policy and should
            // therefore be closed.
            finish();
            return;
    @VisibleForTesting
    @NonNull
    LifecycleOwner getLifecycleOwner() {
        return getViewLifecycleOwner();
    }

    private void updateBody() {
        final CarrierConfigManager configManager = (CarrierConfigManager)
                getSystemService(Context.CARRIER_CONFIG_SERVICE);
        boolean isWifiOnlySupported = true;
@@ -448,8 +444,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
        if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) {
            showAlert(intent);
        }
        // Register callback for provisioning changes.
        registerProvisioningChangedCallback();
    }

    @Override
@@ -462,8 +456,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
            mSwitchBar.removeOnSwitchChangeListener(this);
        }
        context.unregisterReceiver(mIntentReceiver);
        // Remove callback for provisioning changes.
        unregisterProvisioningChangedCallback();
    }

    /**
@@ -699,27 +691,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
        return SubscriptionManager.getResourcesForSubId(getContext(), mSubId);
    }

    @VisibleForTesting
    void registerProvisioningChangedCallback() {
        if (mProvisioningManager == null) {
            return;
        }
        try {
            mProvisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
                    mProvisioningCallback);
        } catch (Exception ex) {
            Log.w(TAG, "onResume: Unable to register callback for provisioning changes.");
        }
    }

    @VisibleForTesting
    void unregisterProvisioningChangedCallback() {
        if (mProvisioningManager == null) {
            return;
        }
        mProvisioningManager.unregisterProvisioningChangedCallback(mProvisioningCallback);
    }

    /**
     * Determine whether to override roaming Wi-Fi calling preference when device is connected to
     * non-terrestrial network.
+33 −18
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ import android.telephony.TelephonyManager;
import android.telephony.ims.ImsMmTelManager;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

@@ -56,10 +58,14 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.network.ims.MockWifiCallingQueryImsState;
import com.android.settings.network.ims.WifiCallingQueryImsState;
import com.android.settings.network.telephony.wificalling.IWifiCallingRepository;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settings.widget.SettingsMainSwitchPreference;

import kotlin.Unit;
import kotlin.jvm.functions.Function1;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -183,35 +189,24 @@ public class WifiCallingSettingsForSubTest {
    }

    @Test
    public void onResume_provisioningAllowed_shouldNotFinish() {
        // Call onResume while provisioning is allowed.
        mFragment.onResume();
    public void onViewCreated_provisioningAllowed_shouldNotFinish() {
        // Call onViewCreated while provisioning is allowed.
        mFragment.onViewCreated(mView, null);

        // Verify that finish() is not called.
        verify(mFragment, never()).finish();
    }

    @Test
    public void onResume_provisioningDisallowed_shouldFinish() {
        // Call onResume while provisioning is disallowed.
        mQueryImsState.setIsProvisionedOnDevice(false);
        mFragment.onResume();
    public void onViewCreated_provisioningDisallowed_shouldFinish() {
        // Call onViewCreated while provisioning is disallowed.
        mFragment.mIsWifiCallingReady = false;
        mFragment.onViewCreated(mView, null);

        // Verify that finish() is called
        verify(mFragment).finish();
    }

    @Test
    public void onResumeOnPause_provisioningCallbackRegistration() throws Exception {
        // Verify that provisioning callback is registered after call to onResume().
        mFragment.onResume();
        verify(mFragment).registerProvisioningChangedCallback();

        // Verify that provisioning callback is unregistered after call to onPause.
        mFragment.onPause();
        verify(mFragment).unregisterProvisioningChangedCallback();
    }

    @Test
    public void onResume_useWfcHomeModeConfigFalseAndEditable_shouldShowWfcRoaming() {
        // Call onResume to update the WFC roaming preference.
@@ -377,6 +372,7 @@ public class WifiCallingSettingsForSubTest {

    protected class TestFragment extends WifiCallingSettingsForSub {
        private SettingsMainSwitchPreference mSwitchPref;
        protected boolean mIsWifiCallingReady = true;

        protected void setSwitchBar(SettingsMainSwitchPreference switchPref) {
            mSwitchPref = switchPref;
@@ -421,6 +417,25 @@ public class WifiCallingSettingsForSubTest {
            return mQueryImsState;
        }

        @Override
        @NonNull
        IWifiCallingRepository getWifiCallingRepository() {
            return new IWifiCallingRepository() {
                @Override
                public void collectIsWifiCallingReadyFlow(
                        @NonNull LifecycleOwner lifecycleOwner,
                        @NonNull Function1<? super Boolean, Unit> action) {
                    action.invoke(mIsWifiCallingReady);
                }
            };
        }

        @NonNull
        @Override
        LifecycleOwner getLifecycleOwner() {
            return this;
        }

        @Override
        void showAlert(Intent intent) {
        }