Hook up the storage item preferences to actual data.
This uses the same storage query implementation as the previous
iteration of the Storage Settings. In b/32206268, a new API for
querying this information will be added for querying this info.
Once the new API has landed, a future patch will swap out the
impl, but this should work for today.
Bug: 33199077
Test: Settings Robo Tests
Change-Id: I58763e8ee38aabbea533bc614268288e854ff8d4
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index abefce6..efcf479 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -81,6 +81,8 @@
final long usedBytes = mTotalSize - mVolume.getPath().getFreeSpace();
mSummaryController.updateBytes(usedBytes, mTotalSize);
mPreferenceController.setVolume(mVolume);
+ mPreferenceController.setSystemSize(systemSize);
+ mPreferenceController.startMeasurement();
// Initialize the footer preference to go to the smart storage management.
final FooterPreference pref = mFooterPreferenceMixin.createFooterPreference();
@@ -119,8 +121,8 @@
controllers.add(mSummaryController);
StorageManager sm = context.getSystemService(StorageManager.class);
- mPreferenceController = new StorageItemPreferenceController(context, this, mVolume,
- new StorageManagerVolumeProvider(sm));
+ mPreferenceController = new StorageItemPreferenceController(context, getLifecycle(), this,
+ mVolume, new StorageManagerVolumeProvider(sm));
controllers.add(mPreferenceController);
controllers.add(new ManageStoragePreferenceController(context));
return controllers;
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 3e802fd..dce8a25 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -21,11 +21,14 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.os.Environment;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
+import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import com.android.settings.R;
@@ -33,24 +36,56 @@
import com.android.settings.Utils;
import com.android.settings.applications.ManageApplications;
import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnDestroy;
+import com.android.settings.deviceinfo.StorageItemPreference;
+import com.android.settingslib.deviceinfo.StorageMeasurement;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
+import java.util.HashMap;
+
/**
* StorageItemPreferenceController handles the storage line items which summarize the storage
* categorization breakdown.
*/
-public class StorageItemPreferenceController extends PreferenceController {
+public class StorageItemPreferenceController extends PreferenceController
+ implements StorageMeasurement.MeasurementReceiver, LifecycleObserver, OnDestroy {
private static final String TAG = "StorageItemPreference";
+
+ @VisibleForTesting
+ static final String PHOTO_KEY = "pref_photos_videos";
+ @VisibleForTesting
+ static final String AUDIO_KEY = "pref_music_audio";
+ @VisibleForTesting
+ static final String GAME_KEY = "pref_games";
+ @VisibleForTesting
+ static final String OTHER_APPS_KEY = "pref_other_apps";
+ @VisibleForTesting
+ static final String SYSTEM_KEY = "pref_system";
+ @VisibleForTesting
+ static final String FILES_KEY = "pref_files";
+
private final Fragment mFragment;
private final StorageVolumeProvider mSvp;
private VolumeInfo mVolume;
private final int mUserId;
+ private StorageMeasurement mMeasure;
+ private long mSystemSize;
+ private long mUsedSize;
+
+ private StorageItemPreferenceAlternate mPhotoPreference;
+ private StorageItemPreferenceAlternate mAudioPreference;
+ private StorageItemPreferenceAlternate mGamePreference;
+ private StorageItemPreferenceAlternate mAppPreference;
+ private StorageItemPreferenceAlternate mFilePreference;
+ private StorageItemPreferenceAlternate mSystemPreference;
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
- public StorageItemPreferenceController(Context context, Fragment hostFragment,
- VolumeInfo volume, StorageVolumeProvider svp) {
+ public StorageItemPreferenceController(Context context, Lifecycle lifecycle,
+ Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp) {
super(context);
mFragment = hostFragment;
mVolume = volume;
@@ -58,6 +93,10 @@
UserManager um = mContext.getSystemService(UserManager.class);
mUserId = um.getUserHandle();
+
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
}
@Override
@@ -75,15 +114,15 @@
// After the intermediate views are built, swap them in.
Intent intent = null;
switch (preference.getKey()) {
- case "pref_photos_videos":
+ case PHOTO_KEY:
intent = getPhotosIntent();
break;
- case "pref_music_audio":
+ case AUDIO_KEY:
intent = getAudioIntent();
break;
- case "pref_games":
+ case GAME_KEY:
// TODO: Once app categorization is added, make this section.
- case "pref_other_apps":
+ case OTHER_APPS_KEY:
// Because we are likely constructed with a null volume, this is theoretically
// possible.
if (mVolume == null) {
@@ -91,7 +130,7 @@
}
intent = getAppsIntent();
break;
- case "pref_files":
+ case FILES_KEY:
intent = getFilesIntent();
break;
}
@@ -118,6 +157,81 @@
mVolume = volume;
}
+ @Override
+ public void onDetailsChanged(StorageMeasurement.MeasurementDetails details) {
+ final long imagesSize = totalValues(details, mUserId,
+ Environment.DIRECTORY_DCIM,
+ Environment.DIRECTORY_PICTURES,
+ Environment.DIRECTORY_MOVIES);
+ if (mPhotoPreference != null) {
+ mPhotoPreference.setStorageSize(imagesSize);
+ }
+
+ final long audioSize = totalValues(details, mUserId,
+ Environment.DIRECTORY_MUSIC,
+ Environment.DIRECTORY_ALARMS,
+ Environment.DIRECTORY_NOTIFICATIONS,
+ Environment.DIRECTORY_RINGTONES,
+ Environment.DIRECTORY_PODCASTS);
+ if (mAudioPreference != null) {
+ mAudioPreference.setStorageSize(audioSize);
+ }
+
+ if (mGamePreference != null) {
+ mGamePreference.setStorageSize(0);
+ }
+
+ final long appSize = details.appsSize.get(mUserId);
+ if (mAppPreference != null) {
+ mAppPreference.setStorageSize(appSize);
+ }
+
+ if (mSystemPreference != null) {
+ mSystemPreference.setStorageSize(mSystemSize);
+ }
+
+ final long downloadsSize = totalValues(details, mUserId, Environment.DIRECTORY_DOWNLOADS);
+ final long miscSize = details.miscSize.get(mUserId);
+ if (mFilePreference != null) {
+ mFilePreference.setStorageSize(downloadsSize + miscSize);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mMeasure != null) {
+ mMeasure.onDestroy();
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mPhotoPreference = (StorageItemPreferenceAlternate) screen.findPreference(PHOTO_KEY);
+ mAudioPreference = (StorageItemPreferenceAlternate) screen.findPreference(AUDIO_KEY);
+ mGamePreference = (StorageItemPreferenceAlternate) screen.findPreference(GAME_KEY);
+ mAppPreference = (StorageItemPreferenceAlternate) screen.findPreference(OTHER_APPS_KEY);
+ mSystemPreference = (StorageItemPreferenceAlternate) screen.findPreference(SYSTEM_KEY);
+ mFilePreference = (StorageItemPreferenceAlternate) screen.findPreference(FILES_KEY);
+ }
+
+ /**
+ * Begins an asynchronous storage measurement task for the preferences.
+ */
+ public void startMeasurement() {
+ //TODO: When the GID-based measurement system is completed, swap in the GID impl.
+ mMeasure = new StorageMeasurement(mContext, mVolume, mSvp.findEmulatedForPrivate(mVolume));
+ mMeasure.setReceiver(this);
+ mMeasure.forceMeasure();
+ }
+
+ /**
+ * Sets the system size for the system size preference.
+ * @param systemSize the size of the system in bytes
+ */
+ public void setSystemSize(long systemSize) {
+ mSystemSize = systemSize;
+ }
+
private Intent getPhotosIntent() {
Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "images_root"));
@@ -160,4 +274,20 @@
Log.w(TAG, "No activity found for " + intent);
}
}
+
+ private static long totalValues(StorageMeasurement.MeasurementDetails details, int userId,
+ String... keys) {
+ long total = 0;
+ HashMap<String, Long> map = details.mediaSize.get(userId);
+ if (map != null) {
+ for (String key : keys) {
+ if (map.containsKey(key)) {
+ total += map.get(key);
+ }
+ }
+ } else {
+ Log.w(TAG, "MeasurementDetails mediaSize array does not have key for user " + userId);
+ }
+ return total;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 19936c4..b0c0b44 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -18,16 +18,20 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
+import android.os.Environment;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
+import android.support.v7.preference.PreferenceScreen;
import android.view.LayoutInflater;
+import android.view.View;
import android.widget.LinearLayout;
import com.android.settings.R;
@@ -36,6 +40,7 @@
import com.android.settings.SubSettings;
import com.android.settings.TestConfig;
import com.android.settings.applications.ManageApplications;
+import com.android.settingslib.deviceinfo.StorageMeasurement;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
import org.junit.Before;
@@ -44,13 +49,22 @@
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import java.util.HashMap;
+
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class StorageItemPreferenceControllerTest {
+ /**
+ * In O, this will change to 1000 instead of 1024 due to the formatter properly defining a
+ * kilobyte.
+ */
+ private static long KILOBYTE = 1024L;
+
private Context mContext;
private VolumeInfo mVolume;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -65,12 +79,15 @@
MockitoAnnotations.initMocks(this);
mVolume = new VolumeInfo("id", 0, null, "id");
mContext = RuntimeEnvironment.application;
- mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp);
+ // Note: null is passed as the Lifecycle because we are handling it outside of the normal
+ // Settings fragment lifecycle for test purposes.
+ mController = new StorageItemPreferenceController(mContext, null, mFragment, mVolume, mSvp);
mPreference = new StorageItemPreferenceAlternate(mContext);
// Inflate the preference and the widget.
LayoutInflater inflater = LayoutInflater.from(mContext);
- inflater.inflate(mPreference.getLayoutResource(), new LinearLayout(mContext), false);
+ final View view = inflater.inflate(
+ mPreference.getLayoutResource(), new LinearLayout(mContext), false);
}
@Test
@@ -142,4 +159,46 @@
assertThat(intent.getAction()).isEqualTo(browseIntent.getAction());
assertThat(intent.getData()).isEqualTo(browseIntent.getData());
}
+
+ @Test
+ public void testMeasurementCompletedUpdatesPreferences() {
+ StorageItemPreferenceAlternate audio = new StorageItemPreferenceAlternate(mContext);
+ StorageItemPreferenceAlternate image = new StorageItemPreferenceAlternate(mContext);
+ StorageItemPreferenceAlternate games = new StorageItemPreferenceAlternate(mContext);
+ StorageItemPreferenceAlternate apps = new StorageItemPreferenceAlternate(mContext);
+ StorageItemPreferenceAlternate system = new StorageItemPreferenceAlternate(mContext);
+ StorageItemPreferenceAlternate files = new StorageItemPreferenceAlternate(mContext);
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ when(screen.findPreference(
+ Mockito.eq(StorageItemPreferenceController.AUDIO_KEY))).thenReturn(audio);
+ when(screen.findPreference(
+ Mockito.eq(StorageItemPreferenceController.PHOTO_KEY))).thenReturn(image);
+ when(screen.findPreference(
+ Mockito.eq(StorageItemPreferenceController.GAME_KEY))).thenReturn(games);
+ when(screen.findPreference(
+ Mockito.eq(StorageItemPreferenceController.OTHER_APPS_KEY))).thenReturn(apps);
+ when(screen.findPreference(
+ Mockito.eq(StorageItemPreferenceController.SYSTEM_KEY))).thenReturn(system);
+ when(screen.findPreference(
+ Mockito.eq(StorageItemPreferenceController.FILES_KEY))).thenReturn(files);
+ mController.displayPreference(screen);
+
+ StorageMeasurement.MeasurementDetails details = new StorageMeasurement.MeasurementDetails();
+ details.appsSize.put(0, KILOBYTE);
+ HashMap<String, Long> mediaSizes = new HashMap<>();
+ mediaSizes.put(Environment.DIRECTORY_PICTURES, KILOBYTE * 2);
+ mediaSizes.put(Environment.DIRECTORY_MOVIES, KILOBYTE * 3);
+ mediaSizes.put(Environment.DIRECTORY_MUSIC, KILOBYTE * 4);
+ mediaSizes.put(Environment.DIRECTORY_DOWNLOADS, KILOBYTE * 5);
+ details.mediaSize.put(0, mediaSizes);
+ mController.setSystemSize(KILOBYTE * 6);
+ mController.onDetailsChanged(details);
+
+ assertThat(audio.getSummary().toString()).isEqualTo("4.00KB");
+ assertThat(image.getSummary().toString()).isEqualTo("5.00KB");
+ assertThat(games.getSummary().toString()).isEqualTo("0");
+ assertThat(apps.getSummary().toString()).isEqualTo("1.00KB");
+ assertThat(system.getSummary().toString()).isEqualTo("6.00KB");
+ assertThat(files.getSummary().toString()).isEqualTo("5.00KB");
+ }
}
\ No newline at end of file