BUG 5457035 : Anti-spoofing : DO NOT MERGE

Squashed commit of the following:

commit 060b9daf5fe3c45573a13a149bf98f4fa1e6a46f
Author: Danielle Millett <dmillett@google.com>
Date:   Wed May 30 15:50:03 2012 -0400

    Added head turn option for Face Unlock.

    In security settings there is an option for head turn and it shows the current
    status (on/off).  Clicking on this goes to another screen that describes the
    feature and allows the user to it on/off.
    Since the head turn option goes to a different screen instead of using a check box,
    this change also rips out the rest of the code for the old liveliness checkbox.

    Change-Id: I197af51084f3e751081fa159dadd6c2c80840d1e

Change-Id: I67c8acd49316b49771a0bb97b4a5fbd5a1c13262
diff --git a/res/layout/biometric_weak_liveliness.xml b/res/layout/biometric_weak_liveliness.xml
new file mode 100644
index 0000000..916bd9a
--- /dev/null
+++ b/res/layout/biometric_weak_liveliness.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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:paddingLeft="6dip"
+    android:paddingRight="6dip"
+    android:layout_width="match_parent" android:layout_height="wrap_content"
+    android:scrollbars="vertical" >
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:fillViewport="true">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <TextView android:id="@+id/biometric_weak_liveliness_explained"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dip"
+                android:gravity="top"
+                android:text="@string/biometric_weak_liveliness_explained"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+            />
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 13b4e56..10a18db 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -644,6 +644,16 @@
 
     <!-- Security settings screen when using face unlock, setting option name to start an activity that allows the user to improve accuracy by adding additional enrollment faces -->
     <string name="biometric_weak_improve_matching_title">Improve face matching</string>
+    <!-- On the security settings screen when using face unlock.  This goes to a screen that explains liveliness detection and allows for it to be turned on/off -->
+    <string name="biometric_weak_liveliness_title">Require head turn</string>
+    <!-- Used to describe the on state of the face unlock liveliness feature -->
+    <string name="biometric_weak_liveliness_on_summary">On</string>
+    <!-- Used to describe the off state of the face unlock liveliness feature -->
+    <string name="biometric_weak_liveliness_off_summary">Off</string>
+    <!-- Explanation of the Face Unlock liveliness feature. It's displayed on a screen with an on/off toggle switch. -->
+    <string name="biometric_weak_liveliness_explained" product="tablet">When this feature is turned on, other people can\'t use a photo of you to fool Face Unlock.  While unlocking your tablet, you\'ll be asked to turn your head.  You can turn it slightly to the left or right.</string>
+    <!-- Explanation of the Face Unlock liveliness feature. It's displayed on a screen with an on/off toggle switch. -->
+    <string name="biometric_weak_liveliness_explained" product="default">When this feature is turned on, other people can\'t use a photo of you to fool Face Unlock.  While unlocking your phone, you\'ll be asked to turn your head.  You can turn it slightly to the left or right.</string>
 
     <!-- Security settings screen, setting option name to change screen timeout -->
     <string name="lock_after_timeout">Automatically lock</string>
diff --git a/res/xml/security_settings_biometric_weak.xml b/res/xml/security_settings_biometric_weak.xml
index 080fbc9..66cca28 100644
--- a/res/xml/security_settings_biometric_weak.xml
+++ b/res/xml/security_settings_biometric_weak.xml
@@ -30,6 +30,11 @@
             android:key="biometric_weak_improve_matching"
             android:title="@string/biometric_weak_improve_matching_title"/>
 
+        <PreferenceScreen
+           android:key="biometric_weak_liveliness"
+           android:fragment="com.android.settings.BiometricWeakLiveliness"
+           android:title="@string/biometric_weak_liveliness_title"/>
+
         <CheckBoxPreference
             android:key="visiblepattern"
             android:title="@string/lockpattern_settings_enable_visible_pattern_title"/>
