Merge "Fork SecuritySettings page and hide behind a feature flag."

This commit is contained in:
TreeHugger Robot
2018-01-03 02:02:58 +00:00
committed by Android (Google) Code Review
12 changed files with 1154 additions and 5 deletions

View File

@@ -68,6 +68,7 @@ public class Settings extends SettingsActivity {
public static class AccessibilityContrastSettingsActivity extends SettingsActivity { /* empty */ }
public static class AccessibilityDaltonizerSettingsActivity extends SettingsActivity { /* empty */ }
public static class SecuritySettingsActivity extends SettingsActivity { /* empty */ }
public static class SecuritySettingsActivityV2 extends SettingsActivity { /* empty */ }
public static class UsageAccessSettingsActivity extends SettingsActivity { /* empty */ }
public static class LocationSettingsActivity extends SettingsActivity { /* empty */ }
public static class PrivacySettingsActivity extends SettingsActivity { /* empty */ }

View File

@@ -751,6 +751,7 @@ public class SettingsActivity extends SettingsDrawerActivity
PackageManager pm = getPackageManager();
final UserManager um = UserManager.get(this);
final boolean isAdmin = um.isAdminUser();
final FeatureFactory featureFactory = FeatureFactory.getFactory(this);
boolean somethingChanged = false;
String packageName = getPackageName();
somethingChanged = setTileEnabled(
@@ -805,12 +806,26 @@ public class SettingsActivity extends SettingsDrawerActivity
!isConnectedDeviceV2Enabled && !UserManager.isDeviceInDemoMode(this) /* enabled */,
isAdmin) || somethingChanged;
final boolean isSecurityV2Enabled = featureFactory.getSecurityFeatureProvider()
.isSecuritySettingsV2Enabled(this);
// Enable new security page if v2 enabled
somethingChanged = setTileEnabled(
new ComponentName(packageName,Settings.SecuritySettingsActivityV2.class.getName()),
isSecurityV2Enabled,
isAdmin) || somethingChanged;
// Enable old security page if v2 disabled
somethingChanged = setTileEnabled(
new ComponentName(packageName,Settings.SecuritySettingsActivity.class.getName()),
!isSecurityV2Enabled,
isAdmin) || somethingChanged;
somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.SimSettingsActivity.class.getName()),
Utils.showSimCardTile(this), isAdmin)
|| somethingChanged;
final boolean isBatterySettingsV2Enabled = FeatureFactory.getFactory(this)
final boolean isBatterySettingsV2Enabled = featureFactory
.getPowerUsageFeatureProvider(this)
.isBatteryV2Enabled();
// Enable new battery page if v2 enabled

View File

@@ -26,4 +26,5 @@ public class FeatureFlags {
public static final String CONNECTED_DEVICE_V2 = "settings_connected_device_v2";
public static final String BATTERY_SETTINGS_V2 = "settings_battery_v2";
public static final String BATTERY_DISPLAY_APP_LIST = "settings_battery_display_app_list";
public static final String SECURITY_SETTINGS_V2 = "settings_security_settings_v2";
}

View File

