From 928ddbe731a32590d64e14df89738ddf0e999926 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 3 Jan 2018 15:02:02 -0800 Subject: [PATCH] Merge sub pages for lock/unlock into 1 xml. And create PreferenceControllers for each setting The page is still pretty janky and controllers are invoked manually. Next CL will clean these up. Bug: 32953042 Test: TODO Change-Id: I1d7478324f5de4fdb464d79f89086f7e79c0ee67 --- res/layout/preference_category_no_title.xml | 2 +- res/xml/security_settings_v2.xml | 98 ++- .../BluetoothSwitchPreferenceController.java | 3 +- .../core/TogglePreferenceController.java | 7 +- .../AutoBrightnessPreferenceController.java | 3 +- .../fingerprint/FingerprintSettings.java | 4 + ...creenNotificationPreferenceController.java | 31 +- ...ProfileScreenLockPreferenceController.java | 108 +++ .../ChangeScreenLockPreferenceController.java | 169 +++++ ...rintProfileStatusPreferenceController.java | 41 ++ ...FingerprintStatusPreferenceController.java | 120 ++++ .../LockScreenPreferenceController.java | 65 ++ .../LockUnificationPreferenceController.java | 218 ++++++ .../settings/security/SecuritySettings.java | 5 +- .../settings/security/SecuritySettingsV2.java | 647 ++++-------------- .../ShowPasswordPreferenceController.java | 3 +- .../UnificationConfirmationDialog.java | 17 +- ...blePatternProfilePreferenceController.java | 72 ++ .../TrustAgentListPreferenceController.java | 16 +- .../widget/MasterSwitchPreference.java | 1 - .../security/SecuritySettingsTest.java | 21 - 21 files changed, 1050 insertions(+), 601 deletions(-) create mode 100644 src/com/android/settings/security/ChangeProfileScreenLockPreferenceController.java create mode 100644 src/com/android/settings/security/ChangeScreenLockPreferenceController.java create mode 100644 src/com/android/settings/security/FingerprintProfileStatusPreferenceController.java create mode 100644 src/com/android/settings/security/FingerprintStatusPreferenceController.java create mode 100644 src/com/android/settings/security/LockScreenPreferenceController.java create mode 100644 src/com/android/settings/security/LockUnificationPreferenceController.java create mode 100644 src/com/android/settings/security/VisiblePatternProfilePreferenceController.java diff --git a/res/layout/preference_category_no_title.xml b/res/layout/preference_category_no_title.xml index 136ec6d47f6..d4704bdc4ed 100644 --- a/res/layout/preference_category_no_title.xml +++ b/res/layout/preference_category_no_title.xml @@ -18,7 +18,7 @@ set height to 0. This will be used in preference category without title in order to remove extra 32dp blank --> - + + + - - + + + + + + + + + + + + + + + + + @@ -59,54 +101,64 @@ + android:summary="@string/show_password_summary" /> + android:fragment="com.android.settings.DeviceAdminSettings" /> + android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings" /> - + - + - - + android:fragment="com.android.settings.security.EncryptionAndCredential" /> + + + android:fragment="com.android.settings.security.ScreenPinningSettings" /> - + diff --git a/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java b/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java index 3482ee2d91e..8a597686fbe 100644 --- a/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java +++ b/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java @@ -98,10 +98,11 @@ public class BluetoothSwitchPreferenceController extends TogglePreferenceControl } @Override - public void setChecked(boolean isChecked) { + public boolean setChecked(boolean isChecked) { if (mBluetoothAdapter != null) { mBluetoothAdapter.setBluetoothEnabled(isChecked); } + return true; } /** diff --git a/src/com/android/settings/core/TogglePreferenceController.java b/src/com/android/settings/core/TogglePreferenceController.java index febd7ade63b..5431f4da8b1 100644 --- a/src/com/android/settings/core/TogglePreferenceController.java +++ b/src/com/android/settings/core/TogglePreferenceController.java @@ -40,8 +40,9 @@ public abstract class TogglePreferenceController extends BasePreferenceControlle * Set the Setting to {@param isChecked} * * @param isChecked Is {@true} when the setting should be enabled. + * @return {@true} if the underlying setting is updated. */ - public abstract void setChecked(boolean isChecked); + public abstract boolean setChecked(boolean isChecked); @Override public final void updateState(Preference preference) { @@ -50,8 +51,6 @@ public abstract class TogglePreferenceController extends BasePreferenceControlle @Override public final boolean onPreferenceChange(Preference preference, Object newValue) { - boolean auto = (Boolean) newValue; - setChecked(auto); - return true; + return setChecked((Boolean) newValue); } } \ No newline at end of file diff --git a/src/com/android/settings/display/AutoBrightnessPreferenceController.java b/src/com/android/settings/display/AutoBrightnessPreferenceController.java index d71a1f8035e..28f9260651a 100644 --- a/src/com/android/settings/display/AutoBrightnessPreferenceController.java +++ b/src/com/android/settings/display/AutoBrightnessPreferenceController.java @@ -45,9 +45,10 @@ public class AutoBrightnessPreferenceController extends TogglePreferenceControll } @Override - public void setChecked(boolean isChecked) { + public boolean setChecked(boolean isChecked) { Settings.System.putInt(mContext.getContentResolver(), SYSTEM_KEY, isChecked ? SCREEN_BRIGHTNESS_MODE_AUTOMATIC : DEFAULT_VALUE); + return true; } @Override diff --git a/src/com/android/settings/fingerprint/FingerprintSettings.java b/src/com/android/settings/fingerprint/FingerprintSettings.java index ad7f83acd58..5d178d2c39e 100644 --- a/src/com/android/settings/fingerprint/FingerprintSettings.java +++ b/src/com/android/settings/fingerprint/FingerprintSettings.java @@ -974,6 +974,10 @@ public class FingerprintSettings extends SubSettings { } } + /** + * @deprecated in favor of new SecuritySettings. + */ + @Deprecated public static Preference getFingerprintPreferenceForUser(Context context, final int userId) { final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(context); if (fpm == null || !fpm.isHardwareDetected()) { diff --git a/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java b/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java index dd7b0fbac8c..d56febb1544 100644 --- a/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java +++ b/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java @@ -36,6 +36,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.core.PreferenceControllerMixin; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; @@ -78,7 +79,9 @@ public class LockScreenNotificationPreferenceController extends AbstractPreferen mProfileChallengeUserId = Utils.getManagedProfileId( UserManager.get(context), UserHandle.myUserId()); - final LockPatternUtils utils = new LockPatternUtils(context); + final LockPatternUtils utils = FeatureFactory.getFactory(context) + .getSecurityFeatureProvider() + .getLockPatternUtils(context); mSecure = utils.isSecure(UserHandle.myUserId()); mSecureProfile = (mProfileChallengeUserId != UserHandle.USER_NULL) && (utils.isSecure(mProfileChallengeUserId) @@ -278,10 +281,14 @@ public class LockScreenNotificationPreferenceController extends AbstractPreferen } } - public int getSummaryResource() { - final boolean enabled = getLockscreenNotificationsEnabled(UserHandle.myUserId()); - final boolean allowPrivate = !mSecure - || getLockscreenAllowPrivateNotifications(UserHandle.myUserId()); + public static int getSummaryResource(Context context) { + final boolean enabled = getLockscreenNotificationsEnabled(context, UserHandle.myUserId()); + final boolean secure = FeatureFactory.getFactory(context) + .getSecurityFeatureProvider() + .getLockPatternUtils(context) + .isSecure(UserHandle.myUserId()); + final boolean allowPrivate = !secure + || getLockscreenAllowPrivateNotifications(context, UserHandle.myUserId()); return !enabled ? R.string.lock_screen_notifications_summary_disable : allowPrivate ? R.string.lock_screen_notifications_summary_show : R.string.lock_screen_notifications_summary_hide; @@ -291,7 +298,7 @@ public class LockScreenNotificationPreferenceController extends AbstractPreferen if (mLockscreen == null) { return; } - mLockscreenSelectedValue = getSummaryResource(); + mLockscreenSelectedValue = getSummaryResource(mContext); mLockscreen.setSummary("%s"); mLockscreen.setValue(Integer.toString(mLockscreenSelectedValue)); } @@ -303,9 +310,9 @@ public class LockScreenNotificationPreferenceController extends AbstractPreferen if (mLockscreenProfile == null) { return; } - final boolean enabled = getLockscreenNotificationsEnabled(mProfileChallengeUserId); + final boolean enabled = getLockscreenNotificationsEnabled(mContext,mProfileChallengeUserId); final boolean allowPrivate = !mSecureProfile - || getLockscreenAllowPrivateNotifications(mProfileChallengeUserId); + || getLockscreenAllowPrivateNotifications(mContext, mProfileChallengeUserId); mLockscreenProfile.setSummary("%s"); mLockscreenSelectedValueProfile = !enabled ? R.string.lock_screen_notifications_summary_disable_profile @@ -314,13 +321,13 @@ public class LockScreenNotificationPreferenceController extends AbstractPreferen mLockscreenProfile.setValue(Integer.toString(mLockscreenSelectedValueProfile)); } - private boolean getLockscreenNotificationsEnabled(int userId) { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), + private static boolean getLockscreenNotificationsEnabled(Context context, int userId) { + return Settings.Secure.getIntForUser(context.getContentResolver(), Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userId) != 0; } - private boolean getLockscreenAllowPrivateNotifications(int userId) { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), + private static boolean getLockscreenAllowPrivateNotifications(Context context, int userId) { + return Settings.Secure.getIntForUser(context.getContentResolver(), Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userId) != 0; } diff --git a/src/com/android/settings/security/ChangeProfileScreenLockPreferenceController.java b/src/com/android/settings/security/ChangeProfileScreenLockPreferenceController.java new file mode 100644 index 00000000000..612dd6d503f --- /dev/null +++ b/src/com/android/settings/security/ChangeProfileScreenLockPreferenceController.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2018 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.security; + +import static com.android.settings.security + .SecuritySettingsV2.SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE; + +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.UserHandle; +import android.support.v7.preference.Preference; +import android.text.TextUtils; + +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.password.ChooseLockGeneric; +import com.android.settings.widget.GearPreference; + +public class ChangeProfileScreenLockPreferenceController extends + ChangeScreenLockPreferenceController { + + private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "unlock_set_or_change_profile"; + + public ChangeProfileScreenLockPreferenceController(Context context, + SecuritySettingsV2 host) { + super(context, host); + } + + @Override + public void onGearClick(GearPreference p) { + + } + + @Override + public boolean isAvailable() { + if (mProfileChallengeUserId == UserHandle.USER_NULL || + !mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) { + return false; + } + if (!mLockPatternUtils.isSecure(mProfileChallengeUserId)) { + return true; + } + switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId)) { + case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: + case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: + case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: + case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: + case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: + return true; + } + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_UNLOCK_SET_OR_CHANGE_PROFILE; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { + return false; + } + if (Utils.startQuietModeDialogIfNecessary(mContext, mUm, mProfileChallengeUserId)) { + return false; + } + final Bundle extras = new Bundle(); + extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId); + mHost.startFragment(mHost, ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), + R.string.lock_settings_picker_title_profile, + SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras); + return true; + } + + @Override + public void updateState(Preference preference) { + updateSummary(preference, mProfileChallengeUserId); + + if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) { + final String summary = mContext.getString( + R.string.lock_settings_profile_unified_summary); + mPreference.setSummary(summary); + mPreference.setEnabled(false); + } else { + // PO may disallow to change profile password, and the profile's password is + // separated from screen lock password. Disable profile specific "Screen lock" menu. + disableIfPasswordQualityManaged(mProfileChallengeUserId); + } + } +} diff --git a/src/com/android/settings/security/ChangeScreenLockPreferenceController.java b/src/com/android/settings/security/ChangeScreenLockPreferenceController.java new file mode 100644 index 00000000000..3cd235fb7eb --- /dev/null +++ b/src/com/android/settings/security/ChangeScreenLockPreferenceController.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2018 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.security; + +import static com.android.settings.security.SecuritySettingsV2.SET_OR_CHANGE_LOCK_METHOD_REQUEST; + +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; +import android.os.storage.StorageManager; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; +import android.text.TextUtils; + +import com.android.internal.widget.LockPatternUtils; +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settings.overlay.FeatureFactory; +import com.android.settings.password.ChooseLockGeneric; +import com.android.settings.security.screenlock.ScreenLockSettings; +import com.android.settings.widget.GearPreference; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedPreference; +import com.android.settingslib.core.AbstractPreferenceController; + +public class ChangeScreenLockPreferenceController extends AbstractPreferenceController implements + PreferenceControllerMixin, GearPreference.OnGearClickListener { + + private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; + + protected final DevicePolicyManager mDPM; + protected final SecuritySettingsV2 mHost; + protected final UserManager mUm; + protected final LockPatternUtils mLockPatternUtils; + + protected final int mUserId = UserHandle.myUserId(); + protected final int mProfileChallengeUserId; + + protected RestrictedPreference mPreference; + + public ChangeScreenLockPreferenceController(Context context, SecuritySettingsV2 host) { + super(context); + mUm = (UserManager) context.getSystemService(Context.USER_SERVICE); + mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); + mLockPatternUtils = FeatureFactory.getFactory(context) + .getSecurityFeatureProvider() + .getLockPatternUtils(context); + mHost = host; + mProfileChallengeUserId = Utils.getManagedProfileId(mUm, mUserId); + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public String getPreferenceKey() { + return KEY_UNLOCK_SET_OR_CHANGE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = (RestrictedPreference) screen.findPreference(getPreferenceKey()); + if (mPreference != null && mPreference instanceof GearPreference) { + ((GearPreference) mPreference).setOnGearClickListener(this); + } + } + + @Override + public void updateState(Preference preference) { + updateSummary(preference, mUserId); + disableIfPasswordQualityManaged(mUserId); + if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) { + // PO may disallow to change password for the profile, but screen lock and managed + // profile's lock is the same. Disable main "Screen lock" menu. + disableIfPasswordQualityManaged(mProfileChallengeUserId); + } + } + + @Override + public void onGearClick(GearPreference p) { + if (TextUtils.equals(p.getKey(), getPreferenceKey())) { + mHost.startFragment(mHost, ScreenLockSettings.class.getName(), 0, 0, null); + } + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { + return super.handlePreferenceTreeClick(preference); + } + // TODO(b/35930129): Remove once existing password can be passed into vold directly. + // Currently we need this logic to ensure that the QUIET_MODE is off for any work + // profile with unified challenge on FBE-enabled devices. Otherwise, vold would not be + // able to complete the operation due to the lack of (old) encryption key. + if (mProfileChallengeUserId != UserHandle.USER_NULL + && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId) + && StorageManager.isFileEncryptedNativeOnly()) { + if (Utils.startQuietModeDialogIfNecessary(mContext, mUm, mProfileChallengeUserId)) { + return false; + } + } + mHost.startFragment(mHost, ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), + R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null); + return true; + } + + protected void updateSummary(Preference preference, int userId) { + if (!mLockPatternUtils.isSecure(userId)) { + if (userId == mProfileChallengeUserId + || mLockPatternUtils.isLockScreenDisabled(userId)) { + preference.setSummary(R.string.unlock_set_unlock_mode_off); + } else { + preference.setSummary(R.string.unlock_set_unlock_mode_none); + } + } else { + switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(userId)) { + case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: + preference.setSummary(R.string.unlock_set_unlock_mode_pattern); + break; + case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: + preference.setSummary(R.string.unlock_set_unlock_mode_pin); + break; + case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: + case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: + case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: + preference.setSummary(R.string.unlock_set_unlock_mode_password); + break; + } + } + } + + /** + * Sets the preference as disabled by admin if PASSWORD_QUALITY_MANAGED is set. + * The preference must be a RestrictedPreference. + *

