• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.Shared.DEBUG;
20 import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
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.net.Uri;
27 import android.os.ParcelFileDescriptor;
28 import android.os.RemoteException;
29 import android.provider.DocumentsContract;
30 import android.provider.DocumentsContract.Document;
31 import android.util.Log;
32 
33 import com.android.documentsui.Metrics;
34 import com.android.documentsui.R;
35 import com.android.documentsui.archives.ArchivesProvider;
36 import com.android.documentsui.base.DocumentInfo;
37 import com.android.documentsui.base.DocumentStack;
38 import com.android.documentsui.base.Features;
39 import com.android.documentsui.clipping.UrisSupplier;
40 
41 import java.io.FileNotFoundException;
42 
43 import javax.annotation.Nullable;
44 
45 // TODO: Stop extending CopyJob.
46 final class CompressJob extends CopyJob {
47 
48     private static final String TAG = "CompressJob";
49     private static final String NEW_ARCHIVE_EXTENSION = ".zip";
50 
51     /**
52      * Moves files to a destination identified by {@code destination}.
53      * Performs most work by delegating to CopyJob, then deleting
54      * a file after it has been copied.
55      *
56      * @see @link {@link Job} constructor for most param descriptions.
57      */
CompressJob(Context service, Listener listener, String id, DocumentStack destination, UrisSupplier srcs, Features features)58     CompressJob(Context service, Listener listener,
59             String id, DocumentStack destination, UrisSupplier srcs, Features features) {
60         super(service, listener, id, OPERATION_MOVE, destination, srcs, features);
61     }
62 
63     @Override
createProgressBuilder()64     Builder createProgressBuilder() {
65         return super.createProgressBuilder(
66                 service.getString(R.string.compress_notification_title),
67                 R.drawable.ic_menu_compress,
68                 service.getString(android.R.string.cancel),
69                 R.drawable.ic_cab_cancel);
70     }
71 
72     @Override
getSetupNotification()73     public Notification getSetupNotification() {
74         return getSetupNotification(service.getString(R.string.compress_preparing));
75     }
76 
77     @Override
getProgressNotification()78     public Notification getProgressNotification() {
79         return getProgressNotification(R.string.copy_remaining);
80     }
81 
82     @Override
getFailureNotification()83     Notification getFailureNotification() {
84         return getFailureNotification(
85                 R.plurals.compress_error_notification_title, R.drawable.ic_menu_compress);
86     }
87 
88     @Override
setUp()89     public boolean setUp() {
90         if (!super.setUp()) {
91             return false;
92         }
93 
94         final ContentResolver resolver = appContext.getContentResolver();
95 
96         // TODO: Move this to DocumentsProvider.
97 
98         String displayName;
99         if (mResolvedDocs.size() == 1) {
100             displayName = mResolvedDocs.get(0).displayName + NEW_ARCHIVE_EXTENSION;
101         } else {
102             displayName = service.getString(R.string.new_archive_file_name, NEW_ARCHIVE_EXTENSION);
103         }
104 
105         Uri archiveUri;
106         try {
107             archiveUri = DocumentsContract.createDocument(
108                 resolver, mDstInfo.derivedUri, "application/zip", displayName);
109         } catch (Exception e) {
110             archiveUri = null;
111         }
112 
113         try {
114             mDstInfo = DocumentInfo.fromUri(resolver, ArchivesProvider.buildUriForArchive(
115                     archiveUri, ParcelFileDescriptor.MODE_WRITE_ONLY));
116             ArchivesProvider.acquireArchive(getClient(mDstInfo), mDstInfo.derivedUri);
117         } catch (FileNotFoundException e) {
118             Log.e(TAG, "Failed to create dstInfo.", e);
119             failureCount = mResourceUris.getItemCount();
120             return false;
121         } catch (RemoteException e) {
122             Log.e(TAG, "Failed to acquire the archive.", e);
123             failureCount = mResourceUris.getItemCount();
124             return false;
125         }
126 
127         return true;
128     }
129 
130     @Override
finish()131     void finish() {
132         try {
133             ArchivesProvider.releaseArchive(getClient(mDstInfo), mDstInfo.derivedUri);
134         } catch (RemoteException e) {
135             Log.e(TAG, "Failed to release the archive.");
136         }
137 
138         // TODO: Remove the archive file in case of an error.
139 
140         super.finish();
141     }
142 
143     /**
144      * {@inheritDoc}
145      *
146      * Only check space for moves across authorities. For now we don't know if the doc in
147      * {@link #mSrcs} is in the same root of destination, and if it's optimized move in the same
148      * root it should succeed regardless of free space, but it's for sure a failure if there is no
149      * enough free space if docs are moved from another authority.
150      */
151     @Override
checkSpace()152     boolean checkSpace() {
153         // We're unable to say how much space the archive will take, so assume
154         // it will fit.
155         return true;
156     }
157 
processDocument(DocumentInfo src, DocumentInfo dest)158     void processDocument(DocumentInfo src, DocumentInfo dest) throws ResourceException {
159         byteCopyDocument(src, dest);
160     }
161 
162     @Override
toString()163     public String toString() {
164         return new StringBuilder()
165                 .append("CompressJob")
166                 .append("{")
167                 .append("id=" + id)
168                 .append(", uris=" + mResourceUris)
169                 .append(", docs=" + mResolvedDocs)
170                 .append(", destination=" + stack)
171                 .append("}")
172                 .toString();
173     }
174 }
175