ANR observed under settings when trying to reset network settings

- Move reset network settings code to async task.

Test: manual, Robolectric
Fixes: 130772994
Change-Id: I59345f48ed840ecfd64c29c2c20ab8caf2679f63
Merged-In: I59345f48ed840ecfd64c29c2c20ab8caf2679f63
This commit is contained in:
Raff Tsai
2019-04-22 14:52:28 +08:00
parent 27e0c844ae
commit 1f0a1171b7
3 changed files with 112 additions and 88 deletions

View File

@@ -18,6 +18,8 @@ package com.android.settings;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.app.Activity;
import android.app.ProgressDialog;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothManager;
@@ -33,7 +35,6 @@ import android.os.Bundle;
import android.os.RecoverySystem; import android.os.RecoverySystem;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Telephony;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -66,35 +67,82 @@ import com.android.settingslib.RestrictedLockUtilsInternal;
public class ResetNetworkConfirm extends InstrumentedFragment { public class ResetNetworkConfirm extends InstrumentedFragment {
@VisibleForTesting View mContentView; @VisibleForTesting View mContentView;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@VisibleForTesting boolean mEraseEsim; @VisibleForTesting boolean mEraseEsim;
@VisibleForTesting EraseEsimAsyncTask mEraseEsimTask; @VisibleForTesting ResetNetworkTask mResetNetworkTask;
@VisibleForTesting Activity mActivity;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private ProgressDialog mProgressDialog;
private AlertDialog mAlertDialog;
/** /**
* Async task used to erase all the eSIM profiles from the phone. If error happens during * Async task used to do all reset task. If error happens during
* erasing eSIM profiles or timeout, an error msg is shown. * erasing eSIM profiles or timeout, an error msg is shown.
*/ */
private static class EraseEsimAsyncTask extends AsyncTask<Void, Void, Boolean> { private class ResetNetworkTask extends AsyncTask<Void, Void, Boolean> {
private final Context mContext; private final Context mContext;
private final String mPackageName; private final String mPackageName;
EraseEsimAsyncTask(Context context, String packageName) { ResetNetworkTask(Context context) {
mContext = context; mContext = context;
mPackageName = packageName; mPackageName = context.getPackageName();
} }
@Override @Override
protected Boolean doInBackground(Void... params) { protected Boolean doInBackground(Void... params) {
ConnectivityManager connectivityManager = (ConnectivityManager)
mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
connectivityManager.factoryReset();
}
WifiManager wifiManager = (WifiManager)
mContext.getSystemService(Context.WIFI_SERVICE);
if (wifiManager != null) {
wifiManager.factoryReset();
}
p2pFactoryReset(mContext);
TelephonyManager telephonyManager = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
telephonyManager.factoryReset(mSubId);
}
NetworkPolicyManager policyManager = (NetworkPolicyManager)
mContext.getSystemService(Context.NETWORK_POLICY_SERVICE);
if (policyManager != null) {
String subscriberId = telephonyManager.getSubscriberId(mSubId);
policyManager.factoryReset(subscriberId);
}
BluetoothManager btManager = (BluetoothManager)
mContext.getSystemService(Context.BLUETOOTH_SERVICE);
if (btManager != null) {
BluetoothAdapter btAdapter = btManager.getAdapter();
if (btAdapter != null) {
btAdapter.factoryReset();
}
}
ImsManager.getInstance(mContext,
SubscriptionManager.getPhoneId(mSubId)).factoryReset();
restoreDefaultApn(mContext);
if (mEraseEsim) {
return RecoverySystem.wipeEuiccData(mContext, mPackageName); return RecoverySystem.wipeEuiccData(mContext, mPackageName);
} else {
return true;
}
} }
@Override @Override
protected void onPostExecute(Boolean succeeded) { protected void onPostExecute(Boolean succeeded) {
mProgressDialog.dismiss();
if (succeeded) { if (succeeded) {
Toast.makeText(mContext, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT) Toast.makeText(mContext, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
.show(); .show();
} else { } else {
new AlertDialog.Builder(mContext) mAlertDialog = new AlertDialog.Builder(mContext)
.setTitle(R.string.reset_esim_error_title) .setTitle(R.string.reset_esim_error_title)
.setMessage(R.string.reset_esim_error_msg) .setMessage(R.string.reset_esim_error_msg)
.setPositiveButton(android.R.string.ok, null /* listener */) .setPositiveButton(android.R.string.ok, null /* listener */)
@@ -107,71 +155,23 @@ public class ResetNetworkConfirm extends InstrumentedFragment {
* The user has gone through the multiple confirmation, so now we go ahead * The user has gone through the multiple confirmation, so now we go ahead
* and reset the network settings to its factory-default state. * and reset the network settings to its factory-default state.
*/ */
private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() { @VisibleForTesting
Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (Utils.isMonkeyRunning()) { if (Utils.isMonkeyRunning()) {
return; return;
} }
// TODO maybe show a progress screen if this ends up taking a while and won't let user
// go back until the tasks finished.
Context context = getActivity();
ConnectivityManager connectivityManager = (ConnectivityManager) mProgressDialog = getProgressDialog(mActivity);
context.getSystemService(Context.CONNECTIVITY_SERVICE); mProgressDialog.show();
if (connectivityManager != null) {
connectivityManager.factoryReset();
}
WifiManager wifiManager = (WifiManager) mResetNetworkTask = new ResetNetworkTask(mActivity);
context.getSystemService(Context.WIFI_SERVICE); mResetNetworkTask.execute();
if (wifiManager != null) {
wifiManager.factoryReset();
}
p2pFactoryReset(context);
TelephonyManager telephonyManager = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
telephonyManager.factoryReset(mSubId);
}
NetworkPolicyManager policyManager = (NetworkPolicyManager)
context.getSystemService(Context.NETWORK_POLICY_SERVICE);
if (policyManager != null) {
String subscriberId = telephonyManager.getSubscriberId(mSubId);
policyManager.factoryReset(subscriberId);
}
BluetoothManager btManager = (BluetoothManager)
context.getSystemService(Context.BLUETOOTH_SERVICE);
if (btManager != null) {
BluetoothAdapter btAdapter = btManager.getAdapter();
if (btAdapter != null) {
btAdapter.factoryReset();
}
}
ImsManager.getInstance(context,
SubscriptionManager.getPhoneId(mSubId)).factoryReset();
restoreDefaultApn(context);
esimFactoryReset(context, context.getPackageName());
} }
}; };
@VisibleForTesting
void esimFactoryReset(Context context, String packageName) {
if (mEraseEsim) {
mEraseEsimTask = new EraseEsimAsyncTask(context, packageName);
mEraseEsimTask.execute();
} else {
Toast.makeText(context, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
.show();
}
}
@VisibleForTesting @VisibleForTesting
void p2pFactoryReset(Context context) { void p2pFactoryReset(Context context) {
WifiP2pManager wifiP2pManager = (WifiP2pManager) WifiP2pManager wifiP2pManager = (WifiP2pManager)
@@ -186,6 +186,15 @@ public class ResetNetworkConfirm extends InstrumentedFragment {
} }
} }
private ProgressDialog getProgressDialog(Context context) {
final ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(false);
progressDialog.setMessage(
context.getString(R.string.master_clear_progress_text));
return progressDialog;
}
/** /**
* Restore APN settings to default. * Restore APN settings to default.
*/ */
@@ -220,16 +229,16 @@ public class ResetNetworkConfirm extends InstrumentedFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced( final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
getActivity(), UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId()); mActivity, UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
if (RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(), if (RestrictedLockUtilsInternal.hasBaseUserRestriction(mActivity,
UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) { UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
return inflater.inflate(R.layout.network_reset_disallowed_screen, null); return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
} else if (admin != null) { } else if (admin != null) {
new ActionDisabledByAdminDialogHelper(getActivity()) new ActionDisabledByAdminDialogHelper(mActivity)
.prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin) .prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin)
.setOnDismissListener(__ -> getActivity().finish()) .setOnDismissListener(__ -> mActivity.finish())
.show(); .show();
return new View(getContext()); return new View(mActivity);
} }
mContentView = inflater.inflate(R.layout.reset_network_confirm, null); mContentView = inflater.inflate(R.layout.reset_network_confirm, null);
establishFinalConfirmationState(); establishFinalConfirmationState();
@@ -247,13 +256,21 @@ public class ResetNetworkConfirm extends InstrumentedFragment {
SubscriptionManager.INVALID_SUBSCRIPTION_ID); SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mEraseEsim = args.getBoolean(MasterClear.ERASE_ESIMS_EXTRA); mEraseEsim = args.getBoolean(MasterClear.ERASE_ESIMS_EXTRA);
} }
mActivity = getActivity();
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
if (mEraseEsimTask != null) { if (mResetNetworkTask != null) {
mEraseEsimTask.cancel(true /* mayInterruptIfRunning */); mResetNetworkTask.cancel(true /* mayInterruptIfRunning */);
mEraseEsimTask = null; mResetNetworkTask = null;
}
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
if (mAlertDialog != null) {
mAlertDialog.dismiss();
} }
super.onDestroy(); super.onDestroy();
} }

