OSDN Git Service

Update FaceSettings to match mocks
authorKevin Chyn <kchyn@google.com>
Tue, 25 Sep 2018 19:08:21 +0000 (12:08 -0700)
committerKevin Chyn <kchyn@google.com>
Wed, 26 Sep 2018 18:50:02 +0000 (11:50 -0700)
Settings page should not show if device credential is not confirmed

Bug: 111548037
Fixes: 116531896

Test: adb shell settings get secure face_unlock_app_enabled
Test: make -j56 RunSettingsRoboTests

Change-Id: I651ee88e9ee4017ee3dc52fa8a5d05cb8f092e1d

res/values/strings.xml
res/xml/security_settings_face.xml
src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
src/com/android/settings/biometrics/face/FaceSettings.java
src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java [new file with mode: 0644]
src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java [new file with mode: 0644]
src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java [moved from src/com/android/settings/biometrics/face/FaceSettingsUnlockPreferenceController.java with 89% similarity]
src/com/android/settings/biometrics/face/FaceSettingsVideoPreferenceController.java [deleted file]
src/com/android/settings/password/SetNewPasswordController.java
tests/robotests/src/com/android/settings/password/SetNewPasswordControllerTest.java

index 04852e0..5f5d58e 100644 (file)
     <string name="security_settings_face_settings_use_face_category">Use your face to</string>
     <!-- Text shown on a toggle which allows or disallows the device to use face for unlocking the device. [CHAR LIMIT=20] -->
     <string name="security_settings_face_settings_use_face_unlock_phone">Unlock your device</string>
+    <!-- Text shown on a toggle which allows or disallows the device to use face authentication for apps. This will be presented to the user together with the context of security_settings_face_settings_use_face_category. [CHAR LIMIT=30] -->
+    <string name="security_settings_face_settings_use_face_for_apps">App sign-in \u0026 payments</string>
+    <!-- Text shown on a toggle which disables/enables face authentication, depending if the user's eyes are open. [CHAR LIMIT=30] -->
+    <string name="security_settings_face_settings_require_attention">Eyes open to unlock</string>
+    <!-- Text shown on the details of a toggle which disables/enables face authentication, depending if the user's eyes are open. [CHAR LIMIT=70] -->
+    <string name="security_settings_face_settings_require_attention_details">When using face authentication, your eyes must be open</string>
     <!-- Button text in face settings which removes the user's faces from the device [CHAR LIMIT=20] -->
     <string name="security_settings_face_settings_remove_face_data">Remove face data</string>
     <!-- Text shown in face settings allowing the user to update/improve the enrolled face. This brings the user back to the enrollment flow. [CHAR LIMIT=30] -->
     <string name="keywords_payment_settings">pay, tap, payments</string>
     <string name="keywords_backup">backup, back up</string>
     <string name="keywords_assist_gesture_launch">gesture</string>
-    <string name="keywords_face_unlock">face, unlock</string>
+    <string name="keywords_face_unlock">face, unlock, auth, sign in</string>
     <string name="keywords_imei_info">imei, meid, min, prl version, imei sv</string>
     <string name="keywords_sim_status">network, mobile network state, service state, signal strength, mobile network type, roaming, iccid</string>
     <string name="keywords_model_and_hardware">serial number, hardware version</string>
index 3dfcfd7..2bdfdc8 100644 (file)
 
     <com.android.settings.widget.VideoPreference
         android:key="security_settings_face_video"
+        android:title="@string/summary_placeholder"
         app:animation="@raw/gesture_fingerprint_swipe"
-        app:preview="@drawable/face_enroll_introduction" />
+        app:preview="@drawable/face_enroll_introduction"
+        app:controller="com.android.settings.widget.VideoPreferenceController"/>
 
     <PreferenceCategory
         android:key="security_settings_face_unlock_category"
         android:title="@string/security_settings_face_settings_use_face_category">
         <SwitchPreference
-            android:key="security_settings_face_unlock"
+            android:key="security_settings_face_keyguard"
             android:title="@string/security_settings_face_settings_use_face_unlock_phone"
             app:keywords="@string/keywords_face_unlock"
-            app:controller="com.android.settings.biometrics.face.FaceSettingsUnlockPreferenceController"/>
+            app:controller="com.android.settings.biometrics.face.FaceSettingsKeyguardPreferenceController"/>
+        <SwitchPreference
+            android:key="security_settings_face_app"
+            android:title="@string/security_settings_face_settings_use_face_for_apps"
+            app:keywords="@string/keywords_face_unlock"
+            app:controller="com.android.settings.biometrics.face.FaceSettingsAppPreferenceController"/>
     </PreferenceCategory>
 
     <PreferenceCategory
         android:key="security_settings_face_manage_category">
