Merge pull request #1088 from owncloud/updated_docs_about_target_of_PRs
[pub/Android/ownCloud.git] / src / com / owncloud / android / datamodel / ThumbnailsCacheManager.java
index ce53c44..0e59a83 100644 (file)
@@ -1,5 +1,9 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2014 ownCloud Inc.
+/**
+ *   ownCloud Android client application
+ *
+ *   @author Tobias Kaminsky
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
 package com.owncloud.android.datamodel;
 
 import java.io.File;
+import java.io.InputStream;
 import java.lang.ref.WeakReference;
 
 import org.apache.commons.httpclient.HttpStatus;
 import org.apache.commons.httpclient.methods.GetMethod;
 
 import android.accounts.Account;
-import android.accounts.AccountManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.media.ExifInterface;
 import android.media.ThumbnailUtils;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -40,10 +42,10 @@ import android.widget.ImageView;
 
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
-import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 import com.owncloud.android.ui.adapter.DiskLruImageCache;
@@ -51,18 +53,14 @@ import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.DisplayUtils;
 
 /**
- * Manager for concurrent access to thumbnails cache. 
- *  
- * @author Tobias Kaminsky
- * @author David A. Velasco
+ * Manager for concurrent access to thumbnails cache.
  */
 public class ThumbnailsCacheManager {
     
     private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
     
     private static final String CACHE_FOLDER = "thumbnailCache";
-    private static final String MINOR_SERVER_VERSION_FOR_THUMBS = "7.8.0";
-    
+
     private static final Object mThumbnailsDiskCacheLock = new Object();
     private static DiskLruImageCache mThumbnailCache = null;
     private static boolean mThumbnailCacheStarting = true;
@@ -71,12 +69,11 @@ public class ThumbnailsCacheManager {
     private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
     private static final int mCompressQuality = 70;
     private static OwnCloudClient mClient = null;
-    private static String mServerVersion = null;
 
     public static Bitmap mDefaultImg = 
             BitmapFactory.decodeResource(
                     MainApp.getAppContext().getResources(), 
-                    DisplayUtils.getResourceId("image/png", "default.png")
+                    DisplayUtils.getFileTypeIconId("image/png", "default.png")
             );
 
     
@@ -130,53 +127,27 @@ public class ThumbnailsCacheManager {
             while (mThumbnailCacheStarting) {
                 try {
                     mThumbnailsDiskCacheLock.wait();
-                } catch (InterruptedException e) {}
+                } catch (InterruptedException e) {
+                    Log_OC.e(TAG, "Wait in mThumbnailsDiskCacheLock was interrupted", e);
+                }
             }
             if (mThumbnailCache != null) {
-                return (Bitmap) mThumbnailCache.getBitmap(key);
+                return mThumbnailCache.getBitmap(key);
             }
         }
         return null;
     }
 
-    
-    public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
-        final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
-
-        if (bitmapWorkerTask != null) {
-            final OCFile bitmapData = bitmapWorkerTask.mFile;
-            // If bitmapData is not yet set or it differs from the new data
-            if (bitmapData == null || bitmapData != file) {
-                // Cancel previous task
-                bitmapWorkerTask.cancel(true);
-            } else {
-                // The same work is already in progress
-                return false;
-            }
-        }
-        // No task associated with the ImageView, or an existing task was cancelled
-        return true;
-    }
-    
-    public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
-        if (imageView != null) {
-            final Drawable drawable = imageView.getDrawable();
-            if (drawable instanceof AsyncDrawable) {
-                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
-                return asyncDrawable.getBitmapWorkerTask();
-            }
-         }
-         return null;
-     }
-
-    public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
+    public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
         private final WeakReference<ImageView> mImageViewReference;
         private static Account mAccount;
-        private OCFile mFile;
+        private Object mFile;
         private FileDataStorageManager mStorageManager;
