diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 23dc206298c..2229d0174c2 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1506,7 +1506,7 @@ diff --git a/res/values/strings.xml b/res/values/strings.xml index 3dbc79e41f1..f7b171fc038 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1304,10 +1304,13 @@ Device administration - Device administrators + Device admin apps - - View or deactivate device administrators + + + %d active app + %d active apps + Trust agents @@ -8135,13 +8138,13 @@ - Device management + Managed device details - View all settings applied by your admin - - Device management - - To provide access to your work data, your organization may change settings and install software on your device. \n\nFor more details, contact your organization\'s admin. + Changes & settings managed by your organization + + Changes & settings managed by %s + + To provide access to your work data, your organization may change settings and install software on your device.\n\nFor more details, contact your organization\'s admin. Types of information your organization can see @@ -8201,8 +8204,8 @@ - Trusted CA Certificate installed in the personal profile - Trusted CA Certificates installed in the personal profile + Trusted CA Certificate installed in your personal profile + Trusted CA Certificates installed in your personal profile @@ -8216,8 +8219,8 @@ - Trusted CA Certificate installed in the work profile - Trusted CA Certificates installed in the work profile + Trusted CA Certificate installed in your work profile + Trusted CA Certificates installed in your work profile Admin can lock the device and reset password diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml index f08b9f21ed8..68403c5e40e 100644 --- a/res/xml/enterprise_privacy_settings.xml +++ b/res/xml/enterprise_privacy_settings.xml @@ -17,7 +17,13 @@ + android:title="@string/enterprise_privacy_settings"> + + + - - diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml index 155f21a91a8..e058b3ea8fe 100644 --- a/res/xml/security_settings_misc.xml +++ b/res/xml/security_settings_misc.xml @@ -39,13 +39,11 @@ diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index fb590cc0f97..53fab730e40 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -58,6 +58,8 @@ import com.android.settings.TrustAgentUtils.TrustAgentComponentInfo; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.dashboard.DashboardFeatureProvider; 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.overlay.FeatureFactory; @@ -128,6 +130,10 @@ public class SecuritySettings extends SettingsPreferenceFragment static final String KEY_PACKAGE_VERIFIER_STATUS = "security_status_package_verifier"; private static final int PACKAGE_VERIFIER_STATE_ENABLED = 1; + // 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 @@ -164,6 +170,8 @@ public class SecuritySettings extends SettingsPreferenceFragment private String mCurrentProfilePassword; private LocationPreferenceController mLocationcontroller; + private ManageDeviceAdminPreferenceController mManageDeviceAdminPreferenceController; + private EnterprisePrivacyPreferenceController mEnterprisePrivacyPreferenceController; @Override public int getMetricsCategory() { @@ -201,6 +209,10 @@ public class SecuritySettings extends SettingsPreferenceFragment } mLocationcontroller = new LocationPreferenceController(activity); + mManageDeviceAdminPreferenceController + = new ManageDeviceAdminPreferenceController(activity); + mEnterprisePrivacyPreferenceController + = new EnterprisePrivacyPreferenceController(activity, null /* lifecycle */); } private static int getResIdForLockUnlockScreen(Context context, @@ -394,6 +406,11 @@ public class SecuritySettings extends SettingsPreferenceFragment } mLocationcontroller.displayPreference(root); + mManageDeviceAdminPreferenceController.updateState( + root.findPreference(KEY_MANAGE_DEVICE_ADMIN)); + mEnterprisePrivacyPreferenceController.displayPreference(root); + mEnterprisePrivacyPreferenceController.onResume(); + return root; } @@ -895,6 +912,11 @@ public class SecuritySettings extends SettingsPreferenceFragment keys.add(KEY_MANAGE_TRUST_AGENTS); } + if (!(new EnterprisePrivacyPreferenceController(context, null /* lifecycle */)) + .isAvailable()) { + keys.add(KEY_ENTERPRISE_PRIVACY); + } + return keys; } } diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java index 7fae8bb7e95..ed9dd947079 100644 --- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java +++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java @@ -30,6 +30,13 @@ import java.util.List; * newer than the API version supported by Robolectric. */ public interface DevicePolicyManagerWrapper { + /** + * Calls {@code DevicePolicyManager.getActiveAdminsAsUser()}. + * + * @see android.app.admin.DevicePolicyManager#getActiveAdminsAsUser + */ + public @Nullable List getActiveAdminsAsUser(int userId); + /** * Calls {@code DevicePolicyManager.getMaximumFailedPasswordsForWipe()}. * diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java index 76264b4c44d..647b4a75b5e 100644 --- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java +++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java @@ -31,6 +31,11 @@ public class DevicePolicyManagerWrapperImpl implements DevicePolicyManagerWrappe mDpm = dpm; } + @Override + public @Nullable List getActiveAdminsAsUser(int userId) { + return mDpm.getActiveAdminsAsUser(userId); + } + @Override public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin, int userHandle) { return mDpm.getMaximumFailedPasswordsForWipe(admin, userHandle); diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java index 792c3acc7ba..2270efac8d5 100644 --- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java +++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java @@ -31,6 +31,13 @@ public interface EnterprisePrivacyFeatureProvider { */ boolean isInCompMode(); + /** + * Returns the name of the organization managing the device via a Device Owner app. If the device + * is not managed by a Device Owner app or the name of the managing organization was not set, + * returns {@code null}. + */ + String getDeviceOwnerOrganizationName(); + /** * Returns a message informing the user that the device is managed by a Device Owner app. The * message includes a Learn More link that takes the user to the enterprise privacy section of @@ -100,4 +107,10 @@ public interface EnterprisePrivacyFeatureProvider { * managed profile (if any). */ int getNumberOfOwnerInstalledCaCertsInManagedProfile(); + + /** + * Returns the number of Device Admin apps active in the current user and the user's managed + * profile (if any). + */ + int getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile(); } diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java index 3b8251cb83a..6cff807de91 100644 --- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java +++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java @@ -83,6 +83,16 @@ public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFe return hasDeviceOwner() && getManagedProfileUserId() != UserHandle.USER_NULL; } + @Override + public String getDeviceOwnerOrganizationName() { + final CharSequence organizationName = mDpm.getDeviceOwnerOrganizationName(); + if (organizationName == null) { + return null; + } else { + return organizationName.toString(); + } + } + @Override public CharSequence getDeviceOwnerDisclosure() { if (!hasDeviceOwner()) { @@ -194,6 +204,19 @@ public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFe return certs != null ? certs.size() : 0; } + @Override + public int getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile() { + int activeAdmins = 0; + for (final UserInfo userInfo : mUm.getProfiles(MY_USER_ID)) { + final List activeAdminsForUser + = mDpm.getActiveAdminsAsUser(userInfo.id); + if (activeAdminsForUser != null) { + activeAdmins += activeAdminsForUser.size(); + } + } + return activeAdmins; + } + protected static class EnterprisePrivacySpan extends ClickableSpan { private final Context mContext; diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceController.java b/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceController.java new file mode 100644 index 00000000000..254940e0201 --- /dev/null +++ b/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceController.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 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.enterprise; + +import android.content.Context; +import android.content.res.Resources; +import android.support.v7.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.DynamicAvailabilityPreferenceController; +import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.overlay.FeatureFactory; + +public class EnterprisePrivacyPreferenceController extends DynamicAvailabilityPreferenceController { + + private static final String KEY_ENTERPRISE_PRIVACY = "enterprise_privacy"; + private final EnterprisePrivacyFeatureProvider mFeatureProvider; + + public EnterprisePrivacyPreferenceController(Context context, Lifecycle lifecycle) { + super(context, lifecycle); + mFeatureProvider = FeatureFactory.getFactory(context) + .getEnterprisePrivacyFeatureProvider(context); + } + + @Override + public void updateState(Preference preference) { + final String organizationName = mFeatureProvider.getDeviceOwnerOrganizationName(); + if (organizationName == null) { + preference.setSummary(R.string.enterprise_privacy_settings_summary_generic); + } else { + preference.setSummary(mContext.getResources().getString( + R.string.enterprise_privacy_settings_summary_with_name, organizationName)); + } + } + + @Override + public boolean isAvailable() { + return mFeatureProvider.hasDeviceOwner(); + } + + @Override + public String getPreferenceKey() { + return KEY_ENTERPRISE_PRIVACY; + } +} diff --git a/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceController.java b/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceController.java new file mode 100644 index 00000000000..55937ecebb7 --- /dev/null +++ b/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceController.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 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.enterprise; + +import android.content.Context; +import android.content.res.Resources; +import android.support.v7.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.PreferenceController; +import com.android.settings.overlay.FeatureFactory; + +public class ManageDeviceAdminPreferenceController extends PreferenceController { + + private static final String KEY_MANAGE_DEVICE_ADMIN = "manage_device_admin"; + private final EnterprisePrivacyFeatureProvider mFeatureProvider; + + public ManageDeviceAdminPreferenceController(Context context) { + super(context); + mFeatureProvider = FeatureFactory.getFactory(context) + .getEnterprisePrivacyFeatureProvider(context); + } + + @Override + public void updateState(Preference preference) { + final int activeAdmins + = mFeatureProvider.getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile(); + preference.setSummary(mContext.getResources().getQuantityString( + R.plurals.number_of_device_admins, activeAdmins, activeAdmins)); + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public String getPreferenceKey() { + return KEY_MANAGE_DEVICE_ADMIN; + } +} diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java index e0fb876dda4..20f578b8f19 100644 --- a/src/com/android/settings/search/Ranking.java +++ b/src/com/android/settings/search/Ranking.java @@ -172,6 +172,7 @@ public final class Ranking { sRankMap.put(SecuritySettings.class.getName(), RANK_SECURITY); sRankMap.put(ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), RANK_SECURITY); sRankMap.put(ScreenPinningSettings.class.getName(), RANK_SECURITY); + sRankMap.put(EnterprisePrivacySettings.class.getName(), RANK_SECURITY); // Accounts sRankMap.put(UserAndAccountDashboardFragment.class.getName(), RANK_ACCOUNT); @@ -181,7 +182,6 @@ public final class Ranking { // Privacy sRankMap.put(PrivacySettings.class.getName(), RANK_PRIVACY); - sRankMap.put(EnterprisePrivacySettings.class.getName(), RANK_PRIVACY); // Date / Time sRankMap.put(DateTimeSettings.class.getName(), RANK_DATE_TIME); diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java index 38d9221f18c..d4eec19f7bc 100644 --- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java @@ -60,6 +60,8 @@ import static org.mockito.Mockito.when; public final class EnterprisePrivacyFeatureProviderImplTest { private final ComponentName OWNER = new ComponentName("dummy", "component"); + private final ComponentName ADMIN_1 = new ComponentName("dummy", "admin1"); + private final ComponentName ADMIN_2 = new ComponentName("dummy", "admin2"); private final String OWNER_ORGANIZATION = new String("ACME"); private final Date TIMESTAMP = new Date(2011, 11, 11); private final int MY_USER_ID = UserHandle.myUserId(); @@ -113,6 +115,15 @@ public final class EnterprisePrivacyFeatureProviderImplTest { assertThat(mProvider.isInCompMode()).isTrue(); } + @Test + public void testGetDeviceOwnerOrganizationName() { + when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null); + assertThat(mProvider.getDeviceOwnerOrganizationName()).isNull(); + + when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(OWNER_ORGANIZATION); + assertThat(mProvider.getDeviceOwnerOrganizationName()).isEqualTo(OWNER_ORGANIZATION); + } + @Test public void testGetDeviceOwnerDisclosure() { when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(null); @@ -292,6 +303,21 @@ public final class EnterprisePrivacyFeatureProviderImplTest { assertThat(mProvider.getNumberOfOwnerInstalledCaCertsInManagedProfile()).isEqualTo(0); } + @Test + public void testGetNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile() { + when(mDevicePolicyManager.getActiveAdminsAsUser(MY_USER_ID)) + .thenReturn(Arrays.asList(new ComponentName[] {ADMIN_1, ADMIN_2})); + when(mDevicePolicyManager.getActiveAdminsAsUser(MANAGED_PROFILE_USER_ID)) + .thenReturn(Arrays.asList(new ComponentName[] {ADMIN_1})); + + assertThat(mProvider.getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile()) + .isEqualTo(2); + + mProfiles.add(new UserInfo(MANAGED_PROFILE_USER_ID, "", "", UserInfo.FLAG_MANAGED_PROFILE)); + assertThat(mProvider.getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile()) + .isEqualTo(3); + } + private void resetAndInitializePackageManagerWrapper() { reset(mPackageManagerWrapper); when(mPackageManagerWrapper.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceControllerTest.java new file mode 100644 index 00000000000..fe483471bde --- /dev/null +++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceControllerTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2017 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.enterprise; + +import android.content.Context; +import android.content.res.Resources; +import android.support.v7.preference.Preference; + +import com.android.settings.R; +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.testutils.FakeFeatureFactory; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link EnterprisePrivacyPreferenceController}. + */ +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public final class EnterprisePrivacyPreferenceControllerTest { + + private final String MANAGED_GENERIC = "managed by organization"; + private final String MANAGED_WITH_NAME = "managed by Foo, Inc."; + private final String MANAGING_ORGANIZATION = "Foo, Inc."; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + private FakeFeatureFactory mFeatureFactory; + + private EnterprisePrivacyPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory.setupForTest(mContext); + mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); + mController = new EnterprisePrivacyPreferenceController(mContext, null /* lifecycle */); + } + + @Test + public void testUpdateState() { + final Preference preference = new Preference(mContext, null, 0, 0); + + when(mContext.getString(R.string.enterprise_privacy_settings_summary_generic)) + .thenReturn(MANAGED_GENERIC); + when(mFeatureFactory.enterprisePrivacyFeatureProvider.getDeviceOwnerOrganizationName()) + .thenReturn(null); + mController.updateState(preference); + assertThat(preference.getSummary()).isEqualTo(MANAGED_GENERIC); + + when(mContext.getResources().getString( + R.string.enterprise_privacy_settings_summary_with_name, MANAGING_ORGANIZATION)) + .thenReturn(MANAGED_WITH_NAME); + when(mFeatureFactory.enterprisePrivacyFeatureProvider.getDeviceOwnerOrganizationName()) + .thenReturn(MANAGING_ORGANIZATION); + mController.updateState(preference); + assertThat(preference.getSummary()).isEqualTo(MANAGED_WITH_NAME); + } + + @Test + public void testIsAvailable() { + when(mFeatureFactory.enterprisePrivacyFeatureProvider.hasDeviceOwner()).thenReturn(false); + assertThat(mController.isAvailable()).isFalse(); + + when(mFeatureFactory.enterprisePrivacyFeatureProvider.hasDeviceOwner()).thenReturn(true); + assertThat(mController.isAvailable()).isTrue(); + + } + + @Test + public void testHandlePreferenceTreeClick() { + assertThat(mController.handlePreferenceTreeClick(new Preference(mContext, null, 0, 0))) + .isFalse(); + } + + @Test + public void testGetPreferenceKey() { + assertThat(mController.getPreferenceKey()).isEqualTo("enterprise_privacy"); + } +} diff --git a/tests/robotests/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceControllerTest.java new file mode 100644 index 00000000000..5cb637703e0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceControllerTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2017 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.enterprise; + +import android.content.Context; +import android.content.res.Resources; +import android.support.v7.preference.Preference; + +import com.android.settings.R; +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.testutils.FakeFeatureFactory; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link ManageDeviceAdminPreferenceController}. + */ +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public final class ManageDeviceAdminPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + private FakeFeatureFactory mFeatureFactory; + + private ManageDeviceAdminPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory.setupForTest(mContext); + mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); + mController = new ManageDeviceAdminPreferenceController(mContext); + } + + @Test + public void testUpdateState() { + final Preference preference = new Preference(mContext, null, 0, 0); + + when(mFeatureFactory.enterprisePrivacyFeatureProvider + .getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile()).thenReturn(5); + when(mContext.getResources().getQuantityString(R.plurals.number_of_device_admins, 5, 5)) + .thenReturn("5 active apps"); + mController.updateState(preference); + assertThat(preference.getSummary()).isEqualTo("5 active apps"); + } + + @Test + public void testIsAvailable() { + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void testHandlePreferenceTreeClick() { + assertThat(mController.handlePreferenceTreeClick(new Preference(mContext, null, 0, 0))) + .isFalse(); + } + + @Test + public void testGetPreferenceKey() { + assertThat(mController.getPreferenceKey()).isEqualTo("manage_device_admin"); + } +}