Merge "Shows trash category in Storage Settings" into sc-dev
diff --git a/res/drawable/ic_trash_can.xml b/res/drawable/ic_trash_can.xml
index ed4a4cb..7829e1b 100644
--- a/res/drawable/ic_trash_can.xml
+++ b/res/drawable/ic_trash_can.xml
@@ -18,7 +18,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorControlNormal">
   <path
       android:pathData="M15,3V4H20V6H19V19C19,20.1 18.1,21 17,21H7C5.9,21 5,20.1 5,19V6H4V4H9V3H15ZM7,19H17V6H7V19ZM9,8H11V17H9V8ZM15,8H13V17H15V8Z"
       android:fillColor="#5F6368"
diff --git a/src/com/android/settings/deviceinfo/StorageItemPreference.java b/src/com/android/settings/deviceinfo/StorageItemPreference.java
index 8410e42..cdb9f9d 100644
--- a/src/com/android/settings/deviceinfo/StorageItemPreference.java
+++ b/src/com/android/settings/deviceinfo/StorageItemPreference.java
@@ -17,8 +17,6 @@
 package com.android.settings.deviceinfo;
 
 import android.content.Context;
-import android.text.TextUtils;
-import android.text.format.Formatter;
 import android.util.AttributeSet;
 import android.widget.ProgressBar;
 
@@ -26,6 +24,7 @@
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
+import com.android.settings.deviceinfo.storage.StorageUtils;
 
 public class StorageItemPreference extends Preference {
     public int userHandle;
@@ -49,7 +48,7 @@
 
     public void setStorageSize(long size, long total) {
         mStorageSize = size;
-        setSummary(getStorageSummary(size));
+        setSummary(StorageUtils.getStorageSizeLabel(getContext(), size));
 
         if (total == 0) {
             mProgressPercent = 0;
@@ -77,11 +76,4 @@
         updateProgressBar();
         super.onBindViewHolder(view);
     }
-
-    private String getStorageSummary(long bytes) {
-        final Formatter.BytesResult result = Formatter.formatBytes(getContext().getResources(),
-                bytes, Formatter.FLAG_SHORTER);
-        return TextUtils.expandTemplate(getContext().getText(R.string.storage_size_large),
-                result.value, result.units).toString();
-    }
 }
diff --git a/src/com/android/settings/deviceinfo/storage/EmptyTrashFragment.java b/src/com/android/settings/deviceinfo/storage/EmptyTrashFragment.java
index da7b9ba..3c48672 100644
--- a/src/com/android/settings/deviceinfo/storage/EmptyTrashFragment.java
+++ b/src/com/android/settings/deviceinfo/storage/EmptyTrashFragment.java
@@ -18,25 +18,54 @@
 
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.MediaStore;
+import android.util.Log;
 
 import androidx.appcompat.app.AlertDialog;
 import androidx.fragment.app.Fragment;
 
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settingslib.utils.ThreadUtils;
 
 /**
  * Dialog asks if users want to empty trash files.
+ * TODO(b/189388449): Shows "Deleting..." and disables Trash category while deleting trash files.
  */
 public class EmptyTrashFragment extends InstrumentedDialogFragment {
+    private static final String TAG = "EmptyTrashFragment";
+
     private static final String TAG_EMPTY_TRASH = "empty_trash";
 
+    private final Fragment mParentFragment;
+    private final int mUserId;
+    private final long mTrashSize;
+    private final OnEmptyTrashCompleteListener mOnEmptyTrashCompleteListener;
+
+    /** The listener to receive empty trash complete callback event. */
+    public interface OnEmptyTrashCompleteListener {
+        /** The empty trash complete callback. */
+        void onEmptyTrashComplete();
+    }
+
+    public EmptyTrashFragment(Fragment parent, int userId, long trashSize,
+            OnEmptyTrashCompleteListener onEmptyTrashCompleteListener) {
+        super();
+
+        mParentFragment = parent;
+        setTargetFragment(mParentFragment, 0 /* requestCode */);
+        mUserId = userId;
+        mTrashSize = trashSize;
+        mOnEmptyTrashCompleteListener = onEmptyTrashCompleteListener;
+    }
+
     /** Shows the empty trash dialog. */
-    public static void show(Fragment parent) {
-        final EmptyTrashFragment dialog = new EmptyTrashFragment();
-        dialog.setTargetFragment(parent, 0 /* requestCode */);
-        dialog.show(parent.getFragmentManager(), TAG_EMPTY_TRASH);
+    public void show() {
+        show(mParentFragment.getFragmentManager(), TAG_EMPTY_TRASH);
     }
 
     @Override
@@ -48,10 +77,38 @@
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         return builder.setTitle(R.string.storage_trash_dialog_title)
-                .setMessage(R.string.storage_trash_dialog_ask_message)
-                .setPositiveButton(R.string.storage_trash_dialog_confirm, (dialog, which) -> {
-                    // TODO(170918505): Implement the logic in worker thread.
-                }).setNegativeButton(android.R.string.cancel, null)
+                .setMessage(getActivity().getString(R.string.storage_trash_dialog_ask_message,
+                        StorageUtils.getStorageSizeLabel(getActivity(), mTrashSize)))
+                .setPositiveButton(R.string.storage_trash_dialog_confirm,
+                        (dialog, which) -> emptyTrashAsync())
+                .setNegativeButton(android.R.string.cancel, null)
                 .create();
     }
+
+    private void emptyTrashAsync() {
+        final Context context = getActivity();
+        final Context perUserContext;
+        try {
+            perUserContext = context.createPackageContextAsUser(
+                context.getApplicationContext().getPackageName(),
+                0 /* flags= */,
+                UserHandle.of(mUserId));
+        } catch (NameNotFoundException e) {
+            Log.e(TAG, "Not able to get Context for user ID " + mUserId);
+            return;
+        }
+
+        final Bundle trashQueryArgs = new Bundle();
+        trashQueryArgs.putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY);
+        ThreadUtils.postOnBackgroundThread(() -> {
+            perUserContext.getContentResolver().delete(
+                    MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
+                    trashQueryArgs);
+            if (mOnEmptyTrashCompleteListener == null) {
+                return;
+            }
+            ThreadUtils.postOnMainThread(
+                    () -> mOnEmptyTrashCompleteListener.onEmptyTrashComplete());
+        });
+    }
 }
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 67a5bb7..d57d81e 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -32,6 +32,7 @@
 import android.os.storage.VolumeInfo;
 import android.util.Log;
 import android.util.SparseArray;