-        
-        public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) {
-         // Use a WeakReference to ensure the ImageView can be garbage collected
+
+
+        public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager,
+                                       Account account) {
+            // Use a WeakReference to ensure the ImageView can be garbage collected
             mImageViewReference = new WeakReference<ImageView>(imageView);
             if (storageManager == null)
                 throw new IllegalArgumentException("storageManager must not be NULL");
@@ -184,143 +155,227 @@ public class ThumbnailsCacheManager {
             mAccount = account;
         }
 
-        // Decode image in background.
+        public ThumbnailGenerationTask(ImageView imageView) {
+            // Use a WeakReference to ensure the ImageView can be garbage collected
+            mImageViewReference = new WeakReference<ImageView>(imageView);
+        }
+
         @Override
-        protected Bitmap doInBackground(OCFile... params) {
+        protected Bitmap doInBackground(Object... params) {
             Bitmap thumbnail = null;
-            
+
             try {
                 if (mAccount != null) {
-                    AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());
-                    
-                    mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
-                    OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount,
+                            MainApp.getAppContext());
                     mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
                             getClientFor(ocAccount, MainApp.getAppContext());
                 }
-                
+
                 mFile = params[0];
-                final String imageKey = String.valueOf(mFile.getRemoteId());
-    
-                // Check disk cache in background thread
-                thumbnail = getBitmapFromDiskCache(imageKey);
-    
-                // Not found in disk cache
-                if (thumbnail == null || mFile.needsUpdateThumbnail()) { 
-                    // Converts dp to pixel
-                    Resources r = MainApp.getAppContext().getResources();
-                    
-                    int px = (int) Math.round(r.getDimension(R.dimen.file_icon_size));
-                    
-                    if (mFile.isDown()){
-                        Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
-                                mFile.getStoragePath(), px, px);
-                        
-                        if (bitmap != null) {
-                            thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
-                            
-                            // Rotate image, obeying exif tag
-                            thumbnail = BitmapUtils.rotateImage(thumbnail, mFile.getStoragePath());
-    
-                            // Add thumbnail to cache
-                            addBitmapToCache(imageKey, thumbnail);
+                
+                if (mFile instanceof OCFile) {
+                    thumbnail = doOCFileInBackground();
+                }  else if (mFile instanceof File) {
+                    thumbnail = doFileInBackground();
+                //} else {  do nothing
+                }
 
-                            mFile.setNeedsUpdateThumbnail(false);
-                            mStorageManager.saveFile(mFile);
-                        }
-    
-                    } else {
-                        // Download thumbnail from server
-                        if (mClient != null && mServerVersion != null) {
-                            OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
-                            if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
-                                try {
-                                    int status = -1;
-
-                                    String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + 
-                                            px + "/" + px + Uri.encode(mFile.getRemotePath(), "/");
-                                    Log_OC.d("Thumbnail", "URI: " + uri);
-                                    GetMethod get = new GetMethod(uri);
-                                    status = mClient.executeMethod(get);
-                                    if (status == HttpStatus.SC_OK) {
-                                        byte[] bytes = get.getResponseBody();
-                                        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
-                                        thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
-
-                                        // Add thumbnail to cache
-                                        if (thumbnail != null) {
-                                            addBitmapToCache(imageKey, thumbnail);
-                                        }
-                                    }
-                                } catch (Exception e) {
-                                    e.printStackTrace();
-                                }
-                            } else {
-                                Log_OC.d(TAG, "Server too old");
-                            }
-                        }
+                }catch(Throwable t){
+                    // the app should never break due to a problem with thumbnails
+                    Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
+                    if (t instanceof OutOfMemoryError) {
+                        System.gc();
                     }
                 }
-                
-            } catch (Throwable t) {
-                // the app should never break due to a problem with thumbnails
-                Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
-                if (t instanceof OutOfMemoryError) {
-                    System.gc();
-                }
-            }
-            
+
             return thumbnail;
         }
