blob: e85f6dfeff67cde2b572260a0e2d6b382e23b807 [file] [log] [blame]
Jim Millerb5f3b702012-10-21 19:09:23 -07001/*
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 */
Jim Miller5ecd8112013-01-09 18:50:26 -080016package com.android.keyguard;
Jim Millerd6523da2012-10-21 16:47:02 -070017
Adam Cohen6fb841f2012-10-24 13:15:38 -070018import android.os.Handler;
19import android.os.Looper;
Jim Millerd6523da2012-10-21 16:47:02 -070020import android.view.View;
21
Winson Chung48275d22012-11-05 10:56:31 -080022public class KeyguardViewStateManager implements
23 SlidingChallengeLayout.OnChallengeScrolledListener,
24 ChallengeLayout.OnBouncerStateChangedListener {
Jim Millerd6523da2012-10-21 16:47:02 -070025
Adam Cohen7f6bb6e2012-11-04 14:00:05 -080026 private KeyguardWidgetPager mKeyguardWidgetPager;
Jim Miller19a52672012-10-23 19:52:04 -070027 private ChallengeLayout mChallengeLayout;
Adam Cohend6f89602012-11-06 11:46:25 -080028 private KeyguardHostView mKeyguardHostView;
Jim Millerd6523da2012-10-21 16:47:02 -070029 private int[] mTmpPoint = new int[2];
Adam Cohen8a7785c2012-10-29 22:01:33 -070030 private int[] mTmpLoc = new int[2];
31
32 private KeyguardSecurityView mKeyguardSecurityContainer;
Adam Cohen6fb841f2012-10-24 13:15:38 -070033 private static final int SCREEN_ON_HINT_DURATION = 1000;
Adam Cohen47c6cfa2012-10-27 18:29:52 -070034 private static final int SCREEN_ON_RING_HINT_DELAY = 300;
Adam Cohen6fb841f2012-10-24 13:15:38 -070035 Handler mMainQueue = new Handler(Looper.myLooper());
Jim Millerd6523da2012-10-21 16:47:02 -070036
Adam Cohene3643132012-10-28 18:29:17 -070037 int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
38
39 // Paged view state
40 private int mPageListeningToSlider = -1;
41 private int mCurrentPage = -1;
Adam Cohen8caabad2012-11-04 17:23:25 -080042 private int mPageIndexOnPageBeginMoving = -1;
Adam Cohene3643132012-10-28 18:29:17 -070043
Jim Millerd6523da2012-10-21 16:47:02 -070044 int mChallengeTop = 0;
45
Adam Cohend6f89602012-11-06 11:46:25 -080046 public KeyguardViewStateManager(KeyguardHostView hostView) {
47 mKeyguardHostView = hostView;
Jim Millerd6523da2012-10-21 16:47:02 -070048 }
49
50 public void setPagedView(KeyguardWidgetPager pagedView) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -080051 mKeyguardWidgetPager = pagedView;
52 updateEdgeSwiping();
Jim Millerd6523da2012-10-21 16:47:02 -070053 }
54
Jim Miller19a52672012-10-23 19:52:04 -070055 public void setChallengeLayout(ChallengeLayout layout) {
56 mChallengeLayout = layout;
Adam Cohen7f6bb6e2012-11-04 14:00:05 -080057 updateEdgeSwiping();
58 }
59
60 private void updateEdgeSwiping() {
61 if (mChallengeLayout != null && mKeyguardWidgetPager != null) {
62 if (mChallengeLayout.isChallengeOverlapping()) {
63 mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(true);
64 } else {
65 mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(false);
66 }
67 }
Jim Millerd6523da2012-10-21 16:47:02 -070068 }
69
Winson Chung9dc99232012-10-29 17:43:18 -070070 public boolean isChallengeShowing() {
71 if (mChallengeLayout != null) {
72 return mChallengeLayout.isChallengeShowing();
73 }
74 return false;
75 }
76
Winson Chung70aa5282012-10-30 10:56:37 -070077 public boolean isChallengeOverlapping() {
78 if (mChallengeLayout != null) {
79 return mChallengeLayout.isChallengeOverlapping();
80 }
81 return false;
82 }
83
Adam Cohen6fb841f2012-10-24 13:15:38 -070084 public void setSecurityViewContainer(KeyguardSecurityView container) {
85 mKeyguardSecurityContainer = container;
86 }
87
Jim Millerb5f3b702012-10-21 19:09:23 -070088 public void showBouncer(boolean show) {
Jim Miller19a52672012-10-23 19:52:04 -070089 mChallengeLayout.showBouncer();
Jim Millerb5f3b702012-10-21 19:09:23 -070090 }
91
Chris Wrenc0ae9e62012-11-05 13:16:31 -050092 public boolean isBouncing() {
93 return mChallengeLayout.isBouncing();
94 }
95
Adam Cohen70009e42012-10-30 16:48:22 -070096 public void fadeOutSecurity(int duration) {
97 ((View) mKeyguardSecurityContainer).animate().alpha(0).setDuration(duration);
98 }
99
100 public void fadeInSecurity(int duration) {
101 ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration);
102 }
103
Adam Cohen8caabad2012-11-04 17:23:25 -0800104 public void onPageBeginMoving() {
105 if (mChallengeLayout.isChallengeOverlapping() &&
106 mChallengeLayout instanceof SlidingChallengeLayout) {
107 SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
108 scl.fadeOutChallenge();
109 mPageIndexOnPageBeginMoving = mKeyguardWidgetPager.getCurrentPage();
110 }
Michael Jurka14138892012-11-07 13:45:53 -0800111 // We use mAppWidgetToShow to show a particular widget after you add it--
112 // once the user swipes a page we clear that behavior
113 if (mKeyguardHostView != null) {
114 mKeyguardHostView.clearAppWidgetToShow();
Jim Miller4eeb4f62012-11-08 00:04:29 -0800115 mKeyguardHostView.setOnDismissAction(null);
Michael Jurka14138892012-11-07 13:45:53 -0800116 }
Adam Cohen8caabad2012-11-04 17:23:25 -0800117 if (mHideHintsRunnable != null) {
118 mMainQueue.removeCallbacks(mHideHintsRunnable);
119 mHideHintsRunnable = null;
120 }
121 }
122
123 public void onPageEndMoving() {
124 mPageIndexOnPageBeginMoving = -1;
125 }
126
John Spurlockbb5c9412012-10-31 09:46:15 -0400127 public void onPageSwitching(View newPage, int newPageIndex) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800128 if (mKeyguardWidgetPager != null && mChallengeLayout instanceof SlidingChallengeLayout) {
John Spurlockbb5c9412012-10-31 09:46:15 -0400129 boolean isCameraPage = newPage instanceof CameraWidgetFrame;
130 ((SlidingChallengeLayout) mChallengeLayout).setChallengeInteractive(!isCameraPage);
131 }
Adam Cohen8caabad2012-11-04 17:23:25 -0800132
133 // If the page we're settling to is the same as we started on, and the action of
134 // moving the page hid the security, we restore it immediately.
135 if (mPageIndexOnPageBeginMoving == mKeyguardWidgetPager.getNextPage() &&
136 mChallengeLayout instanceof SlidingChallengeLayout) {
137 SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
138 scl.fadeInChallenge();
139 mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(-1);
140 }
141 mPageIndexOnPageBeginMoving = -1;
John Spurlockbb5c9412012-10-31 09:46:15 -0400142 }
143
144 public void onPageSwitched(View newPage, int newPageIndex) {
Adam Cohene3643132012-10-28 18:29:17 -0700145 // Reset the previous page size and ensure the current page is sized appropriately.
146 // We only modify the page state if it is not currently under control by the slider.
147 // This prevents conflicts.
Adam Cohen4ddcd572012-11-01 17:36:32 -0700148
149 // If the page hasn't switched, don't bother with any of this
Adam Cohen25228802012-11-04 13:20:26 -0800150 if (mCurrentPage == newPageIndex) return;
Adam Cohen4ddcd572012-11-01 17:36:32 -0700151
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800152 if (mKeyguardWidgetPager != null && mChallengeLayout != null) {
153 KeyguardWidgetFrame prevPage = mKeyguardWidgetPager.getWidgetPageAt(mCurrentPage);
Adam Cohen8caabad2012-11-04 17:23:25 -0800154 if (prevPage != null && mCurrentPage != mPageListeningToSlider && mCurrentPage
155 != mKeyguardWidgetPager.getWidgetToResetOnPageFadeOut()) {
Adam Cohene3643132012-10-28 18:29:17 -0700156 prevPage.resetSize();
Jim Millerd6523da2012-10-21 16:47:02 -0700157 }
158
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800159 KeyguardWidgetFrame newCurPage = mKeyguardWidgetPager.getWidgetPageAt(newPageIndex);
Adam Cohene3643132012-10-28 18:29:17 -0700160 boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
161 if (challengeOverlapping && !newCurPage.isSmall()
162 && mPageListeningToSlider != newPageIndex) {
Adam Cohen8a7785c2012-10-29 22:01:33 -0700163 newCurPage.shrinkWidget();
Jim Millerd6523da2012-10-21 16:47:02 -0700164 }
165 }
Adam Cohen8caabad2012-11-04 17:23:25 -0800166
Adam Cohene3643132012-10-28 18:29:17 -0700167 mCurrentPage = newPageIndex;
Jim Millerd6523da2012-10-21 16:47:02 -0700168 }
169
Adam Cohene3643132012-10-28 18:29:17 -0700170 private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
Jim Millerd6523da2012-10-21 16:47:02 -0700171 mTmpPoint[0] = 0;
Adam Cohene3643132012-10-28 18:29:17 -0700172 mTmpPoint[1] = top;
Jim Miller19a52672012-10-23 19:52:04 -0700173 mapPoint((View) mChallengeLayout, frame, mTmpPoint);
Adam Cohene3643132012-10-28 18:29:17 -0700174 return mTmpPoint[1];
175 }
176
Jim Millerd6523da2012-10-21 16:47:02 -0700177 /**
178 * Simple method to map a point from one view's coordinates to another's. Note: this method
179 * doesn't account for transforms, so if the views will be transformed, this should not be used.
180 *
181 * @param fromView The view to which the point is relative
182 * @param toView The view into which the point should be mapped
183 * @param pt The point
184 */
Adam Cohen8a7785c2012-10-29 22:01:33 -0700185 private void mapPoint(View fromView, View toView, int pt[]) {
186 fromView.getLocationInWindow(mTmpLoc);
Jim Millerd6523da2012-10-21 16:47:02 -0700187
Adam Cohen8a7785c2012-10-29 22:01:33 -0700188 int x = mTmpLoc[0];
189 int y = mTmpLoc[1];
190
191 toView.getLocationInWindow(mTmpLoc);
192 int vX = mTmpLoc[0];
193 int vY = mTmpLoc[1];
Jim Millerd6523da2012-10-21 16:47:02 -0700194
195 pt[0] += x - vX;
196 pt[1] += y - vY;
197 }
198
Adam Cohen08c83ef2012-11-08 00:25:47 -0800199 private void userActivity() {
200 if (mKeyguardHostView != null) {
201 mKeyguardHostView.onUserActivityTimeoutChanged();
202 mKeyguardHostView.userActivity();
203 }
204 }
205
Jim Millerd6523da2012-10-21 16:47:02 -0700206 @Override
207 public void onScrollStateChanged(int scrollState) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800208 if (mKeyguardWidgetPager == null || mChallengeLayout == null) return;
Winson Chung48275d22012-11-05 10:56:31 -0800209
Adam Cohene3643132012-10-28 18:29:17 -0700210 boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
211
Jim Millerd6523da2012-10-21 16:47:02 -0700212 if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800213 KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
Adam Cohene3643132012-10-28 18:29:17 -0700214 if (frame == null) return;
Jim Millerd6523da2012-10-21 16:47:02 -0700215
Adam Cohene3643132012-10-28 18:29:17 -0700216 if (!challengeOverlapping) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800217 if (!mKeyguardWidgetPager.isPageMoving()) {
Adam Cohendb1c5d52012-11-03 17:10:07 -0700218 frame.resetSize();
Adam Cohen08c83ef2012-11-08 00:25:47 -0800219 userActivity();
Adam Cohendb1c5d52012-11-03 17:10:07 -0700220 } else {
Adam Cohen8caabad2012-11-04 17:23:25 -0800221 mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(mPageListeningToSlider);
Adam Cohendb1c5d52012-11-03 17:10:07 -0700222 }
Jim Millerd6523da2012-10-21 16:47:02 -0700223 }
Adam Cohen44dc1412012-11-07 20:50:39 -0800224 if (frame.isSmall()) {
225 // This is to make sure that if the scroller animation gets cut off midway
226 // that the frame doesn't stay in a partial down position.
227 frame.setFrameHeight(frame.getSmallFrameHeight());
228 }
Adam Cohend51700b32012-11-07 16:26:46 -0800229 if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
230 frame.hideFrame(this);
231 }
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800232 updateEdgeSwiping();
Jim Millerd6523da2012-10-21 16:47:02 -0700233
Jim Millerbbba68a2012-10-24 22:21:40 -0700234 if (mChallengeLayout.isChallengeShowing()) {
Chris Wrena042ac92012-11-07 11:37:06 -0500235 mKeyguardSecurityContainer.onResume(KeyguardSecurityView.VIEW_REVEALED);
Jim Millerbbba68a2012-10-24 22:21:40 -0700236 } else {
237 mKeyguardSecurityContainer.onPause();
238 }
Adam Cohene3643132012-10-28 18:29:17 -0700239 mPageListeningToSlider = -1;
240 } else if (mLastScrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
241 // Whether dragging or settling, if the last state was idle, we use this signal
242 // to update the current page who will receive events from the sliding challenge.
243 // We resize the frame as appropriate.
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800244 mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
245 KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
Adam Cohene3643132012-10-28 18:29:17 -0700246 if (frame == null) return;
247
Winson Chung48275d22012-11-05 10:56:31 -0800248 // Skip showing the frame and shrinking the widget if we are
249 if (!mChallengeLayout.isBouncing()) {
Adam Cohend51700b32012-11-07 16:26:46 -0800250 if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
251 frame.showFrame(this);
252 }
Adam Cohene3643132012-10-28 18:29:17 -0700253
Winson Chung48275d22012-11-05 10:56:31 -0800254 // As soon as the security begins sliding, the widget becomes small (if it wasn't
255 // small to begin with).
256 if (!frame.isSmall()) {
257 // We need to fetch the final page, in case the pages are in motion.
258 mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
Adam Cohen44dc1412012-11-07 20:50:39 -0800259 frame.shrinkWidget(false);
Winson Chung48275d22012-11-05 10:56:31 -0800260 }
261 } else {
262 if (!frame.isSmall()) {
263 // We need to fetch the final page, in case the pages are in motion.
264 mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
265 }
Adam Cohene3643132012-10-28 18:29:17 -0700266 }
Winson Chung48275d22012-11-05 10:56:31 -0800267
Jim Millerbbba68a2012-10-24 22:21:40 -0700268 // View is on the move. Pause the security view until it completes.
269 mKeyguardSecurityContainer.onPause();
Jim Millerd6523da2012-10-21 16:47:02 -0700270 }
Adam Cohene3643132012-10-28 18:29:17 -0700271 mLastScrollState = scrollState;
272 }
273
274 @Override
275 public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
276 mChallengeTop = challengeTop;
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800277 KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
Adam Cohen44dc1412012-11-07 20:50:39 -0800278 if (frame != null && mLastScrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
Adam Cohene3643132012-10-28 18:29:17 -0700279 frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
280 }
Jim Millerd6523da2012-10-21 16:47:02 -0700281 }
282
Adam Cohen196cde92012-11-02 15:25:32 -0700283 private Runnable mHideHintsRunnable = new Runnable() {
284 @Override
285 public void run() {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800286 if (mKeyguardWidgetPager != null) {
287 mKeyguardWidgetPager.hideOutlinesAndSidePages();
Adam Cohen196cde92012-11-02 15:25:32 -0700288 }
289 }
290 };
291
Adam Cohen6fb841f2012-10-24 13:15:38 -0700292 public void showUsabilityHints() {
Adam Cohen47c6cfa2012-10-27 18:29:52 -0700293 mMainQueue.postDelayed( new Runnable() {
294 @Override
295 public void run() {
296 mKeyguardSecurityContainer.showUsabilityHint();
297 }
298 } , SCREEN_ON_RING_HINT_DELAY);
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800299 mKeyguardWidgetPager.showInitialPageHints();
Adam Cohen196cde92012-11-02 15:25:32 -0700300 if (mHideHintsRunnable != null) {
301 mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
302 }
Adam Cohen6fb841f2012-10-24 13:15:38 -0700303 }
Jim Millere0566da2012-10-30 14:57:29 -0700304
Winson Chung48275d22012-11-05 10:56:31 -0800305 // ChallengeLayout.OnBouncerStateChangedListener
306 @Override
307 public void onBouncerStateChanged(boolean bouncerActive) {
308 if (bouncerActive) {
309 mKeyguardWidgetPager.zoomOutToBouncer();
310 } else {
311 mKeyguardWidgetPager.zoomInFromBouncer();
Jim Miller4eeb4f62012-11-08 00:04:29 -0800312 if (mKeyguardHostView != null) {
313 mKeyguardHostView.setOnDismissAction(null);
314 }
Winson Chung48275d22012-11-05 10:56:31 -0800315 }
316 }
Jim Millerd6523da2012-10-21 16:47:02 -0700317}