@@ -115,6 +115,7 @@ import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.security.CryptKeeperSettings;
import com.android.settings.security.LockscreenDashboardFragment;
import com.android.settings.security.SecuritySettings;
import com.android.settings.security.SecuritySettingsV2;
import com.android.settings.sim.SimSettings;
import com.android.settings.support.SupportDashboardActivity;
import com.android.settings.system.ResetDashboardFragment;
@@ -163,6 +164,7 @@ public class SettingsGateway {
NotificationStation.class.getName(),
LocationSettings.class.getName(),
SecuritySettings.class.getName(),
SecuritySettingsV2.class.getName(),
UsageAccessDetails.class.getName(),
PrivacySettings.class.getName(),
DeviceAdminSettings.class.getName(),

View File

@@ -33,7 +33,7 @@ import com.android.settings.network.NetworkDashboardFragment;
import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.SoundSettings;
import com.android.settings.security.LockscreenDashboardFragment;
import com.android.settings.security.SecuritySettings;
import com.android.settings.security.SecuritySettingsV2;
import com.android.settings.system.SystemDashboardFragment;
import com.android.settingslib.drawer.CategoryKey;
@@ -77,7 +77,7 @@ public class DashboardFragmentRegistry {
CategoryKey.CATEGORY_SOUND);
PARENT_TO_CATEGORY_KEY_MAP.put(StorageDashboardFragment.class.getName(),
CategoryKey.CATEGORY_STORAGE);
PARENT_TO_CATEGORY_KEY_MAP.put(SecuritySettings.class.getName(),
PARENT_TO_CATEGORY_KEY_MAP.put(SecuritySettingsV2.class.getName(),
CategoryKey.CATEGORY_SECURITY);
PARENT_TO_CATEGORY_KEY_MAP.put(AccountDetailDashboardFragment.class.getName(),
CategoryKey.CATEGORY_ACCOUNT_DETAIL);

View File

@@ -18,7 +18,9 @@ package com.android.settings.security;
import android.content.Context;
import android.support.v7.preference.PreferenceScreen;
import android.util.FeatureFlagUtils;
import com.android.settings.core.FeatureFlags;
import com.android.settings.security.trustagent.TrustAgentManager;
import com.android.settingslib.drawer.DashboardCategory;
@@ -26,6 +28,10 @@ import com.android.settingslib.drawer.DashboardCategory;
/** FeatureProvider for security. */
public interface SecurityFeatureProvider {
default boolean isSecuritySettingsV2Enabled(Context context) {
return FeatureFlagUtils.isEnabled(context, FeatureFlags.SECURITY_SETTINGS_V2);
}
/** Update preferences with data from associated tiles. */
void updatePreferences(Context context, PreferenceScreen preferenceScreen,
DashboardCategory dashboardCategory);

View File

@@ -0,0 +1,917 @@
package com.android.settings.security;
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.PersistableBundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
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.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFeatureProvider;
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.TrustAgentManager;
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 {
private static final String TAG = "SecuritySettingsV2";
private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";
// 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";
@VisibleForTesting
static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
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;
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 int UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 130;
private static final String TAG_UNIFICATION_DIALOG = "unification_dialog";
// Misc Settings
private static final String KEY_SIM_LOCK = "sim_lock_settings";
private static final String KEY_SHOW_PASSWORD = "show_password";
private static final String KEY_TRUST_AGENT = "trust_agent";
private static final String KEY_SCREEN_PINNING = "screen_pinning_settings";
// 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_SHOW_PASSWORD, 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 TrustAgentManager mTrustAgentManager;
private SubscriptionManager mSubscriptionManager;
private UserManager mUm;
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private LockPatternUtils mLockPatternUtils;
private ManagedLockPasswordProvider mManagedPasswordProvider;
private SwitchPreference mVisiblePatternProfile;
private RestrictedSwitchPreference mUnifyProfile;
private SwitchPreference mShowPassword;
private boolean mIsAdmin;
private Intent mTrustAgentClickIntent;
private int mProfileChallengeUserId;
private String mCurrentDevicePassword;
private String mCurrentProfilePassword;
private LocationPreferenceController mLocationController;
private ManageDeviceAdminPreferenceController mManageDeviceAdminPreferenceController;
private EnterprisePrivacyPreferenceController mEnterprisePrivacyPreferenceController;
private LockScreenNotificationPreferenceController mLockScreenNotificationPreferenceController;
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SECURITY;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mLocationController = new LocationPreferenceController(context, getLifecycle());
mSubscriptionManager = SubscriptionManager.from(context);
mLockPatternUtils = new LockPatternUtils(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);
mSecurityFeatureProvider = FeatureFactory.getFactory(context).getSecurityFeatureProvider();
mTrustAgentManager = mSecurityFeatureProvider.getTrustAgentManager();
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.security_settings_v2;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
mManageDeviceAdminPreferenceController
= new ManageDeviceAdminPreferenceController(context);
mEnterprisePrivacyPreferenceController
= new EnterprisePrivacyPreferenceController(context);
mLockScreenNotificationPreferenceController
= new LockScreenNotificationPreferenceController(context);
return null;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
if (savedInstanceState != null
&& savedInstanceState.containsKey(TRUST_AGENT_CLICK_INTENT)) {
mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT);
}
}
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!
*
* Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the
* 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();
// 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);
}
mIsAdmin = mUm.isAdminUser();
// Fingerprint and trust agents
int numberOfTrustAgent = 0;
PreferenceGroup securityCategory = (PreferenceGroup)
root.findPreference(KEY_SECURITY_CATEGORY);
if (securityCategory != null) {
maybeAddFingerprintPreference(securityCategory, UserHandle.myUserId());
numberOfTrustAgent = addTrustAgentSettings(securityCategory);
setLockscreenPreferencesSummary(securityCategory);
}
mVisiblePatternProfile =
(SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN_PROFILE);
mUnifyProfile = (RestrictedSwitchPreference) root.findPreference(KEY_UNIFICATION);
// Do not display SIM lock for devices without an Icc card
TelephonyManager tm = TelephonyManager.getDefault();
CarrierConfigManager cfgMgr = (CarrierConfigManager)
getActivity().getSystemService(Context.CARRIER_CONFIG_SERVICE);
PersistableBundle b = cfgMgr.getConfig();
if (!mIsAdmin || !isSimIccReady() ||
b.getBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL)) {
root.removePreference(root.findPreference(KEY_SIM_LOCK));
} else {
// Disable SIM lock if there is no ready SIM card.
root.findPreference(KEY_SIM_LOCK).setEnabled(isSimReady());
}
if (Settings.System.getInt(getContentResolver(),
Settings.System.LOCK_TO_APP_ENABLED, 0) != 0) {
root.findPreference(KEY_SCREEN_PINNING).setSummary(
getResources().getString(R.string.switch_on_text));
}
// Encryption status of device
if (LockPatternUtils.isDeviceEncryptionEnabled()) {
root.findPreference(KEY_ENCRYPTION_AND_CREDENTIALS).setSummary(
R.string.encryption_and_credential_settings_summary);
} else {
root.findPreference(KEY_ENCRYPTION_AND_CREDENTIALS).setSummary(
R.string.summary_placeholder);
}
// Show password
mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD);
// Credential storage
final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
// Advanced Security features
initTrustAgentPreference(root, numberOfTrustAgent);
PreferenceGroup securityStatusPreferenceGroup =
(PreferenceGroup) root.findPreference(KEY_SECURITY_STATUS);
final List<Preference> 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);
}
mLocationController.displayPreference(root);
mManageDeviceAdminPreferenceController.updateState(
root.findPreference(KEY_MANAGE_DEVICE_ADMIN));
mEnterprisePrivacyPreferenceController.displayPreference(root);
final Preference enterprisePrivacyPreference = root.findPreference(
mEnterprisePrivacyPreferenceController.getPreferenceKey());
mEnterprisePrivacyPreferenceController.updateState(enterprisePrivacyPreference);
return root;
}
@VisibleForTesting
void initTrustAgentPreference(PreferenceScreen root, int numberOfTrustAgent) {
Preference manageAgents = root.findPreference(KEY_MANAGE_TRUST_AGENTS);
if (manageAgents != null) {
if (!mLockPatternUtils.isSecure(MY_USER_ID)) {
manageAgents.setEnabled(false);
manageAgents.setSummary(R.string.disabled_because_no_backup_security);
} else if (numberOfTrustAgent > 0) {
manageAgents.setSummary(getActivity().getResources().getQuantityString(
R.plurals.manage_trust_agents_summary_on,
numberOfTrustAgent, numberOfTrustAgent));
} else {
manageAgents.setSummary(R.string.manage_trust_agents_summary);
}
}
}
@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);
}
}
// Return the number of trust agents being added
private int addTrustAgentSettings(PreferenceGroup securityCategory) {
final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID);
final List<TrustAgentManager.TrustAgentComponentInfo> agents = mTrustAgentManager.getActiveTrustAgents(
getActivity(), mLockPatternUtils);
for (TrustAgentManager.TrustAgentComponentInfo agent : agents) {
final RestrictedPreference trustAgentPreference =
new RestrictedPreference(securityCategory.getContext());
trustAgentPreference.setKey(KEY_TRUST_AGENT);
trustAgentPreference.setTitle(agent.title);
trustAgentPreference.setSummary(agent.summary);
// Create intent for this preference.
Intent intent = new Intent();
intent.setComponent(agent.componentName);
intent.setAction(Intent.ACTION_MAIN);
trustAgentPreference.setIntent(intent);
// Add preference to the settings menu.
securityCategory.addPreference(trustAgentPreference);
trustAgentPreference.setDisabledByAdmin(agent.admin);
if (!trustAgentPreference.isDisabledByAdmin() && !hasSecurity) {
trustAgentPreference.setEnabled(false);
trustAgentPreference.setSummary(R.string.disabled_because_no_backup_security);
}
}
return agents.size();
}
/* Return true if a there is a Slot that has Icc.
*/
private boolean isSimIccReady() {
TelephonyManager tm = TelephonyManager.getDefault();
final List<SubscriptionInfo> subInfoList =
mSubscriptionManager.getActiveSubscriptionInfoList();
if (subInfoList != null) {
for (SubscriptionInfo subInfo : subInfoList) {
if (tm.hasIccCard(subInfo.getSimSlotIndex())) {
return true;
}
}
}
return false;
}
/* Return true if a SIM is ready for locking.
* TODO: consider adding to TelephonyManager or SubscritpionManasger.
*/
private boolean isSimReady() {
final List<SubscriptionInfo> subInfoList =
mSubscriptionManager.getActiveSubscriptionInfoList();
if (subInfoList != null) {
for (SubscriptionInfo subInfo : subInfoList) {
final int simState = TelephonyManager.getDefault()
.getSimState(subInfo.getSimSlotIndex());
if ((simState != TelephonyManager.SIM_STATE_ABSENT) &&
(simState != TelephonyManager.SIM_STATE_UNKNOWN)) {
return true;
}
}
}
return false;
}
@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 onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mTrustAgentClickIntent != null) {
outState.putParcelable(TRUST_AGENT_CLICK_INTENT, mTrustAgentClickIntent);
}
}
@Override
public void onResume() {
super.onResume();
// Make sure we reload the preference hierarchy since some of these settings
// depend on others...
createPreferenceHierarchy();
if (mVisiblePatternProfile != null) {
mVisiblePatternProfile.setChecked(mLockPatternUtils.isVisiblePatternEnabled(
mProfileChallengeUserId));
}
updateUnificationPreference();
if (mShowPassword != null) {
mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
}
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) {
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 (KEY_TRUST_AGENT.equals(key)) {
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
mTrustAgentClickIntent = preference.getIntent();
boolean confirmationLaunched = helper.launchConfirmationActivity(
CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());
if (!confirmationLaunched&& mTrustAgentClickIntent != null) {
// If this returns false, it means no password confirmation is required.
startActivity(mTrustAgentClickIntent);
mTrustAgentClickIntent = null;
}
} else {
// If we didn't handle it, let preferences handle it.
return super.onPreferenceTreeClick(preference);
}
return true;
}
/**
* see confirmPatternThenDisableAndClear
*/
@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) {
if (mTrustAgentClickIntent != null) {
startActivity(mTrustAgentClickIntent);
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;
} else if (requestCode == UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST
&& resultCode == Activity.RESULT_OK) {
ununifyLocks();
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();
}
}
} 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);
}
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();
private static class SecuritySearchIndexProvider extends BaseSearchIndexProvider {
// TODO (b/68001777) Refactor indexing to include all XML and block other settings.
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final List<SearchIndexableResource> 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<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
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<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
// Do not display SIM lock for devices without an Icc card
final UserManager um = UserManager.get(context);
final TelephonyManager tm = TelephonyManager.from(context);
if (!um.isAdminUser() || !tm.hasIccCard()) {
keys.add(KEY_SIM_LOCK);
}
// TrustAgent settings disappear when the user has no primary security.
if (!lockPatternUtils.isSecure(MY_USER_ID)) {
keys.add(KEY_TRUST_AGENT);
keys.add(KEY_MANAGE_TRUST_AGENTS);
}
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_SCREEN_PINNING);
keys.add(KEY_LOCATION_SCANNING);
return keys;
}
}
static class SummaryProvider implements SummaryLoader.SummaryProvider {
private final Context mContext;
private final SummaryLoader mSummaryLoader;
public SummaryProvider(Context context, SummaryLoader summaryLoader) {
mContext = context;
mSummaryLoader = summaryLoader;
}
@Override
public void setListening(boolean listening) {
if (listening) {
final FingerprintManager fpm =
Utils.getFingerprintManagerOrNull(mContext);
if (fpm != null && fpm.isHardwareDetected()) {
mSummaryLoader.setSummary(this,
mContext.getString(R.string.security_dashboard_summary));
} else {
mSummaryLoader.setSummary(this, mContext.getString(
R.string.security_dashboard_summary_no_fingerprint));
}
}
}
}
public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY =
new SummaryLoader.SummaryProviderFactory() {
@Override
public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
SummaryLoader summaryLoader) {
return new SummaryProvider(activity, summaryLoader);
}
};
}

