• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.systemui.statusbar.phone;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.animation.ValueAnimator;
22 import android.content.Context;
23 import android.view.MotionEvent;
24 import android.view.VelocityTracker;
25 import android.view.View;
26 import android.view.ViewConfiguration;
27 
28 import com.android.systemui.R;
29 import com.android.systemui.animation.Interpolators;
30 import com.android.systemui.classifier.Classifier;
31 import com.android.systemui.plugins.FalsingManager;
32 import com.android.systemui.statusbar.KeyguardAffordanceView;
33 import com.android.wm.shell.animation.FlingAnimationUtils;
34 
35 /**
36  * A touch handler of the keyguard which is responsible for launching phone and camera affordances.
37  */
38 public class KeyguardAffordanceHelper {
39 
40     public static final long HINT_PHASE1_DURATION = 200;
41     private static final long HINT_PHASE2_DURATION = 350;
42     private static final float BACKGROUND_RADIUS_SCALE_FACTOR = 0.25f;
43     private static final int HINT_CIRCLE_OPEN_DURATION = 500;
44 
45     private final Context mContext;
46     private final Callback mCallback;
47 
48     private FlingAnimationUtils mFlingAnimationUtils;
49     private VelocityTracker mVelocityTracker;
50     private boolean mSwipingInProgress;
51     private float mInitialTouchX;
52     private float mInitialTouchY;
53     private float mTranslation;
54     private float mTranslationOnDown;
55     private int mTouchSlop;
56     private int mMinTranslationAmount;
57     private int mMinFlingVelocity;
58     private int mHintGrowAmount;
59     private KeyguardAffordanceView mLeftIcon;
60     private KeyguardAffordanceView mRightIcon;
61     private Animator mSwipeAnimator;
62     private final FalsingManager mFalsingManager;
63     private int mMinBackgroundRadius;
64     private boolean mMotionCancelled;
65     private int mTouchTargetSize;
66     private View mTargetedView;
67     private boolean mTouchSlopExeeded;
68     private AnimatorListenerAdapter mFlingEndListener = new AnimatorListenerAdapter() {
69         @Override
70         public void onAnimationEnd(Animator animation) {
71             mSwipeAnimator = null;
72             mSwipingInProgress = false;
73             mTargetedView = null;
74         }
75     };
76     private Runnable mAnimationEndRunnable = new Runnable() {
77         @Override
78         public void run() {
79             mCallback.onAnimationToSideEnded();
80         }
81     };
82 
KeyguardAffordanceHelper(Callback callback, Context context, FalsingManager falsingManager)83     KeyguardAffordanceHelper(Callback callback, Context context, FalsingManager falsingManager) {
84         mContext = context;
85         mCallback = callback;
86         initIcons();
87         updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false);
88         updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false);
89         mFalsingManager = falsingManager;
90         initDimens();
91     }
92 
initDimens()93     private void initDimens() {
94         final ViewConfiguration configuration = ViewConfiguration.get(mContext);
95         mTouchSlop = configuration.getScaledPagingTouchSlop();
96         mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
97         mMinTranslationAmount = mContext.getResources().getDimensionPixelSize(
98                 R.dimen.keyguard_min_swipe_amount);
99         mMinBackgroundRadius = mContext.getResources().getDimensionPixelSize(
100                 R.dimen.keyguard_affordance_min_background_radius);
101         mTouchTargetSize = mContext.getResources().getDimensionPixelSize(
102                 R.dimen.keyguard_affordance_touch_target_size);
103         mHintGrowAmount =
104                 mContext.getResources().getDimensionPixelSize(R.dimen.hint_grow_amount_sideways);
105         mFlingAnimationUtils = new FlingAnimationUtils(mContext.getResources().getDisplayMetrics(),
106                 0.4f);
107     }
108 
initIcons()109     private void initIcons() {
110         mLeftIcon = mCallback.getLeftIcon();
111         mRightIcon = mCallback.getRightIcon();
112         updatePreviews();
113     }
114 
updatePreviews()115     public void updatePreviews() {
116         mLeftIcon.setPreviewView(mCallback.getLeftPreview());
117         mRightIcon.setPreviewView(mCallback.getRightPreview());
118     }
119 
onTouchEvent(MotionEvent event)120     public boolean onTouchEvent(MotionEvent event) {
121         int action = event.getActionMasked();
122         if (mMotionCancelled && action != MotionEvent.ACTION_DOWN) {
123             return false;
124         }
125         final float y = event.getY();
126         final float x = event.getX();
127 
128         boolean isUp = false;
129         switch (action) {
130             case MotionEvent.ACTION_DOWN:
131                 View targetView = getIconAtPosition(x, y);
132                 if (targetView == null || (mTargetedView != null && mTargetedView != targetView)) {
133                     mMotionCancelled = true;
134                     return false;
135                 }
136                 if (mTargetedView != null) {
137                     cancelAnimation();
138                 } else {
139                     mTouchSlopExeeded = false;
140                 }
141                 startSwiping(targetView);
142                 mInitialTouchX = x;
143                 mInitialTouchY = y;
144                 mTranslationOnDown = mTranslation;
145                 initVelocityTracker();
146                 trackMovement(event);
147                 mMotionCancelled = false;
148                 break;
149             case MotionEvent.ACTION_POINTER_DOWN:
150                 mMotionCancelled = true;
151                 endMotion(true /* forceSnapBack */, x, y);
152                 break;
153             case MotionEvent.ACTION_MOVE:
154                 trackMovement(event);
155                 float xDist = x - mInitialTouchX;
156                 float yDist = y - mInitialTouchY;
157                 float distance = (float) Math.hypot(xDist, yDist);
158                 if (!mTouchSlopExeeded && distance > mTouchSlop) {
159                     mTouchSlopExeeded = true;
160                 }
161                 if (mSwipingInProgress) {
162                     if (mTargetedView == mRightIcon) {
163                         distance = mTranslationOnDown - distance;
164                         distance = Math.min(0, distance);
165                     } else {
166                         distance = mTranslationOnDown + distance;
167                         distance = Math.max(0, distance);
168                     }
169                     setTranslation(distance, false /* isReset */, false /* animateReset */);
170                 }
171                 break;
172 
173             case MotionEvent.ACTION_UP:
174                 isUp = true;
175             case MotionEvent.ACTION_CANCEL:
176                 boolean hintOnTheRight = mTargetedView == mRightIcon;
177                 trackMovement(event);
178                 endMotion(!isUp, x, y);
179                 if (!mTouchSlopExeeded && isUp) {
180                     mCallback.onIconClicked(hintOnTheRight);
181                 }
182                 break;
183         }
184         return true;
185     }
186 
startSwiping(View targetView)187     private void startSwiping(View targetView) {
188         mCallback.onSwipingStarted(targetView == mRightIcon);
189         mSwipingInProgress = true;
190         mTargetedView = targetView;
191     }
192 
getIconAtPosition(float x, float y)193     private View getIconAtPosition(float x, float y) {
194         if (leftSwipePossible() && isOnIcon(mLeftIcon, x, y)) {
195             return mLeftIcon;
196         }
197         if (rightSwipePossible() && isOnIcon(mRightIcon, x, y)) {
198             return mRightIcon;
199         }
200         return null;
201     }
202 
isOnAffordanceIcon(float x, float y)203     public boolean isOnAffordanceIcon(float x, float y) {
204         return isOnIcon(mLeftIcon, x, y) || isOnIcon(mRightIcon, x, y);
205     }
206 
isOnIcon(View icon, float x, float y)207     private boolean isOnIcon(View icon, float x, float y) {
208         float iconX = icon.getX() + icon.getWidth() / 2.0f;
209         float iconY = icon.getY() + icon.getHeight() / 2.0f;
210         double distance = Math.hypot(x - iconX, y - iconY);
211         return distance <= mTouchTargetSize / 2;
212     }
213 
endMotion(boolean forceSnapBack, float lastX, float lastY)214     private void endMotion(boolean forceSnapBack, float lastX, float lastY) {
215         if (mSwipingInProgress) {
216             flingWithCurrentVelocity(forceSnapBack, lastX, lastY);
217         } else {
218             mTargetedView = null;
219         }
220         if (mVelocityTracker != null) {
221             mVelocityTracker.recycle();
222             mVelocityTracker = null;
223         }
224     }
225 
rightSwipePossible()226     private boolean rightSwipePossible() {
227         return mRightIcon.getVisibility() == View.VISIBLE;
228     }
229 
leftSwipePossible()230     private boolean leftSwipePossible() {
231         return mLeftIcon.getVisibility() == View.VISIBLE;
232     }
233 
onInterceptTouchEvent(MotionEvent ev)234     public boolean onInterceptTouchEvent(MotionEvent ev) {
235         return false;
236     }
237 
startHintAnimation(boolean right, Runnable onFinishedListener)238     public void startHintAnimation(boolean right,
239             Runnable onFinishedListener) {
240         cancelAnimation();
241         startHintAnimationPhase1(right, onFinishedListener);
242     }
243 
startHintAnimationPhase1(final boolean right, final Runnable onFinishedListener)244     private void startHintAnimationPhase1(final boolean right, final Runnable onFinishedListener) {
245         final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
246         ValueAnimator animator = getAnimatorToRadius(right, mHintGrowAmount);
247         animator.addListener(new AnimatorListenerAdapter() {
248             private boolean mCancelled;
249 
250             @Override
251             public void onAnimationCancel(Animator animation) {
252                 mCancelled = true;
253             }
254 
255             @Override
256             public void onAnimationEnd(Animator animation) {
257                 if (mCancelled) {
258                     mSwipeAnimator = null;
259                     mTargetedView = null;
260                     onFinishedListener.run();
261                 } else {
262                     startUnlockHintAnimationPhase2(right, onFinishedListener);
263                 }
264             }
265         });
266         animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
267         animator.setDuration(HINT_PHASE1_DURATION);
268         animator.start();
269         mSwipeAnimator = animator;
270         mTargetedView = targetView;
271     }
272 
273     /**
274      * Phase 2: Move back.
275      */
startUnlockHintAnimationPhase2(boolean right, final Runnable onFinishedListener)276     private void startUnlockHintAnimationPhase2(boolean right, final Runnable onFinishedListener) {
277         ValueAnimator animator = getAnimatorToRadius(right, 0);
278         animator.addListener(new AnimatorListenerAdapter() {
279             @Override
280             public void onAnimationEnd(Animator animation) {
281                 mSwipeAnimator = null;
282                 mTargetedView = null;
283                 onFinishedListener.run();
284             }
285         });
286         animator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
287         animator.setDuration(HINT_PHASE2_DURATION);
288         animator.setStartDelay(HINT_CIRCLE_OPEN_DURATION);
289         animator.start();
290         mSwipeAnimator = animator;
291     }
292 
getAnimatorToRadius(final boolean right, int radius)293     private ValueAnimator getAnimatorToRadius(final boolean right, int radius) {
294         final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
295         ValueAnimator animator = ValueAnimator.ofFloat(targetView.getCircleRadius(), radius);
296         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
297             @Override
298             public void onAnimationUpdate(ValueAnimator animation) {
299                 float newRadius = (float) animation.getAnimatedValue();
300                 targetView.setCircleRadiusWithoutAnimation(newRadius);
301                 float translation = getTranslationFromRadius(newRadius);
302                 mTranslation = right ? -translation : translation;
303                 updateIconsFromTranslation(targetView);
304             }
305         });
306         return animator;
307     }
308 
cancelAnimation()309     private void cancelAnimation() {
310         if (mSwipeAnimator != null) {
311             mSwipeAnimator.cancel();
312         }
313     }
314 
flingWithCurrentVelocity(boolean forceSnapBack, float lastX, float lastY)315     private void flingWithCurrentVelocity(boolean forceSnapBack, float lastX, float lastY) {
316         float vel = getCurrentVelocity(lastX, lastY);
317 
318         // We snap back if the current translation is not far enough
319         boolean snapBack = false;
320         if (mCallback.needsAntiFalsing()) {
321             snapBack = snapBack || mFalsingManager.isFalseTouch(
322                     mTargetedView == mRightIcon
323                             ? Classifier.RIGHT_AFFORDANCE : Classifier.LEFT_AFFORDANCE);
324         }
325         snapBack = snapBack || isBelowFalsingThreshold();
326 
327         // or if the velocity is in the opposite direction.
328         boolean velIsInWrongDirection = vel * mTranslation < 0;
329         snapBack |= Math.abs(vel) > mMinFlingVelocity && velIsInWrongDirection;
330         vel = snapBack ^ velIsInWrongDirection ? 0 : vel;
331         fling(vel, snapBack || forceSnapBack, mTranslation < 0);
332     }
333 
isBelowFalsingThreshold()334     private boolean isBelowFalsingThreshold() {
335         return Math.abs(mTranslation) < Math.abs(mTranslationOnDown) + getMinTranslationAmount();
336     }
337 
getMinTranslationAmount()338     private int getMinTranslationAmount() {
339         float factor = mCallback.getAffordanceFalsingFactor();
340         return (int) (mMinTranslationAmount * factor);
341     }
342 
fling(float vel, final boolean snapBack, boolean right)343     private void fling(float vel, final boolean snapBack, boolean right) {
344         float target = right ? -mCallback.getMaxTranslationDistance()
345                 : mCallback.getMaxTranslationDistance();
346         target = snapBack ? 0 : target;
347 
348         ValueAnimator animator = ValueAnimator.ofFloat(mTranslation, target);
349         mFlingAnimationUtils.apply(animator, mTranslation, target, vel);
350         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
351             @Override
352             public void onAnimationUpdate(ValueAnimator animation) {
353                 mTranslation = (float) animation.getAnimatedValue();
354             }
355         });
356         animator.addListener(mFlingEndListener);
357         if (!snapBack) {
358             startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable, right);
359             mCallback.onAnimationToSideStarted(right, mTranslation, vel);
360         } else {
361             reset(true);
362         }
363         animator.start();
364         mSwipeAnimator = animator;
365         if (snapBack) {
366             mCallback.onSwipingAborted();
367         }
368     }
369 
startFinishingCircleAnimation(float velocity, Runnable animationEndRunnable, boolean right)370     private void startFinishingCircleAnimation(float velocity, Runnable animationEndRunnable,
371             boolean right) {
372         KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
373         targetView.finishAnimation(velocity, animationEndRunnable);
374     }
375 
setTranslation(float translation, boolean isReset, boolean animateReset)376     private void setTranslation(float translation, boolean isReset, boolean animateReset) {
377         translation = rightSwipePossible() ? translation : Math.max(0, translation);
378         translation = leftSwipePossible() ? translation : Math.min(0, translation);
379         float absTranslation = Math.abs(translation);
380         if (translation != mTranslation || isReset) {
381             KeyguardAffordanceView targetView = translation > 0 ? mLeftIcon : mRightIcon;
382             KeyguardAffordanceView otherView = translation > 0 ? mRightIcon : mLeftIcon;
383             float alpha = absTranslation / getMinTranslationAmount();
384 
385             // We interpolate the alpha of the other icons to 0
386             float fadeOutAlpha = 1.0f - alpha;
387             fadeOutAlpha = Math.max(fadeOutAlpha, 0.0f);
388 
389             boolean animateIcons = isReset && animateReset;
390             boolean forceNoCircleAnimation = isReset && !animateReset;
391             float radius = getRadiusFromTranslation(absTranslation);
392             boolean slowAnimation = isReset && isBelowFalsingThreshold();
393             if (!isReset) {
394                 updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(),
395                         false, false, false, false);
396             } else {
397                 updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(),
398                         animateIcons, slowAnimation, true /* isReset */, forceNoCircleAnimation);
399             }
400             updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(),
401                     animateIcons, slowAnimation, isReset, forceNoCircleAnimation);
402 
403             mTranslation = translation;
404         }
405     }
406 
updateIconsFromTranslation(KeyguardAffordanceView targetView)407     private void updateIconsFromTranslation(KeyguardAffordanceView targetView) {
408         float absTranslation = Math.abs(mTranslation);
409         float alpha = absTranslation / getMinTranslationAmount();
410 
411         // We interpolate the alpha of the other icons to 0
412         float fadeOutAlpha =  1.0f - alpha;
413         fadeOutAlpha = Math.max(0.0f, fadeOutAlpha);
414 
415         // We interpolate the alpha of the targetView to 1
416         KeyguardAffordanceView otherView = targetView == mRightIcon ? mLeftIcon : mRightIcon;
417         updateIconAlpha(targetView, alpha + fadeOutAlpha * targetView.getRestingAlpha(), false);
418         updateIconAlpha(otherView, fadeOutAlpha * otherView.getRestingAlpha(), false);
419     }
420 
getTranslationFromRadius(float circleSize)421     private float getTranslationFromRadius(float circleSize) {
422         float translation = (circleSize - mMinBackgroundRadius)
423                 / BACKGROUND_RADIUS_SCALE_FACTOR;
424         return translation > 0.0f ? translation + mTouchSlop : 0.0f;
425     }
426 
getRadiusFromTranslation(float translation)427     private float getRadiusFromTranslation(float translation) {
428         if (translation <= mTouchSlop) {
429             return 0.0f;
430         }
431         return (translation - mTouchSlop)  * BACKGROUND_RADIUS_SCALE_FACTOR + mMinBackgroundRadius;
432     }
433 
animateHideLeftRightIcon()434     public void animateHideLeftRightIcon() {
435         cancelAnimation();
436         updateIcon(mRightIcon, 0f, 0f, true, false, false, false);
437         updateIcon(mLeftIcon, 0f, 0f, true, false, false, false);
438     }
439 
updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha, boolean animate, boolean slowRadiusAnimation, boolean force, boolean forceNoCircleAnimation)440     private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha,
441                             boolean animate, boolean slowRadiusAnimation, boolean force,
442                             boolean forceNoCircleAnimation) {
443         if (view.getVisibility() != View.VISIBLE && !force) {
444             return;
445         }
446         if (forceNoCircleAnimation) {
447             view.setCircleRadiusWithoutAnimation(circleRadius);
448         } else {
449             view.setCircleRadius(circleRadius, slowRadiusAnimation);
450         }
451         updateIconAlpha(view, alpha, animate);
452     }
453 
updateIconAlpha(KeyguardAffordanceView view, float alpha, boolean animate)454     private void updateIconAlpha(KeyguardAffordanceView view, float alpha, boolean animate) {
455         float scale = getScale(alpha, view);
456         alpha = Math.min(1.0f, alpha);
457         view.setImageAlpha(alpha, animate);
458         view.setImageScale(scale, animate);
459     }
460 
getScale(float alpha, KeyguardAffordanceView icon)461     private float getScale(float alpha, KeyguardAffordanceView icon) {
462         float scale = alpha / icon.getRestingAlpha() * 0.2f +
463                 KeyguardAffordanceView.MIN_ICON_SCALE_AMOUNT;
464         return Math.min(scale, KeyguardAffordanceView.MAX_ICON_SCALE_AMOUNT);
465     }
466 
trackMovement(MotionEvent event)467     private void trackMovement(MotionEvent event) {
468         if (mVelocityTracker != null) {
469             mVelocityTracker.addMovement(event);
470         }
471     }
472 
initVelocityTracker()473     private void initVelocityTracker() {
474         if (mVelocityTracker != null) {
475             mVelocityTracker.recycle();
476         }
477         mVelocityTracker = VelocityTracker.obtain();
478     }
479 
getCurrentVelocity(float lastX, float lastY)480     private float getCurrentVelocity(float lastX, float lastY) {
481         if (mVelocityTracker == null) {
482             return 0;
483         }
484         mVelocityTracker.computeCurrentVelocity(1000);
485         float aX = mVelocityTracker.getXVelocity();
486         float aY = mVelocityTracker.getYVelocity();
487         float bX = lastX - mInitialTouchX;
488         float bY = lastY - mInitialTouchY;
489         float bLen = (float) Math.hypot(bX, bY);
490         // Project the velocity onto the distance vector: a * b / |b|
491         float projectedVelocity = (aX * bX + aY * bY) / bLen;
492         if (mTargetedView == mRightIcon) {
493             projectedVelocity = -projectedVelocity;
494         }
495         return projectedVelocity;
496     }
497 
onConfigurationChanged()498     public void onConfigurationChanged() {
499         initDimens();
500         initIcons();
501     }
502 
onRtlPropertiesChanged()503     public void onRtlPropertiesChanged() {
504         initIcons();
505     }
506 
reset(boolean animate)507     public void reset(boolean animate) {
508         cancelAnimation();
509         setTranslation(0.0f, true /* isReset */, animate);
510         mMotionCancelled = true;
511         if (mSwipingInProgress) {
512             mCallback.onSwipingAborted();
513             mSwipingInProgress = false;
514         }
515     }
516 
isSwipingInProgress()517     public boolean isSwipingInProgress() {
518         return mSwipingInProgress;
519     }
520 
launchAffordance(boolean animate, boolean left)521     public void launchAffordance(boolean animate, boolean left) {
522         if (mSwipingInProgress) {
523             // We don't want to mess with the state if the user is actually swiping already.
524             return;
525         }
526         KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon;
527         KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon;
528         startSwiping(targetView);
529 
530         // Do not animate the circle expanding if the affordance isn't visible,
531         // otherwise the circle will be meaningless.
532         if (targetView.getVisibility() != View.VISIBLE) {
533             animate = false;
534         }
535 
536         if (animate) {
537             fling(0, false, !left);
538             updateIcon(otherView, 0.0f, 0, true, false, true, false);
539         } else {
540             mCallback.onAnimationToSideStarted(!left, mTranslation, 0);
541             mTranslation = left ? mCallback.getMaxTranslationDistance()
542                     : mCallback.getMaxTranslationDistance();
543             updateIcon(otherView, 0.0f, 0.0f, false, false, true, false);
544             targetView.instantFinishAnimation();
545             mFlingEndListener.onAnimationEnd(null);
546             mAnimationEndRunnable.run();
547         }
548     }
549 
550     public interface Callback {
551 
552         /**
553          * Notifies the callback when an animation to a side page was started.
554          *
555          * @param rightPage Is the page animated to the right page?
556          */
onAnimationToSideStarted(boolean rightPage, float translation, float vel)557         void onAnimationToSideStarted(boolean rightPage, float translation, float vel);
558 
559         /**
560          * Notifies the callback the animation to a side page has ended.
561          */
onAnimationToSideEnded()562         void onAnimationToSideEnded();
563 
getMaxTranslationDistance()564         float getMaxTranslationDistance();
565 
onSwipingStarted(boolean rightIcon)566         void onSwipingStarted(boolean rightIcon);
567 
onSwipingAborted()568         void onSwipingAborted();
569 
onIconClicked(boolean rightIcon)570         void onIconClicked(boolean rightIcon);
571 
getLeftIcon()572         KeyguardAffordanceView getLeftIcon();
573 
getRightIcon()574         KeyguardAffordanceView getRightIcon();
575 
getLeftPreview()576         View getLeftPreview();
577 
getRightPreview()578         View getRightPreview();
579 
580         /**
581          * @return The factor the minimum swipe amount should be multiplied with.
582          */
getAffordanceFalsingFactor()583         float getAffordanceFalsingFactor();
584 
needsAntiFalsing()585         boolean needsAntiFalsing();
586     }
587 }
588