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
This commit is contained in:
Jim Miller
2015-03-04 18:07:32 -08:00
parent 5455bb540a
commit 9218687e4b
32 changed files with 514 additions and 161 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"/>
</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"
android:visibility="visible" />
<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"
android:visibility="visible" />
</FrameLayout>
</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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 -->

View File

@@ -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>

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}