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

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

Merge "Avoid ANR when UI query network selection state" into udc-dev

parents bec6e40d 7b9c2234
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -272,7 +272,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
                use(OpenNetworkSelectPagePreferenceController.class).init(mSubId);
        final AutoSelectPreferenceController autoSelectPreferenceController =
                use(AutoSelectPreferenceController.class)
                        .init(mSubId)
                        .init(getLifecycle(), mSubId)
                        .addListener(openNetworkSelectPagePreferenceController);
        use(NetworkPreferenceCategoryController.class).init(mSubId)
                .setChildren(Arrays.asList(autoSelectPreferenceController));
+81 −12
Original line number Diff line number Diff line
@@ -34,8 +34,10 @@ import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
@@ -45,6 +47,7 @@ import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.network.AllowedNetworkTypesListener;
import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.helper.ServiceStateStatus;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.network.telephony.TelephonyTogglePreferenceController;
import com.android.settingslib.utils.ThreadUtils;
@@ -62,6 +65,9 @@ import java.util.concurrent.atomic.AtomicLong;
public class AutoSelectPreferenceController extends TelephonyTogglePreferenceController
        implements LifecycleObserver{
    private static final long MINIMUM_DIALOG_TIME_MILLIS = TimeUnit.SECONDS.toMillis(1);
    private static final String LOG_TAG = "AutoSelectPreferenceController";
    private static final String INTERNAL_LOG_TAG_INIT = "Init";
    private static final String INTERNAL_LOG_TAG_AFTERSET = "AfterSet";

    private final Handler mUiHandler;
    private PreferenceScreen mPreferenceScreen;
@@ -76,6 +82,7 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
    private AtomicBoolean mUpdatingConfig;
    private int mCacheOfModeStatus;
    private AtomicLong mRecursiveUpdate;
    ServiceStateStatus mServiceStateStatus;

    public AutoSelectPreferenceController(Context context, String key) {
        super(context, key);
@@ -129,12 +136,6 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon

    @Override
    public boolean isChecked() {
        if (!mUpdatingConfig.get()) {
            mCacheOfModeStatus = mTelephonyManager.getNetworkSelectionMode();
            for (OnNetworkSelectModeListener lsn : mListeners) {
                lsn.onNetworkSelectModeUpdated(mCacheOfModeStatus);
            }
        }
        return mCacheOfModeStatus == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
    }

@@ -197,12 +198,22 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon

            //Update UI in UI thread
            final long durationMillis = SystemClock.elapsedRealtime() - startMillis;

            mUiHandler.postDelayed(() -> {
                ThreadUtils.postOnBackgroundThread(() -> {
                    queryNetworkSelectionMode(INTERNAL_LOG_TAG_AFTERSET);

                    //Update UI in UI thread
                    mUiHandler.post(() -> {
                        mRecursiveUpdate.getAndIncrement();
                        if (mSwitchPreference != null) {
                            mSwitchPreference.setEnabled(true);
                            mSwitchPreference.setChecked(isChecked());
                        }
                        mRecursiveUpdate.decrementAndGet();
                        dismissProgressBar();
                    });
                });
            }, Math.max(MINIMUM_DIALOG_TIME_MILLIS - durationMillis, 0));
        });
    }
@@ -210,7 +221,7 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
    /**
     * Initialization based on given subscription id.
     **/
    public AutoSelectPreferenceController init(int subId) {
    public AutoSelectPreferenceController init(Lifecycle lifecycle, int subId) {
        mSubId = subId;
        mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
                .createForSubscriptionId(mSubId);
@@ -221,6 +232,29 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
                CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL)
                : false;

        mServiceStateStatus = new ServiceStateStatus(lifecycle, mTelephonyManager,
                new HandlerExecutor(mUiHandler)) {
            @Override
            protected void setValue(ServiceState status) {
                if (status == null) {
                    return;
                }
                updateUiAutoSelectValue(status);
            }
        };

        ThreadUtils.postOnBackgroundThread(() -> {
            queryNetworkSelectionMode(INTERNAL_LOG_TAG_INIT);

            //Update UI in UI thread
            mUiHandler.post(() -> {
                if (mSwitchPreference != null) {
                    mRecursiveUpdate.getAndIncrement();
                    mSwitchPreference.setChecked(isChecked());
                    mRecursiveUpdate.decrementAndGet();
                }
            });
        });
        return this;
    }

