1 /*
2  * Copyright (C) 2016 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.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
21 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
22 import static android.app.admin.DevicePolicyManager.EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY;
23 import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
24 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
25 
26 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME;
27 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CHOOSE_LOCK_SCREEN_DESCRIPTION;
28 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CHOOSE_LOCK_SCREEN_TITLE;
29 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY;
30 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FINGERPRINT_ENROLLMENT_ONLY;
31 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN;
32 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
33 
34 import android.app.Activity;
35 import android.app.RemoteServiceException.MissingRequestPasswordComplexityPermissionException;
36 import android.app.admin.DevicePolicyManager;
37 import android.app.admin.DevicePolicyManager.PasswordComplexity;
38 import android.app.admin.PasswordMetrics;
39 import android.app.settings.SettingsEnums;
40 import android.content.ComponentName;
41 import android.content.Intent;
42 import android.os.Bundle;
43 import android.os.IBinder;
44 import android.util.Log;
45 
46 import com.android.settings.overlay.FeatureFactory;
47 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
48 
49 import com.google.android.setupcompat.util.WizardManagerHelper;
50 
51 import java.util.List;
52 
53 /**
54  * Trampolines {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD} and
55  * {@link DevicePolicyManager#ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} intent to the appropriate UI
56  * activity for handling set new password.
57  */
58 public class SetNewPasswordActivity extends Activity implements SetNewPasswordController.Ui {
59     private static final String TAG = "SetNewPasswordActivity";
60     private String mNewPasswordAction;
61     private SetNewPasswordController mSetNewPasswordController;
62 
63     /**
64      * From intent extra {@link DevicePolicyManager#EXTRA_PASSWORD_COMPLEXITY}.
65      *
66      * <p>This is used only if caller has the required permission and activity is launched by
67      * {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD}.
68      */
69     private @PasswordComplexity int mRequestedMinComplexity = PASSWORD_COMPLEXITY_NONE;
70 
71     private boolean mDevicePasswordRequirementOnly = false;
72 
73     /**
74      * Label of the app which launches this activity.
75      *
76      * <p>Value would be {@code null} if launched from settings app.
77      */
78     private String mCallerAppName = null;
79 
80     @Override
onCreate(Bundle savedState)81     protected void onCreate(Bundle savedState) {
82         super.onCreate(savedState);
83         final Intent intent = getIntent();
84 
85         mNewPasswordAction = intent.getAction();
86         if (!ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction)
87                 && !ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(mNewPasswordAction)) {
88             Log.e(TAG, "Unexpected action to launch this activity");
89             finish();
90             return;
91         }
92         logSetNewPasswordIntent();
93 
94         final IBinder activityToken = getActivityToken();
95         mCallerAppName = (String) PasswordUtils.getCallingAppLabel(this, activityToken);
96         if (ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction)
97                 && intent.hasExtra(EXTRA_PASSWORD_COMPLEXITY)) {
98             final boolean hasPermission = PasswordUtils.isCallingAppPermitted(
99                     this, activityToken, REQUEST_PASSWORD_COMPLEXITY);
100             if (hasPermission) {
101                 mRequestedMinComplexity =
102                         PasswordMetrics.sanitizeComplexityLevel(intent.getIntExtra(
103                                 EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE));
104             } else {
105                 PasswordUtils.crashCallingApplication(activityToken,
106                         "Must have permission "
107                                 + REQUEST_PASSWORD_COMPLEXITY + " to use extra "
108                                 + EXTRA_PASSWORD_COMPLEXITY,
109                         MissingRequestPasswordComplexityPermissionException.TYPE_ID);
110                 finish();
111                 return;
112             }
113         }
114         if (ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(mNewPasswordAction)) {
115             mDevicePasswordRequirementOnly = intent.getBooleanExtra(
116                     EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY, false);
117             Log.i(TAG, String.format("DEVICE_PASSWORD_REQUIREMENT_ONLY: %b",
118                     mDevicePasswordRequirementOnly));
119         }
120         mSetNewPasswordController = SetNewPasswordController.create(
121                 this, this, intent, activityToken);
122         mSetNewPasswordController.dispatchSetNewPasswordIntent();
123     }
124 
125     @Override
launchChooseLock(Bundle chooseLockFingerprintExtras)126     public void launchChooseLock(Bundle chooseLockFingerprintExtras) {
127         final boolean isInSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
128         Intent intent = isInSetupWizard ? new Intent(this, SetupChooseLockGeneric.class)
129                 : new Intent(this, ChooseLockGeneric.class);
130         intent.setAction(mNewPasswordAction);
131         intent.putExtras(chooseLockFingerprintExtras);
132         intent.putExtra(EXTRA_KEY_CHOOSE_LOCK_SCREEN_TITLE,
133                 getIntent().getIntExtra(EXTRA_KEY_CHOOSE_LOCK_SCREEN_TITLE, -1));
134         intent.putExtra(EXTRA_KEY_CHOOSE_LOCK_SCREEN_DESCRIPTION,
135                 getIntent().getIntExtra(EXTRA_KEY_CHOOSE_LOCK_SCREEN_DESCRIPTION, -1));
136         intent.putExtra(EXTRA_KEY_FINGERPRINT_ENROLLMENT_ONLY,
137                 getIntent().getBooleanExtra(EXTRA_KEY_FINGERPRINT_ENROLLMENT_ONLY, false));
138         if (mCallerAppName != null) {
139             intent.putExtra(EXTRA_KEY_CALLER_APP_NAME, mCallerAppName);
140         }
141         if (mRequestedMinComplexity != PASSWORD_COMPLEXITY_NONE) {
142             intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, mRequestedMinComplexity);
143         }
144         if (isCallingAppAdmin()) {
145             intent.putExtra(EXTRA_KEY_IS_CALLING_APP_ADMIN, true);
146         }
147         intent.putExtra(EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, mDevicePasswordRequirementOnly);
148         // Copy the setup wizard intent extra to the intent.
149         WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
150         startActivity(intent);
151         finish();
152     }
153 
isCallingAppAdmin()154     private boolean isCallingAppAdmin() {
155         DevicePolicyManager devicePolicyManager = getSystemService(DevicePolicyManager.class);
156         String callingAppPackageName = PasswordUtils.getCallingAppPackageName(getActivityToken());
157         List<ComponentName> admins = devicePolicyManager.getActiveAdmins();
158         if (admins == null) {
159             return false;
160         }
161         for (ComponentName componentName : admins) {
162             if (componentName.getPackageName().equals(callingAppPackageName)) {
163                 return true;
164             }
165         }
166         return false;
167     }
168 
logSetNewPasswordIntent()169     private void logSetNewPasswordIntent() {
170         final String callingAppPackageName =
171                 PasswordUtils.getCallingAppPackageName(getActivityToken());
172 
173         // use int min value to denote absence of EXTRA_PASSWORD_COMPLEXITY
174         final int extraPasswordComplexity = getIntent().hasExtra(EXTRA_PASSWORD_COMPLEXITY)
175                 ? getIntent().getIntExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)
176                 : Integer.MIN_VALUE;
177 
178         final boolean extraDevicePasswordRequirementOnly = getIntent().getBooleanExtra(
179                 EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY, false);
180 
181         // Use 30th bit to encode extraDevicePasswordRequirementOnly, since the top bit (31th bit)
182         // encodes whether EXTRA_PASSWORD_COMPLEXITY has been absent.
183         final int logValue = extraPasswordComplexity
184                 | (extraDevicePasswordRequirementOnly ? 1 << 30 : 0);
185         // this activity is launched by either ACTION_SET_NEW_PASSWORD or
186         // ACTION_SET_NEW_PARENT_PROFILE_PASSWORD
187         final int action = ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction)
188                 ? SettingsEnums.ACTION_SET_NEW_PASSWORD
189                 : SettingsEnums.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
190 
191         final MetricsFeatureProvider metricsProvider =
192                 FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
193         metricsProvider.action(
194                 metricsProvider.getAttribution(this),
195                 action,
196                 SettingsEnums.SET_NEW_PASSWORD_ACTIVITY,
197                 callingAppPackageName,
198                 logValue);
199     }
200 }
201