Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2014 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 
     17 package com.android.systemui.statusbar.phone;
     18 
     19 import android.content.Context;
     20 import android.view.Choreographer;
     21 import android.view.KeyEvent;
     22 import android.view.LayoutInflater;
     23 import android.view.View;
     24 import android.view.ViewGroup;
     25 
     26 import com.android.internal.widget.LockPatternUtils;
     27 import com.android.keyguard.KeyguardViewBase;
     28 import com.android.keyguard.R;
     29 import com.android.keyguard.ViewMediatorCallback;
     30 import com.android.systemui.keyguard.KeyguardViewMediator;
     31 
     32 import static com.android.keyguard.KeyguardHostView.OnDismissAction;
     33 import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
     34 
     35 /**
     36  * A class which manages the bouncer on the lockscreen.
     37  */
     38 public class KeyguardBouncer {
     39 
     40     private Context mContext;
     41     private ViewMediatorCallback mCallback;
     42     private LockPatternUtils mLockPatternUtils;
     43     private ViewGroup mContainer;
     44     private StatusBarWindowManager mWindowManager;
     45     private KeyguardViewBase mKeyguardView;
     46     private ViewGroup mRoot;
     47     private boolean mShowingSoon;
     48     private Choreographer mChoreographer = Choreographer.getInstance();
     49 
     50     public KeyguardBouncer(Context context, ViewMediatorCallback callback,
     51             LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
     52             ViewGroup container) {
     53         mContext = context;
     54         mCallback = callback;
     55         mLockPatternUtils = lockPatternUtils;
     56         mContainer = container;
     57         mWindowManager = windowManager;
     58     }
     59 
     60     public void show() {
     61         ensureView();
     62         if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
     63 
     64             // show() updates the current security method. This is needed in case we are already
     65             // showing and the current security method changed.
     66             mKeyguardView.show();
     67             return;
     68         }
     69 
     70         // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
     71         // Keyguard. If we need to authenticate, show the bouncer.
     72         if (!mKeyguardView.dismiss()) {
     73             mShowingSoon = true;
     74 
     75             // Split up the work over multiple frames.
     76             mChoreographer.postCallbackDelayed(Choreographer.CALLBACK_ANIMATION, mShowRunnable,
     77                     null, 48);
     78         }
     79     }
     80 
     81     private final Runnable mShowRunnable = new Runnable() {
     82         @Override
     83         public void run() {
     84             mRoot.setVisibility(View.VISIBLE);
     85             mKeyguardView.onResume();
     86             mKeyguardView.startAppearAnimation();
     87             mShowingSoon = false;
     88         }
     89     };
     90 
     91     private void cancelShowRunnable() {
     92         mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null);
     93         mShowingSoon = false;
     94     }
     95 
     96     public void showWithDismissAction(OnDismissAction r) {
     97         ensureView();
     98         mKeyguardView.setOnDismissAction(r);
     99         show();
    100     }
    101 
    102     public void hide(boolean destroyView) {
    103         cancelShowRunnable();
    104          if (mKeyguardView != null) {
    105             mKeyguardView.setOnDismissAction(null);
    106             mKeyguardView.cleanUp();
    107         }
    108         if (destroyView) {
    109             removeView();
    110         } else if (mRoot != null) {
    111             mRoot.setVisibility(View.INVISIBLE);
    112         }
    113     }
    114 
    115     /**
    116      * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
    117      */
    118     public void startPreHideAnimation(Runnable runnable) {
    119         if (mKeyguardView != null) {
    120             mKeyguardView.startDisappearAnimation(runnable);
    121         } else if (runnable != null) {
    122             runnable.run();
    123         }
    124     }
    125 
    126     /**
    127      * Reset the state of the view.
    128      */
    129     public void reset() {
    130         cancelShowRunnable();
    131         inflateView();
    132     }
    133 
    134     public void onScreenTurnedOff() {
    135         if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
    136             mKeyguardView.onPause();
    137         }
    138     }
    139 
    140     public long getUserActivityTimeout() {
    141         if (mKeyguardView != null) {
    142             long timeout = mKeyguardView.getUserActivityTimeout();
    143             if (timeout >= 0) {
    144                 return timeout;
    145             }
    146         }
    147         return KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
    148     }
    149 
    150     public boolean isShowing() {
    151         return mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE);
    152     }
    153 
    154     public void prepare() {
    155         ensureView();
    156     }
    157 
    158     private void ensureView() {
    159         if (mRoot == null) {
    160             inflateView();
    161         }
    162     }
    163 
    164     private void inflateView() {
    165         removeView();
    166         mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
    167         mKeyguardView = (KeyguardViewBase) mRoot.findViewById(R.id.keyguard_host_view);
    168         mKeyguardView.setLockPatternUtils(mLockPatternUtils);
    169         mKeyguardView.setViewMediatorCallback(mCallback);
    170         mContainer.addView(mRoot, mContainer.getChildCount());
    171         mRoot.setVisibility(View.INVISIBLE);
    172         mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
    173     }
    174 
    175     private void removeView() {
    176         if (mRoot != null && mRoot.getParent() == mContainer) {
    177             mContainer.removeView(mRoot);
    178             mRoot = null;
    179         }
    180     }
    181 
    182     public boolean onBackPressed() {
    183         return mKeyguardView != null && mKeyguardView.handleBackKey();
    184     }
    185 
    186     /**
    187      * @return True if and only if the current security method should be shown before showing
    188      *         the notifications on Keyguard, like SIM PIN/PUK.
    189      */
    190     public boolean needsFullscreenBouncer() {
    191         if (mKeyguardView != null) {
    192             SecurityMode mode = mKeyguardView.getSecurityMode();
    193             return mode == SecurityMode.SimPin
    194                     || mode == SecurityMode.SimPuk;
    195         }
    196         return false;
    197     }
    198 
    199     public boolean isSecure() {
    200         return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
    201     }
    202 
    203     public boolean onMenuPressed() {
    204         ensureView();
    205         if (mKeyguardView.handleMenuKey()) {
    206 
    207             // We need to show it in case it is secure. If not, it will get dismissed in any case.
    208             mRoot.setVisibility(View.VISIBLE);
    209             mKeyguardView.requestFocus();
    210             mKeyguardView.onResume();
    211             return true;
    212         } else {
    213             return false;
    214         }
    215     }
    216 
    217     public boolean interceptMediaKey(KeyEvent event) {
    218         ensureView();
    219         return mKeyguardView.interceptMediaKey(event);
    220     }
    221 }
    222