Merge "Avoid ANR when UI query network selection state" into tm-qpr-dev am: d911a095eb

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/22135268

Change-Id: Ideef6fbd4bd904456cb2b91207f8e2acdf54637f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
SongFerng Wang
2023-03-20 09:29:21 +00:00
committed by Automerger Merge Worker
3 changed files with 133 additions and 17 deletions

View File

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

View File

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

View File

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