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;