diff options
author | Jim Miller <jaggies@google.com> | 2015-03-04 18:07:32 -0800 |
---|---|---|
committer | Jim Miller <jaggies@google.com> | 2015-03-11 18:15:55 -0700 |
commit | 9218687e4baaf0226ef16b58f78123d979711e5d (patch) | |
tree | 0f5f51299a5f28ead30386f71243782bab000981 | |
parent | 5455bb540a8b4a5150a1b790c4a36fb0410f8ac3 (diff) | |
download | packages_apps_Settings-9218687e4baaf0226ef16b58f78123d979711e5d.zip packages_apps_Settings-9218687e4baaf0226ef16b58f78123d979711e5d.tar.gz packages_apps_Settings-9218687e4baaf0226ef16b58f78123d979711e5d.tar.bz2 |
Implement additional fingerprint flows in Settings.
- new onboarding flow ("locate sensor")
- changed sensor location image
- changed in-app sensor icon
- remove fingerprint animation since it caused people to
want to tap on it.
- remove enrolled fingerprint templates when switching back to "none" or "slide"
- use real in-app icon for fingerprint
- much improved layout
- basic landscape layout working
- added 250ms delay to final enrollment step so it's not so jarring
- delete is now working
- rename wired, but not functional yet
Bug 19592835
Change-Id: Ie3e73a2fc8f834f1b90e2746c4cc841216aa6031
32 files changed, 514 insertions, 161 deletions
diff --git a/res/drawable-nodpi/fingerprint_anim00.png b/res/drawable-nodpi/fingerprint_anim00.png Binary files differdeleted file mode 100644 index 97d2644..0000000 --- a/res/drawable-nodpi/fingerprint_anim00.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim01.png b/res/drawable-nodpi/fingerprint_anim01.png Binary files differdeleted file mode 100644 index d6c86b8..0000000 --- a/res/drawable-nodpi/fingerprint_anim01.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim02.png b/res/drawable-nodpi/fingerprint_anim02.png Binary files differdeleted file mode 100644 index ddc8ac3..0000000 --- a/res/drawable-nodpi/fingerprint_anim02.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim03.png b/res/drawable-nodpi/fingerprint_anim03.png Binary files differdeleted file mode 100644 index 3435c46..0000000 --- a/res/drawable-nodpi/fingerprint_anim03.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim04.png b/res/drawable-nodpi/fingerprint_anim04.png Binary files differdeleted file mode 100644 index 2f8f949..0000000 --- a/res/drawable-nodpi/fingerprint_anim04.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim05.png b/res/drawable-nodpi/fingerprint_anim05.png Binary files differdeleted file mode 100644 index 47178b7..0000000 --- a/res/drawable-nodpi/fingerprint_anim05.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim06.png b/res/drawable-nodpi/fingerprint_anim06.png Binary files differdeleted file mode 100644 index e0a29d1..0000000 --- a/res/drawable-nodpi/fingerprint_anim06.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim07.png b/res/drawable-nodpi/fingerprint_anim07.png Binary files differdeleted file mode 100644 index d92d75b..0000000 --- a/res/drawable-nodpi/fingerprint_anim07.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim08.png b/res/drawable-nodpi/fingerprint_anim08.png Binary files differdeleted file mode 100644 index 9c77868..0000000 --- a/res/drawable-nodpi/fingerprint_anim08.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim09.png b/res/drawable-nodpi/fingerprint_anim09.png Binary files differdeleted file mode 100644 index 5ebaa0c..0000000 --- a/res/drawable-nodpi/fingerprint_anim09.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim10.png b/res/drawable-nodpi/fingerprint_anim10.png Binary files differdeleted file mode 100644 index b1f9ca9..0000000 --- a/res/drawable-nodpi/fingerprint_anim10.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim11.png b/res/drawable-nodpi/fingerprint_anim11.png Binary files differdeleted file mode 100644 index b8fb5d7..0000000 --- a/res/drawable-nodpi/fingerprint_anim11.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_anim12.png b/res/drawable-nodpi/fingerprint_anim12.png Binary files differdeleted file mode 100644 index 97d2644..0000000 --- a/res/drawable-nodpi/fingerprint_anim12.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_in_app_indicator.png b/res/drawable-nodpi/fingerprint_in_app_indicator.png Binary files differdeleted file mode 100644 index 4af83e6..0000000 --- a/res/drawable-nodpi/fingerprint_in_app_indicator.png +++ /dev/null diff --git a/res/drawable-nodpi/fingerprint_sensor_location.png b/res/drawable-nodpi/fingerprint_sensor_location.png Binary files differdeleted file mode 100644 index 0486dba..0000000 --- a/res/drawable-nodpi/fingerprint_sensor_location.png +++ /dev/null diff --git a/res/drawable-xxhdpi/fingerprint_in_app_indicator.png b/res/drawable-xxhdpi/fingerprint_in_app_indicator.png Binary files differnew file mode 100644 index 0000000..fc56a9a --- /dev/null +++ b/res/drawable-xxhdpi/fingerprint_in_app_indicator.png diff --git a/res/drawable-xxhdpi/fingerprint_indicator.png b/res/drawable-xxhdpi/fingerprint_indicator.png Binary files differnew file mode 100644 index 0000000..fc5ef0f --- /dev/null +++ b/res/drawable-xxhdpi/fingerprint_indicator.png diff --git a/res/drawable-xxhdpi/fingerprint_sensor_location.png b/res/drawable-xxhdpi/fingerprint_sensor_location.png Binary files differnew file mode 100644 index 0000000..b95816f --- /dev/null +++ b/res/drawable-xxhdpi/fingerprint_sensor_location.png diff --git a/res/drawable/fingerprint_animation.xml b/res/drawable/fingerprint_animation.xml deleted file mode 100644 index a2c1030..0000000 --- a/res/drawable/fingerprint_animation.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - 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. ---> - -<animation-list xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/fingerprint_animation" - android:oneshot="false" - android:duration="1000"> - <item android:drawable="@drawable/fingerprint_anim00" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim01" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim02" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim03" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim04" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim05" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim06" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim07" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim08" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim09" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim10" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim11" android:duration="77" /> - <item android:drawable="@drawable/fingerprint_anim12" android:duration="77" /> -</animation-list> diff --git a/res/drawable/fingerprint_progress_ring.xml b/res/drawable/fingerprint_progress_ring.xml index a2d9cba..04578cd 100644 --- a/res/drawable/fingerprint_progress_ring.xml +++ b/res/drawable/fingerprint_progress_ring.xml @@ -15,15 +15,24 @@ --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item> + <item android:id="@android:id/background"> <shape - android:innerRadius="96dip" + android:innerRadius="@dimen/fingerprint_ring_radius" android:shape="ring" - android:thickness="4dip"> + android:thickness="@dimen/fingerprint_ring_thickness" + android:useLevel="false"> + <solid android:color="@color/fingerprint_progress_ring_bg" /> + </shape> + </item> + <item android:id="@android:id/progress"> + <shape + android:innerRadius="@dimen/fingerprint_ring_radius" + android:shape="ring" + android:thickness="@dimen/fingerprint_ring_thickness"> <gradient - android:startColor="@color/fingerprint_progress_ring_color" - android:endColor="@color/fingerprint_progress_ring_color" - android:angle="180" + android:startColor="@color/fingerprint_progress_ring" + android:endColor="@color/fingerprint_progress_ring" + android:angle="0" /> </shape> </item> diff --git a/res/drawable/fingerprint_progress_ring_bg.xml b/res/drawable/fingerprint_progress_ring_bg.xml deleted file mode 100644 index 52d439b..0000000 --- a/res/drawable/fingerprint_progress_ring_bg.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:innerRadius="96dip" - android:shape="ring" - android:thickness="4dip" - android:color="@color/fingerprint_progress_ring_bg"> -</shape> diff --git a/res/layout-land/fingerprint_enroll.xml b/res/layout-land/fingerprint_enroll.xml index 8954d74..7bd41d1 100644 --- a/res/layout-land/fingerprint_enroll.xml +++ b/res/layout-land/fingerprint_enroll.xml @@ -62,62 +62,59 @@ <!-- Right area --> <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dip" + android:layout_width="0dip" + android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical"> - <LinearLayout + <RelativeLayout android:id="@+id/fingerprint_view_selector" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="0dip" - android:orientation="vertical" android:layout_weight="1" - android:layout_gravity="center"> + android:layout_gravity="center" + android:gravity="center"> - <FrameLayout + <!-- Only one of the following views will show for any given mode --> + <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center" - android:background="@drawable/fingerprint_progress_ring_bg"> + android:layout_centerInParent="true"> + + <ImageView + android:id="@+id/fingerprint_animator" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:src="@drawable/fingerprint_indicator" /> - <!-- One of the following views will show for any given mode --> <ProgressBar android:id="@+id/fingerprint_progress_bar" - style="?android:attr/progressBarStyleHorizontal" android:layout_width="200dip" android:layout_height="200dip" - android:max="100" + android:layout_centerInParent="true" + style="?android:attr/progressBarStyleHorizontal" + android:max="10000" android:progress="0" android:indeterminate="false" android:progressDrawable="@drawable/fingerprint_progress_ring" /> - <ImageView - android:id="@+id/fingerprint_sensor_location" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:src="@drawable/fingerprint_sensor_location" - android:visibility="gone"/> - - <ImageView - android:id="@+id/fingerprint_animator" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center" - android:src="@drawable/fingerprint_animation" - android:visibility="visible" /> + </RelativeLayout> - <ImageView - android:id="@+id/fingerprint_in_app_indicator" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:src="@drawable/fingerprint_in_app_indicator" - android:visibility="visible" /> - </FrameLayout> + <ImageView + android:id="@+id/fingerprint_sensor_location" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:src="@drawable/fingerprint_sensor_location" /> - </LinearLayout> + <ImageView + android:id="@+id/fingerprint_in_app_indicator" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:src="@drawable/fingerprint_in_app_indicator" /> + </RelativeLayout> <!-- Button area --> <LinearLayout diff --git a/res/layout/fingerprint_enroll.xml b/res/layout/fingerprint_enroll.xml index d7bf046..5a0b24b 100644 --- a/res/layout/fingerprint_enroll.xml +++ b/res/layout/fingerprint_enroll.xml @@ -25,7 +25,7 @@ <RelativeLayout android:layout_width="match_parent" android:layout_height="0dip" - android:layout_weight="0.3" + android:layout_weight="0.25" android:background="@color/fingerprint_title_area_bg"> <TextView @@ -44,7 +44,7 @@ <LinearLayout android:layout_width="match_parent" android:layout_height="0dip" - android:layout_weight="0.6" + android:layout_weight="0.75" android:orientation="vertical"> <TextView @@ -57,53 +57,55 @@ android:layout_marginBottom="36dip" style="@style/TextAppearance.FingerprintMessage"/> - <FrameLayout + <RelativeLayout android:id="@+id/fingerprint_view_selector" - android:layout_width="match_parent" + android:layout_width="wrap_content" android:layout_height="0dip" android:layout_weight="1" - android:layout_gravity="center"> + android:layout_gravity="center" + android:gravity="center"> - <FrameLayout + <!-- Only one of the following views will show for any given mode --> + <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center" - android:background="@drawable/fingerprint_progress_ring_bg"> + android:layout_centerInParent="true"> + + <ImageView + android:id="@+id/fingerprint_animator" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:src="@drawable/fingerprint_indicator" /> - <!-- One of the following views will show for any given mode --> <ProgressBar android:id="@+id/fingerprint_progress_bar" - style="?android:attr/progressBarStyleHorizontal" android:layout_width="200dip" android:layout_height="200dip" - android:max="100" + android:layout_centerInParent="true" + style="?android:attr/progressBarStyleHorizontal" + android:max="10000" android:progress="0" android:indeterminate="false" android:progressDrawable="@drawable/fingerprint_progress_ring" /> - <ImageView - android:id="@+id/fingerprint_sensor_location" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:src="@drawable/fingerprint_sensor_location" /> + </RelativeLayout> - <ImageView - android:id="@+id/fingerprint_animator" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center" - android:src="@drawable/fingerprint_animation" /> + <ImageView + android:id="@+id/fingerprint_sensor_location" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:src="@drawable/fingerprint_sensor_location" /> - <ImageView - android:id="@+id/fingerprint_in_app_indicator" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:src="@drawable/fingerprint_in_app_indicator" /> - </FrameLayout> + <ImageView + android:id="@+id/fingerprint_in_app_indicator" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:src="@drawable/fingerprint_in_app_indicator" /> - </FrameLayout> + </RelativeLayout> </LinearLayout> @@ -117,12 +119,15 @@ <Button android:id="@+id/fingerprint_enroll_button_add" style="@style/SecurityPreferenceButton" - android:text="@string/fingerprint_enroll_button_add" /> + android:text="@string/fingerprint_enroll_button_add" + android:layout_margin="10dip" /> <Button android:id="@+id/fingerprint_enroll_button_next" style="@style/SecurityPreferenceButton" - android:text="@string/fingerprint_enroll_button_next" /> + android:text="@string/fingerprint_enroll_button_next" + android:layout_margin="10dip" /> + </LinearLayout> </LinearLayout> diff --git a/res/layout/fingerprint_rename_dialog.xml b/res/layout/fingerprint_rename_dialog.xml new file mode 100644 index 0000000..38b6ff2 --- /dev/null +++ b/res/layout/fingerprint_rename_dialog.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_horizontal"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|start" + android:layout_margin="10dip" + android:text="@string/security_settings_fingerprint_enroll_dialog_name_label"/> + + <EditText + android:id="@+id/fingerprint_rename_field" + android:layout_width="160dip" + android:layout_height="wrap_content" /> + +</LinearLayout> diff --git a/res/values/colors.xml b/res/values/colors.xml index 21b5924..83449f9 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -63,7 +63,7 @@ <color name="fingerprint_title_area_bg">#ff009688</color> <color name="fingerprint_title_color">#ffffffff</color> <color name="fingerprint_message_color">#de000000</color> - <color name="fingerprint_progress_ring_color">#ff009688</color> + <color name="fingerprint_progress_ring">#ff009688</color> <color name="fingerprint_progress_ring_bg">#20000000</color> <color name="running_processes_system_ram">#ff384248</color> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index a494db9..5ed69c4 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -233,4 +233,8 @@ <!-- RedactionInterstitial --> <dimen name="redaction_vertical_margins">8dp</dimen> + <!-- Fingerprint --> + <dimen name="fingerprint_ring_radius">96dip</dimen> + <dimen name="fingerprint_ring_thickness">4dip</dimen> + </resources> diff --git a/res/values/strings.xml b/res/values/strings.xml index 01fa8da..d99570b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -759,7 +759,15 @@ <!-- Fingerprint enrollment and settings --><skip /> <!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] --> <string name="security_settings_fingerprint_preference_title">Fingerprint</string> - <!-- Message shown for menu item that launches fingerprint settings or enrollment --> + <!-- Fingerprint managment category title - configuration options for managing enrolled fingerprints [CHAR LIMIT=22] --> + <string name="fingerprint_manage_category_title">Manage fingerprints</string> + <!-- Fingerprint category title - configuration options for managing fingerprint enrollment [CHAR LIMIT=22] --> + <string name="fingerprint_usage_category_title">Use fingerprint for</string> + <!-- Preference to add another fingerprint --> + <string name="fingerprint_add_title">Add</string> + <!-- switch for allowing fingerprint to be used for keyguard --> + <string name="fingerprint_enable_keyguard_toggle_title">screen lock</string> + <!-- message shown for menu item that launches fingerprint settings or enrollment --> <plurals name="security_settings_fingerprint_preference_summary"> <item quantity="one"><xliff:g id="count">%1$d</xliff:g> fingerprint enrolled</item> <item quantity="other"><xliff:g id="count">%1$d</xliff:g> fingerprints enrolled</item> @@ -769,8 +777,19 @@ <!-- Introduction detail message shown in fingerprint enrollment dialog --> <string name="security_settings_fingerprint_enroll_onboard_message"> To use your fingerprint to unlock your screen or confirm purchases, we\'ll need to: - \n\u2713 Set up your background screen lock method - \n\u2713 Add your fingerprint</string> + \n\n\u2713 Set up your background screen lock method + \n\n\u2713 Add your fingerprint</string> + <!-- Introduction title shown in fingerprint enrollment dialog to locate the sensor [CHAR LIMIT=22] --> + <string name="security_settings_fingerprint_enroll_find_sensor_title">Find the sensor</string> + <!-- Introduction detail message shown in fingerprint enrollment dialog --> + <string name="security_settings_fingerprint_enroll_find_sensor_message"> + Locate the fingerprint sensor on the back of your phone.</string> + <!-- Label text shown in fingerprint dialog for renaming a fingerprint template [CHAR LIMIT=22] --> + <string name="security_settings_fingerprint_enroll_dialog_name_label">Name</string> + <!-- Button text shown in fingerprint dialog that allows the user to rename a fingerprint template [CHAR LIMIT=22] --> + <string name="security_settings_fingerprint_enroll_dialog_ok">OK</string> + <!-- Button text shown in fingerprint dialog that allows the user to delete the fingerprint template [CHAR LIMIT=22] --> + <string name="security_settings_fingerprint_enroll_dialog_delete">Delete</string> <!-- Title shown in fingerprint enrollment dialog to begin enrollment [CHAR LIMIT=22]--> <string name="security_settings_fingerprint_enroll_start_title">Let\'s start!</string> <!-- Message shown in fingerprint enrollment dialog to begin enrollment --> @@ -2675,7 +2694,7 @@ <!-- Lock Pattern settings --> <!-- Security & location settings screen, header --> - <string name="lock_settings_title">Screen security</string> + <string name="lock_settings_title">Device security</string> <!-- Security & location settings screen, setting option name --> <string name="lockpattern_change_lock_pattern_label">Change unlock pattern</string> <!-- Security & location settings screen, change unlock pattern screen instruction when the user chooses "Change unlock pattern". We first ask the user toe nter the current pattern, and this is the message seen --> diff --git a/res/xml/security_settings_fingerprint.xml b/res/xml/security_settings_fingerprint.xml new file mode 100644 index 0000000..7cc3a56 --- /dev/null +++ b/res/xml/security_settings_fingerprint.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" + android:title="@string/security_settings_fingerprint_preference_title"> + + <PreferenceCategory + android:key="fingerprint_manage_category" + android:title="@string/fingerprint_manage_category_title"> + </PreferenceCategory> + + <PreferenceCategory + android:key="fingerprint_usage_category" + android:title="@string/fingerprint_usage_category_title"> + + <SwitchPreference + android:key="fingerprint_enable_keyguard_toggle" + android:title="@string/fingerprint_enable_keyguard_toggle_title" + android:persistent="false" /> + + </PreferenceCategory> + +</PreferenceScreen> + diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java index bfb328d..216b1ca 100644 --- a/src/com/android/settings/ChooseLockGeneric.java +++ b/src/com/android/settings/ChooseLockGeneric.java @@ -35,6 +35,8 @@ import android.os.UserManager; import android.preference.Preference; import android.preference.PreferenceScreen; import android.security.KeyStore; +import android.service.fingerprint.FingerprintManager; +import android.service.fingerprint.FingerprintManagerReceiver; import android.util.EventLog; import android.util.Log; import android.util.MutableBoolean; @@ -102,11 +104,14 @@ public class ChooseLockGeneric extends SettingsActivity { private boolean mEncryptionRequestDisabled; private boolean mRequirePassword; private LockPatternUtils mLockPatternUtils; + private FingerprintManager mFingerprintManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mFingerprintManager = + (FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE); mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); mKeyStore = KeyStore.getInstance(); mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity()); @@ -391,13 +396,36 @@ public class ChooseLockGeneric extends SettingsActivity { } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { mChooseLockSettingsHelper.utils().clearLock(); mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled); + removeAllFingerprintTemplates(); getActivity().setResult(Activity.RESULT_OK); finish(); } else { + removeAllFingerprintTemplates(); finish(); } } + // TODO: This is only required because we used to enforce clients have a listener, + // which is no longer required in the new API. Remove when that happens. + FingerprintManagerReceiver mReceiver = new FingerprintManagerReceiver() { + public void onRemoved(int fingerprintId) { + Log.v(TAG, "onRemoved(id=" + fingerprintId + ")"); + } + }; + + private void removeAllFingerprintTemplates() { + mFingerprintManager.startListening(mReceiver); + if (mFingerprintManager != null) { + mFingerprintManager.remove(0 /* all fingerprint templates */); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + mFingerprintManager.stopListening(); + } + @Override protected int getHelpResource() { return R.string.help_url_choose_lockscreen; diff --git a/src/com/android/settings/FingerprintEnroll.java b/src/com/android/settings/FingerprintEnroll.java index 24f479e..f7ca36b 100644 --- a/src/com/android/settings/FingerprintEnroll.java +++ b/src/com/android/settings/FingerprintEnroll.java @@ -21,10 +21,12 @@ import android.animation.Animator.AnimatorListener; import android.animation.ObjectAnimator; import android.app.Activity; import android.app.Fragment; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.Drawable; import android.media.AudioAttributes; import android.os.Bundle; import android.os.PowerManager; @@ -80,11 +82,13 @@ public class FingerprintEnroll extends SettingsActivity { } public static class FingerprintEnrollFragment extends Fragment implements View.OnClickListener { + private static final int PROGRESS_BAR_MAX = 10000; private static final String TAG = "FingerprintEnroll"; private static final boolean DEBUG = true; private static final int CONFIRM_REQUEST = 101; private static final int CHOOSE_LOCK_GENERIC_REQUEST = 102; private static final long ENROLL_TIMEOUT = 300*1000; + private static final int FINISH_DELAY = 250; private PowerManager mPowerManager; private FingerprintManager mFingerprintManager; @@ -98,6 +102,15 @@ public class FingerprintEnroll extends SettingsActivity { private ProgressBar mProgressBar; private ImageView mFingerprintAnimator; private ObjectAnimator mProgressAnim; + + // Give the user a chance to see progress completed before jumping to the next stage. + Runnable mDelayedFinishRunnable = new Runnable() { + @Override + public void run() { + updateStage(Stage.EnrollingFinish); + } + }; + private final AnimatorListener mProgressAnimationListener = new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @@ -107,8 +120,8 @@ public class FingerprintEnroll extends SettingsActivity { @Override public void onAnimationEnd(Animator animation) { - if (mProgressBar.getProgress() >= 100) { - updateStage(Stage.EnrollingFinish); + if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { + mContentView.postDelayed(mDelayedFinishRunnable, FINISH_DELAY); } } @@ -133,12 +146,17 @@ public class FingerprintEnroll extends SettingsActivity { R.id.fingerprint_enroll_button_next }; - private static final int VIEWS_ENROLL_START[] = { + private static final int VIEWS_ENROLL_FIND_SENSOR[] = { R.id.fingerprint_sensor_location, - R.id.fingerprint_progress_bar + R.id.fingerprint_enroll_button_area, + R.id.fingerprint_enroll_button_next }; - private static final int VIEWS_ENROLL_PROGRESS[] = { + private static final int VIEWS_ENROLL_START[] = { + R.id.fingerprint_animator, + }; + + private static final int VIEWS_ENROLL_REPEAT[] = { R.id.fingerprint_animator, R.id.fingerprint_progress_bar }; @@ -149,17 +167,21 @@ public class FingerprintEnroll extends SettingsActivity { R.id.fingerprint_enroll_button_add, R.id.fingerprint_enroll_button_next }; + private static final boolean ALWAYS_SHOW_FIND_SCREEN = true; - enum Stage { - EnrollingOnboarding(R.string.security_settings_fingerprint_enroll_onboard_title, + private enum Stage { + EnrollingOnboard(R.string.security_settings_fingerprint_enroll_onboard_title, R.string.security_settings_fingerprint_enroll_onboard_message, VIEWS_ENROLL_ONBOARD), + EnrollingFindSensor(R.string.security_settings_fingerprint_enroll_find_sensor_title, + R.string.security_settings_fingerprint_enroll_find_sensor_message, + VIEWS_ENROLL_FIND_SENSOR), EnrollingStart(R.string.security_settings_fingerprint_enroll_start_title, R.string.security_settings_fingerprint_enroll_start_message, VIEWS_ENROLL_START), EnrollingRepeat(R.string.security_settings_fingerprint_enroll_repeat_title, R.string.security_settings_fingerprint_enroll_repeat_message, - VIEWS_ENROLL_PROGRESS), + VIEWS_ENROLL_REPEAT), EnrollingFinish(R.string.security_settings_fingerprint_enroll_finish_title, R.string.security_settings_fingerprint_enroll_finish_message, VIEWS_ENROLL_FINISH); @@ -196,22 +218,29 @@ public class FingerprintEnroll extends SettingsActivity { } private void startFingerprintAnimator() { - AnimationDrawable drawable = (AnimationDrawable) mFingerprintAnimator.getDrawable(); - drawable.start(); + final Drawable d = mFingerprintAnimator.getDrawable(); + if (d instanceof AnimationDrawable) { + ((AnimationDrawable) d).start(); + } } private void stopFingerprintAnimator() { - AnimationDrawable drawable = (AnimationDrawable) mFingerprintAnimator.getDrawable(); - drawable.stop(); - drawable.setLevel(0); + final Drawable d = mFingerprintAnimator.getDrawable(); + if (d instanceof AnimationDrawable) { + final AnimationDrawable drawable = (AnimationDrawable) d; + drawable.stop(); + drawable.setLevel(0); + } } private void onStageChanged(Stage stage) { // Update state switch (stage) { - case EnrollingOnboarding: + case EnrollingOnboard: // pass through + case EnrollingFindSensor: mEnrollmentSteps = -1; mEnrolling = false; + mFingerprintManager.stopListening(); break; case EnrollingStart: @@ -288,7 +317,7 @@ public class FingerprintEnroll extends SettingsActivity { } if (remaining >= 0) { int progress = Math.max(0, mEnrollmentSteps + 1 - remaining); - updateProgress(100*progress / (mEnrollmentSteps + 1)); + updateProgress(PROGRESS_BAR_MAX * progress / (mEnrollmentSteps + 1)); // Treat fingerprint like a touch event mPowerManager.userActivity(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER, @@ -371,7 +400,7 @@ public class FingerprintEnroll extends SettingsActivity { if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) { if (resultCode == RESULT_FINISHED) { // The lock pin/pattern/password was set. Start enrolling! - updateStage(Stage.EnrollingStart); + updateStage(Stage.EnrollingFindSensor); } } } @@ -401,7 +430,10 @@ public class FingerprintEnroll extends SettingsActivity { LockPatternUtils utils = new LockPatternUtils(activity); if (!utils.isSecure()) { // Device doesn't have any security. Set that up first. - updateStage(Stage.EnrollingOnboarding); + updateStage(Stage.EnrollingOnboard); + } else if (ALWAYS_SHOW_FIND_SCREEN + || mFingerprintManager.getEnrolledFingerprints().size() == 0) { + updateStage(Stage.EnrollingFindSensor); } else { updateStage(Stage.EnrollingStart); } @@ -415,8 +447,10 @@ public class FingerprintEnroll extends SettingsActivity { updateStage(Stage.EnrollingStart); break; case R.id.fingerprint_enroll_button_next: - if (mStage == Stage.EnrollingOnboarding) { + if (mStage == Stage.EnrollingOnboard) { launchChooseLock(); + } else if (mStage == Stage.EnrollingFindSensor) { + updateStage(Stage.EnrollingStart); } else if (mStage == Stage.EnrollingFinish) { getActivity().finish(); } else { @@ -429,6 +463,8 @@ public class FingerprintEnroll extends SettingsActivity { private void launchChooseLock() { Intent intent = new Intent(); intent.setClassName("com.android.settings", ChooseLockGeneric.class.getName()); + intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, + DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST); } } diff --git a/src/com/android/settings/FingerprintSettings.java b/src/com/android/settings/FingerprintSettings.java new file mode 100644 index 0000000..f91fcfa --- /dev/null +++ b/src/com/android/settings/FingerprintSettings.java @@ -0,0 +1,235 @@ +/* + * 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.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceGroup; +import android.preference.PreferenceScreen; +import android.service.fingerprint.FingerprintManager; +import android.service.fingerprint.FingerprintManagerReceiver; +import android.service.fingerprint.FingerprintManager.FingerprintItem; +import android.util.Log; +import android.widget.EditText; + +import com.android.settings.search.Indexable; + +import java.util.HashMap; +import java.util.List; + +/** + * Settings screen for fingerprints + */ +public class FingerprintSettings extends SettingsActivity { + + @Override + public Intent getIntent() { + Intent modIntent = new Intent(super.getIntent()); + modIntent.putExtra(EXTRA_SHOW_FRAGMENT, FingerprintSettingsFragment.class.getName()); + return modIntent; + } + + @Override + protected boolean isValidFragment(String fragmentName) { + if (FingerprintSettingsFragment.class.getName().equals(fragmentName)) return true; + return false; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + CharSequence msg = getText(R.string.security_settings_fingerprint_preference_title); + setTitle(msg); + } + + public static class FingerprintSettingsFragment extends SettingsPreferenceFragment + implements OnPreferenceChangeListener, Indexable { + private static final String TAG = "FingerprintSettings"; + private static final String KEY_FINGERPRINT_ITEM = "key_fingerprint_item"; + private static final String KEY_USAGE_CATEGORY = "fingerprint_usage_category"; + private static final String KEY_FINGERPRINT_ADD = "key_fingerprint_add"; + private static final String KEY_MANAGE_CATEGORY = "fingerprint_manage_category"; + private static final String KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE = + "fingerprint_enable_keyguard_toggle"; + + private static final int ADD_FINGERPRINT_REQUEST = 10; + + private static final boolean ENABLE_USAGE_CATEGORY = false; + + private FingerprintManager mFingerprintManager; + private HashMap<Preference, FingerprintItem> mFingerprintMap + = new HashMap<Preference, FingerprintManager.FingerprintItem>(); + private EditText mDialogTextField; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mFingerprintManager = (FingerprintManager) getActivity().getSystemService( + Context.FINGERPRINT_SERVICE); + mFingerprintManager.startListening(new FingerprintManagerReceiver() { + @Override + public void onRemoved(int fingerprintId) { + Log.v(TAG, "Fingerprint template " + fingerprintId + " removed"); + // TODO: this is a bit wasteful; just remove the fingerprint id item + createPreferenceHierarchy(); + } + @Override + public void onProcessed(int fingerprintId) { + Log.v(TAG, "Fingerprint " + fingerprintId + " detected"); + } + }); + } + + /** + * Important! + * + * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the + * logic or adding/removing preferences here. + */ + private PreferenceScreen createPreferenceHierarchy() { + PreferenceScreen root = getPreferenceScreen(); + if (root != null) { + root.removeAll(); + } + addPreferencesFromResource(R.xml.security_settings_fingerprint); + root = getPreferenceScreen(); + + // Fingerprint items + PreferenceGroup manageCategory = (PreferenceGroup) root.findPreference( + KEY_MANAGE_CATEGORY); + if (manageCategory != null) { + addFingerprintItemPreferences(manageCategory); + } + + // Fingerprint usage options + PreferenceGroup usageCategory = (PreferenceGroup) root.findPreference( + KEY_USAGE_CATEGORY); + if (usageCategory != null) { + Preference toggle = root.findPreference(KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE); + toggle.setOnPreferenceChangeListener(this); + if (!ENABLE_USAGE_CATEGORY) { + root.removePreference(usageCategory); + } else { + toggle.setOnPreferenceChangeListener(this); + } + } + + return root; + } + + private void addFingerprintItemPreferences(PreferenceGroup manageFingerprintCategory) { + manageFingerprintCategory.removeAll(); + List<FingerprintItem> items = mFingerprintManager.getEnrolledFingerprints(); + final int fingerprintCount = items.size(); + mFingerprintMap.clear(); + for (int i = 0; i < fingerprintCount; i++) { + Preference pref = new Preference(manageFingerprintCategory.getContext()); + pref.setKey(KEY_FINGERPRINT_ITEM); + FingerprintItem item = items.get(i); + pref.setTitle(item.name); + manageFingerprintCategory.addPreference(pref); + pref.setOnPreferenceChangeListener(this); + mFingerprintMap.put(pref, item); + } + Preference addPreference = new Preference(manageFingerprintCategory.getContext()); + addPreference.setKey(KEY_FINGERPRINT_ADD); + addPreference.setTitle(R.string.fingerprint_add_title); + manageFingerprintCategory.addPreference(addPreference); + addPreference.setOnPreferenceChangeListener(this); + } + + @Override + public void onResume() { + super.onResume(); + // Make sure we reload the preference hierarchy since fingerprints may be added, + // deleted or renamed. + createPreferenceHierarchy(); + } + + @Override + public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference pref) { + final String key = pref.getKey(); + if (KEY_FINGERPRINT_ADD.equals(key)) { + Intent intent = new Intent(); + intent.setClassName("com.android.settings", FingerprintEnroll.class.getName()); + startActivityForResult(intent, ADD_FINGERPRINT_REQUEST); + } else if (KEY_FINGERPRINT_ITEM.equals(key)) { + final FingerprintItem item = mFingerprintMap.get(pref); + showRenameDeleteDialog(item.name, pref, item.id); + return super.onPreferenceTreeClick(preferenceScreen, pref); + } + return true; + } + + private void showRenameDeleteDialog(final CharSequence name, Preference pref, + final int fpId) { + final Activity activity = getActivity(); + AlertDialog dialog = new AlertDialog.Builder(activity) + .setView(R.layout.fingerprint_rename_dialog) + .setPositiveButton(R.string.security_settings_fingerprint_enroll_dialog_ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String newName = mDialogTextField.getText().toString(); + if (!newName.equals(name)) { + Log.v(TAG, "Would rename " + name + " to " + newName); + mFingerprintManager.rename(fpId, newName); + } + dialog.dismiss(); + } + }) + .setNegativeButton(R.string.security_settings_fingerprint_enroll_dialog_delete, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Log.v(TAG, "Removing fpId " + fpId); + mFingerprintManager.remove(fpId); + dialog.dismiss(); + } + }) + .create(); + dialog.show(); + mDialogTextField = (EditText) dialog.findViewById(R.id.fingerprint_rename_field); + mDialogTextField.setText(name); + mDialogTextField.selectAll(); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object value) { + boolean result = true; + final String key = preference.getKey(); + if (KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE.equals(key)) { + // TODO + } else { + Log.v(TAG, "Unknown key:" + key); + } + return result; + } + + @Override + protected int getHelpResource() { + return R.string.help_url_security; + } + } +} diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index 95826e4..053e7f0 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -67,8 +67,9 @@ import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; */ public class SecuritySettings extends SettingsPreferenceFragment implements OnPreferenceChangeListener, DialogInterface.OnClickListener, Indexable { + + private static final String TAG = "SecuritySettings"; private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent"; - static final String TAG = "SecuritySettings"; private static final Intent TRUST_AGENT_INTENT = new Intent(TrustAgentService.SERVICE_INTERFACE); @@ -81,6 +82,7 @@ public class SecuritySettings extends SettingsPreferenceFragment private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings"; private static final String KEY_ADVANCED_SECURITY = "advanced_security"; private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents"; + private static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings"; private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; private static final int CHANGE_TRUST_AGENT_SETTINGS = 126; @@ -337,21 +339,22 @@ public class SecuritySettings extends SettingsPreferenceFragment return; } Preference fingerprintPreference = new Preference(securityCategory.getContext()); - fingerprintPreference.setKey(KEY_TRUST_AGENT); + fingerprintPreference.setKey(KEY_FINGERPRINT_SETTINGS); fingerprintPreference.setTitle(R.string.security_settings_fingerprint_preference_title); Intent intent = new Intent(); List<FingerprintItem> items = fpm.getEnrolledFingerprints(); int fingerprintCount = items.size(); + final String clazz; if (fingerprintCount > 0) { fingerprintPreference.setSummary(getResources().getQuantityString( R.plurals.security_settings_fingerprint_preference_summary, fingerprintCount, fingerprintCount)); - // TODO: Launch fingerprintSettings instead... - intent.setClassName("com.android.settings", FingerprintEnroll.class.getName()); + clazz = FingerprintSettings.class.getName(); } else { - // No fingerprints registered, launch directly into fingerprint enrollment wizard - intent.setClassName("com.android.settings", FingerprintEnroll.class.getName()); + // No fingerprints registered, launch directly into enrollment wizard + clazz = FingerprintEnroll.class.getName(); } + intent.setClassName("com.android.settings", clazz); fingerprintPreference.setIntent(intent); securityCategory.addPreference(fingerprintPreference); } |