+        <SwitchPreference
+            android:key="security_settings_face_require_attention"
+            android:title="@string/security_settings_face_settings_require_attention"
+            app:keywords="@string/keywords_face_unlock"
+            app:controller="com.android.settings.biometrics.face.FaceSettingsAttentionPreferenceController"/>
+
         <Preference
             android:key="security_settings_face_improve"
             android:title="@string/security_settings_face_settings_improve_face">
index c718dde..748f874 100644 (file)
@@ -104,7 +104,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
         if (mFaceManager == null) {
             return 0;
         }
-        return mFaceManager.preEnroll();
+        return mFaceManager.generateChallenge();
     }
 
     @Override
index 4944c7f..d7dc9f8 100644 (file)
 
 package com.android.settings.biometrics.face;
 
+import static android.app.Activity.RESULT_OK;
+
 import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST;
+import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
 
 import android.content.Context;
+import android.content.Intent;
 import android.hardware.face.FaceManager;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.provider.SearchIndexableResource;
 import android.util.Log;
 
@@ -30,6 +35,7 @@ import com.android.settings.Utils;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.VideoPreferenceController;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.search.SearchIndexable;
@@ -47,7 +53,11 @@ public class FaceSettings extends DashboardFragment {
     private static final String TAG = "FaceSettings";
     private static final String KEY_LAUNCHED_CONFIRM = "key_launched_confirm";
 
+    private FaceManager mFaceManager;
+    private int mUserId;
     private boolean mLaunchedConfirm;
+    private byte[] mToken;
+    private FaceSettingsAttentionPreferenceController mAttentionController;
 
     public static boolean isAvailable(Context context) {
         FaceManager manager = Utils.getFaceManagerOrNull(context);
@@ -79,14 +89,20 @@ public class FaceSettings extends DashboardFragment {
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mFaceManager = getPrefContext().getSystemService(FaceManager.class);
+        mUserId = getActivity().getIntent().getIntExtra(
+                Intent.EXTRA_USER_ID, UserHandle.myUserId());
+
         if (savedInstanceState != null) {
             mLaunchedConfirm = savedInstanceState.getBoolean(KEY_LAUNCHED_CONFIRM, false);
         }
 
         if (!mLaunchedConfirm) {
+            final long challenge = mFaceManager.generateChallenge();
             ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
             if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
-                    getString(R.string.security_settings_face_preference_title))) {
+                    getString(R.string.security_settings_face_preference_title),
+                    null, null, challenge, mUserId)) {
                 Log.e(TAG, "Password not set");
                 finish();
             }
@@ -94,16 +110,59 @@ public class FaceSettings extends DashboardFragment {
     }
 
     @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == CONFIRM_REQUEST) {
+            if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
+                // The pin/pattern/password was set.
+                if (data != null) {
+                    mToken = data.getByteArrayExtra(
+                            ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
+                    if (mToken != null) {
+                        mAttentionController.setToken(mToken);
+                    }
+                }
+            }
+        }
+
+        if (mToken == null) {
+            // Didn't get an authentication, finishing
+            getActivity().finish();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (getActivity().isFinishing()) {
+            final int result = mFaceManager.revokeChallenge();
+            if (result < 0) {
+                Log.w(TAG, "revokeChallenge failed, result: " + result);
+            }
+        }
+    }
+
+    @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
-        return buildPreferenceControllers(context, getSettingsLifecycle());
+        final List<AbstractPreferenceController> controllers =
+                buildPreferenceControllers(context, getSettingsLifecycle());
+        for (AbstractPreferenceController controller : controllers) {
+            if (controller instanceof FaceSettingsAttentionPreferenceController) {
+                mAttentionController = (FaceSettingsAttentionPreferenceController) controller;
+                break;
+            }
+        }
+
+        return controllers;
     }
 
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(new FaceSettingsVideoPreferenceController(context));
         controllers.add(new FaceSettingsImprovePreferenceController(context));
