OSDN Git Service

b53e1659dae33a7d8b2acaa024fb1578283bbcd2
[android-x86/frameworks-base.git] / packages / DocumentsUI / src / com / android / documentsui / services / FileOperations.java
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 android.os.SystemClock.elapsedRealtime;
20 import static com.android.documentsui.Shared.DEBUG;
21 import static com.android.documentsui.Shared.EXTRA_STACK;
22 import static com.android.documentsui.Shared.asArrayList;
23 import static com.android.documentsui.Shared.getQuantityString;
24 import static com.android.documentsui.services.FileOperationService.EXTRA_CANCEL;
25 import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID;
26 import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
27 import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
28 import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_PARENT;
29 import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
30 import static com.android.documentsui.services.FileOperationService.OPERATION_DELETE;
31 import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
32
33 import android.app.Activity;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.res.Resources;
37 import android.os.Parcelable;
38 import android.support.annotation.VisibleForTesting;
39 import android.support.design.widget.Snackbar;
40 import android.util.Log;
41
42 import com.android.documentsui.R;
43 import com.android.documentsui.Snackbars;
44 import com.android.documentsui.model.DocumentInfo;
45 import com.android.documentsui.model.DocumentStack;
46 import com.android.documentsui.services.FileOperationService.OpType;
47
48 import java.util.List;
49
50 /**
51  * Helper functions for starting various file operations.
52  */
53 public final class FileOperations {
54
55     private static final String TAG = "FileOperations";
56
57     private static final IdBuilder idBuilder = new IdBuilder();
58
59     private FileOperations() {}
60
61     public static String createJobId() {
62         return idBuilder.getNext();
63     }
64
65     /**
66      * Tries to start the activity. Returns the job id.
67      */
68     public static String start(
69             Activity activity, List<DocumentInfo> srcDocs,
70             DocumentStack stack, int operationType) {
71
72         if (DEBUG) Log.d(TAG, "Handling generic 'start' call.");
73
74         switch (operationType) {
75             case OPERATION_COPY:
76                 return FileOperations.copy(activity, srcDocs, stack);
77             case OPERATION_MOVE:
78                 throw new IllegalArgumentException("Moving requires providing the source parent.");
79             case OPERATION_DELETE:
80                 throw new UnsupportedOperationException("Delete isn't currently supported.");
81             default:
82                 throw new UnsupportedOperationException("Unknown operation: " + operationType);
83         }
84     }
85
86     /**
87      * Tries to start the activity. Returns the job id.
88      */
89     public static String start(
90             Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
91             DocumentStack stack, int operationType) {
92
93         if (DEBUG) Log.d(TAG, "Handling generic 'start' call.");
94
95         switch (operationType) {
96             case OPERATION_COPY:
97                 return FileOperations.copy(activity, srcDocs, stack);
98             case OPERATION_MOVE:
99                 return FileOperations.move(activity, srcDocs, srcParent, stack);
100             case OPERATION_DELETE:
101                 throw new UnsupportedOperationException("Delete isn't currently supported.");
102             default:
103                 throw new UnsupportedOperationException("Unknown operation: " + operationType);
104         }
105     }
106
107     @VisibleForTesting
108     public static void cancel(Activity activity, String jobId) {
109         if (DEBUG) Log.d(TAG, "Attempting to canceling operation: " + jobId);
110
111         Intent intent = new Intent(activity, FileOperationService.class);
112         intent.putExtra(EXTRA_CANCEL, true);
113         intent.putExtra(EXTRA_JOB_ID, jobId);
114
115         activity.startService(intent);
116     }
117
118     @VisibleForTesting
119     public static String copy(
120             Activity activity, List<DocumentInfo> srcDocs, DocumentStack destination) {
121         String jobId = createJobId();
122         if (DEBUG) Log.d(TAG, "Initiating 'copy' operation id: " + jobId);
123
124         Intent intent = createBaseIntent(OPERATION_COPY, activity, jobId, srcDocs, destination);
125
126         createSharedSnackBar(activity, R.plurals.copy_begin, srcDocs.size())
127                 .show();
128
129         activity.startService(intent);
130
131         return jobId;
132     }
133
134     /**
135      * Starts the service for a move operation.
136      *
137      * @param jobId A unique jobid for this job.
138      *     Use {@link #createJobId} if you don't have one handy.
139      * @param srcDocs A list of src files to copy.
140      * @param srcParent Parent of all the source documents.
141      * @param destination The move destination stack.
142      */
143     public static String move(
144             Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
145             DocumentStack destination) {
146         String jobId = createJobId();
147         if (DEBUG) Log.d(TAG, "Initiating 'move' operation id: " + jobId);
148
149         Intent intent = createBaseIntent(OPERATION_MOVE, activity, jobId, srcDocs, srcParent,
150                 destination);
151
152         createSharedSnackBar(activity, R.plurals.move_begin, srcDocs.size())
153                 .show();
154
155         activity.startService(intent);
156
157         return jobId;
158     }
159
160     /**
161      * Starts the service for a move operation.
162      *
163      * @param jobId A unique jobid for this job.
164      *     Use {@link #createJobId} if you don't have one handy.
165      * @param srcDocs A list of src files to copy.
166      * @param srcParent Parent of all the source documents.
167      * @return Id of the job.
168      */
169     public static String delete(
170             Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
171             DocumentStack location) {
172         String jobId = createJobId();
173         if (DEBUG) Log.d(TAG, "Initiating 'delete' operation id " + jobId + ".");
174
175         Intent intent = createBaseIntent(OPERATION_DELETE, activity, jobId, srcDocs, srcParent,
176                 location);
177         activity.startService(intent);
178
179         return jobId;
180     }
181
182     /**
183      * Starts the service for an operation.
184      *
185      * @param jobId A unique jobid for this job.
186      *     Use {@link #createJobId} if you don't have one handy.
187      * @param srcDocs A list of src files to copy.
188      * @return Id of the job.
189      */
190     public static Intent createBaseIntent(
191             @OpType int operationType, Context context, String jobId, List<DocumentInfo> srcDocs,
192             DocumentStack localeStack) {
193
194         Intent intent = new Intent(context, FileOperationService.class);
195         intent.putExtra(EXTRA_JOB_ID, jobId);
196         intent.putParcelableArrayListExtra(EXTRA_SRC_LIST, asArrayList(srcDocs));
197         intent.putExtra(EXTRA_STACK, (Parcelable) localeStack);
198         intent.putExtra(EXTRA_OPERATION, operationType);
199
200         return intent;
201     }
202
203     /**
204      * Starts the service for an operation.
205      *
206      * @param jobId A unique jobid for this job.
207      *     Use {@link #createJobId} if you don't have one handy.
208      * @param srcDocs A list of src files to copy.
209      * @param srcParent Parent of all the source documents.
210      * @return Id of the job.
211      */
212     public static Intent createBaseIntent(
213             @OpType int operationType, Context context, String jobId,
214             List<DocumentInfo> srcDocs, DocumentInfo srcParent, DocumentStack localeStack) {
215
216         Intent intent = new Intent(context, FileOperationService.class);
217         intent.putExtra(EXTRA_JOB_ID, jobId);
218         intent.putParcelableArrayListExtra(EXTRA_SRC_LIST, asArrayList(srcDocs));
219         intent.putExtra(EXTRA_SRC_PARENT, srcParent);
220         intent.putExtra(EXTRA_STACK, (Parcelable) localeStack);
221         intent.putExtra(EXTRA_OPERATION, operationType);
222
223         return intent;
224     }
225
226     private static Snackbar createSharedSnackBar(Activity activity, int contentId, int fileCount) {
227         Resources res = activity.getResources();
228         return Snackbars.makeSnackbar(
229                 activity,
230                 getQuantityString(activity, contentId, fileCount),
231                 Snackbar.LENGTH_SHORT);
232     }
233
234     private static final class IdBuilder {
235
236         // Remember last job time so we can guard against collisions.
237         private long mLastJobTime;
238
239         // If we detect a collision, use subId to make distinct.
240         private int mSubId;
241
242         public synchronized String getNext() {
243             long time = elapsedRealtime();
244             if (time == mLastJobTime) {
245                 mSubId++;
246             } else {
247                 mSubId = 0;
248             }
249             mLastJobTime = time;
250             return String.valueOf(mLastJobTime) + "-" + String.valueOf(mSubId);
251         }
252     }
253 }