Merge "Avoid ANR when UI query network selection state"
This commit is contained in:
committed by
Android (Google) Code Review
commit
65734dd29b
@@ -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));
|
||||
|
@@ -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(() -> {
|
||||
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();
|
||||
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);
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user