import android.graphics.drawable.Drawable;
import com.android.settings.biometrics.BiometricEnrollSidecar;
+import com.android.settings.overlay.FeatureFactory;
/**
* A drawable containing the circle cutout as well as the animations.
private static final int BORDER_BOUNDS = 20;
private final Context mContext;
- private final ParticleCollection.Listener mListener;
+ private final FaceFeatureProvider.Listener mListener;
private Rect mBounds;
private final Paint mSquarePaint;
private final Paint mCircleCutoutPaint;
- private ParticleCollection mParticleCollection;
+ private FaceFeatureProvider.EnrollingAnimation mEnrollingAnimation;
private TimeAnimator mTimeAnimator;
- private final ParticleCollection.Listener mAnimationListener
- = new ParticleCollection.Listener() {
+ private final FaceFeatureProvider.Listener mAnimationListener
+ = new FaceFeatureProvider.Listener() {
@Override
public void onEnrolled() {
if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
}
};
- public FaceEnrollAnimationDrawable(Context context, ParticleCollection.Listener listener) {
+ public FaceEnrollAnimationDrawable(Context context, FaceFeatureProvider.Listener listener) {
mContext = context;
mListener = listener;
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
- mParticleCollection.onEnrollmentHelp(helpMsgId, helpString);
+ mEnrollingAnimation.onEnrollmentHelp(helpMsgId, helpString);
}
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
- mParticleCollection.onEnrollmentError(errMsgId, errString);
+ mEnrollingAnimation.onEnrollmentError(errMsgId, errString);
}
@Override
public void onEnrollmentProgressChange(int steps, int remaining) {
- mParticleCollection.onEnrollmentProgressChange(steps, remaining);
+ mEnrollingAnimation.onEnrollmentProgressChange(steps, remaining);
}
@Override
protected void onBoundsChange(Rect bounds) {
mBounds = bounds;
- mParticleCollection =
- new ParticleCollection(mContext, mAnimationListener, bounds, BORDER_BOUNDS);
+ mEnrollingAnimation = FeatureFactory.getFactory(mContext).getFaceFeatureProvider()
+ .getEnrollingAnimation(mContext, mAnimationListener, bounds, BORDER_BOUNDS);
if (mTimeAnimator == null) {
mTimeAnimator = new TimeAnimator();
mTimeAnimator.setTimeListener((animation, totalTimeMs, deltaTimeMs) -> {
- mParticleCollection.update(totalTimeMs, deltaTimeMs);
+ mEnrollingAnimation.update(totalTimeMs, deltaTimeMs);
FaceEnrollAnimationDrawable.this.invalidateSelf();
});
mTimeAnimator.start();
mBounds.height() / 2 - BORDER_BOUNDS, mCircleCutoutPaint);
// Draw the animation
- mParticleCollection.draw(canvas);
+ mEnrollingAnimation.draw(canvas);
canvas.restore();
}
private boolean mShouldFinishOnStop = true;
private FaceEnrollPreviewFragment mPreviewFragment;
- private ParticleCollection.Listener mListener = new ParticleCollection.Listener() {
+ private FaceFeatureProvider.Listener mListener = new FaceFeatureProvider.Listener() {
@Override
public void onEnrolled() {
FaceEnrollEnrolling.this.launchFinish(mToken);
private CameraCaptureSession mCaptureSession;
private CaptureRequest mPreviewRequest;
private Size mPreviewSize;
- private ParticleCollection.Listener mListener;
+ private FaceFeatureProvider.Listener mListener;
// View used to contain the circular cutout and enrollment animation drawable
private ImageView mCircleView;
private FaceSquareTextureView mTextureView;
// Listener sent to the animation drawable
- private final ParticleCollection.Listener mAnimationListener
- = new ParticleCollection.Listener() {
+ private final FaceFeatureProvider.Listener mAnimationListener
+ = new FaceFeatureProvider.Listener() {
@Override
public void onEnrolled() {
mListener.onEnrolled();
mAnimationDrawable.onEnrollmentProgressChange(steps, remaining);
}
- public void setListener(ParticleCollection.Listener listener) {
+ public void setListener(FaceFeatureProvider.Listener listener) {
mListener = listener;
}
--- /dev/null
+/*
+ * Copyright (C) 2018 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.biometrics.face;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+
+/**
+ * Feature provider for face authentication.
+ */
+public interface FaceFeatureProvider {
+
+ interface EnrollingAnimation {
+ void onEnrollmentHelp(int helpMsgId, CharSequence helpString);
+ void onEnrollmentError(int errMsgId, CharSequence errString);
+ void onEnrollmentProgressChange(int steps, int remaining);
+ void draw(Canvas canvas);
+ void update(long t, long dt);
+ }
+
+ interface Listener {
+ void onEnrolled();
+ }
+
+ EnrollingAnimation getEnrollingAnimation(Context context, Listener listener, Rect bounds,
+ int borderWidth);
+}
--- /dev/null
+/*
+ * Copyright (C) 2018 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.biometrics.face;
+
+import android.content.Context;
+import android.graphics.Rect;
+
+public class FaceFeatureProviderImpl implements FaceFeatureProvider {
+ @Override
+ public EnrollingAnimation getEnrollingAnimation(Context context, Listener listener, Rect bounds,
+ int borderWidth) {
+ return new ParticleCollection(context, listener, bounds, borderWidth);
+ }
+}
* are updated/drawn in a special order so that the overlap is correct during the final completion
* effect.
*/
-public class ParticleCollection implements BiometricEnrollSidecar.Listener {
+public class ParticleCollection implements FaceFeatureProviderImpl.EnrollingAnimation {
private static final String TAG = "AnimationController";
private final List<AnimationParticle> mParticleList;
private final List<Integer> mPrimariesInProgress; // primary particles not done animating yet
private int mState;
- private Listener mListener;
-
- public interface Listener {
- void onEnrolled();
- }
+ private FaceFeatureProvider.Listener mListener;
private final AnimationParticle.Listener mParticleListener = new AnimationParticle.Listener() {
@Override
}
};
- public ParticleCollection(Context context, Listener listener, Rect bounds, int borderWidth) {
+ public ParticleCollection(Context context, FaceFeatureProvider.Listener listener, Rect bounds,
+ int borderWidth) {
mParticleList = new ArrayList<>();
mListener = listener;
updateState(STATE_STARTED);
}
+ @Override
public void update(long t, long dt) {
for (int i = 0; i < mParticleList.size(); i++) {
mParticleList.get(i).update(t, dt);
}
}
+ @Override
public void draw(Canvas canvas) {
for (int i = 0; i < mParticleList.size(); i++) {
mParticleList.get(i).draw(canvas);
import com.android.settings.R;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
+import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider();
+ public abstract FaceFeatureProvider getFaceFeatureProvider();
+
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
import com.android.settings.accounts.AccountFeatureProviderImpl;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProviderImpl;
+import com.android.settings.biometrics.face.FaceFeatureProvider;
+import com.android.settings.biometrics.face.FaceFeatureProviderImpl;
import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl;
import com.android.settings.core.instrumentation.SettingsMetricsFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
private AccountFeatureProvider mAccountFeatureProvider;
private PanelFeatureProvider mPanelFeatureProvider;
private ContextualCardFeatureProvider mContextualCardFeatureProvider;
+ private FaceFeatureProvider mFaceFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
return mPanelFeatureProvider;
}
+ @Override
public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
if (mContextualCardFeatureProvider == null) {
mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl();
}
return mContextualCardFeatureProvider;
}
+
+ @Override
+ public FaceFeatureProvider getFaceFeatureProvider() {
+ if (mFaceFeatureProvider == null) {
+ mFaceFeatureProvider = new FaceFeatureProviderImpl();
+ }
+ return mFaceFeatureProvider;
+ }
}
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
+import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
public final AssistGestureFeatureProvider assistGestureFeatureProvider;
public final AccountFeatureProvider mAccountFeatureProvider;
public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
+ public final FaceFeatureProvider mFaceFeatureProvider;
public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
mAccountFeatureProvider = mock(AccountFeatureProvider.class);
mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
panelFeatureProvider = mock(PanelFeatureProvider.class);
+ mFaceFeatureProvider = mock(FaceFeatureProvider.class);
}
@Override
return panelFeatureProvider;
}
+ @Override
public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
return mContextualCardFeatureProvider;
}
+
+ @Override
+ public FaceFeatureProvider getFaceFeatureProvider() {
+ return mFaceFeatureProvider;
+ }
}