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