diff --git a/res/values/strings.xml b/res/values/strings.xml index fd359bcded5..bb6bbc0c506 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3015,6 +3015,12 @@ Application is not installed on your phone. + + + Work profile + + Work profile security + Manage apps @@ -5562,6 +5568,7 @@ ignore optimizations, doze, app standby vibrant, RGB, sRGB, color, natural, standard slide to unlock, password, pattern, PIN + work challenge, work, profile diff --git a/res/xml/profile_challenge_settings.xml b/res/xml/profile_challenge_settings.xml new file mode 100644 index 00000000000..cd611191ebd --- /dev/null +++ b/res/xml/profile_challenge_settings.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/res/xml/security_settings_profile.xml b/res/xml/security_settings_profile.xml new file mode 100644 index 00000000000..1c10b794789 --- /dev/null +++ b/res/xml/security_settings_profile.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java index 73f8c46c482..2641ad2665e 100644 --- a/src/com/android/settings/ChooseLockGeneric.java +++ b/src/com/android/settings/ChooseLockGeneric.java @@ -48,7 +48,6 @@ import com.android.internal.widget.LockPatternUtils; public class ChooseLockGeneric extends SettingsActivity { public static final String CONFIRM_CREDENTIALS = "confirm_credentials"; - public static final String KEY_USER_ID = "user_id"; @Override public Intent getIntent() { @@ -369,6 +368,10 @@ public class ChooseLockGeneric extends SettingsActivity { visible = false; } } else if (KEY_UNLOCK_SET_NONE.equals(key)) { + if (mUserId != UserHandle.myUserId()) { + // Swipe doesn't make sense for profiles. + visible = false; + } enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) { enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java index cf330adbe56..eacf1ab0ebd 100644 --- a/src/com/android/settings/ChooseLockPassword.java +++ b/src/com/android/settings/ChooseLockPassword.java @@ -87,7 +87,7 @@ public class ChooseLockPassword extends SettingsActivity { boolean confirmCredentials, int userId) { Intent intent = createIntent(context, quality, minLength, maxLength, requirePasswordToDecrypt, confirmCredentials); - intent.putExtra(ChooseLockGeneric.KEY_USER_ID, userId); + intent.putExtra(Intent.EXTRA_USER_ID, userId); return intent; } @@ -103,7 +103,7 @@ public class ChooseLockPassword extends SettingsActivity { int maxLength, boolean requirePasswordToDecrypt, String password, int userId) { Intent intent = createIntent(context, quality, minLength, maxLength, requirePasswordToDecrypt, password); - intent.putExtra(ChooseLockGeneric.KEY_USER_ID, userId); + intent.putExtra(Intent.EXTRA_USER_ID, userId); return intent; } @@ -120,7 +120,7 @@ public class ChooseLockPassword extends SettingsActivity { int maxLength, boolean requirePasswordToDecrypt, long challenge, int userId) { Intent intent = createIntent(context, quality, minLength, maxLength, requirePasswordToDecrypt, challenge); - intent.putExtra(ChooseLockGeneric.KEY_USER_ID, userId); + intent.putExtra(Intent.EXTRA_USER_ID, userId); return intent; } diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java index 4a6008c9053..e20db932889 100644 --- a/src/com/android/settings/ChooseLockPattern.java +++ b/src/com/android/settings/ChooseLockPattern.java @@ -78,7 +78,7 @@ public class ChooseLockPattern extends SettingsActivity { intent.putExtra("key_lock_method", "pattern"); intent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, confirmCredentials); intent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, requirePassword); - intent.putExtra(ChooseLockGeneric.KEY_USER_ID, userId); + intent.putExtra(Intent.EXTRA_USER_ID, userId); return intent; } diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java index 53fbb7fb46d..b88dea2a9ce 100644 --- a/src/com/android/settings/ChooseLockSettingsHelper.java +++ b/src/com/android/settings/ChooseLockSettingsHelper.java @@ -192,7 +192,7 @@ public final class ChooseLockSettingsHelper { intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, hasChallenge); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); - intent.putExtra(ChooseLockGeneric.KEY_USER_ID, userId); + intent.putExtra(Intent.EXTRA_USER_ID, userId); intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName()); if (external) { intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); diff --git a/src/com/android/settings/ProfileChallengePreferenceFragment.java b/src/com/android/settings/ProfileChallengePreferenceFragment.java new file mode 100644 index 00000000000..34c38f01b1a --- /dev/null +++ b/src/com/android/settings/ProfileChallengePreferenceFragment.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settings; + +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.UserInfo; +import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; +import android.provider.Settings; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.Preference.OnPreferenceChangeListener; +import android.support.v7.preference.Preference.OnPreferenceClickListener; +import android.support.v7.preference.PreferenceCategory; +import android.support.v7.preference.PreferenceGroup; +import android.support.v7.preference.PreferenceScreen; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.widget.LockPatternUtils; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Settings for the Profile Challenge. + */ +public class ProfileChallengePreferenceFragment extends SettingsPreferenceFragment + implements OnPreferenceChangeListener { + private static final String TAG = "WorkChallengePreferenceFragment"; + + private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; + private static final String KEY_VISIBLE_PATTERN = "visiblepattern"; + + private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; + + // Not all preferences make sense for the Work Challenge, this is a whitelist. + private static final Set ALLOWED_PREFERENCE_KEYS = new HashSet<>(); + { + ALLOWED_PREFERENCE_KEYS.add(KEY_UNLOCK_SET_OR_CHANGE); + ALLOWED_PREFERENCE_KEYS.add(KEY_VISIBLE_PATTERN); + } + // These switch preferences need special handling since they're not all stored in Settings. + private static final Set SWITCH_PREFERENCE_KEYS = new HashSet<>(); + { + SWITCH_PREFERENCE_KEYS.add(KEY_VISIBLE_PATTERN); + } + + private LockPatternUtils mLockPatternUtils; + private int mProfileUserId; + + private SwitchPreference mVisiblePattern; + + @Override + protected int getMetricsCategory() { + return MetricsLogger.PROFILE_CHALLENGE; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mLockPatternUtils = new LockPatternUtils(getActivity()); + + mProfileUserId = getArguments().getInt(Intent.EXTRA_USER_ID, -1); + if (mProfileUserId == -1) { + finish(); + } + } + + @Override + public boolean onPreferenceTreeClick(Preference preference) { + final String key = preference.getKey(); + if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) { + Bundle extras = new Bundle(); + extras.putInt(Intent.EXTRA_USER_ID, mProfileUserId); + startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment", + R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, extras); + return true; + } + return super.onPreferenceTreeClick(preference); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object value) { + final String key = preference.getKey(); + if (KEY_VISIBLE_PATTERN.equals(key)) { + mLockPatternUtils.setVisiblePatternEnabled((Boolean) value, mProfileUserId); + return true; + } + return false; + } + + @Override + public void onResume() { + super.onResume(); + + // Make sure we reload the preference hierarchy since some of these settings + // depend on others... + createPreferenceHierarchy(); + + if (mVisiblePattern != null) { + mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled( + mProfileUserId)); + } + } + + private void createPreferenceHierarchy() { + PreferenceScreen root = getPreferenceScreen(); + if (root != null) { + root.removeAll(); + } + addPreferencesFromResource(R.xml.profile_challenge_settings); + root = getPreferenceScreen(); + + // Add options for lock/unlock screen + final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils); + addPreferencesFromResource(resid); + + mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN); + + removeNonWhitelistedItems(root); + } + + private void removeNonWhitelistedItems(PreferenceGroup prefScreen) { + int numPreferences = prefScreen.getPreferenceCount(); + int i = 0; + while (i < numPreferences) { + final Preference pref = prefScreen.getPreference(i); + // Recursively look into categories and remove them if they are empty. + if (pref instanceof PreferenceCategory) { + PreferenceCategory category = (PreferenceCategory) pref; + removeNonWhitelistedItems(category); + if (category.getPreferenceCount() == 0) { + prefScreen.removePreference(category); + --i; + --numPreferences; + } + } else if (ALLOWED_PREFERENCE_KEYS.contains(pref.getKey())) { + if (SWITCH_PREFERENCE_KEYS.contains(pref.getKey())) { + pref.setOnPreferenceChangeListener(this); + } + } else { + prefScreen.removePreference(pref); + --i; + --numPreferences; + } + ++i; + } + } + + private int getResIdForLockUnlockScreen(Context context, + LockPatternUtils lockPatternUtils) { + int resid = 0; + if (!lockPatternUtils.isSecure(mProfileUserId)) { + resid = R.xml.security_settings_lockscreen; + } else { + switch (lockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId)) { + case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: + resid = R.xml.security_settings_pattern; + break; + case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: + resid = R.xml.security_settings_pin; + break; + case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: + case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: + resid = R.xml.security_settings_password; + break; + } + } + return resid; + } +} diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index 4ce76ce4951..4e9447eecbc 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -26,6 +26,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.pm.UserInfo; import android.content.res.Resources; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; @@ -79,6 +80,7 @@ public class SecuritySettings extends SettingsPreferenceFragment // Lock Settings private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; + private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "profile_challenge"; private static final String KEY_VISIBLE_PATTERN = "visiblepattern"; private static final String KEY_SECURITY_CATEGORY = "security_category"; private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category"; @@ -138,6 +140,8 @@ public class SecuritySettings extends SettingsPreferenceFragment private Intent mTrustAgentClickIntent; private Preference mOwnerInfoPref; + private int mProfileChallengeUserId; + @Override protected int getMetricsCategory() { return MetricsLogger.SECURITY; @@ -209,6 +213,20 @@ public class SecuritySettings extends SettingsPreferenceFragment final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils); addPreferencesFromResource(resid); + List profiles = mUm.getProfiles(UserHandle.myUserId()); + int numProfiles = profiles.size(); + if (numProfiles > 1) { + for (int i = 0; i < numProfiles; ++i) { + UserInfo profile = profiles.get(i); + if (profile.id != UserHandle.myUserId()) { + mProfileChallengeUserId = profile.id; + } + } + if (LockPatternUtils.isSeparateWorkChallengeEnabled()) { + addPreferencesFromResource(R.xml.security_settings_profile); + } + } + // Add options for device encryption mIsAdmin = mUm.isAdminUser(); @@ -655,6 +673,11 @@ public class SecuritySettings extends SettingsPreferenceFragment if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) { startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment", R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null); + } else if (KEY_UNLOCK_SET_OR_CHANGE_PROFILE.equals(key)) { + Bundle extras = new Bundle(); + extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId); + startFragment(this, "com.android.settings.ProfileChallengePreferenceFragment", + R.string.lock_settings_profile_label, SET_OR_CHANGE_LOCK_METHOD_REQUEST, extras); } else if (KEY_TRUST_AGENT.equals(key)) { ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this.getActivity(), this); @@ -752,6 +775,13 @@ public class SecuritySettings extends SettingsPreferenceFragment result.add(sir); final UserManager um = UserManager.get(context); + boolean hasChildProfile = um.getProfiles(UserHandle.myUserId()).size() > 1; + if (hasChildProfile && LockPatternUtils.isSeparateWorkChallengeEnabled()) { + sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.security_settings_profile; + result.add(sir); + } + if (um.isAdminUser()) { DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index ba975a2c2e7..3014225c841 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -335,6 +335,17 @@ public class SettingsActivity extends SettingsDrawerActivity } }; + private final BroadcastReceiver mUserAddRemoveReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(Intent.ACTION_USER_ADDED) + || action.equals(Intent.ACTION_USER_REMOVED)) { + Index.getInstance(getApplicationContext()).update(); + } + } + }; + private final DynamicIndexableContentMonitor mDynamicIndexableContentMonitor = new DynamicIndexableContentMonitor(); @@ -752,6 +763,8 @@ public class SettingsActivity extends SettingsDrawerActivity mDevelopmentPreferencesListener); registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + registerReceiver(mUserAddRemoveReceiver, new IntentFilter(Intent.ACTION_USER_ADDED)); + registerReceiver(mUserAddRemoveReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED)); mDynamicIndexableContentMonitor.register(this); diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index ddea92b24be..9aa040388cf 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -1026,7 +1026,7 @@ public final class Utils { if (bundle == null) { return getEffectiveUserId(context); } - int userId = bundle.getInt(ChooseLockGeneric.KEY_USER_ID, UserHandle.myUserId()); + int userId = bundle.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId()); return getSameOwnerUserId(context, userId); }