Convert some security setting logic to PreferenceController

- Manage trust agent
- Show password
- Sim lock
- Screen pinning

Bug: 32953042
Test: robotests
Change-Id: I0c781a505238cae7a6643b701b750ca63a87a8a5
diff --git a/res/xml/security_settings_v2.xml b/res/xml/security_settings_v2.xml
index 334333a..155ee70 100644
--- a/res/xml/security_settings_v2.xml
+++ b/res/xml/security_settings_v2.xml
@@ -63,8 +63,7 @@
     </PreferenceCategory>
 
     <Preference android:key="sim_lock_settings"
-                android:title="@string/sim_lock_settings_category"
-                android:persistent="false">
+                android:title="@string/sim_lock_settings_category">
 
         <intent android:action="android.intent.action.MAIN"
                 android:targetPackage="com.android.settings"
@@ -86,7 +85,7 @@
     <Preference
         android:key="screen_pinning_settings"
         android:title="@string/screen_pinning_title"
-        android:summary="@string/switch_off_text"
+        android:summary="@string/summary_placeholder"
         android:fragment="com.android.settings.security.ScreenPinningSettings"/>
 
     <Preference android:key="security_misc_usage_access"
diff --git a/src/com/android/settings/core/TogglePreferenceController.java b/src/com/android/settings/core/TogglePreferenceController.java
index 99d2ecc..febd7ad 100644
--- a/src/com/android/settings/core/TogglePreferenceController.java
+++ b/src/com/android/settings/core/TogglePreferenceController.java
@@ -14,8 +14,8 @@
 package com.android.settings.core;
 
 import android.content.Context;
-import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
+import android.support.v7.preference.TwoStatePreference;
 
 /**
  * Abstract class that consolidates logic for updating toggle controllers.
@@ -45,7 +45,7 @@
 
     @Override
     public final void updateState(Preference preference) {
-        ((SwitchPreference) preference).setChecked(isChecked());
+        ((TwoStatePreference) preference).setChecked(isChecked());
     }
 
     @Override
diff --git a/src/com/android/settings/security/ScreenPinningPreferenceController.java b/src/com/android/settings/security/ScreenPinningPreferenceController.java
new file mode 100644
index 0000000..60279c7
--- /dev/null
+++ b/src/com/android/settings/security/ScreenPinningPreferenceController.java
@@ -0,0 +1,56 @@
+/*
+ * 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.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+public class ScreenPinningPreferenceController extends BasePreferenceController {
+
+    private static final String KEY_SCREEN_PINNING = "screen_pinning_settings";
+
+    public ScreenPinningPreferenceController(Context context) {
+        super(context, KEY_SCREEN_PINNING);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        final Preference preference = screen.findPreference(getPreferenceKey());
+        if (preference == null) {
+            return;
+        }
+        if (Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.LOCK_TO_APP_ENABLED, 0) != 0) {
+            preference.setSummary(
+                    mContext.getString(R.string.switch_on_text));
+        } else {
+            preference.setSummary(
+                    mContext.getString(R.string.switch_off_text));
+        }
+    }
+}
diff --git a/src/com/android/settings/security/SecurityFeatureProvider.java b/src/com/android/settings/security/SecurityFeatureProvider.java
index b4f4635..35ff586 100644
--- a/src/com/android/settings/security/SecurityFeatureProvider.java
+++ b/src/com/android/settings/security/SecurityFeatureProvider.java
@@ -20,6 +20,7 @@
 import android.support.v7.preference.PreferenceScreen;
 import android.util.FeatureFlagUtils;
 
+import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.security.trustagent.TrustAgentManager;
 import com.android.settingslib.drawer.DashboardCategory;
@@ -38,4 +39,9 @@
 
     /** Returns the {@link TrustAgentManager} bound to this {@link SecurityFeatureProvider}. */
     TrustAgentManager getTrustAgentManager();
+
+    /**
+     * Returns a {@link LockPatternUtils} instance bound to application context.
+     */
+    LockPatternUtils getLockPatternUtils(Context context);
 }
diff --git a/src/com/android/settings/security/SecurityFeatureProviderImpl.java b/src/com/android/settings/security/SecurityFeatureProviderImpl.java
index 29aaefe..70b1ec1 100644
--- a/src/com/android/settings/security/SecurityFeatureProviderImpl.java
+++ b/src/com/android/settings/security/SecurityFeatureProviderImpl.java
@@ -29,6 +29,7 @@
 import android.util.ArrayMap;
 import android.util.Pair;
 
