• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
20 import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
21 
22 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
23 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
24 
25 import android.app.RemoteServiceException.MissingRequestPasswordComplexityPermissionException;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.graphics.Color;
29 import android.graphics.drawable.ColorDrawable;
30 import android.os.Bundle;
31 import android.os.IBinder;
32 import android.os.UserHandle;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.view.ViewGroup;
36 
37 import androidx.fragment.app.Fragment;
38 import androidx.preference.Preference;
39 import androidx.preference.PreferenceFragmentCompat;
40 import androidx.recyclerview.widget.RecyclerView;
41 
42 import com.android.internal.widget.LockPatternUtils;
43 import com.android.settings.R;
44 import com.android.settings.SetupWizardUtils;
45 import com.android.settings.utils.SettingsDividerItemDecoration;
46 
47 import com.google.android.setupcompat.util.WizardManagerHelper;
48 import com.google.android.setupdesign.GlifPreferenceLayout;
49 import com.google.android.setupdesign.util.ThemeHelper;
50 
51 import org.jetbrains.annotations.NotNull;
52 
53 /**
54  * Setup Wizard's version of ChooseLockGeneric screen. It inherits the logic and basic structure
55  * from ChooseLockGeneric class, and should remain similar to that behaviorally. This class should
56  * only overload base methods for minor theme and behavior differences specific to Setup Wizard.
57  * Other changes should be done to ChooseLockGeneric class instead and let this class inherit
58  * those changes.
59  */
60 // TODO(b/123225425): Restrict SetupChooseLockGeneric to be accessible by SUW only
61 public class SetupChooseLockGeneric extends ChooseLockGeneric {
62 
63     private static final String KEY_UNLOCK_SET_DO_LATER = "unlock_set_do_later";
64 
65     @Override
isValidFragment(String fragmentName)66     protected boolean isValidFragment(String fragmentName) {
67         return SetupChooseLockGenericFragment.class.getName().equals(fragmentName);
68     }
69 
70     @Override
getFragmentClass()71     /* package */ Class<? extends PreferenceFragmentCompat> getFragmentClass() {
72         return SetupChooseLockGenericFragment.class;
73     }
74 
75     @Override
onCreate(Bundle savedInstance)76     protected void onCreate(Bundle savedInstance) {
77         setTheme(SetupWizardUtils.getTheme(this, getIntent()));
78         ThemeHelper.trySetDynamicColor(this);
79         super.onCreate(savedInstance);
80 
81         if(getIntent().hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)) {
82             IBinder activityToken = getActivityToken();
83             boolean hasPermission = PasswordUtils.isCallingAppPermitted(
84                     this, activityToken, REQUEST_PASSWORD_COMPLEXITY);
85             if (!hasPermission) {
86                 PasswordUtils.crashCallingApplication(activityToken,
87                         "Must have permission " + REQUEST_PASSWORD_COMPLEXITY
88                                 + " to use extra " + EXTRA_PASSWORD_COMPLEXITY,
89                         MissingRequestPasswordComplexityPermissionException.TYPE_ID);
90                 finish();
91                 return;
92             }
93         }
94 
95         findViewById(R.id.content_parent).setFitsSystemWindows(false);
96     }
97 
98     @Override
isToolbarEnabled()99     protected boolean isToolbarEnabled() {
100         // Hide the action bar from this page.
101         return false;
102     }
103 
104     public static class SetupChooseLockGenericFragment extends ChooseLockGenericFragment {
105 
106         public static final String EXTRA_PASSWORD_QUALITY = ":settings:password_quality";
107 
108         @Override
onViewCreated(View view, Bundle savedInstanceState)109         public void onViewCreated(View view, Bundle savedInstanceState) {
110             super.onViewCreated(view, savedInstanceState);
111 
112             GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
113             layout.setDescriptionText(loadDescriptionText());
114             layout.setDividerItemDecoration(new SettingsDividerItemDecoration(getContext()));
115             layout.setDividerInset(getContext().getResources().getDimensionPixelSize(
116                     R.dimen.sud_items_glif_text_divider_inset));
117 
118             layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
119 
120             int titleResource = isForBiometric() ?
121                     R.string.lock_settings_picker_title : R.string.setup_lock_settings_picker_title;
122             if (getActivity() != null) {
123                 getActivity().setTitle(titleResource);
124             }
125 
126             layout.setHeaderText(titleResource);
127             // Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in
128             // PreferenceFragment.
129             setDivider(null);
130         }
131 
132         @Override
addHeaderView()133         protected void addHeaderView() {
134             // The original logic has been moved to onViewCreated and
135             // uses GlifLayout#setDescriptionText instead,
136             // keep empty body here since we won't call super method.
137         }
138 
139         @Override
onActivityResult(int requestCode, int resultCode, Intent data)140         public void onActivityResult(int requestCode, int resultCode, Intent data) {
141             if (data == null) {
142                 data = new Intent();
143             }
144             // Add the password quality extra to the intent data that will be sent back for
145             // Setup Wizard.
146             LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
147             data.putExtra(EXTRA_PASSWORD_QUALITY,
148                     lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId()));
149 
150             super.onActivityResult(requestCode, resultCode, data);
151         }
152 
153         @Override
onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)154         public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
155                 Bundle savedInstanceState) {
156             GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
157             return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
158         }
159 
160         @Override
canRunBeforeDeviceProvisioned()161         protected boolean canRunBeforeDeviceProvisioned() {
162             return true;
163         }
164 
165         @Override
getInternalActivityClass()166         protected Class<? extends ChooseLockGeneric.InternalActivity> getInternalActivityClass() {
167             return SetupChooseLockGeneric.InternalActivity.class;
168         }
169 
170         @Override
alwaysHideInsecureScreenLockTypes()171         protected boolean alwaysHideInsecureScreenLockTypes() {
172             // At this part of the flow, the user has already indicated they want to add a pin,
173             // pattern or password, so don't show "None" or "Slide". We disable them here.
174             // This only happens for setup wizard.
175             return true;
176         }
177 
178         @Override
addPreferences()179         protected void addPreferences() {
180             if (isForBiometric()) {
181                 super.addPreferences();
182             } else {
183                 addPreferencesFromResource(R.xml.setup_security_settings_picker);
184             }
185         }
186 
187         @Override
onPreferenceTreeClick(Preference preference)188         public boolean onPreferenceTreeClick(Preference preference) {
189             final String key = preference.getKey();
190             if (KEY_UNLOCK_SET_DO_LATER.equals(key)) {
191                 // show warning.
192                 final Intent intent = getActivity().getIntent();
193                 SetupSkipDialog dialog = SetupSkipDialog.newInstance(
194                         CREDENTIAL_TYPE_NONE,
195                         intent.getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false),
196                         /* forFingerprint= */ false,
197                         /* forFace= */ false,
198                         /* forBiometrics= */ false,
199                         WizardManagerHelper.isAnySetupWizard(intent)
200                 );
201                 dialog.show(getFragmentManager());
202                 return true;
203             }
204             return super.onPreferenceTreeClick(preference);
205         }
206 
207         @Override
getLockPasswordIntent(int quality)208         protected Intent getLockPasswordIntent(int quality) {
209             final Intent intent = SetupChooseLockPassword.modifyIntentForSetup(
210                     getContext(), super.getLockPasswordIntent(quality));
211             SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
212             return intent;
213         }
214 
215         @Override
getLockPatternIntent()216         protected Intent getLockPatternIntent() {
217             final Intent intent = SetupChooseLockPattern.modifyIntentForSetup(
218                     getContext(), super.getLockPatternIntent());
219             SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
220             return intent;
221         }
222 
223         @Override
getBiometricEnrollIntent(Context context)224         protected Intent getBiometricEnrollIntent(Context context) {
225             final Intent intent = super.getBiometricEnrollIntent(context);
226             SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
227             return intent;
228         }
229 
isForBiometric()230         private boolean isForBiometric() {
231             return mForFingerprint || mForFace || mForBiometrics;
232         }
233 
loadDescriptionText()234         String loadDescriptionText() {
235             return getString(isForBiometric()
236                     ? R.string.lock_settings_picker_biometrics_added_security_message
237                     : R.string.setup_lock_settings_picker_message);
238         }
239     }
240 
241     public static class InternalActivity extends ChooseLockGeneric.InternalActivity {
242         @Override
onCreate(Bundle savedState)243         protected void onCreate(Bundle savedState) {
244             setTheme(SetupWizardUtils.getTheme(this, getIntent()));
245             ThemeHelper.trySetDynamicColor(this);
246             super.onCreate(savedState);
247         }
248 
249         @Override
isValidFragment(String fragmentName)250         protected boolean isValidFragment(String fragmentName) {
251             return InternalSetupChooseLockGenericFragment.class.getName().equals(fragmentName);
252         }
253 
254         @Override
getFragmentClass()255         /* package */ Class<? extends Fragment> getFragmentClass() {
256             return InternalSetupChooseLockGenericFragment.class;
257         }
258 
259         public static class InternalSetupChooseLockGenericFragment
260                 extends ChooseLockGenericFragment {
261             @Override
canRunBeforeDeviceProvisioned()262             protected boolean canRunBeforeDeviceProvisioned() {
263                 return true;
264             }
265 
266             @Override
onViewCreated(@otNull View view, Bundle savedInstanceState)267             public void onViewCreated(@NotNull View view, Bundle savedInstanceState) {
268                 super.onViewCreated(view, savedInstanceState);
269 
270                 GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
271                 int titleResource = R.string.lock_settings_picker_new_lock_title;
272 
273                 layout.setHeaderText(titleResource);
274                 setDivider(new ColorDrawable(Color.TRANSPARENT));
275                 setDividerHeight(0);
276                 getHeaderView().setVisible(false);
277             }
278 
279             @Override
getLockPasswordIntent(int quality)280             protected Intent getLockPasswordIntent(int quality) {
281                 final Intent intent = SetupChooseLockPassword.modifyIntentForSetup(
282                         getContext(), super.getLockPasswordIntent(quality));
283                 SetupWizardUtils.copySetupExtras(getIntent(), intent);
284                 return intent;
285             }
286 
287             @Override
getLockPatternIntent()288             protected Intent getLockPatternIntent() {
289                 final Intent intent = SetupChooseLockPattern.modifyIntentForSetup(
290                         getContext(), super.getLockPatternIntent());
291                 SetupWizardUtils.copySetupExtras(getIntent(), intent);
292                 return intent;
293             }
294 
295             @Override
getBiometricEnrollIntent(Context context)296             protected Intent getBiometricEnrollIntent(Context context) {
297                 final Intent intent = super.getBiometricEnrollIntent(context);
298                 SetupWizardUtils.copySetupExtras(getIntent(), intent);
299                 return intent;
300             }
301 
302             @Override
onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)303             public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
304                     Bundle savedInstanceState) {
305                 GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
306                 return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
307             }
308         }
309     }
310 }
311