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.admin.DevicePolicyManager; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.res.Resources; 28 import android.os.Bundle; 29 import android.os.IBinder; 30 import android.os.UserHandle; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.LinearLayout; 35 36 import androidx.fragment.app.Fragment; 37 import androidx.preference.Preference; 38 import androidx.preference.PreferenceFragmentCompat; 39 import androidx.recyclerview.widget.RecyclerView; 40 41 import com.android.internal.widget.LockPatternUtils; 42 import com.android.settings.R; 43 import com.android.settings.SetupEncryptionInterstitial; 44 import com.android.settings.SetupWizardUtils; 45 import com.android.settings.biometrics.BiometricEnrollActivity; 46 import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFindSensor; 47 import com.android.settings.utils.SettingsDividerItemDecoration; 48 49 import com.google.android.setupdesign.GlifPreferenceLayout; 50 51 /** 52 * Setup Wizard's version of ChooseLockGeneric screen. It inherits the logic and basic structure 53 * from ChooseLockGeneric class, and should remain similar to that behaviorally. This class should 54 * only overload base methods for minor theme and behavior differences specific to Setup Wizard. 55 * Other changes should be done to ChooseLockGeneric class instead and let this class inherit 56 * those changes. 57 */ 58 // TODO(b/123225425): Restrict SetupChooseLockGeneric to be accessible by SUW only 59 public class SetupChooseLockGeneric extends ChooseLockGeneric { 60 61 private static final String KEY_UNLOCK_SET_DO_LATER = "unlock_set_do_later"; 62 63 @Override isValidFragment(String fragmentName)64 protected boolean isValidFragment(String fragmentName) { 65 return SetupChooseLockGenericFragment.class.getName().equals(fragmentName); 66 } 67 68 @Override getFragmentClass()69 /* package */ Class<? extends PreferenceFragmentCompat> getFragmentClass() { 70 return SetupChooseLockGenericFragment.class; 71 } 72 73 @Override onApplyThemeResource(Resources.Theme theme, int resid, boolean first)74 protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) { 75 resid = SetupWizardUtils.getTheme(getIntent()); 76 super.onApplyThemeResource(theme, resid, first); 77 } 78 79 @Override onCreate(Bundle savedInstance)80 protected void onCreate(Bundle savedInstance) { 81 super.onCreate(savedInstance); 82 83 if(getIntent().hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)) { 84 IBinder activityToken = getActivityToken(); 85 boolean hasPermission = PasswordUtils.isCallingAppPermitted( 86 this, activityToken, REQUEST_PASSWORD_COMPLEXITY); 87 if (!hasPermission) { 88 PasswordUtils.crashCallingApplication(activityToken, 89 "Must have permission " + REQUEST_PASSWORD_COMPLEXITY 90 + " to use extra " + EXTRA_PASSWORD_COMPLEXITY); 91 finish(); 92 return; 93 } 94 } 95 96 findViewById(R.id.content_parent).setFitsSystemWindows(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 /*** 167 * Disables preferences that are less secure than required quality and shows only secure 168 * screen lock options here. 169 * 170 * @param quality the requested quality. 171 */ 172 @Override disableUnusablePreferences(final int quality, boolean hideDisabled)173 protected void disableUnusablePreferences(final int quality, boolean hideDisabled) { 174 // At this part of the flow, the user has already indicated they want to add a pin, 175 // pattern or password, so don't show "None" or "Slide". We disable them here and set 176 // the HIDE_DISABLED flag to true to hide them. This only happens for setup wizard. 177 // We do the following max check here since the device may already have a Device Admin 178 // installed with a policy we need to honor. 179 final int newQuality = Math.max(quality, 180 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 181 super.disableUnusablePreferencesImpl(newQuality, true /* hideDisabled */); 182 } 183 184 @Override addPreferences()185 protected void addPreferences() { 186 if (isForBiometric()) { 187 super.addPreferences(); 188 } else { 189 addPreferencesFromResource(R.xml.setup_security_settings_picker); 190 } 191 } 192 193 @Override onPreferenceTreeClick(Preference preference)194 public boolean onPreferenceTreeClick(Preference preference) { 195 final String key = preference.getKey(); 196 if (KEY_UNLOCK_SET_DO_LATER.equals(key)) { 197 // show warning. 198 SetupSkipDialog dialog = SetupSkipDialog.newInstance( 199 getActivity().getIntent() 200 .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false), 201 /* isPatternMode= */ false, 202 /* isAlphaMode= */ false, 203 /* isFingerprintSupported= */ false, 204 /* isFaceSupported= */ false 205 ); 206 dialog.show(getFragmentManager()); 207 return true; 208 } 209 return super.onPreferenceTreeClick(preference); 210 } 211 212 @Override getLockPasswordIntent(int quality)213 protected Intent getLockPasswordIntent(int quality) { 214 final Intent intent = SetupChooseLockPassword.modifyIntentForSetup( 215 getContext(), super.getLockPasswordIntent(quality)); 216 SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent); 217 return intent; 218 } 219 220 @Override getLockPatternIntent()221 protected Intent getLockPatternIntent() { 222 final Intent intent = SetupChooseLockPattern.modifyIntentForSetup( 223 getContext(), super.getLockPatternIntent()); 224 SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent); 225 return intent; 226 } 227 228 @Override getEncryptionInterstitialIntent(Context context, int quality, boolean required, Intent unlockMethodIntent)229 protected Intent getEncryptionInterstitialIntent(Context context, int quality, 230 boolean required, Intent unlockMethodIntent) { 231 Intent intent = SetupEncryptionInterstitial.createStartIntent(context, quality, 232 required, unlockMethodIntent); 233 SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent); 234 return intent; 235 } 236 237 @Override getBiometricEnrollIntent(Context context)238 protected Intent getBiometricEnrollIntent(Context context) { 239 final Intent intent = super.getBiometricEnrollIntent(context); 240 SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent); 241 return intent; 242 } 243 isForBiometric()244 private boolean isForBiometric() { 245 return mForFingerprint || mForFace; 246 } 247 } 248 249 public static class InternalActivity extends ChooseLockGeneric.InternalActivity { 250 @Override isValidFragment(String fragmentName)251 protected boolean isValidFragment(String fragmentName) { 252 return InternalSetupChooseLockGenericFragment.class.getName().equals(fragmentName); 253 } 254 255 @Override getFragmentClass()256 /* package */ Class<? extends Fragment> getFragmentClass() { 257 return InternalSetupChooseLockGenericFragment.class; 258 } 259 260 public static class InternalSetupChooseLockGenericFragment 261 extends ChooseLockGenericFragment { 262 @Override canRunBeforeDeviceProvisioned()263 protected boolean canRunBeforeDeviceProvisioned() { 264 return true; 265 } 266 } 267 } 268 } 269