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

Commit 58136d02 authored by Jorim Jaggi's avatar Jorim Jaggi Committed by Android (Google) Code Review
Browse files

Merge "Implement unlock hint." into lmp-preview-dev

parents becab9a7 90129587
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -318,4 +318,7 @@


    <!-- Volume panel z depth -->
    <!-- Volume panel z depth -->
    <dimen name="volume_panel_z">3dp</dimen>
    <dimen name="volume_panel_z">3dp</dimen>

    <!-- Move distance for the hint animations on the lockscreen (unlock, phone, camera)-->
    <dimen name="hint_move_distance">75dp</dimen>
</resources>
</resources>
+43 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2014 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.statusbar.phone;

import android.view.animation.Interpolator;

/**
 * An implementation of a bouncer interpolator optimized for unlock hinting.
 */
public class BounceInterpolator implements Interpolator {

    private final static float SCALE_FACTOR = 7.5625f;

    @Override
    public float getInterpolation(float t) {
        if (t < 4f / 11f) {
            return SCALE_FACTOR * t * t;
        } else if (t < 8f / 11f) {
            float t2 = t - 6f / 11f;
            return SCALE_FACTOR * t2 * t2 + 3f / 4f;
        } else if (t < 10f / 11f) {
            float t2 = t - 9f / 11f;
            return SCALE_FACTOR * t2 * t2 + 15f / 16f;
        } else {
            float t2 = t - 21f / 22f;
            return SCALE_FACTOR * t2 * t2 + 63f / 64f;
        }
    }
}
+0 −1
Original line number Original line Diff line number Diff line
@@ -51,7 +51,6 @@ public class NotificationPanelView extends PanelView implements
    private static float EXPANSION_RUBBER_BAND_EXTRA_FACTOR = 0.6f;
    private static float EXPANSION_RUBBER_BAND_EXTRA_FACTOR = 0.6f;


    private KeyguardPageSwipeHelper mPageSwiper;
    private KeyguardPageSwipeHelper mPageSwiper;
    PhoneStatusBar mStatusBar;
    private StatusBarHeaderView mHeader;
    private StatusBarHeaderView mHeader;
    private View mQsContainer;
    private View mQsContainer;
    private View mQsPanel;
    private View mQsPanel;
+133 −23
Original line number Original line Diff line number Diff line
@@ -27,10 +27,13 @@ import android.util.AttributeSet;
import android.util.Log;
import android.util.Log;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.FrameLayout;


import com.android.systemui.R;
import com.android.systemui.R;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;


import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
@@ -44,13 +47,16 @@ public abstract class PanelView extends FrameLayout {
        Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
        Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
    }
    }


    protected PhoneStatusBar mStatusBar;
    private float mPeekHeight;
    private float mPeekHeight;
    private float mHintDistance;
    private float mInitialOffsetOnTouch;
    private float mInitialOffsetOnTouch;
    private float mExpandedFraction = 0;
    private float mExpandedFraction = 0;
    private float mExpandedHeight = 0;
    private float mExpandedHeight = 0;
    private boolean mJustPeeked;
    private boolean mJustPeeked;
    private boolean mClosing;
    private boolean mClosing;
    private boolean mTracking;
    private boolean mTracking;
    private boolean mTouchSlopExceeded;
    private int mTrackingPointer;
    private int mTrackingPointer;
    protected int mTouchSlop;
    protected int mTouchSlop;


