1 /*
2  * Copyright (C) 2013 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.gallery3d.ingest.data;
18 
19 import android.annotation.TargetApi;
20 import android.content.Context;
21 import android.mtp.MtpDevice;
22 import android.os.Build;
23 import android.os.Environment;
24 import android.os.PowerManager;
25 import android.os.StatFs;
26 import android.util.Log;
27 
28 import java.io.File;
29 import java.util.Collection;
30 import java.util.LinkedList;
31 import java.util.List;
32 
33 /**
34  * Task that handles the copying of items from an MTP device.
35  */
36 @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
37 public class ImportTask implements Runnable {
38 
39   private static final String TAG = "ImportTask";
40 
41   /**
42    * Import progress listener.
43    */
44   public interface Listener {
onImportProgress(int visitedCount, int totalCount, String pathIfSuccessful)45     void onImportProgress(int visitedCount, int totalCount, String pathIfSuccessful);
46 
onImportFinish(Collection<IngestObjectInfo> objectsNotImported, int visitedCount)47     void onImportFinish(Collection<IngestObjectInfo> objectsNotImported, int visitedCount);
48   }
49 
50   private static final String WAKELOCK_LABEL = "Google Photos MTP Import Task";
51 
52   private Listener mListener;
53   private String mDestAlbumName;
54   private Collection<IngestObjectInfo> mObjectsToImport;
55   private MtpDevice mDevice;
56   private PowerManager.WakeLock mWakeLock;
57 
ImportTask(MtpDevice device, Collection<IngestObjectInfo> objectsToImport, String destAlbumName, Context context)58   public ImportTask(MtpDevice device, Collection<IngestObjectInfo> objectsToImport,
59       String destAlbumName, Context context) {
60     mDestAlbumName = destAlbumName;
61     mObjectsToImport = objectsToImport;
62     mDevice = device;
63     PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
64     mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, WAKELOCK_LABEL);
65   }
66 
setListener(Listener listener)67   public void setListener(Listener listener) {
68     mListener = listener;
69   }
70 
71   @Override
run()72   public void run() {
73     mWakeLock.acquire();
74     try {
75       List<IngestObjectInfo> objectsNotImported = new LinkedList<IngestObjectInfo>();
76       int visited = 0;
77       int total = mObjectsToImport.size();
78       mListener.onImportProgress(visited, total, null);
79       File dest = new File(Environment.getExternalStorageDirectory(), mDestAlbumName);
80       dest.mkdirs();
81       for (IngestObjectInfo object : mObjectsToImport) {
82         visited++;
83         String importedPath = null;
84         if (hasSpaceForSize(object.getCompressedSize())) {
85           importedPath = new File(dest, object.getName(mDevice)).getAbsolutePath();
86           if (!mDevice.importFile(object.getObjectHandle(), importedPath)) {
87             importedPath = null;
88           }
89         }
90         if (importedPath == null) {
91           objectsNotImported.add(object);
92         }
93         if (mListener != null) {
94           mListener.onImportProgress(visited, total, importedPath);
95         }
96       }
97       if (mListener != null) {
98         mListener.onImportFinish(objectsNotImported, visited);
99       }
100     } finally {
101       mListener = null;
102       mWakeLock.release();
103     }
104   }
105 
hasSpaceForSize(long size)106   private static boolean hasSpaceForSize(long size) {
107     String state = Environment.getExternalStorageState();
108     if (!Environment.MEDIA_MOUNTED.equals(state)) {
109       return false;
110     }
111 
112     String path = Environment.getExternalStorageDirectory().getPath();
113     try {
114       StatFs stat = new StatFs(path);
115       return stat.getAvailableBlocks() * (long) stat.getBlockSize() > size;
116     } catch (Exception e) {
117       Log.i(TAG, "Fail to access external storage", e);
118     }
119     return false;
120   }
121 }
122