1 /*
2  * Copyright (C) 2015 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.fingerprint;
18 
19 import android.app.admin.DevicePolicyManager;
20 import android.content.ActivityNotFoundException;
21 import android.content.Intent;
22 import android.hardware.fingerprint.FingerprintManager;
23 import android.os.Bundle;
24 import android.os.UserHandle;
25 import android.os.UserManager;
26 import android.util.Log;
27 import android.view.View;
28 import android.widget.Button;
29 import android.widget.TextView;
30 
31 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
32 import com.android.settings.ChooseLockGeneric;
33 import com.android.settings.ChooseLockSettingsHelper;
34 import com.android.settings.R;
35 import com.android.settings.Utils;
36 import com.android.settingslib.HelpUtils;
37 import com.android.settingslib.RestrictedLockUtils;
38 import com.android.setupwizardlib.span.LinkSpan;
39 
40 /**
41  * Onboarding activity for fingerprint enrollment.
42  */
43 public class FingerprintEnrollIntroduction extends FingerprintEnrollBase
44         implements View.OnClickListener, LinkSpan.OnClickListener {
45 
46     private static final String TAG = "FingerprintIntro";
47 
48     protected static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
49     protected static final int FINGERPRINT_FIND_SENSOR_REQUEST = 2;
50     protected static final int LEARN_MORE_REQUEST = 3;
51 
52     private UserManager mUserManager;
53     private boolean mHasPassword;
54     private boolean mFingerprintUnlockDisabledByAdmin;
55     private TextView mErrorText;
56 
57     @Override
onCreate(Bundle savedInstanceState)58     protected void onCreate(Bundle savedInstanceState) {
59         super.onCreate(savedInstanceState);
60         mFingerprintUnlockDisabledByAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
61                 this, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId) != null;
62 
63         setContentView(R.layout.fingerprint_enroll_introduction);
64         if (mFingerprintUnlockDisabledByAdmin) {
65             setHeaderText(R.string
66                     .security_settings_fingerprint_enroll_introduction_title_unlock_disabled);
67         } else {
68             setHeaderText(R.string.security_settings_fingerprint_enroll_introduction_title);
69         }
70 
71         Button cancelButton = (Button) findViewById(R.id.fingerprint_cancel_button);
72         cancelButton.setOnClickListener(this);
73 
74         mErrorText = (TextView) findViewById(R.id.error_text);
75 
76         mUserManager = UserManager.get(this);
77         updatePasswordQuality();
78     }
79 
80     @Override
onResume()81     protected void onResume() {
82         super.onResume();
83 
84         final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(this);
85         int errorMsg = 0;
86         if (fingerprintManager != null) {
87             final int max = getResources().getInteger(
88                     com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
89             final int numEnrolledFingerprints =
90                     fingerprintManager.getEnrolledFingerprints(mUserId).size();
91             if (numEnrolledFingerprints >= max) {
92                 errorMsg = R.string.fingerprint_intro_error_max;
93             }
94         } else {
95             errorMsg = R.string.fingerprint_intro_error_unknown;
96         }
97         if (errorMsg == 0) {
98             mErrorText.setText(null);
99             getNextButton().setVisibility(View.VISIBLE);
100         } else {
101             mErrorText.setText(errorMsg);
102             getNextButton().setVisibility(View.GONE);
103         }
104     }
105 
updatePasswordQuality()106     private void updatePasswordQuality() {
107         final int passwordQuality = new ChooseLockSettingsHelper(this).utils()
108                 .getActivePasswordQuality(mUserManager.getCredentialOwnerProfile(mUserId));
109         mHasPassword = passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
110     }
111 
112     @Override
getNextButton()113     protected Button getNextButton() {
114         return (Button) findViewById(R.id.fingerprint_next_button);
115     }
116 
117     @Override
onNextButtonClick()118     protected void onNextButtonClick() {
119         if (!mHasPassword) {
120             // No fingerprints registered, launch into enrollment wizard.
121             launchChooseLock();
122         } else {
123             // Lock thingy is already set up, launch directly into find sensor step from wizard.
124             launchFindSensor(null);
125         }
126     }
127 
launchChooseLock()128     private void launchChooseLock() {
129         Intent intent = getChooseLockIntent();
130         long challenge = Utils.getFingerprintManagerOrNull(this).preEnroll();
131         intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
132                 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
133         intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
134         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
135         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
136         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
137         if (mUserId != UserHandle.USER_NULL) {
138             intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
139         }
140         startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
141     }
142 
launchFindSensor(byte[] token)143     private void launchFindSensor(byte[] token) {
144         Intent intent = getFindSensorIntent();
145         if (token != null) {
146             intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
147         }
148         if (mUserId != UserHandle.USER_NULL) {
149             intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
150         }
151         startActivityForResult(intent, FINGERPRINT_FIND_SENSOR_REQUEST);
152     }
153 
getChooseLockIntent()154     protected Intent getChooseLockIntent() {
155         return new Intent(this, ChooseLockGeneric.class);
156     }
157 
getFindSensorIntent()158     protected Intent getFindSensorIntent() {
159         return new Intent(this, FingerprintEnrollFindSensor.class);
160     }
161 
162     @Override
onActivityResult(int requestCode, int resultCode, Intent data)163     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
164         final boolean isResultFinished = resultCode == RESULT_FINISHED;
165         if (requestCode == FINGERPRINT_FIND_SENSOR_REQUEST) {
166             if (isResultFinished || resultCode == RESULT_SKIP) {
167                 final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
168                 setResult(result, data);
169                 finish();
170                 return;
171             }
172         } else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
173             if (isResultFinished) {
174                 updatePasswordQuality();
175                 byte[] token = data.getByteArrayExtra(
176                         ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
177                 launchFindSensor(token);
178                 return;
179             }
180         } else if (requestCode == LEARN_MORE_REQUEST) {
181             overridePendingTransition(R.anim.suw_slide_back_in, R.anim.suw_slide_back_out);
182         }
183         super.onActivityResult(requestCode, resultCode, data);
184     }
185 
186     @Override
onClick(View v)187     public void onClick(View v) {
188         if (v.getId() == R.id.fingerprint_cancel_button) {
189             onCancelButtonClick();
190         } else {
191             super.onClick(v);
192         }
193     }
194 
195     @Override
getMetricsCategory()196     public int getMetricsCategory() {
197         return MetricsEvent.FINGERPRINT_ENROLL_INTRO;
198     }
199 
onCancelButtonClick()200     protected void onCancelButtonClick() {
201         finish();
202     }
203 
204     @Override
initViews()205     protected void initViews() {
206         super.initViews();
207 
208         TextView description = (TextView) findViewById(R.id.description_text);
209         if (mFingerprintUnlockDisabledByAdmin) {
210             description.setText(R.string
211                     .security_settings_fingerprint_enroll_introduction_message_unlock_disabled);
212         }
213     }
214 
215     @Override
onClick(LinkSpan span)216     public void onClick(LinkSpan span) {
217         if ("url".equals(span.getId())) {
218             String url = getString(R.string.help_url_fingerprint);
219             Intent intent = HelpUtils.getHelpIntent(this, url, getClass().getName());
220             if (intent == null) {
221                 Log.w(TAG, "Null help intent.");
222                 return;
223             }
224             try {
225                 // This needs to be startActivityForResult even though we do not care about the
226                 // actual result because the help app needs to know about who invoked it.
227                 startActivityForResult(intent, LEARN_MORE_REQUEST);
228             } catch (ActivityNotFoundException e) {
229                 Log.w(TAG, "Activity was not found for intent, " + e);
230             }
231         }
232     }
233 }
234