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