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

Commit 6e5b8e47 authored by SongFerng Wang's avatar SongFerng Wang Committed by Android (Google) Code Review
Browse files

Merge "Move the auto data switch preference into DDS sim"

parents 76eabc6c 28ce6b90
Loading
Loading
Loading
Loading
+88 −9
Original line number Diff line number Diff line
@@ -22,8 +22,10 @@ import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;

import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
@@ -36,6 +38,8 @@ import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.network.MobileDataContentObserver;
import com.android.settings.network.SubscriptionsChangeListener;

import java.util.List;

/**
 * Controls whether switch mobile data to the non-default SIM if the non-default SIM has better
 * availability.
@@ -45,39 +49,88 @@ import com.android.settings.network.SubscriptionsChangeListener;
 * signal/connectivity.
 * If this feature is enabled, data will be temporarily enabled on the non-default data SIM,
 * including during any voice calls.
 *
 * Showing this preference in the default data sim UI.
 */
public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenceController
        implements LifecycleObserver,
        SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
    private static final String TAG = "AutoDataSwitchPreferenceController";

    private SwitchPreference mPreference;
    private SubscriptionsChangeListener mChangeListener;
    private TelephonyManager mManager;
    private MobileDataContentObserver mMobileDataContentObserver;
    private PreferenceScreen mScreen;
    private SubscriptionManager mSubscriptionManager;
    private List<SubscriptionInfo> mSubInfoList;

    public AutoDataSwitchPreferenceController(Context context,
            String preferenceKey) {
        super(context, preferenceKey);
        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
    }

    void init(int subId) {
        this.mSubId = subId;
        mManager = mContext.getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
        if (renewSubscriptionInfoList()) {
            // If the subscriptionInfos are changed, then
            mManager = mContext.getSystemService(TelephonyManager.class)
                    .createForSubscriptionId(getNonDdsSubId());
        }
        if (mMobileDataContentObserver == null) {
            mMobileDataContentObserver = new MobileDataContentObserver(
                    new Handler(Looper.getMainLooper()));
            mMobileDataContentObserver.setOnMobileDataChangedListener(() -> {
                mManager = mContext.getSystemService(TelephonyManager.class)
                        .createForSubscriptionId(getNonDdsSubId());
                refreshPreference();
            });
        }
    }

    private void renewTelephonyComponent() {
        if (renewSubscriptionInfoList()) {
            // If the subscriptionInfos are changed, then
            if (mMobileDataContentObserver != null) {
                mMobileDataContentObserver.unRegister(mContext);
            }
        }
        if (mSubInfoList == null) {
            Log.d(TAG, "mSubInfoList is null. Stop to register the listener");
            return;
        }
        if (mMobileDataContentObserver != null) {
            for (SubscriptionInfo subInfo : mSubInfoList) {
                mMobileDataContentObserver.register(mContext, subInfo.getSubscriptionId());
            }
        }
        mManager = mContext.getSystemService(TelephonyManager.class)
                .createForSubscriptionId(getNonDdsSubId());
    }

    /**
     * Renew the subscriptionInfoList if the subscriptionInfos are changed.
     * @return true if the subscriptionInfos are changed. Otherwise, return false.
     */
    private boolean renewSubscriptionInfoList() {
        final List<SubscriptionInfo> newSubInfoList =
                mSubscriptionManager.getActiveSubscriptionInfoList();
        if ((newSubInfoList == null && mSubInfoList == null)
                || (mSubInfoList != null && mSubInfoList.equals(newSubInfoList))) {
            return false;
        }
        mSubInfoList = newSubInfoList;
        return true;
    }

    @OnLifecycleEvent(ON_RESUME)
    public void onResume() {
        renewTelephonyComponent();
        if (mChangeListener == null) {
            mChangeListener = new SubscriptionsChangeListener(mContext, this);
        }
        mChangeListener.start();
        if (mMobileDataContentObserver == null) {
            mMobileDataContentObserver = new MobileDataContentObserver(
                    new Handler(Looper.getMainLooper()));
            mMobileDataContentObserver.setOnMobileDataChangedListener(() -> refreshPreference());
        }
        mMobileDataContentObserver.register(mContext, mSubId);
    }

    @OnLifecycleEvent(ON_PAUSE)
@@ -105,6 +158,10 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc

    @Override
    public boolean setChecked(boolean isChecked) {
        if (mManager == null) {
            Log.d(TAG, "mManager is null.");
            return false;
        }
        mManager.setMobileDataPolicyEnabled(
                TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
                isChecked);
@@ -119,7 +176,8 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
    @Override
    public int getAvailabilityStatus(int subId) {
        if (!SubscriptionManager.isValidSubscriptionId(subId)
                || SubscriptionManager.getDefaultDataSubscriptionId() == subId
                || SubscriptionManager.getDefaultDataSubscriptionId() != subId
                || !SubscriptionManager.isValidSubscriptionId(getNonDdsSubId())
                || (!hasMobileData())) {
            return CONDITIONALLY_UNAVAILABLE;
        }
@@ -136,10 +194,12 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
    }

    @Override
    public void onAirplaneModeChanged(boolean airplaneModeEnabled) {}
    public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
    }

    @Override
    public void onSubscriptionsChanged() {
        renewTelephonyComponent();
        updateState(mPreference);
    }

