Initial checkin of AOSP Messaging app.
b/23110861 Change-Id: I9aa980d7569247d6b2ca78f5dcb4502e1eaadb8a
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.datamodel.media;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FakeImageRequest implements MediaRequest<FakeImageResource> {
|
||||
public static final String INVALID_KEY = "invalid";
|
||||
private final String mKey;
|
||||
private final int mSize;
|
||||
|
||||
public FakeImageRequest(final String key, final int size) {
|
||||
mKey = key;
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FakeImageResource loadMediaBlocking(List<MediaRequest<FakeImageResource>> chainedTask)
|
||||
throws Exception {
|
||||
if (TextUtils.equals(mKey, INVALID_KEY)) {
|
||||
throw new Exception();
|
||||
} else {
|
||||
return new FakeImageResource(mSize, mKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCacheId() {
|
||||
return FakeMediaCacheManager.FAKE_IMAGE_CACHE;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public MediaCache<FakeImageResource> getMediaCache() {
|
||||
return (MediaCache<FakeImageResource>) MediaCacheManager.get().getOrCreateMediaCacheById(
|
||||
getCacheId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRequestType() {
|
||||
return MediaRequest.REQUEST_LOAD_MEDIA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaRequestDescriptor<FakeImageResource> getDescriptor() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.datamodel.media;
|
||||
|
||||
public class FakeImageResource extends RefCountedMediaResource {
|
||||
private boolean mClosed = false;
|
||||
private boolean mCached = false;
|
||||
private final int mSize;
|
||||
private final String mImageId;
|
||||
|
||||
public FakeImageResource(final int size, final String imageId) {
|
||||
super(null);
|
||||
mSize = size;
|
||||
mImageId = imageId;
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return mClosed;
|
||||
}
|
||||
|
||||
public String getImageId() {
|
||||
return mImageId;
|
||||
}
|
||||
|
||||
public void setCached(final boolean cached) {
|
||||
mCached = cached;
|
||||
}
|
||||
|
||||
public boolean getCached() {
|
||||
return mCached;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMediaSize() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close() {
|
||||
mClosed = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.datamodel.media;
|
||||
|
||||
public class FakeMediaCacheManager extends MediaCacheManager {
|
||||
// List of available fake cache ids.
|
||||
public static final int FAKE_IMAGE_CACHE = 1;
|
||||
public static final int FAKE_BATCH_IMAGE_CACHE = 2;
|
||||
|
||||
@Override
|
||||
public MediaCache<?> createMediaCacheById(final int id) {
|
||||
switch (id) {
|
||||
case FAKE_IMAGE_CACHE:
|
||||
// Make a cache of only 3 KB of data.
|
||||
return new MediaCache<FakeImageResource>(3, FAKE_IMAGE_CACHE, "FakeImageCache");
|
||||
|
||||
case FAKE_BATCH_IMAGE_CACHE:
|
||||
return new MediaCache<FakeImageResource>(10, FAKE_BATCH_IMAGE_CACHE,
|
||||
"FakeBatchImageCache");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.datamodel.media;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.android.messaging.BugleTestCase;
|
||||
import com.android.messaging.FakeFactory;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.MemoryCacheManager;
|
||||
import com.android.messaging.util.ImageUtils;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@SmallTest
|
||||
public class ImageRequestTest extends BugleTestCase {
|
||||
private static final int DOWNSAMPLE_IMAGE_SIZE = 2;
|
||||
|
||||
@Spy protected ImageUtils spyImageUtils;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
FakeFactory.register(getTestContext())
|
||||
.withMemoryCacheManager(new MemoryCacheManager())
|
||||
.withMediaCacheManager(new BugleMediaCacheManager());
|
||||
spyImageUtils = Mockito.spy(new ImageUtils());
|
||||
ImageUtils.set(spyImageUtils);
|
||||
}
|
||||
|
||||
public void testLoadImageUnspecifiedSize() {
|
||||
final String uriString = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
|
||||
getContext().getPackageName() + "/" + R.drawable.ic_audio_light;
|
||||
final Uri uri = Uri.parse(uriString);
|
||||
final UriImageRequest imageRequest = new UriImageRequest(getContext(),
|
||||
new UriImageRequestDescriptor(uri));
|
||||
try {
|
||||
final ImageResource imageResource = imageRequest.loadMediaBlocking(null);
|
||||
final ArgumentCaptor<BitmapFactory.Options> options =
|
||||
ArgumentCaptor.forClass(BitmapFactory.Options.class);
|
||||
Mockito.verify(spyImageUtils).calculateInSampleSize(
|
||||
options.capture(),
|
||||
Matchers.eq(ImageRequest.UNSPECIFIED_SIZE),
|
||||
Matchers.eq(ImageRequest.UNSPECIFIED_SIZE));
|
||||
assertEquals(1, options.getValue().inSampleSize);
|
||||
assertNotNull(imageResource);
|
||||
assertNotNull(imageResource.getBitmap());
|
||||
|
||||
// Make sure there's no scaling on the bitmap.
|
||||
final int bitmapWidth = imageResource.getBitmap().getWidth();
|
||||
final int bitmapHeight = imageResource.getBitmap().getHeight();
|
||||
assertEquals(options.getValue().outWidth, bitmapWidth);
|
||||
assertEquals(options.getValue().outHeight, bitmapHeight);
|
||||
} catch (final IOException e) {
|
||||
fail("IO exception while trying to load image resource");
|
||||
}
|
||||
}
|
||||
|
||||
public void testLoadImageWithDownsampling() {
|
||||
final String uriString = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
|
||||
getContext().getPackageName() + "/" + R.drawable.ic_audio_light;
|
||||
final Uri uri = Uri.parse(uriString);
|
||||
final UriImageRequest imageRequest = new UriImageRequest(getContext(),
|
||||
new UriImageRequestDescriptor(uri, DOWNSAMPLE_IMAGE_SIZE, DOWNSAMPLE_IMAGE_SIZE,
|
||||
false, true /* isStatic */, false /* cropToCircle */,
|
||||
ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
|
||||
ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */));
|
||||
try {
|
||||
final ImageResource imageResource = imageRequest.loadMediaBlocking(null);
|
||||
final ArgumentCaptor<BitmapFactory.Options> options =
|
||||
ArgumentCaptor.forClass(BitmapFactory.Options.class);
|
||||
Mockito.verify(spyImageUtils).calculateInSampleSize(
|
||||
options.capture(),
|
||||
Matchers.eq(DOWNSAMPLE_IMAGE_SIZE), Matchers.eq(DOWNSAMPLE_IMAGE_SIZE));
|
||||
assertNotSame(1, options.getValue().inSampleSize);
|
||||
assertNotNull(imageResource);
|
||||
assertNotNull(imageResource.getBitmap());
|
||||
|
||||
// Make sure there's down sampling on the bitmap.
|
||||
final int bitmapWidth = imageResource.getBitmap().getWidth();
|
||||
final int bitmapHeight = imageResource.getBitmap().getHeight();
|
||||
assertTrue(bitmapWidth >= DOWNSAMPLE_IMAGE_SIZE &&
|
||||
bitmapHeight >= DOWNSAMPLE_IMAGE_SIZE &&
|
||||
(bitmapWidth <= DOWNSAMPLE_IMAGE_SIZE * 4 ||
|
||||
bitmapHeight <= DOWNSAMPLE_IMAGE_SIZE * 4));
|
||||
} catch (final IOException e) {
|
||||
fail("IO exception while trying to load image resource");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.datamodel.media;
|
||||
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.android.messaging.BugleTestCase;
|
||||
import com.android.messaging.FakeFactory;
|
||||
import com.android.messaging.datamodel.MemoryCacheManager;
|
||||
import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@SmallTest
|
||||
public class MediaResourceManagerTest extends BugleTestCase {
|
||||
private static final int KB = 1024;
|
||||
|
||||
// Loaded image resource from the MediaResourceManager callback.
|
||||
private FakeImageResource mImageResource;
|
||||
private BindableMediaRequest<FakeImageResource> mImageRequest;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
FakeFactory.register(getTestContext())
|
||||
.withMemoryCacheManager(new MemoryCacheManager())
|
||||
.withMediaCacheManager(new FakeMediaCacheManager());
|
||||
}
|
||||
|
||||
public void testLoadFromCache() {
|
||||
final MediaResourceManager mediaResourceManager =
|
||||
new MediaResourceManager();
|
||||
MediaCacheManager.get().reclaim();
|
||||
assertNotNull(mediaResourceManager);
|
||||
|
||||
// Load one image of 1KB
|
||||
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
|
||||
assertEquals("image1", mImageResource.getImageId());
|
||||
final FakeImageResource loadedResource = mImageResource;
|
||||
|
||||
// Load the same image.
|
||||
loadImage(mediaResourceManager, "image1", 1 * KB, true /* shouldBeCached */, false);
|
||||
assertEquals(loadedResource, mImageResource);
|
||||
}
|
||||
|
||||
public void testCacheEviction() {
|
||||
final MediaResourceManager mediaResourceManager =
|
||||
new MediaResourceManager();
|
||||
MediaCacheManager.get().reclaim();
|
||||
assertNotNull(mediaResourceManager);
|
||||
|
||||
// Load one image of 1KB
|
||||
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
|
||||
assertEquals("image1", mImageResource.getImageId());
|
||||
|
||||
// Load another image
|
||||
loadImage(mediaResourceManager, "image2", 2 * KB, false /* shouldBeCached */, false);
|
||||
assertEquals("image2", mImageResource.getImageId());
|
||||
|
||||
// Load another image. This should fill the cache and cause eviction of image1.
|
||||
loadImage(mediaResourceManager, "image3", 2 * KB, false /* shouldBeCached */, false);
|
||||
assertEquals("image3", mImageResource.getImageId());
|
||||
|
||||
// Load image1. It shouldn't be cached any more.
|
||||
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
|
||||
assertEquals("image1", mImageResource.getImageId());
|
||||
}
|
||||
|
||||
public void testReclaimMemoryFromMediaCache() {
|
||||
final MediaResourceManager mediaResourceManager =
|
||||
new MediaResourceManager();
|
||||
MediaCacheManager.get().reclaim();
|
||||
assertNotNull(mediaResourceManager);
|
||||
|
||||
// Load one image of 1KB
|
||||
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
|
||||
assertEquals("image1", mImageResource.getImageId());
|
||||
|
||||
// Purge everything from the cache, now the image should no longer be cached.
|
||||
MediaCacheManager.get().reclaim();
|
||||
|
||||
// The image resource should have no ref left.
|
||||
assertEquals(0, mImageResource.getRefCount());
|
||||
assertTrue(mImageResource.isClosed());
|
||||
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
|
||||
assertEquals("image1", mImageResource.getImageId());
|
||||
}
|
||||
|
||||
public void testLoadInvalidImage() {
|
||||
final MediaResourceManager mediaResourceManager =
|
||||
new MediaResourceManager();
|
||||
MediaCacheManager.get().reclaim();
|
||||
assertNotNull(mediaResourceManager);
|
||||
|
||||
// Test the failure case with invalid resource.
|
||||
loadImage(mediaResourceManager, FakeImageRequest.INVALID_KEY, 1 * KB, false,
|
||||
true /* shouldFail */);
|
||||
}
|
||||
|
||||
public void testLoadImageSynchronously() {
|
||||
final MediaResourceManager mediaResourceManager =
|
||||
new MediaResourceManager();
|
||||
MediaCacheManager.get().reclaim();
|
||||
assertNotNull(mediaResourceManager);
|
||||
|
||||
// Test a normal sync load.
|
||||
final FakeImageRequest request = new FakeImageRequest("image1", 1 * KB);
|
||||
final FakeImageResource resource = mediaResourceManager.requestMediaResourceSync(request);
|
||||
assertNotNull(resource);
|
||||
assertFalse(resource.isClosed());
|
||||
assertNotSame(0, resource.getRefCount());
|
||||
resource.release();
|
||||
|
||||
// Test a failed sync load.
|
||||
final FakeImageRequest invalidRequest =
|
||||
new FakeImageRequest(FakeImageRequest.INVALID_KEY, 1 * KB);
|
||||
assertNull(mediaResourceManager.requestMediaResourceSync(invalidRequest));
|
||||
}
|
||||
|
||||
private void loadImage(final MediaResourceManager manager, final String key,
|
||||
final int size, final boolean shouldBeCached, final boolean shouldFail) {
|
||||
try {
|
||||
final CountDownLatch signal = new CountDownLatch(1);
|
||||
mImageRequest = AsyncMediaRequestWrapper.createWith(new FakeImageRequest(key, size),
|
||||
createAssertListener(shouldBeCached, shouldFail, signal));
|
||||
mImageRequest.bind("1");
|
||||
manager.requestMediaResourceAsync(mImageRequest);
|
||||
|
||||
// Wait for the asynchronous callback before proceeding.
|
||||
signal.await();
|
||||
} catch (final InterruptedException e) {
|
||||
fail("Something interrupted the signal await.");
|
||||
}
|
||||
}
|
||||
|
||||
private MediaResourceLoadListener<FakeImageResource> createAssertListener(
|
||||
final boolean shouldBeCached, final boolean shouldFail, final CountDownLatch signal) {
|
||||
return new MediaResourceLoadListener<FakeImageResource>() {
|
||||
@Override
|
||||
public void onMediaResourceLoaded(final MediaRequest<FakeImageResource> request,
|
||||
final FakeImageResource resource, final boolean isCached) {
|
||||
assertEquals(mImageRequest, request);
|
||||
assertNotNull(resource);
|
||||
assertFalse(resource.isClosed());
|
||||
assertNotSame(0, resource.getRefCount());
|
||||
assertFalse(shouldFail);
|
||||
assertEquals(shouldBeCached, resource.getCached());
|
||||
resource.setCached(true);
|
||||
mImageResource = resource;
|
||||
signal.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaResourceLoadError(
|
||||
final MediaRequest<FakeImageResource> request, final Exception exception) {
|
||||
assertTrue(shouldFail);
|
||||
mImageResource = null;
|
||||
signal.countDown();
|
||||
}};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user