View File

@@ -0,0 +1,82 @@
/*
* 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.app.AlertDialog;
import android.app.Dialog;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.os.Bundle;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class UnificationConfirmationDialog extends InstrumentedDialogFragment {
private static final String EXTRA_COMPLIANT = "compliant";
public static UnificationConfirmationDialog newIntance(boolean compliant) {
UnificationConfirmationDialog
dialog = new UnificationConfirmationDialog();
Bundle args = new Bundle();
args.putBoolean(EXTRA_COMPLIANT, compliant);
dialog.setArguments(args);
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 SecuritySettingsV2 parentFragment = ((SecuritySettingsV2) getParentFragment());
final boolean compliant = getArguments().getBoolean(EXTRA_COMPLIANT);
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.lock_settings_profile_unification_dialog_title)
.setMessage(compliant ? R.string.lock_settings_profile_unification_dialog_body
: 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,
(dialog, whichButton) -> {
if (compliant) {
parentFragment.launchConfirmDeviceLockForUnification();
} else {
parentFragment.unifyUncompliantLocks();
}
}
)
.setNegativeButton(R.string.cancel, null)
.create();
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
((SecuritySettingsV2) getParentFragment()).updateUnificationPreference();
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DIALOG_UNIFICATION_CONFIRMATION;
}
}