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 setTheme(R.style.SettingsPreferenceTheme_SetupWizard); 79 ThemeHelper.trySetDynamicColor(this); 80 super.onCreate(savedInstance); 81 82 if(getIntent().hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)) { 83 IBinder activityToken = getActivityToken(); 84 boolean hasPermission = PasswordUtils.isCallingAppPermitted( 85 this, activityToken, REQUEST_PASSWORD_COMPLEXITY); 86 if (!hasPermission) { 87 PasswordUtils.crashCallingApplication(activityToken, 88 "Must have permission " + REQUEST_PASSWORD_COMPLEXITY 89 + " to use extra " + EXTRA_PASSWORD_COMPLEXITY, 90 MissingRequestPasswordComplexityPermissionException.TYPE_ID); 91 finish(); 92 return; 93 } 94 } 95 96 findViewById(R.id.content_parent).setFitsSystemWindows(false); 97 } 98 99 @Override isToolbarEnabled()100 protected boolean isToolbarEnabled() { 101 // Hide the action bar from this page. 102 return false; 103 } 104 105 public static class SetupChooseLockGenericFragment extends ChooseLockGenericFragment { 106 107 public static final String EXTRA_PASSWORD_QUALITY = ":settings:password_quality"; 108 109 @Override onViewCreated(View view, Bundle savedInstanceState)110 public void onViewCreated(View view, Bundle savedInstanceState) { 111 super.onViewCreated(view, savedInstanceState); 112 113 GlifPreferenceLayout layout = (GlifPreferenceLayout) view; 114 layout.setDescriptionText(loadDescriptionText()); 115 layout.setDividerItemDecoration(new SettingsDividerItemDecoration(getContext())); 116 layout.setDividerInset(getContext().getResources().getDimensionPixelSize( 117 com.google.android.setupdesign.R.dimen.sud_items_glif_text_divider_inset)); 118 119 layout.setIcon(getContext().getDrawable(R.drawable.ic_lock)); 120 121 int titleResource = isForBiometric() ? 122 R.string.lock_settings_picker_title : R.string.setup_lock_settings_picker_title; 123 if (getActivity() != null) { 124 getActivity().setTitle(titleResource); 125 } 126 127 layout.setHeaderText(titleResource); 128 // Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in 129 // PreferenceFragment. 130 setDivider(null); 131 } 132 133 @Override addHeaderView()134 protected void addHeaderView() { 135 // The original logic has been moved to onViewCreated and 136 // uses GlifLayout#setDescriptionText instead, 137 // keep empty body here since we won't call super method. 138 } 139 140 @Override onActivityResult(int requestCode, int resultCode, Intent data)141 public void onActivityResult(int requestCode, int resultCode, Intent data) { 142 if (data == null) { 143 data = new Intent(); 144 } 145 // Add the password quality extra to the intent data that will be sent back for 146 // Setup Wizard. 147 LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity()); 148 data.putExtra(EXTRA_PASSWORD_QUALITY, 149 lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId())); 150 151 super.onActivityResult(requestCode, resultCode, data); 152 } 153 154 @Override onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)155 public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, 156 Bundle savedInstanceState) { 157 GlifPreferenceLayout layout = (GlifPreferenceLayout) parent; 158 return layout.onCreateRecyclerView(inflater, parent, savedInstanceState); 159 } 160 161 @Override canRunBeforeDeviceProvisioned()162 protected boolean canRunBeforeDeviceProvisioned() { 163 return true; 164 } 165 166 @Override getInternalActivityClass()167 protected Class<? extends ChooseLockGeneric.InternalActivity> getInternalActivityClass() { 168 return SetupChooseLockGeneric.InternalActivity.class; 169 } 170 171 @Override alwaysHideInsecureScreenLockTypes()172 protected boolean alwaysHideInsecureScreenLockTypes() { 173 // At this part of the flow, the user has already indicated they want to add a pin, 174 // pattern or password, so don't show "None" or "Slide". We disable them here. 175 // This only happens for setup wizard. 176 return true; 177 } 178 179 @Override addPreferences()180 protected void addPreferences() { 181 if (isForBiometric()) { 182 super.addPreferences(); 183 } else { 184 addPreferencesFromResource(R.xml.setup_security_settings_picker); 185 } 186 } 187 188 @Override onPreferenceTreeClick(Preference preference)189 public boolean onPreferenceTreeClick(Preference preference) { 190 final String key = preference.getKey(); 191 if (KEY_UNLOCK_SET_DO_LATER.equals(key)) { 192 // show warning. 193 final Intent intent = getActivity().getIntent(); 194 SetupSkipDialog dialog = SetupSkipDialog.newInstance( 195 CREDENTIAL_TYPE_NONE, 196 intent.getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false), 197 /* forFingerprint= */ false, 198 /* forFace= */ false, 199 /* forBiometrics= */ false, 200 WizardManagerHelper.isAnySetupWizard(intent) 201 ); 202 dialog.show(getFragmentManager()); 203 return true; 204 } 205 return super.onPreferenceTreeClick(preference); 206 } 207 208 @Override getLockPasswordIntent(int quality)209 protected Intent getLockPasswordIntent(int quality) { 210 final Intent intent = SetupChooseLockPassword.modifyIntentForSetup( 211 getContext(), super.getLockPasswordIntent(quality)); 212 SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent); 213 return intent; 214 } 215 216 @Override getLockPatternIntent()217 protected Intent getLockPatternIntent() { 218 final Intent intent = SetupChooseLockPattern.modifyIntentForSetup( 219 getContext(), super.getLockPatternIntent()); 220 SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent); 221 return intent; 222 } 223 224 @Override getBiometricEnrollIntent(Context context)225 protected Intent getBiometricEnrollIntent(Context context) { 226 final Intent intent = super.getBiometricEnrollIntent(context); 227 SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent); 228 return intent; 229 } 230 isForBiometric()231 private boolean isForBiometric() { 232 return mForFingerprint || mForFace || mForBiometrics; 233 } 234 loadDescriptionText()235 String loadDescriptionText() { 236 return getString(isForBiometric() 237 ? R.string.lock_settings_picker_biometrics_added_security_message 238 : R.string.setup_lock_settings_picker_message); 239 } 240 } 241 242 public static class InternalActivity extends ChooseLockGeneric.InternalActivity { 243 @Override onCreate(Bundle savedState)244 protected void onCreate(Bundle savedState) { 245 setTheme(SetupWizardUtils.getTheme(this, getIntent())); 246 ThemeHelper.trySetDynamicColor(this); 247 super.onCreate(savedState); 248 } 249 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 @Override onViewCreated(@otNull View view, Bundle savedInstanceState)268 public void onViewCreated(@NotNull View view, Bundle savedInstanceState) { 269 super.onViewCreated(view, savedInstanceState); 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