View File

@@ -18,12 +18,12 @@ package com.android.settings;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.app.Activity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.widget.TextView; import android.widget.TextView;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowRecoverySystem; import com.android.settings.testutils.shadow.ShadowRecoverySystem;
import com.android.settings.testutils.shadow.ShadowWifiP2pManager; import com.android.settings.testutils.shadow.ShadowWifiP2pManager;
@@ -38,18 +38,21 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowRecoverySystem.class, ShadowWifiP2pManager.class}) @Config(shadows = {ShadowRecoverySystem.class,
ShadowWifiP2pManager.class, ShadowBluetoothAdapter.class
})
public class ResetNetworkConfirmTest { public class ResetNetworkConfirmTest {
private Activity mActivity; private FragmentActivity mActivity;
@Mock @Mock
private ResetNetworkConfirm mResetNetworkConfirm; private ResetNetworkConfirm mResetNetworkConfirm;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mResetNetworkConfirm = spy(new ResetNetworkConfirm()); mResetNetworkConfirm = new ResetNetworkConfirm();
mActivity = Robolectric.setupActivity(Activity.class); mActivity = Robolectric.setupActivity(FragmentActivity.class);
mResetNetworkConfirm.mActivity = mActivity;
} }
@After @After
@@ -62,10 +65,9 @@ public class ResetNetworkConfirmTest {
public void testResetNetworkData_resetEsim() { public void testResetNetworkData_resetEsim() {
mResetNetworkConfirm.mEraseEsim = true; mResetNetworkConfirm.mEraseEsim = true;
mResetNetworkConfirm.esimFactoryReset(mActivity, "" /* packageName */); mResetNetworkConfirm.mFinalClickListener.onClick(null /* View */);
Robolectric.getBackgroundThreadScheduler().advanceToLastPostedRunnable(); Robolectric.getBackgroundThreadScheduler().advanceToLastPostedRunnable();
assertThat(mResetNetworkConfirm.mEraseEsimTask).isNotNull();
assertThat(ShadowRecoverySystem.getWipeEuiccCalledCount()).isEqualTo(1); assertThat(ShadowRecoverySystem.getWipeEuiccCalledCount()).isEqualTo(1);
} }
@@ -73,9 +75,9 @@ public class ResetNetworkConfirmTest {
public void testResetNetworkData_notResetEsim() { public void testResetNetworkData_notResetEsim() {
mResetNetworkConfirm.mEraseEsim = false; mResetNetworkConfirm.mEraseEsim = false;
mResetNetworkConfirm.esimFactoryReset(mActivity, "" /* packageName */); mResetNetworkConfirm.mFinalClickListener.onClick(null /* View */);
Robolectric.getBackgroundThreadScheduler().advanceToLastPostedRunnable();
assertThat(mResetNetworkConfirm.mEraseEsimTask).isNull();
assertThat(ShadowRecoverySystem.getWipeEuiccCalledCount()).isEqualTo(0); assertThat(ShadowRecoverySystem.getWipeEuiccCalledCount()).isEqualTo(0);
} }

View File

@@ -51,4 +51,9 @@ public class ShadowBluetoothAdapter extends org.robolectric.shadows.ShadowBlueto
public void setConnectionState(int state) { public void setConnectionState(int state) {
mState = state; mState = state;
} }
@Implementation
protected boolean factoryReset() {
return true;
}
} }