1 /* 2 * Copyright (C) 2014 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.settings.password; 18 19 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 20 21 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; 22 23 import android.content.Context; 24 import android.content.Intent; 25 import android.os.Bundle; 26 import android.view.ContextThemeWrapper; 27 import android.view.LayoutInflater; 28 import android.view.View; 29 import android.view.ViewGroup; 30 import android.widget.Button; 31 32 import androidx.annotation.Nullable; 33 import androidx.fragment.app.Fragment; 34 35 import com.android.settings.R; 36 import com.android.settings.SetupRedactionInterstitial; 37 38 import com.google.android.setupcompat.util.WizardManagerHelper; 39 40 /** 41 * Setup Wizard's version of ChooseLockPattern screen. It inherits the logic and basic structure 42 * from ChooseLockPattern class, and should remain similar to that behaviorally. This class should 43 * only overload base methods for minor theme and behavior differences specific to Setup Wizard. 44 * Other changes should be done to ChooseLockPattern class instead and let this class inherit 45 * those changes. 46 */ 47 public class SetupChooseLockPattern extends ChooseLockPattern { 48 modifyIntentForSetup(Context context, Intent chooseLockPatternIntent)49 public static Intent modifyIntentForSetup(Context context, Intent chooseLockPatternIntent) { 50 chooseLockPatternIntent.setClass(context, SetupChooseLockPattern.class); 51 return chooseLockPatternIntent; 52 } 53 54 @Override isValidFragment(String fragmentName)55 protected boolean isValidFragment(String fragmentName) { 56 return SetupChooseLockPatternFragment.class.getName().equals(fragmentName); 57 } 58 59 @Override getFragmentClass()60 /* package */ Class<? extends Fragment> getFragmentClass() { 61 return SetupChooseLockPatternFragment.class; 62 } 63 64 @Override onCreate(Bundle savedInstanceState)65 protected void onCreate(Bundle savedInstanceState) { 66 super.onCreate(savedInstanceState); 67 68 // Show generic pattern title when pattern lock screen launch in Setup wizard flow before 69 // fingerprint and face setup. 70 setTitle(R.string.lockpassword_choose_your_pattern_header); 71 } 72 73 public static class SetupChooseLockPatternFragment extends ChooseLockPatternFragment 74 implements ChooseLockTypeDialogFragment.OnLockTypeSelectedListener { 75 76 private static final String TAG_SKIP_SCREEN_LOCK_DIALOG = "skip_screen_lock_dialog"; 77 78 @Nullable 79 private Button mOptionsButton; 80 private boolean mLeftButtonIsSkip; 81 82 @Override onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)83 public View onCreateView( 84 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 85 View view = super.onCreateView(inflater, container, savedInstanceState); 86 if (!getResources().getBoolean(R.bool.config_lock_pattern_minimal_ui)) { 87 mOptionsButton = new Button(new ContextThemeWrapper(getActivity(), 88 com.google.android.setupdesign.R.style.SudGlifButton_Tertiary)); 89 mOptionsButton.setId(R.id.screen_lock_options); 90 PasswordUtils.setupScreenLockOptionsButton(getActivity(), view, mOptionsButton); 91 mOptionsButton.setOnClickListener((btn) -> 92 ChooseLockTypeDialogFragment.newInstance(mUserId) 93 .show(getChildFragmentManager(), TAG_SKIP_SCREEN_LOCK_DIALOG)); 94 } 95 // Show the skip button during SUW but not during Settings > Biometric Enrollment 96 mSkipOrClearButton.setOnClickListener(this::onSkipOrClearButtonClick); 97 return view; 98 } 99 100 @Override onSkipOrClearButtonClick(View view)101 protected void onSkipOrClearButtonClick(View view) { 102 if (mLeftButtonIsSkip) { 103 final Intent intent = getActivity().getIntent(); 104 final boolean frpSupported = intent 105 .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false); 106 final boolean forFingerprint = intent 107 .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); 108 final boolean forFace = intent 109 .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false); 110 final boolean forBiometrics = intent 111 .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false); 112 final SetupSkipDialog dialog = SetupSkipDialog.newInstance( 113 CREDENTIAL_TYPE_PATTERN, 114 frpSupported, 115 forFingerprint, 116 forFace, 117 forBiometrics, 118 WizardManagerHelper.isAnySetupWizard(intent)); 119 dialog.show(getFragmentManager()); 120 return; 121 } 122 super.onSkipOrClearButtonClick(view); 123 } 124 125 @Override onLockTypeSelected(ScreenLockType lock)126 public void onLockTypeSelected(ScreenLockType lock) { 127 if (ScreenLockType.PATTERN == lock) { 128 return; 129 } 130 startChooseLockActivity(lock, getActivity()); 131 } 132 showMinimalUi()133 private boolean showMinimalUi() { 134 return getResources().getBoolean(R.bool.config_lock_pattern_minimal_ui); 135 } 136 137 @Override updateStage(Stage stage)138 protected void updateStage(Stage stage) { 139 super.updateStage(stage); 140 if (!showMinimalUi() && mOptionsButton != null) { 141 // In landscape, keep view stub to avoid pattern view shifting, but in portrait the 142 // header title and description could become multiple lines in confirm stage, 143 // gone the button view to reserve more room for growth height of header. 144 @View.Visibility 145 final int hideOrGone = 146 getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE 147 ? View.INVISIBLE : View.GONE; 148 mOptionsButton.setVisibility( 149 (stage == Stage.Introduction || stage == Stage.HelpScreen || 150 stage == Stage.ChoiceTooShort || stage == Stage.FirstChoiceValid) 151 ? View.VISIBLE : hideOrGone); 152 } 153 154 if (stage.leftMode == LeftButtonMode.Gone && stage == Stage.Introduction) { 155 mSkipOrClearButton.setVisibility(View.VISIBLE); 156 mSkipOrClearButton.setText(getActivity(), R.string.skip_label); 157 mLeftButtonIsSkip = true; 158 } else { 159 mLeftButtonIsSkip = false; 160 } 161 } 162 163 @Override shouldShowGenericTitle()164 protected boolean shouldShowGenericTitle() { 165 return true; 166 } 167 168 @Override getRedactionInterstitialIntent(Context context)169 protected Intent getRedactionInterstitialIntent(Context context) { 170 // Setup wizard's redaction interstitial is deferred to optional step. Enable that 171 // optional step if the lock screen was set up. 172 SetupRedactionInterstitial.setEnabled(context, true); 173 return null; 174 } 175 } 176 } 177