KeyguardViewStateManager.java revision 196cde973fd1635f0ac3150caab40287aacb9846
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 int[] mTmpPoint = new int[2];
27    private int[] mTmpLoc = new int[2];
28
29    private KeyguardSecurityView mKeyguardSecurityContainer;
30    private static final int SCREEN_ON_HINT_DURATION = 1000;
31    private static final int SCREEN_ON_RING_HINT_DELAY = 300;
32    Handler mMainQueue = new Handler(Looper.myLooper());
33
34    // transport control states
35    static final int TRANSPORT_GONE = 0;
36    static final int TRANSPORT_INVISIBLE = 1;
37    static final int TRANSPORT_VISIBLE = 2;
38
39    private int mTransportState = TRANSPORT_GONE;
40
41    int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
42
43    // Paged view state
44    private int mPageListeningToSlider = -1;
45    private int mCurrentPage = -1;
46
47    int mChallengeTop = 0;
48
49    public KeyguardViewStateManager() {
50    }
51
52    public void setPagedView(KeyguardWidgetPager pagedView) {
53        mPagedView = pagedView;
54    }
55
56    public void setChallengeLayout(ChallengeLayout layout) {
57        mChallengeLayout = layout;
58    }
59
60    public boolean isChallengeShowing() {
61        if (mChallengeLayout != null) {
62            return mChallengeLayout.isChallengeShowing();
63        }
64        return false;
65    }
66
67    public boolean isChallengeOverlapping() {
68        if (mChallengeLayout != null) {
69            return mChallengeLayout.isChallengeOverlapping();
70        }
71        return false;
72    }
73
74    public void setSecurityViewContainer(KeyguardSecurityView container) {
75        mKeyguardSecurityContainer = container;
76    }
77
78    public void onPageBeginMoving() {
79        if (mChallengeLayout.isChallengeShowing()) {
80            mChallengeLayout.showChallenge(false);
81        }
82        if (mHideHintsRunnable != null) {
83            mMainQueue.removeCallbacks(mHideHintsRunnable);
84            mHideHintsRunnable = null;
85        }
86    }
87
88    public void onPageEndMoving() {
89    }
90
91    public void showBouncer(boolean show) {
92        mChallengeLayout.showBouncer();
93    }
94
95    public void fadeOutSecurity(int duration) {
96        ((View) mKeyguardSecurityContainer).animate().alpha(0).setDuration(duration);
97    }
98
99    public void fadeInSecurity(int duration) {
100        ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration);
101    }
102
103    public void onPageSwitching(View newPage, int newPageIndex) {
104        if (mPagedView != null && mChallengeLayout instanceof SlidingChallengeLayout) {
105            boolean isCameraPage = newPage instanceof CameraWidgetFrame;
106            ((SlidingChallengeLayout) mChallengeLayout).setChallengeInteractive(!isCameraPage);
107        }
108    }
109
110    public void onPageSwitched(View newPage, int newPageIndex) {
111        // Reset the previous page size and ensure the current page is sized appropriately.
112        // We only modify the page state if it is not currently under control by the slider.
113        // This prevents conflicts.
114
115        // If the page hasn't switched, don't bother with any of this
116        if (mCurrentPage != newPageIndex) return;
117
118        if (mPagedView != null && mChallengeLayout != null) {
119            KeyguardWidgetFrame prevPage = mPagedView.getWidgetPageAt(mCurrentPage);
120            if (prevPage != null && mCurrentPage != mPageListeningToSlider) {
121                prevPage.resetSize();
122            }
123
124            KeyguardWidgetFrame newCurPage = mPagedView.getWidgetPageAt(newPageIndex);
125            boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
126            if (challengeOverlapping && !newCurPage.isSmall()
127                    && mPageListeningToSlider != newPageIndex) {
128                newCurPage.shrinkWidget();
129            }
130        }
131        mCurrentPage = newPageIndex;
132    }
133
134    private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
135        mTmpPoint[0] = 0;
136        mTmpPoint[1] = top;
137        mapPoint((View) mChallengeLayout, frame, mTmpPoint);
138        return mTmpPoint[1];
139    }
140
141    /**
142     * Simple method to map a point from one view's coordinates to another's. Note: this method
143     * doesn't account for transforms, so if the views will be transformed, this should not be used.
144     *
145     * @param fromView The view to which the point is relative
146     * @param toView The view into which the point should be mapped
147     * @param pt The point
148     */
149    private void mapPoint(View fromView, View toView, int pt[]) {
150        fromView.getLocationInWindow(mTmpLoc);
151
152        int x = mTmpLoc[0];
153        int y = mTmpLoc[1];
154
155        toView.getLocationInWindow(mTmpLoc);
156        int vX = mTmpLoc[0];
157        int vY = mTmpLoc[1];
158
159        pt[0] += x - vX;
160        pt[1] += y - vY;
161    }
162
163    @Override
164    public void onScrollStateChanged(int scrollState) {
165        if (mPagedView == null || mChallengeLayout == null) return;
166        boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
167
168        if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
169            KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
170            if (frame == null) return;
171
172            if (!challengeOverlapping) {
173                frame.resetSize();
174            }
175            frame.hideFrame(this);
176
177            if (challengeOverlapping) {
178                mPagedView.setOnlyAllowEdgeSwipes(true);
179            } else {
180                mPagedView.setOnlyAllowEdgeSwipes(false);
181            }
182
183            if (mChallengeLayout.isChallengeShowing()) {
184                mKeyguardSecurityContainer.onResume();
185            } else {
186                mKeyguardSecurityContainer.onPause();
187            }
188            mPageListeningToSlider = -1;
189        } else if (mLastScrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
190            // Whether dragging or settling, if the last state was idle, we use this signal
191            // to update the current page who will receive events from the sliding challenge.
192            // We resize the frame as appropriate.
193            mPageListeningToSlider = mPagedView.getNextPage();
194            KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
195            if (frame == null) return;
196
197            frame.showFrame(this);
198
199            // As soon as the security begins sliding, the widget becomes small (if it wasn't
200            // small to begin with).
201            if (!frame.isSmall()) {
202                // We need to fetch the final page, in case the pages are in motion.
203                mPageListeningToSlider = mPagedView.getNextPage();
204                frame.shrinkWidget();
205            }
206            // View is on the move.  Pause the security view until it completes.
207            mKeyguardSecurityContainer.onPause();
208        }
209        mLastScrollState = scrollState;
210    }
211
212    @Override
213    public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
214        mChallengeTop = challengeTop;
215        KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
216        if (frame != null) {
217            frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
218        }
219    }
220
221    private Runnable mHideHintsRunnable = new Runnable() {
222        @Override
223        public void run() {
224            if (mPagedView != null) {
225                mPagedView.hideOutlinesAndSidePages();
226            }
227        }
228    };
229
230    public void showUsabilityHints() {
231        mMainQueue.postDelayed( new Runnable() {
232            @Override
233            public void run() {
234                mKeyguardSecurityContainer.showUsabilityHint();
235            }
236        } , SCREEN_ON_RING_HINT_DELAY);
237        mPagedView.showInitialPageHints();
238        if (mHideHintsRunnable != null) {
239            mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
240        }
241    }
242
243    public void setTransportState(int state) {
244        mTransportState = state;
245    }
246
247    public int getTransportState() {
248        return mTransportState;
249    }
250}
251