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