Merge "Cache mechanism for Storage page" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d3cb79a127
@@ -47,6 +47,7 @@ import com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchP
|
|||||||
import com.android.settings.deviceinfo.storage.DiskInitFragment;
|
import com.android.settings.deviceinfo.storage.DiskInitFragment;
|
||||||
import com.android.settings.deviceinfo.storage.SecondaryUserController;
|
import com.android.settings.deviceinfo.storage.SecondaryUserController;
|
||||||
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
|
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
|
||||||
|
import com.android.settings.deviceinfo.storage.StorageCacheHelper;
|
||||||
import com.android.settings.deviceinfo.storage.StorageEntry;
|
import com.android.settings.deviceinfo.storage.StorageEntry;
|
||||||
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
|
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
|
||||||
import com.android.settings.deviceinfo.storage.StorageSelectionPreferenceController;
|
import com.android.settings.deviceinfo.storage.StorageSelectionPreferenceController;
|
||||||
@@ -109,6 +110,8 @@ public class StorageDashboardFragment extends DashboardFragment
|
|||||||
private boolean mIsWorkProfile;
|
private boolean mIsWorkProfile;
|
||||||
private int mUserId;
|
private int mUserId;
|
||||||
private Preference mFreeUpSpacePreference;
|
private Preference mFreeUpSpacePreference;
|
||||||
|
private boolean mIsLoadedFromCache;
|
||||||
|
private StorageCacheHelper mStorageCacheHelper;
|
||||||
|
|
||||||
private final StorageEventListener mStorageEventListener = new StorageEventListener() {
|
private final StorageEventListener mStorageEventListener = new StorageEventListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -239,15 +242,27 @@ public class StorageDashboardFragment extends DashboardFragment
|
|||||||
mPreferenceController.setVolume(null);
|
mPreferenceController.setVolume(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mStorageCacheHelper.hasCachedSizeInfo() && mSelectedStorageEntry.isPrivate()) {
|
||||||
|
StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize();
|
||||||
|
mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo());
|
||||||
|
mPreferenceController.setUsedSize(cachedData.usedSize);
|
||||||
|
mPreferenceController.setTotalSize(cachedData.totalSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (mSelectedStorageEntry.isPrivate()) {
|
if (mSelectedStorageEntry.isPrivate()) {
|
||||||
mStorageInfo = null;
|
mStorageInfo = null;
|
||||||
mAppsResult = null;
|
mAppsResult = null;
|
||||||
maybeSetLoading(isQuotaSupported());
|
// Hide the loading spinner if there is cached data.
|
||||||
|
if (mStorageCacheHelper.hasCachedSizeInfo()) {
|
||||||
// To prevent flicker, sets null volume to hide category preferences.
|
//TODO(b/220259287): apply cache mechanism to secondary user
|
||||||
// onReceivedSizes will setVolume with the volume of selected storage.
|
mPreferenceController.onLoadFinished(mAppsResult, mUserId);
|
||||||
mPreferenceController.setVolume(null);
|
} else {
|
||||||
|
maybeSetLoading(isQuotaSupported());
|
||||||
|
// To prevent flicker, sets null volume to hide category preferences.
|
||||||
|
// onReceivedSizes will setVolume with the volume of selected storage.
|
||||||
|
mPreferenceController.setVolume(null);
|
||||||
|
}
|
||||||
// Stats data is only available on private volumes.
|
// Stats data is only available on private volumes.
|
||||||
getLoaderManager().restartLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
|
getLoaderManager().restartLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
|
||||||
getLoaderManager()
|
getLoaderManager()
|
||||||
@@ -277,6 +292,16 @@ public class StorageDashboardFragment extends DashboardFragment
|
|||||||
|
|
||||||
initializePreference();
|
initializePreference();
|
||||||
initializeOptionsMenu(activity);
|
initializeOptionsMenu(activity);
|
||||||
|
|
||||||
|
if (mStorageCacheHelper.hasCachedSizeInfo()) {
|
||||||
|
mIsLoadedFromCache = true;
|
||||||
|
mStorageEntries.clear();
|
||||||
|
mStorageEntries.addAll(
|
||||||
|
StorageUtils.getAllStorageEntries(getContext(), mStorageManager));
|
||||||
|
refreshUi();
|
||||||
|
updateSecondaryUserControllers(mSecondaryUsers, mAppsResult);
|
||||||
|
setSecondaryUsersVisible(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializePreference() {
|
private void initializePreference() {
|
||||||
@@ -291,6 +316,7 @@ public class StorageDashboardFragment extends DashboardFragment
|
|||||||
mUserManager = context.getSystemService(UserManager.class);
|
mUserManager = context.getSystemService(UserManager.class);
|
||||||
mIsWorkProfile = false;
|
mIsWorkProfile = false;
|
||||||
mUserId = UserHandle.myUserId();
|
mUserId = UserHandle.myUserId();
|
||||||
|
mStorageCacheHelper = new StorageCacheHelper(getContext(), mUserId);
|
||||||
|
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
use(AutomaticStorageManagementSwitchPreferenceController.class).setFragmentManager(
|
use(AutomaticStorageManagementSwitchPreferenceController.class).setFragmentManager(
|
||||||
@@ -323,9 +349,14 @@ public class StorageDashboardFragment extends DashboardFragment
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
mStorageEntries.clear();
|
if (mIsLoadedFromCache) {
|
||||||
mStorageEntries.addAll(StorageUtils.getAllStorageEntries(getContext(), mStorageManager));
|
mIsLoadedFromCache = false;
|
||||||
refreshUi();
|
} else {
|
||||||
|
mStorageEntries.clear();
|
||||||
|
mStorageEntries.addAll(
|
||||||
|
StorageUtils.getAllStorageEntries(getContext(), mStorageManager));
|
||||||
|
refreshUi();
|
||||||
|
}
|
||||||
mStorageManager.registerListener(mStorageEventListener);
|
mStorageManager.registerListener(mStorageEventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,6 +364,11 @@ public class StorageDashboardFragment extends DashboardFragment
|
|||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mStorageManager.unregisterListener(mStorageEventListener);
|
mStorageManager.unregisterListener(mStorageEventListener);
|
||||||
|
// Destroy the data loaders to prevent unnecessary data loading when switching back to the
|
||||||
|
// page.
|
||||||
|
getLoaderManager().destroyLoader(STORAGE_JOB_ID);
|
||||||
|
getLoaderManager().destroyLoader(ICON_JOB_ID);
|
||||||
|
getLoaderManager().destroyLoader(VOLUME_SIZE_JOB_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -359,6 +395,8 @@ public class StorageDashboardFragment extends DashboardFragment
|
|||||||
mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo());
|
mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo());
|
||||||
mPreferenceController.setUsedSize(privateUsedBytes);
|
mPreferenceController.setUsedSize(privateUsedBytes);
|
||||||
mPreferenceController.setTotalSize(mStorageInfo.totalBytes);
|
mPreferenceController.setTotalSize(mStorageInfo.totalBytes);
|
||||||
|
// Cache total size and used size
|
||||||
|
mStorageCacheHelper.cacheTotalSizeAndUsedSize(mStorageInfo.totalBytes, privateUsedBytes);
|
||||||
for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) {
|
for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) {
|
||||||
final AbstractPreferenceController controller = mSecondaryUsers.get(i);
|
final AbstractPreferenceController controller = mSecondaryUsers.get(i);
|
||||||
if (controller instanceof SecondaryUserController) {
|
if (controller instanceof SecondaryUserController) {
|
||||||
|
@@ -66,7 +66,7 @@ public class StorageItemPreference extends Preference {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
mProgressBar.setMax(PROGRESS_MAX);
|
mProgressBar.setMax(PROGRESS_MAX);
|
||||||
mProgressBar.setProgress(mProgressPercent);
|
mProgressBar.setProgress(mProgressPercent, true /* animate */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -183,6 +183,9 @@ public class SecondaryUserController extends AbstractPreferenceController implem
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleResult(SparseArray<StorageAsyncLoader.StorageResult> stats) {
|
public void handleResult(SparseArray<StorageAsyncLoader.StorageResult> stats) {
|
||||||
|
if (stats == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final StorageAsyncLoader.StorageResult result = stats.get(getUser().id);
|
final StorageAsyncLoader.StorageResult result = stats.get(getUser().id);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
setSize(result.externalStats.totalBytes);
|
setSize(result.externalStats.totalBytes);
|
||||||
|
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class to cache and restore the storage size information.
|
||||||
|
*/
|
||||||
|
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 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";
|
||||||
|
private static final String APPS_SIZE_KEY = "apps_size_key";
|
||||||
|
private static final String GAMES_SIZE_KEY = "games_size_key";
|
||||||
|
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 final SharedPreferences mSharedPreferences;
|
||||||
|
|
||||||
|
public StorageCacheHelper(Context context, int userId) {
|
||||||
|
String sharedPrefName = SHARED_PREFERENCE_NAME + userId;
|
||||||
|
mSharedPreferences = context.getSharedPreferences(sharedPrefName, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there's a cached size info.
|
||||||
|
*/
|
||||||
|
public boolean hasCachedSizeInfo() {
|
||||||
|
return mSharedPreferences.getAll().size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache the size info
|
||||||
|
* @param data a data about the file size info.
|
||||||
|
*/
|
||||||
|
public void cacheSizeInfo(StorageCache data) {
|
||||||
|
mSharedPreferences
|
||||||
|
.edit()
|
||||||
|
.putLong(IMAGES_SIZE_KEY, data.imagesSize)
|
||||||
|
.putLong(VIDEOS_SIZE_KEY, data.videosSize)
|
||||||
|
.putLong(AUDIO_SIZE_KEY, data.audioSize)
|
||||||
|
.putLong(APPS_SIZE_KEY, data.allAppsExceptGamesSize)
|
||||||
|
.putLong(GAMES_SIZE_KEY, data.gamesSize)
|
||||||
|
.putLong(DOCUMENTS_AND_OTHER_SIZE_KEY, data.documentsAndOtherSize)
|
||||||
|
.putLong(TRASH_SIZE_KEY, data.trashSize)
|
||||||
|
.putLong(SYSTEM_SIZE_KEY, data.systemSize)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache total size and used size
|
||||||
|
*/
|
||||||
|
public void cacheTotalSizeAndUsedSize(long totalSize, long usedSize) {
|
||||||
|
mSharedPreferences
|
||||||
|
.edit()
|
||||||
|
.putLong(TOTAL_SIZE_KEY, totalSize)
|
||||||
|
.putLong(USED_SIZE_KEY, usedSize)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.imagesSize = mSharedPreferences.getLong(IMAGES_SIZE_KEY, 0);
|
||||||
|
result.videosSize = mSharedPreferences.getLong(VIDEOS_SIZE_KEY, 0);
|
||||||
|
result.audioSize = mSharedPreferences.getLong(AUDIO_SIZE_KEY, 0);
|
||||||
|
result.allAppsExceptGamesSize = mSharedPreferences.getLong(APPS_SIZE_KEY, 0);
|
||||||
|
result.gamesSize = mSharedPreferences.getLong(GAMES_SIZE_KEY, 0);
|
||||||
|
result.documentsAndOtherSize = mSharedPreferences.getLong(DOCUMENTS_AND_OTHER_SIZE_KEY, 0);
|
||||||
|
result.trashSize = mSharedPreferences.getLong(TRASH_SIZE_KEY, 0);
|
||||||
|
result.systemSize = mSharedPreferences.getLong(SYSTEM_SIZE_KEY, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All the cached data about the file size information.
|
||||||
|
*/
|
||||||
|
public static class StorageCache {
|
||||||
|
public long totalSize;
|
||||||
|
public long usedSize;
|
||||||
|
public long gamesSize;
|
||||||
|
public long allAppsExceptGamesSize;
|
||||||
|
public long audioSize;
|
||||||
|
public long imagesSize;
|
||||||
|
public long videosSize;
|
||||||
|
public long documentsAndOtherSize;
|
||||||
|
public long trashSize;
|
||||||
|
public long systemSize;
|
||||||
|
}
|
||||||
|
}
|
@@ -34,6 +34,7 @@ import android.util.Log;
|
|||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
@@ -135,7 +136,11 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
|||||||
|
|
||||||
private boolean mIsWorkProfile;
|
private boolean mIsWorkProfile;
|
||||||
|
|
||||||
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
|
private StorageCacheHelper mStorageCacheHelper;
|
||||||
|
// The mIsDocumentsPrefShown being used here is to prevent a flicker problem from displaying
|
||||||
|
// the Document entry.
|
||||||
|
private boolean mIsDocumentsPrefShown;
|
||||||
|
private boolean mIsPreferenceOrderedBySize;
|
||||||
|
|
||||||
public StorageItemPreferenceController(Context context, Fragment hostFragment,
|
public StorageItemPreferenceController(Context context, Fragment hostFragment,
|
||||||
VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
|
VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
|
||||||
@@ -148,6 +153,8 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
|||||||
mIsWorkProfile = isWorkProfile;
|
mIsWorkProfile = isWorkProfile;
|
||||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||||
mUserId = getCurrentUserId();
|
mUserId = getCurrentUserId();
|
||||||
|
mIsDocumentsPrefShown = isDocumentsPrefShown();
|
||||||
|
mStorageCacheHelper = new StorageCacheHelper(mContext, mUserId);
|
||||||
|
|
||||||
mImagesUri = Uri.parse(context.getResources()
|
mImagesUri = Uri.parse(context.getResources()
|
||||||
.getString(R.string.config_images_storage_category_uri));
|
.getString(R.string.config_images_storage_category_uri));
|
||||||
@@ -267,14 +274,17 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
|||||||
// If we don't have a shared volume for our internal storage (or the shared volume isn't
|
// If we don't have a shared volume for our internal storage (or the shared volume isn't
|
||||||
// mounted as readable for whatever reason), we should hide the File preference.
|
// mounted as readable for whatever reason), we should hide the File preference.
|
||||||
if (visible) {
|
if (visible) {
|
||||||
final VolumeInfo sharedVolume = mSvp.findEmulatedForPrivate(mVolume);
|
mDocumentsAndOtherPreference.setVisible(mIsDocumentsPrefShown);
|
||||||
mDocumentsAndOtherPreference.setVisible(sharedVolume != null
|
|
||||||
&& sharedVolume.isMountedReadable());
|
|
||||||
} else {
|
} else {
|
||||||
mDocumentsAndOtherPreference.setVisible(false);
|
mDocumentsAndOtherPreference.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isDocumentsPrefShown() {
|
||||||
|
VolumeInfo sharedVolume = mSvp.findEmulatedForPrivate(mVolume);
|
||||||
|
return sharedVolume != null && sharedVolume.isMountedReadable();
|
||||||
|
}
|
||||||
|
|
||||||
private void updatePrivateStorageCategoryPreferencesOrder() {
|
private void updatePrivateStorageCategoryPreferencesOrder() {
|
||||||
if (mScreen == null || !isValidPrivateVolume()) {
|
if (mScreen == null || !isValidPrivateVolume()) {
|
||||||
return;
|
return;
|
||||||
@@ -360,44 +370,74 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
|||||||
mTrashPreference = screen.findPreference(TRASH_KEY);
|
mTrashPreference = screen.findPreference(TRASH_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fragments use it to set storage result and update UI of this controller. */
|
/**
|
||||||
public void onLoadFinished(SparseArray<StorageAsyncLoader.StorageResult> result, int userId) {
|
* Fragments use it to set storage result and update UI of this controller.
|
||||||
final StorageAsyncLoader.StorageResult data = result.get(userId);
|
* @param result The StorageResult from StorageAsyncLoader. This allows a nullable result.
|
||||||
|
* When it's null, the cached storage size info will be used instead.
|
||||||
mImagesPreference.setStorageSize(data.imagesSize, mTotalSize);
|
* @param userId User ID to get the storage size info
|
||||||
mVideosPreference.setStorageSize(data.videosSize, mTotalSize);
|
*/
|
||||||
mAudioPreference.setStorageSize(data.audioSize, mTotalSize);
|
public void onLoadFinished(@Nullable SparseArray<StorageAsyncLoader.StorageResult> result,
|
||||||
mAppsPreference.setStorageSize(data.allAppsExceptGamesSize, mTotalSize);
|
int userId) {
|
||||||
mGamesPreference.setStorageSize(data.gamesSize, mTotalSize);
|
// Calculate the size info for each category
|
||||||
mDocumentsAndOtherPreference.setStorageSize(data.documentsAndOtherSize, mTotalSize);
|
StorageCacheHelper.StorageCache storageCache = getSizeInfo(result, userId);
|
||||||
mTrashPreference.setStorageSize(data.trashSize, mTotalSize);
|
// Set size info to each preference
|
||||||
|
mImagesPreference.setStorageSize(storageCache.imagesSize, mTotalSize);
|
||||||
|
mVideosPreference.setStorageSize(storageCache.videosSize, mTotalSize);
|
||||||
|
mAudioPreference.setStorageSize(storageCache.audioSize, mTotalSize);
|
||||||
|
mAppsPreference.setStorageSize(storageCache.allAppsExceptGamesSize, mTotalSize);
|
||||||
|
mGamesPreference.setStorageSize(storageCache.gamesSize, mTotalSize);
|
||||||
|
mDocumentsAndOtherPreference.setStorageSize(storageCache.documentsAndOtherSize, mTotalSize);
|
||||||
|
mTrashPreference.setStorageSize(storageCache.trashSize, mTotalSize);
|
||||||
if (mSystemPreference != null) {
|
if (mSystemPreference != null) {
|
||||||
// Everything else that hasn't already been attributed is tracked as
|
mSystemPreference.setStorageSize(storageCache.systemSize, mTotalSize);
|
||||||
// belonging to system.
|
}
|
||||||
long attributedSize = 0;
|
// Cache the size info
|
||||||
for (int i = 0; i < result.size(); i++) {
|
if (result != null) {
|
||||||
final StorageAsyncLoader.StorageResult otherData = result.valueAt(i);
|
mStorageCacheHelper.cacheSizeInfo(storageCache);
|
||||||
attributedSize +=
|
|
||||||
otherData.gamesSize
|
|
||||||
+ otherData.audioSize
|
|
||||||
+ otherData.videosSize
|
|
||||||
+ otherData.imagesSize
|
|
||||||
+ otherData.documentsAndOtherSize
|
|
||||||
+ otherData.trashSize
|
|
||||||
+ otherData.allAppsExceptGamesSize;
|
|
||||||
attributedSize -= otherData.duplicateCodeSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
final long systemSize = Math.max(DataUnit.GIBIBYTES.toBytes(1),
|
|
||||||
mUsedBytes - attributedSize);
|
|
||||||
mSystemPreference.setStorageSize(systemSize, mTotalSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePrivateStorageCategoryPreferencesOrder();
|
// Sort the preference according to size info in descending order
|
||||||
|
if (!mIsPreferenceOrderedBySize) {
|
||||||
|
updatePrivateStorageCategoryPreferencesOrder();
|
||||||
|
mIsPreferenceOrderedBySize = true;
|
||||||
|
}
|
||||||
setPrivateStorageCategoryPreferencesVisibility(true);
|
setPrivateStorageCategoryPreferencesVisibility(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private StorageCacheHelper.StorageCache getSizeInfo(
|
||||||
|
SparseArray<StorageAsyncLoader.StorageResult> result, int userId) {
|
||||||
|
if (result == null) {
|
||||||
|
return mStorageCacheHelper.retrieveCachedSize();
|
||||||
|
}
|
||||||
|
StorageAsyncLoader.StorageResult data = result.get(userId);
|
||||||
|
StorageCacheHelper.StorageCache storageCache = new StorageCacheHelper.StorageCache();
|
||||||
|
storageCache.imagesSize = data.imagesSize;
|
||||||
|
storageCache.videosSize = data.videosSize;
|
||||||
|
storageCache.audioSize = data.audioSize;
|
||||||
|
storageCache.allAppsExceptGamesSize = data.allAppsExceptGamesSize;
|
||||||
|
storageCache.gamesSize = data.gamesSize;
|
||||||
|
storageCache.documentsAndOtherSize = data.documentsAndOtherSize;
|
||||||
|
storageCache.trashSize = data.trashSize;
|
||||||
|
// Everything else that hasn't already been attributed is tracked as
|
||||||
|
// belonging to system.
|
||||||
|
long attributedSize = 0;
|
||||||
|
for (int i = 0; i < result.size(); i++) {
|
||||||
|
final StorageAsyncLoader.StorageResult otherData = result.valueAt(i);
|
||||||
|
attributedSize +=
|
||||||
|
otherData.gamesSize
|
||||||
|
+ otherData.audioSize
|
||||||
|
+ otherData.videosSize
|
||||||
|
+ otherData.imagesSize
|
||||||
|
+ otherData.documentsAndOtherSize
|
||||||
|
+ otherData.trashSize
|
||||||
|
+ otherData.allAppsExceptGamesSize;
|
||||||
|
attributedSize -= otherData.duplicateCodeSize;
|
||||||
|
}
|
||||||
|
storageCache.systemSize = Math.max(DataUnit.GIBIBYTES.toBytes(1),
|
||||||
|
mUsedBytes - attributedSize);
|
||||||
|
return storageCache;
|
||||||
|
}
|
||||||
|
|
||||||
public void setUsedSize(long usedSizeBytes) {
|
public void setUsedSize(long usedSizeBytes) {
|
||||||
mUsedBytes = usedSizeBytes;
|
mUsedBytes = usedSizeBytes;
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@ package com.android.settings.deviceinfo.storage;
|
|||||||
|
|
||||||
import android.app.usage.StorageStatsManager;
|
import android.app.usage.StorageStatsManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
@@ -47,11 +48,13 @@ public class StorageUsageProgressBarPreferenceController extends BasePreferenceC
|
|||||||
private UsageProgressBarPreference mUsageProgressBarPreference;
|
private UsageProgressBarPreference mUsageProgressBarPreference;
|
||||||
private StorageEntry mStorageEntry;
|
private StorageEntry mStorageEntry;
|
||||||
boolean mIsUpdateStateFromSelectedStorageEntry;
|
boolean mIsUpdateStateFromSelectedStorageEntry;
|
||||||
|
private StorageCacheHelper mStorageCacheHelper;
|
||||||
|
|
||||||
public StorageUsageProgressBarPreferenceController(Context context, String key) {
|
public StorageUsageProgressBarPreferenceController(Context context, String key) {
|
||||||
super(context, key);
|
super(context, key);
|
||||||
|
|
||||||
mStorageStatsManager = context.getSystemService(StorageStatsManager.class);
|
mStorageStatsManager = context.getSystemService(StorageStatsManager.class);
|
||||||
|
mStorageCacheHelper = new StorageCacheHelper(context, UserHandle.myUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set StorageEntry to display. */
|
/** Set StorageEntry to display. */
|
||||||
@@ -71,6 +74,15 @@ public class StorageUsageProgressBarPreferenceController extends BasePreferenceC
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void getStorageStatsAndUpdateUi() {
|
private void getStorageStatsAndUpdateUi() {
|
||||||
|
// Use cached data for both total size and used size.
|
||||||
|
if (mStorageEntry != null && mStorageEntry.isMounted() && mStorageEntry.isPrivate()) {
|
||||||
|
StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize();
|
||||||
|
mTotalBytes = cachedData.totalSize;
|
||||||
|
mUsedBytes = cachedData.usedSize;
|
||||||
|
mIsUpdateStateFromSelectedStorageEntry = true;
|
||||||
|
updateState(mUsageProgressBarPreference);
|
||||||
|
}
|
||||||
|
// Get the latest data from StorageStatsManager.
|
||||||
ThreadUtils.postOnBackgroundThread(() -> {
|
ThreadUtils.postOnBackgroundThread(() -> {
|
||||||
try {
|
try {
|
||||||
if (mStorageEntry == null || !mStorageEntry.isMounted()) {
|
if (mStorageEntry == null || !mStorageEntry.isMounted()) {
|
||||||
|
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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 android.content.Context;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class StorageCacheHelperTest {
|
||||||
|
private static final long FAKE_IMAGES_SIZE = 7000L;
|
||||||
|
private static final long FAKE_VIDEOS_SIZE = 8900L;
|
||||||
|
private static final long FAKE_AUDIO_SIZE = 3500L;
|
||||||
|
private static final long FAKE_APPS_SIZE = 4000L;
|
||||||
|
private static final long FAKE_GAMES_SIZE = 5000L;
|
||||||
|
private static final long FAKE_DOCS_SIZE = 1500L;
|
||||||
|
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 Context mContext;
|
||||||
|
private StorageCacheHelper mHelper;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
mHelper = new StorageCacheHelper(mContext, UserHandle.myUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasCachedSizeInfo_noCacheData_shouldReturnFalse() {
|
||||||
|
assertThat(mHelper.hasCachedSizeInfo()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasCachedSizeInfo_hasCacheData_shouldReturnTrue() {
|
||||||
|
mHelper.cacheSizeInfo(getFakeStorageCache());
|
||||||
|
|
||||||
|
assertThat(mHelper.hasCachedSizeInfo()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void cacheSizeInfo_shouldSaveToSharedPreference() {
|
||||||
|
mHelper.cacheSizeInfo(getFakeStorageCache());
|
||||||
|
|
||||||
|
StorageCacheHelper.StorageCache storageCache = mHelper.retrieveCachedSize();
|
||||||
|
|
||||||
|
assertThat(storageCache.imagesSize).isEqualTo(FAKE_IMAGES_SIZE);
|
||||||
|
assertThat(storageCache.totalSize).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void cacheTotalSizeAndUsedSize_shouldSaveToSharedPreference() {
|
||||||
|
mHelper.cacheTotalSizeAndUsedSize(FAKE_TOTAL_SIZE, FAKE_USED_SIZE);
|
||||||
|
|
||||||
|
StorageCacheHelper.StorageCache storageCache = mHelper.retrieveCachedSize();
|
||||||
|
|
||||||
|
assertThat(storageCache.totalSize).isEqualTo(FAKE_TOTAL_SIZE);
|
||||||
|
assertThat(storageCache.usedSize).isEqualTo(FAKE_USED_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StorageCacheHelper.StorageCache getFakeStorageCache() {
|
||||||
|
StorageCacheHelper.StorageCache result = new StorageCacheHelper.StorageCache();
|
||||||
|
result.trashSize = FAKE_TRASH_SIZE;
|
||||||
|
result.systemSize = FAKE_SYSTEM_SIZE;
|
||||||
|
result.imagesSize = FAKE_IMAGES_SIZE;
|
||||||
|
result.documentsAndOtherSize = FAKE_DOCS_SIZE;
|
||||||
|
result.audioSize = FAKE_AUDIO_SIZE;
|
||||||
|
result.gamesSize = FAKE_GAMES_SIZE;
|
||||||
|
result.videosSize = FAKE_VIDEOS_SIZE;
|
||||||
|
result.allAppsExceptGamesSize = FAKE_APPS_SIZE;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user