1 /* 2 * Copyright (C) 2016 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.documentsui.services; 18 19 import static com.android.documentsui.base.SharedMinimal.DEBUG; 20 import static com.android.documentsui.services.FileOperationService.OPERATION_DELETE; 21 22 import android.app.Notification; 23 import android.app.Notification.Builder; 24 import android.content.ContentResolver; 25 import android.content.Context; 26 import android.net.Uri; 27 import android.util.Log; 28 29 import com.android.documentsui.MetricConsts; 30 import com.android.documentsui.Metrics; 31 import com.android.documentsui.R; 32 import com.android.documentsui.base.DocumentInfo; 33 import com.android.documentsui.base.DocumentStack; 34 import com.android.documentsui.base.Features; 35 import com.android.documentsui.base.UserId; 36 import com.android.documentsui.clipping.UrisSupplier; 37 38 import java.io.FileNotFoundException; 39 40 import javax.annotation.Nullable; 41 42 final class DeleteJob extends ResolvedResourcesJob { 43 44 private static final String TAG = "DeleteJob"; 45 46 private final Uri mParentUri; 47 48 private volatile int mDocsProcessed = 0; 49 50 /** 51 * Moves files to a destination identified by {@code destination}. 52 * Performs most work by delegating to CopyJob, then deleting 53 * a file after it has been copied. 54 * 55 * @see @link {@link Job} constructor for most param descriptions. 56 */ DeleteJob(Context service, Listener listener, String id, DocumentStack stack, UrisSupplier srcs, @Nullable Uri srcParent, Features features)57 DeleteJob(Context service, Listener listener, String id, DocumentStack stack, 58 UrisSupplier srcs, @Nullable Uri srcParent, Features features) { 59 super(service, listener, id, OPERATION_DELETE, stack, srcs, features); 60 mParentUri = srcParent; 61 } 62 63 @Override createProgressBuilder()64 Builder createProgressBuilder() { 65 return super.createProgressBuilder( 66 service.getString(R.string.delete_notification_title), 67 R.drawable.ic_menu_delete, 68 service.getString(android.R.string.cancel), 69 R.drawable.ic_cab_cancel); 70 } 71 72 @Override getSetupNotification()73 public Notification getSetupNotification() { 74 return getSetupNotification(service.getString(R.string.delete_preparing)); 75 } 76 77 @Override getProgressNotification()78 public Notification getProgressNotification() { 79 mProgressBuilder.setProgress(mResourceUris.getItemCount(), mDocsProcessed, false); 80 String format = service.getString(R.string.delete_progress); 81 mProgressBuilder.setSubText( 82 String.format(format, mDocsProcessed, mResourceUris.getItemCount())); 83 84 mProgressBuilder.setContentText(null); 85 86 return mProgressBuilder.build(); 87 } 88 89 @Override getFailureNotification()90 Notification getFailureNotification() { 91 return getFailureNotification( 92 R.plurals.delete_error_notification_title, R.drawable.ic_menu_delete); 93 } 94 95 @Override getWarningNotification()96 Notification getWarningNotification() { 97 throw new UnsupportedOperationException(); 98 } 99 100 @Override start()101 void start() { 102 ContentResolver resolver = appContext.getContentResolver(); 103 104 DocumentInfo parentDoc; 105 try { 106 parentDoc = mParentUri != null 107 ? DocumentInfo.fromUri(resolver, mParentUri, UserId.DEFAULT_USER) 108 : null; 109 } catch (FileNotFoundException e) { 110 Log.e(TAG, "Failed to resolve parent from Uri: " + mParentUri + ". Cannot continue.", e); 111 failureCount += this.mResourceUris.getItemCount(); 112 return; 113 } 114 115 for (DocumentInfo doc : mResolvedDocs) { 116 if (DEBUG) { 117 Log.d(TAG, "Deleting document @ " + doc.derivedUri); 118 } 119 try { 120 deleteDocument(doc, parentDoc); 121 } catch (ResourceException e) { 122 Metrics.logFileOperationFailure( 123 appContext, MetricConsts.SUBFILEOP_DELETE_DOCUMENT, doc.derivedUri); 124 Log.e(TAG, "Failed to delete document @ " + doc.derivedUri, e); 125 onFileFailed(doc); 126 } 127 128 mDocsProcessed++; 129 if (isCanceled()) { 130 return; 131 } 132 } 133 134 Metrics.logFileOperation(operationType, mResolvedDocs, null); 135 } 136 137 @Override toString()138 public String toString() { 139 return new StringBuilder() 140 .append("DeleteJob") 141 .append("{") 142 .append("id=" + id) 143 .append(", uris=" + mResourceUris) 144 .append(", docs=" + mResolvedDocs) 145 .append(", srcParent=" + mParentUri) 146 .append(", location=" + stack) 147 .append("}") 148 .toString(); 149 } 150 } 151