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