@@ -66,6 +72,9 @@ public abstract class PanelView extends FrameLayout {
    private float mInitialTouchY;
    private float mInitialTouchY;
    private float mInitialTouchX;
    private float mInitialTouchX;


    private Interpolator mLinearOutSlowInInterpolator;
    private Interpolator mBounceInterpolator;

    protected void onExpandingFinished() {
    protected void onExpandingFinished() {
        mBar.onExpandingFinished();
        mBar.onExpandingFinished();
    }
    }
@@ -89,6 +98,9 @@ public abstract class PanelView extends FrameLayout {
    public PanelView(Context context, AttributeSet attrs) {
    public PanelView(Context context, AttributeSet attrs) {
        super(context, attrs);
        super(context, attrs);
        mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f);
        mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f);
        mLinearOutSlowInInterpolator =
                AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
        mBounceInterpolator = new BounceInterpolator();
    }
    }


    protected void loadDimens() {
    protected void loadDimens() {
@@ -98,6 +110,7 @@ public abstract class PanelView extends FrameLayout {


        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
        mTouchSlop = configuration.getScaledTouchSlop();
        mTouchSlop = configuration.getScaledTouchSlop();
        mHintDistance = res.getDimension(R.dimen.hint_move_distance);
    }
    }


    private void trackMovement(MotionEvent event) {
    private void trackMovement(MotionEvent event) {
@@ -138,6 +151,7 @@ public abstract class PanelView extends FrameLayout {
                mInitialTouchY = y;
                mInitialTouchY = y;
                mInitialTouchX = x;
                mInitialTouchX = x;
                mInitialOffsetOnTouch = mExpandedHeight;
                mInitialOffsetOnTouch = mExpandedHeight;
                mTouchSlopExceeded = false;
                if (mVelocityTracker == null) {
                if (mVelocityTracker == null) {
                    initVelocityTracker();
                    initVelocityTracker();
                }
                }
@@ -170,8 +184,9 @@ public abstract class PanelView extends FrameLayout {


            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_MOVE:
                float h = y - mInitialTouchY;
                float h = y - mInitialTouchY;
                if (waitForTouchSlop && !mTracking && Math.abs(h) > mTouchSlop
                if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX)) {
                        && Math.abs(h) > Math.abs(x - mInitialTouchX)) {
                    mTouchSlopExceeded = true;
                    if (waitForTouchSlop && !mTracking) {
                        mInitialOffsetOnTouch = mExpandedHeight;
                        mInitialOffsetOnTouch = mExpandedHeight;
                        mInitialTouchX = x;
                        mInitialTouchX = x;
                        mInitialTouchY = y;
                        mInitialTouchY = y;
@@ -181,6 +196,7 @@ public abstract class PanelView extends FrameLayout {
                        onTrackingStarted();
                        onTrackingStarted();
                        h = 0;
                        h = 0;
                    }
                    }
                }
                final float newHeight = h + mInitialOffsetOnTouch;
                final float newHeight = h + mInitialOffsetOnTouch;
                if (newHeight > mPeekHeight) {
                if (newHeight > mPeekHeight) {
                    if (mPeekAnimator != null && mPeekAnimator.isStarted()) {
                    if (mPeekAnimator != null && mPeekAnimator.isStarted()) {
@@ -200,10 +216,15 @@ public abstract class PanelView extends FrameLayout {
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_CANCEL:
                mTrackingPointer = -1;
                mTrackingPointer = -1;
                trackMovement(event);
                trackMovement(event);
                if (mTracking && mTouchSlopExceeded) {
                    float vel = getCurrentVelocity();
                    float vel = getCurrentVelocity();
                    boolean expand = flingExpands(vel);
                    boolean expand = flingExpands(vel);
                    onTrackingStopped(expand);
                    onTrackingStopped(expand);
                    fling(vel, expand);
                    fling(vel, expand);
                } else {
                    boolean expands = onEmptySpaceClick();
                    onTrackingStopped(expands);
                }
                if (mVelocityTracker != null) {
                if (mVelocityTracker != null) {
                    mVelocityTracker.recycle();
                    mVelocityTracker.recycle();
                    mVelocityTracker = null;
                    mVelocityTracker = null;
@@ -264,6 +285,7 @@ public abstract class PanelView extends FrameLayout {
                }
                }
                mInitialTouchY = y;
                mInitialTouchY = y;
                mInitialTouchX = x;
                mInitialTouchX = x;
                mTouchSlopExceeded = false;
                initVelocityTracker();
                initVelocityTracker();
                trackMovement(event);
                trackMovement(event);
                break;
                break;
@@ -287,6 +309,7 @@ public abstract class PanelView extends FrameLayout {
                        mInitialTouchY = y;
                        mInitialTouchY = y;
                        mInitialTouchX = x;
                        mInitialTouchX = x;
                        mTracking = true;
                        mTracking = true;
                        mTouchSlopExceeded = true;
                        onTrackingStarted();
                        onTrackingStarted();
                        return true;
                        return true;
                    }
                    }
@@ -344,7 +367,7 @@ public abstract class PanelView extends FrameLayout {
            mBar.panelExpansionChanged(this, mExpandedFraction);
            mBar.panelExpansionChanged(this, mExpandedFraction);
            return;
            return;
        }
        }
        ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, target);
        ValueAnimator animator = createHeightAnimator(target);
        if (expand) {
        if (expand) {
            mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
            mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
        } else {
        } else {
@@ -356,12 +379,6 @@ public abstract class PanelView extends FrameLayout {
                animator.setDuration((long) (animator.getDuration() / 1.75f));
                animator.setDuration((long) (animator.getDuration() / 1.75f));
            }
            }
        }
        }
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                setExpandedHeight((Float) animation.getAnimatedValue());
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            @Override
            public void onAnimationEnd(Animator animation) {
            public void onAnimationEnd(Animator animation) {
@@ -449,9 +466,7 @@ public abstract class PanelView extends FrameLayout {
        mOverExpansion = overExpansion;
        mOverExpansion = overExpansion;
    }
    }


    protected void onHeightUpdated(float expandedHeight) {
    protected abstract void onHeightUpdated(float expandedHeight);
        requestLayout();
    }


    /**
    /**
     * This returns the maximum height of the panel. Children should override this if their
     * This returns the maximum height of the panel. Children should override this if their
@@ -526,6 +541,101 @@ public abstract class PanelView extends FrameLayout {
        }
        }
    }
    }


    protected void startUnlockHintAnimation() {

        // We don't need to hint the user if an animation is already running or the user is changing
        // the expansion.
        if (mHeightAnimator != null || mTracking) {
            return;
        }
        cancelPeek();
        onExpandingStarted();
        startUnlockHintAnimationPhase1();
        mStatusBar.onUnlockHintStarted();
    }

    /**
     * Phase 1: Move everything upwards.
     */
    private void startUnlockHintAnimationPhase1() {
        float target = Math.max(0, getMaxPanelHeight() - mHintDistance);
        ValueAnimator animator = createHeightAnimator(target);
        animator.setDuration(250);
        animator.setInterpolator(mLinearOutSlowInInterpolator);
        animator.addListener(new AnimatorListenerAdapter() {
            private boolean mCancelled;

            @Override
            public void onAnimationCancel(Animator animation) {
                mCancelled = true;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (mCancelled) {
                    mHeightAnimator = null;
                    onExpandingFinished();
                    mStatusBar.onUnlockHintFinished();
                } else {
                    startUnlockHintAnimationPhase2();
                }
            }
        });
        animator.start();
        mHeightAnimator = animator;
    }

    /**
     * Phase 2: Bounce down.
     */
    private void startUnlockHintAnimationPhase2() {
        ValueAnimator animator = createHeightAnimator(getMaxPanelHeight());
        animator.setDuration(450);
        animator.setInterpolator(mBounceInterpolator);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mHeightAnimator = null;
                onExpandingFinished();
                mStatusBar.onUnlockHintFinished();
            }
        });
        animator.start();
        mHeightAnimator = animator;
    }

    private ValueAnimator createHeightAnimator(float targetHeight) {
        ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                setExpandedHeight((Float) animation.getAnimatedValue());
            }
        });
        return animator;
    }

    /**
     * Gets called when the user performs a click anywhere in the empty area of the panel.
     *
     * @return whether the panel will be expanded after the action performed by this method
     */
    private boolean onEmptySpaceClick() {
        switch (mStatusBar.getBarState()) {
            case StatusBarState.KEYGUARD:
                startUnlockHintAnimation();
                return true;
            case StatusBarState.SHADE_LOCKED:
                // TODO: Go to Keyguard again.
                return true;
            case StatusBarState.SHADE:
                collapse();
                return false;
            default:
                return true;
        }
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
        pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
                + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
                + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
+8 −6
Original line number Original line Diff line number Diff line
@@ -2957,15 +2957,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    }
    }


    public void onTrackingStarted() {
    public void onTrackingStarted() {
        if (mState == StatusBarState.KEYGUARD) {
            mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock);
    }
    }

    public void onUnlockHintStarted() {
        mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock);
    }
    }


    public void onTrackingStopped(boolean expand) {
    public void onUnlockHintFinished() {
        if (mState == StatusBarState.KEYGUARD) {
        mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
        mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
    }
    }

    public void onTrackingStopped(boolean expand) {
        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
            if (!expand && !mUnlockMethodCache.isMethodInsecure()) {
            if (!expand && !mUnlockMethodCache.isMethodInsecure()) {
                showBouncer();
                showBouncer();
Loading