@@ -230,6 +264,41 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
        return this;
    }

    private void queryNetworkSelectionMode(String tag) {
        mCacheOfModeStatus = mTelephonyManager.getNetworkSelectionMode();
        Log.d(LOG_TAG, tag + ": query commend done. mCacheOfModeStatus: " + mCacheOfModeStatus);
        updateListenerValue();
    }

    @VisibleForTesting
    void updateUiAutoSelectValue(ServiceState status) {
        if (status == null) {
            return;
        }
        if (!mUpdatingConfig.get()) {
            int networkSelectionMode = status.getIsManualSelection()
                    ? TelephonyManager.NETWORK_SELECTION_MODE_MANUAL
                    : TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
            if (mCacheOfModeStatus == networkSelectionMode) {
                return;
            }
            mCacheOfModeStatus = networkSelectionMode;
            Log.d(LOG_TAG, "updateUiAutoSelectValue: mCacheOfModeStatus: " + mCacheOfModeStatus);
            updateListenerValue();

            mRecursiveUpdate.getAndIncrement();
            updateState(mSwitchPreference);
            mRecursiveUpdate.decrementAndGet();

        }
    }

    private void updateListenerValue() {
        for (OnNetworkSelectModeListener lsn : mListeners) {
            lsn.onNetworkSelectModeUpdated(mCacheOfModeStatus);
        }
    }

    private void showAutoSelectProgressBar() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(mContext);
+49 −4
Original line number Diff line number Diff line
@@ -28,9 +28,11 @@ import android.app.ProgressDialog;
import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;

import androidx.lifecycle.Lifecycle;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -61,6 +63,10 @@ public class AutoSelectPreferenceControllerTest {
    private CarrierConfigCache mCarrierConfigCache;
    @Mock
    private ProgressDialog mProgressDialog;
    @Mock
    private ServiceState mTestServiceState;
    @Mock
    private Lifecycle mLifecycle;

    private PersistableBundle mCarrierConfig;
    private AutoSelectPreferenceController mController;
@@ -88,7 +94,16 @@ public class AutoSelectPreferenceControllerTest {
        mController = new AutoSelectPreferenceController(mContext, "auto_select");
        mController.mProgressDialog = mProgressDialog;
        mController.mSwitchPreference = mSwitchPreference;
        mController.init(SUB_ID);
        mController.init(mLifecycle, SUB_ID);
        sleepAfterInit();
    }

    private void sleepAfterInit() {
        try {
            Thread.sleep(2000);
        } catch (Exception e) {
            fail("Sleep timeout " + e);
        }
    }

    @Test
@@ -111,7 +126,8 @@ public class AutoSelectPreferenceControllerTest {

    @Test
    public void updateState_isRoaming_enabled() {
        when(mTelephonyManager.getServiceState().getRoaming()).thenReturn(true);
        when(mTelephonyManager.getServiceState()).thenReturn(mTestServiceState);
        when(mTestServiceState.getRoaming()).thenReturn(true);

        mController.updateState(mSwitchPreference);

@@ -120,7 +136,8 @@ public class AutoSelectPreferenceControllerTest {

    @Test
    public void updateState_notRoamingWithAutoSelectOn_disabled() {
        when(mTelephonyManager.getServiceState().getRoaming()).thenReturn(false);
        when(mTelephonyManager.getServiceState()).thenReturn(mTestServiceState);
        when(mTestServiceState.getRoaming()).thenReturn(false);
        doReturn(OPERATOR_NAME).when(mTelephonyManager).getSimOperatorName();

        mController.updateState(mSwitchPreference);
@@ -136,6 +153,34 @@ public class AutoSelectPreferenceControllerTest {
        when(mCarrierConfigCache.getConfigForSubId(SUB_ID)).thenReturn(null);

        // Should not crash
        mController.init(SUB_ID);
        mController.init(mLifecycle, SUB_ID);
    }

    @Test
    public void updateUiAutoSelectValue_serviceStateGetIsManualSelection_isCheckedFalse() {
        when(mTelephonyManager.getNetworkSelectionMode()).thenReturn(
                TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
        when(mTestServiceState.getIsManualSelection()).thenReturn(true);
        mController.init(mLifecycle, SUB_ID);
        sleepAfterInit();

        mController.updateUiAutoSelectValue(mTestServiceState);

        assertThat(mController.isChecked()).isFalse();
        assertThat(mSwitchPreference.isChecked()).isFalse();
    }

    @Test
    public void updateUiAutoSelectValue_serviceStateGetIsAutoSelection_isCheckedTrue() {
        when(mTelephonyManager.getNetworkSelectionMode()).thenReturn(
                TelephonyManager.NETWORK_SELECTION_MODE_MANUAL);
        when(mTestServiceState.getIsManualSelection()).thenReturn(false);
        mController.init(mLifecycle, SUB_ID);
        sleepAfterInit();

        mController.updateUiAutoSelectValue(mTestServiceState);

        assertThat(mController.isChecked()).isTrue();
        assertThat(mSwitchPreference.isChecked()).isTrue();
    }
}