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