+import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.security.trustagent.TrustAgentManager;
 import com.android.settingslib.drawer.DashboardCategory;
@@ -43,6 +44,7 @@
 public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
 
     private TrustAgentManager mTrustAgentManager;
+    private LockPatternUtils mLockPatternUtils;
 
     @VisibleForTesting
     static final Drawable DEFAULT_ICON = null;
@@ -195,4 +197,12 @@
         }
         return mTrustAgentManager;
     }
+
+    @Override
+    public LockPatternUtils getLockPatternUtils(Context context) {
+        if (mLockPatternUtils == null) {
+            mLockPatternUtils = new LockPatternUtils(context.getApplicationContext());
+        }
+        return mLockPatternUtils;
+    }
 }
diff --git a/src/com/android/settings/security/SecuritySettingsV2.java b/src/com/android/settings/security/SecuritySettingsV2.java
index 4d9f78b..a957c8c 100644
--- a/src/com/android/settings/security/SecuritySettingsV2.java
+++ b/src/com/android/settings/security/SecuritySettingsV2.java
@@ -7,21 +7,15 @@
 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;
@@ -43,6 +37,7 @@
 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.TrustAgentManager;
 import com.android.settings.widget.GearPreference;
 import com.android.settingslib.RestrictedLockUtils;
@@ -67,13 +62,11 @@
     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_SCANNING = "location_scanning";
     private static final String KEY_LOCATION = "location";
 
     private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
@@ -85,10 +78,7 @@
     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";
@@ -100,7 +90,7 @@
 
     // 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
+            KEY_UNIFICATION, KEY_VISIBLE_PATTERN_PROFILE
     };
 
     private static final int MY_USER_ID = UserHandle.myUserId();
@@ -109,7 +99,6 @@
     private DevicePolicyManager mDPM;
     private SecurityFeatureProvider mSecurityFeatureProvider;
     private TrustAgentManager mTrustAgentManager;
-    private SubscriptionManager mSubscriptionManager;
     private UserManager mUm;
 
     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
@@ -119,10 +108,6 @@
     private SwitchPreference mVisiblePatternProfile;
     private RestrictedSwitchPreference mUnifyProfile;
 
-    private SwitchPreference mShowPassword;
-
-    private boolean mIsAdmin;
-
     private Intent mTrustAgentClickIntent;
 
     private int mProfileChallengeUserId;
@@ -134,6 +119,10 @@
     private ManageDeviceAdminPreferenceController mManageDeviceAdminPreferenceController;
     private EnterprisePrivacyPreferenceController mEnterprisePrivacyPreferenceController;
     private LockScreenNotificationPreferenceController mLockScreenNotificationPreferenceController;
+    private ManageTrustAgentsPreferenceController mManageTrustAgentsPreferenceController;
+    private ScreenPinningPreferenceController mScreenPinningPreferenceController;
+    private SimLockPreferenceController mSimLockPreferenceController;
+    private ShowPasswordPreferenceController mShowPasswordPreferenceController;
 
     @Override
     public int getMetricsCategory() {
@@ -143,15 +132,15 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
+        mSecurityFeatureProvider = FeatureFactory.getFactory(context).getSecurityFeatureProvider();
         mLocationController = new LocationPreferenceController(context, getLifecycle());
-        mSubscriptionManager = SubscriptionManager.from(context);
-        mLockPatternUtils = new LockPatternUtils(context);
+        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);
-        mSecurityFeatureProvider = FeatureFactory.getFactory(context).getSecurityFeatureProvider();
+
         mTrustAgentManager = mSecurityFeatureProvider.getTrustAgentManager();
     }
 
@@ -173,6 +162,10 @@
                 = new EnterprisePrivacyPreferenceController(context);
         mLockScreenNotificationPreferenceController
                 = new LockScreenNotificationPreferenceController(context);
+        mManageTrustAgentsPreferenceController = new ManageTrustAgentsPreferenceController(context);
+        mScreenPinningPreferenceController = new ScreenPinningPreferenceController(context);
+        mSimLockPreferenceController = new SimLockPreferenceController(context);
+        mShowPasswordPreferenceController = new ShowPasswordPreferenceController(context);
         return null;
     }
 
