Merge "Enable the backup settings activity before launching"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 34f3c51..da10faf 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1209,9 +1209,9 @@
<string name="lock_profile_wipe_dismiss">Dismiss</string>
<!-- Hint shown in dialog screen when password is too short -->
- <string name="lockpassword_password_too_short">Must be at least %d characters</string>
+ <string name="lockpassword_password_too_short">Must be at least <xliff:g id="count" example="3">%d</xliff:g> characters</string>
<!-- Hint shown in dialog screen when PIN is too short -->
- <string name="lockpassword_pin_too_short">PIN must be at least %d digits</string>
+ <string name="lockpassword_pin_too_short">PIN must be at least <xliff:g id="count" example="3">%d</xliff:g> digits</string>
<!-- Hint shown after minimum password criteria is met -->
<string name="lockpassword_continue_label">Continue</string>
@@ -1242,37 +1242,37 @@
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of letters -->
<plurals name="lockpassword_password_requires_letters">
<item quantity="one">Must contain at least 1 letter</item>
- <item quantity="other">Must contain at least %d letters</item>
+ <item quantity="other">Must contain at least <xliff:g id="count" example="3">%d</xliff:g> letters</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of lowercase letters -->
<plurals name="lockpassword_password_requires_lowercase">
<item quantity="one">Must contain at least 1 lowercase letter</item>
- <item quantity="other">Must contain at least %d lowercase letters</item>
+ <item quantity="other">Must contain at least <xliff:g id="count" example="3">%d</xliff:g> lowercase letters</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of uppercase letters -->
<plurals name="lockpassword_password_requires_uppercase">
<item quantity="one">Must contain at least 1 uppercase letter</item>
- <item quantity="other">Must contain at least %d uppercase letters</item>
+ <item quantity="other">Must contain at least <xliff:g id="count" example="3">%d</xliff:g> uppercase letters</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of numerical digits -->
<plurals name="lockpassword_password_requires_numeric">
<item quantity="one">Must contain at least 1 numerical digit</item>
- <item quantity="other">Must contain at least %d numerical digits</item>
+ <item quantity="other">Must contain at least <xliff:g id="count" example="3">%d</xliff:g> numerical digits</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of special symbols -->
<plurals name="lockpassword_password_requires_symbols">
<item quantity="one">Must contain at least 1 special symbol</item>
- <item quantity="other">Must contain at least %d special symbols</item>
+ <item quantity="other">Must contain at least <xliff:g id="count" example="3">%d</xliff:g> special symbols</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password doesn't contain the required number of non-letter characters -->
<plurals name="lockpassword_password_requires_nonletter">
<item quantity="one">Must contain at least 1 non-letter character</item>
- <item quantity="other">Must contain at least %d non-letter characters</item>
+ <item quantity="other">Must contain at least <xliff:g id="count" example="3">%d</xliff:g> non-letter characters</item>
</plurals>
<!-- Error shown when in PASSWORD mode and password has been used recently. Please keep this string short! -->
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
index 66c9140..ad5315d 100644
--- a/res/xml/wifi_configure_settings.xml
+++ b/res/xml/wifi_configure_settings.xml
@@ -17,12 +17,10 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/wifi_configure_titlebar">
- <!-- android:dependency="enable_wifi" -->
- <ListPreference
- android:key="sleep_policy"
- android:title="@string/wifi_setting_sleep_policy_title"
- android:entries="@array/wifi_sleep_policy_entries"
- android:entryValues="@array/wifi_sleep_policy_values" />
+ <SwitchPreference
+ android:key="enable_wifi_wakeup"
+ android:title="@string/wifi_wakeup"
+ android:summary="@string/wifi_wakeup_summary" />
<SwitchPreference
android:key="allow_recommendations"
@@ -35,22 +33,15 @@
android:summary="@string/wifi_notify_open_networks_summary" />
<SwitchPreference
- android:key="enable_wifi_wakeup"
- android:title="@string/wifi_wakeup"
- android:summary="@string/wifi_wakeup_summary" />
-
- <SwitchPreference
android:key="wifi_cellular_data_fallback"
android:title="@string/wifi_cellular_data_fallback_title"
android:summary="@string/wifi_cellular_data_fallback_summary"/>
- <Preference
- android:key="mac_address"
- android:title="@string/wifi_advanced_mac_address_title"/>
-
- <Preference
- android:key="current_ip_address"
- android:title="@string/wifi_advanced_ip_address_title"/>
+ <ListPreference
+ android:key="sleep_policy"
+ android:title="@string/wifi_setting_sleep_policy_title"
+ android:entries="@array/wifi_sleep_policy_entries"
+ android:entryValues="@array/wifi_sleep_policy_values" />
<Preference
android:key="install_credentials"
@@ -77,4 +68,12 @@
android:key="wps_pin_entry"
android:title="@string/wifi_menu_wps_pin" />
+ <Preference
+ android:key="mac_address"
+ android:title="@string/wifi_advanced_mac_address_title"/>
+
+ <Preference
+ android:key="current_ip_address"
+ android:title="@string/wifi_advanced_ip_address_title"/>
+
</PreferenceScreen>
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index abf0154..dc7b7aa 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -1434,7 +1434,7 @@
Settings.Global.putInt(getActivity().getContentResolver(),
Settings.Global.DEVELOPMENT_FORCE_RTL, value ? 1 : 0);
SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, value ? "1" : "0");
- LocalePicker.updateLocale(getActivity().getResources().getConfiguration().locale);
+ LocalePicker.updateLocales(getActivity().getResources().getConfiguration().getLocales());
}
private void updateWifiDisplayCertificationOptions() {
@@ -1805,9 +1805,11 @@
synchronized (mBluetoothA2dpLock) {
if (mBluetoothA2dp != null) {
codecStatus = mBluetoothA2dp.getCodecStatus();
- codecConfig = codecStatus.getCodecConfig();
- codecsLocalCapabilities = codecStatus.getCodecsLocalCapabilities();
- codecsSelectableCapabilities = codecStatus.getCodecsSelectableCapabilities();
+ if (codecStatus != null) {
+ codecConfig = codecStatus.getCodecConfig();
+ codecsLocalCapabilities = codecStatus.getCodecsLocalCapabilities();
+ codecsSelectableCapabilities = codecStatus.getCodecsSelectableCapabilities();
+ }
}
}
if (codecConfig == null)
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 61f3e95..ea196ad 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -17,7 +17,9 @@
package com.android.settings.deviceinfo;
import android.content.Context;
+import android.content.Loader;
import android.os.Bundle;
+import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.provider.SearchIndexableResource;
@@ -27,6 +29,7 @@
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.deviceinfo.storage.AppsAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
import com.android.settings.overlay.FeatureFactory;
@@ -42,6 +45,7 @@
public class StorageDashboardFragment extends DashboardFragment {
private static final String TAG = "StorageDashboardFrag";
+ private static final int APPS_JOB_ID = 0;
private VolumeInfo mVolume;
@@ -54,6 +58,12 @@
}
@Override
+ public void onResume() {
+ super.onResume();
+ getLoaderManager().initLoader(APPS_JOB_ID, Bundle.EMPTY, mPreferenceController);
+ }
+
+ @Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
diff --git a/src/com/android/settings/deviceinfo/storage/AppsAsyncLoader.java b/src/com/android/settings/deviceinfo/storage/AppsAsyncLoader.java
new file mode 100644
index 0000000..cbedb08
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/storage/AppsAsyncLoader.java
@@ -0,0 +1,86 @@
+/*
+ * 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.deviceinfo.storage;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.util.ArraySet;
+
+import com.android.settings.applications.PackageManagerWrapper;
+import com.android.settings.utils.AsyncLoader;
+
+import java.util.List;
+
+/**
+ * AppsAsyncLoader is a Loader which loads app storage information and categories it by the app's
+ * specified categorization.
+ */
+public class AppsAsyncLoader extends AsyncLoader<AppsAsyncLoader.AppsStorageResult> {
+ private int mUserId;
+ private String mUuid;
+ private StorageStatsSource mStatsManager;
+ private PackageManagerWrapper mPackageManager;
+
+ public AppsAsyncLoader(Context context, int userId, String uuid, StorageStatsSource source,
+ PackageManagerWrapper pm) {
+ super(context);
+ mUserId = userId;
+ mUuid = uuid;
+ mStatsManager = source;
+ mPackageManager = pm;
+ }
+
+ @Override
+ public AppsStorageResult loadInBackground() {
+ return loadApps();
+ }
+
+ private AppsStorageResult loadApps() {
+ AppsStorageResult result = new AppsStorageResult();
+ ArraySet<Integer> seenUid = new ArraySet<>(); // some apps share a uid
+
+ List<ApplicationInfo> applicationInfos =
+ mPackageManager.getInstalledApplicationsAsUser(0, mUserId);
+ int size = applicationInfos.size();
+ for (int i = 0; i < size; i++) {
+ ApplicationInfo app = applicationInfos.get(i);
+ if (seenUid.contains(app.uid)) {
+ continue;
+ }
+ seenUid.add(app.uid);
+
+ StorageStatsSource.AppStorageStats stats = mStatsManager.getStatsForUid(mUuid, app.uid);
+ // Note: This omits cache intentionally -- we are not attributing it to the apps.
+ long appSize = stats.getCodeBytes() + stats.getDataBytes();
+ if (app.category == ApplicationInfo.CATEGORY_GAME) {
+ result.gamesSize += appSize;
+ } else {
+ result.otherAppsSize += appSize;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ protected void onDiscardResult(AppsStorageResult result) {
+ }
+
+ public static class AppsStorageResult {
+ public long gamesSize;
+ public long otherAppsSize;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 16dcd18..5437dcb 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -17,9 +17,12 @@
package com.android.settings.deviceinfo.storage;
import android.app.Fragment;
+import android.app.LoaderManager;
+import android.app.usage.StorageStatsManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
+import android.content.Loader;
import android.os.Bundle;
import android.os.Environment;
import android.os.UserHandle;
@@ -35,6 +38,7 @@
import com.android.settings.Settings;
import com.android.settings.Utils;
import com.android.settings.applications.ManageApplications;
+import com.android.settings.applications.PackageManagerWrapperImpl;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver;
@@ -51,10 +55,12 @@
* categorization breakdown.
*/
public class StorageItemPreferenceController extends PreferenceController
- implements StorageMeasurement.MeasurementReceiver, LifecycleObserver, OnDestroy {
+ implements StorageMeasurement.MeasurementReceiver, LifecycleObserver, OnDestroy,
+ LoaderManager.LoaderCallbacks<AppsAsyncLoader.AppsStorageResult> {
private static final String TAG = "StorageItemPreference";
private static final String IMAGE_MIME_TYPE = "image/*";
+
@VisibleForTesting
static final String PHOTO_KEY = "pref_photos_videos";
@VisibleForTesting
@@ -179,15 +185,6 @@
mAudioPreference.setStorageSize(audioSize);
}
- if (mGamePreference != null) {
- mGamePreference.setStorageSize(0);
- }
-
- final long appSize = details.appsSize.get(mUserId);
- if (mAppPreference != null) {
- mAppPreference.setStorageSize(appSize);
- }
-
if (mSystemPreference != null) {
mSystemPreference.setStorageSize(mSystemSize);
}
@@ -216,6 +213,25 @@
mFilePreference = (StorageItemPreferenceAlternate) screen.findPreference(FILES_KEY);
}
+ @Override
+ public Loader<AppsAsyncLoader.AppsStorageResult> onCreateLoader(int id,
+ Bundle args) {
+ return new AppsAsyncLoader(mContext, UserHandle.myUserId(), mVolume.fsUuid,
+ new StorageStatsSource(mContext),
+ new PackageManagerWrapperImpl(mContext.getPackageManager()));
+ }
+
+ @Override
+ public void onLoadFinished(Loader<AppsAsyncLoader.AppsStorageResult> loader,
+ AppsAsyncLoader.AppsStorageResult data) {
+ mGamePreference.setStorageSize(data.gamesSize);
+ mAppPreference.setStorageSize(data.otherAppsSize);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<AppsAsyncLoader.AppsStorageResult> loader) {
+ }
+
/**
* Begins an asynchronous storage measurement task for the preferences.
*/
diff --git a/src/com/android/settings/deviceinfo/storage/StorageStatsSource.java b/src/com/android/settings/deviceinfo/storage/StorageStatsSource.java
index b6e03fb..98038fd 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageStatsSource.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageStatsSource.java
@@ -16,6 +16,7 @@
package com.android.settings.deviceinfo.storage;
+import android.app.usage.StorageStats;
import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.os.UserHandle;
@@ -24,14 +25,19 @@
* StorageStatsSource wraps the StorageStatsManager for testability purposes.
*/
public class StorageStatsSource {
- private StorageStatsManager mSsm;
+ private StorageStatsManager mStorageStatsManager;
public StorageStatsSource(Context context) {
- mSsm = context.getSystemService(StorageStatsManager.class);
+ mStorageStatsManager = context.getSystemService(StorageStatsManager.class);
}
public ExternalStorageStats getExternalStorageStats(String volumeUuid, UserHandle user) {
- return new ExternalStorageStats(mSsm.queryExternalStatsForUser(volumeUuid, user));
+ return new ExternalStorageStats(
+ mStorageStatsManager.queryExternalStatsForUser(volumeUuid, user));
+ }
+
+ public AppStorageStats getStatsForUid(String volumeUuid, int uid) {
+ return new AppStorageStatsImpl(mStorageStatsManager.queryStatsForUid(volumeUuid, uid));
}
public static class ExternalStorageStats {
@@ -55,4 +61,30 @@
imageBytes = stats.getImageBytes();
}
}
+
+ public interface AppStorageStats {
+ long getCodeBytes();
+ long getDataBytes();
+ long getCacheBytes();
+ }
+
+ public static class AppStorageStatsImpl implements AppStorageStats {
+ private StorageStats mStats;
+
+ public AppStorageStatsImpl(StorageStats stats) {
+ mStats = stats;
+ }
+
+ public long getCodeBytes() {
+ return mStats.getCodeBytes();
+ }
+
+ public long getDataBytes() {
+ return mStats.getDataBytes();
+ }
+
+ public long getCacheBytes() {
+ return mStats.getCacheBytes();
+ }
+ }
}
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index 5fd3eeb..2b4743f 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -50,6 +50,12 @@
}
@Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ mProgressiveDisclosureMixin.setTileLimit(5);
+ }
+
+ @Override
protected int getPreferenceScreenResId() {
return R.xml.wifi_configure_settings;
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index f7baba3..cfec382 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -215,11 +215,15 @@
details.mediaSize.put(0, mediaSizes);
mController.setSystemSize(KILOBYTE * 6);
mController.onDetailsChanged(details);
+ AppsAsyncLoader.AppsStorageResult result = new AppsAsyncLoader.AppsStorageResult();
+ result.gamesSize = KILOBYTE * 8;
+ result.otherAppsSize = KILOBYTE * 9;
+ mController.onLoadFinished(null, result);
assertThat(audio.getSummary().toString()).isEqualTo("4.00KB");
assertThat(image.getSummary().toString()).isEqualTo("5.00KB");
- assertThat(games.getSummary().toString()).isEqualTo("0");
- assertThat(apps.getSummary().toString()).isEqualTo("1.00KB");
+ assertThat(games.getSummary().toString()).isEqualTo("8.00KB");
+ assertThat(apps.getSummary().toString()).isEqualTo("9.00KB");
assertThat(system.getSummary().toString()).isEqualTo("6.00KB");
assertThat(files.getSummary().toString()).isEqualTo("5.00KB");
}
diff --git a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
index 419fd00..acfd400 100644
--- a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
@@ -193,6 +193,30 @@
verify(preference).setSummary(anyString());
}
+ @Test
+ public void onResume_availableButLocked_shouldRedactPreferences() {
+ final String notAvailable = "(not available)";
+ when(mContext.getString(R.string.managed_profile_not_available_label))
+ .thenReturn(notAvailable);
+
+ // Given a device with a managed profile:
+ when(mAudioHelper.isSingleVolume()).thenReturn(false);
+ when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+ when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext);
+ when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+ .thenReturn(UserHandle.myUserId());
+ when(mAudioHelper.isUserUnlocked(any(UserManager.class), anyInt())).thenReturn(false);
+ mockWorkCategory();
+
+ // When resumed:
+ mController.onResume();
+
+ // Sound preferences should explain that the profile isn't available yet.
+ verify(mScreen.findPreference(KEY_WORK_PHONE_RINGTONE)).setSummary(eq(notAvailable));
+ verify(mScreen.findPreference(KEY_WORK_NOTIFICATION_RINGTONE)).setSummary(eq(notAvailable));
+ verify(mScreen.findPreference(KEY_WORK_ALARM_RINGTONE)).setSummary(eq(notAvailable));
+ }
+
private void mockWorkCategory() {
when(mScreen.findPreference(KEY_WORK_CATEGORY))
.thenReturn(mock(PreferenceGroup.class));
diff --git a/tests/unit/src/com/android/settings/deviceinfo/storage/AppAsyncLoaderTest.java b/tests/unit/src/com/android/settings/deviceinfo/storage/AppAsyncLoaderTest.java
new file mode 100644
index 0000000..8d4dd2e
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/storage/AppAsyncLoaderTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.deviceinfo.storage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.settings.applications.PackageManagerWrapper;
+
+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 java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AppAsyncLoaderTest {
+ @Mock
+ private StorageStatsSource mSource;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private PackageManagerWrapper mPackageManager;
+ ArrayList<ApplicationInfo> mInfo = new ArrayList<>();
+
+ private AppsAsyncLoader mLoader;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mInfo = new ArrayList<>();
+ mLoader = new AppsAsyncLoader(mContext, 1, "id", mSource, mPackageManager);
+ when(mPackageManager.getInstalledApplicationsAsUser(anyInt(), anyInt())).thenReturn(mInfo);
+ }
+
+ @Test
+ public void testLoadingApps() throws Exception {
+ addPackage(1001, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
+ addPackage(1002, 0, 100, 1000, ApplicationInfo.CATEGORY_UNDEFINED);
+
+ AppsAsyncLoader.AppsStorageResult result = mLoader.loadInBackground();
+
+ assertThat(result.gamesSize).isEqualTo(0L);
+ assertThat(result.otherAppsSize).isEqualTo(1111L);
+ }
+
+ @Test
+ public void testGamesAreFiltered() throws Exception {
+ addPackage(1001, 0, 1, 10, ApplicationInfo.CATEGORY_GAME);
+
+ AppsAsyncLoader.AppsStorageResult result = mLoader.loadInBackground();
+
+ assertThat(result.gamesSize).isEqualTo(11L);
+ assertThat(result.otherAppsSize).isEqualTo(0);
+ }
+
+ @Test
+ public void testDuplicateUidsAreSkipped() throws Exception {
+ addPackage(1001, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
+ addPackage(1001, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
+
+ AppsAsyncLoader.AppsStorageResult result = mLoader.loadInBackground();
+
+ assertThat(result.otherAppsSize).isEqualTo(11L);
+ }
+
+ @Test
+ public void testCacheIsIgnored() throws Exception {
+ addPackage(1001, 100, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
+
+ AppsAsyncLoader.AppsStorageResult result = mLoader.loadInBackground();
+
+ assertThat(result.otherAppsSize).isEqualTo(11L);
+ }
+
+ private void addPackage(int uid, long cacheSize, long codeSize, long dataSize, int category) {
+ StorageStatsSource.AppStorageStats storageStats =
+ mock(StorageStatsSource.AppStorageStats.class);
+ when(storageStats.getCodeBytes()).thenReturn(codeSize);
+ when(storageStats.getDataBytes()).thenReturn(dataSize);
+ when(mSource.getStatsForUid(anyString(), eq(uid))).thenReturn(storageStats);
+
+ ApplicationInfo info = new ApplicationInfo();
+ info.uid = uid;
+ info.category = category;
+ mInfo.add(info);
+ }
+}