• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.settings.biometrics.face;
18 
19 import android.app.settings.SettingsEnums;
20 import android.content.ComponentName;
21 import android.content.Intent;
22 import android.hardware.face.FaceManager;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import android.os.UserHandle;
26 import android.text.TextUtils;
27 import android.view.View;
28 import android.view.accessibility.AccessibilityManager;
29 import android.widget.Button;
30 import android.widget.CompoundButton;
31 import android.widget.TextView;
32 
33 import com.android.settings.R;
34 import com.android.settings.Utils;
35 import com.android.settings.biometrics.BiometricEnrollBase;
36 import com.android.settings.password.ChooseLockSettingsHelper;
37 
38 import com.google.android.setupcompat.template.FooterBarMixin;
39 import com.google.android.setupcompat.template.FooterButton;
40 import com.google.android.setupcompat.util.WizardManagerHelper;
41 import com.google.android.setupdesign.view.IllustrationVideoView;
42 
43 public class FaceEnrollEducation extends BiometricEnrollBase {
44 
45     private static final String TAG = "FaceEducation";
46     private static final int ON = 1;
47     private static final int OFF = 0;
48 
49     private FaceManager mFaceManager;
50     private FaceEnrollAccessibilityToggle mSwitchDiversity;
51 
52     private IllustrationVideoView mIllustrationNormal;
53     private View mIllustrationAccessibility;
54     private Handler mHandler;
55     private Intent mResultIntent;
56     private TextView mDescriptionText;
57     private boolean mNextClicked;
58     private boolean mAccessibilityEnabled;
59 
60     private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
61             new CompoundButton.OnCheckedChangeListener() {
62                 @Override
63                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
64                     int titleRes = isChecked ?
65                             R.string.security_settings_face_enroll_education_title_accessibility
66                             : R.string.security_settings_face_enroll_education_title;
67                     getLayout().setHeaderText(titleRes);
68                     setTitle(titleRes);
69 
70                     if (isChecked) {
71                         mIllustrationNormal.stop();
72                         mIllustrationNormal.setVisibility(View.INVISIBLE);
73                         mIllustrationAccessibility.setVisibility(View.VISIBLE);
74                         mDescriptionText.setVisibility(View.INVISIBLE);
75                     } else {
76                         mIllustrationNormal.setVisibility(View.VISIBLE);
77                         mIllustrationNormal.start();
78                         mIllustrationAccessibility.setVisibility(View.INVISIBLE);
79                         mDescriptionText.setVisibility(View.VISIBLE);
80                     }
81                 }
82             };
83 
84     @Override
onCreate(Bundle savedInstanceState)85     protected void onCreate(Bundle savedInstanceState) {
86         super.onCreate(savedInstanceState);
87         setContentView(R.layout.face_enroll_education);
88         getLayout().setHeaderText(R.string.security_settings_face_enroll_education_title);
89         setTitle(R.string.security_settings_face_enroll_education_title);
90         mHandler = new Handler();
91 
92         mFaceManager = Utils.getFaceManagerOrNull(this);
93 
94         mIllustrationNormal = findViewById(R.id.illustration_normal);
95         mIllustrationAccessibility = findViewById(R.id.illustration_accessibility);
96         mDescriptionText = findViewById(R.id.sud_layout_description);
97 
98         mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
99 
100         if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
101             mFooterBarMixin.setSecondaryButton(
102                     new FooterButton.Builder(this)
103                             .setText(R.string.skip_label)
104                             .setListener(this::onSkipButtonClick)
105                             .setButtonType(FooterButton.ButtonType.SKIP)
106                             .setTheme(R.style.SudGlifButton_Secondary)
107                             .build()
108             );
109         } else {
110             mFooterBarMixin.setSecondaryButton(
111                     new FooterButton.Builder(this)
112                             .setText(R.string.security_settings_face_enroll_introduction_cancel)
113                             .setListener(this::onSkipButtonClick)
114                             .setButtonType(FooterButton.ButtonType.CANCEL)
115                             .setTheme(R.style.SudGlifButton_Secondary)
116                             .build()
117             );
118         }
119 
120         final FooterButton footerButton = new FooterButton.Builder(this)
121                 .setText(R.string.security_settings_face_enroll_education_start)
122                 .setListener(this::onNextButtonClick)
123                 .setButtonType(FooterButton.ButtonType.NEXT)
124                 .setTheme(R.style.SudGlifButton_Primary)
125                 .build();
126 
127         final AccessibilityManager accessibilityManager = getApplicationContext().getSystemService(
128                 AccessibilityManager.class);
129         if (accessibilityManager != null) {
130             // Add additional check for touch exploration. This prevents other accessibility
131             // features such as Live Transcribe from defaulting to the accessibility setup.
132             mAccessibilityEnabled = accessibilityManager.isEnabled()
133                     && accessibilityManager.isTouchExplorationEnabled();
134         }
135         mFooterBarMixin.setPrimaryButton(footerButton);
136 
137         final Button accessibilityButton = findViewById(R.id.accessibility_button);
138         accessibilityButton.setOnClickListener(view -> {
139             mSwitchDiversity.setChecked(true);
140             accessibilityButton.setVisibility(View.GONE);
141             mSwitchDiversity.setVisibility(View.VISIBLE);
142         });
143 
144         mSwitchDiversity = findViewById(R.id.toggle_diversity);
145         mSwitchDiversity.setListener(mSwitchDiversityListener);
146         mSwitchDiversity.setOnClickListener(v -> {
147             mSwitchDiversity.getSwitch().toggle();
148         });
149 
150         if (mAccessibilityEnabled) {
151             accessibilityButton.callOnClick();
152         }
153     }
154 
155     @Override
onResume()156     protected void onResume() {
157         super.onResume();
158         mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
159                 mSwitchDiversity.isChecked());
160 
161         // If the user goes back after enrollment, we should send them back to the intro page
162         // if they've met the max limit.
163         final int max = getResources().getInteger(
164                 com.android.internal.R.integer.config_faceMaxTemplatesPerUser);
165         final int numEnrolledFaces = mFaceManager.getEnrolledFaces(mUserId).size();
166         if (numEnrolledFaces >= max) {
167             finish();
168         }
169     }
170 
171     @Override
shouldFinishWhenBackgrounded()172     protected boolean shouldFinishWhenBackgrounded() {
173         return super.shouldFinishWhenBackgrounded() && !mNextClicked;
174     }
175 
176     @Override
onNextButtonClick(View view)177     protected void onNextButtonClick(View view) {
178         final Intent intent = new Intent();
179         if (mToken != null) {
180             intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
181         }
182         if (mUserId != UserHandle.USER_NULL) {
183             intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
184         }
185         intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
186         final String flattenedString = getString(R.string.config_face_enroll);
187         if (!TextUtils.isEmpty(flattenedString)) {
188             ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
189             intent.setComponent(componentName);
190         } else {
191             intent.setClass(this, FaceEnrollEnrolling.class);
192         }
193         WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
194         if (mResultIntent != null) {
195             intent.putExtras(mResultIntent);
196         }
197 
198         intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
199 
200         if (!mSwitchDiversity.isChecked() && mAccessibilityEnabled) {
201             FaceEnrollAccessibilityDialog dialog = FaceEnrollAccessibilityDialog.newInstance();
202             dialog.setPositiveButtonListener((dialog1, which) -> {
203                 startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
204                 mNextClicked = true;
205             });
206             dialog.show(getSupportFragmentManager(), FaceEnrollAccessibilityDialog.class.getName());
207         } else {
208             startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
209             mNextClicked = true;
210         }
211     }
212 
onSkipButtonClick(View view)213     protected void onSkipButtonClick(View view) {
214         setResult(RESULT_SKIP);
215         finish();
216     }
217 
218     @Override
onActivityResult(int requestCode, int resultCode, Intent data)219     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
220         super.onActivityResult(requestCode, resultCode, data);
221         mResultIntent = data;
222         if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
223             // If the user finished or skipped enrollment, finish this activity
224             if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP
225                     || resultCode == RESULT_TIMEOUT) {
226                 setResult(resultCode, data);
227                 finish();
228             }
229         }
230     }
231 
232     @Override
getMetricsCategory()233     public int getMetricsCategory() {
234         return SettingsEnums.FACE_ENROLL_INTRO;
235     }
236 }
237