diff --git a/res/xml/security_settings_v2.xml b/res/xml/security_settings_v2.xml
index 155ee70d717..30e829d4e17 100644
--- a/res/xml/security_settings_v2.xml
+++ b/res/xml/security_settings_v2.xml
@@ -28,6 +28,22 @@
android:title="@string/security_status_title" />
+
+
+
+
+
+
+
+
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();
- }
-
@Override
public void onGearClick(GearPreference p) {
if (KEY_UNLOCK_SET_OR_CHANGE.equals(p.getKey())) {
@@ -414,14 +368,6 @@ public class SecuritySettingsV2 extends DashboardFragment
}
}
- @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();
@@ -445,7 +391,7 @@ public class SecuritySettingsV2 extends DashboardFragment
final Preference encryptionStatusPref = getPreferenceScreen().findPreference(
mEncryptionStatusPreferenceController.getPreferenceKey());
mEncryptionStatusPreferenceController.updateState(encryptionStatusPref);
-
+ mTrustAgentListPreferenceController.onResume();
mLocationController.updateSummary();
}
@@ -465,6 +411,9 @@ public class SecuritySettingsV2 extends DashboardFragment
@Override
public boolean onPreferenceTreeClick(Preference preference) {
+ if (mTrustAgentListPreferenceController.handlePreferenceTreeClick(preference)) {
+ return true;
+ }
final String key = preference.getKey();
if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
// TODO(b/35930129): Remove once existing password can be passed into vold directly.
@@ -491,17 +440,6 @@ public class SecuritySettingsV2 extends DashboardFragment
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);
@@ -516,10 +454,7 @@ public class SecuritySettingsV2 extends DashboardFragment
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;
- }
+ mTrustAgentListPreferenceController.handleActivityResult(resultCode);
return;
} else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST
&& resultCode == Activity.RESULT_OK) {
@@ -760,15 +695,9 @@ public class SecuritySettingsV2 extends DashboardFragment
@Override
public List getNonIndexableKeys(Context context) {
final List keys = super.getNonIndexableKeys(context);
- final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
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);
- }
-
if (!(new EnterprisePrivacyPreferenceController(context))
.isAvailable()) {
keys.add(KEY_ENTERPRISE_PRIVACY);
diff --git a/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java b/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java
new file mode 100644
index 00000000000..d99757be256
--- /dev/null
+++ b/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java
@@ -0,0 +1,172 @@
+/*
+ * 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.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.security.SecurityFeatureProvider;
+import com.android.settings.security.SecuritySettingsV2;
+import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnCreate;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
+
+import java.util.List;
+
+public class TrustAgentListPreferenceController extends AbstractPreferenceController
+ implements LifecycleObserver, OnSaveInstanceState, OnCreate, OnResume {
+
+ private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";
+ @VisibleForTesting
+ static final String PREF_KEY_TRUST_AGENT = "trust_agent";
+ @VisibleForTesting
+ static final String PREF_KEY_SECURITY_CATEGORY = "security_category";
+ private static final int MY_USER_ID = UserHandle.myUserId();
+
+ private final LockPatternUtils mLockPatternUtils;
+ private final TrustAgentManager mTrustAgentManager;
+ private final Activity mActivity;
+ private final SecuritySettingsV2 mHost;
+
+ private Intent mTrustAgentClickIntent;
+ private PreferenceCategory mSecurityCategory;
+
+ public TrustAgentListPreferenceController(Activity activity, SecuritySettingsV2 host,
+ Lifecycle lifecycle) {
+ super(activity);
+ final SecurityFeatureProvider provider = FeatureFactory.getFactory(activity)
+ .getSecurityFeatureProvider();
+ mActivity = activity;
+ mHost = host;
+ mLockPatternUtils = provider.getLockPatternUtils(activity);
+ mTrustAgentManager = provider.getTrustAgentManager();
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return PREF_KEY_TRUST_AGENT;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mSecurityCategory = (PreferenceCategory) screen.findPreference(PREF_KEY_SECURITY_CATEGORY);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ if (savedInstanceState != null
+ && savedInstanceState.containsKey(TRUST_AGENT_CLICK_INTENT)) {
+ mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT);
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ if (mTrustAgentClickIntent != null) {
+ outState.putParcelable(TRUST_AGENT_CLICK_INTENT, mTrustAgentClickIntent);
+ }
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ return super.handlePreferenceTreeClick(preference);
+ }
+ final ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(mActivity, mHost);
+ mTrustAgentClickIntent = preference.getIntent();
+ boolean confirmationLaunched = helper.launchConfirmationActivity(
+ SecuritySettingsV2.CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());
+
+ if (!confirmationLaunched && mTrustAgentClickIntent != null) {
+ // If this returns false, it means no password confirmation is required.
+ mHost.startActivity(mTrustAgentClickIntent);
+ mTrustAgentClickIntent = null;
+ }
+ return true;
+ }
+
+ @Override
+ public void onResume() {
+ if (mSecurityCategory == null) {
+ return;
+ }
+ // First remove all old trust agents.
+ while (true) {
+ final Preference oldAgent = mSecurityCategory.findPreference(PREF_KEY_TRUST_AGENT);
+ if (oldAgent == null) {
+ break;
+ } else {
+ mSecurityCategory.removePreference(oldAgent);
+ }
+ }
+ // Then add new ones.
+ final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID);
+ final List agents =
+ mTrustAgentManager.getActiveTrustAgents(mContext, mLockPatternUtils);
+ if (agents == null) {
+ return;
+ }
+ for (TrustAgentManager.TrustAgentComponentInfo agent : agents) {
+ final RestrictedPreference trustAgentPreference =
+ new RestrictedPreference(mSecurityCategory.getContext());
+ trustAgentPreference.setKey(PREF_KEY_TRUST_AGENT);
+ trustAgentPreference.setTitle(agent.title);
+ trustAgentPreference.setSummary(agent.summary);
+ // Create intent for this preference.
+ trustAgentPreference.setIntent(new Intent(Intent.ACTION_MAIN)
+ .setComponent(agent.componentName));
+ trustAgentPreference.setDisabledByAdmin(agent.admin);
+ if (!trustAgentPreference.isDisabledByAdmin() && !hasSecurity) {
+ trustAgentPreference.setEnabled(false);
+ trustAgentPreference.setSummary(R.string.disabled_because_no_backup_security);
+ }
+ // Add preference to the settings menu.
+ mSecurityCategory.addPreference(trustAgentPreference);
+ }
+ }
+
+ public void handleActivityResult(int resultCode) {
+ if (resultCode == Activity.RESULT_OK && mTrustAgentClickIntent != null) {
+ mHost.startActivity(mTrustAgentClickIntent);
+ mTrustAgentClickIntent = null;
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentListPreferenceControllerTest.java
new file mode 100644
index 00000000000..a97780b48e8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentListPreferenceControllerTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.security.trustagent.TrustAgentListPreferenceController
+ .PREF_KEY_SECURITY_CATEGORY;
+import static com.android.settings.security.trustagent.TrustAgentListPreferenceController
+ .PREF_KEY_TRUST_AGENT;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.TestConfig;
+import com.android.settings.security.SecuritySettingsV2;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class TrustAgentListPreferenceControllerTest {
+
+ @Mock
+ private TrustAgentManager mTrustAgentManager;
+ @Mock
+ private LockPatternUtils mLockPatternUtils;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private PreferenceCategory mCategory;
+ @Mock
+ private SecuritySettingsV2 mFragment;
+
+ private Lifecycle mLifecycle;
+ private FakeFeatureFactory mFeatureFactory;
+ private Activity mActivity;
+
+ private TrustAgentListPreferenceController mController;
+
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mActivity = Robolectric.buildActivity(Activity.class).get();
+ mLifecycle = new Lifecycle(() -> mLifecycle);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(any(Context.class)))
+ .thenReturn(mLockPatternUtils);
+ when(mFeatureFactory.securityFeatureProvider.getTrustAgentManager())
+ .thenReturn(mTrustAgentManager);
+ when(mCategory.getKey()).thenReturn(PREF_KEY_SECURITY_CATEGORY);
+ when(mCategory.getContext()).thenReturn(mActivity);
+ when(mScreen.findPreference(PREF_KEY_SECURITY_CATEGORY))
+ .thenReturn(mCategory);
+ mController = new TrustAgentListPreferenceController(mActivity, mFragment, mLifecycle);
+ }
+
+ @Test
+ public void testConstants() {
+ assertThat(mController.isAvailable()).isTrue();
+ assertThat(mController.getPreferenceKey()).isEqualTo(PREF_KEY_TRUST_AGENT);
+ }
+
+ @Test
+ public void onResume_shouldClearOldAgents() {
+ final Preference oldAgent = new Preference(mActivity);
+ oldAgent.setKey(PREF_KEY_TRUST_AGENT);
+ when(mCategory.findPreference(PREF_KEY_TRUST_AGENT))
+ .thenReturn(oldAgent)
+ .thenReturn(null);
+
+ mController.displayPreference(mScreen);
+ mController.onResume();
+
+ verify(mCategory).removePreference(oldAgent);
+ }
+
+ @Test
+ public void onResume_shouldAddNewAgents() {
+ final List agents = new ArrayList<>();
+ final TrustAgentManager.TrustAgentComponentInfo agent = mock(
+ TrustAgentManager.TrustAgentComponentInfo.class);
+ agent.title = "Test_title";
+ agent.summary = "test summary";
+ agent.componentName = new ComponentName("pkg", "agent");
+ agent.admin = null;
+ agents.add(agent);
+ when(mTrustAgentManager.getActiveTrustAgents(mActivity, mLockPatternUtils))
+ .thenReturn(agents);
+
+ mController.displayPreference(mScreen);
+ mController.onResume();
+
+ verify(mCategory).addPreference(any(Preference.class));
+ }
+}