• 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 android.os.SystemClock.elapsedRealtime;
20 import static com.android.documentsui.base.SharedMinimal.DEBUG;
21 import static com.android.documentsui.services.FileOperationService.EXTRA_CANCEL;
22 import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID;
23 import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
24 
25 import android.annotation.IntDef;
26 import android.app.Activity;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.support.annotation.VisibleForTesting;
30 import android.util.Log;
31 
32 import com.android.documentsui.services.FileOperationService.OpType;
33 
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 
37 import javax.annotation.Nullable;
38 
39 /**
40  * Helper functions for starting various file operations.
41  */
42 public final class FileOperations {
43 
44     private static final String TAG = "FileOperations";
45 
46     private static final IdBuilder idBuilder = new IdBuilder();
47 
FileOperations()48     private FileOperations() {}
49 
createJobId()50     public static String createJobId() {
51         return idBuilder.getNext();
52     }
53 
54     /**
55      * Tries to start the activity. Returns the job id.
56      * @param jobId Optional job id. If null, then it will be auto-generated.
57      */
start(Context context, FileOperation operation, Callback callback, @Nullable String jobId)58     public static String start(Context context, FileOperation operation, Callback callback,
59             @Nullable String jobId) {
60 
61         if (DEBUG) Log.d(TAG, "Handling generic 'start' call.");
62 
63         String newJobId = jobId != null ? jobId : createJobId();
64         Intent intent = createBaseIntent(context, newJobId, operation);
65 
66         callback.onOperationResult(Callback.STATUS_ACCEPTED, operation.getOpType(),
67                 operation.getSrc().getItemCount());
68 
69         context.startService(intent);
70 
71         return newJobId;
72     }
73 
74     @VisibleForTesting
cancel(Activity activity, String jobId)75     public static void cancel(Activity activity, String jobId) {
76         if (DEBUG) Log.d(TAG, "Attempting to canceling operation: " + jobId);
77 
78         Intent intent = new Intent(activity, FileOperationService.class);
79         intent.putExtra(EXTRA_CANCEL, true);
80         intent.putExtra(EXTRA_JOB_ID, jobId);
81 
82         activity.startService(intent);
83     }
84 
85     /**
86      * Starts the service for an operation.
87      *
88      * @param jobId A unique jobid for this job.
89      *     Use {@link #createJobId} if you don't have one handy.
90      * @return Id of the job.
91      */
createBaseIntent( Context context, String jobId, FileOperation operation)92     public static Intent createBaseIntent(
93             Context context, String jobId, FileOperation operation) {
94 
95         Intent intent = new Intent(context, FileOperationService.class);
96         intent.putExtra(EXTRA_JOB_ID, jobId);
97         intent.putExtra(EXTRA_OPERATION, operation);
98 
99         return intent;
100     }
101 
102     private static final class IdBuilder {
103 
104         // Remember last job time so we can guard against collisions.
105         private long mLastJobTime;
106 
107         // If we detect a collision, use subId to make distinct.
108         private int mSubId;
109 
getNext()110         public synchronized String getNext() {
111             long time = elapsedRealtime();
112             if (time == mLastJobTime) {
113                 mSubId++;
114             } else {
115                 mSubId = 0;
116             }
117             mLastJobTime = time;
118             return String.valueOf(mLastJobTime) + "-" + String.valueOf(mSubId);
119         }
120     }
121 
122     /**
123      * A functional callback called when the file operation starts or fails to start.
124      */
125     @FunctionalInterface
126     public interface Callback {
127         @Retention(RetentionPolicy.SOURCE)
128         @IntDef({STATUS_ACCEPTED, STATUS_REJECTED})
129         @interface Status {}
130         static final int STATUS_ACCEPTED = 0;
131         static final int STATUS_REJECTED = 1;
132         static final int STATUS_FAILED = 2;
133 
134         /**
135          * Performs operation when the file operation starts or fails to start.
136          *
137          * @param status {@link Status} of this operation.
138          * @param opType file operation type {@link OpType}.
139          * @param docCount number of documents operated.
140          */
onOperationResult(@tatus int status, @OpType int opType, int docCount)141         void onOperationResult(@Status int status, @OpType int opType, int docCount);
142     }
143 }
144