diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index 94b6aaf1bcc..4fed5072c24 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -207,7 +207,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)); diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java index 72d9e91ff77..5c49a3b7040 100644 --- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java +++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java @@ -33,9 +33,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; @@ -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; + TelephonyCallbackListener mTelephonyCallbackListener; public AutoSelectPreferenceController(Context context, String key) { super(context, key); @@ -90,6 +97,7 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon new HandlerExecutor(mUiHandler)); mAllowedNetworkTypesListener.setAllowedNetworkTypesListener( () -> updatePreference()); + mTelephonyCallbackListener = new TelephonyCallbackListener(); } private void updatePreference() { @@ -106,11 +114,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 @@ -129,12 +140,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 +202,23 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon //Update UI in UI thread final long durationMillis = SystemClock.elapsedRealtime() - startMillis; + mUiHandler.postDelayed(() -> { - mRecursiveUpdate.getAndIncrement(); - mSwitchPreference.setEnabled(true); - mSwitchPreference.setChecked(isChecked()); - mRecursiveUpdate.decrementAndGet(); - dismissProgressBar(); + 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)); }); } @@ -210,7 +226,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 +237,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; } @@ -230,6 +259,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); @@ -260,4 +322,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); + } + } } diff --git a/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java index 292b4a9ae5c..39f2050b7f7 100644 --- a/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java @@ -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(); } }