• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.Nullable;
20 import android.app.Activity;
21 import android.content.Intent;
22 import android.hardware.fingerprint.FingerprintManager;
23 import android.os.Bundle;
24 import android.os.CancellationSignal;
25 import android.os.Handler;
26 import android.os.UserHandle;
27 
28 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
29 import com.android.settings.Utils;
30 import com.android.settings.core.InstrumentedFragment;
31 import com.android.settings.password.ChooseLockSettingsHelper;
32 
33 import java.util.ArrayList;
34 
35 /**
36  * Sidecar fragment to handle the state around fingerprint enrollment.
37  */
38 public class FingerprintEnrollSidecar extends InstrumentedFragment {
39 
40     private int mEnrollmentSteps = -1;
41     private int mEnrollmentRemaining = 0;
42     private Listener mListener;
43     private boolean mEnrolling;
44     private CancellationSignal mEnrollmentCancel;
45     private Handler mHandler = new Handler();
46     private byte[] mToken;
47     private boolean mDone;
48     private int mUserId;
49     private FingerprintManager mFingerprintManager;
50     private ArrayList<QueuedEvent> mQueuedEvents;
51 
52     private abstract class QueuedEvent {
send(Listener listener)53         public abstract void send(Listener listener);
54     }
55 
56     private class QueuedEnrollmentProgress extends QueuedEvent {
57         int enrollmentSteps;
58         int remaining;
QueuedEnrollmentProgress(int enrollmentSteps, int remaining)59         public QueuedEnrollmentProgress(int enrollmentSteps, int remaining) {
60             this.enrollmentSteps = enrollmentSteps;
61             this.remaining = remaining;
62         }
63 
64         @Override
send(Listener listener)65         public void send(Listener listener) {
66             listener.onEnrollmentProgressChange(enrollmentSteps, remaining);
67         }
68     }
69 
70     private class QueuedEnrollmentHelp extends QueuedEvent {
71         int helpMsgId;
72         CharSequence helpString;
QueuedEnrollmentHelp(int helpMsgId, CharSequence helpString)73         public QueuedEnrollmentHelp(int helpMsgId, CharSequence helpString) {
74             this.helpMsgId = helpMsgId;
75             this.helpString = helpString;
76         }
77 
78         @Override
send(Listener listener)79         public void send(Listener listener) {
80             listener.onEnrollmentHelp(helpString);
81         }
82     }
83 
84     private class QueuedEnrollmentError extends QueuedEvent {
85         int errMsgId;
86         CharSequence errString;
QueuedEnrollmentError(int errMsgId, CharSequence errString)87         public QueuedEnrollmentError(int errMsgId, CharSequence errString) {
88             this.errMsgId = errMsgId;
89             this.errString = errString;
90         }
91 
92         @Override
send(Listener listener)93         public void send(Listener listener) {
94             listener.onEnrollmentError(errMsgId, errString);
95         }
96     }
97 
FingerprintEnrollSidecar()98     public FingerprintEnrollSidecar() {
99         mQueuedEvents = new ArrayList<>();
100     }
101 
102     @Override
onCreate(@ullable Bundle savedInstanceState)103     public void onCreate(@Nullable Bundle savedInstanceState) {
104         super.onCreate(savedInstanceState);
105         setRetainInstance(true);
106     }
107 
108     @Override
onAttach(Activity activity)109     public void onAttach(Activity activity) {
110         super.onAttach(activity);
111         mFingerprintManager = Utils.getFingerprintManagerOrNull(activity);
112         mToken = activity.getIntent().getByteArrayExtra(
113                 ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
114         mUserId = activity.getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
115     }
116 
117     @Override
onStart()118     public void onStart() {
119         super.onStart();
120         if (!mEnrolling) {
121             startEnrollment();
122         }
123     }
124 
125     @Override
onStop()126     public void onStop() {
127         super.onStop();
128         if (!getActivity().isChangingConfigurations()) {
129             cancelEnrollment();
130         }
131     }
132 
startEnrollment()133     private void startEnrollment() {
134         mHandler.removeCallbacks(mTimeoutRunnable);
135         mEnrollmentSteps = -1;
136         mEnrollmentCancel = new CancellationSignal();
137         if (mUserId != UserHandle.USER_NULL) {
138             mFingerprintManager.setActiveUser(mUserId);
139         }
140         mFingerprintManager.enroll(mToken, mEnrollmentCancel,
141                 0 /* flags */, mUserId, mEnrollmentCallback);
142         mEnrolling = true;
143     }
144 
cancelEnrollment()145     boolean cancelEnrollment() {
146         mHandler.removeCallbacks(mTimeoutRunnable);
147         if (mEnrolling) {
148             mEnrollmentCancel.cancel();
149             mEnrolling = false;
150             mEnrollmentSteps = -1;
151             return true;
152         }
153         return false;
154     }
155 
setListener(Listener listener)156     public void setListener(Listener listener) {
157         mListener = listener;
158         if (mListener != null) {
159             for (int i=0; i<mQueuedEvents.size(); i++) {
160                 QueuedEvent event = mQueuedEvents.get(i);
161                 event.send(mListener);
162             }
163             mQueuedEvents.clear();
164         }
165     }
166 
getEnrollmentSteps()167     public int getEnrollmentSteps() {
168         return mEnrollmentSteps;
169     }
170 
getEnrollmentRemaining()171     public int getEnrollmentRemaining() {
172         return mEnrollmentRemaining;
173     }
174 
isDone()175     public boolean isDone() {
176         return mDone;
177     }
178 
179     private FingerprintManager.EnrollmentCallback mEnrollmentCallback
180             = new FingerprintManager.EnrollmentCallback() {
181 
182         @Override
183         public void onEnrollmentProgress(int remaining) {
184             if (mEnrollmentSteps == -1) {
185                 mEnrollmentSteps = remaining;
186             }
187             mEnrollmentRemaining = remaining;
188             mDone = remaining == 0;
189             if (mListener != null) {
190                 mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining);
191             } else {
192                 mQueuedEvents.add(new QueuedEnrollmentProgress(mEnrollmentSteps, remaining));
193             }
194         }
195 
196         @Override
197         public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
198             if (mListener != null) {
199                 mListener.onEnrollmentHelp(helpString);
200             } else {
201                 mQueuedEvents.add(new QueuedEnrollmentHelp(helpMsgId, helpString));
202             }
203         }
204 
205         @Override
206         public void onEnrollmentError(int errMsgId, CharSequence errString) {
207             if (mListener != null) {
208                 mListener.onEnrollmentError(errMsgId, errString);
209             } else {
210                 mQueuedEvents.add(new QueuedEnrollmentError(errMsgId, errString));
211             }
212             mEnrolling = false;
213         }
214     };
215 
216     private final Runnable mTimeoutRunnable = new Runnable() {
217         @Override
218         public void run() {
219             cancelEnrollment();
220         }
221     };
222 
223     @Override
getMetricsCategory()224     public int getMetricsCategory() {
225         return MetricsEvent.FINGERPRINT_ENROLL_SIDECAR;
226     }
227 
228     public interface Listener {
onEnrollmentHelp(CharSequence helpString)229         void onEnrollmentHelp(CharSequence helpString);
onEnrollmentError(int errMsgId, CharSequence errString)230         void onEnrollmentError(int errMsgId, CharSequence errString);
onEnrollmentProgressChange(int steps, int remaining)231         void onEnrollmentProgressChange(int steps, int remaining);
232     }
233 
isEnrolling()234     public boolean isEnrolling() {
235         return mEnrolling;
236     }
237 }
238