• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.car.keyguard;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.content.Context;
22 import android.content.res.Resources;
23 import android.graphics.PixelFormat;
24 import android.os.Bundle;
25 import android.os.UserHandle;
26 import android.util.Log;
27 import android.view.Gravity;
28 import android.view.View;
29 import android.view.ViewGroup;
30 import android.view.ViewRootImpl;
31 import android.view.WindowManager;
32 
33 import androidx.annotation.MainThread;
34 
35 import com.android.car.ui.FocusParkingView;
36 import com.android.internal.widget.LockPatternView;
37 import com.android.keyguard.KeyguardSecurityModel;
38 import com.android.keyguard.KeyguardUpdateMonitor;
39 import com.android.keyguard.KeyguardViewController;
40 import com.android.keyguard.ViewMediatorCallback;
41 import com.android.keyguard.dagger.KeyguardBouncerComponent;
42 import com.android.systemui.R;
43 import com.android.systemui.car.systembar.CarSystemBarController;
44 import com.android.systemui.car.window.OverlayViewController;
45 import com.android.systemui.car.window.OverlayViewGlobalStateController;
46 import com.android.systemui.car.window.SystemUIOverlayWindowController;
47 import com.android.systemui.dagger.SysUISingleton;
48 import com.android.systemui.dagger.qualifiers.Main;
49 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
50 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
51 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
52 import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
53 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
54 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
55 import com.android.systemui.shade.NotificationPanelViewController;
56 import com.android.systemui.shade.ShadeExpansionStateManager;
57 import com.android.systemui.statusbar.phone.BiometricUnlockController;
58 import com.android.systemui.statusbar.phone.CentralSurfaces;
59 import com.android.systemui.statusbar.phone.KeyguardBypassController;
60 import com.android.systemui.statusbar.policy.KeyguardStateController;
61 import com.android.systemui.toast.SystemUIToast;
62 import com.android.systemui.toast.ToastFactory;
63 import com.android.systemui.util.concurrency.DelayableExecutor;
64 
65 import javax.inject.Inject;
66 
67 import dagger.Lazy;
68 
69 /**
70  * Automotive implementation of the {@link KeyguardViewController}. It controls the Keyguard View
71  * that is mounted to the SystemUIOverlayWindow.
72  */
73 @SysUISingleton
74 public class CarKeyguardViewController extends OverlayViewController implements
75         KeyguardViewController {
76     private static final String TAG = "CarKeyguardViewController";
77     private static final boolean DEBUG = true;
78     private static final float TOAST_PARAMS_HORIZONTAL_WEIGHT = 1.0f;
79     private static final float TOAST_PARAMS_VERTICAL_WEIGHT = 1.0f;
80 
81     private final Context mContext;
82     private final DelayableExecutor mMainExecutor;
83     private final WindowManager mWindowManager;
84     private final ToastFactory mToastFactory;
85     private final FocusParkingView mFocusParkingView;
86     private final KeyguardStateController mKeyguardStateController;
87     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
88     private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
89     private final ViewMediatorCallback mViewMediatorCallback;
90     private final CarSystemBarController mCarSystemBarController;
91     private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
92     private final KeyguardSecurityModel mKeyguardSecurityModel;
93     private final KeyguardBouncerViewModel mKeyguardBouncerViewModel;
94     private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
95     private final PrimaryBouncerExpansionCallback mExpansionCallback =
96             new PrimaryBouncerExpansionCallback() {
97                 @Override
98                 public void onFullyShown() {
99                     LockPatternView patternView = getLayout().findViewById(R.id.lockPatternView);
100                     if (patternView != null) {
101                         patternView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
102                             @Override
103                             public void onFocusChange(View v, boolean hasFocus) {
104                                 if (hasFocus) {
105                                     makeOverlayToast(R.string.lockpattern_does_not_support_rotary);
106                                 }
107                             }
108                         });
109                     }
110                 }
111 
112                 @Override
113                 public void onStartingToHide() {
114                 }
115 
116                 @Override
117                 public void onStartingToShow() {
118                 }
119 
120                 @Override
121                 public void onFullyHidden() {
122                 }
123 
124                 @Override
125                 public void onVisibilityChanged(boolean isVisible) {
126                 }
127 
128                 @Override
129                 public void onExpansionChanged(float bouncerHideAmount) {
130                 }
131             };
132 
133     private OnKeyguardCancelClickedListener mKeyguardCancelClickedListener;
134     private boolean mShowing;
135     private boolean mIsOccluded;
136     private boolean mIsSleeping;
137     private int mToastShowDurationMillisecond;
138     private ViewGroup mKeyguardContainer;
139     private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
140 
141     @Inject
CarKeyguardViewController( Context context, @Main DelayableExecutor mainExecutor, WindowManager windowManager, ToastFactory toastFactory, SystemUIOverlayWindowController systemUIOverlayWindowController, OverlayViewGlobalStateController overlayViewGlobalStateController, KeyguardStateController keyguardStateController, KeyguardUpdateMonitor keyguardUpdateMonitor, Lazy<BiometricUnlockController> biometricUnlockControllerLazy, ViewMediatorCallback viewMediatorCallback, CarSystemBarController carSystemBarController, PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor, PrimaryBouncerInteractor primaryBouncerInteractor, KeyguardSecurityModel keyguardSecurityModel, KeyguardBouncerViewModel keyguardBouncerViewModel, PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel, KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory)142     public CarKeyguardViewController(
143             Context context,
144             @Main DelayableExecutor mainExecutor,
145             WindowManager windowManager,
146             ToastFactory toastFactory,
147             SystemUIOverlayWindowController systemUIOverlayWindowController,
148             OverlayViewGlobalStateController overlayViewGlobalStateController,
149             KeyguardStateController keyguardStateController,
150             KeyguardUpdateMonitor keyguardUpdateMonitor,
151             Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
152             ViewMediatorCallback viewMediatorCallback,
153             CarSystemBarController carSystemBarController,
154             PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
155             PrimaryBouncerInteractor primaryBouncerInteractor,
156             KeyguardSecurityModel keyguardSecurityModel,
157             KeyguardBouncerViewModel keyguardBouncerViewModel,
158             PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
159             KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
160 
161         super(R.id.keyguard_stub, overlayViewGlobalStateController);
162 
163         mContext = context;
164         mMainExecutor = mainExecutor;
165         mWindowManager = windowManager;
166         mToastFactory = toastFactory;
167         mFocusParkingView = systemUIOverlayWindowController.getBaseLayout().findViewById(
168                 R.id.focus_parking_view);
169         mKeyguardStateController = keyguardStateController;
170         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
171         mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
172         mViewMediatorCallback = viewMediatorCallback;
173         mCarSystemBarController = carSystemBarController;
174         mPrimaryBouncerInteractor = primaryBouncerInteractor;
175         mKeyguardSecurityModel = keyguardSecurityModel;
176         mKeyguardBouncerViewModel = keyguardBouncerViewModel;
177         mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
178         mPrimaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel;
179 
180         mToastShowDurationMillisecond = mContext.getResources().getInteger(
181                 R.integer.car_keyguard_toast_show_duration_millisecond);
182         primaryBouncerCallbackInteractor.addBouncerExpansionCallback(mExpansionCallback);
183     }
184 
185     @Override
getFocusAreaViewId()186     protected int getFocusAreaViewId() {
187         return R.id.keyguard_container;
188     }
189 
190     @Override
shouldShowNavigationBarInsets()191     protected boolean shouldShowNavigationBarInsets() {
192         return true;
193     }
194 
195     @Override
onFinishInflate()196     public void onFinishInflate() {
197         mKeyguardContainer = getLayout().findViewById(R.id.keyguard_container);
198         KeyguardBouncerViewBinder.bind(mKeyguardContainer,
199                 mKeyguardBouncerViewModel, mPrimaryBouncerToGoneTransitionViewModel,
200                 mKeyguardBouncerComponentFactory);
201         mBiometricUnlockControllerLazy.get().setKeyguardViewController(this);
202     }
203 
204     @Override
205     @MainThread
notifyKeyguardAuthenticated(boolean strongAuth)206     public void notifyKeyguardAuthenticated(boolean strongAuth) {
207         mPrimaryBouncerInteractor.notifyKeyguardAuthenticated(strongAuth);
208     }
209 
210     @Override
211     @MainThread
showPrimaryBouncer(boolean scrimmed)212     public void showPrimaryBouncer(boolean scrimmed) {
213         if (mShowing && !mPrimaryBouncerInteractor.isFullyShowing()) {
214             mPrimaryBouncerInteractor.show(/* isScrimmed= */ true);
215         }
216     }
217 
218     @Override
219     @MainThread
show(Bundle options)220     public void show(Bundle options) {
221         if (mShowing) return;
222 
223         mShowing = true;
224         mKeyguardStateController.notifyKeyguardState(mShowing, /* occluded= */ false);
225         mCarSystemBarController.showAllKeyguardButtons(/* isSetUp= */ true);
226         start();
227         reset(/* hideBouncerWhenShowing= */ false);
228         notifyKeyguardUpdateMonitor();
229     }
230 
231     @Override
232     @MainThread
hide(long startTime, long fadeoutDuration)233     public void hide(long startTime, long fadeoutDuration) {
234         if (!mShowing || mIsSleeping) return;
235 
236         mViewMediatorCallback.readyForKeyguardDone();
237         mShowing = false;
238         mKeyguardStateController.notifyKeyguardState(mShowing, /* occluded= */ false);
239         mPrimaryBouncerInteractor.hide();
240         mCarSystemBarController.showAllNavigationButtons(/* isSetUp= */ true);
241         stop();
242         mKeyguardStateController.notifyKeyguardDoneFading();
243         mMainExecutor.execute(mViewMediatorCallback::keyguardGone);
244         notifyKeyguardUpdateMonitor();
245     }
246 
247     @Override
reset(boolean hideBouncerWhenShowing)248     public void reset(boolean hideBouncerWhenShowing) {
249         if (mIsSleeping) return;
250 
251         mMainExecutor.execute(() -> {
252             if (mShowing) {
253                 if (!isSecure()) {
254                     dismissAndCollapse();
255                 }
256                 resetBouncer();
257                 mKeyguardUpdateMonitor.sendKeyguardReset();
258                 notifyKeyguardUpdateMonitor();
259             } else {
260                 // This is necessary in order to address an inconsistency between the keyguard
261                 // service and the keyguard views.
262                 // TODO: Investigate the source of the inconsistency.
263                 show(/* options= */ null);
264             }
265         });
266     }
267 
268     @Override
hideAlternateBouncer(boolean forceUpdateScrim)269     public void hideAlternateBouncer(boolean forceUpdateScrim) {
270         // no-op
271     }
272 
273     @Override
274     @MainThread
onFinishedGoingToSleep()275     public void onFinishedGoingToSleep() {
276         mPrimaryBouncerInteractor.hide();
277     }
278 
279     @Override
280     @MainThread
setOccluded(boolean occluded, boolean animate)281     public void setOccluded(boolean occluded, boolean animate) {
282         mIsOccluded = occluded;
283         getOverlayViewGlobalStateController().setOccluded(occluded);
284         if (occluded) {
285             mCarSystemBarController.showAllOcclusionButtons(/* isSetup= */ true);
286         } else {
287             if (mShowing && isSecure()) {
288                 mCarSystemBarController.showAllKeyguardButtons(/* isSetup= */ true);
289             } else {
290                 mCarSystemBarController.showAllNavigationButtons(/* isSetUp= */ true);
291             }
292         }
293     }
294 
295     @Override
296     @MainThread
onCancelClicked()297     public void onCancelClicked() {
298         getOverlayViewGlobalStateController().setWindowNeedsInput(/* needsInput= */ false);
299         mPrimaryBouncerInteractor.hide();
300         mKeyguardCancelClickedListener.onCancelClicked();
301     }
302 
303     @Override
304     @MainThread
dismissAndCollapse()305     public void dismissAndCollapse() {
306         // If dismissing and collapsing Keyguard is requested (e.g. by a Keyguard-dismissing
307         // Activity) while Keyguard is occluded, unocclude Keyguard so the user can authenticate to
308         // dismiss Keyguard.
309         if (mIsOccluded) {
310             setOccluded(/* occluded= */ false, /* animate= */ false);
311         }
312         if (!isSecure()) {
313             hide(/* startTime= */ 0, /* fadeoutDuration= */ 0);
314         }
315     }
316 
317     @Override
318     @MainThread
startPreHideAnimation(Runnable finishRunnable)319     public void startPreHideAnimation(Runnable finishRunnable) {
320         if (isBouncerShowing()) {
321             mPrimaryBouncerInteractor.startDisappearAnimation(finishRunnable);
322         } else if (finishRunnable != null) {
323             finishRunnable.run();
324         }
325     }
326 
327     @Override
setNeedsInput(boolean needsInput)328     public void setNeedsInput(boolean needsInput) {
329         getOverlayViewGlobalStateController().setWindowNeedsInput(needsInput);
330     }
331 
332     @Override
onStartedGoingToSleep()333     public void onStartedGoingToSleep() {
334         mIsSleeping = true;
335     }
336 
337     @Override
onStartedWakingUp()338     public void onStartedWakingUp() {
339         mIsSleeping = false;
340         reset(/* hideBouncerWhenShowing= */ false);
341     }
342 
343     /**
344      * Add listener for keyguard cancel clicked.
345      */
registerOnKeyguardCancelClickedListener( OnKeyguardCancelClickedListener keyguardCancelClickedListener)346     public void registerOnKeyguardCancelClickedListener(
347             OnKeyguardCancelClickedListener keyguardCancelClickedListener) {
348         mKeyguardCancelClickedListener = keyguardCancelClickedListener;
349     }
350 
351     /**
352      * Remove listener for keyguard cancel clicked.
353      */
unregisterOnKeyguardCancelClickedListener( OnKeyguardCancelClickedListener keyguardCancelClickedListener)354     public void unregisterOnKeyguardCancelClickedListener(
355             OnKeyguardCancelClickedListener keyguardCancelClickedListener) {
356         mKeyguardCancelClickedListener = null;
357     }
358 
359     @Override
getViewRootImpl()360     public ViewRootImpl getViewRootImpl() {
361         return ((View) getLayout().getParent()).getViewRootImpl();
362     }
363 
364     @Override
365     @MainThread
isBouncerShowing()366     public boolean isBouncerShowing() {
367         return mPrimaryBouncerInteractor.isFullyShowing();
368     }
369 
370     @Override
371     @MainThread
primaryBouncerIsOrWillBeShowing()372     public boolean primaryBouncerIsOrWillBeShowing() {
373         return mPrimaryBouncerInteractor.isFullyShowing()
374                 || mPrimaryBouncerInteractor.isInTransit();
375     }
376 
377     @Override
keyguardGoingAway()378     public void keyguardGoingAway() {
379         // no-op
380     }
381 
382     @Override
setKeyguardGoingAwayState(boolean isKeyguardGoingAway)383     public void setKeyguardGoingAwayState(boolean isKeyguardGoingAway) {
384         // no-op
385     }
386 
387     @Override
shouldDisableWindowAnimationsForUnlock()388     public boolean shouldDisableWindowAnimationsForUnlock() {
389         // TODO(b/205189147): revert the following change after the proper fix is landed.
390         // Disables the KeyGuard animation to resolve TaskView misalignment issue after display-on.
391         return true;
392     }
393 
394     @Override
isGoingToNotificationShade()395     public boolean isGoingToNotificationShade() {
396         return false;
397     }
398 
399     @Override
isUnlockWithWallpaper()400     public boolean isUnlockWithWallpaper() {
401         return false;
402     }
403 
404     @Override
shouldSubtleWindowAnimationsForUnlock()405     public boolean shouldSubtleWindowAnimationsForUnlock() {
406         return false;
407     }
408 
409     @Override
blockPanelExpansionFromCurrentTouch()410     public void blockPanelExpansionFromCurrentTouch() {
411         // no-op
412     }
413 
414     @Override
registerCentralSurfaces( CentralSurfaces centralSurfaces, NotificationPanelViewController notificationPanelViewController, ShadeExpansionStateManager shadeExpansionStateManager, BiometricUnlockController biometricUnlockController, View notificationContainer, KeyguardBypassController bypassController)415     public void registerCentralSurfaces(
416             CentralSurfaces centralSurfaces,
417             NotificationPanelViewController notificationPanelViewController,
418             ShadeExpansionStateManager shadeExpansionStateManager,
419             BiometricUnlockController biometricUnlockController,
420             View notificationContainer,
421             KeyguardBypassController bypassController) {
422         // no-op
423     }
424 
425     /**
426      * Hides Keyguard so that the transitioning Bouncer can be hidden until it is prepared. To be
427      * called by {@link com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator}
428      * when a new user is selected.
429      */
hideKeyguardToPrepareBouncer()430     public void hideKeyguardToPrepareBouncer() {
431         getLayout().setVisibility(View.INVISIBLE);
432     }
433 
434     @Override
setAllowRotaryFocus(boolean allowRotaryFocus)435     public boolean setAllowRotaryFocus(boolean allowRotaryFocus) {
436         boolean changed = super.setAllowRotaryFocus(allowRotaryFocus);
437         // When focus on keyguard becomes allowed, focus needs to be restored back to the pin entry
438         // view. Depending on the timing of the calls, pinView may believe it is focused
439         // (isFocused()=true) but the root view does not believe anything is focused
440         // (findFocus()=null). To guarantee that the view is fully focused, it is necessary to
441         // clear and refocus the element.
442         if (changed && allowRotaryFocus && getLayout() != null) {
443             View pinView = getLayout().findViewById(R.id.pinEntry);
444             if (pinView != null) {
445                 pinView.clearFocus();
446                 pinView.requestFocus();
447             }
448         }
449         return changed;
450     }
451 
revealKeyguardIfBouncerPrepared()452     private void revealKeyguardIfBouncerPrepared() {
453         int reattemptDelayMillis = 50;
454         Runnable revealKeyguard = () -> {
455             if (!mPrimaryBouncerInteractor.isInTransit() || !isSecure()) {
456                 if (mShowing) {
457                     // Only set the layout as visible if the keyguard should be showing
458                     showInternal();
459                 }
460             } else {
461                 if (DEBUG) {
462                     Log.d(TAG, "revealKeyguardIfBouncerPrepared: Bouncer is not prepared "
463                             + "yet so reattempting after " + reattemptDelayMillis + "ms.");
464                 }
465                 mMainExecutor.executeDelayed(this::revealKeyguardIfBouncerPrepared,
466                         reattemptDelayMillis);
467             }
468         };
469         mMainExecutor.execute(revealKeyguard);
470     }
471 
notifyKeyguardUpdateMonitor()472     private void notifyKeyguardUpdateMonitor() {
473         mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(
474                 primaryBouncerIsOrWillBeShowing(), isBouncerShowing());
475     }
476 
477     /**
478      * WARNING: This method might cause Binder calls.
479      */
isSecure()480     private boolean isSecure() {
481         return mKeyguardSecurityModel.getSecurityMode(
482                 KeyguardUpdateMonitor.getCurrentUser()) != KeyguardSecurityModel.SecurityMode.None;
483     }
484 
485 
resetBouncer()486     private void resetBouncer() {
487         mMainExecutor.execute(() -> {
488             hideInternal();
489             mPrimaryBouncerInteractor.hide();
490             mPrimaryBouncerInteractor.show(/* isScrimmed= */ true);
491             revealKeyguardIfBouncerPrepared();
492         });
493     }
494 
makeOverlayToast(int stringId)495     private void makeOverlayToast(int stringId) {
496         Resources res = mContext.getResources();
497 
498         SystemUIToast systemUIToast = mToastFactory.createToast(mContext,
499                 res.getString(stringId), mContext.getPackageName(), UserHandle.myUserId(),
500                 res.getConfiguration().orientation);
501 
502         if (systemUIToast == null) {
503             return;
504         }
505 
506         View toastView = systemUIToast.getView();
507 
508         WindowManager.LayoutParams params = new WindowManager.LayoutParams();
509         params.height = WindowManager.LayoutParams.WRAP_CONTENT;
510         params.width = WindowManager.LayoutParams.WRAP_CONTENT;
511         params.format = PixelFormat.TRANSLUCENT;
512         params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
513         params.y = systemUIToast.getYOffset();
514 
515         int absGravity = Gravity.getAbsoluteGravity(systemUIToast.getGravity(),
516                 res.getConfiguration().getLayoutDirection());
517         params.gravity = absGravity;
518 
519         if ((absGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
520             params.horizontalWeight = TOAST_PARAMS_HORIZONTAL_WEIGHT;
521         }
522         if ((absGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
523             params.verticalWeight = TOAST_PARAMS_VERTICAL_WEIGHT;
524         }
525 
526         // Make FocusParkingView temporarily unfocusable so it does not steal the focus.
527         // If FocusParkingView is focusable, it first steals focus and then returns it to Pattern
528         // Lock, which causes the Toast to appear repeatedly.
529         mFocusParkingView.setFocusable(false);
530         mWindowManager.addView(toastView, params);
531 
532         Animator inAnimator = systemUIToast.getInAnimation();
533         if (inAnimator != null) {
534             inAnimator.start();
535         }
536 
537         mMainExecutor.executeDelayed(new Runnable() {
538             @Override
539             public void run() {
540                 Animator outAnimator = systemUIToast.getOutAnimation();
541                 if (outAnimator != null) {
542                     outAnimator.start();
543                     outAnimator.addListener(new AnimatorListenerAdapter() {
544                         @Override
545                         public void onAnimationEnd(Animator animator) {
546                             mWindowManager.removeViewImmediate(toastView);
547                             mFocusParkingView.setFocusable(true);
548                         }
549                     });
550                 } else {
551                     mFocusParkingView.setFocusable(true);
552                 }
553             }
554         }, mToastShowDurationMillisecond);
555     }
556 
557     /**
558      * Defines a callback for keyguard cancel button clicked listeners.
559      */
560     public interface OnKeyguardCancelClickedListener {
561         /**
562          * Called when keyguard cancel button is clicked.
563          */
onCancelClicked()564         void onCancelClicked();
565     }
566 }
567