Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64e9c4cb authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Move fingerprint enroll logic into sidecar fragment

So enroll can continue across configuration changes.

Bug: 20495507
Change-Id: I021f2f3e376fcd12c7a698f5fb7f862733cb720a
parent c9f73801
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@
    <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
    <uses-permission android:name="android.permission.USE_FINGERPRINT" />
    <uses-permission android:name="android.permission.MANAGE_FINGERPRINT" />
    <uses-permission android:name="android.permission.USER_ACTIVITY" />

    <application android:label="@string/settings_label"
            android:icon="@mipmap/ic_launcher_settings"
+2 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
        android:max="10000"
        android:progress="0"
        android:indeterminate="false"
        android:progressDrawable="@drawable/fingerprint_progress_ring" />
        android:progressDrawable="@drawable/fingerprint_progress_ring"
        android:rotation="-90"/>

</RelativeLayout>
+61 −57
Original line number Diff line number Diff line
@@ -42,7 +42,10 @@ import com.android.settings.R;
/**
 * Activity which handles the actual enrolling for fingerprint.
 */
public class FingerprintEnrollEnrolling extends FingerprintEnrollBase {
public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
        implements FingerprintEnrollSidecar.Listener {

    private static final String TAG_SIDECAR = "sidecar";

    private static final int PROGRESS_BAR_MAX = 10000;
    private static final int FINISH_DELAY = 250;
@@ -53,10 +56,6 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase {
     */
    private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;

    private PowerManager mPowerManager;
    private CancellationSignal mEnrollmentCancel = new CancellationSignal();
    private int mEnrollmentSteps;
    private boolean mEnrolling;
    private ProgressBar mProgressBar;
    private ImageView mFingerprintAnimator;
    private ObjectAnimator mProgressAnim;
@@ -65,13 +64,13 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase {
    private TextView mErrorText;
    private Interpolator mFastOutSlowInInterpolator;
    private int mIconTouchCount;
    private FingerprintEnrollSidecar mSidecar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fingerprint_enroll_enrolling);
        setHeaderText(R.string.security_settings_fingerprint_enroll_start_title);
        mPowerManager = getSystemService(PowerManager.class);
        mStartMessage = (TextView) findViewById(R.id.start_message);
        mRepeatMessage = (TextView) findViewById(R.id.repeat_message);
        mErrorText = (TextView) findViewById(R.id.error_text);
@@ -92,31 +91,32 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase {
                return true;
            }
        });
        startEnrollment();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cancelEnrollment();
    protected void onStart() {
        super.onStart();
        mSidecar = (FingerprintEnrollSidecar) getFragmentManager().findFragmentByTag(TAG_SIDECAR);
        if (mSidecar == null) {
            mSidecar = new FingerprintEnrollSidecar();
            getFragmentManager().beginTransaction().add(mSidecar, TAG_SIDECAR).commit();
        }
        mSidecar.setListener(this);
        if (mSidecar.isDone()) {
            launchFinish(mToken);
        } else {
            updateProgress(false /* animate */);
            updateDescription();
        }

    private void startEnrollment() {
        mEnrollmentSteps = -1;
        getSystemService(FingerprintManager.class).enroll(mToken, mEnrollmentCancel,
                mEnrollmentCallback, 0);
        mProgressBar.setProgress(0);
        mEnrolling = true;
    }

    private void cancelEnrollment() {
        if (mEnrolling) {
            mEnrollmentCancel.cancel();
            mEnrolling = false;
        }
    @Override
    protected void onStop() {
        super.onStop();
        mSidecar.setListener(null);
    }

    private void updateProgress(int progress) {
    private void animateProgress(int progress) {
        if (mProgressAnim != null) {
            mProgressAnim.cancel();
        }
@@ -139,7 +139,7 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase {
    }

    private void updateDescription() {
        if (mEnrollmentSteps == -1) {
        if (mSidecar.getEnrollmentSteps() == -1) {
            setHeaderText(R.string.security_settings_fingerprint_enroll_start_title);
            mStartMessage.setVisibility(View.VISIBLE);
            mRepeatMessage.setVisibility(View.INVISIBLE);
@@ -150,6 +150,42 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase {
        }
    }


    @Override
    public void onEnrollmentHelp(CharSequence helpString) {
        mErrorText.setText(helpString);
    }

    @Override
    public void onEnrollmentError(CharSequence errString) {
        mErrorText.setText(errString);
    }

    @Override
    public void onEnrollmentProgressChange(int steps, int remaining) {
        updateProgress(true /* animate */);
        updateDescription();
        mErrorText.setText("");
    }

    private void updateProgress(boolean animate) {
        int progress = getProgress(
                mSidecar.getEnrollmentSteps(), mSidecar.getEnrollmentRemaining());
        if (animate) {
            animateProgress(progress);
        } else {
            mProgressBar.setProgress(progress);
        }
    }

    private int getProgress(int steps, int remaining) {
        if (steps == -1) {
            return 0;
        }
        int progress = Math.max(0, steps + 1 - remaining);
        return PROGRESS_BAR_MAX * progress / (steps + 1);
    }

    private void showIconTouchDialog() {
        new IconTouchDialog().show(getFragmentManager(), null /* tag */);
    }
@@ -174,38 +210,6 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase {
        public void onAnimationCancel(Animator animation) { }
    };

    private FingerprintManager.EnrollmentCallback mEnrollmentCallback
            = new FingerprintManager.EnrollmentCallback() {

        @Override
        public void onEnrollmentProgress(int remaining) {
            if (mEnrollmentSteps == -1) {
                mEnrollmentSteps = remaining;
                updateDescription();
            }
            if (remaining >= 0) {
                int progress = Math.max(0, mEnrollmentSteps + 1 - remaining);
                updateProgress(PROGRESS_BAR_MAX * progress / (mEnrollmentSteps + 1));

                // Treat fingerprint like a touch event
                mPowerManager.userActivity(SystemClock.uptimeMillis(),
                        PowerManager.USER_ACTIVITY_EVENT_OTHER,
                        PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS);
            }
            mErrorText.setText("");
        }

        @Override
        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
            mErrorText.setText(helpString);
        }

        @Override
        public void onEnrollmentError(int errMsgId, CharSequence errString) {
            mErrorText.setText(errString);
        }
    };

    // Give the user a chance to see progress completed before jumping to the next stage.
    Runnable mDelayedFinishRunnable = new Runnable() {
        @Override
+157 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.fingerprint;

import android.annotation.Nullable;
import android.app.Activity;
import android.app.Fragment;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;

import com.android.settings.ChooseLockSettingsHelper;

/**
 * Sidecar fragment to handle the state around fingerprint enrollment.
 */
public class FingerprintEnrollSidecar extends Fragment {

    private int mEnrollmentSteps = -1;
    private int mEnrollmentRemaining = 0;
    private Listener mListener;
    private PowerManager mPowerManager;
    private boolean mEnrolling;
    private CancellationSignal mEnrollmentCancel;
    private Handler mHandler = new Handler();
    private byte[] mToken;
    private boolean mDone;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mPowerManager = activity.getSystemService(PowerManager.class);
        mToken = activity.getIntent().getByteArrayExtra(
                ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
    }

    @Override
    public void onStart() {
        super.onStart();
        if (!mEnrolling) {
            startEnrollment();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (!getActivity().isChangingConfigurations()) {
            cancelEnrollment();
        }
    }

    private void startEnrollment() {
        mHandler.removeCallbacks(mTimeoutRunnable);
        mEnrollmentSteps = -1;
        mEnrollmentCancel = new CancellationSignal();
        getActivity().getSystemService(FingerprintManager.class).enroll(mToken, mEnrollmentCancel,
                mEnrollmentCallback, 0);
        mEnrolling = true;
    }

    private void cancelEnrollment() {
        mHandler.removeCallbacks(mTimeoutRunnable);
        if (mEnrolling) {
            mEnrollmentCancel.cancel();
            mEnrolling = false;
            mEnrollmentSteps = -1;
        }
    }

    public void setListener(Listener listener) {
        mListener = listener;
    }

    public int getEnrollmentSteps() {
        return mEnrollmentSteps;
    }

    public int getEnrollmentRemaining() {
        return mEnrollmentRemaining;
    }

    public boolean isDone() {
        return mDone;
    }

    private FingerprintManager.EnrollmentCallback mEnrollmentCallback
            = new FingerprintManager.EnrollmentCallback() {

        @Override
        public void onEnrollmentProgress(int remaining) {
            if (mEnrollmentSteps == -1) {
                mEnrollmentSteps = remaining;
            }
            mEnrollmentRemaining = remaining;
            mDone = remaining == 0;
            if (mListener != null) {
                mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining);
            }

            // Treat fingerprint like a touch event
            mPowerManager.userActivity(SystemClock.uptimeMillis(),
                    PowerManager.USER_ACTIVITY_EVENT_OTHER,
                    PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS);
        }

        @Override
        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
            if (mListener != null) {
                mListener.onEnrollmentHelp(helpString);
            }
        }

        @Override
        public void onEnrollmentError(int errMsgId, CharSequence errString) {
            if (mListener != null) {
                mListener.onEnrollmentError(errString);
            }
        }
    };

    private final Runnable mTimeoutRunnable = new Runnable() {
        @Override
        public void run() {
            cancelEnrollment();
        }
    };

    public interface Listener {
        void onEnrollmentHelp(CharSequence helpString);
        void onEnrollmentError(CharSequence errString);
        void onEnrollmentProgressChange(int steps, int remaining);
    }
}