@@ -182,7 +175,6 @@
 
         mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
 
-
         if (savedInstanceState != null
                 && savedInstanceState.containsKey(TRUST_AGENT_CLICK_INTENT)) {
             mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT);
@@ -280,15 +272,13 @@
             ((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);
+            addTrustAgentSettings(securityCategory);
             setLockscreenPreferencesSummary(securityCategory);
         }
 
@@ -296,24 +286,8 @@
                 (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));
-        }
+        mSimLockPreferenceController.displayPreference(root);
+        mScreenPinningPreferenceController.displayPreference(root);
 
         // Encryption status of device
         if (LockPatternUtils.isDeviceEncryptionEnabled()) {
@@ -324,14 +298,8 @@
                     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);
+        mManageTrustAgentsPreferenceController.displayPreference(root);
 
         PreferenceGroup securityStatusPreferenceGroup =
                 (PreferenceGroup) root.findPreference(KEY_SECURITY_STATUS);
@@ -381,23 +349,6 @@
     }
 
     @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) {
@@ -411,8 +362,9 @@
      * The preference must be a RestrictedPreference.
      */
     private void disableIfPasswordQualityManaged(String preferenceKey, int userId) {
-        final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
-                getActivity(), userId);
+        final RestrictedLockUtils.EnforcedAdmin admin =
+                RestrictedLockUtils.checkIfPasswordQualityIsSet(
+                        getActivity(), userId);
         if (admin != null && mDPM.getPasswordQuality(admin.component, userId) ==
                 DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
             final RestrictedPreference pref =
@@ -433,8 +385,8 @@
     // 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);
+        final List<TrustAgentManager.TrustAgentComponentInfo> agents =
+                mTrustAgentManager.getActiveTrustAgents(getActivity(), mLockPatternUtils);
         for (TrustAgentManager.TrustAgentComponentInfo agent : agents) {
             final RestrictedPreference trustAgentPreference =
                     new RestrictedPreference(securityCategory.getContext());
@@ -458,43 +410,6 @@
         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())) {
@@ -524,12 +439,10 @@
         }
 
         updateUnificationPreference();
-
-        if (mShowPassword != null) {
-            mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
-                    Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
-        }
-
+        final Preference showPasswordPref = getPreferenceScreen().findPreference(
+                mShowPasswordPreferenceController.getPreferenceKey());
+        showPasswordPref.setOnPreferenceChangeListener(mShowPasswordPreferenceController);
+        mShowPasswordPreferenceController.updateState(showPasswordPref);
         mLocationController.updateSummary();
     }
 
@@ -581,7 +494,7 @@
             mTrustAgentClickIntent = preference.getIntent();
             boolean confirmationLaunched = helper.launchConfirmationActivity(
                     CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());
-            if (!confirmationLaunched&&  mTrustAgentClickIntent != null) {
+            if (!confirmationLaunched && mTrustAgentClickIntent != null) {
                 // If this returns false, it means no password confirmation is required.
                 startActivity(mTrustAgentClickIntent);
                 mTrustAgentClickIntent = null;
@@ -715,15 +628,11 @@
                         R.string.unlock_set_unlock_launch_picker_title);
                 final ChooseLockSettingsHelper helper =
                         new ChooseLockSettingsHelper(getActivity(), this);
-                if(!helper.launchConfirmationActivity(
+                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;
     }
@@ -788,8 +697,9 @@
         }
 
         private boolean isPasswordManaged(int userId, Context context, DevicePolicyManager dpm) {
-            final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
-                    context, userId);
+            final RestrictedLockUtils.EnforcedAdmin admin =
+                    RestrictedLockUtils.checkIfPasswordQualityIsSet(
+                            context, userId);
             return admin != null && dpm.getPasswordQuality(admin.component, userId) ==
                     DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
         }
@@ -847,20 +757,13 @@
         @Override
         public List<String> getNonIndexableKeys(Context context) {
             final List<String> keys = super.getNonIndexableKeys(context);
+            final LockPatternUtils lockPatternUtils = new LockPatternUtils(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);
-            }
+            new SimLockPreferenceController(context).updateNonIndexableKeys(keys);
 
             // 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))
@@ -873,7 +776,6 @@
             // 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;
