KeyguardBouncer.java revision 1de8bcb1e51917a301cab2ef7d276b4f9423d95f
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.KeyEvent; 21import android.view.LayoutInflater; 22import android.view.View; 23import android.view.ViewGroup; 24import android.view.accessibility.AccessibilityEvent; 25 26import com.android.internal.widget.LockPatternUtils; 27import com.android.keyguard.KeyguardHostView; 28import com.android.keyguard.KeyguardSecurityView; 29import com.android.keyguard.KeyguardUpdateMonitor; 30import com.android.keyguard.KeyguardUpdateMonitorCallback; 31import com.android.keyguard.R; 32import com.android.keyguard.ViewMediatorCallback; 33import com.android.systemui.DejankUtils; 34 35import static com.android.keyguard.KeyguardHostView.OnDismissAction; 36import static com.android.keyguard.KeyguardSecurityModel.SecurityMode; 37 38/** 39 * A class which manages the bouncer on the lockscreen. 40 */ 41public class KeyguardBouncer { 42 43 private Context mContext; 44 private ViewMediatorCallback mCallback; 45 private LockPatternUtils mLockPatternUtils; 46 private ViewGroup mContainer; 47 private StatusBarWindowManager mWindowManager; 48 private KeyguardHostView mKeyguardView; 49 private ViewGroup mRoot; 50 private boolean mShowingSoon; 51 private int mBouncerPromptReason; 52 private KeyguardUpdateMonitorCallback mUpdateMonitorCallback = 53 new KeyguardUpdateMonitorCallback() { 54 @Override 55 public void onStrongAuthStateChanged(int userId) { 56 mBouncerPromptReason = mCallback.getBouncerPromptReason(); 57 } 58 }; 59 60 public KeyguardBouncer(Context context, ViewMediatorCallback callback, 61 LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager, 62 ViewGroup container) { 63 mContext = context; 64 mCallback = callback; 65 mLockPatternUtils = lockPatternUtils; 66 mContainer = container; 67 mWindowManager = windowManager; 68 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback); 69 } 70 71 public void show(boolean resetSecuritySelection) { 72 ensureView(); 73 if (resetSecuritySelection) { 74 // showPrimarySecurityScreen() updates the current security method. This is needed in 75 // case we are already showing and the current security method changed. 76 mKeyguardView.showPrimarySecurityScreen(); 77 } 78 if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) { 79 return; 80 } 81 82 // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole 83 // Keyguard. If we need to authenticate, show the bouncer. 84 if (!mKeyguardView.dismiss()) { 85 mShowingSoon = true; 86 87 // Split up the work over multiple frames. 88 DejankUtils.postAfterTraversal(mShowRunnable); 89 } 90 } 91 92 private final Runnable mShowRunnable = new Runnable() { 93 @Override 94 public void run() { 95 mRoot.setVisibility(View.VISIBLE); 96 mKeyguardView.onResume(); 97 showPromptReason(mBouncerPromptReason); 98 mKeyguardView.startAppearAnimation(); 99 mShowingSoon = false; 100 mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 101 } 102 }; 103 104 /** 105 * Show a string explaining why the security view needs to be solved. 106 * 107 * @param reason a flag indicating which string should be shown, see 108 * {@link KeyguardSecurityView#PROMPT_REASON_NONE} 109 * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART} 110 */ 111 public void showPromptReason(int reason) { 112 mKeyguardView.showPromptReason(reason); 113 } 114 115 public void showMessage(String message, int color) { 116 mKeyguardView.showMessage(message, color); 117 } 118 119 private void cancelShowRunnable() { 120 DejankUtils.removeCallbacks(mShowRunnable); 121 mShowingSoon = false; 122 } 123 124 public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) { 125 ensureView(); 126 mKeyguardView.setOnDismissAction(r, cancelAction); 127 show(false /* resetSecuritySelection */); 128 } 129 130 public void hide(boolean destroyView) { 131 cancelShowRunnable(); 132 if (mKeyguardView != null) { 133 mKeyguardView.cancelDismissAction(); 134 mKeyguardView.cleanUp(); 135 } 136 if (destroyView) { 137 removeView(); 138 } else if (mRoot != null) { 139 mRoot.setVisibility(View.INVISIBLE); 140 } 141 } 142 143 /** 144 * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}. 145 */ 146 public void startPreHideAnimation(Runnable runnable) { 147 if (mKeyguardView != null) { 148 mKeyguardView.startDisappearAnimation(runnable); 149 } else if (runnable != null) { 150 runnable.run(); 151 } 152 } 153 154 /** 155 * Reset the state of the view. 156 */ 157 public void reset() { 158 cancelShowRunnable(); 159 inflateView(); 160 } 161 162 public void onScreenTurnedOff() { 163 if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) { 164 mKeyguardView.onPause(); 165 } 166 } 167 168 public boolean isShowing() { 169 return mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE); 170 } 171 172 public void prepare() { 173 boolean wasInitialized = mRoot != null; 174 ensureView(); 175 if (wasInitialized) { 176 mKeyguardView.showPrimarySecurityScreen(); 177 } 178 mBouncerPromptReason = mCallback.getBouncerPromptReason(); 179 } 180 181 private void ensureView() { 182 if (mRoot == null) { 183 inflateView(); 184 } 185 } 186 187 private void inflateView() { 188 removeView(); 189 mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null); 190 mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view); 191 mKeyguardView.setLockPatternUtils(mLockPatternUtils); 192 mKeyguardView.setViewMediatorCallback(mCallback); 193 mContainer.addView(mRoot, mContainer.getChildCount()); 194 mRoot.setVisibility(View.INVISIBLE); 195 mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME); 196 } 197 198 private void removeView() { 199 if (mRoot != null && mRoot.getParent() == mContainer) { 200 mContainer.removeView(mRoot); 201 mRoot = null; 202 } 203 } 204 205 public boolean onBackPressed() { 206 return mKeyguardView != null && mKeyguardView.handleBackKey(); 207 } 208 209 /** 210 * @return True if and only if the security method should be shown before showing the 211 * notifications on Keyguard, like SIM PIN/PUK. 212 */ 213 public boolean needsFullscreenBouncer() { 214 ensureView(); 215 if (mKeyguardView != null) { 216 SecurityMode mode = mKeyguardView.getSecurityMode(); 217 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; 218 } 219 return false; 220 } 221 222 /** 223 * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which 224 * makes this method much faster. 225 */ 226 public boolean isFullscreenBouncer() { 227 if (mKeyguardView != null) { 228 SecurityMode mode = mKeyguardView.getCurrentSecurityMode(); 229 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; 230 } 231 return false; 232 } 233 234 /** 235 * WARNING: This method might cause Binder calls. 236 */ 237 public boolean isSecure() { 238 return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None; 239 } 240 241 public boolean onMenuPressed() { 242 ensureView(); 243 if (mKeyguardView.handleMenuKey()) { 244 245 // We need to show it in case it is secure. If not, it will get dismissed in any case. 246 mRoot.setVisibility(View.VISIBLE); 247 mKeyguardView.requestFocus(); 248 mKeyguardView.onResume(); 249 return true; 250 } else { 251 return false; 252 } 253 } 254 255 public boolean interceptMediaKey(KeyEvent event) { 256 ensureView(); 257 return mKeyguardView.interceptMediaKey(event); 258 } 259 260 public void notifyKeyguardAuthenticated(boolean strongAuth) { 261 ensureView(); 262 mKeyguardView.finish(strongAuth); 263 } 264} 265