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