Merge "Update the card behavior of Low Storage slice"
diff --git a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
index d893587..3cbbb0c 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
@@ -22,7 +22,6 @@
 import android.net.Uri;
 import android.os.storage.StorageManager;
 import android.text.format.Formatter;
-import android.util.Log;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -45,10 +44,8 @@
 
 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;
 
@@ -60,45 +57,37 @@
 
     @Override
     public Slice getSlice() {
-        // Get current storage percentage from StorageManager.
+        // Get used storage percentage from StorageManager.
         final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
                 new StorageManagerVolumeProvider(mContext.getSystemService(StorageManager.class)));
-        final double currentStoragePercentage =
-                (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
+        final double usedPercentage = (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
 
-        // Used storage < 85%. NOT show Low storage Slice.
-        if (currentStoragePercentage < LOW_STORAGE_THRESHOLD) {
-            /**
-             * TODO(b/114808204): Contextual Home Page - "Low Storage"
-             * The behavior is under decision making, will update new behavior or remove TODO later.
-             */
-            Log.i(TAG, "Not show low storage slice, not match condition.");
-            return null;
+        // Generate Low storage Slice.
+        final String percentageString = NumberFormat.getPercentInstance().format(usedPercentage);
+        final String freeSizeString = Formatter.formatFileSize(mContext, info.freeBytes);
+        final ListBuilder listBuilder = new ListBuilder(mContext,
+                CustomSliceRegistry.LOW_STORAGE_SLICE_URI, ListBuilder.INFINITY).setAccentColor(
+                Utils.getColorAccentDefaultColor(mContext));
+        final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
+
+        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 IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
-        final CharSequence title = mContext.getText(R.string.storage_menu_free);
-        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));
+        final CharSequence titleLowStorage = mContext.getText(R.string.storage_menu_free);
+        final String summaryLowStorage = mContext.getString(R.string.low_storage_summary,
+                percentageString, freeSizeString);
 
-        /**
-         * 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 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))
+        return listBuilder
+                .addRow(buildRowBuilder(titleLowStorage, summaryLowStorage, icon))
                 .build();
     }
 
@@ -123,4 +112,21 @@
                 MetricsProto.MetricsEvent.SLICE)
                 .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);
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
index 0be55d9..9787aee 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
+import static android.app.slice.Slice.HINT_ERROR;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
@@ -66,7 +68,7 @@
 
     @Test
     @Config(shadows = ShadowPrivateStorageInfo.class)
-    public void getSlice_hasLowStorage_shouldBeCorrectSliceContent() {
+    public void getSlice_lowStorage_shouldHaveStorageFreeTitle() {
         ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
 
         final Slice slice = mLowStorageSlice.getSlice();
@@ -77,12 +79,33 @@
 
     @Test
     @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));
 
         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)