From ee41ad89a90d0fd1c6f54cac6c734265a154b497 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 14 Mar 2022 19:30:03 +0800 Subject: [PATCH] Add cache mechanism for secondary users in Storage To prevent from the flicker happening, the size info for secondary users will be cached. Bug: 220259287 Test: manual test 1) Create secondary user 2) Finish setup flow 3) Install any types of apps and try to change the storage size 4) Navigate to Settings > Storage 5) Observe the storage size and progress bar, they should have animation when storage size info updated. Change-Id: Iff706b20446603f08334a0b782dd505ca78bdab2 --- .../deviceinfo/StorageCategoryFragment.java | 5 ++-- .../deviceinfo/StorageDashboardFragment.java | 5 ++-- .../storage/SecondaryUserController.java | 16 ++++++----- .../storage/StorageCacheHelper.java | 27 ++++++++++++++----- ...eUsageProgressBarPreferenceController.java | 2 +- .../storage/SecondaryUserControllerTest.java | 21 ++++++++------- .../storage/StorageCacheHelperTest.java | 14 +++++++--- 7 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/com/android/settings/deviceinfo/StorageCategoryFragment.java b/src/com/android/settings/deviceinfo/StorageCategoryFragment.java index efdd16535e4..4c9559b2e3b 100644 --- a/src/com/android/settings/deviceinfo/StorageCategoryFragment.java +++ b/src/com/android/settings/deviceinfo/StorageCategoryFragment.java @@ -117,7 +117,7 @@ public class StorageCategoryFragment extends DashboardFragment if (mStorageCacheHelper.hasCachedSizeInfo() && mSelectedStorageEntry.isPrivate()) { StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize(); mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo()); - mPreferenceController.setUsedSize(cachedData.usedSize); + mPreferenceController.setUsedSize(cachedData.totalUsedSize); mPreferenceController.setTotalSize(cachedData.totalSize); } if (mSelectedStorageEntry.isPrivate()) { @@ -225,7 +225,8 @@ public class StorageCategoryFragment extends DashboardFragment mPreferenceController.setUsedSize(privateUsedBytes); mPreferenceController.setTotalSize(mStorageInfo.totalBytes); // Cache total size infor and used size info - mStorageCacheHelper.cacheTotalSizeAndUsedSize(mStorageInfo.totalBytes, privateUsedBytes); + mStorageCacheHelper + .cacheTotalSizeAndTotalUsedSize(mStorageInfo.totalBytes, privateUsedBytes); for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) { final AbstractPreferenceController controller = mSecondaryUsers.get(i); if (controller instanceof SecondaryUserController) { diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java index cf31724ad69..42d67c1e5d2 100644 --- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java +++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java @@ -246,7 +246,7 @@ public class StorageDashboardFragment extends DashboardFragment if (mStorageCacheHelper.hasCachedSizeInfo() && mSelectedStorageEntry.isPrivate()) { StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize(); mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo()); - mPreferenceController.setUsedSize(cachedData.usedSize); + mPreferenceController.setUsedSize(cachedData.totalUsedSize); mPreferenceController.setTotalSize(cachedData.totalSize); } @@ -396,7 +396,8 @@ public class StorageDashboardFragment extends DashboardFragment mPreferenceController.setUsedSize(privateUsedBytes); mPreferenceController.setTotalSize(mStorageInfo.totalBytes); // Cache total size and used size - mStorageCacheHelper.cacheTotalSizeAndUsedSize(mStorageInfo.totalBytes, privateUsedBytes); + mStorageCacheHelper + .cacheTotalSizeAndTotalUsedSize(mStorageInfo.totalBytes, privateUsedBytes); for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) { final AbstractPreferenceController controller = mSecondaryUsers.get(i); if (controller instanceof SecondaryUserController) { diff --git a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java index 84cafd40797..9a280bfa4e2 100644 --- a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java +++ b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java @@ -46,7 +46,6 @@ public class SecondaryUserController extends AbstractPreferenceController implem // PreferenceGroupKey to try to add our preference onto. private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users"; private static final String PREFERENCE_KEY_BASE = "pref_user_"; - private static final int USER_PROFILE_INSERTION_LOCATION = 6; private static final int SIZE_NOT_SET = -1; private @NonNull @@ -58,6 +57,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem private long mSize; private long mTotalSizeBytes; private boolean mIsVisible; + private StorageCacheHelper mStorageCacheHelper; /** * Adds the appropriate controllers to a controller list for handling all secondary users on @@ -110,6 +110,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem super(context); mUser = info; mSize = SIZE_NOT_SET; + mStorageCacheHelper = new StorageCacheHelper(context, info.id); } @Override @@ -120,9 +121,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem mPreferenceGroup = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY); mStoragePreference.setTitle(mUser.name); mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id); - if (mSize != SIZE_NOT_SET) { - mStoragePreference.setStorageSize(mSize, mTotalSizeBytes); - } + setSize(mStorageCacheHelper.retrieveUsedSize(), false /* animate */); mPreferenceGroup.setVisible(mIsVisible); mPreferenceGroup.addPreference(mStoragePreference); @@ -153,10 +152,10 @@ public class SecondaryUserController extends AbstractPreferenceController implem * * @param size Size in bytes. */ - public void setSize(long size) { + public void setSize(long size, boolean animate) { mSize = size; if (mStoragePreference != null) { - mStoragePreference.setStorageSize(mSize, mTotalSizeBytes); + mStoragePreference.setStorageSize(mSize, mTotalSizeBytes, animate); } } @@ -184,11 +183,14 @@ public class SecondaryUserController extends AbstractPreferenceController implem @Override public void handleResult(SparseArray stats) { if (stats == null) { + setSize(mStorageCacheHelper.retrieveUsedSize(), false /* animate */); return; } final StorageAsyncLoader.StorageResult result = stats.get(getUser().id); if (result != null) { - setSize(result.externalStats.totalBytes); + setSize(result.externalStats.totalBytes, true /* animate */); + // TODO(b/171758224): Update the source of size info + mStorageCacheHelper.cacheUsedSize(result.externalStats.totalBytes); } } diff --git a/src/com/android/settings/deviceinfo/storage/StorageCacheHelper.java b/src/com/android/settings/deviceinfo/storage/StorageCacheHelper.java index a868c9f3f6e..e6da454f2f1 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageCacheHelper.java +++ b/src/com/android/settings/deviceinfo/storage/StorageCacheHelper.java @@ -26,7 +26,7 @@ public class StorageCacheHelper { private static final String SHARED_PREFERENCE_NAME = "StorageCache"; private static final String TOTAL_SIZE_KEY = "total_size_key"; - private static final String USED_SIZE_KEY = "used_size_key"; + private static final String TOTAL_USED_SIZE_KEY = "total_used_size_key"; private static final String IMAGES_SIZE_KEY = "images_size_key"; private static final String VIDEOS_SIZE_KEY = "videos_size_key"; private static final String AUDIO_SIZE_KEY = "audio_size_key"; @@ -35,6 +35,7 @@ public class StorageCacheHelper { private static final String DOCUMENTS_AND_OTHER_SIZE_KEY = "documents_and_other_size_key"; private static final String TRASH_SIZE_KEY = "trash_size_key"; private static final String SYSTEM_SIZE_KEY = "system_size_key"; + private static final String USED_SIZE_KEY = "used_size_key"; private final SharedPreferences mSharedPreferences; @@ -69,23 +70,37 @@ public class StorageCacheHelper { } /** - * Cache total size and used size + * Cache total size and total used size */ - public void cacheTotalSizeAndUsedSize(long totalSize, long usedSize) { + public void cacheTotalSizeAndTotalUsedSize(long totalSize, long totalUsedSize) { mSharedPreferences .edit() .putLong(TOTAL_SIZE_KEY, totalSize) - .putLong(USED_SIZE_KEY, usedSize) + .putLong(TOTAL_USED_SIZE_KEY, totalUsedSize) .apply(); } + /** + * Cache used size info when a user is treated as a secondary user. + */ + public void cacheUsedSize(long usedSize) { + mSharedPreferences.edit().putLong(USED_SIZE_KEY, usedSize).apply(); + } + + /** + * Returns used size for secondary user. + */ + public long retrieveUsedSize() { + return mSharedPreferences.getLong(USED_SIZE_KEY, 0); + } + /** * Returns a cached data about all file size information. */ public StorageCache retrieveCachedSize() { StorageCache result = new StorageCache(); result.totalSize = mSharedPreferences.getLong(TOTAL_SIZE_KEY, 0); - result.usedSize = mSharedPreferences.getLong(USED_SIZE_KEY, 0); + result.totalUsedSize = mSharedPreferences.getLong(TOTAL_USED_SIZE_KEY, 0); result.imagesSize = mSharedPreferences.getLong(IMAGES_SIZE_KEY, 0); result.videosSize = mSharedPreferences.getLong(VIDEOS_SIZE_KEY, 0); result.audioSize = mSharedPreferences.getLong(AUDIO_SIZE_KEY, 0); @@ -102,7 +117,7 @@ public class StorageCacheHelper { */ public static class StorageCache { public long totalSize; - public long usedSize; + public long totalUsedSize; public long gamesSize; public long allAppsExceptGamesSize; public long audioSize; diff --git a/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java index 872fa8a462b..be2a64abf58 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java +++ b/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java @@ -78,7 +78,7 @@ public class StorageUsageProgressBarPreferenceController extends BasePreferenceC if (mStorageEntry != null && mStorageEntry.isMounted() && mStorageEntry.isPrivate()) { StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize(); mTotalBytes = cachedData.totalSize; - mUsedBytes = cachedData.usedSize; + mUsedBytes = cachedData.totalUsedSize; mIsUpdateStateFromSelectedStorageEntry = true; updateState(mUsageProgressBarPreference); } diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java index ad811dcceac..eb8f5f40535 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java @@ -97,7 +97,7 @@ public class SecondaryUserControllerTest { public void controllerUpdatesSummaryOfNewPreference() { mPrimaryUser.name = TEST_NAME; mController.displayPreference(mScreen); - mController.setSize(MEGABYTE_IN_BYTES * 10); + mController.setSize(MEGABYTE_IN_BYTES * 10, false /* animate */); final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Preference.class); verify(mGroup).addPreference(argumentCaptor.capture()); @@ -114,7 +114,7 @@ public class SecondaryUserControllerTest { when(mUserManager.getUsers()).thenReturn(userInfos); final List controllers = SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager, - false /* isWorkProfileOnly */); + false /* isWorkProfileOnly */); assertThat(controllers).hasSize(1); // We should have the NoSecondaryUserController. @@ -134,7 +134,7 @@ public class SecondaryUserControllerTest { when(mUserManager.getUsers()).thenReturn(userInfos); final List controllers = SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager, - false /* isWorkProfileOnly */); + false /* isWorkProfileOnly */); assertThat(controllers).hasSize(1); assertThat(controllers.get(0) instanceof SecondaryUserController).isTrue(); @@ -153,7 +153,7 @@ public class SecondaryUserControllerTest { when(mUserManager.getUsers()).thenReturn(userInfos); final List controllers = SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager, - false /* isWorkProfileOnly */); + false /* isWorkProfileOnly */); assertThat(controllers).hasSize(1); assertThat(controllers.get(0) instanceof SecondaryUserController).isTrue(); @@ -172,7 +172,7 @@ public class SecondaryUserControllerTest { when(mUserManager.getUsers()).thenReturn(userInfos); final List controllers = SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager, - true /* isWorkProfileOnly */); + true /* isWorkProfileOnly */); assertThat(controllers).hasSize(1); assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse(); @@ -190,14 +190,14 @@ public class SecondaryUserControllerTest { final List controllers = SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager, - false /* isWorkProfileOnly */); + false /* isWorkProfileOnly */); assertThat(controllers).hasSize(1); assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse(); } @Test - public void controllerUpdatesPreferenceOnAcceptingResult() { + public void handleResult_noStatsResult_shouldShowCachedData() { mPrimaryUser.name = TEST_NAME; mPrimaryUser.id = 10; mController.displayPreference(mScreen); @@ -211,8 +211,11 @@ public class SecondaryUserControllerTest { MEGABYTE_IN_BYTES * 10, MEGABYTE_IN_BYTES * 10, 0); result.put(10, userResult); - + // Cache size info at first time mController.handleResult(result); + + // Retrieve cache size info if stats result is null + mController.handleResult(null); final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Preference.class); verify(mGroup).addPreference(argumentCaptor.capture()); final Preference preference = argumentCaptor.getValue(); @@ -233,7 +236,7 @@ public class SecondaryUserControllerTest { when(mUserManager.getUsers()).thenReturn(userInfos); final List controllers = SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager, - false /* isWorkProfileOnly */); + false /* isWorkProfileOnly */); assertThat(controllers).hasSize(1); // We should have the NoSecondaryUserController. diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageCacheHelperTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageCacheHelperTest.java index 1956b09a95d..9e20e78c03a 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageCacheHelperTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageCacheHelperTest.java @@ -39,7 +39,8 @@ public class StorageCacheHelperTest { private static final long FAKE_TRASH_SIZE = 500L; private static final long FAKE_SYSTEM_SIZE = 2300L; private static final long FAKE_TOTAL_SIZE = 256000L; - private static final long FAKE_USED_SIZE = 50000L; + private static final long FAKE_TOTAL_USED_SIZE = 50000L; + private static final long FAKE_USED_SIZE = 6500L; private Context mContext; private StorageCacheHelper mHelper; @@ -74,12 +75,19 @@ public class StorageCacheHelperTest { @Test public void cacheTotalSizeAndUsedSize_shouldSaveToSharedPreference() { - mHelper.cacheTotalSizeAndUsedSize(FAKE_TOTAL_SIZE, FAKE_USED_SIZE); + mHelper.cacheTotalSizeAndTotalUsedSize(FAKE_TOTAL_SIZE, FAKE_TOTAL_USED_SIZE); StorageCacheHelper.StorageCache storageCache = mHelper.retrieveCachedSize(); assertThat(storageCache.totalSize).isEqualTo(FAKE_TOTAL_SIZE); - assertThat(storageCache.usedSize).isEqualTo(FAKE_USED_SIZE); + assertThat(storageCache.totalUsedSize).isEqualTo(FAKE_TOTAL_USED_SIZE); + } + + @Test + public void cacheUsedSize_shouldSaveToSharedPreference() { + mHelper.cacheUsedSize(FAKE_USED_SIZE); + + assertThat(mHelper.retrieveUsedSize()).isEqualTo(FAKE_USED_SIZE); } private StorageCacheHelper.StorageCache getFakeStorageCache() {