+import android.widget.Toast;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
@@ -64,7 +65,8 @@
  * categorization breakdown.
  */
 public class StorageItemPreferenceController extends AbstractPreferenceController implements
-        PreferenceControllerMixin {
+        PreferenceControllerMixin,
+        EmptyTrashFragment.OnEmptyTrashCompleteListener {
     private static final String TAG = "StorageItemPreference";
 
     private static final String SYSTEM_FRAGMENT_TAG = "SystemInfo";
@@ -256,8 +258,7 @@
         mGamesPreference.setVisible(privateStoragePreferencesVisible);
         mDocumentsAndOtherPreference.setVisible(privateStoragePreferencesVisible);
         mSystemPreference.setVisible(privateStoragePreferencesVisible);
-        // TODO(b/170918505): Shows trash category after trash category feature complete.
-        mTrashPreference.setVisible(false);
+        mTrashPreference.setVisible(privateStoragePreferencesVisible);
 
         if (privateStoragePreferencesVisible) {
             final VolumeInfo sharedVolume = mSvp.findEmulatedForPrivate(mVolume);
@@ -460,13 +461,29 @@
     private void launchTrashIntent() {
         final Intent intent = new Intent("android.settings.VIEW_TRASH");
 
-        if (intent.resolveActivity(mPackageManager) == null) {
-            EmptyTrashFragment.show(mFragment);
+        if (mPackageManager.resolveActivityAsUser(intent, 0 /* flags */, mUserId) == null) {
+            final long trashSize = mTrashPreference.getStorageSize();
+            if (trashSize > 0) {
+                new EmptyTrashFragment(mFragment, mUserId, trashSize,
+                        this /* onEmptyTrashCompleteListener */).show();
+            } else {
+                Toast.makeText(mContext, R.string.storage_trash_dialog_empty_message,
+                        Toast.LENGTH_SHORT).show();
+            }
         } else {
             mContext.startActivityAsUser(intent, new UserHandle(mUserId));
         }
     }
 
+    @Override
+    public void onEmptyTrashComplete() {
+        if (mTrashPreference == null) {
+            return;
+        }
+        mTrashPreference.setStorageSize(0, mTotalSize);
+        updatePrivateStorageCategoryPreferencesOrder();
+    }
+
     private static long totalValues(StorageMeasurement.MeasurementDetails details, int userId,
             String... keys) {
         long total = 0;
diff --git a/src/com/android/settings/deviceinfo/storage/StorageUtils.java b/src/com/android/settings/deviceinfo/storage/StorageUtils.java
index 549eef6..9b52fe8 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageUtils.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageUtils.java
@@ -26,6 +26,8 @@
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
+import android.text.TextUtils;
+import android.text.format.Formatter;
 import android.util.Log;
 import android.widget.Toast;
 
@@ -115,6 +117,14 @@
                 .launch();
     }
 
+    /** Returns size label of changing units. (e.g., 1kB, 2MB, 3GB) */
+    public static String getStorageSizeLabel(Context context, long bytes) {
+        final Formatter.BytesResult result = Formatter.formatBytes(context.getResources(),
+                bytes, Formatter.FLAG_SHORTER);
+        return TextUtils.expandTemplate(context.getText(R.string.storage_size_large),
+                result.value, result.units).toString();
+    }
+
     /** An AsyncTask to unmount a specified volume. */
     public static class UnmountTask extends AsyncTask<Void, Void, Exception> {
         private final Context mContext;