186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato/*
286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * Copyright (C) 2008 The Android Open Source Project
386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato *
486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * you may not use this file except in compliance with the License.
686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * You may obtain a copy of the License at
786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato *
886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato *
1086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * Unless required by applicable law or agreed to in writing, software
1186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
1286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * See the License for the specific language governing permissions and
1486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * limitations under the License.
1586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato */
1686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
17fd52b18d9bf3cd62c7a07058536e9f97db65beeaJoe Onoratopackage com.android.systemui.statusbar.policy;
1886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
19a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.animation.AnimatorSet;
20a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.animation.ObjectAnimator;
2186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.content.Context;
2286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.content.res.TypedArray;
2386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.graphics.drawable.Drawable;
24a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.graphics.Canvas;
25a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.graphics.RectF;
26ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.hardware.input.InputManager;
2786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.os.RemoteException;
2886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.os.SystemClock;
2986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.os.ServiceManager;
3086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.util.AttributeSet;
31aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandlerimport android.view.accessibility.AccessibilityEvent;
32804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandlerimport android.view.HapticFeedbackConstants;
3386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.view.IWindowManager;
34bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brownimport android.view.InputDevice;
356b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownimport android.view.KeyCharacterMap;
3686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.view.KeyEvent;
3786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.view.MotionEvent;
38aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandlerimport android.view.SoundEffectConstants;
39a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.view.View;
40804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandlerimport android.view.ViewConfiguration;
4186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.widget.ImageView;
4286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
4386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport com.android.systemui.R;
4486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
4586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratopublic class KeyButtonView extends ImageView {
46fd52b18d9bf3cd62c7a07058536e9f97db65beeaJoe Onorato    private static final String TAG = "StatusBar.KeyButtonView";
47fd52b18d9bf3cd62c7a07058536e9f97db65beeaJoe Onorato
4896f4818ef41141649337d4dee09f837594e93d09Daniel Sandler    final float GLOW_MAX_SCALE_FACTOR = 1.8f;
499345b12b6572d3c2211c0b856bd90034be92bc0aChristian Robertson    final float BUTTON_QUIESCENT_ALPHA = 0.70f;
5096f4818ef41141649337d4dee09f837594e93d09Daniel Sandler
5186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    long mDownTime;
5286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    int mCode;
53aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler    int mTouchSlop;
54a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    Drawable mGlowBG;
553fd0e1a219e42db90b34b3512a6984d7dd2ebe2cDaniel Sandler    int mGlowWidth, mGlowHeight;
56a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    float mGlowAlpha = 0f, mGlowScale = 1f, mDrawingAlpha = 1f;
5744a4616bf780f131f8d78b46a075844800088860Daniel Sandler    boolean mSupportsLongpress = true;
58c638c1eb1bbed67d7d8f0d43f39137d766366f54Daniel Sandler    RectF mRect = new RectF(0f,0f,0f,0f);
5960bc69ef76c32b9a24c0901e6c6e452b50de0cdaMichael Jurka    AnimatorSet mPressedAnim;
60aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler
61804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler    Runnable mCheckLongPress = new Runnable() {
62804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler        public void run() {
63804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler            if (isPressed()) {
6444a4616bf780f131f8d78b46a075844800088860Daniel Sandler                // Slog.d("KeyButtonView", "longpressed: " + this);
65a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                if (mCode != 0) {
6698392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
67a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
68a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                } else {
69a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    // Just an old-fashioned ImageView
70a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    performLongClick();
71a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                }
72804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler            }
73804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler        }
74804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler    };
7586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
7686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    public KeyButtonView(Context context, AttributeSet attrs) {
7786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        this(context, attrs, 0);
7886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
7986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
8086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    public KeyButtonView(Context context, AttributeSet attrs, int defStyle) {
8186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        super(context, attrs);
8286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
8386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyButtonView,
8486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                defStyle, 0);
8586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
8686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0);
8744a4616bf780f131f8d78b46a075844800088860Daniel Sandler
8844a4616bf780f131f8d78b46a075844800088860Daniel Sandler        mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
89a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
90a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        mGlowBG = a.getDrawable(R.styleable.KeyButtonView_glowBackground);
91a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG != null) {
920b6586649fe827d6e7ce39fa71e93fa582640a03Michael Jurka            setDrawingAlpha(BUTTON_QUIESCENT_ALPHA);
933fd0e1a219e42db90b34b3512a6984d7dd2ebe2cDaniel Sandler            mGlowWidth = mGlowBG.getIntrinsicWidth();
943fd0e1a219e42db90b34b3512a6984d7dd2ebe2cDaniel Sandler            mGlowHeight = mGlowBG.getIntrinsicHeight();
9586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        }
9686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
9786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        a.recycle();
9886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
99641bad449ba3b971500843c6bf7bf6f08363d09eJoe Onorato        setClickable(true);
100aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
10186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
10286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
103a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    @Override
104a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    protected void onDraw(Canvas canvas) {
105a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG != null) {
106a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            canvas.save();
107a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            final int w = getWidth();
108a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            final int h = getHeight();
1093fd0e1a219e42db90b34b3512a6984d7dd2ebe2cDaniel Sandler            final float aspect = (float)mGlowWidth / mGlowHeight;
1103fd0e1a219e42db90b34b3512a6984d7dd2ebe2cDaniel Sandler            final int drawW = (int)(h*aspect);
1113fd0e1a219e42db90b34b3512a6984d7dd2ebe2cDaniel Sandler            final int drawH = h;
1123fd0e1a219e42db90b34b3512a6984d7dd2ebe2cDaniel Sandler            final int margin = (drawW-w)/2;
113a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            canvas.scale(mGlowScale, mGlowScale, w*0.5f, h*0.5f);
1143fd0e1a219e42db90b34b3512a6984d7dd2ebe2cDaniel Sandler            mGlowBG.setBounds(-margin, 0, drawW-margin, drawH);
1150b6586649fe827d6e7ce39fa71e93fa582640a03Michael Jurka            mGlowBG.setAlpha((int)(mDrawingAlpha * mGlowAlpha * 255));
116a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            mGlowBG.draw(canvas);
117a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            canvas.restore();
118c638c1eb1bbed67d7d8f0d43f39137d766366f54Daniel Sandler            mRect.right = w;
119c638c1eb1bbed67d7d8f0d43f39137d766366f54Daniel Sandler            mRect.bottom = h;
120a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        }
121a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        super.onDraw(canvas);
122a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
123a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
124a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public float getDrawingAlpha() {
125a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return 0;
126a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        return mDrawingAlpha;
127a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
128a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
129a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public void setDrawingAlpha(float x) {
130a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return;
1310b6586649fe827d6e7ce39fa71e93fa582640a03Michael Jurka        // Calling setAlpha(int), which is an ImageView-specific
1320b6586649fe827d6e7ce39fa71e93fa582640a03Michael Jurka        // method that's different from setAlpha(float). This sets
1330b6586649fe827d6e7ce39fa71e93fa582640a03Michael Jurka        // the alpha on this ImageView's drawable directly
1340b6586649fe827d6e7ce39fa71e93fa582640a03Michael Jurka        setAlpha((int) (x * 255));
135a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        mDrawingAlpha = x;
136a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
137a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
138a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public float getGlowAlpha() {
139a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return 0;
140a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        return mGlowAlpha;
141a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
142a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
143a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public void setGlowAlpha(float x) {
144a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return;
145a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        mGlowAlpha = x;
146a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        invalidate();
147a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
148a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
149a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public float getGlowScale() {
150a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return 0;
151a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        return mGlowScale;
152a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
153a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
154a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public void setGlowScale(float x) {
155a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return;
156a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        mGlowScale = x;
157a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        final float w = getWidth();
158a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        final float h = getHeight();
15996f4818ef41141649337d4dee09f837594e93d09Daniel Sandler        if (GLOW_MAX_SCALE_FACTOR <= 1.0f) {
16096f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            // this only works if we know the glow will never leave our bounds
161a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            invalidate();
162a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        } else {
16396f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            final float rx = (w * (GLOW_MAX_SCALE_FACTOR - 1.0f)) / 2.0f + 1.0f;
16496f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            final float ry = (h * (GLOW_MAX_SCALE_FACTOR - 1.0f)) / 2.0f + 1.0f;
165a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            com.android.systemui.SwipeHelper.invalidateGlobalRegion(
166a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    this,
1675298582717494098fcdf115d832c8e871340d0b5Daniel Sandler                    new RectF(getLeft() - rx,
1685298582717494098fcdf115d832c8e871340d0b5Daniel Sandler                              getTop() - ry,
1695298582717494098fcdf115d832c8e871340d0b5Daniel Sandler                              getRight() + rx,
1705298582717494098fcdf115d832c8e871340d0b5Daniel Sandler                              getBottom() + ry));
17196f4818ef41141649337d4dee09f837594e93d09Daniel Sandler
17296f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            // also invalidate our immediate parent to help avoid situations where nearby glows
17396f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            // interfere
17496f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            ((View)getParent()).invalidate();
175a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        }
176a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
177a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
178a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public void setPressed(boolean pressed) {
179a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG != null) {
180a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            if (pressed != isPressed()) {
18160bc69ef76c32b9a24c0901e6c6e452b50de0cdaMichael Jurka                if (mPressedAnim != null && mPressedAnim.isRunning()) {
18260bc69ef76c32b9a24c0901e6c6e452b50de0cdaMichael Jurka                    mPressedAnim.cancel();
18360bc69ef76c32b9a24c0901e6c6e452b50de0cdaMichael Jurka                }
18460bc69ef76c32b9a24c0901e6c6e452b50de0cdaMichael Jurka                final AnimatorSet as = mPressedAnim = new AnimatorSet();
185a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                if (pressed) {
186bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                    if (mGlowScale < GLOW_MAX_SCALE_FACTOR)
187bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                        mGlowScale = GLOW_MAX_SCALE_FACTOR;
188bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                    if (mGlowAlpha < BUTTON_QUIESCENT_ALPHA)
189bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                        mGlowAlpha = BUTTON_QUIESCENT_ALPHA;
190a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    setDrawingAlpha(1f);
191a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    as.playTogether(
192a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                        ObjectAnimator.ofFloat(this, "glowAlpha", 1f),
19396f4818ef41141649337d4dee09f837594e93d09Daniel Sandler                        ObjectAnimator.ofFloat(this, "glowScale", GLOW_MAX_SCALE_FACTOR)
194a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    );
195a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    as.setDuration(50);
196a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                } else {
197a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    as.playTogether(
198a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                        ObjectAnimator.ofFloat(this, "glowAlpha", 0f),
199a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                        ObjectAnimator.ofFloat(this, "glowScale", 1f),
200bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                        ObjectAnimator.ofFloat(this, "drawingAlpha", BUTTON_QUIESCENT_ALPHA)
201a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    );
202a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    as.setDuration(500);
203a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                }
204a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                as.start();
205a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            }
206a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        }
207a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        super.setPressed(pressed);
208a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
209a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
21086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    public boolean onTouchEvent(MotionEvent ev) {
21186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        final int action = ev.getAction();
21286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        int x, y;
21386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
21486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        switch (action) {
21586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato            case MotionEvent.ACTION_DOWN:
2167a1a2f0e9273afbde398d9804cfaa245f6adbf5dChristopher Tate                //Slog.d("KeyButtonView", "press");
21786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                mDownTime = SystemClock.uptimeMillis();
21844a4616bf780f131f8d78b46a075844800088860Daniel Sandler                setPressed(true);
21998392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mCode != 0) {
22098392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
22198392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                } else {
22298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    // Provide the same haptic feedback that the system offers for virtual keys.
22398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
22498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                }
22544a4616bf780f131f8d78b46a075844800088860Daniel Sandler                if (mSupportsLongpress) {
22644a4616bf780f131f8d78b46a075844800088860Daniel Sandler                    removeCallbacks(mCheckLongPress);
22744a4616bf780f131f8d78b46a075844800088860Daniel Sandler                    postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
22844a4616bf780f131f8d78b46a075844800088860Daniel Sandler                }
22986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                break;
23086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato            case MotionEvent.ACTION_MOVE:
23198392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                x = (int)ev.getX();
23298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                y = (int)ev.getY();
23398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                setPressed(x >= -mTouchSlop
23498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        && x < getWidth() + mTouchSlop
23598392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        && y >= -mTouchSlop
23698392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        && y < getHeight() + mTouchSlop);
23786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                break;
23886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato            case MotionEvent.ACTION_CANCEL:
239804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler                setPressed(false);
24098392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mCode != 0) {
24198392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
24298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                }
24398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mSupportsLongpress) {
24498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    removeCallbacks(mCheckLongPress);
245abb27777f4763d057d37a58936232f8e17f57de1Joe Onorato                }
246abb27777f4763d057d37a58936232f8e17f57de1Joe Onorato                break;
247abb27777f4763d057d37a58936232f8e17f57de1Joe Onorato            case MotionEvent.ACTION_UP:
248aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler                final boolean doIt = isPressed();
249abb27777f4763d057d37a58936232f8e17f57de1Joe Onorato                setPressed(false);
25098392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mCode != 0) {
25198392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    if (doIt) {
25298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        sendEvent(KeyEvent.ACTION_UP, 0);
25398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
25498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        playSoundEffect(SoundEffectConstants.CLICK);
2555ee1a3daf0fb274b2a5fdea797748b569495a621Patrick Dubroy                    } else {
25698392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
257aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler                    }
25898392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                } else {
25998392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    // no key code, just a regular ImageView
26098392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    if (doIt) {
26198392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        performClick();
26298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    }
26398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                }
26498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mSupportsLongpress) {
26598392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    removeCallbacks(mCheckLongPress);
26686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                }
26786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                break;
26886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        }
26986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
27086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        return true;
27186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
27286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
273bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brown    void sendEvent(int action, int flags) {
274bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brown        sendEvent(action, flags, SystemClock.uptimeMillis());
27586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
27686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
277bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brown    void sendEvent(int action, int flags, long when) {
27898392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown        final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
27998392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown        final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
28098392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
28198392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
28298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                InputDevice.SOURCE_KEYBOARD);
2839f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        InputManager.getInstance().injectInputEvent(ev,
2849f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
28586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
28686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato}
28786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
28886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
289