Home | History | Annotate | Download | only in keyguard
      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  */
     16 package com.android.internal.policy.impl.keyguard;
     17 
     18 import android.os.Handler;
     19 import android.os.Looper;
     20 import android.view.View;
     21 
     22 public 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     int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
     38 
     39     // Paged view state
     40     private int mPageListeningToSlider = -1;
     41     private int mCurrentPage = -1;
     42     private int mPageIndexOnPageBeginMoving = -1;
     43 
     44     int mChallengeTop = 0;
     45 
     46     public KeyguardViewStateManager(KeyguardHostView hostView) {
     47         mKeyguardHostView = hostView;
     48     }
     49 
     50     public void setPagedView(KeyguardWidgetPager pagedView) {
     51         mKeyguardWidgetPager = pagedView;
     52         updateEdgeSwiping();
     53     }
     54 
     55     public void setChallengeLayout(ChallengeLayout layout) {
     56         mChallengeLayout = layout;
     57         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         }
     68     }
     69 
     70     public boolean isChallengeShowing() {
     71         if (mChallengeLayout != null) {
     72             return mChallengeLayout.isChallengeShowing();
     73         }
     74         return false;
     75     }
     76 
     77     public boolean isChallengeOverlapping() {
     78         if (mChallengeLayout != null) {
     79             return mChallengeLayout.isChallengeOverlapping();
     80         }
     81         return false;
     82     }
     83 
     84     public void setSecurityViewContainer(KeyguardSecurityView container) {
     85         mKeyguardSecurityContainer = container;
     86     }
     87 
     88     public void showBouncer(boolean show) {
     89         mChallengeLayout.showBouncer();
     90     }
     91 
     92     public boolean isBouncing() {
     93         return mChallengeLayout.isBouncing();
     94     }
     95 
     96     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 
    104     public void onPageBeginMoving() {
    105         if (mChallengeLayout.isChallengeOverlapping() &&
    106                 mChallengeLayout instanceof SlidingChallengeLayout) {
    107             SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
    108             scl.fadeOutChallenge();
    109             mPageIndexOnPageBeginMoving = mKeyguardWidgetPager.getCurrentPage();
    110         }
    111         // 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();
    115             mKeyguardHostView.setOnDismissAction(null);
    116         }
    117         if (mHideHintsRunnable != null) {
    118             mMainQueue.removeCallbacks(mHideHintsRunnable);
    119             mHideHintsRunnable = null;
    120         }
    121     }
    122 
    123     public void onPageEndMoving() {
    124         mPageIndexOnPageBeginMoving = -1;
    125     }
    126 
    127     public void onPageSwitching(View newPage, int newPageIndex) {
    128         if (mKeyguardWidgetPager != null && mChallengeLayout instanceof SlidingChallengeLayout) {
    129             boolean isCameraPage = newPage instanceof CameraWidgetFrame;
    130             ((SlidingChallengeLayout) mChallengeLayout).setChallengeInteractive(!isCameraPage);
    131         }
    132 
    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;
    142     }
    143 
    144     public void onPageSwitched(View newPage, int newPageIndex) {
    145         // 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.
    148 
    149         // If the page hasn't switched, don't bother with any of this
    150         if (mCurrentPage == newPageIndex) return;
    151 
    152         if (mKeyguardWidgetPager != null && mChallengeLayout != null) {
    153             KeyguardWidgetFrame prevPage = mKeyguardWidgetPager.getWidgetPageAt(mCurrentPage);
    154             if (prevPage != null && mCurrentPage != mPageListeningToSlider && mCurrentPage
    155                     != mKeyguardWidgetPager.getWidgetToResetOnPageFadeOut()) {
    156                 prevPage.resetSize();
    157             }
    158 
    159             KeyguardWidgetFrame newCurPage = mKeyguardWidgetPager.getWidgetPageAt(newPageIndex);
    160             boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
    161             if (challengeOverlapping && !newCurPage.isSmall()
    162                     && mPageListeningToSlider != newPageIndex) {
    163                 newCurPage.shrinkWidget();
    164             }
    165         }
    166 
    167         mCurrentPage = newPageIndex;
    168     }
    169 
    170     private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
    171         mTmpPoint[0] = 0;
    172         mTmpPoint[1] = top;
    173         mapPoint((View) mChallengeLayout, frame, mTmpPoint);
    174         return mTmpPoint[1];
    175     }
    176 
    177     /**
    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      */
    185     private void mapPoint(View fromView, View toView, int pt[]) {
    186         fromView.getLocationInWindow(mTmpLoc);
    187 
    188         int x = mTmpLoc[0];
    189         int y = mTmpLoc[1];
    190 
    191         toView.getLocationInWindow(mTmpLoc);
    192         int vX = mTmpLoc[0];
    193         int vY = mTmpLoc[1];
    194 
    195         pt[0] += x - vX;
    196         pt[1] += y - vY;
    197     }
    198 
    199     private void userActivity() {
    200         if (mKeyguardHostView != null) {
    201             mKeyguardHostView.onUserActivityTimeoutChanged();
    202             mKeyguardHostView.userActivity();
    203         }
    204     }
    205 
    206     @Override
    207     public void onScrollStateChanged(int scrollState) {
    208         if (mKeyguardWidgetPager == null || mChallengeLayout == null) return;
    209 
    210         boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
    211 
    212         if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
    213             KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
    214             if (frame == null) return;
    215 
    216             if (!challengeOverlapping) {
    217                 if (!mKeyguardWidgetPager.isPageMoving()) {
    218                     frame.resetSize();
    219                     userActivity();
    220                 } else {
    221                     mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(mPageListeningToSlider);
    222                 }
    223             }
    224             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             }
    229             if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
    230                 frame.hideFrame(this);
    231             }
    232             updateEdgeSwiping();
    233 
    234             if (mChallengeLayout.isChallengeShowing()) {
    235                 mKeyguardSecurityContainer.onResume(KeyguardSecurityView.VIEW_REVEALED);
    236             } else {
    237                 mKeyguardSecurityContainer.onPause();
    238             }
    239             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.
    244             mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
    245             KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
    246             if (frame == null) return;
    247 
    248             // Skip showing the frame and shrinking the widget if we are
    249             if (!mChallengeLayout.isBouncing()) {
    250                 if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
    251                     frame.showFrame(this);
    252                 }
    253 
    254                 // 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();
    259                     frame.shrinkWidget(false);
    260                 }
    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                 }
    266             }
    267 
    268             // View is on the move.  Pause the security view until it completes.
    269             mKeyguardSecurityContainer.onPause();
    270         }
    271         mLastScrollState = scrollState;
    272     }
    273 
    274     @Override
    275     public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
    276         mChallengeTop = challengeTop;
    277         KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
    278         if (frame != null && mLastScrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
    279             frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
    280         }
    281     }
    282 
    283     private Runnable mHideHintsRunnable = new Runnable() {
    284         @Override
    285         public void run() {
    286             if (mKeyguardWidgetPager != null) {
    287                 mKeyguardWidgetPager.hideOutlinesAndSidePages();
    288             }
    289         }
    290     };
    291 
    292     public void showUsabilityHints() {
    293         mMainQueue.postDelayed( new Runnable() {
    294             @Override
    295             public void run() {
    296                 mKeyguardSecurityContainer.showUsabilityHint();
    297             }
    298         } , SCREEN_ON_RING_HINT_DELAY);
    299         mKeyguardWidgetPager.showInitialPageHints();
    300         if (mHideHintsRunnable != null) {
    301             mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
    302         }
    303     }
    304 
    305     // ChallengeLayout.OnBouncerStateChangedListener
    306     @Override
    307     public void onBouncerStateChanged(boolean bouncerActive) {
    308         if (bouncerActive) {
    309             mKeyguardWidgetPager.zoomOutToBouncer();
    310         } else {
    311             mKeyguardWidgetPager.zoomInFromBouncer();
    312             if (mKeyguardHostView != null) {
    313                 mKeyguardHostView.setOnDismissAction(null);
    314             }
    315         }
    316     }
    317 }
    318