diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index af9c3b4b53e..564bf1f70e7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1299,10 +1299,12 @@
-
+
+ android:windowSoftInputMode="stateVisible|adjustResize"
+ android:theme="@style/Theme.ConfirmDeviceCredentials"/>
diff --git a/res/drawable/ic_fingerprint.xml b/res/drawable/ic_fingerprint.xml
new file mode 100644
index 00000000000..2f277532b99
--- /dev/null
+++ b/res/drawable/ic_fingerprint.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
diff --git a/res/drawable/ic_fingerprint_error.xml b/res/drawable/ic_fingerprint_error.xml
new file mode 100644
index 00000000000..d00280d929a
--- /dev/null
+++ b/res/drawable/ic_fingerprint_error.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
diff --git a/res/layout-land/confirm_lock_password.xml b/res/layout-land/confirm_lock_password.xml
index 4158c88486e..d8da8fee070 100644
--- a/res/layout-land/confirm_lock_password.xml
+++ b/res/layout-land/confirm_lock_password.xml
@@ -1,104 +1,92 @@
-
-
-
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
-
+
+
-
-
-
-
-
-
-
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
-
-
-
-
+ android:orientation="horizontal">
-
+ android:layout_gravity="start|bottom"
+ android:text="@string/cancel"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginBottom="14dp"/>
-
+ android:layout_gravity="center_horizontal|bottom"
+ android:layout_marginBottom="26dp"
+ android:inputType="textPassword"
+ android:imeOptions="actionNext|flagNoFullscreen"
+ android:gravity="center"
+ android:textSize="16sp"
+ style="@style/TextAppearance.PasswordEntry"/>
-
+
-
+
+
+
\ No newline at end of file
diff --git a/res/layout-land/confirm_lock_pattern.xml b/res/layout-land/confirm_lock_pattern.xml
index b58b46f155f..0567fad051e 100644
--- a/res/layout-land/confirm_lock_pattern.xml
+++ b/res/layout-land/confirm_lock_pattern.xml
@@ -13,56 +13,102 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false">
-
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:orientation="vertical">
-
-
+
-
-
+
-
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout-sw600dp-land/confirm_lock_password.xml b/res/layout-sw600dp-land/confirm_lock_password.xml
deleted file mode 100644
index cbaad7ad8f5..00000000000
--- a/res/layout-sw600dp-land/confirm_lock_password.xml
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout-sw600dp-land/confirm_lock_pattern.xml b/res/layout-sw600dp-land/confirm_lock_pattern.xml
deleted file mode 100644
index a090a6f0a2f..00000000000
--- a/res/layout-sw600dp-land/confirm_lock_pattern.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout-sw600dp/confirm_lock_password.xml b/res/layout-sw600dp/confirm_lock_password.xml
index 12b6ab27fcc..1649aaa5884 100644
--- a/res/layout-sw600dp/confirm_lock_password.xml
+++ b/res/layout-sw600dp/confirm_lock_password.xml
@@ -1,103 +1,26 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ ~ Copyright (C) 2015 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
+ -->
+
+
+
diff --git a/res/layout-sw600dp/confirm_lock_pattern.xml b/res/layout-sw600dp/confirm_lock_pattern.xml
index 12e2b86bafc..5c93ccd18f3 100644
--- a/res/layout-sw600dp/confirm_lock_pattern.xml
+++ b/res/layout-sw600dp/confirm_lock_pattern.xml
@@ -13,48 +13,19 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+ android:paddingTop="48dp"
+ android:background="#80000000">
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/res/layout/confirm_lock_password.xml b/res/layout/confirm_lock_password.xml
deleted file mode 100644
index c9a0bbed943..00000000000
--- a/res/layout/confirm_lock_password.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/confirm_lock_password_base.xml b/res/layout/confirm_lock_password_base.xml
new file mode 100644
index 00000000000..af4ffe8491b
--- /dev/null
+++ b/res/layout/confirm_lock_password_base.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/confirm_lock_pattern.xml b/res/layout/confirm_lock_pattern.xml
deleted file mode 100644
index 44262423994..00000000000
--- a/res/layout/confirm_lock_pattern.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/confirm_lock_pattern_base.xml b/res/layout/confirm_lock_pattern_base.xml
new file mode 100644
index 00000000000..029b85645ec
--- /dev/null
+++ b/res/layout/confirm_lock_pattern_base.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values-land/themes.xml b/res/values-land/themes.xml
new file mode 100644
index 00000000000..8f407c6df8f
--- /dev/null
+++ b/res/values-land/themes.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index e1bb33e20d0..a26c99bb576 100755
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -87,4 +87,6 @@
24dp
25dp
24dp
+
+ 72dp
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
index d09b23e24b2..8cf0e86d0dc 100644
--- a/res/values-sw600dp/styles.xml
+++ b/res/values-sw600dp/styles.xml
@@ -68,5 +68,4 @@
-
diff --git a/res/values-sw600dp/themes.xml b/res/values-sw600dp/themes.xml
new file mode 100644
index 00000000000..833e36e4a02
--- /dev/null
+++ b/res/values-sw600dp/themes.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/aliases.xml b/res/values/aliases.xml
index 97a50c5a675..248ac71263c 100644
--- a/res/values/aliases.xml
+++ b/res/values/aliases.xml
@@ -15,7 +15,8 @@
-->
- - @*android:layout/preference_category_material
-
+ - @*android:layout/preference_category_material
+ - @layout/confirm_lock_pattern_base
+ - @layout/confirm_lock_password_base
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 1fe36d6fb19..248cf92274f 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -109,4 +109,8 @@
+
+
+
+
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 97ba2edb3e2..2d0c74132cc 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -53,7 +53,9 @@
#00000000
#ff37474f
- #fff4511e
+ @color/warning
+
+ #ffffff
@android:color/white
#fff4511e
@@ -76,4 +78,6 @@
#ffe0e0e0
@*android:color/material_deep_teal_500
+ #ff5621
+ #263238
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1fd22e06689..07e6957ce6e 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -238,4 +238,5 @@
96dip
4dip
+ 48dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0cfe9bf86fd..4d63c505636 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -835,12 +835,6 @@
You need to set a lock screen PIN or
password before you can start encryption.
-
-
- You need to draw your unlock pattern to confirm encrypting your device.
-
-
Encrypt?
@@ -2430,8 +2424,6 @@
Reset all network settings? You can\'t reverse this action!
Reset settings
-
- You need to draw your unlock pattern to confirm a network settings reset.
Reset?
@@ -2472,8 +2464,6 @@
Erase all your personal information and downloaded apps? You can\'t reverse this action!
Erase everything
-
- You need to draw your unlock pattern to confirm a factory data reset.
No reset was performed because the System Clear service isn\'t available.
@@ -2508,10 +2498,6 @@
Erase the SD card, deleting all files stored there? You can\'t reverse this action!
Erase everything
-
- You need to draw your unlock pattern to confirm that you want to erase the USB storage.
-
- You need to draw your unlock pattern to confirm that you want to erase the SD card.
Call settings
@@ -2764,6 +2750,26 @@
Pattern has been set
+
+ Use your device pattern to continue.
+
+ Enter your device PIN to continue.
+
+ Enter your device password to continue.
+
+
+ Wrong PIN
+
+ Wrong password
+
+ Wrong pattern
+
Device security
@@ -2771,14 +2777,6 @@
Change unlock pattern
Change unlock PIN
-
- Confirm saved pattern
-
-
-
- Try again:
-
-
Draw an unlock pattern
@@ -2820,10 +2818,9 @@
Change unlock pattern
How to draw an unlock pattern
-
- Too many incorrect attempts!
-
- Try again in %d seconds.
+
+ Too many incorrect attempts. Try again in %d seconds.
Application is not installed on your phone.
@@ -3410,10 +3407,6 @@
OEM unlocking
Allow the bootloader to be unlocked
-
- Enter your PIN
-
- Enter your device PIN to enable OEM unlock
Allow OEM unlocking?
@@ -4388,9 +4381,6 @@
Credentials are not available for this user
-
- You need to draw your unlock pattern to confirm credential installation.
-
@@ -6224,6 +6214,9 @@
- %d apps can open their domain URLs
+
+ Not recognized
+
Default Apps
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 78a3572e0a9..22061e67171 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -78,7 +78,6 @@
@@ -350,6 +349,11 @@
- @color/fingerprint_message_color
+
+
+
+
+
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 479baf70f41..f4e3c4e5c4d 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -145,7 +145,8 @@ public class ChooseLockGeneric extends SettingsActivity {
} else if (!mWaitingForConfirmation) {
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
- if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, null, null)) {
+ if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
+ getString(R.string.unlock_set_unlock_launch_picker_title))) {
mPasswordConfirmed = true; // no password set, so no need to confirm
updatePreferencesOrFinish();
} else {
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 6d7b71d711b..8838286c25e 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -243,7 +243,7 @@ public class ChooseLockPassword extends SettingsActivity {
updateStage(Stage.Introduction);
if (confirmCredentials) {
mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
- null, null);
+ getString(R.string.unlock_set_unlock_launch_picker_title));
}
} else {
mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index 1865a6b8276..889234636a7 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -379,7 +379,8 @@ public class ChooseLockPattern extends SettingsActivity {
updateStage(Stage.NeedToConfirm);
boolean launchedConfirmationActivity =
mChooseLockSettingsHelper.launchConfirmationActivity(
- CONFIRM_EXISTING_REQUEST, null, null);
+ CONFIRM_EXISTING_REQUEST,
+ getString(R.string.unlock_set_unlock_launch_picker_title));
if (!launchedConfirmationActivity) {
updateStage(Stage.Introduction);
}
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index bba45ced86b..65697f69708 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -16,13 +16,14 @@
package com.android.settings;
-import com.android.internal.widget.LockPatternUtils;
-
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
+import com.android.internal.widget.LockPatternUtils;
+
public final class ChooseLockSettingsHelper {
static final String EXTRA_KEY_TYPE = "type";
@@ -48,64 +49,77 @@ public final class ChooseLockSettingsHelper {
/**
* If a pattern, password or PIN exists, prompt the user before allowing them to change it.
- * @param message optional message to display about the action about to be done
- * @param details optional detail message to display
+ *
+ * @param title title of the confirmation screen; shown in the action bar
* @return true if one exists and we launched an activity to confirm it
- * @see #onActivityResult(int, int, android.content.Intent)
+ * @see Activity#onActivityResult(int, int, android.content.Intent)
*/
- boolean launchConfirmationActivity(int request, CharSequence message, CharSequence details) {
- return launchConfirmationActivity(request, message, details, false);
+ boolean launchConfirmationActivity(int request, CharSequence title) {
+ return launchConfirmationActivity(request, title, null, null, false, false);
}
/**
* If a pattern, password or PIN exists, prompt the user before allowing them to change it.
- * @param message optional message to display about the action about to be done
- * @param details optional detail message to display
+ *
+ * @param title title of the confirmation screen; shown in the action bar
* @param returnCredentials if true, put credentials into intent. Note that if this is true,
- this can only be called internally.
+ * this can only be called internally.
* @return true if one exists and we launched an activity to confirm it
- * @see #onActivityResult(int, int, android.content.Intent)
+ * @see Activity#onActivityResult(int, int, android.content.Intent)
*/
- boolean launchConfirmationActivity(int request, CharSequence message, CharSequence details,
- boolean returnCredentials) {
+ boolean launchConfirmationActivity(int request, CharSequence title, boolean returnCredentials) {
+ return launchConfirmationActivity(request, title, null, null, returnCredentials, false);
+ }
+
+ /**
+ * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
+ *
+ * @param title title of the confirmation screen; shown in the action bar
+ * @param header header of the confirmation screen; shown as large text
+ * @param description description of the confirmation screen
+ * @param returnCredentials if true, put credentials into intent. Note that if this is true,
+ * this can only be called internally.
+ * @param external specifies whether this activity is launched externally, meaning that it will
+ * get a dark theme and allow fingerprint authentication
+ * @return true if one exists and we launched an activity to confirm it
+ * @see Activity#onActivityResult(int, int, android.content.Intent)
+ */
+ boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
+ @Nullable CharSequence header, @Nullable CharSequence description,
+ boolean returnCredentials, boolean external) {
boolean launched = false;
switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
- launched = confirmPattern(request, message, details, returnCredentials);
+ launched = launchConfirmationActivity(request, title, header, description,
+ returnCredentials
+ ? ConfirmLockPattern.InternalActivity.class
+ : ConfirmLockPattern.class, external);
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
- // TODO: update UI layout for ConfirmPassword to show message and details
- launched = confirmPassword(request, message, returnCredentials);
+ launched = launchConfirmationActivity(request, title, header, description,
+ returnCredentials
+ ? ConfirmLockPassword.InternalActivity.class
+ : ConfirmLockPassword.class, external);
break;
}
return launched;
}
- /**
- * Launch screen to confirm the existing lock pattern.
- * @param message shown in header of ConfirmLockPattern if not null
- * @param details shown in footer of ConfirmLockPattern if not null
- * @param returnCredentials if true, put credentials into intent.
- * @see #onActivityResult(int, int, android.content.Intent)
- * @return true if we launched an activity to confirm pattern
- */
- private boolean confirmPattern(int request, CharSequence message,
- CharSequence details, boolean returnCredentials) {
- if (!mLockPatternUtils.isLockPatternEnabled()) {
- return false;
- }
+ private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
+ CharSequence message, Class> activityClass, boolean external) {
final Intent intent = new Intent();
- // supply header and footer text in the intent
- intent.putExtra(ConfirmLockPattern.HEADER_TEXT, message);
- intent.putExtra(ConfirmLockPattern.FOOTER_TEXT, details);
- intent.setClassName("com.android.settings",
- returnCredentials
- ? ConfirmLockPattern.InternalActivity.class.getName()
- : ConfirmLockPattern.class.getName());
+ intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
+ intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
+ intent.putExtra(ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT, message);
+ intent.putExtra(ConfirmDeviceCredentialBaseFragment.ALLOW_FP_AUTHENTICATION, external);
+ intent.putExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, external);
+ intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_CANCEL_BUTTON, external);
+ intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external);
+ intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName());
if (mFragment != null) {
mFragment.startActivityForResult(intent, request);
} else {
@@ -113,31 +127,4 @@ public final class ChooseLockSettingsHelper {
}
return true;
}
-
- /**
- * Launch screen to confirm the existing lock password.
- * @param message shown in header of ConfirmLockPassword if not null
- * @param returnCredentials if true, put credentials into intent.
- * @see #onActivityResult(int, int, android.content.Intent)
- * @return true if we launched an activity to confirm password
- */
- private boolean confirmPassword(int request, CharSequence message,
- boolean returnCredentials) {
- if (!mLockPatternUtils.isLockPasswordEnabled()) return false;
- final Intent intent = new Intent();
- // supply header text in the intent
- intent.putExtra(ConfirmLockPattern.HEADER_TEXT, message);
- intent.setClassName("com.android.settings",
- returnCredentials
- ? ConfirmLockPassword.InternalActivity.class.getName()
- : ConfirmLockPassword.class.getName());
- if (mFragment != null) {
- mFragment.startActivityForResult(intent, request);
- } else {
- mActivity.startActivityForResult(intent, request);
- }
- return true;
- }
-
-
}
diff --git a/src/com/android/settings/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/ConfirmDeviceCredentialActivity.java
index beb2d97d6e1..9a7f843ac3c 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialActivity.java
@@ -48,7 +48,8 @@ public class ConfirmDeviceCredentialActivity extends Activity {
String details = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION);
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
- if (!helper.launchConfirmationActivity(0 /* request code */, title, details)) {
+ if (!helper.launchConfirmationActivity(0 /* request code */, null /* title */, title,
+ details, false /* returnCredentials */, true /* isExternal */)) {
Log.d(TAG, "No pattern, password or PIN set.");
setResult(Activity.RESULT_OK);
finish();
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java b/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java
new file mode 100644
index 00000000000..fe3de976caa
--- /dev/null
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.app.KeyguardManager;
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.WindowManager;
+
+public class ConfirmDeviceCredentialBaseActivity extends SettingsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedState) {
+ if (getIntent().getBooleanExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, false)) {
+ setTheme(R.style.Theme_ConfirmDeviceCredentialsDark);
+ }
+ super.onCreate(savedState);
+ boolean deviceLocked = getSystemService(KeyguardManager.class).isKeyguardLocked();
+ if (deviceLocked && getIntent().getBooleanExtra(
+ ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, false)) {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ }
+ CharSequence msg = getIntent().getStringExtra(
+ ConfirmDeviceCredentialBaseFragment.TITLE_TEXT);
+ setTitle(msg);
+ if (getActionBar() != null) {
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ getActionBar().setHomeButtonEnabled(true);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
new file mode 100644
index 00000000000..f9908b0f64e
--- /dev/null
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.annotation.Nullable;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * Base fragment to be shared for PIN/Pattern/Password confirmation fragments.
+ */
+public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment
+ implements FingerprintUiHelper.Callback {
+
+ public static final String PACKAGE = "com.android.settings";
+ public static final String TITLE_TEXT = PACKAGE + ".ConfirmCredentials.title";
+ public static final String HEADER_TEXT = PACKAGE + ".ConfirmCredentials.header";
+ public static final String DETAILS_TEXT = PACKAGE + ".ConfirmCredentials.details";
+ public static final String ALLOW_FP_AUTHENTICATION =
+ PACKAGE + ".ConfirmCredentials.allowFpAuthentication";
+ public static final String DARK_THEME = PACKAGE + ".ConfirmCredentials.darkTheme";
+ public static final String SHOW_CANCEL_BUTTON =
+ PACKAGE + ".ConfirmCredentials.showCancelButton";
+ public static final String SHOW_WHEN_LOCKED =
+ PACKAGE + ".ConfirmCredentials.showWhenLocked";
+
+ private FingerprintUiHelper mFingerprintHelper;
+ private boolean mAllowFpAuthentication;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mAllowFpAuthentication = getActivity().getIntent().getBooleanExtra(
+ ALLOW_FP_AUTHENTICATION, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ mFingerprintHelper = new FingerprintUiHelper(
+ (ImageView) view.findViewById(R.id.fingerprintIcon),
+ (TextView) view.findViewById(R.id.errorText), this);
+ boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
+ SHOW_CANCEL_BUTTON, false);
+ Button cancelButton = (Button) view.findViewById(R.id.cancelButton);
+ cancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE);
+ cancelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ getActivity().finish();
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mAllowFpAuthentication) {
+ mFingerprintHelper.startListening();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mAllowFpAuthentication) {
+ mFingerprintHelper.stopListening();
+ }
+ }
+
+ @Override
+ public void onAuthenticated() {
+ // Check whether we are still active.
+ if (getActivity() != null && getActivity().isResumed()) {
+ authenticationSucceeded(null /* password */);
+ }
+ }
+
+ protected abstract void authenticationSucceeded(@Nullable String password);
+
+ @Override
+ public void onFingerprintIconVisibilityChanged(boolean visible) {
+ }
+}
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index b49dc6eb00e..44c599b70de 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -16,14 +16,11 @@
package com.android.settings;
+import android.annotation.Nullable;
import android.text.TextUtils;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.PasswordEntryKeyboardHelper;
-import com.android.internal.widget.PasswordEntryKeyboardView;
-import android.app.Activity;
-import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.os.Bundle;
@@ -31,23 +28,18 @@ import android.os.CountDownTimer;
import android.os.Handler;
import android.os.SystemClock;
import android.os.storage.StorageManager;
-import android.text.Editable;
import android.text.InputType;
-import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
-import android.widget.Button;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-public class ConfirmLockPassword extends SettingsActivity {
-
- public static final String PACKAGE = "com.android.settings";
- public static final String HEADER_TEXT = PACKAGE + ".ConfirmLockPattern.header";
+public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
public static class InternalActivity extends ConfirmLockPassword {
}
@@ -65,28 +57,17 @@ public class ConfirmLockPassword extends SettingsActivity {
return false;
}
- @Override
- public void onCreate(Bundle savedInstanceState) {
- // Disable IME on our window since we provide our own keyboard
- //getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- //WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- super.onCreate(savedInstanceState);
- CharSequence msg = getText(R.string.lockpassword_confirm_your_password_header);
- setTitle(msg);
- }
-
- public static class ConfirmLockPasswordFragment extends InstrumentedFragment
- implements OnClickListener, OnEditorActionListener, TextWatcher {
+ public static class ConfirmLockPasswordFragment extends ConfirmDeviceCredentialBaseFragment
+ implements OnClickListener, OnEditorActionListener {
private static final String KEY_NUM_WRONG_CONFIRM_ATTEMPTS
= "confirm_lock_password_fragment.key_num_wrong_confirm_attempts";
private static final long ERROR_MESSAGE_TIMEOUT = 3000;
private TextView mPasswordEntry;
private LockPatternUtils mLockPatternUtils;
- private TextView mHeaderText;
+ private TextView mHeaderTextView;
+ private TextView mDetailsTextView;
+ private TextView mErrorTextView;
private Handler mHandler = new Handler();
- private PasswordEntryKeyboardHelper mKeyboardHelper;
- private PasswordEntryKeyboardView mKeyboardView;
- private Button mContinueButton;
private int mNumWrongConfirmAttempts;
private CountDownTimer mCountdownTimer;
private boolean mIsAlpha;
@@ -111,51 +92,35 @@ public class ConfirmLockPassword extends SettingsActivity {
Bundle savedInstanceState) {
final int storedQuality = mLockPatternUtils.getKeyguardStoredPasswordQuality();
View view = inflater.inflate(R.layout.confirm_lock_password, null);
- // Disable IME on our window since we provide our own keyboard
-
- view.findViewById(R.id.cancel_button).setOnClickListener(this);
- mContinueButton = (Button) view.findViewById(R.id.next_button);
- mContinueButton.setOnClickListener(this);
- mContinueButton.setEnabled(false); // disable until the user enters at least one char
mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
- mPasswordEntry.addTextChangedListener(this);
- mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
- mHeaderText = (TextView) view.findViewById(R.id.headerText);
+ mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
+ mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
+ mErrorTextView = (TextView) view.findViewById(R.id.errorText);
mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
|| DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
|| DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality;
Intent intent = getActivity().getIntent();
if (intent != null) {
- CharSequence headerMessage = intent.getCharSequenceExtra(HEADER_TEXT);
+ CharSequence headerMessage = intent.getCharSequenceExtra(
+ ConfirmDeviceCredentialBaseFragment.HEADER_TEXT);
+ CharSequence detailsMessage = intent.getCharSequenceExtra(
+ ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT);
if (TextUtils.isEmpty(headerMessage)) {
headerMessage = getString(getDefaultHeader());
}
- mHeaderText.setText(headerMessage);
+ if (TextUtils.isEmpty(detailsMessage)) {
+ detailsMessage = getString(getDefaultDetails());
+ }
+ mHeaderTextView.setText(headerMessage);
+ mDetailsTextView.setText(detailsMessage);
}
-
- final Activity activity = getActivity();
- mKeyboardHelper = new PasswordEntryKeyboardHelper(activity,
- mKeyboardView, mPasswordEntry);
- mKeyboardHelper.setKeyboardMode(mIsAlpha ?
- PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
- : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
- mKeyboardView.requestFocus();
-
int currentType = mPasswordEntry.getInputType();
mPasswordEntry.setInputType(mIsAlpha ? currentType
: (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
-
- if (activity instanceof SettingsActivity) {
- final SettingsActivity sa = (SettingsActivity) activity;
- int id = getDefaultHeader();
- CharSequence title = getText(id);
- sa.setTitle(title);
- }
-
return view;
}
@@ -164,10 +129,19 @@ public class ConfirmLockPassword extends SettingsActivity {
: R.string.lockpassword_confirm_your_pin_header;
}
+ private int getDefaultDetails() {
+ return mIsAlpha ? R.string.lockpassword_confirm_your_password_generic
+ : R.string.lockpassword_confirm_your_pin_generic;
+ }
+
+ private int getErrorMessage() {
+ return mIsAlpha ? R.string.lockpassword_invalid_password
+ : R.string.lockpassword_invalid_pin;
+ }
+
@Override
public void onPause() {
super.onPause();
- mKeyboardView.requestFocus();
if (mCountdownTimer != null) {
mCountdownTimer.cancel();
mCountdownTimer = null;
@@ -181,9 +155,7 @@ public class ConfirmLockPassword extends SettingsActivity {
@Override
public void onResume() {
- // TODO Auto-generated method stub
super.onResume();
- mKeyboardView.requestFocus();
long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
if (deadline != 0) {
handleAttemptLockout(deadline);
@@ -196,33 +168,35 @@ public class ConfirmLockPassword extends SettingsActivity {
outState.putInt(KEY_NUM_WRONG_CONFIRM_ATTEMPTS, mNumWrongConfirmAttempts);
}
+ @Override
+ protected void authenticationSucceeded(@Nullable String password) {
+ Intent intent = new Intent();
+ if (getActivity() instanceof ConfirmLockPassword.InternalActivity) {
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
+ mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
+ : StorageManager.CRYPT_TYPE_PIN);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
+ }
+ getActivity().setResult(RESULT_OK, intent);
+ getActivity().finish();
+ }
+
private void handleNext() {
final String pin = mPasswordEntry.getText().toString();
if (mLockPatternUtils.checkPassword(pin)) {
-
- Intent intent = new Intent();
- if (getActivity() instanceof ConfirmLockPassword.InternalActivity) {
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
- mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
- : StorageManager.CRYPT_TYPE_PIN);
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pin);
- }
-
- getActivity().setResult(RESULT_OK, intent);
- getActivity().finish();
+ authenticationSucceeded(pin);
} else {
if (++mNumWrongConfirmAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
handleAttemptLockout(deadline);
} else {
- showError(R.string.lockpattern_need_to_unlock_wrong);
+ showError(getErrorMessage());
}
}
}
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
long elapsedRealtime = SystemClock.elapsedRealtime();
- showError(R.string.lockpattern_too_many_failed_confirmation_attempts_header, 0);
mPasswordEntry.setEnabled(false);
mCountdownTimer = new CountDownTimer(
elapsedRealtimeDeadline - elapsedRealtime,
@@ -231,15 +205,15 @@ public class ConfirmLockPassword extends SettingsActivity {
@Override
public void onTick(long millisUntilFinished) {
final int secondsCountdown = (int) (millisUntilFinished / 1000);
- mHeaderText.setText(getString(
- R.string.lockpattern_too_many_failed_confirmation_attempts_footer,
- secondsCountdown));
+ showError(getString(
+ R.string.lockpattern_too_many_failed_confirmation_attempts,
+ secondsCountdown), 0);
}
@Override
public void onFinish() {
mPasswordEntry.setEnabled(true);
- mHeaderText.setText(getDefaultHeader());
+ mErrorTextView.setText("");
mNumWrongConfirmAttempts = 0;
}
}.start();
@@ -264,13 +238,13 @@ public class ConfirmLockPassword extends SettingsActivity {
private final Runnable mResetErrorRunnable = new Runnable() {
public void run() {
- mHeaderText.setText(getDefaultHeader());
+ mErrorTextView.setText("");
}
};
- private void showError(int msg, long timeout) {
- mHeaderText.setText(msg);
- mHeaderText.announceForAccessibility(mHeaderText.getText());
+ private void showError(CharSequence msg, long timeout) {
+ mErrorTextView.setText(msg);
+ mErrorTextView.announceForAccessibility(mErrorTextView.getText());
mPasswordEntry.setText(null);
mHandler.removeCallbacks(mResetErrorRunnable);
if (timeout != 0) {
@@ -278,6 +252,10 @@ public class ConfirmLockPassword extends SettingsActivity {
}
}
+ private void showError(int msg, long timeout) {
+ showError(getText(msg), timeout);
+ }
+
// {@link OnEditorActionListener} methods.
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter or "done" key
@@ -289,16 +267,5 @@ public class ConfirmLockPassword extends SettingsActivity {
}
return false;
}
-
- // {@link TextWatcher} methods.
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- public void afterTextChanged(Editable s) {
- mContinueButton.setEnabled(mPasswordEntry.getText().length() > 0);
- }
}
}
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index b5d444bfead..8c4fabcd639 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -22,13 +22,14 @@ import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
import com.android.internal.widget.LockPatternView.Cell;
+import android.annotation.Nullable;
import android.app.Activity;
-import android.app.Fragment;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.os.Bundle;
import android.os.storage.StorageManager;
+import android.view.MenuItem;
import android.widget.TextView;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,36 +43,17 @@ import java.util.List;
* Sets an activity result of {@link Activity#RESULT_OK} when the user
* successfully confirmed their pattern.
*/
-public class ConfirmLockPattern extends SettingsActivity {
+public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
public static class InternalActivity extends ConfirmLockPattern {
}
- /**
- * Names of {@link CharSequence} fields within the originating {@link Intent}
- * that are used to configure the keyguard confirmation view's labeling.
- * The view will use the system-defined resource strings for any labels that
- * the caller does not supply.
- */
- public static final String PACKAGE = "com.android.settings";
- public static final String HEADER_TEXT = PACKAGE + ".ConfirmLockPattern.header";
- public static final String FOOTER_TEXT = PACKAGE + ".ConfirmLockPattern.footer";
- public static final String HEADER_WRONG_TEXT = PACKAGE + ".ConfirmLockPattern.header_wrong";
- public static final String FOOTER_WRONG_TEXT = PACKAGE + ".ConfirmLockPattern.footer_wrong";
-
private enum Stage {
NeedToUnlock,
NeedToUnlockWrong,
LockedOut
}
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- CharSequence msg = getText(R.string.lockpassword_confirm_your_pattern_header);
- setTitle(msg);
- }
-
@Override
public Intent getIntent() {
Intent modIntent = new Intent(super.getIntent());
@@ -85,7 +67,7 @@ public class ConfirmLockPattern extends SettingsActivity {
return false;
}
- public static class ConfirmLockPatternFragment extends InstrumentedFragment {
+ public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment {
// how long we wait to clear a wrong pattern
private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
@@ -98,13 +80,14 @@ public class ConfirmLockPattern extends SettingsActivity {
private CountDownTimer mCountdownTimer;
private TextView mHeaderTextView;
- private TextView mFooterTextView;
+ private TextView mDetailsTextView;
+ private TextView mErrorTextView;
+ private View mLeftSpacerLandscape;
+ private View mRightSpacerLandscape;
// caller-supplied text for various prompts
private CharSequence mHeaderText;
- private CharSequence mFooterText;
- private CharSequence mHeaderWrongText;
- private CharSequence mFooterWrongText;
+ private CharSequence mDetailsText;
// required constructor for fragments
public ConfirmLockPatternFragment() {
@@ -123,7 +106,10 @@ public class ConfirmLockPattern extends SettingsActivity {
View view = inflater.inflate(R.layout.confirm_lock_pattern, null);
mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern);
- mFooterTextView = (TextView) view.findViewById(R.id.footerText);
+ mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
+ mErrorTextView = (TextView) view.findViewById(R.id.errorText);
+ mLeftSpacerLandscape = view.findViewById(R.id.leftSpacer);
+ mRightSpacerLandscape = view.findViewById(R.id.rightSpacer);
// make it so unhandled touch events within the unlock screen go to the
// lock pattern view.
@@ -133,10 +119,10 @@ public class ConfirmLockPattern extends SettingsActivity {
Intent intent = getActivity().getIntent();
if (intent != null) {
- mHeaderText = intent.getCharSequenceExtra(HEADER_TEXT);
- mFooterText = intent.getCharSequenceExtra(FOOTER_TEXT);
- mHeaderWrongText = intent.getCharSequenceExtra(HEADER_WRONG_TEXT);
- mFooterWrongText = intent.getCharSequenceExtra(FOOTER_WRONG_TEXT);
+ mHeaderText = intent.getCharSequenceExtra(
+ ConfirmDeviceCredentialBaseFragment.HEADER_TEXT);
+ mDetailsText = intent.getCharSequenceExtra(
+ ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT);
}
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
@@ -199,28 +185,21 @@ public class ConfirmLockPattern extends SettingsActivity {
if (mHeaderText != null) {
mHeaderTextView.setText(mHeaderText);
} else {
- mHeaderTextView.setText(R.string.lockpattern_need_to_unlock);
+ mHeaderTextView.setText(R.string.lockpassword_confirm_your_pattern_header);
}
- if (mFooterText != null) {
- mFooterTextView.setText(mFooterText);
+ if (mDetailsText != null) {
+ mDetailsTextView.setText(mDetailsText);
} else {
- mFooterTextView.setText(R.string.lockpattern_need_to_unlock_footer);
+ mDetailsTextView.setText(
+ R.string.lockpassword_confirm_your_pattern_generic);
}
+ mErrorTextView.setText("");
mLockPatternView.setEnabled(true);
mLockPatternView.enableInput();
break;
case NeedToUnlockWrong:
- if (mHeaderWrongText != null) {
- mHeaderTextView.setText(mHeaderWrongText);
- } else {
- mHeaderTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
- }
- if (mFooterWrongText != null) {
- mFooterTextView.setText(mFooterWrongText);
- } else {
- mFooterTextView.setText(R.string.lockpattern_need_to_unlock_wrong_footer);
- }
+ mErrorTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
mLockPatternView.setEnabled(true);
@@ -252,6 +231,28 @@ public class ConfirmLockPattern extends SettingsActivity {
mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
}
+ @Override
+ protected void authenticationSucceeded(@Nullable String password) {
+ Intent intent = new Intent();
+ if (getActivity() instanceof ConfirmLockPattern.InternalActivity) {
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
+ StorageManager.CRYPT_TYPE_PATTERN);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
+ }
+ getActivity().setResult(Activity.RESULT_OK, intent);
+ getActivity().finish();
+ }
+
+ @Override
+ public void onFingerprintIconVisibilityChanged(boolean visible) {
+ if (mLeftSpacerLandscape != null && mRightSpacerLandscape != null) {
+
+ // In landscape, adjust spacing depending on fingerprint icon visibility.
+ mLeftSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
+ mRightSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
+ }
+ }
+
/**
* The pattern listener that responds according to a user confirming
* an existing lock pattern.
@@ -273,17 +274,7 @@ public class ConfirmLockPattern extends SettingsActivity {
public void onPatternDetected(List pattern) {
if (mLockPatternUtils.checkPattern(pattern)) {
-
- Intent intent = new Intent();
- if (getActivity() instanceof ConfirmLockPattern.InternalActivity) {
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
- StorageManager.CRYPT_TYPE_PATTERN);
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
- LockPatternUtils.patternToString(pattern));
- }
-
- getActivity().setResult(Activity.RESULT_OK, intent);
- getActivity().finish();
+ authenticationSucceeded(LockPatternUtils.patternToString(pattern));
} else {
if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL &&
++mNumWrongConfirmAttempts
@@ -308,10 +299,9 @@ public class ConfirmLockPattern extends SettingsActivity {
@Override
public void onTick(long millisUntilFinished) {
- mHeaderTextView.setText(R.string.lockpattern_too_many_failed_confirmation_attempts_header);
final int secondsCountdown = (int) (millisUntilFinished / 1000);
- mFooterTextView.setText(getString(
- R.string.lockpattern_too_many_failed_confirmation_attempts_footer,
+ mErrorTextView.setText(getString(
+ R.string.lockpattern_too_many_failed_confirmation_attempts,
secondsCountdown));
}
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java
index 45d3d117a38..8506964d87d 100644
--- a/src/com/android/settings/CredentialStorage.java
+++ b/src/com/android/settings/CredentialStorage.java
@@ -439,9 +439,8 @@ public final class CredentialStorage extends Activity {
private boolean confirmKeyGuard() {
Resources res = getResources();
boolean launched = new ChooseLockSettingsHelper(this)
- .launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST, null,
- res.getText(R.string.credentials_install_gesture_explanation),
- true);
+ .launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST,
+ res.getText(R.string.credentials_title), true);
return launched;
}
diff --git a/src/com/android/settings/CryptKeeperSettings.java b/src/com/android/settings/CryptKeeperSettings.java
index 3fb60e3284c..2e4aeb89f4f 100644
--- a/src/com/android/settings/CryptKeeperSettings.java
+++ b/src/com/android/settings/CryptKeeperSettings.java
@@ -166,9 +166,8 @@ public class CryptKeeperSettings extends InstrumentedFragment {
return true;
}
- return helper.launchConfirmationActivity(request, null,
- res.getText(R.string.crypt_keeper_confirm_encrypt),
- true);
+ return helper.launchConfirmationActivity(request,
+ res.getText(R.string.crypt_keeper_encrypt_title), true);
}
@Override
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 5fafc923f77..5c7e0e97b22 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -1610,10 +1610,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
}
private boolean showKeyguardConfirmation(Resources resources, int requestCode) {
- return new ChooseLockSettingsHelper(getActivity(), this)
- .launchConfirmationActivity(requestCode,
- resources.getString(R.string.oem_unlock_enable_pin_prompt),
- resources.getString(R.string.oem_unlock_enable_pin_description));
+ return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
+ requestCode, resources.getString(R.string.oem_unlock_enable));
}
@Override
diff --git a/src/com/android/settings/FingerprintUiHelper.java b/src/com/android/settings/FingerprintUiHelper.java
new file mode 100644
index 00000000000..20ad7fc50c4
--- /dev/null
+++ b/src/com/android/settings/FingerprintUiHelper.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.CancellationSignal;
+import android.os.Vibrator;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * Small helper class to manage text/icon around fingerprint authentication UI.
+ */
+public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
+
+ private static final long ERROR_TIMEOUT = 1300;
+ private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30};
+ private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30};
+
+ private ImageView mIcon;
+ private TextView mErrorTextView;
+ private CancellationSignal mCancellationSignal;
+
+ private Callback mCallback;
+ private FingerprintManager mFingerprintManager;
+
+ public FingerprintUiHelper(ImageView icon, TextView errorTextView, Callback callback) {
+ mFingerprintManager = icon.getContext().getSystemService(FingerprintManager.class);
+ mIcon = icon;
+ mErrorTextView = errorTextView;
+ mCallback = callback;
+ }
+
+ public void startListening() {
+ if (mFingerprintManager.getEnrolledFingerprints().size() > 0) {
+ mCancellationSignal = new CancellationSignal();
+ mFingerprintManager.authenticate(null, mCancellationSignal, this, 0 /* flags */);
+ setFingerprintIconVisibility(true);
+ mIcon.setImageResource(R.drawable.ic_fingerprint);
+ }
+ }
+
+ public void stopListening() {
+ mCancellationSignal.cancel();
+ mCancellationSignal = null;
+ }
+
+ private void setFingerprintIconVisibility(boolean visible) {
+ mIcon.setVisibility(visible ? View.VISIBLE : View.GONE);
+ mCallback.onFingerprintIconVisibilityChanged(visible);
+ }
+
+ @Override
+ public void onAuthenticationError(int errMsgId, CharSequence errString) {
+ showError(errString);
+ setFingerprintIconVisibility(false);
+ }
+
+ @Override
+ public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
+ showError(helpString);
+ }
+
+ @Override
+ public void onAuthenticationFailed() {
+ showError(mIcon.getResources().getString(
+ R.string.fingerprint_not_recognized));
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
+ vibrateFingerprintSuccess();
+ mCallback.onAuthenticated();
+ }
+
+ private void showError(CharSequence error) {
+ vibrateFingerprintError();
+ mIcon.setImageResource(R.drawable.ic_fingerprint_error);
+ mErrorTextView.setText(error);
+ mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
+ mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT);
+ }
+
+ private void vibrateFingerprintError() {
+ mIcon.getContext().getSystemService(Vibrator.class).vibrate(FP_ERROR_VIBRATE_PATTERN, -1);
+ }
+
+ private void vibrateFingerprintSuccess() {
+ mIcon.getContext().getSystemService(Vibrator.class).vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1);
+ }
+
+ private Runnable mResetErrorTextRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mErrorTextView.setText("");
+ mIcon.setImageResource(R.drawable.ic_fingerprint);
+ }
+ };
+
+ public interface Callback {
+ void onAuthenticated();
+ void onFingerprintIconVisibilityChanged(boolean visible);
+ }
+}
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 1b6468fd116..23f6812289d 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -75,8 +75,8 @@ public class MasterClear extends InstrumentedFragment {
*/
private boolean runKeyguardConfirmation(int request) {
Resources res = getActivity().getResources();
- return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(request,
- null, res.getText(R.string.master_clear_gesture_explanation));
+ return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
+ request, res.getText(R.string.master_clear_title));
}
@Override
diff --git a/src/com/android/settings/MediaFormat.java b/src/com/android/settings/MediaFormat.java
index 20dac8e5767..517ec2d7030 100644
--- a/src/com/android/settings/MediaFormat.java
+++ b/src/com/android/settings/MediaFormat.java
@@ -72,9 +72,8 @@ public class MediaFormat extends Activity {
* component as a subactivity
*/
private boolean runKeyguardConfirmation(int request) {
- return new ChooseLockSettingsHelper(this)
- .launchConfirmationActivity(request, null,
- getText(R.string.media_format_gesture_explanation));
+ return new ChooseLockSettingsHelper(this).launchConfirmationActivity(request,
+ getText(R.string.media_format_title));
}
@Override
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index a3376d3fd4e..587b8e8623b 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -78,8 +78,8 @@ public class ResetNetwork extends InstrumentedFragment {
*/
private boolean runKeyguardConfirmation(int request) {
Resources res = getActivity().getResources();
- return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(request,
- null, res.getText(R.string.reset_network_gesture_explanation));
+ return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
+ request, res.getText(R.string.reset_network_title));
}
@Override
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index c74c90a5c9d..fd99536b6a6 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -603,8 +603,9 @@ public class SecuritySettings extends SettingsPreferenceFragment
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
mTrustAgentClickIntent = preference.getIntent();
- if (!helper.launchConfirmationActivity(CHANGE_TRUST_AGENT_SETTINGS, null, null) &&
- mTrustAgentClickIntent != null) {
+ boolean confirmationLaunched = helper.launchConfirmationActivity(
+ CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());
+ if (!confirmationLaunched&& mTrustAgentClickIntent != null) {
// If this returns false, it means no password confirmation is required.
startActivity(mTrustAgentClickIntent);
mTrustAgentClickIntent = null;