KeyguardViewStateManager.java revision 70aa528b73fc54fe7896ac1ae349569d83caba59
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.internal.policy.impl.keyguard;
17
18import android.os.Handler;
19import android.os.Looper;
20import android.view.View;
21
22public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChallengeScrolledListener {
23
24    private KeyguardWidgetPager mPagedView;
25    private ChallengeLayout mChallengeLayout;
26    private Runnable mHideHintsRunnable;
27    private int[] mTmpPoint = new int[2];
28    private int[] mTmpLoc = new int[2];
29
30    private KeyguardSecurityView mKeyguardSecurityContainer;
31    private static final int SCREEN_ON_HINT_DURATION = 1000;
32    private static final int SCREEN_ON_RING_HINT_DELAY = 300;
33    Handler mMainQueue = new Handler(Looper.myLooper());
34
35    int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
36
37    // Paged view state
38    private int mPageListeningToSlider = -1;
39    private int mCurrentPage = -1;
40
41    int mChallengeTop = 0;
42
43    public KeyguardViewStateManager() {
44    }
45
46    public void setPagedView(KeyguardWidgetPager pagedView) {
47        mPagedView = pagedView;
48    }
49
50    public void setChallengeLayout(ChallengeLayout layout) {
51        mChallengeLayout = layout;
52    }
53
54    public boolean isChallengeShowing() {
55        if (mChallengeLayout != null) {
56            return mChallengeLayout.isChallengeShowing();
57        }
58        return false;
59    }
60
61    public boolean isChallengeOverlapping() {
62        if (mChallengeLayout != null) {
63            return mChallengeLayout.isChallengeOverlapping();
64        }
65        return false;
66    }
67
68    public void setSecurityViewContainer(KeyguardSecurityView container) {
69        mKeyguardSecurityContainer = container;
70    }
71
72    public void onPageBeginMoving() {
73        if (mChallengeLayout.isChallengeShowing()) {
74            mChallengeLayout.showChallenge(false);
75        }
76        if (mHideHintsRunnable != null) {
77            mMainQueue.removeCallbacks(mHideHintsRunnable);
78            mHideHintsRunnable = null;
79        }
80    }
81
82    public void onPageEndMoving() {
83    }
84
85    public void showBouncer(boolean show) {
86        mChallengeLayout.showBouncer();
87    }
88
89    public void onPageSwitch(View newPage, int newPageIndex) {
90        // Reset the previous page size and ensure the current page is sized appropriately.
91        // We only modify the page state if it is not currently under control by the slider.
92        // This prevents conflicts.
93        if (mPagedView != null && mChallengeLayout != null) {
94            KeyguardWidgetFrame prevPage = mPagedView.getWidgetPageAt(mCurrentPage);
95            if (prevPage != null && mCurrentPage != mPageListeningToSlider) {
96                prevPage.resetSize();
97            }
98
99            KeyguardWidgetFrame newCurPage = mPagedView.getWidgetPageAt(newPageIndex);
100            boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
101            if (challengeOverlapping && !newCurPage.isSmall()
102                    && mPageListeningToSlider != newPageIndex) {
103                newCurPage.shrinkWidget();
104            }
105        }
106        mCurrentPage = newPageIndex;
107    }
108
109    private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
110        mTmpPoint[0] = 0;
111        mTmpPoint[1] = top;
112        mapPoint((View) mChallengeLayout, frame, mTmpPoint);
113        return mTmpPoint[1];
114    }
115
116    /**
117     * Simple method to map a point from one view's coordinates to another's. Note: this method
118     * doesn't account for transforms, so if the views will be transformed, this should not be used.
119     *
120     * @param fromView The view to which the point is relative
121     * @param toView The view into which the point should be mapped
122     * @param pt The point
123     */
124    private void mapPoint(View fromView, View toView, int pt[]) {
125        fromView.getLocationInWindow(mTmpLoc);
126
127        int x = mTmpLoc[0];
128        int y = mTmpLoc[1];
129
130        toView.getLocationInWindow(mTmpLoc);
131        int vX = mTmpLoc[0];
132        int vY = mTmpLoc[1];
133
134        pt[0] += x - vX;
135        pt[1] += y - vY;
136    }
137
138    @Override
139    public void onScrollStateChanged(int scrollState) {
140        if (mPagedView == null || mChallengeLayout == null) return;
141        boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
142
143        if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
144            KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
145            if (frame == null) return;
146
147            if (!challengeOverlapping) {
148                frame.resetSize();
149            }
150            frame.onChallengeActive(mChallengeLayout.isChallengeShowing());
151            frame.hideFrame(this);
152
153            if (challengeOverlapping) {
154                mPagedView.setOnlyAllowEdgeSwipes(true);
155            } else {
156                mPagedView.setOnlyAllowEdgeSwipes(false);
157            }
158
159            if (mChallengeLayout.isChallengeShowing()) {
160                mKeyguardSecurityContainer.onResume();
161            } else {
162                mKeyguardSecurityContainer.onPause();
163            }
164            mPageListeningToSlider = -1;
165        } else if (mLastScrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
166            // Whether dragging or settling, if the last state was idle, we use this signal
167            // to update the current page who will receive events from the sliding challenge.
168            // We resize the frame as appropriate.
169            mPageListeningToSlider = mPagedView.getNextPage();
170            KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
171            if (frame == null) return;
172
173            frame.showFrame(this);
174
175            // As soon as the security begins sliding, the widget becomes small (if it wasn't
176            // small to begin with).
177            if (!frame.isSmall()) {
178                // We need to fetch the final page, in case the pages are in motion.
179                mPageListeningToSlider = mPagedView.getNextPage();
180                frame.shrinkWidget();
181            }
182            // View is on the move.  Pause the security view until it completes.
183            mKeyguardSecurityContainer.onPause();
184
185            frame.onChallengeActive(true);
186        }
187        mLastScrollState = scrollState;
188    }
189
190    @Override
191    public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
192        mChallengeTop = challengeTop;
193        KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
194        if (frame != null) {
195            frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
196        }
197    }
198
199    public void showUsabilityHints() {
200        mMainQueue.postDelayed( new Runnable() {
201            @Override
202            public void run() {
203                mKeyguardSecurityContainer.showUsabilityHint();
204            }
205        } , SCREEN_ON_RING_HINT_DELAY);
206        mPagedView.showInitialPageHints();
207        mHideHintsRunnable = new Runnable() {
208            @Override
209            public void run() {
210                mPagedView.hideOutlinesAndSidePages();
211                mHideHintsRunnable = null;
212            }
213        };
214
215        mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
216    }
217}
218