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