import com.android.internal.widget.LockPatternUtils;
import com.android.org.bouncycastle.asn1.ASN1InputStream;
import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.security.ConfigureKeyGuardDialog;
import com.android.settings.vpn2.VpnUtils;
import java.io.ByteArrayInputStream;
* KeyGuard: ON
* Action: confirm key guard
* Notes: user had key guard but no keystore and upgraded from pre-ICS
- * OR user had key guard and pre-ICS keystore password which was then reset
+ * OR user had key guard and pre-ICS keystore password which was then reset
*
* KeyStore: LOCKED
* KeyGuard: OFF/ON
* Action: old unlock dialog
* Notes: assume old password, need to use it to unlock.
- * if unlock, ensure key guard before install.
- * if reset, treat as UNINITALIZED/OFF
+ * if unlock, ensure key guard before install.
+ * if reset, treat as UNINITALIZED/OFF
*
* KeyStore: UNLOCKED
* KeyGuard: OFF
// This is the minimum acceptable password quality. If the current password quality is
// 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_CLEAR_SYSTEM_CREDENTIAL_REQUEST = 2;
}
case UNLOCKED: {
if (!checkKeyGuardQuality()) {
- new ConfigureKeyGuardDialog();
+ final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
+ dialog.show(getFragmentManager(), ConfigureKeyGuardDialog.TAG);
return;
}
installIfAvailable();
private void ensureKeyGuard() {
if (!checkKeyGuardQuality()) {
// 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
return;
}
* Prompt for reset confirmation, resetting on confirmation, finishing otherwise.
*/
private class ResetDialog
- implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
- {
+ implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
private boolean mResetConfirmed;
private ResetDialog() {
dialog.show();
}
- @Override public void onClick(DialogInterface dialog, int button) {
+ @Override
+ public void onClick(DialogInterface dialog, int button) {
mResetConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
}
- @Override public void onDismiss(DialogInterface dialog) {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
if (mResetConfirmed) {
mResetConfirmed = false;
if (confirmKeyGuard(CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST)) {
*/
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.
new LockPatternUtils(CredentialStorage.this).resetKeyStore(UserHandle.myUserId());
}
}
- @Override protected void onPostExecute(Boolean success) {
+ @Override
+ protected void onPostExecute(Boolean success) {
if (success) {
Toast.makeText(CredentialStorage.this,
- R.string.credentials_erased, Toast.LENGTH_SHORT).show();
+ R.string.credentials_erased, Toast.LENGTH_SHORT).show();
clearLegacyVpnIfEstablished();
} else {
Toast.makeText(CredentialStorage.this,
- R.string.credentials_not_erased, Toast.LENGTH_SHORT).show();
+ R.string.credentials_not_erased, Toast.LENGTH_SHORT).show();
}
finish();
}
}
/**
- * 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.
*/
private boolean checkCallerIsCertInstallerOrSelfInProfile() {
* On unsuccessful unlock, retry by calling handleUnlockOrInstall.
*/
private class UnlockDialog implements TextWatcher,
- DialogInterface.OnClickListener, DialogInterface.OnDismissListener
- {
+ DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
private boolean mUnlockConfirmed;
private final Button mButton;
mButton.setEnabled(false);
}
- @Override public void afterTextChanged(Editable editable) {
+ @Override
+ public void afterTextChanged(Editable editable) {
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);
}
- @Override public void onDismiss(DialogInterface dialog) {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
if (mUnlockConfirmed) {
mUnlockConfirmed = false;
mError.setVisibility(View.VISIBLE);
if (error == KeyStore.NO_ERROR) {
mRetriesRemaining = -1;
Toast.makeText(CredentialStorage.this,
- R.string.credentials_enabled,
- Toast.LENGTH_SHORT).show();
+ R.string.credentials_enabled,
+ Toast.LENGTH_SHORT).show();
// aha, now we are unlocked, switch to key guard.
// we'll end up back in onResume to install
ensureKeyGuard();
} else if (error == KeyStore.UNINITIALIZED) {
mRetriesRemaining = -1;
Toast.makeText(CredentialStorage.this,
- R.string.credentials_erased,
- Toast.LENGTH_SHORT).show();
+ R.string.credentials_erased,
+ Toast.LENGTH_SHORT).show();
// we are reset, we can now set new password with key guard
handleUnlockOrInstall();
} else if (error >= KeyStore.WRONG_PASSWORD) {
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}