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.keyguard;
18 
19 import android.annotation.CallSuper;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.res.ColorStateList;
23 import android.content.res.Resources;
24 import android.telephony.TelephonyManager;
25 import android.text.TextUtils;
26 import android.util.Log;
27 import android.view.inputmethod.InputMethodManager;
28 
29 import com.android.internal.util.LatencyTracker;
30 import com.android.internal.widget.LockPatternUtils;
31 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
32 import com.android.systemui.R;
33 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
34 import com.android.systemui.bouncer.ui.BouncerMessageView;
35 import com.android.systemui.bouncer.ui.binder.BouncerMessageViewBinder;
36 import com.android.systemui.classifier.FalsingCollector;
37 import com.android.systemui.dagger.qualifiers.Main;
38 import com.android.systemui.flags.FeatureFlags;
39 import com.android.systemui.flags.Flags;
40 import com.android.systemui.log.BouncerLogger;
41 import com.android.systemui.statusbar.policy.DevicePostureController;
42 import com.android.systemui.util.ViewController;
43 import com.android.systemui.util.concurrency.DelayableExecutor;
44 
45 import javax.inject.Inject;
46 
47 
48 /** Controller for a {@link KeyguardSecurityView}. */
49 public abstract class KeyguardInputViewController<T extends KeyguardInputView>
50         extends ViewController<T> implements KeyguardSecurityView {
51 
52     private final SecurityMode mSecurityMode;
53     private final KeyguardSecurityCallback mKeyguardSecurityCallback;
54     private final EmergencyButton mEmergencyButton;
55     private final EmergencyButtonController mEmergencyButtonController;
56     private boolean mPaused;
57     protected KeyguardMessageAreaController<BouncerKeyguardMessageArea> mMessageAreaController;
58 
59     // The following is used to ignore callbacks from SecurityViews that are no longer current
60     // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
61     // state for the current security method.
62     private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {};
63     private final FeatureFlags mFeatureFlags;
64 
KeyguardInputViewController(T view, SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback, EmergencyButtonController emergencyButtonController, @Nullable KeyguardMessageAreaController.Factory messageAreaControllerFactory, FeatureFlags featureFlags)65     protected KeyguardInputViewController(T view, SecurityMode securityMode,
66             KeyguardSecurityCallback keyguardSecurityCallback,
67             EmergencyButtonController emergencyButtonController,
68             @Nullable KeyguardMessageAreaController.Factory messageAreaControllerFactory,
69             FeatureFlags featureFlags) {
70         super(view);
71         mSecurityMode = securityMode;
72         mKeyguardSecurityCallback = keyguardSecurityCallback;
73         mEmergencyButton = view == null ? null : view.findViewById(R.id.emergency_call_button);
74         mEmergencyButtonController = emergencyButtonController;
75         mFeatureFlags = featureFlags;
76         if (messageAreaControllerFactory != null) {
77             try {
78                 BouncerKeyguardMessageArea kma = view.requireViewById(R.id.bouncer_message_area);
79                 mMessageAreaController = messageAreaControllerFactory.create(kma);
80                 mMessageAreaController.init();
81                 mMessageAreaController.setIsVisible(true);
82             } catch (IllegalArgumentException exception) {
83                 Log.e("KeyguardInputViewController",
84                         "Ensure that a BouncerKeyguardMessageArea is included in the layout");
85             }
86         }
87     }
88 
89     @Override
onInit()90     protected void onInit() {
91         mEmergencyButtonController.init();
92     }
93 
94     @Override
95     @CallSuper
onViewAttached()96     protected void onViewAttached() {
97         updateMessageAreaVisibility();
98         if (TextUtils.isEmpty(mMessageAreaController.getMessage())
99                 && getInitialMessageResId() != 0) {
100             mMessageAreaController.setMessage(
101                     mView.getResources().getString(getInitialMessageResId()),
102                     /* animate= */ false);
103         }
104     }
105 
updateMessageAreaVisibility()106     private void updateMessageAreaVisibility() {
107         if (mMessageAreaController == null) return;
108         if (mFeatureFlags.isEnabled(Flags.REVAMPED_BOUNCER_MESSAGES)) {
109             mMessageAreaController.disable();
110         } else {
111             mMessageAreaController.setIsVisible(true);
112         }
113     }
114 
115 
116     @Override
onViewDetached()117     protected void onViewDetached() {
118     }
119 
getSecurityMode()120     SecurityMode getSecurityMode() {
121         return mSecurityMode;
122     }
123 
getKeyguardSecurityCallback()124     protected KeyguardSecurityCallback getKeyguardSecurityCallback() {
125         if (mPaused) {
126             return mNullCallback;
127         }
128 
129         return mKeyguardSecurityCallback;
130     }
131 
132     @Override
reset()133     public void reset() {
134         mMessageAreaController.setMessage("", false);
135     }
136 
137     @Override
onPause()138     public void onPause() {
139         mPaused = true;
140     }
141 
142     @Override
onResume(int reason)143     public void onResume(int reason) {
144         mPaused = false;
145     }
146 
147     @Override
showPromptReason(int reason)148     public void showPromptReason(int reason) {
149     }
150 
151     @Override
showMessage(CharSequence message, ColorStateList colorState, boolean animated)152     public void showMessage(CharSequence message, ColorStateList colorState, boolean animated) {
153     }
154 
startAppearAnimation()155     public void startAppearAnimation() {
156         mView.startAppearAnimation();
157     }
158 
startDisappearAnimation(Runnable finishRunnable)159     public boolean startDisappearAnimation(Runnable finishRunnable) {
160         return mView.startDisappearAnimation(finishRunnable);
161     }
162 
163     @Override
getTitle()164     public CharSequence getTitle() {
165         return mView.getTitle();
166     }
167 
168     /** Finds the index of this view in the suppplied parent view. */
getIndexIn(KeyguardSecurityViewFlipper view)169     public int getIndexIn(KeyguardSecurityViewFlipper view) {
170         return view.indexOfChild(mView);
171     }
172 
173     /** Determines the message to show in the bouncer when it first appears. */
getInitialMessageResId()174     protected abstract int getInitialMessageResId();
175 
176     /**
177      * Binds the {@link KeyguardInputView#getBouncerMessageView()} view with the provided context.
178      */
bindMessageView( @onNull BouncerMessageInteractor bouncerMessageInteractor, KeyguardMessageAreaController.Factory messageAreaControllerFactory, BouncerLogger bouncerLogger, FeatureFlags featureFlags)179     public void bindMessageView(
180             @NonNull BouncerMessageInteractor bouncerMessageInteractor,
181             KeyguardMessageAreaController.Factory messageAreaControllerFactory,
182             BouncerLogger bouncerLogger,
183             FeatureFlags featureFlags) {
184         BouncerMessageView bouncerMessageView = (BouncerMessageView) mView.getBouncerMessageView();
185         if (bouncerMessageView != null) {
186             BouncerMessageViewBinder.bind(bouncerMessageView,
187                     bouncerMessageInteractor,
188                     messageAreaControllerFactory,
189                     bouncerLogger,
190                     featureFlags);
191         }
192     }
193 
194     /** Factory for a {@link KeyguardInputViewController}. */
195     public static class Factory {
196         private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
197         private final LockPatternUtils mLockPatternUtils;
198         private final LatencyTracker mLatencyTracker;
199         private final KeyguardMessageAreaController.Factory mMessageAreaControllerFactory;
200         private final InputMethodManager mInputMethodManager;
201         private final DelayableExecutor mMainExecutor;
202         private final Resources mResources;
203         private final LiftToActivateListener mLiftToActivateListener;
204         private final TelephonyManager mTelephonyManager;
205         private final EmergencyButtonController.Factory mEmergencyButtonControllerFactory;
206         private final FalsingCollector mFalsingCollector;
207         private final DevicePostureController mDevicePostureController;
208         private final KeyguardViewController mKeyguardViewController;
209         private final FeatureFlags mFeatureFlags;
210 
211         @Inject
Factory(KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils, LatencyTracker latencyTracker, KeyguardMessageAreaController.Factory messageAreaControllerFactory, InputMethodManager inputMethodManager, @Main DelayableExecutor mainExecutor, @Main Resources resources, LiftToActivateListener liftToActivateListener, TelephonyManager telephonyManager, FalsingCollector falsingCollector, EmergencyButtonController.Factory emergencyButtonControllerFactory, DevicePostureController devicePostureController, KeyguardViewController keyguardViewController, FeatureFlags featureFlags)212         public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor,
213                 LockPatternUtils lockPatternUtils,
214                 LatencyTracker latencyTracker,
215                 KeyguardMessageAreaController.Factory messageAreaControllerFactory,
216                 InputMethodManager inputMethodManager, @Main DelayableExecutor mainExecutor,
217                 @Main Resources resources, LiftToActivateListener liftToActivateListener,
218                 TelephonyManager telephonyManager, FalsingCollector falsingCollector,
219                 EmergencyButtonController.Factory emergencyButtonControllerFactory,
220                 DevicePostureController devicePostureController,
221                 KeyguardViewController keyguardViewController,
222                 FeatureFlags featureFlags) {
223             mKeyguardUpdateMonitor = keyguardUpdateMonitor;
224             mLockPatternUtils = lockPatternUtils;
225             mLatencyTracker = latencyTracker;
226             mMessageAreaControllerFactory = messageAreaControllerFactory;
227             mInputMethodManager = inputMethodManager;
228             mMainExecutor = mainExecutor;
229             mResources = resources;
230             mLiftToActivateListener = liftToActivateListener;
231             mTelephonyManager = telephonyManager;
232             mEmergencyButtonControllerFactory = emergencyButtonControllerFactory;
233             mFalsingCollector = falsingCollector;
234             mDevicePostureController = devicePostureController;
235             mKeyguardViewController = keyguardViewController;
236             mFeatureFlags = featureFlags;
237         }
238 
239         /** Create a new {@link KeyguardInputViewController}. */
create(KeyguardInputView keyguardInputView, SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback)240         public KeyguardInputViewController create(KeyguardInputView keyguardInputView,
241                 SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback) {
242             EmergencyButtonController emergencyButtonController =
243                     mEmergencyButtonControllerFactory.create(
244                             keyguardInputView.findViewById(R.id.emergency_call_button));
245 
246             if (keyguardInputView instanceof KeyguardPatternView) {
247                 return new KeyguardPatternViewController((KeyguardPatternView) keyguardInputView,
248                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
249                         keyguardSecurityCallback, mLatencyTracker, mFalsingCollector,
250                         emergencyButtonController, mMessageAreaControllerFactory,
251                         mDevicePostureController, mFeatureFlags);
252             } else if (keyguardInputView instanceof KeyguardPasswordView) {
253                 return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
254                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
255                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
256                         mInputMethodManager, emergencyButtonController, mMainExecutor, mResources,
257                         mFalsingCollector, mKeyguardViewController,
258                         mFeatureFlags);
259             } else if (keyguardInputView instanceof KeyguardPINView) {
260                 return new KeyguardPinViewController((KeyguardPINView) keyguardInputView,
261                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
262                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
263                         mLiftToActivateListener, emergencyButtonController, mFalsingCollector,
264                         mDevicePostureController, mFeatureFlags);
265             } else if (keyguardInputView instanceof KeyguardSimPinView) {
266                 return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
267                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
268                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
269                         mLiftToActivateListener, mTelephonyManager, mFalsingCollector,
270                         emergencyButtonController, mFeatureFlags);
271             } else if (keyguardInputView instanceof KeyguardSimPukView) {
272                 return new KeyguardSimPukViewController((KeyguardSimPukView) keyguardInputView,
273                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
274                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
275                         mLiftToActivateListener, mTelephonyManager, mFalsingCollector,
276                         emergencyButtonController, mFeatureFlags);
277             }
278 
279             throw new RuntimeException("Unable to find controller for " + keyguardInputView);
280         }
281     }
282 }
283