Make the storage free/total sizes consistent.
We were using a different calculation in the top level view compared to
within the Storage settings. Technically, both are correct (one of them
is aware that we're considering cache as free, one does not). This patch
aligns us on the cache as free strategy.
Change-Id: I9ac26683a4d2a30b77a1da534aa2ddd3d4da6657
Fixes: 37175551
Test: Settings robotest
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 2a5ac17..57f7345 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -18,6 +18,7 @@
import android.app.Activity;
import android.app.LoaderManager;
+import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.content.Loader;
import android.graphics.drawable.Drawable;
@@ -29,6 +30,7 @@
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
import android.util.SparseArray;
+import android.view.View;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -44,9 +46,11 @@
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
import com.android.settings.deviceinfo.storage.UserIconLoader;
+import com.android.settings.deviceinfo.storage.VolumeSizesLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
import java.util.ArrayList;
@@ -58,9 +62,12 @@
private static final String TAG = "StorageDashboardFrag";
private static final int STORAGE_JOB_ID = 0;
private static final int ICON_JOB_ID = 1;
+ private static final int VOLUME_SIZE_JOB_ID = 2;
private static final int OPTIONS_MENU_MIGRATE_DATA = 100;
private VolumeInfo mVolume;
+ private PrivateStorageInfo mStorageInfo;
+ private SparseArray<StorageAsyncLoader.AppsStorageResult> mAppsResult;
private StorageSummaryDonutPreferenceController mSummaryController;
private StorageItemPreferenceController mPreferenceController;
@@ -81,29 +88,6 @@
}
initializeOptionsMenu(activity);
-
- final long sharedDataSize = mVolume.getPath().getTotalSpace();
- long totalSize = sm.getPrimaryStorageSize();
- long systemSize = totalSize - sharedDataSize;
-
- if (totalSize <= 0) {
- totalSize = sharedDataSize;
- systemSize = 0;
- }
-
- final long usedBytes = totalSize - mVolume.getPath().getFreeSpace();
- mSummaryController.updateBytes(usedBytes, totalSize);
- mPreferenceController.setVolume(mVolume);
- mPreferenceController.setUsedSize(usedBytes);
- mPreferenceController.setTotalSize(totalSize);
- for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) {
- PreferenceController controller = mSecondaryUsers.get(i);
- if (controller instanceof SecondaryUserController) {
- SecondaryUserController userController = (SecondaryUserController) controller;
- userController.setTotalSize(totalSize);
-
- }
- }
}
@VisibleForTesting
@@ -116,10 +100,40 @@
}
@Override
+ public void onViewCreated(View v, Bundle savedInstanceState) {
+ super.onViewCreated(v, savedInstanceState);
+ setLoading(true, false);
+ }
+
+ @Override
public void onResume() {
super.onResume();
getLoaderManager().restartLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
getLoaderManager().initLoader(ICON_JOB_ID, Bundle.EMPTY, new IconLoaderCallbacks());
+ getLoaderManager().initLoader(VOLUME_SIZE_JOB_ID, Bundle.EMPTY, new VolumeSizeCallbacks());
+ }
+
+ private void onReceivedSizes() {
+ if (mStorageInfo == null || mAppsResult == null) {
+ return;
+ }
+
+ long privateUsedBytes = mStorageInfo.totalBytes - mStorageInfo.freeBytes;
+ mSummaryController.updateBytes(privateUsedBytes, mStorageInfo.totalBytes);
+ mPreferenceController.setVolume(mVolume);
+ mPreferenceController.setUsedSize(privateUsedBytes);
+ mPreferenceController.setTotalSize(mStorageInfo.totalBytes);
+ for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) {
+ PreferenceController controller = mSecondaryUsers.get(i);
+ if (controller instanceof SecondaryUserController) {
+ SecondaryUserController userController = (SecondaryUserController) controller;
+ userController.setTotalSize(mStorageInfo.totalBytes);
+ }
+ }
+
+ mPreferenceController.onLoadFinished(mAppsResult.get(UserHandle.myUserId()));
+ updateSecondaryUserControllers(mSecondaryUsers, mAppsResult);
+ setLoading(false, true);
}
@Override
@@ -224,8 +238,8 @@
@Override
public void onLoadFinished(Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> loader,
SparseArray<StorageAsyncLoader.AppsStorageResult> data) {
- mPreferenceController.onLoadFinished(data.get(UserHandle.myUserId()));
- updateSecondaryUserControllers(mSecondaryUsers, data);
+ mAppsResult = data;
+ onReceivedSizes();
}
@Override
@@ -260,4 +274,31 @@
@Override
public void onLoaderReset(Loader<SparseArray<Drawable>> loader) {}
}
+
+ public final class VolumeSizeCallbacks
+ implements LoaderManager.LoaderCallbacks<PrivateStorageInfo> {
+ @Override
+ public Loader<PrivateStorageInfo> onCreateLoader(int id, Bundle args) {
+ Context context = getContext();
+ StorageManager sm = context.getSystemService(StorageManager.class);
+ StorageManagerVolumeProvider smvp = new StorageManagerVolumeProvider(sm);
+ final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
+ return new VolumeSizesLoader(context, smvp, stats, mVolume);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<PrivateStorageInfo> loader) {}
+
+ @Override
+ public void onLoadFinished(
+ Loader<PrivateStorageInfo> loader, PrivateStorageInfo privateStorageInfo) {
+ if (privateStorageInfo == null) {
+ getActivity().finish();
+ return;
+ }
+
+ mStorageInfo = privateStorageInfo;
+ onReceivedSizes();
+ }
+ }
}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
index 890d99e..91c4a6b 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
@@ -34,6 +34,7 @@
public class StorageSummaryDonutPreferenceController extends PreferenceController {
private long mUsedBytes;
private long mTotalBytes;
+ private StorageSummaryDonutPreference mSummary;
public StorageSummaryDonutPreferenceController(Context context) {
super(context);
@@ -41,9 +42,8 @@
@Override
public void displayPreference(PreferenceScreen screen) {
- StorageSummaryDonutPreference summary = (StorageSummaryDonutPreference)
- screen.findPreference("pref_summary");
- summary.setEnabled(true);
+ mSummary = (StorageSummaryDonutPreference) screen.findPreference("pref_summary");
+ mSummary.setEnabled(true);
}
@Override
@@ -61,6 +61,13 @@
summary.setEnabled(true);
}
+ /** Invalidates the data on the view and re-renders. */
+ public void invalidateData() {
+ if (mSummary != null) {
+ updateState(mSummary);
+ }
+ }
+
@Override
public boolean isAvailable() {
return true;
@@ -79,6 +86,7 @@
public void updateBytes(long used, long total) {
mUsedBytes = used;
mTotalBytes = total;
+ invalidateData();
}
/**
diff --git a/src/com/android/settings/deviceinfo/storage/VolumeSizesLoader.java b/src/com/android/settings/deviceinfo/storage/VolumeSizesLoader.java
new file mode 100644
index 0000000..720f151
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/storage/VolumeSizesLoader.java
@@ -0,0 +1,68 @@
+/*
+ * 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.app.usage.StorageStatsManager;
+import android.content.Context;
+import android.os.storage.VolumeInfo;
+import android.support.annotation.VisibleForTesting;
+
+import com.android.settings.utils.AsyncLoader;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+import com.android.settingslib.deviceinfo.StorageVolumeProvider;
+
+import java.io.IOException;
+
+public class VolumeSizesLoader extends AsyncLoader<PrivateStorageInfo> {
+ private StorageVolumeProvider mVolumeProvider;
+ private StorageStatsManager mStats;
+ private VolumeInfo mVolume;
+
+ public VolumeSizesLoader(
+ Context context,
+ StorageVolumeProvider volumeProvider,
+ StorageStatsManager stats,
+ VolumeInfo volume) {
+ super(context);
+ mVolumeProvider = volumeProvider;
+ mStats = stats;
+ mVolume = volume;
+ }
+
+ @Override
+ protected void onDiscardResult(PrivateStorageInfo result) {}
+
+ @Override
+ public PrivateStorageInfo loadInBackground() {
+ PrivateStorageInfo volumeSizes;
+ try {
+ volumeSizes = getVolumeSize(mVolumeProvider, mStats, mVolume);
+ } catch (IOException e) {
+ return null;
+ }
+ return volumeSizes;
+ }
+
+ @VisibleForTesting
+ static PrivateStorageInfo getVolumeSize(
+ StorageVolumeProvider storageVolumeProvider, StorageStatsManager stats, VolumeInfo info)
+ throws IOException {
+ long privateTotalBytes = storageVolumeProvider.getTotalBytes(stats, info);
+ long privateFreeBytes = storageVolumeProvider.getFreeBytes(stats, info);
+ return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/VolumeSizesLoaderTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/VolumeSizesLoaderTest.java
new file mode 100644
index 0000000..3f9ccaf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/VolumeSizesLoaderTest.java
@@ -0,0 +1,30 @@
+package com.android.settings.deviceinfo.storage;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.os.storage.VolumeInfo;
+
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+import com.android.settingslib.deviceinfo.StorageVolumeProvider;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+
+public class VolumeSizesLoaderTest {
+ @Test
+ public void getVolumeSize_getsValidSizes() throws Exception {
+ VolumeInfo info = mock(VolumeInfo.class);
+ StorageVolumeProvider storageVolumeProvider = mock(StorageVolumeProvider.class);
+ when(storageVolumeProvider.getTotalBytes(any(), any())).thenReturn(10000L);
+ when(storageVolumeProvider.getFreeBytes(any(), any())).thenReturn(1000L);
+
+ PrivateStorageInfo storageInfo =
+ VolumeSizesLoader.getVolumeSize(storageVolumeProvider, null, info);
+
+ assertThat(storageInfo.freeBytes).isEqualTo(1000L);
+ assertThat(storageInfo.totalBytes).isEqualTo(10000L);
+ }
+}