• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 android.annotation.Nullable;
20 import android.app.Activity;
21 import android.app.Fragment;
22 import android.app.KeyguardManager;
23 import android.app.admin.DevicePolicyManager;
24 import android.content.Intent;
25 import android.content.IntentSender;
26 import android.os.UserManager;
27 
28 import com.android.internal.annotations.VisibleForTesting;
29 import com.android.internal.widget.LockPatternUtils;
30 import com.android.settings.SettingsActivity;
31 import com.android.settings.Utils;
32 import com.android.setupwizardlib.util.WizardManagerHelper;
33 
34 public final class ChooseLockSettingsHelper {
35 
36     public static final String EXTRA_KEY_TYPE = "type";
37     public static final String EXTRA_KEY_PASSWORD = "password";
38     public static final String EXTRA_KEY_RETURN_CREDENTIALS = "return_credentials";
39     public static final String EXTRA_KEY_HAS_CHALLENGE = "has_challenge";
40     public static final String EXTRA_KEY_CHALLENGE = "challenge";
41     public static final String EXTRA_KEY_CHALLENGE_TOKEN = "hw_auth_token";
42     public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
43     public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
44 
45 
46     @VisibleForTesting LockPatternUtils mLockPatternUtils;
47     private Activity mActivity;
48     private Fragment mFragment;
49 
ChooseLockSettingsHelper(Activity activity)50     public ChooseLockSettingsHelper(Activity activity) {
51         mActivity = activity;
52         mLockPatternUtils = new LockPatternUtils(activity);
53     }
54 
ChooseLockSettingsHelper(Activity activity, Fragment fragment)55     public ChooseLockSettingsHelper(Activity activity, Fragment fragment) {
56         this(activity);
57         mFragment = fragment;
58     }
59 
utils()60     public LockPatternUtils utils() {
61         return mLockPatternUtils;
62     }
63 
64     /**
65      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
66      *
67      * @param title title of the confirmation screen; shown in the action bar
68      * @return true if one exists and we launched an activity to confirm it
69      * @see Activity#onActivityResult(int, int, android.content.Intent)
70      */
launchConfirmationActivity(int request, CharSequence title)71     public boolean launchConfirmationActivity(int request, CharSequence title) {
72         return launchConfirmationActivity(request, title, null, null, false, false);
73     }
74 
75     /**
76      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
77      *
78      * @param title title of the confirmation screen; shown in the action bar
79      * @param returnCredentials if true, put credentials into intent. Note that if this is true,
80      *                          this can only be called internally.
81      * @return true if one exists and we launched an activity to confirm it
82      * @see Activity#onActivityResult(int, int, android.content.Intent)
83      */
launchConfirmationActivity(int request, CharSequence title, boolean returnCredentials)84     public boolean launchConfirmationActivity(int request, CharSequence title, boolean returnCredentials) {
85         return launchConfirmationActivity(request, title, null, null, returnCredentials, false);
86     }
87 
88     /**
89      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
90      *
91      * @param title title of the confirmation screen; shown in the action bar
92      * @param returnCredentials if true, put credentials into intent. Note that if this is true,
93      *                          this can only be called internally.
94      * @param userId The userId for whom the lock should be confirmed.
95      * @return true if one exists and we launched an activity to confirm it
96      * @see Activity#onActivityResult(int, int, android.content.Intent)
97      */
launchConfirmationActivity(int request, CharSequence title, boolean returnCredentials, int userId)98     public boolean launchConfirmationActivity(int request, CharSequence title,
99             boolean returnCredentials, int userId) {
100         return launchConfirmationActivity(request, title, null, null,
101                 returnCredentials, false, false, 0, Utils.enforceSameOwner(mActivity, userId));
102     }
103 
104     /**
105      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
106      *
107      * @param title title of the confirmation screen; shown in the action bar
108      * @param header header of the confirmation screen; shown as large text
109      * @param description description of the confirmation screen
110      * @param returnCredentials if true, put credentials into intent. Note that if this is true,
111      *                          this can only be called internally.
112      * @param external specifies whether this activity is launched externally, meaning that it will
113      *                 get a dark theme, allow fingerprint authentication and it will forward
114      *                 activity result.
115      * @return true if one exists and we launched an activity to confirm it
116      * @see Activity#onActivityResult(int, int, android.content.Intent)
117      */
launchConfirmationActivity(int request, @Nullable CharSequence title, @Nullable CharSequence header, @Nullable CharSequence description, boolean returnCredentials, boolean external)118     boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
119             @Nullable CharSequence header, @Nullable CharSequence description,
120             boolean returnCredentials, boolean external) {
121         return launchConfirmationActivity(request, title, header, description,
122                 returnCredentials, external, false, 0, Utils.getCredentialOwnerUserId(mActivity));
123     }
124 
125     /**
126      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
127      *
128      * @param title title of the confirmation screen; shown in the action bar
129      * @param header header of the confirmation screen; shown as large text
130      * @param description description of the confirmation screen
131      * @param returnCredentials if true, put credentials into intent. Note that if this is true,
132      *                          this can only be called internally.
133      * @param external specifies whether this activity is launched externally, meaning that it will
134      *                 get a dark theme, allow fingerprint authentication and it will forward
135      *                 activity result.
136      * @param userId The userId for whom the lock should be confirmed.
137      * @return true if one exists and we launched an activity to confirm it
138      * @see Activity#onActivityResult(int, int, android.content.Intent)
139      */
launchConfirmationActivity(int request, @Nullable CharSequence title, @Nullable CharSequence header, @Nullable CharSequence description, boolean returnCredentials, boolean external, int userId)140     boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
141             @Nullable CharSequence header, @Nullable CharSequence description,
142             boolean returnCredentials, boolean external, int userId) {
143         return launchConfirmationActivity(request, title, header, description,
144                 returnCredentials, external, false, 0, Utils.enforceSameOwner(mActivity, userId));
145     }
146 
147     /**
148      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
149      *
150      * @param title title of the confirmation screen; shown in the action bar
151      * @param header header of the confirmation screen; shown as large text
152      * @param description description of the confirmation screen
153      * @param challenge a challenge to be verified against the device credential.
154      * @return true if one exists and we launched an activity to confirm it
155      * @see Activity#onActivityResult(int, int, android.content.Intent)
156      */
launchConfirmationActivity(int request, @Nullable CharSequence title, @Nullable CharSequence header, @Nullable CharSequence description, long challenge)157     public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
158             @Nullable CharSequence header, @Nullable CharSequence description,
159             long challenge) {
160         return launchConfirmationActivity(request, title, header, description,
161                 true, false, true, challenge, Utils.getCredentialOwnerUserId(mActivity));
162     }
163 
164     /**
165      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
166      *
167      * @param title title of the confirmation screen; shown in the action bar
168      * @param header header of the confirmation screen; shown as large text
169      * @param description description of the confirmation screen
170      * @param challenge a challenge to be verified against the device credential.
171      * @param userId The userId for whom the lock should be confirmed.
172      * @return true if one exists and we launched an activity to confirm it
173      * @see Activity#onActivityResult(int, int, android.content.Intent)
174      */
launchConfirmationActivity(int request, @Nullable CharSequence title, @Nullable CharSequence header, @Nullable CharSequence description, long challenge, int userId)175     public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
176             @Nullable CharSequence header, @Nullable CharSequence description,
177             long challenge, int userId) {
178         return launchConfirmationActivity(request, title, header, description,
179                 true, false, true, challenge, Utils.enforceSameOwner(mActivity, userId));
180     }
181 
182     /**
183      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
184      *
185      * @param title title of the confirmation screen; shown in the action bar
186      * @param header header of the confirmation screen; shown as large text
187      * @param description description of the confirmation screen
188      * @param external specifies whether this activity is launched externally, meaning that it will
189      *                 get a dark theme, allow fingerprint authentication and it will forward
190      *                 activity result.
191      * @param challenge a challenge to be verified against the device credential.
192      * @param userId The userId for whom the lock should be confirmed.
193      * @return true if one exists and we launched an activity to confirm it
194      * @see Activity#onActivityResult(int, int, android.content.Intent)
195      */
launchConfirmationActivityWithExternalAndChallenge(int request, @Nullable CharSequence title, @Nullable CharSequence header, @Nullable CharSequence description, boolean external, long challenge, int userId)196     public boolean launchConfirmationActivityWithExternalAndChallenge(int request,
197             @Nullable CharSequence title, @Nullable CharSequence header,
198             @Nullable CharSequence description, boolean external, long challenge, int userId) {
199         return launchConfirmationActivity(request, title, header, description, false,
200                 external, true, challenge, Utils.enforceSameOwner(mActivity, userId));
201     }
202 
launchConfirmationActivity(int request, @Nullable CharSequence title, @Nullable CharSequence header, @Nullable CharSequence description, boolean returnCredentials, boolean external, boolean hasChallenge, long challenge, int userId)203     private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
204             @Nullable CharSequence header, @Nullable CharSequence description,
205             boolean returnCredentials, boolean external, boolean hasChallenge,
206             long challenge, int userId) {
207         return launchConfirmationActivity(request, title, header, description, returnCredentials,
208                 external, hasChallenge, challenge, userId, null /* alternateButton */);
209     }
210 
launchFrpConfirmationActivity(int request, @Nullable CharSequence header, @Nullable CharSequence description, @Nullable CharSequence alternateButton)211     public boolean launchFrpConfirmationActivity(int request, @Nullable CharSequence header,
212             @Nullable CharSequence description, @Nullable CharSequence alternateButton) {
213         return launchConfirmationActivity(request, null /* title */, header, description,
214                 false /* returnCredentials */, true /* external */, false /* hasChallenge */,
215                 0 /* challenge */, LockPatternUtils.USER_FRP, alternateButton);
216     }
217 
launchConfirmationActivity(int request, @Nullable CharSequence title, @Nullable CharSequence header, @Nullable CharSequence description, boolean returnCredentials, boolean external, boolean hasChallenge, long challenge, int userId, @Nullable CharSequence alternateButton)218     private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
219             @Nullable CharSequence header, @Nullable CharSequence description,
220             boolean returnCredentials, boolean external, boolean hasChallenge,
221             long challenge, int userId, @Nullable CharSequence alternateButton) {
222         final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
223         boolean launched = false;
224 
225         switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(effectiveUserId)) {
226             case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
227                 launched = launchConfirmationActivity(request, title, header, description,
228                         returnCredentials || hasChallenge
229                                 ? ConfirmLockPattern.InternalActivity.class
230                                 : ConfirmLockPattern.class, returnCredentials, external,
231                                 hasChallenge, challenge, userId, alternateButton);
232                 break;
233             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
234             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
235             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
236             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
237             case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
238             case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
239                 launched = launchConfirmationActivity(request, title, header, description,
240                         returnCredentials || hasChallenge
241                                 ? ConfirmLockPassword.InternalActivity.class
242                                 : ConfirmLockPassword.class, returnCredentials, external,
243                                 hasChallenge, challenge, userId, alternateButton);
244                 break;
245         }
246         return launched;
247     }
248 
launchConfirmationActivity(int request, CharSequence title, CharSequence header, CharSequence message, Class<?> activityClass, boolean returnCredentials, boolean external, boolean hasChallenge, long challenge, int userId, @Nullable CharSequence alternateButton)249     private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
250             CharSequence message, Class<?> activityClass, boolean returnCredentials,
251             boolean external, boolean hasChallenge, long challenge,
252             int userId, @Nullable CharSequence alternateButton) {
253         final boolean frp = (userId == LockPatternUtils.USER_FRP);
254         final Intent intent = new Intent();
255         intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
256         intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
257         intent.putExtra(ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT, message);
258         intent.putExtra(ConfirmDeviceCredentialBaseFragment.ALLOW_FP_AUTHENTICATION, external);
259         intent.putExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, external && !frp);
260         intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_CANCEL_BUTTON, external);
261         intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external);
262         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, returnCredentials);
263         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, hasChallenge);
264         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
265         // we should never have a drawer when confirming device credentials.
266         intent.putExtra(SettingsActivity.EXTRA_HIDE_DRAWER, true);
267         intent.putExtra(Intent.EXTRA_USER_ID, userId);
268         intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
269         intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName());
270         if (external) {
271             intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
272             if (mFragment != null) {
273                 copyOptionalExtras(mFragment.getActivity().getIntent(), intent);
274                 mFragment.startActivity(intent);
275             } else {
276                 copyOptionalExtras(mActivity.getIntent(), intent);
277                 mActivity.startActivity(intent);
278             }
279         } else {
280             if (mFragment != null) {
281                 copyInternalExtras(mFragment.getActivity().getIntent(), intent);
282                 mFragment.startActivityForResult(intent, request);
283             } else {
284                 copyInternalExtras(mActivity.getIntent(), intent);
285                 mActivity.startActivityForResult(intent, request);
286             }
287         }
288         return true;
289     }
290 
copyOptionalExtras(Intent inIntent, Intent outIntent)291     private void copyOptionalExtras(Intent inIntent, Intent outIntent) {
292         IntentSender intentSender = inIntent.getParcelableExtra(Intent.EXTRA_INTENT);
293         if (intentSender != null) {
294             outIntent.putExtra(Intent.EXTRA_INTENT, intentSender);
295         }
296         int taskId = inIntent.getIntExtra(Intent.EXTRA_TASK_ID, -1);
297         if (taskId != -1) {
298             outIntent.putExtra(Intent.EXTRA_TASK_ID, taskId);
299         }
300         // If we will launch another activity once credentials are confirmed, exclude from recents.
301         // This is a workaround to a framework bug where affinity is incorrect for activities
302         // that are started from a no display activity, as is ConfirmDeviceCredentialActivity.
303         // TODO: Remove once that bug is fixed.
304         if (intentSender != null || taskId != -1) {
305             outIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
306             outIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
307         }
308     }
309 
copyInternalExtras(Intent inIntent, Intent outIntent)310     private void copyInternalExtras(Intent inIntent, Intent outIntent) {
311         String theme = inIntent.getStringExtra(WizardManagerHelper.EXTRA_THEME);
312         if (theme != null) {
313             outIntent.putExtra(WizardManagerHelper.EXTRA_THEME, theme);
314         }
315     }
316 }
317