blob: 169899f372c60e973e202755a417bf29ce79432c [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
John Spurlock56d007b2013-10-28 18:40:56 -040018import android.animation.Animator;
19import android.animation.Animator.AnimatorListener;
20import android.animation.AnimatorListenerAdapter;
Adam Cohen6fb841f2012-10-24 13:15:38 -070021import android.os.Handler;
22import android.os.Looper;
Jim Millerc162dd02013-09-25 18:57:43 -070023import android.util.Log;
Jim Millerd6523da2012-10-21 16:47:02 -070024import android.view.View;
25
Winson Chung48275d22012-11-05 10:56:31 -080026public class KeyguardViewStateManager implements
27 SlidingChallengeLayout.OnChallengeScrolledListener,
28 ChallengeLayout.OnBouncerStateChangedListener {
Jim Millerd6523da2012-10-21 16:47:02 -070029
Jim Millerc162dd02013-09-25 18:57:43 -070030 private static final String TAG = "KeyguardViewStateManager";
Adam Cohen7f6bb6e2012-11-04 14:00:05 -080031 private KeyguardWidgetPager mKeyguardWidgetPager;
Jim Miller19a52672012-10-23 19:52:04 -070032 private ChallengeLayout mChallengeLayout;
Adam Cohend6f89602012-11-06 11:46:25 -080033 private KeyguardHostView mKeyguardHostView;
Jim Millerd6523da2012-10-21 16:47:02 -070034 private int[] mTmpPoint = new int[2];
Adam Cohen8a7785c2012-10-29 22:01:33 -070035 private int[] mTmpLoc = new int[2];
36
37 private KeyguardSecurityView mKeyguardSecurityContainer;
Adam Cohen6fb841f2012-10-24 13:15:38 -070038 private static final int SCREEN_ON_HINT_DURATION = 1000;
Adam Cohen47c6cfa2012-10-27 18:29:52 -070039 private static final int SCREEN_ON_RING_HINT_DELAY = 300;
Jim Millercaf24fc2013-09-10 18:37:01 -070040 private static final boolean SHOW_INITIAL_PAGE_HINTS = false;
Adam Cohen6fb841f2012-10-24 13:15:38 -070041 Handler mMainQueue = new Handler(Looper.myLooper());
Jim Millerd6523da2012-10-21 16:47:02 -070042
Adam Cohene3643132012-10-28 18:29:17 -070043 int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
44
45 // Paged view state
46 private int mPageListeningToSlider = -1;
47 private int mCurrentPage = -1;
Adam Cohen8caabad2012-11-04 17:23:25 -080048 private int mPageIndexOnPageBeginMoving = -1;
Adam Cohene3643132012-10-28 18:29:17 -070049
Jim Millerd6523da2012-10-21 16:47:02 -070050 int mChallengeTop = 0;
51
John Spurlock56d007b2013-10-28 18:40:56 -040052 private final AnimatorListener mPauseListener = new AnimatorListenerAdapter() {
53 public void onAnimationEnd(Animator animation) {
54 mKeyguardSecurityContainer.onPause();
55 }
56 };
57
58 private final AnimatorListener mResumeListener = new AnimatorListenerAdapter() {
59 public void onAnimationEnd(Animator animation) {
60 if (((View)mKeyguardSecurityContainer).isShown()) {
61 mKeyguardSecurityContainer.onResume(0);
62 }
63 }
64 };
65
Adam Cohend6f89602012-11-06 11:46:25 -080066 public KeyguardViewStateManager(KeyguardHostView hostView) {
67 mKeyguardHostView = hostView;
Jim Millerd6523da2012-10-21 16:47:02 -070068 }
69
70 public void setPagedView(KeyguardWidgetPager pagedView) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -080071 mKeyguardWidgetPager = pagedView;
72 updateEdgeSwiping();
Jim Millerd6523da2012-10-21 16:47:02 -070073 }
74
Jim Miller19a52672012-10-23 19:52:04 -070075 public void setChallengeLayout(ChallengeLayout layout) {
76 mChallengeLayout = layout;
Adam Cohen7f6bb6e2012-11-04 14:00:05 -080077 updateEdgeSwiping();
78 }
79
80 private void updateEdgeSwiping() {
81 if (mChallengeLayout != null && mKeyguardWidgetPager != null) {
82 if (mChallengeLayout.isChallengeOverlapping()) {
83 mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(true);
84 } else {
85 mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(false);
86 }
87 }
Jim Millerd6523da2012-10-21 16:47:02 -070088 }
89
Winson Chung9dc99232012-10-29 17:43:18 -070090 public boolean isChallengeShowing() {
91 if (mChallengeLayout != null) {
92 return mChallengeLayout.isChallengeShowing();
93 }
94 return false;
95 }
96
Winson Chung70aa5282012-10-30 10:56:37 -070097 public boolean isChallengeOverlapping() {
98 if (mChallengeLayout != null) {
99 return mChallengeLayout.isChallengeOverlapping();
100 }
101 return false;
102 }
103
Adam Cohen6fb841f2012-10-24 13:15:38 -0700104 public void setSecurityViewContainer(KeyguardSecurityView container) {
105 mKeyguardSecurityContainer = container;
106 }
107
Jim Millerb5f3b702012-10-21 19:09:23 -0700108 public void showBouncer(boolean show) {
Jim Miller138f25d2013-09-25 13:46:58 -0700109 CharSequence what = mKeyguardHostView.getContext().getResources().getText(
110 show ? R.string.keyguard_accessibility_show_bouncer
111 : R.string.keyguard_accessibility_hide_bouncer);
112 mKeyguardHostView.announceForAccessibility(what);
113 mKeyguardHostView.announceCurrentSecurityMethod();
Jim Miller19a52672012-10-23 19:52:04 -0700114 mChallengeLayout.showBouncer();
Jim Millerb5f3b702012-10-21 19:09:23 -0700115 }
116
Chris Wrenc0ae9e62012-11-05 13:16:31 -0500117 public boolean isBouncing() {
118 return mChallengeLayout.isBouncing();
119 }
120
Adam Cohen70009e42012-10-30 16:48:22 -0700121 public void fadeOutSecurity(int duration) {
John Spurlock56d007b2013-10-28 18:40:56 -0400122 ((View) mKeyguardSecurityContainer).animate().alpha(0f).setDuration(duration)
Jim Miller6b0afad2013-10-28 19:08:42 -0700123 .setListener(mPauseListener);
Adam Cohen70009e42012-10-30 16:48:22 -0700124 }
125
126 public void fadeInSecurity(int duration) {
John Spurlock56d007b2013-10-28 18:40:56 -0400127 ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration)
Jim Miller6b0afad2013-10-28 19:08:42 -0700128 .setListener(mResumeListener);
Adam Cohen70009e42012-10-30 16:48:22 -0700129 }
130
Adam Cohen8caabad2012-11-04 17:23:25 -0800131 public void onPageBeginMoving() {
132 if (mChallengeLayout.isChallengeOverlapping() &&
133 mChallengeLayout instanceof SlidingChallengeLayout) {
134 SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
Jim Miller6b0afad2013-10-28 19:08:42 -0700135 scl.fadeOutChallenge();
Adam Cohen8caabad2012-11-04 17:23:25 -0800136 mPageIndexOnPageBeginMoving = mKeyguardWidgetPager.getCurrentPage();
137 }
Michael Jurka14138892012-11-07 13:45:53 -0800138 // We use mAppWidgetToShow to show a particular widget after you add it--
139 // once the user swipes a page we clear that behavior
140 if (mKeyguardHostView != null) {
141 mKeyguardHostView.clearAppWidgetToShow();
Jim Miller4eeb4f62012-11-08 00:04:29 -0800142 mKeyguardHostView.setOnDismissAction(null);
Michael Jurka14138892012-11-07 13:45:53 -0800143 }
Adam Cohen8caabad2012-11-04 17:23:25 -0800144 if (mHideHintsRunnable != null) {
145 mMainQueue.removeCallbacks(mHideHintsRunnable);
146 mHideHintsRunnable = null;
147 }
148 }
149
150 public void onPageEndMoving() {
151 mPageIndexOnPageBeginMoving = -1;
152 }
153
John Spurlockbb5c9412012-10-31 09:46:15 -0400154 public void onPageSwitching(View newPage, int newPageIndex) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800155 if (mKeyguardWidgetPager != null && mChallengeLayout instanceof SlidingChallengeLayout) {
John Spurlockbb5c9412012-10-31 09:46:15 -0400156 boolean isCameraPage = newPage instanceof CameraWidgetFrame;
Jim Millerc816b8e2013-11-12 19:52:12 -0800157 if (isCameraPage) {
158 CameraWidgetFrame camera = (CameraWidgetFrame) newPage;
159 camera.setUseFastTransition(mKeyguardWidgetPager.isWarping());
160 }
Jim Millerc162dd02013-09-25 18:57:43 -0700161 SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
162 scl.setChallengeInteractive(!isCameraPage);
Jim Millerfadccf12013-10-13 17:26:39 -0700163 final int currentFlags = mKeyguardWidgetPager.getSystemUiVisibility();
164 final int newFlags = isCameraPage ? (currentFlags | View.STATUS_BAR_DISABLE_SEARCH)
165 : (currentFlags & ~View.STATUS_BAR_DISABLE_SEARCH);
166 mKeyguardWidgetPager.setSystemUiVisibility(newFlags);
John Spurlockbb5c9412012-10-31 09:46:15 -0400167 }
Adam Cohen8caabad2012-11-04 17:23:25 -0800168
169 // If the page we're settling to is the same as we started on, and the action of
170 // moving the page hid the security, we restore it immediately.
171 if (mPageIndexOnPageBeginMoving == mKeyguardWidgetPager.getNextPage() &&
172 mChallengeLayout instanceof SlidingChallengeLayout) {
173 SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
174 scl.fadeInChallenge();
175 mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(-1);
176 }
177 mPageIndexOnPageBeginMoving = -1;
John Spurlockbb5c9412012-10-31 09:46:15 -0400178 }
179
180 public void onPageSwitched(View newPage, int newPageIndex) {
Adam Cohene3643132012-10-28 18:29:17 -0700181 // Reset the previous page size and ensure the current page is sized appropriately.
182 // We only modify the page state if it is not currently under control by the slider.
183 // This prevents conflicts.
Adam Cohen4ddcd572012-11-01 17:36:32 -0700184
185 // If the page hasn't switched, don't bother with any of this
Adam Cohen25228802012-11-04 13:20:26 -0800186 if (mCurrentPage == newPageIndex) return;
Adam Cohen4ddcd572012-11-01 17:36:32 -0700187
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800188 if (mKeyguardWidgetPager != null && mChallengeLayout != null) {
189 KeyguardWidgetFrame prevPage = mKeyguardWidgetPager.getWidgetPageAt(mCurrentPage);
Adam Cohen8caabad2012-11-04 17:23:25 -0800190 if (prevPage != null && mCurrentPage != mPageListeningToSlider && mCurrentPage
191 != mKeyguardWidgetPager.getWidgetToResetOnPageFadeOut()) {
Adam Cohene3643132012-10-28 18:29:17 -0700192 prevPage.resetSize();
Jim Millerd6523da2012-10-21 16:47:02 -0700193 }
194
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800195 KeyguardWidgetFrame newCurPage = mKeyguardWidgetPager.getWidgetPageAt(newPageIndex);
Adam Cohene3643132012-10-28 18:29:17 -0700196 boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
197 if (challengeOverlapping && !newCurPage.isSmall()
198 && mPageListeningToSlider != newPageIndex) {
Jim Miller6b0afad2013-10-28 19:08:42 -0700199 newCurPage.shrinkWidget(true);
Jim Millerd6523da2012-10-21 16:47:02 -0700200 }
201 }
Adam Cohen8caabad2012-11-04 17:23:25 -0800202
Adam Cohene3643132012-10-28 18:29:17 -0700203 mCurrentPage = newPageIndex;
Jim Millerd6523da2012-10-21 16:47:02 -0700204 }
205
Jim Millercaf24fc2013-09-10 18:37:01 -0700206 public void onPageBeginWarp() {
Jim Millerc162dd02013-09-25 18:57:43 -0700207 fadeOutSecurity(SlidingChallengeLayout.CHALLENGE_FADE_OUT_DURATION);
208 View frame = mKeyguardWidgetPager.getPageAt(mKeyguardWidgetPager.getPageWarpIndex());
209 ((KeyguardWidgetFrame)frame).showFrame(this);
Jim Millercaf24fc2013-09-10 18:37:01 -0700210 }
211
212 public void onPageEndWarp() {
Jim Millerc162dd02013-09-25 18:57:43 -0700213 fadeInSecurity(SlidingChallengeLayout.CHALLENGE_FADE_IN_DURATION);
214 View frame = mKeyguardWidgetPager.getPageAt(mKeyguardWidgetPager.getPageWarpIndex());
215 ((KeyguardWidgetFrame)frame).hideFrame(this);
Jim Millercaf24fc2013-09-10 18:37:01 -0700216 }
217
Adam Cohene3643132012-10-28 18:29:17 -0700218 private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
Jim Millerd6523da2012-10-21 16:47:02 -0700219 mTmpPoint[0] = 0;
Adam Cohene3643132012-10-28 18:29:17 -0700220 mTmpPoint[1] = top;
Jim Miller19a52672012-10-23 19:52:04 -0700221 mapPoint((View) mChallengeLayout, frame, mTmpPoint);
Adam Cohene3643132012-10-28 18:29:17 -0700222 return mTmpPoint[1];
223 }
224
Jim Millerd6523da2012-10-21 16:47:02 -0700225 /**
226 * Simple method to map a point from one view's coordinates to another's. Note: this method
227 * doesn't account for transforms, so if the views will be transformed, this should not be used.
228 *
229 * @param fromView The view to which the point is relative
230 * @param toView The view into which the point should be mapped
231 * @param pt The point
232 */
Adam Cohen8a7785c2012-10-29 22:01:33 -0700233 private void mapPoint(View fromView, View toView, int pt[]) {
234 fromView.getLocationInWindow(mTmpLoc);
Jim Millerd6523da2012-10-21 16:47:02 -0700235
Adam Cohen8a7785c2012-10-29 22:01:33 -0700236 int x = mTmpLoc[0];
237 int y = mTmpLoc[1];
238
239 toView.getLocationInWindow(mTmpLoc);
240 int vX = mTmpLoc[0];
241 int vY = mTmpLoc[1];
Jim Millerd6523da2012-10-21 16:47:02 -0700242
243 pt[0] += x - vX;
244 pt[1] += y - vY;
245 }
246
Adam Cohen08c83ef2012-11-08 00:25:47 -0800247 private void userActivity() {
248 if (mKeyguardHostView != null) {
249 mKeyguardHostView.onUserActivityTimeoutChanged();
250 mKeyguardHostView.userActivity();
251 }
252 }
253
Jim Millerd6523da2012-10-21 16:47:02 -0700254 @Override
255 public void onScrollStateChanged(int scrollState) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800256 if (mKeyguardWidgetPager == null || mChallengeLayout == null) return;
Winson Chung48275d22012-11-05 10:56:31 -0800257
Adam Cohene3643132012-10-28 18:29:17 -0700258 boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
259
Jim Millerd6523da2012-10-21 16:47:02 -0700260 if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800261 KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
Adam Cohene3643132012-10-28 18:29:17 -0700262 if (frame == null) return;
Jim Millerd6523da2012-10-21 16:47:02 -0700263
Adam Cohene3643132012-10-28 18:29:17 -0700264 if (!challengeOverlapping) {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800265 if (!mKeyguardWidgetPager.isPageMoving()) {
Adam Cohendb1c5d52012-11-03 17:10:07 -0700266 frame.resetSize();
Adam Cohen08c83ef2012-11-08 00:25:47 -0800267 userActivity();
Adam Cohendb1c5d52012-11-03 17:10:07 -0700268 } else {
Adam Cohen8caabad2012-11-04 17:23:25 -0800269 mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(mPageListeningToSlider);
Adam Cohendb1c5d52012-11-03 17:10:07 -0700270 }
Jim Millerd6523da2012-10-21 16:47:02 -0700271 }
Adam Cohen44dc1412012-11-07 20:50:39 -0800272 if (frame.isSmall()) {
273 // This is to make sure that if the scroller animation gets cut off midway
274 // that the frame doesn't stay in a partial down position.
275 frame.setFrameHeight(frame.getSmallFrameHeight());
276 }
Adam Cohend51700b32012-11-07 16:26:46 -0800277 if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
278 frame.hideFrame(this);
279 }
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800280 updateEdgeSwiping();
Jim Millerd6523da2012-10-21 16:47:02 -0700281
Jim Millerbbba68a2012-10-24 22:21:40 -0700282 if (mChallengeLayout.isChallengeShowing()) {
Chris Wrena042ac92012-11-07 11:37:06 -0500283 mKeyguardSecurityContainer.onResume(KeyguardSecurityView.VIEW_REVEALED);
Jim Millerbbba68a2012-10-24 22:21:40 -0700284 } else {
285 mKeyguardSecurityContainer.onPause();
286 }
Adam Cohene3643132012-10-28 18:29:17 -0700287 mPageListeningToSlider = -1;
288 } else if (mLastScrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
289 // Whether dragging or settling, if the last state was idle, we use this signal
290 // to update the current page who will receive events from the sliding challenge.
291 // We resize the frame as appropriate.
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800292 mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
293 KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
Adam Cohene3643132012-10-28 18:29:17 -0700294 if (frame == null) return;
295
Winson Chung48275d22012-11-05 10:56:31 -0800296 // Skip showing the frame and shrinking the widget if we are
297 if (!mChallengeLayout.isBouncing()) {
Adam Cohend51700b32012-11-07 16:26:46 -0800298 if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
299 frame.showFrame(this);
300 }
Adam Cohene3643132012-10-28 18:29:17 -0700301
Winson Chung48275d22012-11-05 10:56:31 -0800302 // As soon as the security begins sliding, the widget becomes small (if it wasn't
303 // small to begin with).
304 if (!frame.isSmall()) {
305 // We need to fetch the final page, in case the pages are in motion.
306 mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
Adam Cohen44dc1412012-11-07 20:50:39 -0800307 frame.shrinkWidget(false);
Winson Chung48275d22012-11-05 10:56:31 -0800308 }
309 } else {
310 if (!frame.isSmall()) {
311 // We need to fetch the final page, in case the pages are in motion.
312 mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
313 }
Adam Cohene3643132012-10-28 18:29:17 -0700314 }
Winson Chung48275d22012-11-05 10:56:31 -0800315
Jim Millerbbba68a2012-10-24 22:21:40 -0700316 // View is on the move. Pause the security view until it completes.
317 mKeyguardSecurityContainer.onPause();
Jim Millerd6523da2012-10-21 16:47:02 -0700318 }
Adam Cohene3643132012-10-28 18:29:17 -0700319 mLastScrollState = scrollState;
320 }
321
322 @Override
323 public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
324 mChallengeTop = challengeTop;
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800325 KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
Adam Cohen44dc1412012-11-07 20:50:39 -0800326 if (frame != null && mLastScrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
Adam Cohene3643132012-10-28 18:29:17 -0700327 frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
328 }
Jim Millerd6523da2012-10-21 16:47:02 -0700329 }
330
Adam Cohen196cde92012-11-02 15:25:32 -0700331 private Runnable mHideHintsRunnable = new Runnable() {
332 @Override
333 public void run() {
Adam Cohen7f6bb6e2012-11-04 14:00:05 -0800334 if (mKeyguardWidgetPager != null) {
335 mKeyguardWidgetPager.hideOutlinesAndSidePages();
Adam Cohen196cde92012-11-02 15:25:32 -0700336 }
337 }
338 };
339
Adam Cohen6fb841f2012-10-24 13:15:38 -0700340 public void showUsabilityHints() {
Adam Cohen47c6cfa2012-10-27 18:29:52 -0700341 mMainQueue.postDelayed( new Runnable() {
342 @Override
343 public void run() {
344 mKeyguardSecurityContainer.showUsabilityHint();
345 }
346 } , SCREEN_ON_RING_HINT_DELAY);
Jim Millercaf24fc2013-09-10 18:37:01 -0700347 if (SHOW_INITIAL_PAGE_HINTS) {
348 mKeyguardWidgetPager.showInitialPageHints();
349 }
Adam Cohen196cde92012-11-02 15:25:32 -0700350 if (mHideHintsRunnable != null) {
351 mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
352 }
Adam Cohen6fb841f2012-10-24 13:15:38 -0700353 }
Jim Millere0566da2012-10-30 14:57:29 -0700354
Winson Chung48275d22012-11-05 10:56:31 -0800355 // ChallengeLayout.OnBouncerStateChangedListener
356 @Override
357 public void onBouncerStateChanged(boolean bouncerActive) {
358 if (bouncerActive) {
359 mKeyguardWidgetPager.zoomOutToBouncer();
360 } else {
361 mKeyguardWidgetPager.zoomInFromBouncer();
Jim Miller4eeb4f62012-11-08 00:04:29 -0800362 if (mKeyguardHostView != null) {
363 mKeyguardHostView.setOnDismissAction(null);
364 }
Winson Chung48275d22012-11-05 10:56:31 -0800365 }
366 }
Jim Millerd6523da2012-10-21 16:47:02 -0700367}