1a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn/*
2a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * Copyright (C) 2012 The Android Open Source Project
3a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn *
4a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * you may not use this file except in compliance with the License.
6a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * You may obtain a copy of the License at
7a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn *
8a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn *
10a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * Unless required by applicable law or agreed to in writing, software
11a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * See the License for the specific language governing permissions and
14a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn * limitations under the License.
15a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn */
16a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
17a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornpackage com.android.systemui;
18a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
19a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.app.ActivityManager;
20a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.content.Context;
21a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.content.res.Configuration;
22a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.content.res.Resources;
23a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.graphics.Matrix;
24a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.graphics.PixelFormat;
25a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.os.RemoteException;
26a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.util.Log;
27a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.util.Slog;
28a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.Choreographer;
29a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.Display;
30a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.IWindowSession;
31a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.MotionEvent;
32a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.VelocityTracker;
33a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.View;
34a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.ViewRootImpl;
35a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.WindowManager;
3698365d7663cbd82979a5700faf0050220b01084dJeff Brownimport android.view.WindowManagerGlobal;
37a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.view.animation.Transformation;
38a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornimport android.widget.FrameLayout;
39a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
40a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackbornpublic class UniverseBackground extends FrameLayout {
41a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    static final String TAG = "UniverseBackground";
42a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    static final boolean SPEW = false;
43a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    static final boolean CHATTY = false;
44a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
45a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    final IWindowSession mSession;
46a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    final View mContent;
47a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    final View mBottomAnchor;
48a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
49a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    final Runnable mAnimationCallback = new Runnable() {
50a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        @Override
51a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        public void run() {
52a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            doAnimation(mChoreographer.getFrameTimeNanos());
53a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
54a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    };
55a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
56a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    // fling gesture tuning parameters, scaled to display density
57a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mSelfExpandVelocityPx; // classic value: 2000px/s
58a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
59a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mFlingExpandMinVelocityPx; // classic value: 200px/s
60a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
61a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
62a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
63a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
64a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
65a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mExpandAccelPx; // classic value: 2000px/s/s
66a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
67a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
68a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    static final int STATE_CLOSED = 0;
69a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    static final int STATE_OPENING = 1;
70a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    static final int STATE_OPEN = 2;
71a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private int mState = STATE_CLOSED;
72a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
73a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mDragStartX, mDragStartY;
74a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mAverageX, mAverageY;
75a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
76a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    // position
77a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private int[] mPositionTmp = new int[2];
78a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private boolean mExpanded;
79a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private boolean mExpandedVisible;
80a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
81a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private boolean mTracking;
82a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private VelocityTracker mVelocityTracker;
83a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
84a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private Choreographer mChoreographer;
85a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private boolean mAnimating;
86a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
87a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mAnimY;
88a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mAnimVel;
89a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private float mAnimAccel;
90a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private long mAnimLastTimeNanos;
91a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private boolean mAnimatingReveal = false;
92a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
93a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private int mYDelta = 0;
94a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private Transformation mUniverseTransform = new Transformation();
95a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private final float[] mTmpFloats = new float[9];
96a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
97a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    public UniverseBackground(Context context) {
98a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        super(context);
99a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        setBackgroundColor(0xff000000);
100f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown        mSession = WindowManagerGlobal.getWindowSession();
101a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mContent = View.inflate(context, R.layout.universe, null);
102a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        addView(mContent);
103a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mContent.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
104a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            @Override public void onClick(View v) {
105a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                animateCollapse();
106a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
107a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        });
108a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mBottomAnchor = mContent.findViewById(R.id.bottom);
109a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mChoreographer = Choreographer.getInstance();
110a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        loadDimens();
111a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
112a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
113a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    @Override
114a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    protected void onConfigurationChanged(Configuration newConfig) {
115a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        super.onConfigurationChanged(newConfig);
116a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        loadDimens();
117a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
118a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
119a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private void loadDimens() {
120a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        final Resources res = getContext().getResources();
121a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
122a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
123a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
124a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
125a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
126a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
127a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
128a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
129a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
130a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
131a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
132a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
133a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
134a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
135a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private void computeAveragePos(MotionEvent event) {
136a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        final int num = event.getPointerCount();
137a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        float x = 0, y = 0;
138a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        for (int i=0; i<num; i++) {
139a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            x += event.getX(i);
140a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            y += event.getY(i);
141a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
142a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAverageX = x / num;
143a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAverageY = y / num;
144a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
145a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
146a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private void sendUniverseTransform() {
147a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (getWindowToken() != null) {
148a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mUniverseTransform.getMatrix().getValues(mTmpFloats);
149a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            try {
150a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mSession.setUniverseTransform(getWindowToken(), mUniverseTransform.getAlpha(),
151a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y],
152a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
153a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
154a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            } catch (RemoteException e) {
155a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
156a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
157a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
158a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
15998365d7663cbd82979a5700faf0050220b01084dJeff Brown    public WindowManager.LayoutParams getLayoutParams() {
160a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
161a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
162a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND,
163a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    0
164a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
165a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
166a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
167a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                PixelFormat.OPAQUE);
168a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        // this will allow the window to run in an overlay on devices that support this
16998365d7663cbd82979a5700faf0050220b01084dJeff Brown        if (ActivityManager.isHighEndGfx()) {
170a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
171a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
172a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        lp.setTitle("UniverseBackground");
173a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        lp.windowAnimations = 0;
174a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        return lp;
175a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
176a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
177a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private int getExpandedViewMaxHeight() {
178a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        return mBottomAnchor.getTop();
179a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
180a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
181a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    public void animateCollapse() {
182a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        animateCollapse(1.0f);
183a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
184a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
185a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    public void animateCollapse(float velocityMultiplier) {
186a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (SPEW) {
187a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
188a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    + " mExpandedVisible=" + mExpandedVisible
189a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    + " mExpanded=" + mExpanded
190a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    + " mAnimating=" + mAnimating
191a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    + " mAnimY=" + mAnimY
192a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    + " mAnimVel=" + mAnimVel);
193a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
194a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
195a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mState = STATE_CLOSED;
196a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (!mExpandedVisible) {
197a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            return;
198a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
199a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
200a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        int y;
201a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (mAnimating) {
202a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            y = (int)mAnimY;
203a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        } else {
204a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            y = getExpandedViewMaxHeight()-1;
205a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
206a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        // Let the fling think that we're open so it goes in the right direction
207a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        // and doesn't try to re-open the windowshade.
208a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mExpanded = true;
209a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        prepareTracking(y, false);
210a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        performFling(y, -mSelfCollapseVelocityPx*velocityMultiplier, true);
211a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
212a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
213a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private void updateUniverseScale() {
214a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (mYDelta > 0) {
215a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            int w = getWidth();
216a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            int h = getHeight();
217a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            float scale = (h-mYDelta+.5f) / (float)h;
218a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mUniverseTransform.getMatrix().setScale(scale, scale, w/2, h);
219a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (CHATTY) Log.i(TAG, "w=" + w + " h=" + h + " scale=" + scale
220a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    + ": " + mUniverseTransform);
221a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            sendUniverseTransform();
222a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (getVisibility() != VISIBLE) {
223a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                setVisibility(VISIBLE);
224a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
225a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        } else {
226a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (CHATTY) Log.i(TAG, "mYDelta=" + mYDelta);
227a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mUniverseTransform.clear();
228a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            sendUniverseTransform();
229a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (getVisibility() == VISIBLE) {
230a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                setVisibility(GONE);
231a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
232a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
233a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
234a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
235a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    void resetLastAnimTime() {
236a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAnimLastTimeNanos = System.nanoTime();
237a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (SPEW) {
238a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            Throwable t = new Throwable();
239a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            t.fillInStackTrace();
240a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            Slog.d(TAG, "resetting last anim time=" + mAnimLastTimeNanos, t);
241a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
242a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
243a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
244a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    void doAnimation(long frameTimeNanos) {
245a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (mAnimating) {
246a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (SPEW) Slog.d(TAG, "doAnimation dt=" + (frameTimeNanos - mAnimLastTimeNanos));
247a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
248a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            incrementAnim(frameTimeNanos);
249a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (SPEW) {
250a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                Slog.d(TAG, "doAnimation after  mAnimY=" + mAnimY);
251a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
252a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
253a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (mAnimY >= getExpandedViewMaxHeight()-1 && !mClosing) {
254a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
255a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mAnimating = false;
256a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mYDelta = getExpandedViewMaxHeight();
257a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                updateUniverseScale();
258a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mExpanded = true;
259a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mState = STATE_OPEN;
260a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                return;
261a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
262a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
263a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (mAnimY <= 0 && mClosing) {
264a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
265a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mAnimating = false;
266a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mYDelta = 0;
267a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                updateUniverseScale();
268a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mExpanded = false;
269a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mState = STATE_CLOSED;
270a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                return;
271a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
272a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
273a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mYDelta = (int)mAnimY;
274a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            updateUniverseScale();
275a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
276a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    mAnimationCallback, null);
277a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
278a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
279a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
280a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    void stopTracking() {
281a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mTracking = false;
282a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mVelocityTracker.recycle();
283a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mVelocityTracker = null;
284a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
285a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
286a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    void incrementAnim(long frameTimeNanos) {
287a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
288a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        final float t = deltaNanos * 0.000000001f;                  // ns -> s
289a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        final float y = mAnimY;
290a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        final float v = mAnimVel;                                   // px/s
291a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        final float a = mAnimAccel;                                 // px/s/s
292a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAnimY = y + (v*t) + (0.5f*a*t*t);                          // px
293a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAnimVel = v + (a*t);                                       // px/s
294a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAnimLastTimeNanos = frameTimeNanos;                        // ns
295a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
296a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        //        + " mAnimAccel=" + mAnimAccel);
297a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
298a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
299a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    void prepareTracking(int y, boolean opening) {
300a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (CHATTY) {
301a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
302a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
303a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
304a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mTracking = true;
305a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mVelocityTracker = VelocityTracker.obtain();
306a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (opening) {
307a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mAnimAccel = mExpandAccelPx;
308a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mAnimVel = mFlingExpandMinVelocityPx;
309a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mAnimY = y;
310a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mAnimating = true;
311a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mAnimatingReveal = true;
312a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            resetLastAnimTime();
313a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mExpandedVisible = true;
314a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
315a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (mAnimating) {
316a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mAnimating = false;
317a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
318a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    mAnimationCallback, null);
319a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
320a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
321a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
322a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    void performFling(int y, float vel, boolean always) {
323a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (CHATTY) {
324a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel);
325a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
326a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
327a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAnimatingReveal = false;
328a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
329a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAnimY = y;
330a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAnimVel = vel;
331a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
332a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
333a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
334a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (mExpanded) {
335a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (!always && (
336a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    vel > mFlingCollapseMinVelocityPx
337a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    || (y > (getExpandedViewMaxHeight()*(1f-mCollapseMinDisplayFraction)) &&
338a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        vel > -mFlingExpandMinVelocityPx))) {
339a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                // We are expanded, but they didn't move sufficiently to cause
340a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                // us to retract.  Animate back to the expanded position.
341a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mAnimAccel = mExpandAccelPx;
342a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (vel < 0) {
343a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    mAnimVel = 0;
344a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                }
345a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
346a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            else {
347a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                // We are expanded and are now going to animate away.
348a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mAnimAccel = -mCollapseAccelPx;
349a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (vel > 0) {
350a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    mAnimVel = 0;
351a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                }
352a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
353a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        } else {
354a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (always || (
355a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    vel > mFlingExpandMinVelocityPx
356a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    || (y > (getExpandedViewMaxHeight()*(1f-mExpandMinDisplayFraction)) &&
357a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        vel > -mFlingCollapseMinVelocityPx))) {
358a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                // We are collapsed, and they moved enough to allow us to
359a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                // expand.  Animate in the notifications.
360a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mAnimAccel = mExpandAccelPx;
361a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (vel < 0) {
362a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    mAnimVel = 0;
363a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                }
364a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
365a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            else {
366a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                // We are collapsed, but they didn't move sufficiently to cause
367a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                // us to retract.  Animate back to the collapsed position.
368a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mAnimAccel = -mCollapseAccelPx;
369a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (vel > 0) {
370a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    mAnimVel = 0;
371a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                }
372a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
373a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
374a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
375a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        //        + " mAnimAccel=" + mAnimAccel);
376a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
377a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        resetLastAnimTime();
378a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mAnimating = true;
379a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mClosing = mAnimAccel < 0;
380a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
381a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mAnimationCallback, null);
382a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
383a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mAnimationCallback, null);
384a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
385a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        stopTracking();
386a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
387a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
388a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    private void trackMovement(MotionEvent event) {
389a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        mVelocityTracker.addMovement(event);
390a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
391a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
392a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    public boolean consumeEvent(MotionEvent event) {
393a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (mState == STATE_CLOSED) {
394a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
395a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                // Second finger down, time to start opening!
396a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                computeAveragePos(event);
397a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mDragStartX = mAverageX;
398a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mDragStartY = mAverageY;
399a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mYDelta = 0;
400a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mUniverseTransform.clear();
401a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                sendUniverseTransform();
402a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                setVisibility(VISIBLE);
403a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mState = STATE_OPENING;
404a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                prepareTracking((int)mDragStartY, true);
405a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mVelocityTracker.clear();
406a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                trackMovement(event);
407a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                return true;
408a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
409a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            return false;
410a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
411a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
412a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        if (mState == STATE_OPENING) {
413a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (event.getActionMasked() == MotionEvent.ACTION_UP
414a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
415a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mVelocityTracker.computeCurrentVelocity(1000);
416a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                computeAveragePos(event);
417a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
418a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                float yVel = mVelocityTracker.getYVelocity();
419a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                boolean negative = yVel < 0;
420a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
421a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                float xVel = mVelocityTracker.getXVelocity();
422a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (xVel < 0) {
423a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    xVel = -xVel;
424a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                }
425a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (xVel > mFlingGestureMaxXVelocityPx) {
426a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
427a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                }
428a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
429a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                float vel = (float)Math.hypot(yVel, xVel);
430a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (negative) {
431a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    vel = -vel;
432a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                }
433a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
434a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                if (CHATTY) {
435a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                    Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
436a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        mVelocityTracker.getXVelocity(),
437a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        mVelocityTracker.getYVelocity(),
438a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        xVel, yVel,
439a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                        vel));
440a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                }
441a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
442a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                performFling((int)mAverageY, vel, false);
443a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mState = STATE_OPEN;
444a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                return true;
445a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
446a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
447a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            computeAveragePos(event);
448a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            mYDelta = (int)(mAverageY - mDragStartY);
449a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            if (mYDelta > getExpandedViewMaxHeight()) {
450a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn                mYDelta = getExpandedViewMaxHeight();
451a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            }
452a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            updateUniverseScale();
453a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn            return true;
454a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        }
455a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn
456a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn        return false;
457a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn    }
458a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn}
459