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

Commit 88717f2c authored by SongFerngWang's avatar SongFerngWang
Browse files

Avoid ANR when UI query network selection state

Moving the quert network selection state to back ground
and listening the service state to detect the betwork selection
changed.

Bug: 270652395
Test: atest AutoSelectPreferenceControllerTest
Merged-In: I81a597f28cf7ce25ff4eff5100bdb4d29c897a14
Merged-In: Idfc7a07106d552c35a94414bb14eac0fbdc3974f
Change-Id: Ifb548de301021f992ef13c3d299de1642f379fbf
parent 34db15a0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -211,7 +211,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
                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));
+83 −12
Original line number Diff line number Diff line
@@ -31,9 +31,12 @@ import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
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;
import androidx.preference.Preference;
@@ -60,6 +63,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;
@@ -74,6 +80,7 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
    private AtomicBoolean mUpdatingConfig;
    private int mCacheOfModeStatus;
    private AtomicLong mRecursiveUpdate;
    TelephonyCallbackListener mTelephonyCallbackListener;

    public AutoSelectPreferenceController(Context context, String key) {
        super(context, key);
@@ -88,6 +95,7 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
                new HandlerExecutor(mUiHandler));
        mAllowedNetworkTypesListener.setAllowedNetworkTypesListener(
                () -> updatePreference());
        mTelephonyCallbackListener = new TelephonyCallbackListener();
    }

    private void updatePreference() {
@@ -104,11 +112,14 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
    @OnLifecycleEvent(ON_START)
    public void onStart() {
        mAllowedNetworkTypesListener.register(mContext, mSubId);
        mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(mUiHandler),
                mTelephonyCallbackListener);
    }

    @OnLifecycleEvent(ON_STOP)
    public void onStop() {
        mAllowedNetworkTypesListener.unregister(mContext, mSubId);
        mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallbackListener);
    }

    @Override
@@ -127,12 +138,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;
    }

@@ -195,12 +200,23 @@ 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();
                        updateListenerValue();
                        dismissProgressBar();
                    });
                });
            }, Math.max(MINIMUM_DIALOG_TIME_MILLIS - durationMillis, 0));
        });
    }
@@ -208,7 +224,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);
@@ -219,6 +235,19 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
                CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL)
                : false;

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

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

@@ -228,6 +257,39 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
        return this;
    }

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

    @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);

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

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

    private void showAutoSelectProgressBar() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(mContext);
@@ -258,4 +320,13 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
    public interface OnNetworkSelectModeListener {
        void onNetworkSelectModeUpdated(int mode);
    }

    private class TelephonyCallbackListener extends TelephonyCallback
            implements TelephonyCallback.ServiceStateListener {

        @Override
        public void onServiceStateChanged(ServiceState serviceState) {
            updateUiAutoSelectValue(serviceState);
        }
    }
}
+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();
    }
}