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
17package com.android.settings.fingerprint;
18
19import android.content.Intent;
20import android.hardware.fingerprint.FingerprintManager;
21import android.os.Bundle;
22import android.os.UserHandle;
23
24import com.android.internal.logging.MetricsProto.MetricsEvent;
25import com.android.settings.ChooseLockSettingsHelper;
26import com.android.settings.R;
27import com.android.settings.fingerprint.FingerprintEnrollSidecar.Listener;
28
29/**
30 * Activity explaining the fingerprint sensor location for fingerprint enrollment.
31 */
32public class FingerprintEnrollFindSensor extends FingerprintEnrollBase {
33
34    private static final int CONFIRM_REQUEST = 1;
35    private static final int ENROLLING = 2;
36    public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
37
38    private FingerprintFindSensorAnimation mAnimation;
39    private boolean mLaunchedConfirmLock;
40    private FingerprintEnrollSidecar mSidecar;
41    private boolean mNextClicked;
42
43    @Override
44    protected void onCreate(Bundle savedInstanceState) {
45        super.onCreate(savedInstanceState);
46        setContentView(getContentView());
47        setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
48        if (savedInstanceState != null) {
49            mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM);
50            mToken = savedInstanceState.getByteArray(
51                    ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
52        }
53        if (mToken == null && !mLaunchedConfirmLock) {
54            launchConfirmLock();
55        } else if (mToken != null) {
56            startLookingForFingerprint(); // already confirmed, so start looking for fingerprint
57        }
58        mAnimation = (FingerprintFindSensorAnimation) findViewById(
59                R.id.fingerprint_sensor_location_animation);
60    }
61
62    protected int getContentView() {
63        return R.layout.fingerprint_enroll_find_sensor;
64    }
65
66    @Override
67    protected void onStart() {
68        super.onStart();
69        mAnimation.startAnimation();
70    }
71
72    private void startLookingForFingerprint() {
73        mSidecar = (FingerprintEnrollSidecar) getFragmentManager().findFragmentByTag(
74                FingerprintEnrollEnrolling.TAG_SIDECAR);
75        if (mSidecar == null) {
76            mSidecar = new FingerprintEnrollSidecar();
77            getFragmentManager().beginTransaction()
78                    .add(mSidecar, FingerprintEnrollEnrolling.TAG_SIDECAR).commit();
79        }
80        mSidecar.setListener(new Listener() {
81            @Override
82            public void onEnrollmentProgressChange(int steps, int remaining) {
83                mNextClicked = true;
84                if (!mSidecar.cancelEnrollment()) {
85                    proceedToEnrolling();
86                }
87            }
88
89            @Override
90            public void onEnrollmentHelp(CharSequence helpString) {
91            }
92
93            @Override
94            public void onEnrollmentError(int errMsgId, CharSequence errString) {
95                if (mNextClicked && errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
96                    mNextClicked = false;
97                    proceedToEnrolling();
98                }
99            }
100        });
101    }
102
103    @Override
104    protected void onStop() {
105        super.onStop();
106        mAnimation.pauseAnimation();
107    }
108
109    @Override
110    protected void onDestroy() {
111        super.onDestroy();
112        mAnimation.stopAnimation();
113    }
114
115    @Override
116    public void onSaveInstanceState(Bundle outState) {
117        super.onSaveInstanceState(outState);
118        outState.putBoolean(EXTRA_KEY_LAUNCHED_CONFIRM, mLaunchedConfirmLock);
119        outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
120    }
121
122    @Override
123    protected void onNextButtonClick() {
124        mNextClicked = true;
125        if (mSidecar == null || (mSidecar != null && !mSidecar.cancelEnrollment())) {
126            proceedToEnrolling();
127        }
128    }
129
130    private void proceedToEnrolling() {
131        getFragmentManager().beginTransaction().remove(mSidecar).commit();
132        mSidecar = null;
133        startActivityForResult(getEnrollingIntent(), ENROLLING);
134    }
135
136    @Override
137    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
138        if (requestCode == CONFIRM_REQUEST) {
139            if (resultCode == RESULT_OK) {
140                mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
141                overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
142                getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
143                startLookingForFingerprint();
144            } else {
145                finish();
146            }
147        } else if (requestCode == ENROLLING) {
148            if (resultCode == RESULT_FINISHED) {
149                setResult(RESULT_FINISHED);
150                finish();
151            } else if (resultCode == RESULT_SKIP) {
152                setResult(RESULT_SKIP);
153                finish();
154            } else if (resultCode == RESULT_TIMEOUT) {
155                setResult(RESULT_TIMEOUT);
156                finish();
157            } else {
158                FingerprintManager fpm = getSystemService(FingerprintManager.class);
159                int enrolled = fpm.getEnrolledFingerprints().size();
160                int max = getResources().getInteger(
161                        com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
162                if (enrolled >= max) {
163                    finish();
164                } else {
165                    // We came back from enrolling but it wasn't completed, start again.
166                    startLookingForFingerprint();
167                }
168            }
169        } else {
170            super.onActivityResult(requestCode, resultCode, data);
171        }
172    }
173
174    private void launchConfirmLock() {
175        long challenge = getSystemService(FingerprintManager.class).preEnroll();
176        ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
177        boolean launchedConfirmationActivity = false;
178        if (mUserId == UserHandle.USER_NULL) {
179            launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
180                getString(R.string.security_settings_fingerprint_preference_title),
181                null, null, challenge);
182        } else {
183            launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
184                    getString(R.string.security_settings_fingerprint_preference_title),
185                    null, null, challenge, mUserId);
186        }
187        if (!launchedConfirmationActivity) {
188            // This shouldn't happen, as we should only end up at this step if a lock thingy is
189            // already set.
190            finish();
191        } else {
192            mLaunchedConfirmLock = true;
193        }
194    }
195
196    @Override
197    protected int getMetricsCategory() {
198        return MetricsEvent.FINGERPRINT_FIND_SENSOR;
199    }
200}
201