OSDN Git Service

Prevent showing multiple keyguard dialog in vpn setup UI
authorFan Zhang <zhfan@google.com>
Tue, 6 Jun 2017 00:15:21 +0000 (17:15 -0700)
committerFan Zhang <zhfan@google.com>
Tue, 6 Jun 2017 00:42:53 +0000 (17:42 -0700)
Change-Id: If3a0d4ee285bfdde5f4b84bee58d62708071fe75
Fix: 37552190
Test: make RunSettingsRoboTests

src/com/android/settings/CredentialStorage.java
src/com/android/settings/security/ConfigureKeyGuardDialog.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/security/ConfigureKeyGuardDialogTest.java [new file with mode: 0644]

index 03a5f4b..e5d40b7 100644 (file)
@@ -47,8 +47,8 @@ import android.widget.Toast;
 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;
@@ -74,14 +74,14 @@ import sun.security.x509.AlgorithmId;
  * 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
@@ -103,7 +103,7 @@ public final class CredentialStorage extends Activity {
 
     // 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;
@@ -171,7 +171,8 @@ public final class CredentialStorage extends Activity {
             }
             case UNLOCKED: {
                 if (!checkKeyGuardQuality()) {
-                    new ConfigureKeyGuardDialog();
+                    final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
+                    dialog.show(getFragmentManager(), ConfigureKeyGuardDialog.TAG);
                     return;
                 }
                 installIfAvailable();
@@ -190,7 +191,8 @@ public final class CredentialStorage extends Activity {
     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;
         }
@@ -308,8 +310,7 @@ public final class CredentialStorage extends Activity {
      * 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() {
@@ -323,11 +324,13 @@ public final class CredentialStorage extends Activity {
             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)) {
@@ -344,7 +347,8 @@ public final class CredentialStorage extends Activity {
      */
     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());
@@ -364,14 +368,15 @@ public final class CredentialStorage extends Activity {
             }
         }
 
-        @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();
         }
@@ -386,42 +391,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.
      */
     private boolean checkCallerIsCertInstallerOrSelfInProfile() {
@@ -506,8 +475,7 @@ public final class CredentialStorage extends Activity {
      * 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;
@@ -546,21 +514,26 @@ public final class CredentialStorage extends Activity {
             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);
@@ -569,16 +542,16 @@ public final class CredentialStorage extends Activity {
                 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) {
diff --git a/src/com/android/settings/security/ConfigureKeyGuardDialog.java b/src/com/android/settings/security/ConfigureKeyGuardDialog.java
new file mode 100644 (file)
index 0000000..3c89340
--- /dev/null
@@ -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);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/security/ConfigureKeyGuardDialogTest.java b/tests/robotests/src/com/android/settings/security/ConfigureKeyGuardDialogTest.java
new file mode 100644 (file)
index 0000000..8a80fe5
--- /dev/null
@@ -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();
+    }
+}