• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.icu.text.MessageFormat;
27 import android.net.Uri;
28 import android.text.BidiFormatter;
29 import android.util.Log;
30 
31 import com.android.documentsui.MetricConsts;
32 import com.android.documentsui.Metrics;
33 import com.android.documentsui.R;
34 import com.android.documentsui.base.DocumentInfo;
35 import com.android.documentsui.base.DocumentStack;
36 import com.android.documentsui.base.Features;
37 import com.android.documentsui.base.UserId;
38 import com.android.documentsui.clipping.UrisSupplier;
39 
40 import java.io.FileNotFoundException;
41 import java.util.HashMap;
42 import java.util.Locale;
43 import java.util.Map;
44 
45 import javax.annotation.Nullable;
46 
47 final class DeleteJob extends ResolvedResourcesJob {
48 
49     private static final String TAG = "DeleteJob";
50 
51     private final Uri mParentUri;
52 
53     private volatile int mDocsProcessed = 0;
54 
55     /**
56      * Moves files to a destination identified by {@code destination}.
57      * Performs most work by delegating to CopyJob, then deleting
58      * a file after it has been copied.
59      *
60      * @see @link {@link Job} constructor for most param descriptions.
61      */
DeleteJob(Context service, Listener listener, String id, DocumentStack stack, UrisSupplier srcs, @Nullable Uri srcParent, Features features)62     DeleteJob(Context service, Listener listener, String id, DocumentStack stack,
63             UrisSupplier srcs, @Nullable Uri srcParent, Features features) {
64         super(service, listener, id, OPERATION_DELETE, stack, srcs, features);
65         mParentUri = srcParent;
66     }
67 
68     @Override
createProgressBuilder()69     Builder createProgressBuilder() {
70         return super.createProgressBuilder(
71                 service.getString(R.string.delete_notification_title),
72                 R.drawable.ic_menu_delete,
73                 service.getString(android.R.string.cancel),
74                 R.drawable.ic_cab_cancel);
75     }
76 
77     @Override
getSetupNotification()78     public Notification getSetupNotification() {
79         return getSetupNotification(service.getString(R.string.delete_preparing));
80     }
81 
82     @Override
getProgressNotification()83     public Notification getProgressNotification() {
84         mProgressBuilder.setProgress(mResourceUris.getItemCount(), mDocsProcessed, false);
85         String format = service.getString(R.string.delete_progress);
86         mProgressBuilder.setSubText(
87                 String.format(format, mDocsProcessed, mResourceUris.getItemCount()));
88 
89         mProgressBuilder.setContentText(null);
90 
91         return mProgressBuilder.build();
92     }
93 
94     @Override
getFailureNotification()95     Notification getFailureNotification() {
96         return getFailureNotification(
97                 R.plurals.delete_error_notification_title, R.drawable.ic_menu_delete);
98     }
99 
100     @Override
getWarningNotification()101     Notification getWarningNotification() {
102         throw new UnsupportedOperationException();
103     }
104 
getProgressMessage()105     private String getProgressMessage() {
106         switch (getState()) {
107             case Job.STATE_SET_UP:
108             case Job.STATE_COMPLETED:
109             case Job.STATE_CANCELED:
110                 Map<String, Object> formatArgs = new HashMap<>();
111                 formatArgs.put("count", mResolvedDocs.size());
112                 if (mResolvedDocs.size() == 1) {
113                     formatArgs.put("filename", BidiFormatter.getInstance().unicodeWrap(
114                             mResolvedDocs.get(0).displayName));
115                 }
116                 return (new MessageFormat(
117                         service.getString(R.string.delete_in_progress), Locale.getDefault()))
118                         .format(formatArgs);
119             default:
120                 return "";
121         }
122     }
123 
124     @Override
getJobProgress()125     JobProgress getJobProgress() {
126         return new JobProgress(
127                 id,
128                 getState(),
129                 getProgressMessage(),
130                 hasFailures());
131     }
132 
133     @Override
start()134     void start() {
135         ContentResolver resolver = appContext.getContentResolver();
136 
137         DocumentInfo parentDoc;
138         try {
139             parentDoc = mParentUri != null
140                 ? DocumentInfo.fromUri(resolver, mParentUri, UserId.DEFAULT_USER)
141                 : null;
142         } catch (FileNotFoundException e) {
143           Log.e(TAG, "Failed to resolve parent from Uri: " + mParentUri + ". Cannot continue.", e);
144           failureCount += this.mResourceUris.getItemCount();
145           return;
146         }
147 
148         for (DocumentInfo doc : mResolvedDocs) {
149             if (DEBUG) {
150                 Log.d(TAG, "Deleting document @ " + doc.derivedUri);
151             }
152             try {
153                 deleteDocument(doc, parentDoc);
154             } catch (ResourceException e) {
155                 Metrics.logFileOperationFailure(
156                         appContext, MetricConsts.SUBFILEOP_DELETE_DOCUMENT, doc.derivedUri);
157                 Log.e(TAG, "Failed to delete document @ " + doc.derivedUri, e);
158                 onFileFailed(doc);
159             }
160 
161             mDocsProcessed++;
162             if (isCanceled()) {
163                 return;
164             }
165         }
166 
167         Metrics.logFileOperation(operationType, mResolvedDocs, null);
168     }
169 
170     @Override
toString()171     public String toString() {
172         return new StringBuilder()
173                 .append("DeleteJob")
174                 .append("{")
175                 .append("id=" + id)
176                 .append(", uris=" + mResourceUris)
177                 .append(", docs=" + mResolvedDocs)
178                 .append(", srcParent=" + mParentUri)
179                 .append(", location=" + stack)
180                 .append("}")
181                 .toString();
182     }
183 }
184