1e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler/*
2e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * Copyright (C) 2012 The Android Open Source Project
3e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler *
4e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * Licensed under the Apache License, Version 2.0 (the "License");
5e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * you may not use this file except in compliance with the License.
6e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * You may obtain a copy of the License at
7e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler *
8e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler *      http://www.apache.org/licenses/LICENSE-2.0
9e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler *
10e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * Unless required by applicable law or agreed to in writing, software
11e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * distributed under the License is distributed on an "AS IS" BASIS,
12e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * See the License for the specific language governing permissions and
14e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler * limitations under the License.
15e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler */
16e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler
17e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandlerpackage com.android.systemui.statusbar.policy;
18e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler
19c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandlerimport android.animation.ObjectAnimator;
20e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandlerimport android.content.Context;
21c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandlerimport android.content.res.TypedArray;
22c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandlerimport android.graphics.Canvas;
23c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandlerimport android.os.SystemClock;
24e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandlerimport android.util.AttributeSet;
25c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandlerimport android.util.Slog;
26e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandlerimport android.view.MotionEvent;
27e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandlerimport android.view.View;
28e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler
29e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandlerimport com.android.systemui.R;
30e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler
31e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandlerpublic class DeadZone extends View {
32c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public static final String TAG = "DeadZone";
33c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
34c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public static final boolean DEBUG = false;
35c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public static final int HORIZONTAL = 0;
36c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public static final int VERTICAL = 1;
37c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
3825bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler    private static final boolean CHATTY = true; // print to logcat when we eat a click
3925bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler
40c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private boolean mShouldFlash;
41c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private float mFlashFrac = 0f;
42c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
43c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private int mSizeMax;
44c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private int mSizeMin;
45c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    // Upon activity elsewhere in the UI, the dead zone will hold steady for
46c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    // mHold ms, then move back over the course of mDecay ms
47c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private int mHold, mDecay;
48c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private boolean mVertical;
49c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private long mLastPokeTime;
50c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
51c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private final Runnable mDebugFlash = new Runnable() {
52c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        @Override
53c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        public void run() {
54c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            ObjectAnimator.ofFloat(DeadZone.this, "flash", 1f, 0f).setDuration(150).start();
55c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        }
56c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    };
57c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
58e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler    public DeadZone(Context context, AttributeSet attrs) {
59e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler        this(context, attrs, 0);
60e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler    }
61e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler
62e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler    public DeadZone(Context context, AttributeSet attrs, int defStyle) {
63e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler        super(context, attrs);
64c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
65c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeadZone,
66c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler                defStyle, 0);
67c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
68c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mHold = a.getInteger(R.styleable.DeadZone_holdTime, 0);
69c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mDecay = a.getInteger(R.styleable.DeadZone_decayTime, 0);
70c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
71c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mSizeMin = a.getDimensionPixelSize(R.styleable.DeadZone_minSize, 0);
72c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mSizeMax = a.getDimensionPixelSize(R.styleable.DeadZone_maxSize, 0);
73c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
74c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        int index = a.getInt(R.styleable.DeadZone_orientation, -1);
75c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mVertical = (index == VERTICAL);
76c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
77c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        if (DEBUG)
78c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
79c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler                    + (mVertical ? " vertical" : " horizontal"));
80c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
8125bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler        setFlashOnTouchCapture(context.getResources().getBoolean(R.bool.config_dead_zone_flash));
82c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    }
83c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
84c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    static float lerp(float a, float b, float f) {
85c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        return (b - a) * f + a;
86c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    }
87c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
88c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    private float getSize(long now) {
89c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        if (mSizeMax == 0)
90c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            return 0;
91c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        long dt = (now - mLastPokeTime);
92c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        if (dt > mHold + mDecay)
93c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            return mSizeMin;
94c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        if (dt < mHold)
95c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            return mSizeMax;
96c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        return (int) lerp(mSizeMax, mSizeMin, (float) (dt - mHold) / mDecay);
97c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    }
98c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
99c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public void setFlashOnTouchCapture(boolean dbg) {
100c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mShouldFlash = dbg;
101c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mFlashFrac = 0f;
102c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        postInvalidate();
103e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler    }
104e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler
10525bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler    // I made you a touch event...
106e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler    @Override
107c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public boolean onTouchEvent(MotionEvent event) {
10825bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler        if (DEBUG) {
109c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
11025bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler        }
111c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
112c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        final int action = event.getAction();
113c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        if (action == MotionEvent.ACTION_OUTSIDE) {
114c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            poke(event);
115c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        } else if (action == MotionEvent.ACTION_DOWN) {
11625bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler            if (DEBUG) {
117c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler                Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
11825bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler            }
119c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            int size = (int) getSize(event.getEventTime());
120c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            if ((mVertical && event.getX() < size) || event.getY() < size) {
12125bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler                if (CHATTY) {
12225bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler                    Slog.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
12325bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler                }
124c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler                if (mShouldFlash) {
125c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler                    post(mDebugFlash);
126c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler                    postInvalidate();
127c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler                }
12825bb8eec2d63add7d43d357c26f9792ae6156a92Daniel Sandler                return true; // ...but I eated it
129c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            }
130c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        }
131c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        return false;
132c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    }
133c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
134c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public void poke(MotionEvent event) {
135c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mLastPokeTime = event.getEventTime();
136c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        if (DEBUG)
137c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
138c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        postInvalidate();
139c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    }
140c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
141c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public void setFlash(float f) {
142c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        mFlashFrac = f;
143c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        postInvalidate();
144e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler    }
145e97a776e9cbb2a7a8d698c49c5c70f2b7cd9eb1bDaniel Sandler
146c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public float getFlash() {
147c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        return mFlashFrac;
148c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    }
149c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
150c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    @Override
151c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    public void onDraw(Canvas can) {
152c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        if (!mShouldFlash || mFlashFrac <= 0f) {
153c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            return;
154c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        }
155c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
156c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        final int size = (int) getSize(SystemClock.uptimeMillis());
157c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        can.clipRect(0, 0, mVertical ? size : can.getWidth(), mVertical ? can.getHeight() : size);
158c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        final float frac = DEBUG ? (mFlashFrac - 0.5f) + 0.5f : mFlashFrac;
159c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA);
160c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler
161c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler        if (DEBUG && size > mSizeMin)
162c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            // crazy aggressive redrawing here, for debugging only
163c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler            postInvalidateDelayed(100);
164c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler    }
165c26185bb7b30508a1940eb452af64b6d8661915fDaniel Sandler}
166