blob: b2a54097539dd523da2370445f38483d6bb1ee5e [file] [log] [blame]
/*
* Copyright (C) 2021 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.systemui.biometrics;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* UDFPS enrollment progress bar.
*/
public class UdfpsEnrollProgressBarDrawable extends Drawable {
private static final String TAG = "UdfpsProgressBar";
private static final float SEGMENT_GAP_ANGLE = 12f;
@NonNull private final Context mContext;
@Nullable private UdfpsEnrollHelper mEnrollHelper;
@NonNull private List<UdfpsEnrollProgressBarSegment> mSegments = new ArrayList<>();
private int mTotalSteps = 1;
private int mProgressSteps = 0;
private boolean mIsShowingHelp = false;
public UdfpsEnrollProgressBarDrawable(@NonNull Context context) {
mContext = context;
}
void setEnrollHelper(@Nullable UdfpsEnrollHelper enrollHelper) {
mEnrollHelper = enrollHelper;
if (enrollHelper != null) {
final int stageCount = enrollHelper.getStageCount();
mSegments = new ArrayList<>(stageCount);
float startAngle = SEGMENT_GAP_ANGLE / 2f;
final float sweepAngle = (360f / stageCount) - SEGMENT_GAP_ANGLE;
final Runnable invalidateRunnable = this::invalidateSelf;
for (int index = 0; index < stageCount; index++) {
mSegments.add(new UdfpsEnrollProgressBarSegment(mContext, getBounds(), startAngle,
sweepAngle, SEGMENT_GAP_ANGLE, invalidateRunnable));
startAngle += sweepAngle + SEGMENT_GAP_ANGLE;
}
invalidateSelf();
}
}
void onEnrollmentProgress(int remaining, int totalSteps) {
mTotalSteps = totalSteps;
updateState(getProgressSteps(remaining, totalSteps), false /* isShowingHelp */);
}
void onEnrollmentHelp(int remaining, int totalSteps) {
updateState(getProgressSteps(remaining, totalSteps), true /* isShowingHelp */);
}
void onLastStepAcquired() {
updateState(mTotalSteps, false /* isShowingHelp */);
}
private static int getProgressSteps(int remaining, int totalSteps) {
// Show some progress for the initial touch.
return Math.max(1, totalSteps - remaining);
}
private void updateState(int progressSteps, boolean isShowingHelp) {
updateProgress(progressSteps);
updateFillColor(isShowingHelp);
}
private void updateProgress(int progressSteps) {
if (mProgressSteps == progressSteps) {
return;
}
mProgressSteps = progressSteps;
if (mEnrollHelper == null) {
Log.e(TAG, "updateState: UDFPS enroll helper was null");
return;
}
int index = 0;
int prevThreshold = 0;
while (index < mSegments.size()) {
final UdfpsEnrollProgressBarSegment segment = mSegments.get(index);
final int thresholdSteps = mEnrollHelper.getStageThresholdSteps(mTotalSteps, index);
if (progressSteps >= thresholdSteps && segment.getProgress() < 1f) {
segment.updateProgress(1f);
break;
} else if (progressSteps >= prevThreshold && progressSteps < thresholdSteps) {
final int relativeSteps = progressSteps - prevThreshold;
final int relativeThreshold = thresholdSteps - prevThreshold;
final float segmentProgress = (float) relativeSteps / (float) relativeThreshold;
segment.updateProgress(segmentProgress);
break;
}
index++;
prevThreshold = thresholdSteps;
}
if (progressSteps >= mTotalSteps) {
for (final UdfpsEnrollProgressBarSegment segment : mSegments) {
segment.startCompletionAnimation();
}
} else {
for (final UdfpsEnrollProgressBarSegment segment : mSegments) {
segment.cancelCompletionAnimation();
}
}
}
private void updateFillColor(boolean isShowingHelp) {
if (mIsShowingHelp == isShowingHelp) {
return;
}
mIsShowingHelp = isShowingHelp;
for (final UdfpsEnrollProgressBarSegment segment : mSegments) {
segment.updateFillColor(isShowingHelp);
}
}
@Override
public void draw(@NonNull Canvas canvas) {
canvas.save();
// Progress starts from the top, instead of the right
canvas.rotate(-90f, getBounds().centerX(), getBounds().centerY());
// Draw each of the enroll segments.
for (final UdfpsEnrollProgressBarSegment segment : mSegments) {
segment.draw(canvas);
}
canvas.restore();
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return 0;
}
}