• 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.keyguard;
18 
19 import android.util.Log;
20 import android.view.LayoutInflater;
21 
22 import androidx.annotation.Nullable;
23 import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 import com.android.keyguard.KeyguardInputViewController.Factory;
27 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
28 import com.android.keyguard.dagger.KeyguardBouncerScope;
29 import com.android.systemui.R;
30 import com.android.systemui.flags.FeatureFlags;
31 import com.android.systemui.flags.Flags;
32 import com.android.systemui.util.ViewController;
33 
34 import java.util.ArrayList;
35 import java.util.List;
36 
37 import javax.inject.Inject;
38 
39 /**
40  * Controller for a {@link KeyguardSecurityViewFlipper}.
41  */
42 @KeyguardBouncerScope
43 public class KeyguardSecurityViewFlipperController
44         extends ViewController<KeyguardSecurityViewFlipper> {
45 
46     private static final boolean DEBUG = KeyguardConstants.DEBUG;
47     private static final String TAG = "KeyguardSecurityView";
48 
49     private final List<KeyguardInputViewController<KeyguardInputView>> mChildren =
50             new ArrayList<>();
51     private final LayoutInflater mLayoutInflater;
52     private final AsyncLayoutInflater mAsyncLayoutInflater;
53     private final EmergencyButtonController.Factory mEmergencyButtonControllerFactory;
54     private final Factory mKeyguardSecurityViewControllerFactory;
55     private final FeatureFlags mFeatureFlags;
56 
57     @Inject
KeyguardSecurityViewFlipperController(KeyguardSecurityViewFlipper view, LayoutInflater layoutInflater, AsyncLayoutInflater asyncLayoutInflater, KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory, EmergencyButtonController.Factory emergencyButtonControllerFactory, FeatureFlags featureFlags)58     protected KeyguardSecurityViewFlipperController(KeyguardSecurityViewFlipper view,
59             LayoutInflater layoutInflater,
60             AsyncLayoutInflater asyncLayoutInflater,
61             KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory,
62             EmergencyButtonController.Factory emergencyButtonControllerFactory,
63             FeatureFlags featureFlags) {
64         super(view);
65         mKeyguardSecurityViewControllerFactory = keyguardSecurityViewControllerFactory;
66         mLayoutInflater = layoutInflater;
67         mEmergencyButtonControllerFactory = emergencyButtonControllerFactory;
68         mAsyncLayoutInflater = asyncLayoutInflater;
69         mFeatureFlags = featureFlags;
70     }
71 
72     @Override
onViewAttached()73     protected void onViewAttached() {
74 
75     }
76 
77     @Override
onViewDetached()78     protected void onViewDetached() {
79 
80     }
81 
reset()82     public void reset() {
83         for (KeyguardInputViewController<KeyguardInputView> child : mChildren) {
84             child.reset();
85         }
86     }
87 
88     /** Handles density or font scale changes. */
clearViews()89     public void clearViews() {
90         mView.removeAllViews();
91         mChildren.clear();
92     }
93 
94 
95     @VisibleForTesting
getSecurityView(SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback)96     KeyguardInputViewController<KeyguardInputView> getSecurityView(SecurityMode securityMode,
97             KeyguardSecurityCallback keyguardSecurityCallback) {
98         KeyguardInputViewController<KeyguardInputView> childController = null;
99         for (KeyguardInputViewController<KeyguardInputView> child : mChildren) {
100             if (child.getSecurityMode() == securityMode) {
101                 childController = child;
102                 break;
103             }
104         }
105 
106         if (!mFeatureFlags.isEnabled(Flags.ASYNC_INFLATE_BOUNCER) && childController == null
107                 && securityMode != SecurityMode.None && securityMode != SecurityMode.Invalid) {
108             int layoutId = getLayoutIdFor(securityMode);
109             KeyguardInputView view = null;
110             if (layoutId != 0) {
111                 if (DEBUG) Log.v(TAG, "inflating on main thread id = " + layoutId);
112                 view = (KeyguardInputView) mLayoutInflater.inflate(
113                         layoutId, mView, false);
114                 mView.addView(view);
115                 childController = mKeyguardSecurityViewControllerFactory.create(
116                         view, securityMode, keyguardSecurityCallback);
117                 childController.init();
118 
119                 mChildren.add(childController);
120             }
121         }
122 
123         if (childController == null) {
124             childController = new NullKeyguardInputViewController(
125                     securityMode, keyguardSecurityCallback,
126                     mEmergencyButtonControllerFactory.create(null));
127         }
128 
129         return childController;
130     }
131 
132     /**
133      * Asynchronously inflate view and then add it to view flipper on the main thread when complete.
134      *
135      * OnInflateFinishedListener will be called on the main thread.
136      *
137      * @param securityMode
138      * @param keyguardSecurityCallback
139      */
asynchronouslyInflateView(SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback, @Nullable OnViewInflatedListener onViewInflatedListener)140     public void asynchronouslyInflateView(SecurityMode securityMode,
141             KeyguardSecurityCallback keyguardSecurityCallback,
142             @Nullable OnViewInflatedListener onViewInflatedListener) {
143         int layoutId = getLayoutIdFor(securityMode);
144         if (layoutId != 0) {
145             if (DEBUG) Log.v(TAG, "inflating on bg thread id = " + layoutId);
146             mAsyncLayoutInflater.inflate(layoutId, mView,
147                     (view, resId, parent) -> {
148                         mView.addView(view);
149                         KeyguardInputViewController<KeyguardInputView> childController =
150                                 mKeyguardSecurityViewControllerFactory.create(
151                                         (KeyguardInputView) view, securityMode,
152                                         keyguardSecurityCallback);
153                         childController.init();
154                         mChildren.add(childController);
155                         if (onViewInflatedListener != null) {
156                             onViewInflatedListener.onViewInflated();
157                         }
158                     });
159         }
160     }
161 
getLayoutIdFor(SecurityMode securityMode)162     private int getLayoutIdFor(SecurityMode securityMode) {
163         switch (securityMode) {
164             case Pattern: return R.layout.keyguard_pattern_view;
165             case PIN: return R.layout.keyguard_pin_view;
166             case Password: return R.layout.keyguard_password_view;
167             case SimPin: return R.layout.keyguard_sim_pin_view;
168             case SimPuk: return R.layout.keyguard_sim_puk_view;
169             default:
170                 return 0;
171         }
172     }
173 
174     /** Makes the supplied child visible if it is contained win this view, */
show(KeyguardInputViewController<KeyguardInputView> childController)175     public void show(KeyguardInputViewController<KeyguardInputView> childController) {
176         int index = childController.getIndexIn(mView);
177         if (index != -1) {
178             mView.setDisplayedChild(index);
179         }
180     }
181 
182     private static class NullKeyguardInputViewController
183             extends KeyguardInputViewController<KeyguardInputView> {
NullKeyguardInputViewController(SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback, EmergencyButtonController emergencyButtonController)184         protected NullKeyguardInputViewController(SecurityMode securityMode,
185                 KeyguardSecurityCallback keyguardSecurityCallback,
186                 EmergencyButtonController emergencyButtonController) {
187             super(null, securityMode, keyguardSecurityCallback, emergencyButtonController,
188                     null);
189         }
190 
191         @Override
needsInput()192         public boolean needsInput() {
193             return false;
194         }
195 
196         @Override
onStartingToHide()197         public void onStartingToHide() {
198         }
199 
200         @Override
getInitialMessageResId()201         protected int getInitialMessageResId() {
202             return 0;
203         }
204     }
205 
206     /** Listener to when view has finished inflation. */
207     public interface OnViewInflatedListener {
208         /** Notifies that view has been inflated */
onViewInflated()209         void onViewInflated();
210     }
211 }
212