diff --git a/src/com/android/settings/security/ShowPasswordPreferenceController.java b/src/com/android/settings/security/ShowPasswordPreferenceController.java
new file mode 100644
index 0000000..9f9b52d
--- /dev/null
+++ b/src/com/android/settings/security/ShowPasswordPreferenceController.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+import android.provider.Settings;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+
+public class ShowPasswordPreferenceController extends TogglePreferenceController {
+
+    private static final String KEY_SHOW_PASSWORD = "show_password";
+    private static final int MY_USER_ID = UserHandle.myUserId();
+    private final LockPatternUtils mLockPatternUtils;
+
+    public ShowPasswordPreferenceController(Context context) {
+        super(context, KEY_SHOW_PASSWORD);
+        mLockPatternUtils = FeatureFactory.getFactory(context)
+                .getSecurityFeatureProvider()
+                .getLockPatternUtils(context);
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.TEXT_SHOW_PASSWORD, 1) != 0;
+    }
+
+    @Override
+    public void setChecked(boolean isChecked) {
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
+                isChecked ? 1 : 0);
+        mLockPatternUtils.setVisiblePasswordEnabled(isChecked, MY_USER_ID);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
+
diff --git a/src/com/android/settings/security/SimLockPreferenceController.java b/src/com/android/settings/security/SimLockPreferenceController.java
new file mode 100644
index 0000000..797f098
--- /dev/null
+++ b/src/com/android/settings/security/SimLockPreferenceController.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 android.content.Context;
+import android.os.PersistableBundle;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.core.BasePreferenceController;
+
+import java.util.List;
+
+public class SimLockPreferenceController extends BasePreferenceController {
+
+    private static final String KEY_SIM_LOCK = "sim_lock_settings";
+
+    private final CarrierConfigManager mCarrierConfigManager;
+    private final UserManager mUserManager;
+    private final SubscriptionManager mSubscriptionManager;
+    private final TelephonyManager mTelephonyManager;
+
+    public SimLockPreferenceController(Context context) {
+        super(context, KEY_SIM_LOCK);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mCarrierConfigManager = (CarrierConfigManager)
+                mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        mSubscriptionManager = (SubscriptionManager) context
+                .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        final PersistableBundle b = mCarrierConfigManager.getConfig();
+        final boolean IsAdmin = mUserManager.isAdminUser();
+        if (!IsAdmin || !isSimIccReady() ||
+                b.getBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL)) {
+            return DISABLED_FOR_USER;
+        }
+        return AVAILABLE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        final Preference preference = screen.findPreference(getPreferenceKey());
+        if (preference == null) {
+            return;
+        }
+        // Disable SIM lock if there is no ready SIM card.
+        preference.setEnabled(isSimReady());
+    }
+
+    /* 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 = mTelephonyManager.getSimState(subInfo.getSimSlotIndex());
+                if ((simState != TelephonyManager.SIM_STATE_ABSENT) &&
+                        (simState != TelephonyManager.SIM_STATE_UNKNOWN)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return true if a there is a Slot that has Icc
+     */
+    private boolean isSimIccReady() {
+        final List<SubscriptionInfo> subInfoList =
+                mSubscriptionManager.getActiveSubscriptionInfoList();
+
+        if (subInfoList != null) {
+            for (SubscriptionInfo subInfo : subInfoList) {
+                if (mTelephonyManager.hasIccCard(subInfo.getSimSlotIndex())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/settings/security/trustagent/ManageTrustAgentsPreferenceController.java b/src/com/android/settings/security/trustagent/ManageTrustAgentsPreferenceController.java
new file mode 100644
index 0000000..c615eff
--- /dev/null
+++ b/src/com/android/settings/security/trustagent/ManageTrustAgentsPreferenceController.java
@@ -0,0 +1,76 @@
+/*
+ * 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.trustagent;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.support.annotation.VisibleForTesting;
+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.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.security.SecurityFeatureProvider;
+
+public class ManageTrustAgentsPreferenceController extends BasePreferenceController {
+
+    @VisibleForTesting
+    static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
+    private static final int MY_USER_ID = UserHandle.myUserId();
+
+    private final LockPatternUtils mLockPatternUtils;
+    private TrustAgentManager mTrustAgentManager;
+
+    public ManageTrustAgentsPreferenceController(Context context) {
+        super(context, KEY_MANAGE_TRUST_AGENTS);
+        final SecurityFeatureProvider securityFeatureProvider = FeatureFactory.getFactory(context)
+                .getSecurityFeatureProvider();
+        mLockPatternUtils = securityFeatureProvider.getLockPatternUtils(context);
+        mTrustAgentManager = securityFeatureProvider.getTrustAgentManager();
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        final Preference preference = screen.findPreference(getPreferenceKey());
+        if (preference == null) {
+            return;
+        }
+        final int numberOfTrustAgent = getTrustAgentCount();
+        if (!mLockPatternUtils.isSecure(MY_USER_ID)) {
+            preference.setEnabled(false);
+            preference.setSummary(R.string.disabled_because_no_backup_security);
+        } else if (numberOfTrustAgent > 0) {
+            preference.setSummary(mContext.getResources().getQuantityString(
+                    R.plurals.manage_trust_agents_summary_on,
+                    numberOfTrustAgent, numberOfTrustAgent));
+        } else {
+            preference.setSummary(R.string.manage_trust_agents_summary);
+        }
+    }
+
+    private int getTrustAgentCount() {
+        return mTrustAgentManager.getActiveTrustAgents(mContext, mLockPatternUtils).size();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/security/ScreenPinningPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/ScreenPinningPreferenceControllerTest.java
new file mode 100644
index 0000000..797e7d0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/ScreenPinningPreferenceControllerTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.core.BasePreferenceController.AVAILABLE;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ScreenPinningPreferenceControllerTest {
+
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private FakeFeatureFactory mFeatureFactory;
+    private Context mContext;
+    private ScreenPinningPreferenceController mController;
+    private Preference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mController = new ScreenPinningPreferenceController(mContext);
+        mPreference = new Preference(mContext);
+        mPreference.setKey(mController.getPreferenceKey());
+        when(mScreen.findPreference(mController.getPreferenceKey()))
+                .thenReturn(mPreference);
+    }
+
+    @After
+    public void tearDown() {
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.LOCK_TO_APP_ENABLED, 0);
+    }
+
+    @Test
+    public void isAlwaysAvailable() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void displayPreference_isOff_shouldDisableOffSummary() {
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.LOCK_TO_APP_ENABLED, 0);
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.switch_off_text));
+    }
+
+    @Test
+    public void displayPreference_isOn_shouldDisableOnSummary() {
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.LOCK_TO_APP_ENABLED, 1);
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.switch_on_text));
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/security/ShowPasswordPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/ShowPasswordPreferenceControllerTest.java
new file mode 100644
index 0000000..63cf00b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/ShowPasswordPreferenceControllerTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.core.BasePreferenceController.AVAILABLE;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ShowPasswordPreferenceControllerTest {
+
+    @Mock
+    private LockPatternUtils mLockPatternUtils;
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private FakeFeatureFactory mFeatureFactory;
+    private Context mContext;
+    private ShowPasswordPreferenceController mController;
+    private Preference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
+                .thenReturn(mLockPatternUtils);
+        mController = new ShowPasswordPreferenceController(mContext);
+        mPreference = new Preference(mContext);
+        mPreference.setKey(mController.getPreferenceKey());
+        when(mScreen.findPreference(mController.getPreferenceKey()))
+                .thenReturn(mPreference);
+    }
+
+    @Test
+    public void isAlwaysAvailable() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void isChecked_settingIsOff_false() {
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
+                0);
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_settingIsOn_true() {
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
+                1);
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void changePref_turnOn_shouldChangeSettingTo1() {
+        mController.onPreferenceChange(mPreference, true);
+
+        assertThat(mController.isChecked()).isTrue();
+        verify(mLockPatternUtils).setVisiblePasswordEnabled(true, UserHandle.myUserId());
+    }
+
+    @Test
+    public void changePref_turnOff_shouldChangeSettingTo0() {
+        mController.onPreferenceChange(mPreference, false);
+
+        assertThat(mController.isChecked()).isFalse();
+        verify(mLockPatternUtils).setVisiblePasswordEnabled(false, UserHandle.myUserId());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/security/SimLockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/SimLockPreferenceControllerTest.java
new file mode 100644
index 0000000..a3a4fe3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/SimLockPreferenceControllerTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.telephony.TelephonyManager.SIM_STATE_READY;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SimLockPreferenceControllerTest {
+
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
+    private CarrierConfigManager mCarrierManager;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private Context mContext;
+    private SimLockPreferenceController mController;
+    private Preference mPreference;
+
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        ShadowApplication shadowApplication = ShadowApplication.getInstance();
+        shadowApplication.setSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE,
+                mSubscriptionManager);
+        shadowApplication.setSystemService(Context.CARRIER_CONFIG_SERVICE, mCarrierManager);
+        shadowApplication.setSystemService(Context.USER_SERVICE, mUserManager);
+        shadowApplication.setSystemService(Context.TELEPHONY_SERVICE, mTelephonyManager);
+        mController = new SimLockPreferenceController(mContext);
+        mPreference = new Preference(mContext);
+        mPreference.setKey(mController.getPreferenceKey());
+        when(mScreen.findPreference(mController.getPreferenceKey()))
+                .thenReturn(mPreference);
+    }
+
+    @Test
+    public void isAvailable_notAdmin_false() {
+        when(mUserManager.isAdminUser()).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
+    }
+
+    @Test
+    public void isAvailable_simIccNotReady_false() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
+    }
+
+    @Test
+    public void isAvailable_carrierConfigDisabled_false() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        setupMockIcc();
+        final PersistableBundle pb = new PersistableBundle();
+        pb.putBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, true);
+        when(mCarrierManager.getConfig()).thenReturn(pb);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
+    }
+
+    @Test
+    public void isAvailable_true() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        setupMockIcc();
+        final PersistableBundle pb = new PersistableBundle();
+        when(mCarrierManager.getConfig()).thenReturn(pb);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void displayPreference_simReady_enablePreference() {
+        mController.displayPreference(mScreen);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void displayPreference_simNotReady_disablePreference() {
+        setupMockSimReady();
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+    }
+
+    private void setupMockIcc() {
+        final List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+        SubscriptionInfo info = mock(SubscriptionInfo.class);
+        subscriptionInfoList.add(info);
+        when(mTelephonyManager.hasIccCard(anyInt()))
+                .thenReturn(true);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList())
+                .thenReturn(subscriptionInfoList);
+    }
+
+    private void setupMockSimReady() {
+        final List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+        SubscriptionInfo info = mock(SubscriptionInfo.class);
+        subscriptionInfoList.add(info);
+        when(mTelephonyManager.getSimState(anyInt()))
+                .thenReturn(SIM_STATE_READY);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList())
+                .thenReturn(subscriptionInfoList);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/security/trustagent/ManageTrustAgentsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/trustagent/ManageTrustAgentsPreferenceControllerTest.java
new file mode 100644
index 0000000..8818602
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/trustagent/ManageTrustAgentsPreferenceControllerTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.trustagent;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+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.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ManageTrustAgentsPreferenceControllerTest {
+
+    @Mock
+    private TrustAgentManager mTrustAgentManager;
+    @Mock
+    private LockPatternUtils mLockPatternUtils;
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private FakeFeatureFactory mFeatureFactory;
+    private Context mContext;
+    private ManageTrustAgentsPreferenceController mController;
+    private Preference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
+                .thenReturn(mLockPatternUtils);
+        when(mFeatureFactory.securityFeatureProvider.getTrustAgentManager())
+                .thenReturn(mTrustAgentManager);
+        mController = new ManageTrustAgentsPreferenceController(mContext);
+        mPreference = new Preference(mContext);
+        mPreference.setKey(mController.getPreferenceKey());
+        when(mScreen.findPreference(mController.getPreferenceKey()))
+                .thenReturn(mPreference);
+    }
+
+    @Test
+    public void isAlwaysAvailable() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void displayPreference_isNotSecure_shouldDisablePreference() {
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.disabled_because_no_backup_security));
+    }
+
+    @Test
+    public void displayPreference_isSecure_noTrustAgent_shouldShowGenericSummary() {
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+        when(mTrustAgentManager.getActiveTrustAgents(mContext, mLockPatternUtils))
+                .thenReturn(new ArrayList<>());
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.manage_trust_agents_summary));
+    }
+
+    @Test
+    public void displayPreference_isSecure_hasTrustAgent_shouldShowDetailedSummary() {
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+        when(mTrustAgentManager.getActiveTrustAgents(mContext, mLockPatternUtils))
+                .thenReturn(Arrays.asList(new TrustAgentManager.TrustAgentComponentInfo()));
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getResources().getQuantityString(
+                        R.plurals.manage_trust_agents_summary_on, 1, 1));
+    }
+}