diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java index 2a5ac17bc16..57f73455d30 100644 --- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java +++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java @@ -18,6 +18,7 @@ package com.android.settings.deviceinfo; 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.os.storage.VolumeInfo; 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.StorageAsyncLoader; 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 @@ public class StorageDashboardFragment extends DashboardFragment 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 mAppsResult; private StorageSummaryDonutPreferenceController mSummaryController; private StorageItemPreferenceController mPreferenceController; @@ -81,29 +88,6 @@ public class StorageDashboardFragment extends DashboardFragment } 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 @@ -115,11 +99,41 @@ public class StorageDashboardFragment extends DashboardFragment activity.invalidateOptionsMenu(); } + @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 @@ public class StorageDashboardFragment extends DashboardFragment @Override public void onLoadFinished(Loader> loader, SparseArray data) { - mPreferenceController.onLoadFinished(data.get(UserHandle.myUserId())); - updateSecondaryUserControllers(mSecondaryUsers, data); + mAppsResult = data; + onReceivedSizes(); } @Override @@ -260,4 +274,31 @@ public class StorageDashboardFragment extends DashboardFragment @Override public void onLoaderReset(Loader> loader) {} } + + public final class VolumeSizeCallbacks + implements LoaderManager.LoaderCallbacks { + @Override + public Loader 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 loader) {} + + @Override + public void onLoadFinished( + Loader 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 890d99e2845..91c4a6b523b 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java +++ b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java @@ -34,6 +34,7 @@ import com.android.settingslib.deviceinfo.StorageVolumeProvider; public class StorageSummaryDonutPreferenceController extends PreferenceController { private long mUsedBytes; private long mTotalBytes; + private StorageSummaryDonutPreference mSummary; public StorageSummaryDonutPreferenceController(Context context) { super(context); @@ -41,9 +42,8 @@ public class StorageSummaryDonutPreferenceController extends PreferenceControlle @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 @@ public class StorageSummaryDonutPreferenceController extends PreferenceControlle 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 class StorageSummaryDonutPreferenceController extends PreferenceControlle 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 00000000000..720f1512b59 --- /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 { + 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 00000000000..3f9ccaf1009 --- /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); + } +}