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