Prevent showing multiple keyguard dialog in vpn setup UI

Change-Id: If3a0d4ee285bfdde5f4b84bee58d62708071fe75
Fix: 37552190
Test: make RunSettingsRoboTests
This commit is contained in:
Fan Zhang
2017-06-05 17:15:21 -07:00
parent fe23da579d
commit ab0a0c8202
3 changed files with 173 additions and 62 deletions

View File

@@ -47,8 +47,8 @@ import android.widget.Toast;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.org.bouncycastle.asn1.ASN1InputStream; import com.android.org.bouncycastle.asn1.ASN1InputStream;
import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.security.ConfigureKeyGuardDialog;
import com.android.settings.vpn2.VpnUtils; import com.android.settings.vpn2.VpnUtils;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@@ -103,7 +103,7 @@ public final class CredentialStorage extends Activity {
// This is the minimum acceptable password quality. If the current password quality is // This is the minimum acceptable password quality. If the current password quality is
// lower than this, keystore should not be activated. // lower than this, keystore should not be activated.
static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; public static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
private static final int CONFIRM_KEY_GUARD_REQUEST = 1; private static final int CONFIRM_KEY_GUARD_REQUEST = 1;
private static final int CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST = 2; private static final int CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST = 2;
@@ -171,7 +171,8 @@ public final class CredentialStorage extends Activity {
} }
case UNLOCKED: { case UNLOCKED: {
if (!checkKeyGuardQuality()) { if (!checkKeyGuardQuality()) {
new ConfigureKeyGuardDialog(); final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
dialog.show(getFragmentManager(), ConfigureKeyGuardDialog.TAG);
return; return;
} }
installIfAvailable(); installIfAvailable();
@@ -190,7 +191,8 @@ public final class CredentialStorage extends Activity {
private void ensureKeyGuard() { private void ensureKeyGuard() {
if (!checkKeyGuardQuality()) { if (!checkKeyGuardQuality()) {
// key guard not setup, doing so will initialize keystore // key guard not setup, doing so will initialize keystore
new ConfigureKeyGuardDialog(); final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
dialog.show(getFragmentManager(), ConfigureKeyGuardDialog.TAG);
// will return to onResume after Activity // will return to onResume after Activity
return; return;
} }
@@ -308,8 +310,7 @@ public final class CredentialStorage extends Activity {
* Prompt for reset confirmation, resetting on confirmation, finishing otherwise. * Prompt for reset confirmation, resetting on confirmation, finishing otherwise.
*/ */
private class ResetDialog private class ResetDialog
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
{
private boolean mResetConfirmed; private boolean mResetConfirmed;
private ResetDialog() { private ResetDialog() {
@@ -323,11 +324,13 @@ public final class CredentialStorage extends Activity {
dialog.show(); dialog.show();
} }
@Override public void onClick(DialogInterface dialog, int button) { @Override
public void onClick(DialogInterface dialog, int button) {
mResetConfirmed = (button == DialogInterface.BUTTON_POSITIVE); mResetConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
} }
@Override public void onDismiss(DialogInterface dialog) { @Override
public void onDismiss(DialogInterface dialog) {
if (mResetConfirmed) { if (mResetConfirmed) {
mResetConfirmed = false; mResetConfirmed = false;
if (confirmKeyGuard(CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST)) { if (confirmKeyGuard(CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST)) {
@@ -344,7 +347,8 @@ public final class CredentialStorage extends Activity {
*/ */
private class ResetKeyStoreAndKeyChain extends AsyncTask<Void, Void, Boolean> { private class ResetKeyStoreAndKeyChain extends AsyncTask<Void, Void, Boolean> {
@Override protected Boolean doInBackground(Void... unused) { @Override
protected Boolean doInBackground(Void... unused) {
// Clear all the users credentials could have been installed in for this user. // Clear all the users credentials could have been installed in for this user.
new LockPatternUtils(CredentialStorage.this).resetKeyStore(UserHandle.myUserId()); new LockPatternUtils(CredentialStorage.this).resetKeyStore(UserHandle.myUserId());
@@ -364,7 +368,8 @@ public final class CredentialStorage extends Activity {
} }
} }
@Override protected void onPostExecute(Boolean success) { @Override
protected void onPostExecute(Boolean success) {
if (success) { if (success) {
Toast.makeText(CredentialStorage.this, Toast.makeText(CredentialStorage.this,
R.string.credentials_erased, Toast.LENGTH_SHORT).show(); R.string.credentials_erased, Toast.LENGTH_SHORT).show();
@@ -385,42 +390,6 @@ public final class CredentialStorage extends Activity {
} }
} }
/**
* Prompt for key guard configuration confirmation.
*/
private class ConfigureKeyGuardDialog
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
{
private boolean mConfigureConfirmed;
private ConfigureKeyGuardDialog() {
AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
.setTitle(android.R.string.dialog_alert_title)
.setMessage(R.string.credentials_configure_lock_screen_hint)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this)
.create();
dialog.setOnDismissListener(this);
dialog.show();
}
@Override public void onClick(DialogInterface dialog, int button) {
mConfigureConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
}
@Override public void onDismiss(DialogInterface dialog) {
if (mConfigureConfirmed) {
mConfigureConfirmed = false;
Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
MIN_PASSWORD_QUALITY);
startActivity(intent);
return;
}
finish();
}
}
/** /**
* Check that the caller is either certinstaller or Settings running in a profile of this user. * Check that the caller is either certinstaller or Settings running in a profile of this user.
*/ */
@@ -506,8 +475,7 @@ public final class CredentialStorage extends Activity {
* On unsuccessful unlock, retry by calling handleUnlockOrInstall. * On unsuccessful unlock, retry by calling handleUnlockOrInstall.
*/ */
private class UnlockDialog implements TextWatcher, private class UnlockDialog implements TextWatcher,
DialogInterface.OnClickListener, DialogInterface.OnDismissListener DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
{
private boolean mUnlockConfirmed; private boolean mUnlockConfirmed;
private final Button mButton; private final Button mButton;
@@ -546,21 +514,26 @@ public final class CredentialStorage extends Activity {
mButton.setEnabled(false); mButton.setEnabled(false);
} }
@Override public void afterTextChanged(Editable editable) { @Override
public void afterTextChanged(Editable editable) {
mButton.setEnabled(mOldPassword == null || mOldPassword.getText().length() > 0); mButton.setEnabled(mOldPassword == null || mOldPassword.getText().length() > 0);
} }
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
} }
@Override public void onTextChanged(CharSequence s,int start, int before, int count) { @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
} }
@Override public void onClick(DialogInterface dialog, int button) { @Override
public void onClick(DialogInterface dialog, int button) {
mUnlockConfirmed = (button == DialogInterface.BUTTON_POSITIVE); mUnlockConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
} }
@Override public void onDismiss(DialogInterface dialog) { @Override
public void onDismiss(DialogInterface dialog) {
if (mUnlockConfirmed) { if (mUnlockConfirmed) {
mUnlockConfirmed = false; mUnlockConfirmed = false;
mError.setVisibility(View.VISIBLE); mError.setVisibility(View.VISIBLE);

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.security;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.CredentialStorage;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.password.ChooseLockGeneric;
/**
* Prompt for key guard configuration confirmation.
*/
public class ConfigureKeyGuardDialog extends InstrumentedDialogFragment
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
public static final String TAG = "ConfigureKeyGuardDialog";
private boolean mConfigureConfirmed;
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.CONFIGURE_KEYGUARD_DIALOG;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(android.R.string.dialog_alert_title)
.setMessage(R.string.credentials_configure_lock_screen_hint)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this)
.create();
}
@Override
public void onClick(DialogInterface dialog, int button) {
mConfigureConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
}
@Override
public void onDismiss(DialogInterface dialog) {
if (mConfigureConfirmed) {
mConfigureConfirmed = false;
startPasswordSetup();
return;
} else {
final Activity activity = getActivity();
if (activity != null) {
activity.finish();
}
}
}
@VisibleForTesting
void startPasswordSetup() {
Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
CredentialStorage.MIN_PASSWORD_QUALITY);
startActivity(intent);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.security;
import android.content.DialogInterface;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
import org.robolectric.util.FragmentController;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ConfigureKeyGuardDialogTest {
@Test
@Config(shadows = ShadowEventLogWriter.class)
public void displayDialog_clickPositiveButton_launchSetNewPassword() {
final FragmentController<ConfigureKeyGuardDialog> fragmentController =
Robolectric.buildFragment(ConfigureKeyGuardDialog.class);
final ConfigureKeyGuardDialog fragment = spy(fragmentController.get());
doNothing().when(fragment).startPasswordSetup();
fragmentController.attach().create().start().resume();
fragment.onClick(null /* dialog */, DialogInterface.BUTTON_POSITIVE);
fragment.onDismiss(null /* dialog */);
verify(fragment).startPasswordSetup();
}
}