-        
+
         protected void onPostExecute(Bitmap bitmap){
             if (isCancelled()) {
                 bitmap = null;
             }
 
-            if (mImageViewReference != null && bitmap != null) {
+            if (bitmap != null) {
                 final ImageView imageView = mImageViewReference.get();
-                final ThumbnailGenerationTask bitmapWorkerTask =
-                        getBitmapWorkerTask(imageView);
-                if (this == bitmapWorkerTask && imageView != null) {
-                    if (imageView.getTag().equals(mFile.getFileId())) {
+                final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+                if (this == bitmapWorkerTask) {
+                    String tagId = "";
+                    if (mFile instanceof OCFile){
+                        tagId = String.valueOf(((OCFile)mFile).getFileId());
+                    } else if (mFile instanceof File){
+                        tagId = String.valueOf(mFile.hashCode());
+                    }
+                    if (String.valueOf(imageView.getTag()).equals(tagId)) {
                         imageView.setImageBitmap(bitmap);
                     }
                 }
             }
         }
+
+        /**
+         * Add thumbnail to cache
+         * @param imageKey: thumb key
+         * @param bitmap:   image for extracting thumbnail
+         * @param path:     image path
+         * @param px:       thumbnail dp
+         * @return Bitmap
+         */
+        private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){
+
+            Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+
+            // Rotate image, obeying exif tag
+            thumbnail = BitmapUtils.rotateImage(thumbnail,path);
+
+            // Add thumbnail to cache
+            addBitmapToCache(imageKey, thumbnail);
+
+            return thumbnail;
+        }
+
+        /**
+         * Converts size of file icon from dp to pixel
+         * @return int
+         */
+        private int getThumbnailDimension(){
+            // Converts dp to pixel
+            Resources r = MainApp.getAppContext().getResources();
+            return Math.round(r.getDimension(R.dimen.file_icon_size_grid));
+        }
+
+        private Bitmap doOCFileInBackground() {
+            OCFile file = (OCFile)mFile;
+
+            final String imageKey = String.valueOf(file.getRemoteId());
+
+            // Check disk cache in background thread
+            Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
+
+            // Not found in disk cache
+            if (thumbnail == null || file.needsUpdateThumbnail()) {
+
+                int px = getThumbnailDimension();
+
+                if (file.isDown()) {
+                    Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
+                            file.getStoragePath(), px, px);
+
+                    if (bitmap != null) {
+                        thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px);
+
+                        file.setNeedsUpdateThumbnail(false);
+                        mStorageManager.saveFile(file);
+                    }
+
+                } else {
+                    // Download thumbnail from server
+                    OwnCloudVersion serverOCVersion = AccountUtils.getServerVersion(mAccount);
+                    if (mClient != null && serverOCVersion != null) {
+                        if (serverOCVersion.supportsRemoteThumbnails()) {
+                            try {
+                                String uri = mClient.getBaseUri() + "" +
+                                        "/index.php/apps/files/api/v1/thumbnail/" +
+                                        px + "/" + px + Uri.encode(file.getRemotePath(), "/");
+                                Log_OC.d("Thumbnail", "URI: " + uri);
+                                GetMethod get = new GetMethod(uri);
+                                int status = mClient.executeMethod(get);
+                                if (status == HttpStatus.SC_OK) {
+//                                    byte[] bytes = get.getResponseBody();
+//                                    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0,
+//                                            bytes.length);
+                                    InputStream inputStream = get.getResponseBodyAsStream();
+                                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+                                    thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+
+                                    // Add thumbnail to cache
+                                    if (thumbnail != null) {
+                                        addBitmapToCache(imageKey, thumbnail);
+                                    }
+                                }
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        } else {
+                            Log_OC.d(TAG, "Server too old");
+                        }
+                    }
+                }
+            }
+
+            return thumbnail;
+
+        }
+
+        private Bitmap doFileInBackground() {
+            File file = (File)mFile;
+
+            final String imageKey = String.valueOf(file.hashCode());
+
+            // Check disk cache in background thread
+            Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
+
+            // Not found in disk cache
+            if (thumbnail == null) {
+
+                int px = getThumbnailDimension();
+
+                Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
+                        file.getAbsolutePath(), px, px);
+
+                if (bitmap != null) {
+                    thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
+                }
+            }
+            return thumbnail;
+        }
+
     }
-  
-    
+
+    public static boolean cancelPotentialWork(Object file, ImageView imageView) {
+        final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+
+        if (bitmapWorkerTask != null) {
+            final Object bitmapData = bitmapWorkerTask.mFile;
+            // If bitmapData is not yet set or it differs from the new data
+            if (bitmapData == null || bitmapData != file) {
+                // Cancel previous task
+                bitmapWorkerTask.cancel(true);
+            } else {
+                // The same work is already in progress
+                return false;
+            }
+        }
+        // No task associated with the ImageView, or an existing task was cancelled
+        return true;
+    }
+
+    public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
+        if (imageView != null) {
+            final Drawable drawable = imageView.getDrawable();
+            if (drawable instanceof AsyncDrawable) {
+                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
+                return asyncDrawable.getBitmapWorkerTask();
+            }
+        }
+        return null;
+    }
+
     public static class AsyncDrawable extends BitmapDrawable {
         private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
 
         public AsyncDrawable(
                 Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
-            ) {
-            
+        ) {
+
             super(res, bitmap);
             bitmapWorkerTaskReference =
-                new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
+                    new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
         }
 
         public ThumbnailGenerationTask getBitmapWorkerTask() {
             return bitmapWorkerTaskReference.get();
         }
     }
-
-    
-    /**
-     * Remove from cache the remoteId passed
-     * @param fileRemoteId: remote id of mFile passed
-     */
-    public static void removeFileFromCache(String fileRemoteId){
-        synchronized (mThumbnailsDiskCacheLock) {
-            if (mThumbnailCache != null) {
-                mThumbnailCache.removeKey(fileRemoteId);
-            }
-            mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
-        }
-    }
-    
 }