blob: b53e1659dae33a7d8b2acaa024fb1578283bbcd2 [file] [log] [blame]
Steve McKay14e827a2016-01-06 18:32:13 -08001/*
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
17package com.android.documentsui.services;
18
Steve McKayecbf3c52016-01-13 17:17:39 -080019import static android.os.SystemClock.elapsedRealtime;
Steve McKay14e827a2016-01-06 18:32:13 -080020import static com.android.documentsui.Shared.DEBUG;
21import static com.android.documentsui.Shared.EXTRA_STACK;
22import static com.android.documentsui.Shared.asArrayList;
23import static com.android.documentsui.Shared.getQuantityString;
24import static com.android.documentsui.services.FileOperationService.EXTRA_CANCEL;
25import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID;
26import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
27import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +090028import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_PARENT;
Steve McKay14e827a2016-01-06 18:32:13 -080029import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
30import static com.android.documentsui.services.FileOperationService.OPERATION_DELETE;
31import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
32
33import android.app.Activity;
Steve McKayecbf3c52016-01-13 17:17:39 -080034import android.content.Context;
Steve McKay14e827a2016-01-06 18:32:13 -080035import android.content.Intent;
36import android.content.res.Resources;
37import android.os.Parcelable;
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +090038import android.support.annotation.VisibleForTesting;
Steve McKay14e827a2016-01-06 18:32:13 -080039import android.support.design.widget.Snackbar;
40import android.util.Log;
41
42import com.android.documentsui.R;
43import com.android.documentsui.Snackbars;
44import com.android.documentsui.model.DocumentInfo;
45import com.android.documentsui.model.DocumentStack;
46import com.android.documentsui.services.FileOperationService.OpType;
47
48import java.util.List;
49
50/**
51 * Helper functions for starting various file operations.
52 */
53public final class FileOperations {
54
55 private static final String TAG = "FileOperations";
56
Steve McKay35645432016-01-20 15:09:35 -080057 private static final IdBuilder idBuilder = new IdBuilder();
58
Steve McKay14e827a2016-01-06 18:32:13 -080059 private FileOperations() {}
60
Steve McKayecbf3c52016-01-13 17:17:39 -080061 public static String createJobId() {
Steve McKay35645432016-01-20 15:09:35 -080062 return idBuilder.getNext();
Steve McKayecbf3c52016-01-13 17:17:39 -080063 }
64
Steve McKay14e827a2016-01-06 18:32:13 -080065 /**
66 * Tries to start the activity. Returns the job id.
67 */
68 public static String start(
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +090069 Activity activity, List<DocumentInfo> srcDocs,
70 DocumentStack stack, int operationType) {
Steve McKay14e827a2016-01-06 18:32:13 -080071
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:
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +090078 throw new IllegalArgumentException("Moving requires providing the source parent.");
Steve McKay14e827a2016-01-06 18:32:13 -080079 case OPERATION_DELETE:
Steve McKay35645432016-01-20 15:09:35 -080080 throw new UnsupportedOperationException("Delete isn't currently supported.");
Steve McKay14e827a2016-01-06 18:32:13 -080081 default:
82 throw new UnsupportedOperationException("Unknown operation: " + operationType);
83 }
84 }
85
86 /**
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +090087 * Tries to start the activity. Returns the job id.
Steve McKay14e827a2016-01-06 18:32:13 -080088 */
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +090089 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
Steve McKay14e827a2016-01-06 18:32:13 -0800108 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
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900118 @VisibleForTesting
Steve McKay14e827a2016-01-06 18:32:13 -0800119 public static String copy(
120 Activity activity, List<DocumentInfo> srcDocs, DocumentStack destination) {
Steve McKayecbf3c52016-01-13 17:17:39 -0800121 String jobId = createJobId();
Steve McKay14e827a2016-01-06 18:32:13 -0800122 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.
Steve McKayecbf3c52016-01-13 17:17:39 -0800138 * Use {@link #createJobId} if you don't have one handy.
Steve McKay14e827a2016-01-06 18:32:13 -0800139 * @param srcDocs A list of src files to copy.
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900140 * @param srcParent Parent of all the source documents.
Steve McKay14e827a2016-01-06 18:32:13 -0800141 * @param destination The move destination stack.
142 */
143 public static String move(
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900144 Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
145 DocumentStack destination) {
Steve McKayecbf3c52016-01-13 17:17:39 -0800146 String jobId = createJobId();
Steve McKay14e827a2016-01-06 18:32:13 -0800147 if (DEBUG) Log.d(TAG, "Initiating 'move' operation id: " + jobId);
148
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900149 Intent intent = createBaseIntent(OPERATION_MOVE, activity, jobId, srcDocs, srcParent,
150 destination);
Steve McKay14e827a2016-01-06 18:32:13 -0800151
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.
Steve McKayecbf3c52016-01-13 17:17:39 -0800164 * Use {@link #createJobId} if you don't have one handy.
Steve McKay14e827a2016-01-06 18:32:13 -0800165 * @param srcDocs A list of src files to copy.
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900166 * @param srcParent Parent of all the source documents.
Steve McKay14e827a2016-01-06 18:32:13 -0800167 * @return Id of the job.
168 */
169 public static String delete(
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900170 Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
Steve McKay7a3b8112016-02-23 10:06:50 -0800171 DocumentStack location) {
Steve McKayecbf3c52016-01-13 17:17:39 -0800172 String jobId = createJobId();
Steve McKay7a3b8112016-02-23 10:06:50 -0800173 if (DEBUG) Log.d(TAG, "Initiating 'delete' operation id " + jobId + ".");
Steve McKay14e827a2016-01-06 18:32:13 -0800174
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900175 Intent intent = createBaseIntent(OPERATION_DELETE, activity, jobId, srcDocs, srcParent,
176 location);
Steve McKay14e827a2016-01-06 18:32:13 -0800177 activity.startService(intent);
178
179 return jobId;
180 }
181
182 /**
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900183 * Starts the service for an operation.
Steve McKay14e827a2016-01-06 18:32:13 -0800184 *
185 * @param jobId A unique jobid for this job.
Steve McKayecbf3c52016-01-13 17:17:39 -0800186 * Use {@link #createJobId} if you don't have one handy.
Steve McKay14e827a2016-01-06 18:32:13 -0800187 * @param srcDocs A list of src files to copy.
188 * @return Id of the job.
189 */
190 public static Intent createBaseIntent(
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900191 @OpType int operationType, Context context, String jobId, List<DocumentInfo> srcDocs,
192 DocumentStack localeStack) {
Steve McKay14e827a2016-01-06 18:32:13 -0800193
Steve McKayecbf3c52016-01-13 17:17:39 -0800194 Intent intent = new Intent(context, FileOperationService.class);
Steve McKay14e827a2016-01-06 18:32:13 -0800195 intent.putExtra(EXTRA_JOB_ID, jobId);
Tomasz Mikolajewskib8436af2016-01-25 16:20:15 +0900196 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);
Steve McKay14e827a2016-01-06 18:32:13 -0800220 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 }
Steve McKay35645432016-01-20 15:09:35 -0800233
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 }
Steve McKay14e827a2016-01-06 18:32:13 -0800253}