diff --git a/src/com/android/settings/BiometricWeakLiveliness.java b/src/com/android/settings/BiometricWeakLiveliness.java
new file mode 100644
index 0000000..6bba77f
--- /dev/null
+++ b/src/com/android/settings/BiometricWeakLiveliness.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2012 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.ActionBar;
+import android.app.Activity;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.os.Handler;
+import android.content.Intent;
+import android.preference.PreferenceActivity;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+import com.android.settings.R;
+
+import com.android.internal.widget.LockPatternUtils;
+
+public class BiometricWeakLiveliness extends Fragment
+        implements CompoundButton.OnCheckedChangeListener {
+    private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF = 125;
+
+    private View mView;
+    private ChooseLockSettingsHelper mChooseLockSettingsHelper;
+    private LockPatternUtils mLockPatternUtils;
+    private Switch mActionBarSwitch;
+    private boolean mSuppressCheckChanged;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Activity activity = getActivity();
+
+        mActionBarSwitch = new Switch(activity);
+        mSuppressCheckChanged = false;
+
+        if (activity instanceof PreferenceActivity) {
+            PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
+            if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) {
+                final int padding = activity.getResources().getDimensionPixelSize(
+                        R.dimen.action_bar_switch_padding);
+                mActionBarSwitch.setPadding(0, 0, padding, 0);
+                activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+                        ActionBar.DISPLAY_SHOW_CUSTOM);
+                activity.getActionBar().setCustomView(mActionBarSwitch, new ActionBar.LayoutParams(
+                        ActionBar.LayoutParams.WRAP_CONTENT,
+                        ActionBar.LayoutParams.WRAP_CONTENT,
+                        Gravity.CENTER_VERTICAL | Gravity.RIGHT));
+                activity.getActionBar().setTitle(R.string.biometric_weak_liveliness_title);
+            }
+        }
+
+        mActionBarSwitch.setOnCheckedChangeListener(this);
+
+        mLockPatternUtils = new LockPatternUtils(getActivity());
+        mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
+        mActionBarSwitch.setChecked(mLockPatternUtils.isBiometricWeakLivelinessEnabled());
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        mView = inflater.inflate(R.layout.biometric_weak_liveliness, container, false);
+        initView(mView);
+        return mView;
+    }
+
+    private void initView(View view) {
+        mActionBarSwitch.setOnCheckedChangeListener(this);
+        mActionBarSwitch.setChecked(mLockPatternUtils.isBiometricWeakLivelinessEnabled());
+    }
+
+    @Override
+    public void onCheckedChanged(CompoundButton buttonView, boolean desiredState) {
+        if (mSuppressCheckChanged) {
+            return;
+        }
+        mActionBarSwitch.setEnabled(false);
+        if (desiredState) {
+            mLockPatternUtils.setBiometricWeakLivelinessEnabled(true);
+            mActionBarSwitch.setChecked(true);
+        } else {
+            // In this case the user has just turned it off, but this action requires them
+            // to confirm their password.  We need to turn the switch back on until
+            // they've confirmed their password
+            mActionBarSwitch.setChecked(true);
+            mActionBarSwitch.requestLayout();
+            ChooseLockSettingsHelper helper =
+                    new ChooseLockSettingsHelper(this.getActivity(), this);
+            if (!helper.launchConfirmationActivity(
+                            CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF, null, null)) {
+                // If this returns false, it means no password confirmation is required, so
+                // go ahead and turn it off here.
+                // Note: currently a backup is required for biometric_weak so this code path
+                // can't be reached, but is here in case things change in the future
+                mLockPatternUtils.setBiometricWeakLivelinessEnabled(false);
+                mActionBarSwitch.setChecked(false);
+                mActionBarSwitch.requestLayout();
+            }
+        }
+        mActionBarSwitch.setEnabled(true);
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF &&
+                resultCode == Activity.RESULT_OK) {
+            final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
+            lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
+            mSuppressCheckChanged = true;
+            mActionBarSwitch.setChecked(false);
+            mSuppressCheckChanged = false;
+            return;
+        }
+    }
+
+}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 8196d0b..6b67730 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -62,7 +62,6 @@
     private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
     private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
     private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST = 124;
-    private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF = 125;
 
     // Misc Settings
     private static final String KEY_SIM_LOCK = "sim_lock";
@@ -77,7 +76,7 @@
     private LockPatternUtils mLockPatternUtils;
     private ListPreference mLockAfter;
 
-    private CheckBoxPreference mBiometricWeakLiveliness;
+    private PreferenceScreen mBiometricWeakLiveliness;
     private CheckBoxPreference mVisiblePattern;
     private CheckBoxPreference mTactileFeedback;
 
@@ -163,7 +162,7 @@
 
         // biometric weak liveliness
         mBiometricWeakLiveliness =
-                (CheckBoxPreference) root.findPreference(KEY_BIOMETRIC_WEAK_LIVELINESS);
+                (PreferenceScreen) root.findPreference(KEY_BIOMETRIC_WEAK_LIVELINESS);
 
         // visible pattern
         mVisiblePattern = (CheckBoxPreference) root.findPreference(KEY_VISIBLE_PATTERN);
@@ -339,8 +338,9 @@
 
         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
         if (mBiometricWeakLiveliness != null) {
-            mBiometricWeakLiveliness.setChecked(
-                    lockPatternUtils.isBiometricWeakLivelinessEnabled());
+            mBiometricWeakLiveliness.setSummary(lockPatternUtils.isBiometricWeakLivelinessEnabled()?
+                    R.string.biometric_weak_liveliness_on_summary:
+                    R.string.biometric_weak_liveliness_off_summary);
         }
         if (mVisiblePattern != null) {
             mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled());
@@ -382,26 +382,6 @@
                 // can't be reached, but is here in case things change in the future
                 startBiometricWeakImprove();
             }
-        } else if (KEY_BIOMETRIC_WEAK_LIVELINESS.equals(key)) {
-            if (isToggled(preference)) {
-                lockPatternUtils.setBiometricWeakLivelinessEnabled(true);
-            } else {
-                // In this case the user has just unchecked the checkbox, but this action requires
-                // them to confirm their password.  We need to re-check the checkbox until
-                // they've confirmed their password
-                mBiometricWeakLiveliness.setChecked(true);
-                ChooseLockSettingsHelper helper =
-                        new ChooseLockSettingsHelper(this.getActivity(), this);
-                if (!helper.launchConfirmationActivity(
-                        CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF, null, null)) {
-                    // If this returns false, it means no password confirmation is required, so
-                    // go ahead and uncheck it here.
-                    // Note: currently a backup is required for biometric_weak so this code path
-                    // can't be reached, but is here in case things change in the future
-                    lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
-                    mBiometricWeakLiveliness.setChecked(false);
-                }
-            }
         } else if (KEY_LOCK_ENABLED.equals(key)) {
             lockPatternUtils.setLockPatternEnabled(isToggled(preference));
         } else if (KEY_VISIBLE_PATTERN.equals(key)) {
@@ -442,12 +422,6 @@
                 resultCode == Activity.RESULT_OK) {
             startBiometricWeakImprove();
             return;
-        } else if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF &&
-                resultCode == Activity.RESULT_OK) {
-            final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
-            lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
-            mBiometricWeakLiveliness.setChecked(false);
-            return;
         }
         createPreferenceHierarchy();
     }