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