1 /* 2 * Copyright (C) 2018 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.security; 18 19 import static com.android.settings.security.SecuritySettings.UNIFY_LOCK_CONFIRM_DEVICE_REQUEST; 20 import static com.android.settings.security.SecuritySettings.UNIFY_LOCK_CONFIRM_PROFILE_REQUEST; 21 import static com.android.settings.security.SecuritySettings.UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST; 22 23 import android.app.Activity; 24 import android.app.admin.DevicePolicyManager; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.os.Bundle; 28 import android.os.UserHandle; 29 import android.os.UserManager; 30 import android.support.v7.preference.Preference; 31 import android.support.v7.preference.PreferenceScreen; 32 33 import com.android.internal.widget.LockPatternUtils; 34 import com.android.settings.R; 35 import com.android.settings.Utils; 36 import com.android.settings.core.PreferenceControllerMixin; 37 import com.android.settings.core.SubSettingLauncher; 38 import com.android.settings.overlay.FeatureFactory; 39 import com.android.settings.password.ChooseLockGeneric; 40 import com.android.settings.password.ChooseLockSettingsHelper; 41 import com.android.settingslib.RestrictedLockUtils; 42 import com.android.settingslib.RestrictedSwitchPreference; 43 import com.android.settingslib.core.AbstractPreferenceController; 44 45 public class LockUnificationPreferenceController extends AbstractPreferenceController 46 implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener { 47 48 private static final String KEY_UNIFICATION = "unification"; 49 50 private static final int MY_USER_ID = UserHandle.myUserId(); 51 52 private final UserManager mUm; 53 private final LockPatternUtils mLockPatternUtils; 54 private final int mProfileChallengeUserId; 55 private final SecuritySettings mHost; 56 57 private RestrictedSwitchPreference mUnifyProfile; 58 59 60 private String mCurrentDevicePassword; 61 private String mCurrentProfilePassword; 62 63 @Override 64 public void displayPreference(PreferenceScreen screen) { 65 super.displayPreference(screen); 66 mUnifyProfile = (RestrictedSwitchPreference) screen.findPreference(KEY_UNIFICATION); 67 } 68 69 public LockUnificationPreferenceController(Context context, SecuritySettings host) { 70 super(context); 71 mHost = host; 72 mUm = (UserManager) context.getSystemService(Context.USER_SERVICE); 73 mLockPatternUtils = FeatureFactory.getFactory(context) 74 .getSecurityFeatureProvider() 75 .getLockPatternUtils(context); 76 mProfileChallengeUserId = Utils.getManagedProfileId(mUm, MY_USER_ID); 77 } 78 79 @Override 80 public boolean isAvailable() { 81 final boolean allowSeparateProfileChallenge = 82 mProfileChallengeUserId != UserHandle.USER_NULL 83 && mLockPatternUtils.isSeparateProfileChallengeAllowed( 84 mProfileChallengeUserId); 85 return allowSeparateProfileChallenge; 86 } 87 88 @Override 89 public String getPreferenceKey() { 90 return KEY_UNIFICATION; 91 } 92 93 @Override 94 public boolean onPreferenceChange(Preference preference, Object value) { 95 if (Utils.startQuietModeDialogIfNecessary(mContext, mUm, mProfileChallengeUserId)) { 96 return false; 97 } 98 if ((Boolean) value) { 99 final boolean compliantForDevice = 100 (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId) 101 >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING 102 && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify( 103 mProfileChallengeUserId)); 104 UnificationConfirmationDialog dialog = 105 UnificationConfirmationDialog.newInstance(compliantForDevice); 106 dialog.show(mHost); 107 } else { 108 final String title = mContext.getString(R.string.unlock_set_unlock_launch_picker_title); 109 final ChooseLockSettingsHelper helper = 110 new ChooseLockSettingsHelper(mHost.getActivity(), mHost); 111 if (!helper.launchConfirmationActivity( 112 UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST, 113 title, true /* returnCredentials */, MY_USER_ID)) { 114 ununifyLocks(); 115 } 116 } 117 return true; 118 } 119 120 @Override 121 public void updateState(Preference preference) { 122 if (mUnifyProfile != null) { 123 final boolean separate = 124 mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId); 125 mUnifyProfile.setChecked(!separate); 126 if (separate) { 127 mUnifyProfile.setDisabledByAdmin(RestrictedLockUtils.checkIfRestrictionEnforced( 128 mContext, UserManager.DISALLOW_UNIFIED_PASSWORD, 129 mProfileChallengeUserId)); 130 } 131 } 132 } 133 134 public boolean handleActivityResult(int requestCode, int resultCode, Intent data) { 135 if (requestCode == UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST 136 && resultCode == Activity.RESULT_OK) { 137 ununifyLocks(); 138 return true; 139 } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST 140 && resultCode == Activity.RESULT_OK) { 141 mCurrentDevicePassword = 142 data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 143 launchConfirmProfileLockForUnification(); 144 return true; 145 } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST 146 && resultCode == Activity.RESULT_OK) { 147 mCurrentProfilePassword = 148 data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 149 unifyLocks(); 150 return true; 151 } 152 return false; 153 } 154 155 private void ununifyLocks() { 156 final Bundle extras = new Bundle(); 157 extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId); 158 new SubSettingLauncher(mContext) 159 .setDestination(ChooseLockGeneric.ChooseLockGenericFragment.class.getName()) 160 .setTitle(R.string.lock_settings_picker_title_profile) 161 .setSourceMetricsCategory(mHost.getMetricsCategory()) 162 .setArguments(extras) 163 .launch(); 164 } 165 166 void launchConfirmDeviceLockForUnification() { 167 final String title = mContext.getString( 168 R.string.unlock_set_unlock_launch_picker_title); 169 final ChooseLockSettingsHelper helper = 170 new ChooseLockSettingsHelper(mHost.getActivity(), mHost); 171 if (!helper.launchConfirmationActivity( 172 UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, MY_USER_ID)) { 173 launchConfirmProfileLockForUnification(); 174 } 175 } 176 177 private void launchConfirmProfileLockForUnification() { 178 final String title = mContext.getString( 179 R.string.unlock_set_unlock_launch_picker_title_profile); 180 final ChooseLockSettingsHelper helper = 181 new ChooseLockSettingsHelper(mHost.getActivity(), mHost); 182 if (!helper.launchConfirmationActivity( 183 UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileChallengeUserId)) { 184 unifyLocks(); 185 // TODO: update relevant prefs. 186 // createPreferenceHierarchy(); 187 } 188 } 189 190 private void unifyLocks() { 191 int profileQuality = 192 mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId); 193 if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { 194 mLockPatternUtils.saveLockPattern( 195 LockPatternUtils.stringToPattern(mCurrentProfilePassword), 196 mCurrentDevicePassword, MY_USER_ID); 197 } else { 198 mLockPatternUtils.saveLockPassword( 199 mCurrentProfilePassword, mCurrentDevicePassword, 200 profileQuality, MY_USER_ID); 201 } 202 mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false, 203 mCurrentProfilePassword); 204 final boolean profilePatternVisibility = 205 mLockPatternUtils.isVisiblePatternEnabled(mProfileChallengeUserId); 206 mLockPatternUtils.setVisiblePatternEnabled(profilePatternVisibility, MY_USER_ID); 207 mCurrentDevicePassword = null; 208 mCurrentProfilePassword = null; 209 } 210 211 void unifyUncompliantLocks() { 212 mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false, 213 mCurrentProfilePassword); 214 new SubSettingLauncher(mContext) 215 .setDestination(ChooseLockGeneric.ChooseLockGenericFragment.class.getName()) 216 .setTitle(R.string.lock_settings_picker_title) 217 .setSourceMetricsCategory(mHost.getMetricsCategory()) 218 .launch(); 219 } 220 221 } 222