Update the card behavior of Low Storage slice
If used storage >= 85%, show low storage slice to all clients. Else, a generic storage slice with error flag will be given. Home page will check error flag in loading eligible cards. Bug: 114808204 Test: robotests, visual Change-Id: I757c46b3bbff785dc112fec6bdc37e5ce9269ed8
This commit is contained in:
@@ -22,7 +22,6 @@ import android.content.Intent;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.text.format.Formatter;
|
import android.text.format.Formatter;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
import androidx.core.graphics.drawable.IconCompat;
|
||||||
import androidx.slice.Slice;
|
import androidx.slice.Slice;
|
||||||
@@ -45,10 +44,8 @@ import java.text.NumberFormat;
|
|||||||
|
|
||||||
public class LowStorageSlice implements CustomSliceable {
|
public class LowStorageSlice implements CustomSliceable {
|
||||||
|
|
||||||
private static final String TAG = "LowStorageSlice";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If user used >= 85% storage.
|
* If used storage >= 85%, it would be low storage.
|
||||||
*/
|
*/
|
||||||
private static final double LOW_STORAGE_THRESHOLD = 0.85;
|
private static final double LOW_STORAGE_THRESHOLD = 0.85;
|
||||||
|
|
||||||
@@ -60,45 +57,37 @@ public class LowStorageSlice implements CustomSliceable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Slice getSlice() {
|
public Slice getSlice() {
|
||||||
// Get current storage percentage from StorageManager.
|
// Get used storage percentage from StorageManager.
|
||||||
final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
|
final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
|
||||||
new StorageManagerVolumeProvider(mContext.getSystemService(StorageManager.class)));
|
new StorageManagerVolumeProvider(mContext.getSystemService(StorageManager.class)));
|
||||||
final double currentStoragePercentage =
|
final double usedPercentage = (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
|
||||||
(double) (info.totalBytes - info.freeBytes) / info.totalBytes;
|
|
||||||
|
|
||||||
// Used storage < 85%. NOT show Low storage Slice.
|
// Generate Low storage Slice.
|
||||||
if (currentStoragePercentage < LOW_STORAGE_THRESHOLD) {
|
final String percentageString = NumberFormat.getPercentInstance().format(usedPercentage);
|
||||||
/**
|
final String freeSizeString = Formatter.formatFileSize(mContext, info.freeBytes);
|
||||||
* TODO(b/114808204): Contextual Home Page - "Low Storage"
|
final ListBuilder listBuilder = new ListBuilder(mContext,
|
||||||
* The behavior is under decision making, will update new behavior or remove TODO later.
|
CustomSliceRegistry.LOW_STORAGE_SLICE_URI, ListBuilder.INFINITY).setAccentColor(
|
||||||
*/
|
Utils.getColorAccentDefaultColor(mContext));
|
||||||
Log.i(TAG, "Not show low storage slice, not match condition.");
|
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
|
||||||
return null;
|
|
||||||
|
if (usedPercentage < LOW_STORAGE_THRESHOLD) {
|
||||||
|
// For clients that ignore error checking, a generic storage slice will be given.
|
||||||
|
final CharSequence titleStorage = mContext.getText(R.string.storage_settings);
|
||||||
|
final String summaryStorage = mContext.getString(R.string.storage_summary,
|
||||||
|
percentageString, freeSizeString);
|
||||||
|
|
||||||
|
return listBuilder
|
||||||
|
.addRow(buildRowBuilder(titleStorage, summaryStorage, icon))
|
||||||
|
.setIsError(true)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show Low storage Slice.
|
final CharSequence titleLowStorage = mContext.getText(R.string.storage_menu_free);
|
||||||
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
|
final String summaryLowStorage = mContext.getString(R.string.low_storage_summary,
|
||||||
final CharSequence title = mContext.getText(R.string.storage_menu_free);
|
percentageString, freeSizeString);
|
||||||
final SliceAction primarySliceAction = SliceAction.createDeeplink(
|
|
||||||
PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon,
|
|
||||||
ListBuilder.ICON_IMAGE, title);
|
|
||||||
final String lowStorageSummary = mContext.getString(R.string.low_storage_summary,
|
|
||||||
NumberFormat.getPercentInstance().format(currentStoragePercentage),
|
|
||||||
Formatter.formatFileSize(mContext, info.freeBytes));
|
|
||||||
|
|
||||||
/**
|
return listBuilder
|
||||||
* TODO(b/114808204): Contextual Home Page - "Low Storage"
|
.addRow(buildRowBuilder(titleLowStorage, summaryLowStorage, icon))
|
||||||
* Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
|
|
||||||
* right aligned. Will update the icon to left until Slices support it.
|
|
||||||
*/
|
|
||||||
return new ListBuilder(mContext, CustomSliceRegistry.LOW_STORAGE_SLICE_URI,
|
|
||||||
ListBuilder.INFINITY)
|
|
||||||
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
|
|
||||||
.addRow(new RowBuilder()
|
|
||||||
.setTitle(title)
|
|
||||||
.setSubtitle(lowStorageSummary)
|
|
||||||
.addEndItem(icon, ListBuilder.ICON_IMAGE)
|
|
||||||
.setPrimaryAction(primarySliceAction))
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,4 +112,21 @@ public class LowStorageSlice implements CustomSliceable {
|
|||||||
MetricsProto.MetricsEvent.SLICE)
|
MetricsProto.MetricsEvent.SLICE)
|
||||||
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
|
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RowBuilder buildRowBuilder(CharSequence title, String summary, IconCompat icon) {
|
||||||
|
final SliceAction primarySliceAction = SliceAction.createDeeplink(
|
||||||
|
PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon,
|
||||||
|
ListBuilder.ICON_IMAGE, title);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO(b/114808204): Contextual Home Page - "Low Storage"
|
||||||
|
* Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
|
||||||
|
* right aligned. Will update the icon to left until Slices support it.
|
||||||
|
*/
|
||||||
|
return new RowBuilder()
|
||||||
|
.setTitle(title)
|
||||||
|
.setSubtitle(summary)
|
||||||
|
.addEndItem(icon, ListBuilder.ICON_IMAGE)
|
||||||
|
.setPrimaryAction(primarySliceAction);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings.homepage.contextualcards.slices;
|
package com.android.settings.homepage.contextualcards.slices;
|
||||||
|
|
||||||
|
import static android.app.slice.Slice.HINT_ERROR;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -66,7 +68,7 @@ public class LowStorageSliceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Config(shadows = ShadowPrivateStorageInfo.class)
|
@Config(shadows = ShadowPrivateStorageInfo.class)
|
||||||
public void getSlice_hasLowStorage_shouldBeCorrectSliceContent() {
|
public void getSlice_lowStorage_shouldHaveStorageFreeTitle() {
|
||||||
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
|
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
|
||||||
|
|
||||||
final Slice slice = mLowStorageSlice.getSlice();
|
final Slice slice = mLowStorageSlice.getSlice();
|
||||||
@@ -77,12 +79,33 @@ public class LowStorageSliceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Config(shadows = ShadowPrivateStorageInfo.class)
|
@Config(shadows = ShadowPrivateStorageInfo.class)
|
||||||
public void getSlice_hasNoLowStorage_shouldBeNull() {
|
public void getSlice_lowStorage_shouldNotHaveErrorHint() {
|
||||||
|
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
|
||||||
|
|
||||||
|
final Slice slice = mLowStorageSlice.getSlice();
|
||||||
|
|
||||||
|
assertThat(slice.hasHint(HINT_ERROR)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(shadows = ShadowPrivateStorageInfo.class)
|
||||||
|
public void getSlice_storageFree_shouldHaveStorageSettingsTitle() {
|
||||||
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
|
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
|
||||||
|
|
||||||
final Slice slice = mLowStorageSlice.getSlice();
|
final Slice slice = mLowStorageSlice.getSlice();
|
||||||
|
|
||||||
assertThat(slice).isNull();
|
final List<SliceItem> sliceItems = slice.getItems();
|
||||||
|
SliceTester.assertTitle(sliceItems, mContext.getString(R.string.storage_settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(shadows = ShadowPrivateStorageInfo.class)
|
||||||
|
public void getSlice_storageFree_shouldHaveErrorHint() {
|
||||||
|
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
|
||||||
|
|
||||||
|
final Slice slice = mLowStorageSlice.getSlice();
|
||||||
|
|
||||||
|
assertThat(slice.hasHint(HINT_ERROR)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Implements(PrivateStorageInfo.class)
|
@Implements(PrivateStorageInfo.class)
|
||||||
|
Reference in New Issue
Block a user