+ * DO or PO installed in the user may disallow to change password. + */ + void disableIfPasswordQualityManaged(int userId) { + final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtils + .checkIfPasswordQualityIsSet(mContext, userId); + final DevicePolicyManager dpm = (DevicePolicyManager) mContext + .getSystemService(Context.DEVICE_POLICY_SERVICE); + if (admin != null && dpm.getPasswordQuality(admin.component, userId) + == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) { + mPreference.setDisabledByAdmin(admin); + } + } +} diff --git a/src/com/android/settings/security/FingerprintProfileStatusPreferenceController.java b/src/com/android/settings/security/FingerprintProfileStatusPreferenceController.java new file mode 100644 index 00000000000..1c72a4631ee --- /dev/null +++ b/src/com/android/settings/security/FingerprintProfileStatusPreferenceController.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2018 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.security; + +import android.content.Context; +import android.os.UserHandle; + +public class FingerprintProfileStatusPreferenceController + extends FingerprintStatusPreferenceController { + + public static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings_profile"; + + public FingerprintProfileStatusPreferenceController(Context context) { + super(context, KEY_FINGERPRINT_SETTINGS); + } + + @Override + protected boolean isUserSupported() { + return mProfileChallengeUserId != UserHandle.USER_NULL + && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId); + } + + @Override + protected int getUserId() { + return mProfileChallengeUserId; + } +} diff --git a/src/com/android/settings/security/FingerprintStatusPreferenceController.java b/src/com/android/settings/security/FingerprintStatusPreferenceController.java new file mode 100644 index 00000000000..2985f40cc0c --- /dev/null +++ b/src/com/android/settings/security/FingerprintStatusPreferenceController.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2018 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.security; + +import android.content.Context; +import android.content.Intent; +import android.hardware.fingerprint.Fingerprint; +import android.hardware.fingerprint.FingerprintManager; +import android.os.UserHandle; +import android.os.UserManager; +import android.support.v7.preference.Preference; + +import com.android.internal.widget.LockPatternUtils; +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.fingerprint.FingerprintEnrollIntroduction; +import com.android.settings.fingerprint.FingerprintSettings; +import com.android.settings.overlay.FeatureFactory; + +import java.util.List; + +public class FingerprintStatusPreferenceController extends BasePreferenceController { + + private static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings"; + + protected final FingerprintManager mFingerprintManager; + protected final UserManager mUm; + protected final LockPatternUtils mLockPatternUtils; + + protected final int mUserId = UserHandle.myUserId(); + protected final int mProfileChallengeUserId; + + public FingerprintStatusPreferenceController(Context context) { + this(context, KEY_FINGERPRINT_SETTINGS); + } + + public FingerprintStatusPreferenceController(Context context, String key) { + super(context, key); + mFingerprintManager = Utils.getFingerprintManagerOrNull(context); + mUm = (UserManager) context.getSystemService(Context.USER_SERVICE); + mLockPatternUtils = FeatureFactory.getFactory(context) + .getSecurityFeatureProvider() + .getLockPatternUtils(context); + mProfileChallengeUserId = Utils.getManagedProfileId(mUm, mUserId); + } + + @Override + public int getAvailabilityStatus() { + if (mFingerprintManager == null || !mFingerprintManager.isHardwareDetected()) { + return DISABLED_UNSUPPORTED; + } + if (isUserSupported()) { + return AVAILABLE; + } else { + return DISABLED_FOR_USER; + } + } + + @Override + public void updateState(Preference preference) { + if (!isAvailable()) { + if (preference != null) { + preference.setVisible(false); + } + return; + } else { + preference.setVisible(true); + } + final int userId = getUserId(); + final List items = mFingerprintManager.getEnrolledFingerprints(userId); + final int fingerprintCount = items != null ? items.size() : 0; + final String clazz; + if (fingerprintCount > 0) { + preference.setSummary(mContext.getResources().getQuantityString( + R.plurals.security_settings_fingerprint_preference_summary, + fingerprintCount, fingerprintCount)); + clazz = FingerprintSettings.class.getName(); + } else { + preference.setSummary( + R.string.security_settings_fingerprint_preference_summary_none); + clazz = FingerprintEnrollIntroduction.class.getName(); + } + preference.setOnPreferenceClickListener(target -> { + final Context context = target.getContext(); + final UserManager userManager = UserManager.get(context); + if (Utils.startQuietModeDialogIfNecessary(context, userManager, + userId)) { + return false; + } + Intent intent = new Intent(); + intent.setClassName("com.android.settings", clazz); + intent.putExtra(Intent.EXTRA_USER_ID, userId); + context.startActivity(intent); + return true; + }); + } + + protected int getUserId() { + return mUserId; + } + + protected boolean isUserSupported() { + return true; + } +} diff --git a/src/com/android/settings/security/LockScreenPreferenceController.java b/src/com/android/settings/security/LockScreenPreferenceController.java new file mode 100644 index 00000000000..213c39c1184 --- /dev/null +++ b/src/com/android/settings/security/LockScreenPreferenceController.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2018 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.security; + +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; + +import android.content.Context; +import android.os.UserHandle; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.internal.widget.LockPatternUtils; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.notification.LockScreenNotificationPreferenceController; +import com.android.settings.overlay.FeatureFactory; + +public class LockScreenPreferenceController extends BasePreferenceController { + + static final String KEY_LOCKSCREEN_PREFERENCES = "lockscreen_preferences"; + + private static final int MY_USER_ID = UserHandle.myUserId(); + private final LockPatternUtils mLockPatternUtils; + + public LockScreenPreferenceController(Context context) { + super(context, KEY_LOCKSCREEN_PREFERENCES); + mLockPatternUtils = FeatureFactory.getFactory(context) + .getSecurityFeatureProvider().getLockPatternUtils(context); + } + + @Override + public int getAvailabilityStatus() { + if (!mLockPatternUtils.isSecure(MY_USER_ID)) { + return mLockPatternUtils.isLockScreenDisabled(MY_USER_ID) + ? DISABLED_FOR_USER : AVAILABLE; + } else { + return mLockPatternUtils.getKeyguardStoredPasswordQuality(MY_USER_ID) + == PASSWORD_QUALITY_UNSPECIFIED + ? DISABLED_FOR_USER : AVAILABLE; + } + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + final Preference lockscreenPreferences = screen.findPreference(getPreferenceKey()); + if (lockscreenPreferences != null) { + lockscreenPreferences.setSummary( + LockScreenNotificationPreferenceController.getSummaryResource(mContext)); + } + } +} diff --git a/src/com/android/settings/security/LockUnificationPreferenceController.java b/src/com/android/settings/security/LockUnificationPreferenceController.java new file mode 100644 index 00000000000..5486e2967e4 --- /dev/null +++ b/src/com/android/settings/security/LockUnificationPreferenceController.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2018 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.security; + +import static com.android.settings.security + .SecuritySettingsV2.SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE; +import static com.android.settings.security.SecuritySettingsV2.UNIFY_LOCK_CONFIRM_DEVICE_REQUEST; +import static com.android.settings.security.SecuritySettingsV2.UNIFY_LOCK_CONFIRM_PROFILE_REQUEST; +import static com.android.settings.security.SecuritySettingsV2.UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST; + +import android.app.Activity; +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.internal.widget.LockPatternUtils; +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settings.overlay.FeatureFactory; +import com.android.settings.password.ChooseLockGeneric; +import com.android.settings.password.ChooseLockSettingsHelper; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedSwitchPreference; +import com.android.settingslib.core.AbstractPreferenceController; + +public class LockUnificationPreferenceController extends AbstractPreferenceController + implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener { + + private static final String KEY_UNIFICATION = "unification"; + + private static final int MY_USER_ID = UserHandle.myUserId(); + + private final UserManager mUm; + private final LockPatternUtils mLockPatternUtils; + private final int mProfileChallengeUserId; + private final SecuritySettingsV2 mHost; + + private RestrictedSwitchPreference mUnifyProfile; + + + private String mCurrentDevicePassword; + private String mCurrentProfilePassword; + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mUnifyProfile = (RestrictedSwitchPreference) screen.findPreference(KEY_UNIFICATION); + } + + public LockUnificationPreferenceController(Context context, SecuritySettingsV2 host) { + super(context); + mHost = host; + mUm = (UserManager) context.getSystemService(Context.USER_SERVICE); + mLockPatternUtils = FeatureFactory.getFactory(context) + .getSecurityFeatureProvider() + .getLockPatternUtils(context); + mProfileChallengeUserId = Utils.getManagedProfileId(mUm, MY_USER_ID); + } + + @Override + public boolean isAvailable() { + final boolean allowSeparateProfileChallenge = + mProfileChallengeUserId != UserHandle.USER_NULL + && mLockPatternUtils.isSeparateProfileChallengeAllowed( + mProfileChallengeUserId); + return allowSeparateProfileChallenge; + } + + @Override + public String getPreferenceKey() { + return KEY_UNIFICATION; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object value) { + if (Utils.startQuietModeDialogIfNecessary(mContext, mUm, mProfileChallengeUserId)) { + return false; + } + if ((Boolean) value) { + final boolean compliantForDevice = + (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId) + >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING + && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify( + mProfileChallengeUserId)); + UnificationConfirmationDialog dialog = + UnificationConfirmationDialog.newInstance(compliantForDevice); + dialog.show(mHost); + } else { + final String title = mContext.getString(R.string.unlock_set_unlock_launch_picker_title); + final ChooseLockSettingsHelper helper = + new ChooseLockSettingsHelper(mHost.getActivity(), mHost); + if (!helper.launchConfirmationActivity( + UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST, + title, true /* returnCredentials */, MY_USER_ID)) { + ununifyLocks(); + } + } + return true; + } + + @Override + public void updateState(Preference preference) { + if (mUnifyProfile != null) { + final boolean separate = + mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId); + mUnifyProfile.setChecked(!separate); + if (separate) { + mUnifyProfile.setDisabledByAdmin(RestrictedLockUtils.checkIfRestrictionEnforced( + mContext, UserManager.DISALLOW_UNIFIED_PASSWORD, + mProfileChallengeUserId)); + } + } + } + + public boolean handleActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST + && resultCode == Activity.RESULT_OK) { + ununifyLocks(); + return true; + } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST + && resultCode == Activity.RESULT_OK) { + mCurrentDevicePassword = + data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + launchConfirmProfileLockForUnification(); + return true; + } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST + && resultCode == Activity.RESULT_OK) { + mCurrentProfilePassword = + data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + unifyLocks(); + return true; + } + return false; + } + + private void ununifyLocks() { + Bundle extras = new Bundle(); + extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId); + mHost.startFragment(mHost, + ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), + R.string.lock_settings_picker_title_profile, + SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras); + } + + void launchConfirmDeviceLockForUnification() { + final String title = mContext.getString( + R.string.unlock_set_unlock_launch_picker_title); + final ChooseLockSettingsHelper helper = + new ChooseLockSettingsHelper(mHost.getActivity(), mHost); + if (!helper.launchConfirmationActivity( + UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, MY_USER_ID)) { + launchConfirmProfileLockForUnification(); + } + } + + private void launchConfirmProfileLockForUnification() { + final String title = mContext.getString( + R.string.unlock_set_unlock_launch_picker_title_profile); + final ChooseLockSettingsHelper helper = + new ChooseLockSettingsHelper(mHost.getActivity(), mHost); + if (!helper.launchConfirmationActivity( + UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileChallengeUserId)) { + unifyLocks(); + // TODO: update relevant prefs. + // createPreferenceHierarchy(); + } + } + + private void unifyLocks() { + int profileQuality = + mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId); + if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { + mLockPatternUtils.saveLockPattern( + LockPatternUtils.stringToPattern(mCurrentProfilePassword), + mCurrentDevicePassword, MY_USER_ID); + } else { + mLockPatternUtils.saveLockPassword( + mCurrentProfilePassword, mCurrentDevicePassword, + profileQuality, MY_USER_ID); + } + mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false, + mCurrentProfilePassword); + final boolean profilePatternVisibility = + mLockPatternUtils.isVisiblePatternEnabled(mProfileChallengeUserId); + mLockPatternUtils.setVisiblePatternEnabled(profilePatternVisibility, MY_USER_ID); + mCurrentDevicePassword = null; + mCurrentProfilePassword = null; + } + + void unifyUncompliantLocks() { + mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false, + mCurrentProfilePassword); + mHost.startFragment(mHost, ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), + R.string.lock_settings_picker_title, + SecuritySettingsV2.SET_OR_CHANGE_LOCK_METHOD_REQUEST, null); + } + +} diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java index fc47b5c1901..f099b44883f 100644 --- a/src/com/android/settings/security/SecuritySettings.java +++ b/src/com/android/settings/security/SecuritySettings.java @@ -161,7 +161,6 @@ public class SecuritySettings extends SettingsPreferenceFragment private LocationPreferenceController mLocationcontroller; private ManageDeviceAdminPreferenceController mManageDeviceAdminPreferenceController; private EnterprisePrivacyPreferenceController mEnterprisePrivacyPreferenceController; - private LockScreenNotificationPreferenceController mLockScreenNotificationPreferenceController; @Override public int getMetricsCategory() { @@ -208,8 +207,6 @@ public class SecuritySettings extends SettingsPreferenceFragment = new ManageDeviceAdminPreferenceController(activity); mEnterprisePrivacyPreferenceController = new EnterprisePrivacyPreferenceController(activity); - mLockScreenNotificationPreferenceController - = new LockScreenNotificationPreferenceController(activity); } private static int getResIdForLockUnlockScreen(LockPatternUtils lockPatternUtils, @@ -430,7 +427,7 @@ public class SecuritySettings extends SettingsPreferenceFragment final Preference lockscreenPreferences = group.findPreference(KEY_LOCKSCREEN_PREFERENCES); if (lockscreenPreferences != null) { lockscreenPreferences.setSummary( - mLockScreenNotificationPreferenceController.getSummaryResource()); + LockScreenNotificationPreferenceController.getSummaryResource(getContext())); } } diff --git a/src/com/android/settings/security/SecuritySettingsV2.java b/src/com/android/settings/security/SecuritySettingsV2.java index 002e44772c3..7ae6ca7d3fe 100644 --- a/src/com/android/settings/security/SecuritySettingsV2.java +++ b/src/com/android/settings/security/SecuritySettingsV2.java @@ -1,25 +1,16 @@ package com.android.settings.security; -import static com.android.settings.security.EncryptionStatusPreferenceController - .PREF_KEY_ENCRYPTION_SECURITY_PAGE; +import static com.android.settings.security.EncryptionStatusPreferenceController.PREF_KEY_ENCRYPTION_SECURITY_PAGE; import android.app.Activity; -import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; -import android.content.res.Resources; import android.hardware.fingerprint.FingerprintManager; -import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; -import android.os.storage.StorageManager; import android.provider.SearchIndexableResource; -import android.support.annotation.VisibleForTesting; -import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceScreen; -import android.text.TextUtils; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.widget.LockPatternUtils; @@ -30,96 +21,62 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.SummaryLoader; import com.android.settings.enterprise.EnterprisePrivacyPreferenceController; import com.android.settings.enterprise.ManageDeviceAdminPreferenceController; -import com.android.settings.fingerprint.FingerprintSettings; import com.android.settings.location.LocationPreferenceController; -import com.android.settings.notification.LockScreenNotificationPreferenceController; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.password.ChooseLockGeneric; import com.android.settings.password.ChooseLockSettingsHelper; -import com.android.settings.password.ManagedLockPasswordProvider; import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settings.search.SearchIndexableRaw; -import com.android.settings.security.screenlock.ScreenLockSettings; import com.android.settings.security.trustagent.ManageTrustAgentsPreferenceController; import com.android.settings.security.trustagent.TrustAgentListPreferenceController; -import com.android.settings.widget.GearPreference; -import com.android.settingslib.RestrictedLockUtils; -import com.android.settingslib.RestrictedPreference; -import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.drawer.CategoryKey; import java.util.ArrayList; import java.util.List; -public class SecuritySettingsV2 extends DashboardFragment - implements Preference.OnPreferenceChangeListener, - GearPreference.OnGearClickListener { +public class SecuritySettingsV2 extends DashboardFragment { private static final String TAG = "SecuritySettingsV2"; - // 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 = "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_UNIFICATION = "unification"; - @VisibleForTesting - static final String KEY_LOCKSCREEN_PREFERENCES = "lockscreen_preferences"; - private static final String KEY_ENCRYPTION_AND_CREDENTIALS = "encryption_and_credential"; - private static final String KEY_LOCATION_SCANNING = "location_scanning"; - private static final String KEY_LOCATION = "location"; - - private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; + public static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; public 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 int UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 130; - private static final String TAG_UNIFICATION_DIALOG = "unification_dialog"; + public static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE = 127; + public static final int UNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 128; + public static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 129; + public static final int UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 130; + // Security status private static final String KEY_SECURITY_STATUS = "security_status"; private static final String SECURITY_STATUS_KEY_PREFIX = "security_status_"; - // Device management settings - private static final String KEY_ENTERPRISE_PRIVACY = "enterprise_privacy"; - private static final String KEY_MANAGE_DEVICE_ADMIN = "manage_device_admin"; - - // These switch preferences need special handling since they're not all stored in Settings. - private static final String SWITCH_PREFERENCE_KEYS[] = { - KEY_UNIFICATION, KEY_VISIBLE_PATTERN_PROFILE - }; - private static final int MY_USER_ID = UserHandle.myUserId(); private DashboardFeatureProvider mDashboardFeatureProvider; - private DevicePolicyManager mDPM; private SecurityFeatureProvider mSecurityFeatureProvider; private UserManager mUm; private ChooseLockSettingsHelper mChooseLockSettingsHelper; private LockPatternUtils mLockPatternUtils; - private ManagedLockPasswordProvider mManagedPasswordProvider; - - private SwitchPreference mVisiblePatternProfile; - private RestrictedSwitchPreference mUnifyProfile; private int mProfileChallengeUserId; - private String mCurrentDevicePassword; - private String mCurrentProfilePassword; - private LocationPreferenceController mLocationController; private ManageDeviceAdminPreferenceController mManageDeviceAdminPreferenceController; private EnterprisePrivacyPreferenceController mEnterprisePrivacyPreferenceController; private EncryptionStatusPreferenceController mEncryptionStatusPreferenceController; - private LockScreenNotificationPreferenceController mLockScreenNotificationPreferenceController; private ManageTrustAgentsPreferenceController mManageTrustAgentsPreferenceController; private ScreenPinningPreferenceController mScreenPinningPreferenceController; private SimLockPreferenceController mSimLockPreferenceController; private ShowPasswordPreferenceController mShowPasswordPreferenceController; private TrustAgentListPreferenceController mTrustAgentListPreferenceController; + private LockScreenPreferenceController mLockScreenPreferenceController; + private ChangeScreenLockPreferenceController mChangeScreenLockPreferenceController; + private ChangeProfileScreenLockPreferenceController + mChangeProfileScreenLockPreferenceController; + private LockUnificationPreferenceController mLockUnificationPreferenceController; + private VisiblePatternProfilePreferenceController mVisiblePatternProfilePreferenceController; + private FingerprintStatusPreferenceController mFingerprintStatusPreferenceController; + private FingerprintProfileStatusPreferenceController + mFingerprintProfileStatusPreferenceController; @Override public int getMetricsCategory() { @@ -132,8 +89,6 @@ public class SecuritySettingsV2 extends DashboardFragment mSecurityFeatureProvider = FeatureFactory.getFactory(context).getSecurityFeatureProvider(); mLocationController = new LocationPreferenceController(context, getLifecycle()); mLockPatternUtils = mSecurityFeatureProvider.getLockPatternUtils(context); - mManagedPasswordProvider = ManagedLockPasswordProvider.get(context, MY_USER_ID); - mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); mUm = UserManager.get(context); mDashboardFeatureProvider = FeatureFactory.getFactory(context) .getDashboardFeatureProvider(context); @@ -151,14 +106,18 @@ public class SecuritySettingsV2 extends DashboardFragment return TAG; } + + @Override + public int getHelpResource() { + return R.string.help_url_security; + } + @Override protected List getPreferenceControllers(Context context) { mManageDeviceAdminPreferenceController = new ManageDeviceAdminPreferenceController(context); mEnterprisePrivacyPreferenceController = new EnterprisePrivacyPreferenceController(context); - mLockScreenNotificationPreferenceController - = new LockScreenNotificationPreferenceController(context); mManageTrustAgentsPreferenceController = new ManageTrustAgentsPreferenceController(context); mScreenPinningPreferenceController = new ScreenPinningPreferenceController(context); mSimLockPreferenceController = new SimLockPreferenceController(context); @@ -167,46 +126,21 @@ public class SecuritySettingsV2 extends DashboardFragment context, PREF_KEY_ENCRYPTION_SECURITY_PAGE); mTrustAgentListPreferenceController = new TrustAgentListPreferenceController(getActivity(), this /* host */, getLifecycle()); + mLockScreenPreferenceController = new LockScreenPreferenceController(context); + mChangeScreenLockPreferenceController = new ChangeScreenLockPreferenceController(context, + this /* host */); + mChangeProfileScreenLockPreferenceController = + new ChangeProfileScreenLockPreferenceController(context, this /* host */); + mLockUnificationPreferenceController = new LockUnificationPreferenceController(context, + this /* host */); + mVisiblePatternProfilePreferenceController = + new VisiblePatternProfilePreferenceController(context); + mFingerprintStatusPreferenceController = new FingerprintStatusPreferenceController(context); + mFingerprintProfileStatusPreferenceController = + new FingerprintProfileStatusPreferenceController(context); return null; } - private static int getResIdForLockUnlockScreen(LockPatternUtils lockPatternUtils, - ManagedLockPasswordProvider managedPasswordProvider, int userId) { - final boolean isMyUser = userId == MY_USER_ID; - int resid = 0; - 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(userId)) { - case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: - 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 = 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 = isMyUser ? R.xml.security_settings_password - : R.xml.security_settings_password_profile; - break; - case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: - resid = managedPasswordProvider.getResIdForLockUnlockScreen(!isMyUser); - break; - } - } - return resid; - } - /** * Important! * @@ -214,65 +148,15 @@ public class SecuritySettingsV2 extends DashboardFragment * logic or adding/removing preferences here. */ private PreferenceScreen createPreferenceHierarchy() { - PreferenceScreen root = getPreferenceScreen(); - if (root != null) { - root.removeAll(); - } - addPreferencesFromResource(R.xml.security_settings_v2); - root = getPreferenceScreen(); + final PreferenceScreen root = getPreferenceScreen(); mTrustAgentListPreferenceController.displayPreference(root); - - // Add options for lock/unlock screen - final int resid = getResIdForLockUnlockScreen(mLockPatternUtils, - mManagedPasswordProvider, MY_USER_ID); - addPreferencesFromResource(resid); - - // DO or PO installed in the user may disallow to change password. - disableIfPasswordQualityManaged(KEY_UNLOCK_SET_OR_CHANGE, MY_USER_ID); - - mProfileChallengeUserId = Utils.getManagedProfileId(mUm, MY_USER_ID); - if (mProfileChallengeUserId != UserHandle.USER_NULL - && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) { - addPreferencesFromResource(R.xml.security_settings_profile); - addPreferencesFromResource(R.xml.security_settings_unification); - final int profileResid = getResIdForLockUnlockScreen(mLockPatternUtils, - mManagedPasswordProvider, mProfileChallengeUserId); - addPreferencesFromResource(profileResid); - maybeAddFingerprintPreference(root, mProfileChallengeUserId); - if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) { - final Preference lockPreference = - root.findPreference(KEY_UNLOCK_SET_OR_CHANGE_PROFILE); - final String summary = getContext().getString( - R.string.lock_settings_profile_unified_summary); - lockPreference.setSummary(summary); - lockPreference.setEnabled(false); - // PO may disallow to change password for the profile, but screen lock and managed - // profile's lock is the same. Disable main "Screen lock" menu. - disableIfPasswordQualityManaged(KEY_UNLOCK_SET_OR_CHANGE, mProfileChallengeUserId); - } else { - // PO may disallow to change profile password, and the profile's password is - // separated from screen lock password. Disable profile specific "Screen lock" menu. - disableIfPasswordQualityManaged(KEY_UNLOCK_SET_OR_CHANGE_PROFILE, - mProfileChallengeUserId); - } - } - Preference unlockSetOrChange = findPreference(KEY_UNLOCK_SET_OR_CHANGE); - if (unlockSetOrChange instanceof GearPreference) { - ((GearPreference) unlockSetOrChange).setOnGearClickListener(this); - } - - - // Fingerprint and trust agents - PreferenceGroup securityCategory = (PreferenceGroup) - root.findPreference(KEY_SECURITY_CATEGORY); - if (securityCategory != null) { - maybeAddFingerprintPreference(securityCategory, UserHandle.myUserId()); - setLockscreenPreferencesSummary(securityCategory); - } - - mVisiblePatternProfile = - (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN_PROFILE); - mUnifyProfile = (RestrictedSwitchPreference) root.findPreference(KEY_UNIFICATION); + mLockScreenPreferenceController.displayPreference(root); + mChangeScreenLockPreferenceController.displayPreference(root); + mChangeProfileScreenLockPreferenceController.displayPreference(root); + mLockUnificationPreferenceController.displayPreference(root); + mVisiblePatternProfilePreferenceController.displayPreference(root); + mFingerprintStatusPreferenceController.displayPreference(root); + mFingerprintProfileStatusPreferenceController.displayPreference(root); mSimLockPreferenceController.displayPreference(root); mScreenPinningPreferenceController.displayPreference(root); @@ -280,45 +164,40 @@ public class SecuritySettingsV2 extends DashboardFragment // Advanced Security features mManageTrustAgentsPreferenceController.displayPreference(root); - PreferenceGroup securityStatusPreferenceGroup = - (PreferenceGroup) root.findPreference(KEY_SECURITY_STATUS); - final List tilePrefs = mDashboardFeatureProvider.getPreferencesForCategory( - getActivity(), getPrefContext(), getMetricsCategory(), - CategoryKey.CATEGORY_SECURITY); - int numSecurityStatusPrefs = 0; - if (tilePrefs != null && !tilePrefs.isEmpty()) { - for (Preference preference : tilePrefs) { - if (!TextUtils.isEmpty(preference.getKey()) - && preference.getKey().startsWith(SECURITY_STATUS_KEY_PREFIX)) { - // Injected security status settings are placed under the Security status - // category. - securityStatusPreferenceGroup.addPreference(preference); - numSecurityStatusPrefs++; - } else { - // Other injected settings are placed under the Security preference screen. - root.addPreference(preference); - } - } - } - - if (numSecurityStatusPrefs == 0) { - root.removePreference(securityStatusPreferenceGroup); - } else if (numSecurityStatusPrefs > 0) { - // Update preference data with tile data. Security feature provider only updates the - // data if it actually needs to be changed. - mSecurityFeatureProvider.updatePreferences(getActivity(), root, - mDashboardFeatureProvider.getTilesForCategory( - CategoryKey.CATEGORY_SECURITY)); - } - - for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) { - final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]); - if (pref != null) pref.setOnPreferenceChangeListener(this); - } +// PreferenceGroup securityStatusPreferenceGroup = +// (PreferenceGroup) root.findPreference(KEY_SECURITY_STATUS); +// final List tilePrefs = mDashboardFeatureProvider.getPreferencesForCategory( +// getActivity(), getPrefContext(), getMetricsCategory(), +// CategoryKey.CATEGORY_SECURITY); +// int numSecurityStatusPrefs = 0; +// if (tilePrefs != null && !tilePrefs.isEmpty()) { +// for (Preference preference : tilePrefs) { +// if (!TextUtils.isEmpty(preference.getKey()) +// && preference.getKey().startsWith(SECURITY_STATUS_KEY_PREFIX)) { +// // Injected security status settings are placed under the Security status +// // category. +// securityStatusPreferenceGroup.addPreference(preference); +// numSecurityStatusPrefs++; +// } else { +// // Other injected settings are placed under the Security preference screen. +// root.addPreference(preference); +// } +// } +// } +// +// if (numSecurityStatusPrefs == 0) { +// root.removePreference(securityStatusPreferenceGroup); +// } else if (numSecurityStatusPrefs > 0) { +// // Update preference data with tile data. Security feature provider only updates the +// // data if it actually needs to be changed. +// mSecurityFeatureProvider.updatePreferences(getActivity(), root, +// mDashboardFeatureProvider.getTilesForCategory( +// CategoryKey.CATEGORY_SECURITY)); +// } mLocationController.displayPreference(root); mManageDeviceAdminPreferenceController.updateState( - root.findPreference(KEY_MANAGE_DEVICE_ADMIN)); + root.findPreference(mManageDeviceAdminPreferenceController.getPreferenceKey())); mEnterprisePrivacyPreferenceController.displayPreference(root); final Preference enterprisePrivacyPreference = root.findPreference( mEnterprisePrivacyPreferenceController.getPreferenceKey()); @@ -327,47 +206,6 @@ public class SecuritySettingsV2 extends DashboardFragment return root; } - @VisibleForTesting - void setLockscreenPreferencesSummary(PreferenceGroup group) { - final Preference lockscreenPreferences = group.findPreference(KEY_LOCKSCREEN_PREFERENCES); - if (lockscreenPreferences != null) { - lockscreenPreferences.setSummary( - mLockScreenNotificationPreferenceController.getSummaryResource()); - } - } - - /* - * Sets the preference as disabled by admin if PASSWORD_QUALITY_MANAGED is set. - * The preference must be a RestrictedPreference. - */ - private void disableIfPasswordQualityManaged(String preferenceKey, int userId) { - final RestrictedLockUtils.EnforcedAdmin admin = - RestrictedLockUtils.checkIfPasswordQualityIsSet( - getActivity(), userId); - if (admin != null && mDPM.getPasswordQuality(admin.component, userId) == - DevicePolicyManager.PASSWORD_QUALITY_MANAGED) { - final RestrictedPreference pref = - (RestrictedPreference) getPreferenceScreen().findPreference(preferenceKey); - pref.setDisabledByAdmin(admin); - } - } - - private void maybeAddFingerprintPreference(PreferenceGroup securityCategory, int userId) { - Preference fingerprintPreference = - FingerprintSettings.getFingerprintPreferenceForUser( - securityCategory.getContext(), userId); - if (fingerprintPreference != null) { - securityCategory.addPreference(fingerprintPreference); - } - } - - @Override - public void onGearClick(GearPreference p) { - if (KEY_UNLOCK_SET_OR_CHANGE.equals(p.getKey())) { - startFragment(this, ScreenLockSettings.class.getName(), 0, 0, null); - } - } - @Override public void onResume() { super.onResume(); @@ -376,18 +214,40 @@ public class SecuritySettingsV2 extends DashboardFragment // depend on others... createPreferenceHierarchy(); - if (mVisiblePatternProfile != null) { - mVisiblePatternProfile.setChecked(mLockPatternUtils.isVisiblePatternEnabled( - mProfileChallengeUserId)); + final Preference visiblePatternProfilePref = getPreferenceScreen().findPreference( + mVisiblePatternProfilePreferenceController.getPreferenceKey()); + if (visiblePatternProfilePref != null) { + visiblePatternProfilePref + .setOnPreferenceChangeListener(mVisiblePatternProfilePreferenceController); + mVisiblePatternProfilePreferenceController.updateState(visiblePatternProfilePref); } - updateUnificationPreference(); - final Preference showPasswordPref = getPreferenceScreen().findPreference( mShowPasswordPreferenceController.getPreferenceKey()); showPasswordPref.setOnPreferenceChangeListener(mShowPasswordPreferenceController); mShowPasswordPreferenceController.updateState(showPasswordPref); + final Preference lockUnificationPref = getPreferenceScreen().findPreference( + mLockUnificationPreferenceController.getPreferenceKey()); + lockUnificationPref.setOnPreferenceChangeListener(mLockUnificationPreferenceController); + mLockUnificationPreferenceController.updateState(lockUnificationPref); + + final Preference changeDeviceLockPref = getPreferenceScreen().findPreference( + mChangeScreenLockPreferenceController.getPreferenceKey()); + mChangeScreenLockPreferenceController.updateState(changeDeviceLockPref); + + mFingerprintStatusPreferenceController.updateState( + getPreferenceScreen().findPreference( + mFingerprintStatusPreferenceController.getPreferenceKey())); + + mFingerprintProfileStatusPreferenceController.updateState( + getPreferenceScreen().findPreference( + mFingerprintProfileStatusPreferenceController.getPreferenceKey())); + + final Preference changeProfileLockPref = getPreferenceScreen().findPreference( + mChangeProfileScreenLockPreferenceController.getPreferenceKey()); + mChangeProfileScreenLockPreferenceController.updateState(changeProfileLockPref); + final Preference encryptionStatusPref = getPreferenceScreen().findPreference( mEncryptionStatusPreferenceController.getPreferenceKey()); mEncryptionStatusPreferenceController.updateState(encryptionStatusPref); @@ -395,56 +255,20 @@ public class SecuritySettingsV2 extends DashboardFragment mLocationController.updateSummary(); } - @VisibleForTesting - void updateUnificationPreference() { - if (mUnifyProfile != null) { - final boolean separate = - mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId); - mUnifyProfile.setChecked(!separate); - if (separate) { - mUnifyProfile.setDisabledByAdmin(RestrictedLockUtils.checkIfRestrictionEnforced( - getContext(), UserManager.DISALLOW_UNIFIED_PASSWORD, - mProfileChallengeUserId)); - } - } - } @Override public boolean onPreferenceTreeClick(Preference preference) { if (mTrustAgentListPreferenceController.handlePreferenceTreeClick(preference)) { return true; } - final String key = preference.getKey(); - if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) { - // TODO(b/35930129): Remove once existing password can be passed into vold directly. - // Currently we need this logic to ensure that the QUIET_MODE is off for any work - // profile with unified challenge on FBE-enabled devices. Otherwise, vold would not be - // able to complete the operation due to the lack of (old) encryption key. - if (mProfileChallengeUserId != UserHandle.USER_NULL - && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId) - && StorageManager.isFileEncryptedNativeOnly()) { - if (Utils.startQuietModeDialogIfNecessary(this.getActivity(), mUm, - mProfileChallengeUserId)) { - return false; - } - } - startFragment(this, ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), - R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null); - } else if (KEY_UNLOCK_SET_OR_CHANGE_PROFILE.equals(key)) { - if (Utils.startQuietModeDialogIfNecessary(this.getActivity(), mUm, - mProfileChallengeUserId)) { - return false; - } - Bundle extras = new Bundle(); - extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId); - startFragment(this, ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), - R.string.lock_settings_picker_title_profile, - SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras); - } else { - // If we didn't handle it, let preferences handle it. - return super.onPreferenceTreeClick(preference); + if (mChangeScreenLockPreferenceController.handlePreferenceTreeClick(preference)) { + return true; } - return true; + if (mChangeProfileScreenLockPreferenceController.handlePreferenceTreeClick(preference)) { + return true; + } + // If we didn't handle it, let preferences handle it. + return super.onPreferenceTreeClick(preference); } /** @@ -453,139 +277,34 @@ public class SecuritySettingsV2 extends DashboardFragment @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == CHANGE_TRUST_AGENT_SETTINGS && resultCode == Activity.RESULT_OK) { - mTrustAgentListPreferenceController.handleActivityResult(resultCode); + if (mTrustAgentListPreferenceController.handleActivityResult(requestCode, resultCode)) { 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; - } else if (requestCode == UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST - && resultCode == Activity.RESULT_OK) { - ununifyLocks(); + } + if (mLockUnificationPreferenceController.handleActivityResult( + requestCode, resultCode, data)) { return; } createPreferenceHierarchy(); } - void launchConfirmDeviceLockForUnification() { - final String title = getActivity().getString( - R.string.unlock_set_unlock_launch_picker_title); - final ChooseLockSettingsHelper helper = - new ChooseLockSettingsHelper(getActivity(), this); - if (!helper.launchConfirmationActivity( - UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, MY_USER_ID)) { - launchConfirmProfileLockForUnification(); - } - } - - private void launchConfirmProfileLockForUnification() { - final String title = getActivity().getString( - R.string.unlock_set_unlock_launch_picker_title_profile); - 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); - if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { - mLockPatternUtils.saveLockPattern( - LockPatternUtils.stringToPattern(mCurrentProfilePassword), - mCurrentDevicePassword, MY_USER_ID); - } else { - mLockPatternUtils.saveLockPassword( - mCurrentProfilePassword, mCurrentDevicePassword, - profileQuality, MY_USER_ID); - } - mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false, - mCurrentProfilePassword); - final boolean profilePatternVisibility = - mLockPatternUtils.isVisiblePatternEnabled(mProfileChallengeUserId); - mLockPatternUtils.setVisiblePatternEnabled(profilePatternVisibility, MY_USER_ID); - mCurrentDevicePassword = null; - mCurrentProfilePassword = null; - } - - void unifyUncompliantLocks() { - mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false, - mCurrentProfilePassword); - startFragment(this, ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), - R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null); - } - - private void ununifyLocks() { - Bundle extras = new Bundle(); - extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId); - startFragment(this, - ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), - R.string.lock_settings_picker_title_profile, - SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras); - } - - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - boolean result = true; - final String key = preference.getKey(); - final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); - if (KEY_VISIBLE_PATTERN_PROFILE.equals(key)) { - if (Utils.startQuietModeDialogIfNecessary(this.getActivity(), mUm, - mProfileChallengeUserId)) { - return false; - } - lockPatternUtils.setVisiblePatternEnabled((Boolean) value, mProfileChallengeUserId); - } else if (KEY_UNIFICATION.equals(key)) { - if (Utils.startQuietModeDialogIfNecessary(this.getActivity(), mUm, - mProfileChallengeUserId)) { - return false; - } - if ((Boolean) value) { - final boolean compliantForDevice = - (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId) - >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING - && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify( - mProfileChallengeUserId)); - UnificationConfirmationDialog dialog = - UnificationConfirmationDialog.newIntance(compliantForDevice); - dialog.show(getChildFragmentManager(), TAG_UNIFICATION_DIALOG); - } else { - final String title = getActivity().getString( - R.string.unlock_set_unlock_launch_picker_title); - final ChooseLockSettingsHelper helper = - new ChooseLockSettingsHelper(getActivity(), this); - if (!helper.launchConfirmationActivity( - UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, MY_USER_ID)) { - ununifyLocks(); - } - } - } - return result; - } - - @Override - public int getHelpResource() { - return R.string.help_url_security; - } - /** * For Search. Please keep it in sync when updating "createPreferenceHierarchy()" */ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new SecuritySearchIndexProvider(); + void launchConfirmDeviceLockForUnification() { + mLockUnificationPreferenceController.launchConfirmDeviceLockForUnification(); + } + + void unifyUncompliantLocks() { + mLockUnificationPreferenceController.unifyUncompliantLocks(); + } + + void updateUnificationPreference() { + mLockUnificationPreferenceController.updateState(null); + } + private static class SecuritySearchIndexProvider extends BaseSearchIndexProvider { // TODO (b/68001777) Refactor indexing to include all XML and block other settings. @@ -594,123 +313,11 @@ public class SecuritySettingsV2 extends DashboardFragment public List getXmlResourcesToIndex( Context context, boolean enabled) { final List index = new ArrayList<>(); - - final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); - final ManagedLockPasswordProvider managedPasswordProvider = - ManagedLockPasswordProvider.get(context, MY_USER_ID); - final DevicePolicyManager dpm = (DevicePolicyManager) - context.getSystemService(Context.DEVICE_POLICY_SERVICE); - final UserManager um = UserManager.get(context); - final int profileUserId = Utils.getManagedProfileId(um, MY_USER_ID); - - // To add option for unlock screen, user's password must not be managed and - // must not be unified with managed profile, whose password is managed. - if (!isPasswordManaged(MY_USER_ID, context, dpm) - && (profileUserId == UserHandle.USER_NULL - || lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId) - || !isPasswordManaged(profileUserId, context, dpm))) { - // Add options for lock/unlock screen - final int resId = getResIdForLockUnlockScreen(lockPatternUtils, - managedPasswordProvider, MY_USER_ID); - index.add(getSearchResource(context, resId)); - } - - if (profileUserId != UserHandle.USER_NULL - && lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId) - && !isPasswordManaged(profileUserId, context, dpm)) { - index.add(getSearchResource(context, getResIdForLockUnlockScreen( - lockPatternUtils, managedPasswordProvider, profileUserId))); - } - // Append the rest of the settings - index.add(getSearchResource(context, R.xml.security_settings_misc)); - - return index; - } - - private SearchIndexableResource getSearchResource(Context context, int xmlResId) { final SearchIndexableResource sir = new SearchIndexableResource(context); - sir.xmlResId = xmlResId; - return sir; - } - - private boolean isPasswordManaged(int userId, Context context, DevicePolicyManager dpm) { - final RestrictedLockUtils.EnforcedAdmin admin = - RestrictedLockUtils.checkIfPasswordQualityIsSet( - context, userId); - return admin != null && dpm.getPasswordQuality(admin.component, userId) == - DevicePolicyManager.PASSWORD_QUALITY_MANAGED; - } - - @Override - public List getRawDataToIndex(Context context, boolean enabled) { - final List result = new ArrayList(); - final Resources res = context.getResources(); - - final String screenTitle = res.getString(R.string.security_settings_title); - - SearchIndexableRaw data = new SearchIndexableRaw(context); - data.title = screenTitle; - data.key = "security_settings_screen"; - data.screenTitle = screenTitle; - result.add(data); - - final UserManager um = UserManager.get(context); - - // Fingerprint - final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(context); - if (fpm != null && fpm.isHardwareDetected()) { - // This catches the title which can be overloaded in an overlay - data = new SearchIndexableRaw(context); - data.title = res.getString(R.string.security_settings_fingerprint_preference_title); - data.key = "security_fingerprint"; - data.screenTitle = screenTitle; - result.add(data); - // Fallback for when the above doesn't contain "fingerprint" - data = new SearchIndexableRaw(context); - data.title = res.getString(R.string.fingerprint_manage_category_title); - data.key = "security_managed_fingerprint"; - data.screenTitle = screenTitle; - result.add(data); - } - - final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); - final int profileUserId = Utils.getManagedProfileId(um, MY_USER_ID); - 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.key = "security_use_one_lock"; - data.screenTitle = screenTitle; - result.add(data); - } - } - return result; - } - - @Override - public List getNonIndexableKeys(Context context) { - final List keys = super.getNonIndexableKeys(context); - - new SimLockPreferenceController(context).updateNonIndexableKeys(keys); - - if (!(new EnterprisePrivacyPreferenceController(context)) - .isAvailable()) { - keys.add(KEY_ENTERPRISE_PRIVACY); - } - - // Duplicate in special app access - keys.add(KEY_MANAGE_DEVICE_ADMIN); - // Duplicates between parent-child - keys.add(KEY_LOCATION); - keys.add(KEY_ENCRYPTION_AND_CREDENTIALS); - keys.add(KEY_LOCATION_SCANNING); - - return keys; + sir.xmlResId = R.xml.security_settings_v2; + index.add(sir); + return index; } } diff --git a/src/com/android/settings/security/ShowPasswordPreferenceController.java b/src/com/android/settings/security/ShowPasswordPreferenceController.java index 9f9b52db71b..d0216e8e1b3 100644 --- a/src/com/android/settings/security/ShowPasswordPreferenceController.java +++ b/src/com/android/settings/security/ShowPasswordPreferenceController.java @@ -44,10 +44,11 @@ public class ShowPasswordPreferenceController extends TogglePreferenceController } @Override - public void setChecked(boolean isChecked) { + public boolean setChecked(boolean isChecked) { Settings.System.putInt(mContext.getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD, isChecked ? 1 : 0); mLockPatternUtils.setVisiblePasswordEnabled(isChecked, MY_USER_ID); + return true; } @Override diff --git a/src/com/android/settings/security/UnificationConfirmationDialog.java b/src/com/android/settings/security/UnificationConfirmationDialog.java index 21118d7e402..482e26880ee 100644 --- a/src/com/android/settings/security/UnificationConfirmationDialog.java +++ b/src/com/android/settings/security/UnificationConfirmationDialog.java @@ -27,9 +27,11 @@ import com.android.settings.R; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; public class UnificationConfirmationDialog extends InstrumentedDialogFragment { + + static final String TAG_UNIFICATION_DIALOG = "unification_dialog"; private static final String EXTRA_COMPLIANT = "compliant"; - public static UnificationConfirmationDialog newIntance(boolean compliant) { + public static UnificationConfirmationDialog newInstance(boolean compliant) { UnificationConfirmationDialog dialog = new UnificationConfirmationDialog(); Bundle args = new Bundle(); @@ -38,11 +40,11 @@ public class UnificationConfirmationDialog extends InstrumentedDialogFragment { return dialog; } - @Override - public void show(FragmentManager manager, String tag) { - if (manager.findFragmentByTag(tag) == null) { + public void show(SecuritySettingsV2 host) { + final FragmentManager manager = host.getChildFragmentManager(); + if (manager.findFragmentByTag(TAG_UNIFICATION_DIALOG) == null) { // Prevent opening multiple dialogs if tapped on button quickly - super.show(manager, tag); + show(manager, TAG_UNIFICATION_DIALOG); } } @@ -56,11 +58,12 @@ public class UnificationConfirmationDialog extends InstrumentedDialogFragment { : R.string.lock_settings_profile_unification_dialog_uncompliant_body) .setPositiveButton( compliant ? R.string.lock_settings_profile_unification_dialog_confirm - : R.string.lock_settings_profile_unification_dialog_uncompliant_confirm, + : R.string + .lock_settings_profile_unification_dialog_uncompliant_confirm, (dialog, whichButton) -> { if (compliant) { parentFragment.launchConfirmDeviceLockForUnification(); - } else { + } else { parentFragment.unifyUncompliantLocks(); } } diff --git a/src/com/android/settings/security/VisiblePatternProfilePreferenceController.java b/src/com/android/settings/security/VisiblePatternProfilePreferenceController.java new file mode 100644 index 00000000000..39b1916a072 --- /dev/null +++ b/src/com/android/settings/security/VisiblePatternProfilePreferenceController.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 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.security; + +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; + +import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; + +import com.android.internal.widget.LockPatternUtils; +import com.android.settings.Utils; +import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; + +public class VisiblePatternProfilePreferenceController extends TogglePreferenceController { + + private static final String KEY_VISIBLE_PATTERN_PROFILE = "visiblepattern_profile"; + + private final LockPatternUtils mLockPatternUtils; + private final UserManager mUm; + private final int mUserId = UserHandle.myUserId(); + private final int mProfileChallengeUserId; + + public VisiblePatternProfilePreferenceController(Context context) { + super(context, KEY_VISIBLE_PATTERN_PROFILE); + mUm = (UserManager) context.getSystemService(Context.USER_SERVICE); + mLockPatternUtils = FeatureFactory.getFactory(context) + .getSecurityFeatureProvider() + .getLockPatternUtils(context); + mProfileChallengeUserId = Utils.getManagedProfileId(mUm, mUserId); + } + + @Override + public int getAvailabilityStatus() { + if (mLockPatternUtils.isSecure(mProfileChallengeUserId) + && mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId) + == PASSWORD_QUALITY_SOMETHING) { + return AVAILABLE; + } + return DISABLED_FOR_USER; + } + + @Override + public boolean isChecked() { + return mLockPatternUtils.isVisiblePatternEnabled( + mProfileChallengeUserId); + } + + @Override + public boolean setChecked(boolean isChecked) { + if (Utils.startQuietModeDialogIfNecessary(mContext, mUm, mProfileChallengeUserId)) { + return false; + } + mLockPatternUtils.setVisiblePatternEnabled(isChecked, mProfileChallengeUserId); + return true; + } +} diff --git a/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java b/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java index d99757be256..8d198e7b269 100644 --- a/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java +++ b/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java @@ -16,6 +16,8 @@ package com.android.settings.security.trustagent; +import static com.android.settings.security.SecuritySettingsV2.CHANGE_TRUST_AGENT_SETTINGS; + import android.app.Activity; import android.content.Intent; import android.os.Bundle; @@ -113,7 +115,7 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro final ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(mActivity, mHost); mTrustAgentClickIntent = preference.getIntent(); boolean confirmationLaunched = helper.launchConfirmationActivity( - SecuritySettingsV2.CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle()); + CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle()); if (!confirmationLaunched && mTrustAgentClickIntent != null) { // If this returns false, it means no password confirmation is required. @@ -163,10 +165,14 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro } } - public void handleActivityResult(int resultCode) { - if (resultCode == Activity.RESULT_OK && mTrustAgentClickIntent != null) { - mHost.startActivity(mTrustAgentClickIntent); - mTrustAgentClickIntent = null; + public boolean handleActivityResult(int requestCode, int resultCode) { + if (requestCode == CHANGE_TRUST_AGENT_SETTINGS && resultCode == Activity.RESULT_OK) { + if (mTrustAgentClickIntent != null){ + mHost.startActivity(mTrustAgentClickIntent); + mTrustAgentClickIntent = null; + } + return true; } + return false; } } diff --git a/src/com/android/settings/widget/MasterSwitchPreference.java b/src/com/android/settings/widget/MasterSwitchPreference.java index d47de88b1c1..73774beaa45 100644 --- a/src/com/android/settings/widget/MasterSwitchPreference.java +++ b/src/com/android/settings/widget/MasterSwitchPreference.java @@ -22,7 +22,6 @@ import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; import android.widget.Switch; -import android.widget.TextView; import com.android.settings.R; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; diff --git a/tests/robotests/src/com/android/settings/security/SecuritySettingsTest.java b/tests/robotests/src/com/android/settings/security/SecuritySettingsTest.java index 231cce95a82..81e1481a307 100644 --- a/tests/robotests/src/com/android/settings/security/SecuritySettingsTest.java +++ b/tests/robotests/src/com/android/settings/security/SecuritySettingsTest.java @@ -17,7 +17,6 @@ package com.android.settings.security; import static com.google.common.truth.Truth.assertThat; - import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -35,14 +34,12 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager.EnforcingUser; import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceScreen; import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; import com.android.settings.TestConfig; import com.android.settings.dashboard.SummaryLoader; -import com.android.settings.notification.LockScreenNotificationPreferenceController; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.XmlTestUtils; @@ -161,24 +158,6 @@ public class SecuritySettingsTest { R.plurals.manage_trust_agents_summary_on, 2, 2)); } - @Test - public void testSetLockscreenPreferencesSummary_shouldSetSummaryFromLockScreenNotification() { - final Preference preference = mock(Preference.class); - final PreferenceGroup group = mock(PreferenceGroup.class); - when(group.findPreference(SecuritySettings.KEY_LOCKSCREEN_PREFERENCES)) - .thenReturn(preference); - final LockScreenNotificationPreferenceController controller = - mock(LockScreenNotificationPreferenceController.class); - - final SecuritySettings securitySettings = new SecuritySettings(); - ReflectionHelpers.setField(securitySettings, - "mLockScreenNotificationPreferenceController", controller); - - when(controller.getSummaryResource()).thenReturn(1234); - securitySettings.setLockscreenPreferencesSummary(group); - verify(preference).setSummary(1234); - } - @Test public void testNonIndexableKeys_existInXmlLayout() { final Context context = spy(RuntimeEnvironment.application);