@@ -152,4 +212,23 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
            super.displayPreference(mScreen);
        }
    }

    private int getNonDdsSubId() {
        int ddsSubId = SubscriptionManager.getDefaultDataSubscriptionId();
        Log.d(TAG, "DDS SubId: " + ddsSubId);

        if (ddsSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        }

        if (mSubInfoList == null) {
            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        }

        return mSubInfoList.stream()
                .mapToInt(subInfo -> subInfo.getSubscriptionId())
                .filter(subId -> subId != ddsSubId)
                .findFirst()
                .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
    }
}
+37 −16
Original line number Diff line number Diff line
@@ -28,13 +28,18 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;

import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;

import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;

import com.google.common.collect.ImmutableList;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,10 +61,15 @@ public class AutoDataSwitchPreferenceControllerTest {
    private TelephonyManager mTelephonyManager;
    @Mock
    private PreferenceScreen mPreferenceScreen;
    @Mock
    private SubscriptionInfo mSubscriptionInfo1;
    @Mock
    private SubscriptionInfo mSubscriptionInfo2;

    private Context mContext;
    private SwitchPreference mSwitchPreference;
    private AutoDataSwitchPreferenceController mController;
    private ShadowSubscriptionManager mShadowSubscriptionManager;

    @Before
    public void setUp() {
@@ -69,6 +79,11 @@ public class AutoDataSwitchPreferenceControllerTest {
        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
        mSwitchPreference = new SwitchPreference(mContext);
        when(mPreferenceScreen.findPreference(PREF_KEY)).thenReturn(mSwitchPreference);
        when(mSubscriptionInfo1.getSubscriptionId()).thenReturn(SUB_ID_1);
        when(mSubscriptionInfo2.getSubscriptionId()).thenReturn(SUB_ID_2);
        mShadowSubscriptionManager = shadowOf(mContext.getSystemService(SubscriptionManager.class));
        mShadowSubscriptionManager.setActiveSubscriptionInfoList(ImmutableList.of(
                mSubscriptionInfo1, mSubscriptionInfo2));
        mController = new AutoDataSwitchPreferenceController(mContext, PREF_KEY) {
            @Override
            protected boolean hasMobileData() {
@@ -90,66 +105,72 @@ public class AutoDataSwitchPreferenceControllerTest {
    }

    @Test
    public void displayPreference_defaultForData_notAvailable() {
    public void displayPreference_defaultForData_available() {
        ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_1);
        mController.init(SUB_ID_1);

        mController.displayPreference(mPreferenceScreen);

        assertThat(mController.isAvailable()).isFalse();
        assertThat(mSwitchPreference.isVisible()).isFalse();
        assertThat(mController.isAvailable()).isTrue();
        assertThat(mSwitchPreference.isVisible()).isTrue();
    }

    @Test
    public void  displayPreference_notDefaultForData_available() {
    public void  displayPreference_notDefaultForData_notAvailable() {
        ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_2);

        mController.displayPreference(mPreferenceScreen);

        assertThat(mController.isAvailable()).isTrue();
        assertThat(mSwitchPreference.isVisible()).isTrue();
        assertThat(mController.isAvailable()).isFalse();
        assertThat(mSwitchPreference.isVisible()).isFalse();
    }

    @Test
    public void onSubscriptionsChanged_becomesDefaultForData_notAvailable() {
    public void onSubscriptionsChanged_becomesDefaultForData_available() {
        ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_2);
        mController.init(SUB_ID_1);

        mController.displayPreference(mPreferenceScreen);
        ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_1);
        mController.onSubscriptionsChanged();

        assertThat(mController.isAvailable()).isFalse();
        assertThat(mSwitchPreference.isVisible()).isFalse();
        assertThat(mController.isAvailable()).isTrue();
        assertThat(mSwitchPreference.isVisible()).isTrue();
    }

    @Test
    public void onSubscriptionsChanged_noLongerDefaultForData_available() {
    public void onSubscriptionsChanged_noLongerDefaultForData_notAvailable() {
        ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_1);
        mController.init(SUB_ID_1);

        mController.displayPreference(mPreferenceScreen);
        ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_2);
        mController.onSubscriptionsChanged();

        assertThat(mController.isAvailable()).isTrue();
        assertThat(mSwitchPreference.isVisible()).isTrue();
        assertThat(mController.isAvailable()).isFalse();
        assertThat(mSwitchPreference.isVisible()).isFalse();
    }

    @Test
    public void getAvailabilityStatus_mobileDataChangWithDefaultDataSubId_returnUnavailable() {
    public void getAvailabilityStatus_mobileDataChangWithDefaultDataSubId_returnAvailable() {
        ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_1);
        mController.init(SUB_ID_1);

        mController.refreshPreference();

        assertThat(mController.getAvailabilityStatus(SUB_ID_1))
                .isEqualTo(CONDITIONALLY_UNAVAILABLE);
                .isEqualTo(AVAILABLE);
    }

    @Test
    public void getAvailabilityStatus_mobileDataChangWithoutDefaultDataSubId_returnAvailable() {
    public void getAvailabilityStatus_mobileDataChangWithoutDefaultDataSubId_returnUnavailable() {
        ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_1);
        mController.init(SUB_ID_1);

        mController.displayPreference(mPreferenceScreen);
        mController.refreshPreference();

        assertThat(mController.getAvailabilityStatus(SUB_ID_2)).isEqualTo(AVAILABLE);
        assertThat(mController.getAvailabilityStatus(SUB_ID_2)).isEqualTo(
                CONDITIONALLY_UNAVAILABLE);
    }
}