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.util.ViewController;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 import javax.inject.Inject;
37 
38 /**
39  * Controller for a {@link KeyguardSecurityViewFlipper}.
40  */
41 @KeyguardBouncerScope
42 public class KeyguardSecurityViewFlipperController
43         extends ViewController<KeyguardSecurityViewFlipper> {
44 
45     private static final boolean DEBUG = KeyguardConstants.DEBUG;
46     private static final String TAG = "KeyguardSecurityView";
47 
48     private final List<KeyguardInputViewController<KeyguardInputView>> mChildren =
49             new ArrayList<>();
50     private final LayoutInflater mLayoutInflater;
51     private final AsyncLayoutInflater mAsyncLayoutInflater;
52     private final EmergencyButtonController.Factory mEmergencyButtonControllerFactory;
53     private final Factory mKeyguardSecurityViewControllerFactory;
54     private final FeatureFlags mFeatureFlags;
55 
56     @Inject
KeyguardSecurityViewFlipperController(KeyguardSecurityViewFlipper view, LayoutInflater layoutInflater, AsyncLayoutInflater asyncLayoutInflater, KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory, EmergencyButtonController.Factory emergencyButtonControllerFactory, FeatureFlags featureFlags)57     protected KeyguardSecurityViewFlipperController(KeyguardSecurityViewFlipper view,
58             LayoutInflater layoutInflater,
59             AsyncLayoutInflater asyncLayoutInflater,
60             KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory,
61             EmergencyButtonController.Factory emergencyButtonControllerFactory,
62             FeatureFlags featureFlags) {
63         super(view);
64         mKeyguardSecurityViewControllerFactory = keyguardSecurityViewControllerFactory;
65         mLayoutInflater = layoutInflater;
66         mEmergencyButtonControllerFactory = emergencyButtonControllerFactory;
67         mAsyncLayoutInflater = asyncLayoutInflater;
68         mFeatureFlags = featureFlags;
69     }
70 
71     @Override
onViewAttached()72     protected void onViewAttached() {
73 
74     }
75 
76     @Override
onViewDetached()77     protected void onViewDetached() {
78 
79     }
80 
reset()81     public void reset() {
82         for (KeyguardInputViewController<KeyguardInputView> child : mChildren) {
83             child.reset();
84         }
85     }
86 
87     /** Handles density or font scale changes. */
clearViews()88     public void clearViews() {
89         mView.removeAllViews();
90         mChildren.clear();
91     }
92 
93 
94     @VisibleForTesting
getSecurityView(SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback, OnViewInflatedCallback onViewInflatedCallback)95     void getSecurityView(SecurityMode securityMode,
96             KeyguardSecurityCallback keyguardSecurityCallback,
97             OnViewInflatedCallback onViewInflatedCallback) {
98         for (KeyguardInputViewController<KeyguardInputView> child : mChildren) {
99             if (child.getSecurityMode() == securityMode) {
100                 onViewInflatedCallback.onViewInflated(child);
101                 return;
102             }
103         }
104 
105         asynchronouslyInflateView(securityMode, keyguardSecurityCallback, onViewInflatedCallback);
106     }
107 
108     /**
109      * Asynchronously inflate view and then add it to view flipper on the main thread when complete.
110      *
111      * OnInflateFinishedListener will be called on the main thread.
112      *
113      * @param securityMode
114      * @param keyguardSecurityCallback
115      */
asynchronouslyInflateView(SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback, @Nullable OnViewInflatedCallback onViewInflatedListener)116     public void asynchronouslyInflateView(SecurityMode securityMode,
117             KeyguardSecurityCallback keyguardSecurityCallback,
118             @Nullable OnViewInflatedCallback onViewInflatedListener) {
119         int layoutId = getLayoutIdFor(securityMode);
120         int viewID = getKeyguardInputViewId(securityMode);
121         if (layoutId != 0 && viewID != 0) {
122             if (DEBUG) {
123                 Log.v(TAG, "inflating on bg thread id = "
124                         + layoutId + " . viewID = " + viewID);
125             }
126             mAsyncLayoutInflater.inflate(layoutId, mView,
127                     (view, resId, parent) -> {
128                         mView.addView(view);
129                         KeyguardInputViewController<KeyguardInputView> childController =
130                                 mKeyguardSecurityViewControllerFactory.create(
131                                         (KeyguardInputView) view.findViewById(viewID),
132                                         securityMode, keyguardSecurityCallback);
133                         childController.init();
134                         mChildren.add(childController);
135                         if (onViewInflatedListener != null) {
136                             onViewInflatedListener.onViewInflated(childController);
137                         }
138                     });
139         }
140     }
141 
getLayoutIdFor(SecurityMode securityMode)142     private int getLayoutIdFor(SecurityMode securityMode) {
143         switch (securityMode) {
144             case Pattern: return R.layout.keyguard_pattern_view;
145             case PIN: return R.layout.keyguard_pin_view;
146             case Password: return R.layout.keyguard_password_view;
147             case SimPin: return R.layout.keyguard_sim_pin_view;
148             case SimPuk: return R.layout.keyguard_sim_puk_view;
149             default:
150                 return 0;
151         }
152     }
153 
getKeyguardInputViewId(SecurityMode securityMode)154     private int getKeyguardInputViewId(SecurityMode securityMode) {
155         //Keyguard Input View is not the root view of the layout, use these IDs for lookup.
156         switch (securityMode) {
157             case Pattern: return R.id.keyguard_pattern_view;
158             case PIN: return R.id.keyguard_pin_view;
159             case Password: return R.id.keyguard_password_view;
160             case SimPin: return R.id.keyguard_sim_pin_view;
161             case SimPuk: return R.id.keyguard_sim_puk_view;
162             default:
163                 return 0;
164         }
165     }
166 
167     /** Makes the supplied child visible if it is contained win this view, */
show(KeyguardInputViewController<KeyguardInputView> childController)168     public void show(KeyguardInputViewController<KeyguardInputView> childController) {
169         int index = childController.getIndexIn(mView);
170         if (index != -1) {
171             mView.setDisplayedChild(index);
172         }
173     }
174 
175     /** Listener to when view has finished inflation. */
176     public interface OnViewInflatedCallback {
177         /** Notifies that view has been inflated */
onViewInflated(KeyguardInputViewController<KeyguardInputView> controller)178         void onViewInflated(KeyguardInputViewController<KeyguardInputView> controller);
179     }
180 }
181