| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.documentsui.services; |
| |
| import static android.os.SystemClock.elapsedRealtime; |
| import static com.android.documentsui.base.SharedMinimal.DEBUG; |
| import static com.android.documentsui.services.FileOperationService.EXTRA_CANCEL; |
| import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID; |
| import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION; |
| |
| import androidx.annotation.IntDef; |
| import android.app.Activity; |
| import android.content.Context; |
| import android.content.Intent; |
| import androidx.annotation.VisibleForTesting; |
| import android.util.Log; |
| |
| import com.android.documentsui.services.FileOperationService.OpType; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| |
| import javax.annotation.Nullable; |
| |
| /** |
| * Helper functions for starting various file operations. |
| */ |
| public final class FileOperations { |
| |
| private static final String TAG = "FileOperations"; |
| |
| private static final IdBuilder idBuilder = new IdBuilder(); |
| |
| private FileOperations() {} |
| |
| public static String createJobId() { |
| return idBuilder.getNext(); |
| } |
| |
| /** |
| * Tries to start the activity. Returns the job id. |
| * @param jobId Optional job id. If null, then it will be auto-generated. |
| */ |
| public static String start(Context context, FileOperation operation, Callback callback, |
| @Nullable String jobId) { |
| |
| if (DEBUG) { |
| Log.d(TAG, "Handling generic 'start' call."); |
| } |
| |
| String newJobId = jobId != null ? jobId : createJobId(); |
| Intent intent = createBaseIntent(context, newJobId, operation); |
| if (callback != null) { |
| callback.onOperationResult(Callback.STATUS_ACCEPTED, operation.getOpType(), |
| operation.getSrc().getItemCount()); |
| } |
| |
| context.startService(intent); |
| |
| return newJobId; |
| } |
| |
| @VisibleForTesting |
| public static void cancel(Activity activity, String jobId) { |
| if (DEBUG) { |
| Log.d(TAG, "Attempting to canceling operation: " + jobId); |
| } |
| |
| Intent intent = new Intent(activity, FileOperationService.class); |
| intent.putExtra(EXTRA_CANCEL, true); |
| intent.putExtra(EXTRA_JOB_ID, jobId); |
| |
| activity.startService(intent); |
| } |
| |
| /** |
| * Starts the service for an operation. |
| * |
| * @param jobId A unique jobid for this job. |
| * Use {@link #createJobId} if you don't have one handy. |
| * @return Id of the job. |
| */ |
| public static Intent createBaseIntent( |
| Context context, String jobId, FileOperation operation) { |
| |
| Intent intent = new Intent(context, FileOperationService.class); |
| intent.putExtra(EXTRA_JOB_ID, jobId); |
| intent.putExtra(EXTRA_OPERATION, operation); |
| |
| return intent; |
| } |
| |
| private static final class IdBuilder { |
| |
| // Remember last job time so we can guard against collisions. |
| private long mLastJobTime; |
| |
| // If we detect a collision, use subId to make distinct. |
| private int mSubId; |
| |
| public synchronized String getNext() { |
| long time = elapsedRealtime(); |
| if (time == mLastJobTime) { |
| mSubId++; |
| } else { |
| mSubId = 0; |
| } |
| mLastJobTime = time; |
| return String.valueOf(mLastJobTime) + "-" + String.valueOf(mSubId); |
| } |
| } |
| |
| /** |
| * A functional callback called when the file operation starts or fails to start. |
| */ |
| @FunctionalInterface |
| public interface Callback { |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef({STATUS_ACCEPTED, STATUS_REJECTED}) |
| @interface Status {} |
| static final int STATUS_ACCEPTED = 0; |
| static final int STATUS_REJECTED = 1; |
| static final int STATUS_FAILED = 2; |
| |
| /** |
| * Performs operation when the file operation starts or fails to start. |
| * |
| * @param status {@link Status} of this operation. |
| * @param opType file operation type {@link OpType}. |
| * @param docCount number of documents operated. |
| */ |
| void onOperationResult(@Status int status, @OpType int opType, int docCount); |
| } |
| } |