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