14143e37643f34775a43650a650e6a032239e1ad2Austin Kolander/* 24143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * Copyright (C) 2017 The Android Open Source Project 34143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * 44143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * Licensed under the Apache License, Version 2.0 (the "License"); 54143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * you may not use this file except in compliance with the License. 64143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * You may obtain a copy of the License at 74143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * 84143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * http://www.apache.org/licenses/LICENSE-2.0 94143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * 104143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * Unless required by applicable law or agreed to in writing, software 114143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * distributed under the License is distributed on an "AS IS" BASIS, 124143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * See the License for the specific language governing permissions and 144143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * limitations under the License. 154143e37643f34775a43650a650e6a032239e1ad2Austin Kolander */ 164143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderpackage com.android.documentsui; 174143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 189de5807754666ce80295d15ff681c0d4921cd5e8Felipe Lemeimport static com.android.documentsui.base.SharedMinimal.VERBOSE; 194143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 204143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.content.ContentProviderClient; 214143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.content.ContentResolver; 224143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.content.Context; 234143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.graphics.Bitmap; 244143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.graphics.Point; 254143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.net.Uri; 264143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.os.AsyncTask; 274143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.os.CancellationSignal; 284143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.os.OperationCanceledException; 294143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.provider.DocumentsContract; 304143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.util.Log; 314143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.view.View; 324143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport android.widget.ImageView; 334143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport com.android.documentsui.ProviderExecutor.Preemptable; 344143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderimport java.util.function.BiConsumer; 3504efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolanderimport java.util.function.Consumer; 364143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 374143e37643f34775a43650a650e6a032239e1ad2Austin Kolander/** 384143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * Loads a Thumbnails asynchronously then animates from the mime icon to the thumbnail 394143e37643f34775a43650a650e6a032239e1ad2Austin Kolander */ 404143e37643f34775a43650a650e6a032239e1ad2Austin Kolanderpublic final class ThumbnailLoader extends AsyncTask<Uri, Void, Bitmap> implements Preemptable { 414143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 424143e37643f34775a43650a650e6a032239e1ad2Austin Kolander private static final String TAG = ThumbnailLoader.class.getCanonicalName(); 434143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 444143e37643f34775a43650a650e6a032239e1ad2Austin Kolander /** 454143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * Two animations applied to image views. The first is used to switch mime icon and thumbnail. 464143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * The second is used when we need to update thumbnail. 474143e37643f34775a43650a650e6a032239e1ad2Austin Kolander */ 484143e37643f34775a43650a650e6a032239e1ad2Austin Kolander public static final BiConsumer<View, View> ANIM_FADE_IN = (mime, thumb) -> { 494143e37643f34775a43650a650e6a032239e1ad2Austin Kolander float alpha = mime.getAlpha(); 504143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mime.animate().alpha(0f).start(); 514143e37643f34775a43650a650e6a032239e1ad2Austin Kolander thumb.setAlpha(0f); 524143e37643f34775a43650a650e6a032239e1ad2Austin Kolander thumb.animate().alpha(alpha).start(); 534143e37643f34775a43650a650e6a032239e1ad2Austin Kolander }; 544143e37643f34775a43650a650e6a032239e1ad2Austin Kolander public static final BiConsumer<View, View> ANIM_NO_OP = (mime, thumb) -> {}; 554143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 564143e37643f34775a43650a650e6a032239e1ad2Austin Kolander private final ImageView mIconThumb; 574143e37643f34775a43650a650e6a032239e1ad2Austin Kolander private final Point mThumbSize; 584143e37643f34775a43650a650e6a032239e1ad2Austin Kolander private final Uri mUri; 594143e37643f34775a43650a650e6a032239e1ad2Austin Kolander private final long mLastModified; 6004efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander private final Consumer<Bitmap> mCallback; 614143e37643f34775a43650a650e6a032239e1ad2Austin Kolander private final boolean mAddToCache; 624143e37643f34775a43650a650e6a032239e1ad2Austin Kolander private final CancellationSignal mSignal; 634143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 644143e37643f34775a43650a650e6a032239e1ad2Austin Kolander /** 654143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * @param uri - to a thumbnail. 664143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * @param iconThumb - ImageView to display the thumbnail. 674143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * @param thumbSize - size of the thumbnail. 684143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * @param lastModified - used for updating thumbnail caches. 694143e37643f34775a43650a650e6a032239e1ad2Austin Kolander * @param addToCache - flag that determines if the loader saves the thumbnail to the cache. 704143e37643f34775a43650a650e6a032239e1ad2Austin Kolander */ 7104efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander public ThumbnailLoader(Uri uri, ImageView iconThumb, Point thumbSize, long lastModified, 7204efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander Consumer<Bitmap> callback, boolean addToCache) { 7304efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander 744143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mUri = uri; 754143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mIconThumb = iconThumb; 764143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mThumbSize = thumbSize; 774143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mLastModified = lastModified; 7804efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander mCallback = callback; 794143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mAddToCache = addToCache; 804143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mSignal = new CancellationSignal(); 814143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mIconThumb.setTag(this); 8204efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander 834143e37643f34775a43650a650e6a032239e1ad2Austin Kolander if (VERBOSE) Log.v(TAG, "Starting icon loader task for " + mUri); 844143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } 854143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 864143e37643f34775a43650a650e6a032239e1ad2Austin Kolander @Override 874143e37643f34775a43650a650e6a032239e1ad2Austin Kolander public void preempt() { 884143e37643f34775a43650a650e6a032239e1ad2Austin Kolander if (VERBOSE) Log.v(TAG, "Icon loader task for " + mUri + " was cancelled."); 894143e37643f34775a43650a650e6a032239e1ad2Austin Kolander cancel(false); 904143e37643f34775a43650a650e6a032239e1ad2Austin Kolander mSignal.cancel(); 914143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } 924143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 934143e37643f34775a43650a650e6a032239e1ad2Austin Kolander @Override 944143e37643f34775a43650a650e6a032239e1ad2Austin Kolander protected Bitmap doInBackground(Uri... params) { 954143e37643f34775a43650a650e6a032239e1ad2Austin Kolander if (isCancelled()) { 964143e37643f34775a43650a650e6a032239e1ad2Austin Kolander return null; 974143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } 984143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 994143e37643f34775a43650a650e6a032239e1ad2Austin Kolander final Context context = mIconThumb.getContext(); 1004143e37643f34775a43650a650e6a032239e1ad2Austin Kolander final ContentResolver resolver = context.getContentResolver(); 1014143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 1024143e37643f34775a43650a650e6a032239e1ad2Austin Kolander ContentProviderClient client = null; 1034143e37643f34775a43650a650e6a032239e1ad2Austin Kolander Bitmap result = null; 1044143e37643f34775a43650a650e6a032239e1ad2Austin Kolander try { 1054143e37643f34775a43650a650e6a032239e1ad2Austin Kolander client = DocumentsApplication.acquireUnstableProviderOrThrow( 1064143e37643f34775a43650a650e6a032239e1ad2Austin Kolander resolver, mUri.getAuthority()); 1074143e37643f34775a43650a650e6a032239e1ad2Austin Kolander result = DocumentsContract.getDocumentThumbnail(client, mUri, mThumbSize, mSignal); 1084143e37643f34775a43650a650e6a032239e1ad2Austin Kolander if (result != null && mAddToCache) { 1094143e37643f34775a43650a650e6a032239e1ad2Austin Kolander final ThumbnailCache cache = DocumentsApplication.getThumbnailCache(context); 1104143e37643f34775a43650a650e6a032239e1ad2Austin Kolander cache.putThumbnail(mUri, mThumbSize, result, mLastModified); 1114143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } 1124143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } catch (Exception e) { 1134143e37643f34775a43650a650e6a032239e1ad2Austin Kolander if (!(e instanceof OperationCanceledException)) { 1144143e37643f34775a43650a650e6a032239e1ad2Austin Kolander Log.w(TAG, "Failed to load thumbnail for " + mUri + ": " + e); 1154143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } 1164143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } finally { 1174143e37643f34775a43650a650e6a032239e1ad2Austin Kolander ContentProviderClient.releaseQuietly(client); 1184143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } 1194143e37643f34775a43650a650e6a032239e1ad2Austin Kolander return result; 1204143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } 1214143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 1224143e37643f34775a43650a650e6a032239e1ad2Austin Kolander @Override 1234143e37643f34775a43650a650e6a032239e1ad2Austin Kolander protected void onPostExecute(Bitmap result) { 1244143e37643f34775a43650a650e6a032239e1ad2Austin Kolander if (VERBOSE) Log.v(TAG, "Loader task for " + mUri + " completed"); 1254143e37643f34775a43650a650e6a032239e1ad2Austin Kolander 12604efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander if (mIconThumb.getTag() == this) { 12704efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander mIconThumb.setTag(null); 12804efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander mCallback.accept(result); 12904efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander } 1304143e37643f34775a43650a650e6a032239e1ad2Austin Kolander } 13104efd4af8e8cfcd814377e1913e1718c3480ed53Austin Kolander}