-        controllers.add(new FaceSettingsUnlockPreferenceController(context));
+        controllers.add(new FaceSettingsKeyguardPreferenceController(context));
+        controllers.add(new FaceSettingsAppPreferenceController(context));
+        controllers.add(new FaceSettingsAttentionPreferenceController(context));
         controllers.add(new FaceSettingsRemoveButtonPreferenceController(context));
         controllers.add(new FaceSettingsFooterPreferenceController(context));
         return controllers;
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
new file mode 100644 (file)
index 0000000..038dbd8
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 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.biometrics.face;
+
+import static android.provider.Settings.Secure.FACE_UNLOCK_APP_ENABLED;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+
+/**
+ * Preference controller for Face settings page controlling the ability to use
+ * Face authentication in apps (through BiometricPrompt).
+ */
+public class FaceSettingsAppPreferenceController extends TogglePreferenceController {
+
+    private static final String KEY = "security_settings_face_app";
+
+    private static final int ON = 1;
+    private static final int OFF = 0;
+    private static final int DEFAULT = ON;  // face unlock is enabled for BiometricPrompt by default
+
+    public FaceSettingsAppPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    public FaceSettingsAppPreferenceController(Context context) {
+        this(context, KEY);
+    }
+
+    @Override
+    public boolean isChecked() {
+        if (!FaceSettings.isAvailable(mContext)) {
+            return false;
+        }
+        return Settings.Secure.getInt(
+                mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED, DEFAULT) == ON;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return Settings.Secure.putInt(mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED,
+                isChecked ? ON : OFF);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
new file mode 100644 (file)
index 0000000..e26f881
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 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.biometrics.face;
+
+import android.content.Context;
+import android.hardware.face.FaceManager;
+import android.util.Log;
+
+import com.android.settings.core.TogglePreferenceController;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+/**
+ * Preference controller that manages the ability to use face authentication with/without
+ * user attention. See {@link FaceManager#setRequireAttention(boolean, byte[])}.
+ */
+public class FaceSettingsAttentionPreferenceController extends TogglePreferenceController {
+
+    public static final String KEY = "security_settings_face_require_attention";
+
+    private byte[] mToken;
+    private FaceManager mFaceManager;
+    private SwitchPreference mPreference;
+
+    public FaceSettingsAttentionPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mFaceManager = context.getSystemService(FaceManager.class);
+    }
+
+    public FaceSettingsAttentionPreferenceController(Context context) {
+        this(context, KEY);
+    }
+
+    public void setToken(byte[] token) {
+        mToken = token;
+        mPreference.setChecked(mFaceManager.getRequireAttention(mToken));
+    }
+
+    /**
+     * Displays preference in this controller.
+     */
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = (SwitchPreference) screen.findPreference(KEY);
+    }
+
+    @Override
+    public boolean isChecked() {
+        if (!FaceSettings.isAvailable(mContext)) {
+            return true;
+        } else if (mToken == null) {
+            // The token will be null when the controller is first created, since CC has not been
+            // completed by the user. Once it's completed, FaceSettings will use setToken which
+            // will retrieve the correct value from FaceService
+            return true;
+        }
+        return mFaceManager.getRequireAttention(mToken);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        mFaceManager.setRequireAttention(isChecked, mToken);
+        return true;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
@@ -31,19 +31,19 @@ import com.android.settings.core.TogglePreferenceController;
  * Preference controller for Face settings page controlling the ability to unlock the phone
  * with face.
  */
-public class FaceSettingsUnlockPreferenceController extends TogglePreferenceController {
+public class FaceSettingsKeyguardPreferenceController extends TogglePreferenceController {
 
-    private static final String KEY = "security_settings_face_unlock";
+    private static final String KEY = "security_settings_face_keyguard";
 
     private static final int ON = 1;
     private static final int OFF = 0;
     private static final int DEFAULT = ON;  // face unlock is enabled on keyguard by default
 
-    public FaceSettingsUnlockPreferenceController(Context context, String preferenceKey) {
+    public FaceSettingsKeyguardPreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
     }
 
-    public FaceSettingsUnlockPreferenceController(Context context) {
+    public FaceSettingsKeyguardPreferenceController(Context context) {
         this(context, KEY);
     }
 
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsVideoPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsVideoPreferenceController.java
deleted file mode 100644 (file)
index 6fbb9c4..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2018 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.biometrics.face;
-
-import android.content.Context;
-
-import com.android.settings.core.BasePreferenceController;
-
-public class FaceSettingsVideoPreferenceController extends BasePreferenceController {
-
-    private static final String PREF_KEY_VIDEO = "security_settings_face_video";
-
-    public FaceSettingsVideoPreferenceController(Context context,
-            String preferenceKey) {
-        super(context, preferenceKey);
-    }
-
-    public FaceSettingsVideoPreferenceController(Context context) {
-        this(context, PREF_KEY_VIDEO);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
-    }
-}
index d5641cd..bf55271 100644 (file)
@@ -148,7 +148,7 @@ final class SetNewPasswordController {
 
     private Bundle getFaceChooseLockExtras() {
         Bundle chooseLockExtras = new Bundle();
-        long challenge = mFaceManager.preEnroll();
+        long challenge = mFaceManager.generateChallenge();
         chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
                 PASSWORD_QUALITY_SOMETHING);
         chooseLockExtras.putBoolean(
index af77ad8..67f7b0a 100644 (file)
@@ -84,7 +84,7 @@ public final class SetNewPasswordControllerTest {
         when(mFingerprintManager.preEnroll()).thenReturn(FINGERPRINT_CHALLENGE);
         when(mPackageManager.hasSystemFeature(eq(FEATURE_FINGERPRINT))).thenReturn(true);
 
-        when(mFaceManager.preEnroll()).thenReturn(FACE_CHALLENGE);
+        when(mFaceManager.generateChallenge()).thenReturn(FACE_CHALLENGE);
         when(mPackageManager.hasSystemFeature(eq(FEATURE_FACE))).thenReturn(true);
     }