1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.deviceinfo.storage; 18 19 import android.app.Dialog; 20 import android.app.settings.SettingsEnums; 21 import android.content.Context; 22 import android.content.pm.PackageManager.NameNotFoundException; 23 import android.os.Bundle; 24 import android.os.UserHandle; 25 import android.provider.MediaStore; 26 import android.util.Log; 27 28 import androidx.appcompat.app.AlertDialog; 29 import androidx.fragment.app.Fragment; 30 31 import com.android.settings.R; 32 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 33 import com.android.settingslib.utils.ThreadUtils; 34 35 /** 36 * Dialog asks if users want to empty trash files. 37 * TODO(b/189388449): Shows "Deleting..." and disables Trash category while deleting trash files. 38 */ 39 public class EmptyTrashFragment extends InstrumentedDialogFragment { 40 private static final String TAG = "EmptyTrashFragment"; 41 42 private static final String TAG_EMPTY_TRASH = "empty_trash"; 43 44 private final Fragment mParentFragment; 45 private final int mUserId; 46 private final long mTrashSize; 47 private final OnEmptyTrashCompleteListener mOnEmptyTrashCompleteListener; 48 49 /** The listener to receive empty trash complete callback event. */ 50 public interface OnEmptyTrashCompleteListener { 51 /** The empty trash complete callback. */ onEmptyTrashComplete()52 void onEmptyTrashComplete(); 53 } 54 EmptyTrashFragment(Fragment parent, int userId, long trashSize, OnEmptyTrashCompleteListener onEmptyTrashCompleteListener)55 public EmptyTrashFragment(Fragment parent, int userId, long trashSize, 56 OnEmptyTrashCompleteListener onEmptyTrashCompleteListener) { 57 super(); 58 59 mParentFragment = parent; 60 setTargetFragment(mParentFragment, 0 /* requestCode */); 61 mUserId = userId; 62 mTrashSize = trashSize; 63 mOnEmptyTrashCompleteListener = onEmptyTrashCompleteListener; 64 } 65 66 /** Shows the empty trash dialog. */ show()67 public void show() { 68 show(mParentFragment.getFragmentManager(), TAG_EMPTY_TRASH); 69 } 70 71 @Override getMetricsCategory()72 public int getMetricsCategory() { 73 return SettingsEnums.DIALOG_EMPTY_TRASH; 74 } 75 76 @Override onCreateDialog(Bundle savedInstanceState)77 public Dialog onCreateDialog(Bundle savedInstanceState) { 78 final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 79 return builder.setTitle(R.string.storage_trash_dialog_title) 80 .setMessage(getActivity().getString(R.string.storage_trash_dialog_ask_message, 81 StorageUtils.getStorageSizeLabel(getActivity(), mTrashSize))) 82 .setPositiveButton(R.string.storage_trash_dialog_confirm, 83 (dialog, which) -> emptyTrashAsync()) 84 .setNegativeButton(android.R.string.cancel, null) 85 .create(); 86 } 87 emptyTrashAsync()88 private void emptyTrashAsync() { 89 final Context context = getActivity(); 90 final Context perUserContext; 91 try { 92 perUserContext = context.createPackageContextAsUser( 93 context.getApplicationContext().getPackageName(), 94 0 /* flags= */, 95 UserHandle.of(mUserId)); 96 } catch (NameNotFoundException e) { 97 Log.e(TAG, "Not able to get Context for user ID " + mUserId); 98 return; 99 } 100 101 final Bundle trashQueryArgs = new Bundle(); 102 trashQueryArgs.putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY); 103 ThreadUtils.postOnBackgroundThread(() -> { 104 perUserContext.getContentResolver().delete( 105 MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), 106 trashQueryArgs); 107 if (mOnEmptyTrashCompleteListener == null) { 108 return; 109 } 110 ThreadUtils.postOnMainThread( 111 () -> mOnEmptyTrashCompleteListener.onEmptyTrashComplete()); 112 }); 113 } 114 } 115