diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 9a74fa5763e..7d9ab4a6b52 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -134,6 +134,7 @@ + diff --git a/res/values/strings.xml b/res/values/strings.xml index 7c307c20d5b..097a0f73e35 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7982,4 +7982,21 @@ Privacy To provide access to your work data, your organization may change settings and install software on your device, which could cause some of your personal content to be visible to your admin. Contact your organization\'s admin for more details. + + What types of information can your organization see? + + What changes affect what your organization can see? + + What actions may impact your access to this device? + + Data associated with your work account, such as email and calendar + + List of all apps on your device + + + List of all %d app on your device + List of all %d apps on your device + + + Usage (time spent and amount of data used) of each app on your device diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml index 26cc6a8aebb..1dbb66c0eec 100644 --- a/res/xml/enterprise_privacy_settings.xml +++ b/res/xml/enterprise_privacy_settings.xml @@ -23,4 +23,29 @@ + + + + + + + + + + + + diff --git a/src/com/android/settings/DividerPreference.java b/src/com/android/settings/DividerPreference.java index d499e5223ab..5251ec345ac 100644 --- a/src/com/android/settings/DividerPreference.java +++ b/src/com/android/settings/DividerPreference.java @@ -19,11 +19,13 @@ import android.content.res.TypedArray; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceViewHolder; import android.util.AttributeSet; +import android.widget.TextView; public class DividerPreference extends Preference { private Boolean mAllowAbove; private Boolean mAllowBelow; + private Boolean mMultiLine; public DividerPreference(Context context, AttributeSet attrs) { super(context, attrs); @@ -34,6 +36,9 @@ public class DividerPreference extends Preference { if (a.hasValue(R.styleable.DividerPreference_allowDividerBelow)) { mAllowBelow = a.getBoolean(R.styleable.DividerPreference_allowDividerBelow, false); } + if (a.hasValue(R.styleable.DividerPreference_multiLine)) { + mMultiLine = a.getBoolean(R.styleable.DividerPreference_multiLine, false); + } } public DividerPreference(Context context) { @@ -59,5 +64,12 @@ public class DividerPreference extends Preference { if (mAllowBelow != null) { holder.setDividerAllowedBelow(mAllowBelow); } + + if (mMultiLine != null && mMultiLine) { + TextView textView = (TextView)holder.findViewById(android.R.id.title); + if (textView != null) { + textView.setSingleLine(false); + } + } } } diff --git a/src/com/android/settings/applications/ApplicationFeatureProvider.java b/src/com/android/settings/applications/ApplicationFeatureProvider.java index b6f7381060e..8c7b2574ed9 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProvider.java +++ b/src/com/android/settings/applications/ApplicationFeatureProvider.java @@ -25,5 +25,17 @@ public interface ApplicationFeatureProvider { * Returns a new {@link AppHeaderController} instance to customize app header. */ AppHeaderController newAppHeaderController(Fragment fragment, View appHeader); -} + /** + * Asynchronously calculates the total number of apps installed on the device, across all users + * and managed profiles. + */ + void calculateNumberOfInstalledApps(NumberOfInstalledAppsCallback callback); + + /** + * Callback that receives the total number of packages installed on the device. + */ + public interface NumberOfInstalledAppsCallback { + void onNumberOfInstalledAppsResult(int num); + } +} diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java index b1b44745cde..a284a0a83bf 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java +++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java @@ -18,17 +18,50 @@ package com.android.settings.applications; import android.app.Fragment; import android.content.Context; +import android.content.pm.UserInfo; +import android.os.UserManager; import android.view.View; +import java.util.List; + public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider { private final Context mContext; + private final PackageManagerWrapper mPm; + private final UserManager mUm; - public ApplicationFeatureProviderImpl(Context context) { + public ApplicationFeatureProviderImpl(Context context, PackageManagerWrapper pm) { mContext = context.getApplicationContext(); + mPm = pm; + mUm = UserManager.get(mContext); } + @Override public AppHeaderController newAppHeaderController(Fragment fragment, View appHeader) { return new AppHeaderController(mContext, fragment, appHeader); } + + @Override + public void calculateNumberOfInstalledApps(NumberOfInstalledAppsCallback callback) { + new AllUserInstalledAppCounter(callback).execute(); + } + + private class AllUserInstalledAppCounter extends InstalledAppCounter { + private NumberOfInstalledAppsCallback mCallback; + + AllUserInstalledAppCounter(NumberOfInstalledAppsCallback callback) { + super(mContext, ApplicationFeatureProviderImpl.this.mPm); + mCallback = callback; + } + + @Override + protected void onCountComplete(int num) { + mCallback.onNumberOfInstalledAppsResult(num); + } + + @Override + protected List getUsersToCount() { + return mUm.getUsers(true /* excludeDying */); + } + } } diff --git a/src/com/android/settings/applications/PackageManagerWrapper.java b/src/com/android/settings/applications/PackageManagerWrapper.java index ea019f43aee..d399115b054 100644 --- a/src/com/android/settings/applications/PackageManagerWrapper.java +++ b/src/com/android/settings/applications/PackageManagerWrapper.java @@ -36,6 +36,13 @@ public interface PackageManagerWrapper { */ List getInstalledApplicationsAsUser(int flags, int userId); + /** + * Calls {@code PackageManager.hasSystemFeature()}. + * + * @see android.content.pm.PackageManager.PackageManager#hasSystemFeature + */ + boolean hasSystemFeature(String name); + /** * Calls {@code PackageManager.queryIntentActivitiesAsUser()}. * diff --git a/src/com/android/settings/applications/PackageManagerWrapperImpl.java b/src/com/android/settings/applications/PackageManagerWrapperImpl.java index e41983be049..89668698110 100644 --- a/src/com/android/settings/applications/PackageManagerWrapperImpl.java +++ b/src/com/android/settings/applications/PackageManagerWrapperImpl.java @@ -35,6 +35,11 @@ public class PackageManagerWrapperImpl implements PackageManagerWrapper { return mPm.getInstalledApplicationsAsUser(flags, userId); } + @Override + public boolean hasSystemFeature(String name) { + return mPm.hasSystemFeature(name); + } + @Override public List queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { return mPm.queryIntentActivitiesAsUser(intent, flags, userId); diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java index 3e45de00fd5..2d8ca1f250f 100644 --- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java +++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java @@ -18,10 +18,17 @@ package com.android.settings.enterprise; import android.content.ComponentName; -// This interface replicates a subset of the android.app.admin.DevicePolicyManager (DPM). The -// interface exists so that we can use a thin wrapper around the DPM in production code and a mock -// in tests. We cannot directly mock or shadow the DPM, because some of the methods we rely on are -// newer than the API version supported by Robolectric. +/** + * This interface replicates a subset of the android.app.admin.DevicePolicyManager (DPM). The + * interface exists so that we can use a thin wrapper around the DPM in production code and a mock + * in tests. We cannot directly mock or shadow the DPM, because some of the methods we rely on are + * newer than the API version supported by Robolectric. + */ public interface DevicePolicyManagerWrapper { - public ComponentName getDeviceOwnerComponentOnAnyUser(); + /** + * Calls {@code DevicePolicyManager.getDeviceOwnerComponentOnAnyUser()}. + * + * @see android.app.admin.DevicePolicyManager#getDeviceOwnerComponentOnAnyUser + */ + ComponentName getDeviceOwnerComponentOnAnyUser(); } diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java index 87adcd67e0b..2b1efb44775 100644 --- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java +++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java @@ -26,6 +26,7 @@ public class DevicePolicyManagerWrapperImpl implements DevicePolicyManagerWrappe mDpm = dpm; } + @Override public ComponentName getDeviceOwnerComponentOnAnyUser() { return mDpm.getDeviceOwnerComponentOnAnyUser(); } diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java index 3d35c23fad0..8cdf27048d2 100644 --- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java +++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java @@ -17,21 +17,23 @@ package com.android.settings.enterprise; import android.content.pm.PackageManager; -import android.content.Context; + +import com.android.settings.applications.PackageManagerWrapper; public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFeatureProvider { - private final Context mContext; private final DevicePolicyManagerWrapper mDpm; + private final PackageManagerWrapper mPm; - public EnterprisePrivacyFeatureProviderImpl(Context context, DevicePolicyManagerWrapper dpm) { - mContext = context.getApplicationContext(); + public EnterprisePrivacyFeatureProviderImpl(DevicePolicyManagerWrapper dpm, + PackageManagerWrapper pm) { mDpm = dpm; + mPm = pm; } @Override public boolean hasDeviceOwner() { - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) { + if (!mPm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) { return false; } return mDpm.getDeviceOwnerComponentOnAnyUser() != null; diff --git a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java index a2d1a308e07..9ac76df4489 100644 --- a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java +++ b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java @@ -17,7 +17,6 @@ package com.android.settings.enterprise; import android.content.Context; -import android.os.Bundle; import android.provider.SearchIndexableResource; import com.android.settings.R; @@ -25,7 +24,9 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.core.PreferenceController; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable.SearchIndexProvider; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -55,7 +56,9 @@ public class EnterprisePrivacySettings extends DashboardFragment { @Override protected List getPreferenceControllers(Context context) { - return null; + final List controllers = new ArrayList(); + controllers.add(new InstalledPackagesPreferenceController(context)); + return controllers; } public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = diff --git a/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java b/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java new file mode 100644 index 00000000000..34c72ed2db1 --- /dev/null +++ b/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.settings.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.applications.ApplicationFeatureProvider; +import com.android.settings.core.PreferenceController; +import com.android.settings.overlay.FeatureFactory; + +public class InstalledPackagesPreferenceController extends PreferenceController { + + private static final String KEY_NUMBER_INSTALLED_PACKAGES = "number_installed_packages"; + private final ApplicationFeatureProvider mFeatureProvider; + + public InstalledPackagesPreferenceController(Context context) { + super(context); + mFeatureProvider = FeatureFactory.getFactory(context) + .getApplicationFeatureProvider(context); + } + + @Override + public void updateState(Preference preference) { + mFeatureProvider.calculateNumberOfInstalledApps( + new ApplicationFeatureProvider.NumberOfInstalledAppsCallback() { + @Override + public void onNumberOfInstalledAppsResult(int num) { + preference.setTitle(mContext.getResources().getQuantityString( + R.plurals.number_installed_packages, num, num)); + } + }); + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_NUMBER_INSTALLED_PACKAGES; + } +} diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java index 4a7396e9316..539bd651b10 100644 --- a/src/com/android/settings/overlay/FeatureFactoryImpl.java +++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java @@ -22,6 +22,7 @@ import android.support.annotation.Keep; import com.android.settings.applications.ApplicationFeatureProvider; import com.android.settings.applications.ApplicationFeatureProviderImpl; +import com.android.settings.applications.PackageManagerWrapperImpl; import com.android.settings.core.instrumentation.MetricsFeatureProvider; import com.android.settings.core.instrumentation.MetricsFeatureProviderImpl; import com.android.settings.dashboard.DashboardFeatureProvider; @@ -77,7 +78,8 @@ public final class FeatureFactoryImpl extends FeatureFactory { @Override public ApplicationFeatureProvider getApplicationFeatureProvider(Context context) { if (mApplicationFeatureProvider == null) { - mApplicationFeatureProvider = new ApplicationFeatureProviderImpl(context); + mApplicationFeatureProvider = new ApplicationFeatureProviderImpl(context, + new PackageManagerWrapperImpl(context.getPackageManager())); } return mApplicationFeatureProvider; } @@ -93,9 +95,10 @@ public final class FeatureFactoryImpl extends FeatureFactory { @Override public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) { if (mEnterprisePrivacyFeatureProvider == null) { - mEnterprisePrivacyFeatureProvider = new EnterprisePrivacyFeatureProviderImpl(context, + mEnterprisePrivacyFeatureProvider = new EnterprisePrivacyFeatureProviderImpl( new DevicePolicyManagerWrapperImpl((DevicePolicyManager) context - .getSystemService(Context.DEVICE_POLICY_SERVICE))); + .getSystemService(Context.DEVICE_POLICY_SERVICE)), + new PackageManagerWrapperImpl(context.getPackageManager())); } return mEnterprisePrivacyFeatureProvider; } diff --git a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java new file mode 100644 index 00000000000..dc177b8a5b1 --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.pm.UserInfo; +import android.os.UserManager; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.testutils.ApplicationTestUtils; +import com.android.settings.testutils.shadow.ShadowUserManager; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import java.util.Arrays; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; +import org.robolectric.shadows.ShadowApplication; +/** + * Tests for {@link ApplicationFeatureProviderImpl}. + */ +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, + shadows = {ShadowUserManager.class}) +public final class ApplicationFeatureProviderImplTest { + + private final int MAIN_USER_ID = 0; + private final int MANAGED_PROFILE_ID = 10; + + private @Mock UserManager mUserManager; + private @Mock Context mContext; + private @Mock PackageManagerWrapper mPackageManager; + + private ApplicationFeatureProvider mProvider; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(mContext.getApplicationContext()).thenReturn(mContext); + when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + + mProvider = new ApplicationFeatureProviderImpl(mContext, mPackageManager); + } + + @Test + public void testCalculateNumberOfInstalledApps() { + final Integer[] numberOfInstalledApps = new Integer[1]; + numberOfInstalledApps[0] = null; + + when(mUserManager.getUsers(true)).thenReturn(Arrays.asList( + new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN), + new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0))); + + when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS + | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS + | PackageManager.GET_UNINSTALLED_PACKAGES, + MAIN_USER_ID)).thenReturn(Arrays.asList( + ApplicationTestUtils.buildInfo(MAIN_USER_ID, "app1", 0 /* flags */))); + + when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS + | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, + MANAGED_PROFILE_ID)).thenReturn(Arrays.asList( + ApplicationTestUtils.buildInfo(MANAGED_PROFILE_ID, "app2", 0 /* flags */))); + + mProvider.calculateNumberOfInstalledApps( + new ApplicationFeatureProvider.NumberOfInstalledAppsCallback() { + @Override + public void onNumberOfInstalledAppsResult(int num) { + numberOfInstalledApps[0] = num; + } + }); + ShadowApplication.runBackgroundTasks(); + + assertThat(numberOfInstalledApps[0]).isEqualTo(2); + } +} diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java index afcd4840b18..be43d0ec9e9 100644 --- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java @@ -22,6 +22,7 @@ import android.content.pm.PackageManager; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.applications.PackageManagerWrapper; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -41,9 +42,8 @@ public final class EnterprisePrivacyFeatureProviderImplTest { private final ComponentName DEVICE_OWNER = new ComponentName("dummy", "component"); - private @Mock PackageManager mPackageManager; - private @Mock Context mContext; private @Mock DevicePolicyManagerWrapper mDevicePolicyManager; + private @Mock PackageManagerWrapper mPackageManager; private EnterprisePrivacyFeatureProvider mProvider; @@ -51,12 +51,10 @@ public final class EnterprisePrivacyFeatureProviderImplTest { public void setUp() { MockitoAnnotations.initMocks(this); - when(mContext.getApplicationContext()).thenReturn(mContext); - when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) .thenReturn(true); - mProvider = new EnterprisePrivacyFeatureProviderImpl(mContext, mDevicePolicyManager); + mProvider = new EnterprisePrivacyFeatureProviderImpl(mDevicePolicyManager, mPackageManager); } @Test diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java index 20393eef62c..28db647c3a7 100644 --- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java +++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java @@ -20,6 +20,8 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.core.PreferenceController; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -28,6 +30,8 @@ import org.robolectric.shadows.ShadowApplication; import static com.google.common.truth.Truth.assertThat; +import java.util.List; + /** * Tests for {@link EnterprisePrivacySettings}. */ @@ -66,7 +70,10 @@ public final class EnterprisePrivacySettingsTest { @Test public void getPreferenceControllers() { - assertThat(mSettings.getPreferenceControllers( - ShadowApplication.getInstance().getApplicationContext())).isNull(); + final List controllers = mSettings.getPreferenceControllers( + ShadowApplication.getInstance().getApplicationContext()); + assertThat(controllers).isNotNull(); + assertThat(controllers.size()).isEqualTo(1); + assertThat(controllers.get(0)).isInstanceOf(InstalledPackagesPreferenceController.class); } } diff --git a/tests/robotests/src/com/android/settings/enterprise/InstalledPackagesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/InstalledPackagesPreferenceControllerTest.java new file mode 100644 index 00000000000..fe41faaf05f --- /dev/null +++ b/tests/robotests/src/com/android/settings/enterprise/InstalledPackagesPreferenceControllerTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.enterprise; + +import android.content.Context; +import android.content.res.Resources; +import android.support.v7.preference.Preference; + +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.settings.R; +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.applications.ApplicationFeatureProvider; +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.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.anyObject; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link InstalledPackagesPreferenceController}. + */ +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public final class InstalledPackagesPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + private FakeFeatureFactory mFeatureFactory; + + private InstalledPackagesPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory.setupForTest(mContext); + mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); + mController = new InstalledPackagesPreferenceController(mContext); + } + + @Test + public void testUpdateState() { + final Preference preference = new Preference(mContext, null, 0, 0); + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) { + ((ApplicationFeatureProvider.NumberOfInstalledAppsCallback) + invocation.getArguments()[0]).onNumberOfInstalledAppsResult(20); + return null; + }}).when(mFeatureFactory.applicationFeatureProvider) + .calculateNumberOfInstalledApps(anyObject()); + when(mContext.getResources().getQuantityString(R.plurals.number_installed_packages, 20, 20)) + .thenReturn("20 packages"); + mController.updateState(preference); + assertThat(preference.getTitle()).isEqualTo("20 packages"); + } + + @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("number_installed_packages"); + } +}