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