From 52681ece0454f830401388a71f0db4ff8b1d126b Mon Sep 17 00:00:00 2001 From: Clara Bayarri Date: Thu, 28 Jan 2016 11:11:35 +0000 Subject: [PATCH] Move Profile Security Settings into Security Settings UX requested that we have the settings directly in Security instead of having a separate screen as implemented previously. Bug: 26806582 Change-Id: I55c44848621498afe63d3207a52c974c58f9eb78 --- res/values/strings.xml | 10 + .../security_settings_lockscreen_profile.xml | 28 ++ .../security_settings_password_profile.xml | 28 ++ res/xml/security_settings_pattern_profile.xml | 32 ++ res/xml/security_settings_pin_profile.xml | 28 ++ res/xml/security_settings_profile.xml | 6 - res/xml/security_settings_unification.xml | 28 ++ .../ProfileChallengePreferenceFragment.java | 351 ------------------ .../android/settings/SecuritySettings.java | 251 ++++++++++--- 9 files changed, 362 insertions(+), 400 deletions(-) create mode 100644 res/xml/security_settings_lockscreen_profile.xml create mode 100644 res/xml/security_settings_password_profile.xml create mode 100644 res/xml/security_settings_pattern_profile.xml create mode 100644 res/xml/security_settings_pin_profile.xml create mode 100644 res/xml/security_settings_unification.xml delete mode 100644 src/com/android/settings/ProfileChallengePreferenceFragment.java diff --git a/res/values/strings.xml b/res/values/strings.xml index f9e670f6961..2006a31df59 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -990,6 +990,9 @@ Choose screen lock + + Choose profile screen lock + Protect your phone @@ -1010,6 +1013,10 @@ Screen lock + + + Profile screen lock + Change lock screen @@ -3122,6 +3129,8 @@ Must draw pattern to unlock screen Make pattern visible + + Make profile pattern visible Vibrate on tap @@ -5741,6 +5750,7 @@ color temperature D65 D73 white yellow blue warm cool slide to unlock, password, pattern, PIN work challenge, work, profile + work profile, managed profile, unify, unification, work, profile diff --git a/res/xml/security_settings_lockscreen_profile.xml b/res/xml/security_settings_lockscreen_profile.xml new file mode 100644 index 00000000000..8f99c62fd57 --- /dev/null +++ b/res/xml/security_settings_lockscreen_profile.xml @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/res/xml/security_settings_password_profile.xml b/res/xml/security_settings_password_profile.xml new file mode 100644 index 00000000000..7aff0fd700a --- /dev/null +++ b/res/xml/security_settings_password_profile.xml @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/res/xml/security_settings_pattern_profile.xml b/res/xml/security_settings_pattern_profile.xml new file mode 100644 index 00000000000..2010e0d0187 --- /dev/null +++ b/res/xml/security_settings_pattern_profile.xml @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/res/xml/security_settings_pin_profile.xml b/res/xml/security_settings_pin_profile.xml new file mode 100644 index 00000000000..5c830727739 --- /dev/null +++ b/res/xml/security_settings_pin_profile.xml @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/res/xml/security_settings_profile.xml b/res/xml/security_settings_profile.xml index 1c10b794789..55dd8efe0ca 100644 --- a/res/xml/security_settings_profile.xml +++ b/res/xml/security_settings_profile.xml @@ -22,12 +22,6 @@ android:key="security_category_profile" android:title="@string/lock_settings_profile_title"> - - diff --git a/res/xml/security_settings_unification.xml b/res/xml/security_settings_unification.xml new file mode 100644 index 00000000000..ac8d5b241da --- /dev/null +++ b/res/xml/security_settings_unification.xml @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/src/com/android/settings/ProfileChallengePreferenceFragment.java b/src/com/android/settings/ProfileChallengePreferenceFragment.java deleted file mode 100644 index 4c654418e61..00000000000 --- a/src/com/android/settings/ProfileChallengePreferenceFragment.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.settings; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.app.FragmentManager; -import android.app.admin.DevicePolicyManager; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.UserInfo; -import android.hardware.fingerprint.Fingerprint; -import android.hardware.fingerprint.FingerprintManager; -import android.os.Bundle; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.ListPreference; -import android.support.v7.preference.Preference; -import android.support.v7.preference.Preference.OnPreferenceChangeListener; -import android.support.v7.preference.Preference.OnPreferenceClickListener; -import android.util.Log; -import android.support.v7.preference.PreferenceCategory; -import android.support.v7.preference.PreferenceGroup; -import android.support.v7.preference.PreferenceScreen; - -import com.android.internal.logging.MetricsProto.MetricsEvent; -import com.android.internal.widget.LockPatternUtils; -import com.android.settings.fingerprint.FingerprintEnrollIntroduction; -import com.android.settings.fingerprint.FingerprintSettings; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Settings for the Profile Challenge. - */ -public class ProfileChallengePreferenceFragment extends SettingsPreferenceFragment - implements OnPreferenceChangeListener { - private static final String TAG = "WorkChallengePreferenceFragment"; - - private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; - private static final String KEY_VISIBLE_PATTERN = "visiblepattern"; - private static final String KEY_SECURITY_CATEGORY = "security_category"; - private static final String KEY_UNIFICATION = "unification"; - public static final String TAG_UNIFICATION_DIALOG = "unification_dialog"; - - private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; - private static final int UNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 124; - private static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 125; - - // Not all preferences make sense for the Work Challenge, this is a whitelist. - private static final Set ALLOWED_PREFERENCE_KEYS = new HashSet<>(); - { - ALLOWED_PREFERENCE_KEYS.add(KEY_UNLOCK_SET_OR_CHANGE); - ALLOWED_PREFERENCE_KEYS.add(KEY_VISIBLE_PATTERN); - } - // These switch preferences need special handling since they're not all stored in Settings. - private static final Set SWITCH_PREFERENCE_KEYS = new HashSet<>(); - { - SWITCH_PREFERENCE_KEYS.add(KEY_VISIBLE_PATTERN); - } - - private LockPatternUtils mLockPatternUtils; - private int mProfileUserId; - - private String mCurrentDevicePassword; - private String mCurrentProfilePassword; - - private SwitchPreference mVisiblePattern; - - @Override - protected int getMetricsCategory() { - return MetricsEvent.PROFILE_CHALLENGE; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mLockPatternUtils = new LockPatternUtils(getActivity()); - - mProfileUserId = getArguments().getInt(Intent.EXTRA_USER_ID, -1); - if (mProfileUserId == -1) { - finish(); - } - } - - @Override - public boolean onPreferenceTreeClick(Preference preference) { - final String key = preference.getKey(); - if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) { - Bundle extras = new Bundle(); - extras.putInt(Intent.EXTRA_USER_ID, mProfileUserId); - startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment", - R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, extras); - return true; - } else if (KEY_UNIFICATION.equals(key)) { - UnificationConfirmationDialog dialog = - UnificationConfirmationDialog.newIntance(mProfileUserId); - dialog.show(getChildFragmentManager(), TAG_UNIFICATION_DIALOG); - return true; - } - return super.onPreferenceTreeClick(preference); - } - - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - final String key = preference.getKey(); - if (KEY_VISIBLE_PATTERN.equals(key)) { - mLockPatternUtils.setVisiblePatternEnabled((Boolean) value, mProfileUserId); - return true; - } - return false; - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST && resultCode == Activity.RESULT_OK) { - mCurrentDevicePassword = - data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); - launchConfirmProfileLockForUnification(); - return; - } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST - && resultCode == Activity.RESULT_OK) { - mCurrentProfilePassword = - data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); - unifyLocks(); - return; - } - } - - private void launchConfirmDeviceLockForUnification() { - final String title = getActivity().getString( - R.string.lock_settings_profile_screen_lock_title); - final ChooseLockSettingsHelper helper = - new ChooseLockSettingsHelper(getActivity(), this); - if (!helper.launchConfirmationActivity( - UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, UserHandle.myUserId())) { - launchConfirmProfileLockForUnification(); - } - } - - private void launchConfirmProfileLockForUnification() { - final String title = getActivity().getString( - R.string.lock_settings_profile_screen_lock_title); - final ChooseLockSettingsHelper helper = - new ChooseLockSettingsHelper(getActivity(), this); - if (!helper.launchConfirmationActivity( - UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileUserId)) { - unifyLocks(); - createPreferenceHierarchy(); - } - } - - private void unifyLocks() { - int profileQuality = mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId); - mLockPatternUtils.clearLock(mProfileUserId); - mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileUserId, false); - if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { - mLockPatternUtils.saveLockPattern( - LockPatternUtils.stringToPattern(mCurrentProfilePassword), - mCurrentDevicePassword, UserHandle.myUserId()); - } else { - mLockPatternUtils.saveLockPassword( - mCurrentProfilePassword, mCurrentDevicePassword, - profileQuality, UserHandle.myUserId()); - } - mCurrentDevicePassword = null; - mCurrentProfilePassword = null; - } - - @Override - public void onResume() { - super.onResume(); - - // Make sure we reload the preference hierarchy since some of these settings - // depend on others... - createPreferenceHierarchy(); - - if (mVisiblePattern != null) { - mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled( - mProfileUserId)); - } - } - - private void createPreferenceHierarchy() { - PreferenceScreen root = getPreferenceScreen(); - if (root != null) { - root.removeAll(); - } - addPreferencesFromResource(R.xml.profile_challenge_settings); - root = getPreferenceScreen(); - - // Add options for lock/unlock screen - final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils); - addPreferencesFromResource(resid); - - mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN); - - removeNonWhitelistedItems(root); - - PreferenceGroup securityCategory = (PreferenceGroup) - root.findPreference(KEY_SECURITY_CATEGORY); - if (securityCategory != null) { - maybeAddFingerprintPreference(securityCategory); - if (mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileUserId)) { - maybeAddUnificationPreference(securityCategory); - } else { - Preference lockPreference = - securityCategory.findPreference(KEY_UNLOCK_SET_OR_CHANGE); - String summary = - getContext().getString(R.string.lock_settings_profile_unified_summary); - lockPreference.setSummary(summary); - } - } - } - - private void maybeAddUnificationPreference(PreferenceGroup securityCategory) { - if (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId) - >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING - && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify(mProfileUserId)) { - Preference unificationPreference = new Preference(securityCategory.getContext()); - unificationPreference.setKey(KEY_UNIFICATION); - unificationPreference.setTitle(R.string.lock_settings_profile_unification_title); - unificationPreference.setSummary(R.string.lock_settings_profile_unification_summary); - securityCategory.addPreference(unificationPreference); - } - } - - private void maybeAddFingerprintPreference(PreferenceGroup securityCategory) { - Preference fingerprintPreference = - FingerprintSettings.getFingerprintPreferenceForUser(getActivity(), mProfileUserId); - if (fingerprintPreference != null) { - securityCategory.addPreference(fingerprintPreference); - } - } - - private void removeNonWhitelistedItems(PreferenceGroup prefScreen) { - int numPreferences = prefScreen.getPreferenceCount(); - int i = 0; - while (i < numPreferences) { - final Preference pref = prefScreen.getPreference(i); - // Recursively look into categories and remove them if they are empty. - if (pref instanceof PreferenceCategory) { - PreferenceCategory category = (PreferenceCategory) pref; - removeNonWhitelistedItems(category); - if (category.getPreferenceCount() == 0) { - prefScreen.removePreference(category); - --i; - --numPreferences; - } - } else if (ALLOWED_PREFERENCE_KEYS.contains(pref.getKey())) { - if (SWITCH_PREFERENCE_KEYS.contains(pref.getKey())) { - pref.setOnPreferenceChangeListener(this); - } - } else { - prefScreen.removePreference(pref); - --i; - --numPreferences; - } - ++i; - } - } - - private int getResIdForLockUnlockScreen(Context context, - LockPatternUtils lockPatternUtils) { - int resid = 0; - if (!lockPatternUtils.isSecure(mProfileUserId)) { - resid = R.xml.security_settings_lockscreen; - } else { - switch (lockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId)) { - case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: - resid = R.xml.security_settings_pattern; - break; - case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: - case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: - resid = R.xml.security_settings_pin; - break; - case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: - case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: - case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: - resid = R.xml.security_settings_password; - break; - } - } - return resid; - } - - public static class UnificationConfirmationDialog extends DialogFragment { - - public static UnificationConfirmationDialog newIntance(int userId) { - UnificationConfirmationDialog dialog = new UnificationConfirmationDialog(); - return dialog; - } - - @Override - public void show(FragmentManager manager, String tag) { - if (manager.findFragmentByTag(tag) == null) { - // Prevent opening multiple dialogs if tapped on button quickly - super.show(manager, tag); - } - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final ProfileChallengePreferenceFragment parentFragment = - ((ProfileChallengePreferenceFragment) getParentFragment()); - return new AlertDialog.Builder(getActivity()) - .setTitle(R.string.lock_settings_profile_unification_dialog_title) - .setMessage(R.string.lock_settings_profile_unification_dialog_body) - .setPositiveButton(R.string.okay, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - parentFragment.launchConfirmDeviceLockForUnification(); - } - } - ) - .setNegativeButton(R.string.cancel, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - dismiss(); - } - } - ) - .create(); - } - } -} diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index b4cbab21c74..6ad7df1b37d 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -19,6 +19,9 @@ package com.android.settings; import android.app.Activity; import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.FragmentManager; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; @@ -85,14 +88,20 @@ public class SecuritySettings extends SettingsPreferenceFragment // Lock Settings private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; - private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "profile_challenge"; + private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "unlock_set_or_change_profile"; + private static final String KEY_VISIBLE_PATTERN_PROFILE = "visiblepattern_profile"; private static final String KEY_SECURITY_CATEGORY = "security_category"; private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category"; private static final String KEY_ADVANCED_SECURITY = "advanced_security"; private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents"; + private static final String KEY_UNIFICATION = "unification"; private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; private static final int CHANGE_TRUST_AGENT_SETTINGS = 126; + private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE = 127; + private static final int UNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 128; + private static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 129; + private static final String TAG_UNIFICATION_DIALOG = "unification_dialog"; // Misc Settings private static final String KEY_SIM_LOCK = "sim_lock"; @@ -122,6 +131,8 @@ public class SecuritySettings extends SettingsPreferenceFragment private ChooseLockSettingsHelper mChooseLockSettingsHelper; private LockPatternUtils mLockPatternUtils; + private SwitchPreference mVisiblePatternProfile; + private SwitchPreference mShowPassword; private KeyStore mKeyStore; @@ -136,6 +147,9 @@ public class SecuritySettings extends SettingsPreferenceFragment private int mProfileChallengeUserId; + private String mCurrentDevicePassword; + private String mCurrentProfilePassword; + @Override protected int getMetricsCategory() { return MetricsEvent.SECURITY; @@ -162,27 +176,33 @@ public class SecuritySettings extends SettingsPreferenceFragment } private static int getResIdForLockUnlockScreen(Context context, - LockPatternUtils lockPatternUtils) { + LockPatternUtils lockPatternUtils, int userId) { + final boolean isMyUser = userId == MY_USER_ID; int resid = 0; - if (!lockPatternUtils.isSecure(MY_USER_ID)) { - if (lockPatternUtils.isLockScreenDisabled(MY_USER_ID)) { + if (!lockPatternUtils.isSecure(userId)) { + if (!isMyUser) { + resid = R.xml.security_settings_lockscreen_profile; + } else if (lockPatternUtils.isLockScreenDisabled(userId)) { resid = R.xml.security_settings_lockscreen; } else { resid = R.xml.security_settings_chooser; } } else { - switch (lockPatternUtils.getKeyguardStoredPasswordQuality(MY_USER_ID)) { + switch (lockPatternUtils.getKeyguardStoredPasswordQuality(userId)) { case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: - resid = R.xml.security_settings_pattern; + resid = isMyUser ? R.xml.security_settings_pattern + : R.xml.security_settings_pattern_profile; break; case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: - resid = R.xml.security_settings_pin; + resid = isMyUser ? R.xml.security_settings_pin + : R.xml.security_settings_pin_profile; break; case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: - resid = R.xml.security_settings_password; + resid = isMyUser ? R.xml.security_settings_password + : R.xml.security_settings_password_profile; break; } } @@ -204,20 +224,24 @@ public class SecuritySettings extends SettingsPreferenceFragment root = getPreferenceScreen(); // Add options for lock/unlock screen - final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils); + final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils, MY_USER_ID); addPreferencesFromResource(resid); - List profiles = mUm.getProfiles(UserHandle.myUserId()); - int numProfiles = profiles.size(); - if (numProfiles > 1) { - for (int i = 0; i < numProfiles; ++i) { - UserInfo profile = profiles.get(i); - if (profile.id != UserHandle.myUserId()) { - mProfileChallengeUserId = profile.id; - } - } - if (mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) { - addPreferencesFromResource(R.xml.security_settings_profile); + mProfileChallengeUserId = getManagedProfileId(mUm); + if (mProfileChallengeUserId != UserHandle.USER_NULL + && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) { + addPreferencesFromResource(R.xml.security_settings_profile); + final int profileResid = getResIdForLockUnlockScreen( + getActivity(), mLockPatternUtils, mProfileChallengeUserId); + addPreferencesFromResource(profileResid); + maybeAddFingerprintPreference(root, mProfileChallengeUserId); + if (mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) { + maybeAddUnificationPreference(); + } else { + Preference lockPreference = root.findPreference(KEY_UNLOCK_SET_OR_CHANGE_PROFILE); + String summary = getContext().getString( + R.string.lock_settings_profile_unified_summary); + lockPreference.setSummary(summary); } } @@ -243,10 +267,13 @@ public class SecuritySettings extends SettingsPreferenceFragment PreferenceGroup securityCategory = (PreferenceGroup) root.findPreference(KEY_SECURITY_CATEGORY); if (securityCategory != null) { - maybeAddFingerprintPreference(securityCategory); + maybeAddFingerprintPreference(securityCategory, UserHandle.myUserId()); addTrustAgentSettings(securityCategory); } + mVisiblePatternProfile = + (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN_PROFILE); + // Append the rest of the settings addPreferencesFromResource(R.xml.security_settings_misc); @@ -350,15 +377,24 @@ public class SecuritySettings extends SettingsPreferenceFragment return root; } - private void maybeAddFingerprintPreference(PreferenceGroup securityCategory) { + private void maybeAddFingerprintPreference(PreferenceGroup securityCategory, int userId) { Preference fingerprintPreference = FingerprintSettings.getFingerprintPreferenceForUser( - securityCategory.getContext(), UserHandle.myUserId()); + securityCategory.getContext(), userId); if (fingerprintPreference != null) { securityCategory.addPreference(fingerprintPreference); } } + private void maybeAddUnificationPreference() { + if (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId) + >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING + && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify( + mProfileChallengeUserId)) { + addPreferencesFromResource(R.xml.security_settings_unification); + } + } + private void addTrustAgentSettings(PreferenceGroup securityCategory) { final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID); ArrayList agents = @@ -525,6 +561,11 @@ public class SecuritySettings extends SettingsPreferenceFragment createPreferenceHierarchy(); final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); + if (mVisiblePatternProfile != null) { + mVisiblePatternProfile.setChecked(lockPatternUtils.isVisiblePatternEnabled( + mProfileChallengeUserId)); + } + if (mShowPassword != null) { mShowPassword.setChecked(Settings.System.getInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD, 1) != 0); @@ -544,8 +585,9 @@ public class SecuritySettings extends SettingsPreferenceFragment } else if (KEY_UNLOCK_SET_OR_CHANGE_PROFILE.equals(key)) { Bundle extras = new Bundle(); extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId); - startFragment(this, "com.android.settings.ProfileChallengePreferenceFragment", - R.string.lock_settings_profile_label, SET_OR_CHANGE_LOCK_METHOD_REQUEST, extras); + startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment", + R.string.lock_settings_picker_title_profile, + SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras); } else if (KEY_TRUST_AGENT.equals(key)) { ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this.getActivity(), this); @@ -557,6 +599,11 @@ public class SecuritySettings extends SettingsPreferenceFragment startActivity(mTrustAgentClickIntent); mTrustAgentClickIntent = null; } + } else if (KEY_UNIFICATION.equals(key)) { + UnificationConfirmationDialog dialog = + UnificationConfirmationDialog.newIntance(mProfileChallengeUserId); + dialog.show(getChildFragmentManager(), TAG_UNIFICATION_DIALOG); + return true; } else { // If we didn't handle it, let preferences handle it. return super.onPreferenceTreeClick(preference); @@ -576,16 +623,71 @@ public class SecuritySettings extends SettingsPreferenceFragment mTrustAgentClickIntent = null; } return; + } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST + && resultCode == Activity.RESULT_OK) { + mCurrentDevicePassword = + data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + launchConfirmProfileLockForUnification(); + return; + } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST + && resultCode == Activity.RESULT_OK) { + mCurrentProfilePassword = + data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + unifyLocks(); + return; } createPreferenceHierarchy(); } + private void launchConfirmDeviceLockForUnification() { + final String title = getActivity().getString( + R.string.lock_settings_profile_screen_lock_title); + final ChooseLockSettingsHelper helper = + new ChooseLockSettingsHelper(getActivity(), this); + if (!helper.launchConfirmationActivity( + UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, UserHandle.myUserId())) { + launchConfirmProfileLockForUnification(); + } + } + + private void launchConfirmProfileLockForUnification() { + final String title = getActivity().getString( + R.string.lock_settings_profile_screen_lock_title); + final ChooseLockSettingsHelper helper = + new ChooseLockSettingsHelper(getActivity(), this); + if (!helper.launchConfirmationActivity( + UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileChallengeUserId)) { + unifyLocks(); + createPreferenceHierarchy(); + } + } + + private void unifyLocks() { + int profileQuality = + mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId); + mLockPatternUtils.clearLock(mProfileChallengeUserId); + mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false); + if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { + mLockPatternUtils.saveLockPattern( + LockPatternUtils.stringToPattern(mCurrentProfilePassword), + mCurrentDevicePassword, UserHandle.myUserId()); + } else { + mLockPatternUtils.saveLockPassword( + mCurrentProfilePassword, mCurrentDevicePassword, + profileQuality, UserHandle.myUserId()); + } + mCurrentDevicePassword = null; + mCurrentProfilePassword = null; + } + @Override public boolean onPreferenceChange(Preference preference, Object value) { boolean result = true; final String key = preference.getKey(); final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); - if (KEY_SHOW_PASSWORD.equals(key)) { + if (KEY_VISIBLE_PATTERN_PROFILE.equals(key)) { + lockPatternUtils.setVisiblePatternEnabled((Boolean) value, mProfileChallengeUserId); + } else if (KEY_SHOW_PASSWORD.equals(key)) { Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD, ((Boolean) value) ? 1 : 0); lockPatternUtils.setVisiblePasswordEnabled((Boolean) value, MY_USER_ID); @@ -607,6 +709,21 @@ public class SecuritySettings extends SettingsPreferenceFragment return R.string.help_url_security; } + private static int getManagedProfileId(UserManager um) { + List profiles = um.getProfiles(MY_USER_ID); + int numProfiles = profiles.size(); + if (numProfiles == 1) { + return UserHandle.USER_NULL; + } + for (int i = 0; i < numProfiles; ++i) { + UserInfo profile = profiles.get(i); + if (profile.id != MY_USER_ID) { + return profile.id; + } + } + return UserHandle.USER_NULL; + } + /** * For Search. Please keep it in sync when updating "createPreferenceHierarchy()" */ @@ -623,28 +740,20 @@ public class SecuritySettings extends SettingsPreferenceFragment LockPatternUtils lockPatternUtils = new LockPatternUtils(context); // Add options for lock/unlock screen - int resId = getResIdForLockUnlockScreen(context, lockPatternUtils); + int resId = getResIdForLockUnlockScreen(context, lockPatternUtils, MY_USER_ID); SearchIndexableResource sir = new SearchIndexableResource(context); sir.xmlResId = resId; result.add(sir); final UserManager um = UserManager.get(context); - List profiles = um.getProfiles(UserHandle.myUserId()); - int numProfiles = profiles.size(); - if (numProfiles > 1) { - int profileUserId = -1; - for (int i = 0; i < numProfiles; ++i) { - UserInfo profile = profiles.get(i); - if (profile.id != UserHandle.myUserId()) { - profileUserId = profile.id; - } - } - if (lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)) { - sir = new SearchIndexableResource(context); - sir.xmlResId = R.xml.security_settings_profile; - result.add(sir); - } + final int profileUserId = getManagedProfileId(um); + if (profileUserId != UserHandle.USER_NULL + && lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)) { + sir = new SearchIndexableResource(context); + sir.xmlResId = getResIdForLockUnlockScreen( + context, lockPatternUtils, profileUserId); + result.add(sir); } if (um.isAdminUser()) { @@ -720,6 +829,21 @@ public class SecuritySettings extends SettingsPreferenceFragment result.add(data); } + final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); + final int profileUserId = getManagedProfileId(um); + if (profileUserId != UserHandle.USER_NULL + && lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)) { + if (lockPatternUtils.getKeyguardStoredPasswordQuality(profileUserId) + >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING + && lockPatternUtils.isSeparateProfileChallengeAllowedToUnify( + profileUserId)) { + data = new SearchIndexableRaw(context); + data.title = res.getString(R.string.lock_settings_profile_unification_title); + data.screenTitle = screenTitle; + result.add(data); + } + } + // Credential storage if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { KeyStore keyStore = KeyStore.getInstance(); @@ -735,7 +859,6 @@ public class SecuritySettings extends SettingsPreferenceFragment } // Advanced - final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); if (lockPatternUtils.isSecure(MY_USER_ID)) { ArrayList agents = getActiveTrustAgents(context, lockPatternUtils, @@ -1080,4 +1203,46 @@ public class SecuritySettings extends SettingsPreferenceFragment return true; } } + + public static class UnificationConfirmationDialog extends DialogFragment { + + public static UnificationConfirmationDialog newIntance(int userId) { + UnificationConfirmationDialog dialog = new UnificationConfirmationDialog(); + return dialog; + } + + @Override + public void show(FragmentManager manager, String tag) { + if (manager.findFragmentByTag(tag) == null) { + // Prevent opening multiple dialogs if tapped on button quickly + super.show(manager, tag); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final SecuritySettings parentFragment = ((SecuritySettings) getParentFragment()); + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.lock_settings_profile_unification_dialog_title) + .setMessage(R.string.lock_settings_profile_unification_dialog_body) + .setPositiveButton(R.string.okay, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int whichButton) { + parentFragment.launchConfirmDeviceLockForUnification(); + } + } + ) + .setNegativeButton(R.string.cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int whichButton) { + dismiss(); + } + } + ) + .create(); + } + } + }