Load up-to-date thumbnail if the cached one is out of date.
Bug: 28557412 Change-Id: Ib3ef9962249305be22b7a1e49e26350f3596e430 (cherry picked from commit aacb9219a791d2e4415cbbcacc12caed424dff83)
This commit is contained in:
committed by
Garfield Tan
parent
ffcc6ac263
commit
1ec6f295d1
@@ -65,24 +65,19 @@ public class ThumbnailCache {
|
||||
* @return the thumbnail result
|
||||
*/
|
||||
public Result getThumbnail(Uri uri, Point size) {
|
||||
Result result = Result.obtain(Result.CACHE_MISS, null, null);
|
||||
|
||||
TreeMap<Point, Pair<Uri, Point>> sizeMap;
|
||||
sizeMap = mSizeIndex.get(uri);
|
||||
if (sizeMap == null || sizeMap.isEmpty()) {
|
||||
// There is not any thumbnail for this uri.
|
||||
return result;
|
||||
return Result.obtainMiss();
|
||||
}
|
||||
|
||||
// Look for thumbnail of the same size.
|
||||
Pair<Uri, Point> cacheKey = sizeMap.get(size);
|
||||
if (cacheKey != null) {
|
||||
Bitmap thumbnail = mCache.get(cacheKey);
|
||||
if (thumbnail != null) {
|
||||
result.mStatus = Result.CACHE_HIT_EXACT;
|
||||
result.mThumbnail = thumbnail;
|
||||
result.mSize = size;
|
||||
return result;
|
||||
Entry entry = mCache.get(cacheKey);
|
||||
if (entry != null) {
|
||||
return Result.obtain(Result.CACHE_HIT_EXACT, size, entry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,12 +87,9 @@ public class ThumbnailCache {
|
||||
cacheKey = sizeMap.get(otherSize);
|
||||
|
||||
if (cacheKey != null) {
|
||||
Bitmap thumbnail = mCache.get(cacheKey);
|
||||
if (thumbnail != null) {
|
||||
result.mStatus = Result.CACHE_HIT_LARGER;
|
||||
result.mThumbnail = thumbnail;
|
||||
result.mSize = otherSize;
|
||||
return result;
|
||||
Entry entry = mCache.get(cacheKey);
|
||||
if (entry != null) {
|
||||
return Result.obtain(Result.CACHE_HIT_LARGER, otherSize, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,21 +100,18 @@ public class ThumbnailCache {
|
||||
cacheKey = sizeMap.get(otherSize);
|
||||
|
||||
if (cacheKey != null) {
|
||||
Bitmap thumbnail = mCache.get(cacheKey);
|
||||
if (thumbnail != null) {
|
||||
result.mStatus = Result.CACHE_HIT_SMALLER;
|
||||
result.mThumbnail = thumbnail;
|
||||
result.mSize = otherSize;
|
||||
return result;
|
||||
Entry entry = mCache.get(cacheKey);
|
||||
if (entry != null) {
|
||||
return Result.obtain(Result.CACHE_HIT_SMALLER, otherSize, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache miss.
|
||||
return result;
|
||||
return Result.obtainMiss();
|
||||
}
|
||||
|
||||
public void putThumbnail(Uri uri, Point size, Bitmap thumbnail) {
|
||||
public void putThumbnail(Uri uri, Point size, Bitmap thumbnail, long lastModified) {
|
||||
Pair<Uri, Point> cacheKey = Pair.create(uri, size);
|
||||
|
||||
TreeMap<Point, Pair<Uri, Point>> sizeMap;
|
||||
@@ -134,17 +123,28 @@ public class ThumbnailCache {
|
||||
}
|
||||
}
|
||||
|
||||
mCache.put(cacheKey, thumbnail);
|
||||
Entry entry = new Entry(thumbnail, lastModified);
|
||||
mCache.put(cacheKey, entry);
|
||||
synchronized (sizeMap) {
|
||||
sizeMap.put(size, cacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeKey(Uri uri, Point size) {
|
||||
TreeMap<Point, Pair<Uri, Point>> sizeMap;
|
||||
synchronized (mSizeIndex) {
|
||||
sizeMap = mSizeIndex.get(uri);
|
||||
}
|
||||
|
||||
// LruCache tells us to remove a key, which should exist, so sizeMap can't be null.
|
||||
assert (sizeMap != null);
|
||||
synchronized (sizeMap) {
|
||||
sizeMap.remove(size);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTrimMemory(int level) {
|
||||
if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
|
||||
synchronized (mSizeIndex) {
|
||||
mSizeIndex.clear();
|
||||
}
|
||||
mCache.evictAll();
|
||||
} else if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
|
||||
mCache.trimToSize(mCache.size() / 2);
|
||||
@@ -159,7 +159,6 @@ public class ThumbnailCache {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({CACHE_MISS, CACHE_HIT_EXACT, CACHE_HIT_SMALLER, CACHE_HIT_LARGER})
|
||||
@interface Status {}
|
||||
|
||||
/**
|
||||
* Indicates there is no thumbnail for the requested uri. The thumbnail will be null.
|
||||
*/
|
||||
@@ -182,30 +181,38 @@ public class ThumbnailCache {
|
||||
private static final Pools.SimplePool<Result> sPool = new Pools.SimplePool<>(1);
|
||||
|
||||
private @Status int mStatus;
|
||||
|
||||
private @Nullable Bitmap mThumbnail;
|
||||
|
||||
private @Nullable Point mSize;
|
||||
private long mLastModified;
|
||||
|
||||
private static Result obtainMiss() {
|
||||
return obtain(CACHE_MISS, null, null, 0);
|
||||
}
|
||||
|
||||
private static Result obtain(@Status int status, Point size, Entry entry) {
|
||||
return obtain(status, entry.mThumbnail, size, entry.mLastModified);
|
||||
}
|
||||
|
||||
private static Result obtain(@Status int status, @Nullable Bitmap thumbnail,
|
||||
@Nullable Point size) {
|
||||
@Nullable Point size, long lastModified) {
|
||||
Result instance = sPool.acquire();
|
||||
instance = (instance != null ? instance : new Result());
|
||||
|
||||
instance.mStatus = status;
|
||||
instance.mThumbnail = thumbnail;
|
||||
instance.mSize = size;
|
||||
instance.mLastModified = lastModified;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Result() {
|
||||
}
|
||||
private Result() {}
|
||||
|
||||
public void recycle() {
|
||||
mStatus = -1;
|
||||
mThumbnail = null;
|
||||
mSize = null;
|
||||
mLastModified = -1;
|
||||
|
||||
boolean released = sPool.release(this);
|
||||
// This assert is used to guarantee we won't generate too many instances that can't be
|
||||
@@ -228,6 +235,10 @@ public class ThumbnailCache {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
public long getLastModified() {
|
||||
return mLastModified;
|
||||
}
|
||||
|
||||
public boolean isHit() {
|
||||
return (mStatus != CACHE_MISS);
|
||||
}
|
||||
@@ -237,14 +248,33 @@ public class ThumbnailCache {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Cache extends LruCache<Pair<Uri, Point>, Bitmap> {
|
||||
private static final class Entry {
|
||||
private final Bitmap mThumbnail;
|
||||
private final long mLastModified;
|
||||
|
||||
private Entry(Bitmap thumbnail, long lastModified) {
|
||||
mThumbnail = thumbnail;
|
||||
mLastModified = lastModified;
|
||||
}
|
||||
}
|
||||
|
||||
private final class Cache extends LruCache<Pair<Uri, Point>, Entry> {
|
||||
|
||||
private Cache(int maxSizeBytes) {
|
||||
super(maxSizeBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int sizeOf(Pair<Uri, Point> key, Bitmap value) {
|
||||
return value.getByteCount();
|
||||
protected int sizeOf(Pair<Uri, Point> key, Entry value) {
|
||||
return value.mThumbnail.getByteCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void entryRemoved(
|
||||
boolean evicted, Pair<Uri, Point> key, Entry oldValue, Entry newValue) {
|
||||
if (newValue == null) {
|
||||
removeKey(key.first, key.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,8 @@ final class GridDocumentHolder extends DocumentHolder {
|
||||
mIconThumb.setAlpha(0f);
|
||||
|
||||
final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId);
|
||||
mIconHelper.load(uri, docMimeType, docFlags, docIcon, mIconThumb, mIconMimeLg, mIconMimeSm);
|
||||
mIconHelper.load(uri, docMimeType, docFlags, docIcon, docLastModified, mIconThumb,
|
||||
mIconMimeLg, mIconMimeSm);
|
||||
|
||||
if (mHideTitles) {
|
||||
mTitle.setVisibility(View.GONE);
|
||||
|
||||
@@ -143,6 +143,7 @@ public class IconHelper {
|
||||
private final ImageView mIconMime;
|
||||
private final ImageView mIconThumb;
|
||||
private final Point mThumbSize;
|
||||
private final long mLastModified;
|
||||
|
||||
// A callback to apply animation to image views after the thumbnail is loaded.
|
||||
private final BiConsumer<View, View> mImageAnimator;
|
||||
@@ -150,12 +151,13 @@ public class IconHelper {
|
||||
private final CancellationSignal mSignal;
|
||||
|
||||
public LoaderTask(Uri uri, ImageView iconMime, ImageView iconThumb,
|
||||
Point thumbSize, BiConsumer<View, View> animator) {
|
||||
Point thumbSize, long lastModified, BiConsumer<View, View> animator) {
|
||||
mUri = uri;
|
||||
mIconMime = iconMime;
|
||||
mIconThumb = iconThumb;
|
||||
mThumbSize = thumbSize;
|
||||
mImageAnimator = animator;
|
||||
mLastModified = lastModified;
|
||||
mSignal = new CancellationSignal();
|
||||
if (DEBUG) Log.d(TAG, "Starting icon loader task for " + mUri);
|
||||
}
|
||||
@@ -184,7 +186,7 @@ public class IconHelper {
|
||||
result = DocumentsContract.getDocumentThumbnail(client, mUri, mThumbSize, mSignal);
|
||||
if (result != null) {
|
||||
final ThumbnailCache cache = DocumentsApplication.getThumbnailCache(context);
|
||||
cache.putThumbnail(mUri, mThumbSize, result);
|
||||
cache.putThumbnail(mUri, mThumbSize, result, mLastModified);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!(e instanceof OperationCanceledException)) {
|
||||
@@ -216,12 +218,13 @@ public class IconHelper {
|
||||
* @param mimeType The mime type of the file being represented.
|
||||
* @param docFlags Flags for the file being represented.
|
||||
* @param docIcon Custom icon (if any) for the file being requested.
|
||||
* @param docLastModified the last modified value of the file being requested.
|
||||
* @param iconThumb The itemview's thumbnail icon.
|
||||
* @param iconMime The itemview's mime icon. Hidden when iconThumb is shown.
|
||||
* @param subIconMime The second itemview's mime icon. Always visible.
|
||||
* @return
|
||||
*/
|
||||
public void load(Uri uri, String mimeType, int docFlags, int docIcon,
|
||||
public void load(Uri uri, String mimeType, int docFlags, int docIcon, long docLastModified,
|
||||
ImageView iconThumb, ImageView iconMime, @Nullable ImageView subIconMime) {
|
||||
boolean loadedThumbnail = false;
|
||||
|
||||
@@ -232,7 +235,8 @@ public class IconHelper {
|
||||
|| MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mimeType);
|
||||
final boolean showThumbnail = supportsThumbnail && allowThumbnail && mThumbnailsEnabled;
|
||||
if (showThumbnail) {
|
||||
loadedThumbnail = loadThumbnail(uri, docAuthority, iconThumb, iconMime);
|
||||
loadedThumbnail =
|
||||
loadThumbnail(uri, docAuthority, docLastModified, iconThumb, iconMime);
|
||||
}
|
||||
|
||||
final Drawable mimeIcon = getDocumentIcon(mContext, docAuthority,
|
||||
@@ -250,18 +254,21 @@ public class IconHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadThumbnail(Uri uri, String docAuthority, ImageView iconThumb,
|
||||
ImageView iconMime) {
|
||||
private boolean loadThumbnail(Uri uri, String docAuthority, long docLastModified,
|
||||
ImageView iconThumb, ImageView iconMime) {
|
||||
final Result result = mThumbnailCache.getThumbnail(uri, mCurrentSize);
|
||||
|
||||
final Bitmap cachedThumbnail = result.getThumbnail();
|
||||
iconThumb.setImageBitmap(cachedThumbnail);
|
||||
|
||||
if (!result.isExactHit()) {
|
||||
boolean stale = (docLastModified > result.getLastModified());
|
||||
if (DEBUG) Log.d(TAG, String.format("Load thumbnail for %s, got result %d and stale %b.",
|
||||
uri.toString(), result.getStatus(), stale));
|
||||
if (!result.isExactHit() || stale) {
|
||||
final BiConsumer<View, View> animator =
|
||||
(cachedThumbnail == null ? ANIM_FADE_IN : ANIM_NO_OP);
|
||||
final LoaderTask task =
|
||||
new LoaderTask(uri, iconMime, iconThumb, mCurrentSize, animator);
|
||||
final LoaderTask task = new LoaderTask(uri, iconMime, iconThumb, mCurrentSize,
|
||||
docLastModified, animator);
|
||||
|
||||
iconThumb.setTag(task);
|
||||
|
||||
|
||||
@@ -133,7 +133,8 @@ final class ListDocumentHolder extends DocumentHolder {
|
||||
mIconThumb.setAlpha(0f);
|
||||
|
||||
final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId);
|
||||
mIconHelper.load(uri, docMimeType, docFlags, docIcon, mIconThumb, mIconMime, null);
|
||||
mIconHelper.load(uri, docMimeType, docFlags, docIcon, docLastModified, mIconThumb,
|
||||
mIconMime, null);
|
||||
|
||||
mTitle.setText(docDisplayName, TextView.BufferType.SPANNABLE);
|
||||
mTitle.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -30,7 +30,7 @@ import android.view.View;
|
||||
import com.android.documentsui.testing.ClipDatas;
|
||||
import com.android.documentsui.testing.DragEvents;
|
||||
import com.android.documentsui.testing.TestTimer;
|
||||
import com.android.documentsui.testing.TestViews;
|
||||
import com.android.documentsui.testing.Views;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -53,7 +53,7 @@ public class ItemDragListenerTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mTestView = TestViews.createTestView();
|
||||
mTestView = Views.createTestView();
|
||||
|
||||
mTestTimer = new TestTimer();
|
||||
mTestDragHost = new TestDragHost();
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.ComponentCallbacks2;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
import android.net.Uri;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.documentsui.ThumbnailCache.Result;
|
||||
import com.android.documentsui.testing.Bitmaps;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class ThumbnailCacheTest {
|
||||
|
||||
private static final Uri URI_0 = Uri.parse("content://authority/document/0");
|
||||
private static final Uri URI_1 = Uri.parse("content://authority/document/1");
|
||||
|
||||
private static final Point SMALL_SIZE = new Point(1, 1);
|
||||
private static final Point MID_SIZE = new Point(2, 2);
|
||||
private static final Point LARGE_SIZE = new Point(3, 3);
|
||||
|
||||
private static final Bitmap SMALL_BITMAP = Bitmaps.createTestBitmap(1, 1);
|
||||
private static final Bitmap MIDSIZE_BITMAP = Bitmaps.createTestBitmap(2, 2);
|
||||
private static final Bitmap LARGE_BITMAP = Bitmaps.createTestBitmap(3, 3);
|
||||
|
||||
private static final long LAST_MODIFIED = 100;
|
||||
|
||||
private static final int CACHE_SIZE_LIMIT =
|
||||
MIDSIZE_BITMAP.getByteCount() + LARGE_BITMAP.getByteCount();
|
||||
|
||||
private ThumbnailCache mCache;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mCache = new ThumbnailCache(CACHE_SIZE_LIMIT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMiss() {
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_1, MID_SIZE);
|
||||
|
||||
assertMiss(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHit_Exact() {
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_0, MID_SIZE);
|
||||
|
||||
assertHitExact(result);
|
||||
assertSame(MIDSIZE_BITMAP, result.getThumbnail());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHit_Smaller() {
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_0, LARGE_SIZE);
|
||||
|
||||
assertHitSmaller(result);
|
||||
assertSame(MIDSIZE_BITMAP, result.getThumbnail());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHit_Larger() {
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_0, SMALL_SIZE);
|
||||
|
||||
assertHitLarger(result);
|
||||
assertSame(MIDSIZE_BITMAP, result.getThumbnail());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHit_Larger_HasBothSize() {
|
||||
mCache.putThumbnail(URI_0, LARGE_SIZE, LARGE_BITMAP, LAST_MODIFIED);
|
||||
mCache.putThumbnail(URI_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_0, MID_SIZE);
|
||||
|
||||
assertHitLarger(result);
|
||||
assertSame(LARGE_BITMAP, result.getThumbnail());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHit_Exact_MultiplePut() {
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
|
||||
|
||||
Bitmap localBitmap = Bitmaps.createTestBitmap(MID_SIZE.x, MID_SIZE.y);
|
||||
long localLastModified = LAST_MODIFIED + 100;
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, localBitmap, localLastModified);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_0, MID_SIZE);
|
||||
|
||||
assertHitExact(result);
|
||||
assertSame(localBitmap, result.getThumbnail());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHit_EqualLastModified() {
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_0, MID_SIZE);
|
||||
|
||||
assertEquals(LAST_MODIFIED, result.getLastModified());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEvictOldest_SizeExceeded() {
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
|
||||
mCache.putThumbnail(URI_1, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED);
|
||||
mCache.putThumbnail(URI_1, LARGE_SIZE, LARGE_BITMAP, LAST_MODIFIED);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_0, MID_SIZE);
|
||||
|
||||
assertMiss(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheShrink_OnTrimMemory_Moderate() {
|
||||
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
|
||||
mCache.putThumbnail(URI_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED);
|
||||
mCache.putThumbnail(URI_0, LARGE_SIZE, LARGE_BITMAP, LAST_MODIFIED);
|
||||
|
||||
mCache.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE);
|
||||
|
||||
Result result = mCache.getThumbnail(URI_0, MID_SIZE);
|
||||
assertMiss(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheShrink_OnTrimMemory_Background() {
|
||||
mCache.putThumbnail(URI_0, LARGE_SIZE, LARGE_BITMAP, LAST_MODIFIED);
|
||||
mCache.putThumbnail(URI_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED);
|
||||
|
||||
mCache.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
|
||||
|
||||
// Math here (size of each pixel omitted):
|
||||
// Limit = midSize + largeSize = 2 * 2 + 3 * 3 = 13, so after all putThumbnail the cache is
|
||||
// full.
|
||||
//
|
||||
// HalfLimit = Limit / 2 = 5. After evicting largeSize bitmap, cache size decreases to 4,
|
||||
// which is smaller than 5. Then smallSize bitmap remains.
|
||||
Result result = mCache.getThumbnail(URI_0, MID_SIZE);
|
||||
assertHitSmaller(result);
|
||||
assertSame(SMALL_BITMAP, result.getThumbnail());
|
||||
}
|
||||
|
||||
private static void assertMiss(Result result) {
|
||||
assertEquals(Result.CACHE_MISS, result.getStatus());
|
||||
assertFalse(result.isExactHit());
|
||||
assertFalse(result.isHit());
|
||||
}
|
||||
|
||||
private static void assertHitExact(Result result) {
|
||||
assertEquals(Result.CACHE_HIT_EXACT, result.getStatus());
|
||||
assertTrue(result.isExactHit());
|
||||
assertTrue(result.isHit());
|
||||
}
|
||||
|
||||
private static void assertHitSmaller(Result result) {
|
||||
assertEquals(Result.CACHE_HIT_SMALLER, result.getStatus());
|
||||
assertFalse(result.isExactHit());
|
||||
assertTrue(result.isHit());
|
||||
}
|
||||
|
||||
private static void assertHitLarger(Result result) {
|
||||
assertEquals(Result.CACHE_HIT_LARGER, result.getStatus());
|
||||
assertFalse(result.isExactHit());
|
||||
assertTrue(result.isHit());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.testing;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
public final class Bitmaps {
|
||||
|
||||
private Bitmaps() {}
|
||||
|
||||
public static Bitmap createTestBitmap(int width, int height) {
|
||||
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,14 +20,14 @@ import android.content.ClipData;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/**
|
||||
* Test support for working with {@link ClipData} instances.
|
||||
*/
|
||||
public final class ClipDatas {
|
||||
|
||||
private ClipDatas() {}
|
||||
|
||||
public static ClipData createTestClipData() {
|
||||
ClipData data = Mockito.mock(ClipData.class);
|
||||
final ClipData data = Mockito.mock(ClipData.class);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,9 +21,6 @@ import android.view.DragEvent;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/**
|
||||
* Test support for working with {@link DragEvents} instances.
|
||||
*/
|
||||
public final class DragEvents {
|
||||
|
||||
private DragEvents() {}
|
||||
@@ -41,4 +38,5 @@ public final class DragEvents {
|
||||
|
||||
return dropEvent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,15 +20,12 @@ import android.view.View;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/**
|
||||
* Test support for working with {@link TestViews} instances.
|
||||
*/
|
||||
public final class TestViews {
|
||||
public final class Views {
|
||||
|
||||
private TestViews() {}
|
||||
private Views() {}
|
||||
|
||||
public static View createTestView() {
|
||||
View view = Mockito.mock(View.class);
|
||||
final View view = Mockito.mock(View.class);
|
||||
Mockito.doCallRealMethod().when(view).setTag(Mockito.anyInt(), Mockito.any());
|
||||
Mockito.doCallRealMethod().when(view).getTag(Mockito.anyInt());
|
||||
|
||||
Reference in New Issue
Block a user