Merge "Cache storage values for fast loading." into oc-mr1-dev
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 33d7d36..dd0db9a 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -40,6 +40,7 @@
import com.android.settings.applications.UserManagerWrapperImpl;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController;
+import com.android.settings.deviceinfo.storage.CachedStorageValuesHelper;
import com.android.settings.deviceinfo.storage.SecondaryUserController;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
@@ -68,6 +69,7 @@
private VolumeInfo mVolume;
private PrivateStorageInfo mStorageInfo;
private SparseArray<StorageAsyncLoader.AppsStorageResult> mAppsResult;
+ private CachedStorageValuesHelper mCachedStorageValuesHelper;
private StorageSummaryDonutPreferenceController mSummaryController;
private StorageItemPreferenceController mPreferenceController;
@@ -102,7 +104,10 @@
@Override
public void onViewCreated(View v, Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
- setLoading(true, false);
+ initializeCacheProvider();
+ if (mAppsResult == null || mStorageInfo == null) {
+ setLoading(true, false);
+ }
}
@Override
@@ -249,6 +254,7 @@
public void onLoadFinished(Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> loader,
SparseArray<StorageAsyncLoader.AppsStorageResult> data) {
mAppsResult = data;
+ maybeCacheFreshValues();
onReceivedSizes();
}
@@ -256,6 +262,48 @@
public void onLoaderReset(Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> loader) {
}
+ @VisibleForTesting
+ public void setCachedStorageValuesHelper(CachedStorageValuesHelper helper) {
+ mCachedStorageValuesHelper = helper;
+ }
+
+ @VisibleForTesting
+ public PrivateStorageInfo getPrivateStorageInfo() {
+ return mStorageInfo;
+ }
+
+ @VisibleForTesting
+ public SparseArray<StorageAsyncLoader.AppsStorageResult> getAppsStorageResult() {
+ return mAppsResult;
+ }
+
+ @VisibleForTesting
+ public void initializeCachedValues() {
+ PrivateStorageInfo info = mCachedStorageValuesHelper.getCachedPrivateStorageInfo();
+ SparseArray<StorageAsyncLoader.AppsStorageResult> loaderResult =
+ mCachedStorageValuesHelper.getCachedAppsStorageResult();
+ if (info == null || loaderResult == null) {
+ return;
+ }
+
+ mStorageInfo = info;
+ mAppsResult = loaderResult;
+ }
+
+ private void initializeCacheProvider() {
+ mCachedStorageValuesHelper =
+ new CachedStorageValuesHelper(getContext(), UserHandle.myUserId());
+ initializeCachedValues();
+ onReceivedSizes();
+ }
+
+ private void maybeCacheFreshValues() {
+ if (mStorageInfo != null && mAppsResult != null) {
+ mCachedStorageValuesHelper.cacheResult(
+ mStorageInfo, mAppsResult.get(UserHandle.myUserId()));
+ }
+ }
+
/**
* IconLoaderCallbacks exists because StorageDashboardFragment already implements
* LoaderCallbacks for a different type.
@@ -308,6 +356,7 @@
}
mStorageInfo = privateStorageInfo;
+ maybeCacheFreshValues();
onReceivedSizes();
}
}
diff --git a/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelper.java b/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelper.java
new file mode 100644
index 0000000..8225db3
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelper.java
@@ -0,0 +1,172 @@
+/*
+ * 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.SharedPreferences;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.util.SparseArray;
+
+import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+
+import java.util.concurrent.TimeUnit;
+
+public class CachedStorageValuesHelper {
+
+ @VisibleForTesting public static final String SHARED_PREFERENCES_NAME = "CachedStorageValues";
+ public static final String TIMESTAMP_KEY = "last_query_timestamp";
+ public static final String FREE_BYTES_KEY = "free_bytes";
+ public static final String TOTAL_BYTES_KEY = "total_bytes";
+ public static final String GAME_APPS_SIZE_KEY = "game_apps_size";
+ public static final String MUSIC_APPS_SIZE_KEY = "music_apps_size";
+ public static final String VIDEO_APPS_SIZE_KEY = "video_apps_size";
+ public static final String PHOTO_APPS_SIZE_KEY = "photo_apps_size";
+ public static final String OTHER_APPS_SIZE_KEY = "other_apps_size";
+ public static final String CACHE_APPS_SIZE_KEY = "cache_apps_size";
+ public static final String EXTERNAL_TOTAL_BYTES = "external_total_bytes";
+ public static final String EXTERNAL_AUDIO_BYTES = "external_audio_bytes";
+ public static final String EXTERNAL_VIDEO_BYTES = "external_video_bytes";
+ public static final String EXTERNAL_IMAGE_BYTES = "external_image_bytes";
+ public static final String EXTERNAL_APP_BYTES = "external_apps_bytes";
+ public static final String USER_ID_KEY = "user_id";
+ private final Long mClobberThreshold;
+ private final SharedPreferences mSharedPreferences;
+ private final int mUserId;
+ // This clock is used to provide the time. By default, it uses the system clock, but can be
+ // replaced for test purposes.
+ protected Clock mClock;
+
+ public CachedStorageValuesHelper(Context context, int userId) {
+ mSharedPreferences =
+ context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+ mClock = new Clock();
+ mUserId = userId;
+ mClobberThreshold =
+ Settings.Global.getLong(
+ context.getContentResolver(),
+ Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD,
+ TimeUnit.MINUTES.toMillis(5));
+ }
+
+ public PrivateStorageInfo getCachedPrivateStorageInfo() {
+ if (!isDataValid()) {
+ return null;
+ }
+ final long freeBytes = mSharedPreferences.getLong(FREE_BYTES_KEY, -1);
+ final long totalBytes = mSharedPreferences.getLong(TOTAL_BYTES_KEY, -1);
+ if (freeBytes < 0 || totalBytes < 0) {
+ return null;
+ }
+
+ return new PrivateStorageInfo(freeBytes, totalBytes);
+ }
+
+ public SparseArray<StorageAsyncLoader.AppsStorageResult> getCachedAppsStorageResult() {
+ if (!isDataValid()) {
+ return null;
+ }
+ final long gamesSize = mSharedPreferences.getLong(GAME_APPS_SIZE_KEY, -1);
+ final long musicAppsSize = mSharedPreferences.getLong(MUSIC_APPS_SIZE_KEY, -1);
+ final long videoAppsSize = mSharedPreferences.getLong(VIDEO_APPS_SIZE_KEY, -1);
+ final long photoAppSize = mSharedPreferences.getLong(PHOTO_APPS_SIZE_KEY, -1);
+ final long otherAppsSize = mSharedPreferences.getLong(OTHER_APPS_SIZE_KEY, -1);
+ final long cacheSize = mSharedPreferences.getLong(CACHE_APPS_SIZE_KEY, -1);
+ if (gamesSize < 0
+ || musicAppsSize < 0
+ || videoAppsSize < 0
+ || photoAppSize < 0
+ || otherAppsSize < 0
+ || cacheSize < 0) {
+ return null;
+ }
+
+ final long externalTotalBytes = mSharedPreferences.getLong(EXTERNAL_TOTAL_BYTES, -1);
+ final long externalAudioBytes = mSharedPreferences.getLong(EXTERNAL_AUDIO_BYTES, -1);
+ final long externalVideoBytes = mSharedPreferences.getLong(EXTERNAL_VIDEO_BYTES, -1);
+ final long externalImageBytes = mSharedPreferences.getLong(EXTERNAL_IMAGE_BYTES, -1);
+ final long externalAppBytes = mSharedPreferences.getLong(EXTERNAL_APP_BYTES, -1);
+ if (externalTotalBytes < 0
+ || externalAudioBytes < 0
+ || externalVideoBytes < 0
+ || externalImageBytes < 0
+ || externalAppBytes < 0) {
+ return null;
+ }
+
+ final StorageStatsSource.ExternalStorageStats externalStats =
+ new StorageStatsSource.ExternalStorageStats(
+ externalTotalBytes,
+ externalAudioBytes,
+ externalVideoBytes,
+ externalImageBytes,
+ externalAppBytes);
+ final StorageAsyncLoader.AppsStorageResult result =
+ new StorageAsyncLoader.AppsStorageResult();
+ result.gamesSize = gamesSize;
+ result.musicAppsSize = musicAppsSize;
+ result.videoAppsSize = videoAppsSize;
+ result.photosAppsSize = photoAppSize;
+ result.otherAppsSize = otherAppsSize;
+ result.cacheSize = cacheSize;
+ result.externalStats = externalStats;
+ final SparseArray<StorageAsyncLoader.AppsStorageResult> resultArray = new SparseArray<>();
+ resultArray.append(mUserId, result);
+ return resultArray;
+ }
+
+ public void cacheResult(
+ PrivateStorageInfo storageInfo, StorageAsyncLoader.AppsStorageResult result) {
+ mSharedPreferences
+ .edit()
+ .putLong(FREE_BYTES_KEY, storageInfo.freeBytes)
+ .putLong(TOTAL_BYTES_KEY, storageInfo.totalBytes)
+ .putLong(GAME_APPS_SIZE_KEY, result.gamesSize)
+ .putLong(MUSIC_APPS_SIZE_KEY, result.musicAppsSize)
+ .putLong(VIDEO_APPS_SIZE_KEY, result.videoAppsSize)
+ .putLong(PHOTO_APPS_SIZE_KEY, result.photosAppsSize)
+ .putLong(OTHER_APPS_SIZE_KEY, result.otherAppsSize)
+ .putLong(CACHE_APPS_SIZE_KEY, result.cacheSize)
+ .putLong(EXTERNAL_TOTAL_BYTES, result.externalStats.totalBytes)
+ .putLong(EXTERNAL_AUDIO_BYTES, result.externalStats.audioBytes)
+ .putLong(EXTERNAL_VIDEO_BYTES, result.externalStats.videoBytes)
+ .putLong(EXTERNAL_IMAGE_BYTES, result.externalStats.imageBytes)
+ .putLong(EXTERNAL_APP_BYTES, result.externalStats.appBytes)
+ .putInt(USER_ID_KEY, mUserId)
+ .putLong(TIMESTAMP_KEY, mClock.getCurrentTime())
+ .apply();
+ }
+
+ private boolean isDataValid() {
+ final int cachedUserId = mSharedPreferences.getInt(USER_ID_KEY, -1);
+ if (cachedUserId != mUserId) {
+ return false;
+ }
+
+ final long lastQueryTime = mSharedPreferences.getLong(TIMESTAMP_KEY, Long.MAX_VALUE);
+ final long currentTime = mClock.getCurrentTime();
+ return currentTime - lastQueryTime < mClobberThreshold;
+ }
+
+ /** Clock provides the current time. */
+ static class Clock {
+ public long getCurrentTime() {
+ return System.currentTimeMillis();
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
index b2d259a..a87f563 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
@@ -20,13 +20,18 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.Activity;
import android.os.storage.StorageManager;
import android.provider.SearchIndexableResource;
+import android.util.SparseArray;
+import com.android.settings.deviceinfo.storage.CachedStorageValuesHelper;
+import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.drawer.CategoryKey;
import org.junit.Before;
@@ -69,6 +74,47 @@
}
@Test
+ public void test_cacheProviderProvidesValuesIfBothCached() {
+ CachedStorageValuesHelper helper = mock(CachedStorageValuesHelper.class);
+ PrivateStorageInfo info = new PrivateStorageInfo(0, 0);
+ when(helper.getCachedPrivateStorageInfo()).thenReturn(info);
+ SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
+ when(helper.getCachedAppsStorageResult()).thenReturn(result);
+
+ mFragment.setCachedStorageValuesHelper(helper);
+ mFragment.initializeCachedValues();
+
+ assertThat(mFragment.getPrivateStorageInfo()).isEqualTo(info);
+ assertThat(mFragment.getAppsStorageResult()).isEqualTo(result);
+ }
+
+ @Test
+ public void test_cacheProviderDoesntProvideValuesIfAppsMissing() {
+ CachedStorageValuesHelper helper = mock(CachedStorageValuesHelper.class);
+ PrivateStorageInfo info = new PrivateStorageInfo(0, 0);
+ when(helper.getCachedPrivateStorageInfo()).thenReturn(info);
+
+ mFragment.setCachedStorageValuesHelper(helper);
+ mFragment.initializeCachedValues();
+
+ assertThat(mFragment.getPrivateStorageInfo()).isNull();
+ assertThat(mFragment.getAppsStorageResult()).isNull();
+ }
+
+ @Test
+ public void test_cacheProviderDoesntProvideValuesIfVolumeInfoMissing() {
+ CachedStorageValuesHelper helper = mock(CachedStorageValuesHelper.class);
+ SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
+ when(helper.getCachedAppsStorageResult()).thenReturn(result);
+
+ mFragment.setCachedStorageValuesHelper(helper);
+ mFragment.initializeCachedValues();
+
+ assertThat(mFragment.getPrivateStorageInfo()).isNull();
+ assertThat(mFragment.getAppsStorageResult()).isNull();
+ }
+
+ @Test
public void testSearchIndexProvider_shouldIndexResource() {
final List<SearchIndexableResource> indexRes =
StorageDashboardFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelperTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelperTest.java
new file mode 100644
index 0000000..154a7a1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelperTest.java
@@ -0,0 +1,295 @@
+/*
+ * 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.android.settings.deviceinfo.storage.CachedStorageValuesHelper.CACHE_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_APP_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_AUDIO_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_IMAGE_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_TOTAL_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_VIDEO_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.FREE_BYTES_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.GAME_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.MUSIC_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.OTHER_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.PHOTO_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.SHARED_PREFERENCES_NAME;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.TIMESTAMP_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.TOTAL_BYTES_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.USER_ID_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.VIDEO_APPS_SIZE_KEY;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.SparseArray;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class CachedStorageValuesHelperTest {
+ private Context mContext;
+
+ @Mock private CachedStorageValuesHelper.Clock mMockClock;
+ private CachedStorageValuesHelper mCachedValuesHelper;
+ private SharedPreferences mSharedPreferences;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application.getApplicationContext();
+ mSharedPreferences = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 0);
+ mCachedValuesHelper = new CachedStorageValuesHelper(mContext, 0);
+ mCachedValuesHelper.mClock = mMockClock;
+ }
+
+ @Test
+ public void getCachedPrivateStorageInfo_cachedValuesAreLoaded() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10001L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 6000L)
+ .putInt(USER_ID_KEY, 0)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ PrivateStorageInfo info = mCachedValuesHelper.getCachedPrivateStorageInfo();
+
+ assertThat(info.freeBytes).isEqualTo(1000L);
+ assertThat(info.totalBytes).isEqualTo(6000L);
+ }
+
+ @Test
+ public void getCachedAppsStorageResult_cachedValuesAreLoaded() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10001L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 1)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 222222)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 0)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ SparseArray<StorageAsyncLoader.AppsStorageResult> result =
+ mCachedValuesHelper.getCachedAppsStorageResult();
+
+ StorageAsyncLoader.AppsStorageResult primaryResult = result.get(0);
+ assertThat(primaryResult.gamesSize).isEqualTo(1L);
+ assertThat(primaryResult.musicAppsSize).isEqualTo(10L);
+ assertThat(primaryResult.videoAppsSize).isEqualTo(100L);
+ assertThat(primaryResult.photosAppsSize).isEqualTo(1000L);
+ assertThat(primaryResult.otherAppsSize).isEqualTo(10000L);
+ assertThat(primaryResult.cacheSize).isEqualTo(100000L);
+ assertThat(primaryResult.externalStats.totalBytes).isEqualTo(222222L);
+ assertThat(primaryResult.externalStats.audioBytes).isEqualTo(22L);
+ assertThat(primaryResult.externalStats.videoBytes).isEqualTo(222L);
+ assertThat(primaryResult.externalStats.imageBytes).isEqualTo(2222L);
+ assertThat(primaryResult.externalStats.appBytes).isEqualTo(22222L);
+ }
+
+ @Test
+ public void getCachedPrivateStorageInfo_nullIfDataIsStale() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10000000L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 0)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ PrivateStorageInfo info = mCachedValuesHelper.getCachedPrivateStorageInfo();
+ assertThat(info).isNull();
+ }
+
+ @Test
+ public void getCachedAppsStorageResult_nullIfDataIsStale() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10000000L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 0)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ SparseArray<StorageAsyncLoader.AppsStorageResult> result =
+ mCachedValuesHelper.getCachedAppsStorageResult();
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void getCachedPrivateStorageInfo_nullIfWrongUser() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10001L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 1)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ PrivateStorageInfo info = mCachedValuesHelper.getCachedPrivateStorageInfo();
+ assertThat(info).isNull();
+ }
+
+ @Test
+ public void getCachedAppsStorageResult_nullIfWrongUser() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10001L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 1)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ SparseArray<StorageAsyncLoader.AppsStorageResult> result =
+ mCachedValuesHelper.getCachedAppsStorageResult();
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void getCachedPrivateStorageInfo_nullIfEmpty() throws Exception {
+ PrivateStorageInfo info = mCachedValuesHelper.getCachedPrivateStorageInfo();
+ assertThat(info).isNull();
+ }
+
+ @Test
+ public void getCachedAppsStorageResult_nullIfEmpty() throws Exception {
+ SparseArray<StorageAsyncLoader.AppsStorageResult> result =
+ mCachedValuesHelper.getCachedAppsStorageResult();
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void cacheResult_succeeds() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10000L);
+ final StorageStatsSource.ExternalStorageStats externalStats =
+ new StorageStatsSource.ExternalStorageStats(22222l, 2l, 20L, 200L, 2000L);
+ final StorageAsyncLoader.AppsStorageResult result =
+ new StorageAsyncLoader.AppsStorageResult();
+ result.gamesSize = 1L;
+ result.musicAppsSize = 10l;
+ result.videoAppsSize = 100L;
+ result.photosAppsSize = 1000L;
+ result.otherAppsSize = 10000L;
+ result.cacheSize = 100000l;
+ result.externalStats = externalStats;
+ final PrivateStorageInfo info = new PrivateStorageInfo(1000L, 6000L);
+
+ mCachedValuesHelper.cacheResult(info, result);
+
+ assertThat(mSharedPreferences.getLong(GAME_APPS_SIZE_KEY, -1)).isEqualTo(1L);
+ assertThat(mSharedPreferences.getLong(MUSIC_APPS_SIZE_KEY, -1)).isEqualTo(10L);
+ assertThat(mSharedPreferences.getLong(VIDEO_APPS_SIZE_KEY, -1)).isEqualTo(100L);
+ assertThat(mSharedPreferences.getLong(PHOTO_APPS_SIZE_KEY, -1)).isEqualTo(1000L);
+ assertThat(mSharedPreferences.getLong(OTHER_APPS_SIZE_KEY, -1)).isEqualTo(10000L);
+ assertThat(mSharedPreferences.getLong(CACHE_APPS_SIZE_KEY, -1)).isEqualTo(100000L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_TOTAL_BYTES, -1)).isEqualTo(22222L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_AUDIO_BYTES, -1)).isEqualTo(2L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_VIDEO_BYTES, -1)).isEqualTo(20L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_IMAGE_BYTES, -1)).isEqualTo(200L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_APP_BYTES, -1)).isEqualTo(2000L);
+ assertThat(mSharedPreferences.getLong(FREE_BYTES_KEY, -1)).isEqualTo(1000L);
+ assertThat(mSharedPreferences.getLong(TOTAL_BYTES_KEY, -1)).isEqualTo(6000L);
+ assertThat(mSharedPreferences.getInt(USER_ID_KEY, -1)).isEqualTo(0);
+ assertThat(mSharedPreferences.getLong(TIMESTAMP_KEY, -1)).isEqualTo(10000L);
+ };
+}