@Test public void testLocalVideoMicroThumbnailSuccess() throws Exception { when(mProducerListener.requiresExtraMap(mRequestId)).thenReturn(true); when(android.media.ThumbnailUtils.createVideoThumbnail( mFile.getPath(), MediaStore.Images.Thumbnails.MICRO_KIND)) .thenReturn(mBitmap); doAnswer( new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { mCloseableReference = ((CloseableReference) invocation.getArguments()[0]).clone(); return null; } }) .when(mConsumer) .onNewResult(any(CloseableReference.class), eq(true)); mLocalVideoThumbnailProducer.produceResults(mConsumer, mProducerContext); mExecutor.runUntilIdle(); assertEquals(1, mCloseableReference.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); assertEquals( mBitmap, mCloseableReference.getUnderlyingReferenceTestOnly().get().getUnderlyingBitmap()); verify(mProducerListener).onProducerStart(mRequestId, PRODUCER_NAME); Map<String, String> thumbnailFoundMap = ImmutableMap.of(LocalVideoThumbnailProducer.CREATED_THUMBNAIL, "true"); verify(mProducerListener) .onProducerFinishWithSuccess(mRequestId, PRODUCER_NAME, thumbnailFoundMap); }
@Test public void testTrimUnsuccessful() { CloseableReference<byte[]> arrayRef = mArray.get(7); mArray.trim(MemoryTrimType.OnCloseToDalvikHeapLimit); assertSame(arrayRef.get(), mArray.mByteArraySoftRef.get()); assertEquals(0, mArray.mSemaphore.availablePermits()); }
@Test public void testGet() throws Exception { CloseableReference<byte[]> arrayRef = mArray.get(1); assertSame(mArray.mByteArraySoftRef.get(), arrayRef.get()); assertEquals(4, arrayRef.get().length); assertEquals(0, mArray.mSemaphore.availablePermits()); }
@Test public void testLocalVideoMiniThumbnailSuccess() throws Exception { when(mImageRequest.getPreferredWidth()).thenReturn(100); when(mImageRequest.getPreferredHeight()).thenReturn(100); when(android.media.ThumbnailUtils.createVideoThumbnail( mFile.getPath(), MediaStore.Images.Thumbnails.MINI_KIND)) .thenReturn(mBitmap); doAnswer( new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { mCloseableReference = ((CloseableReference) invocation.getArguments()[0]).clone(); return null; } }) .when(mConsumer) .onNewResult(any(CloseableReference.class), eq(true)); mLocalVideoThumbnailProducer.produceResults(mConsumer, mProducerContext); mExecutor.runUntilIdle(); assertEquals(1, mCloseableReference.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); assertEquals( mBitmap, mCloseableReference.getUnderlyingReferenceTestOnly().get().getUnderlyingBitmap()); verify(mProducerListener).onProducerStart(mRequestId, PRODUCER_NAME); verify(mProducerListener).onProducerFinishWithSuccess(mRequestId, PRODUCER_NAME, null); }
@Override protected void onDestroy() { super.onDestroy(); if (mCurrentBitmapReference != null && mCurrentBitmapReference.isValid()) { mCurrentBitmapReference.close(); } }
private void doPostprocessing( CloseableReference<CloseableImage> sourceImageRef, boolean isLast) { Preconditions.checkArgument(CloseableReference.isValid(sourceImageRef)); if (!shouldPostprocess(sourceImageRef.get())) { maybeNotifyOnNewResult(sourceImageRef, isLast); return; } mListener.onProducerStart(mRequestId, NAME); CloseableReference<CloseableImage> destImageRef = null; try { try { destImageRef = postprocessInternal(sourceImageRef.get()); } catch (Exception e) { mListener.onProducerFinishWithFailure( mRequestId, NAME, e, getExtraMap(mListener, mRequestId, mPostprocessor)); maybeNotifyOnFailure(e); return; } mListener.onProducerFinishWithSuccess( mRequestId, NAME, getExtraMap(mListener, mRequestId, mPostprocessor)); maybeNotifyOnNewResult(destImageRef, isLast); } finally { CloseableReference.closeSafely(destImageRef); } }
/** Notifies consumer of new result and finishes if the result is final. */ private void handleResult(final CloseableImage decodedImage, final boolean isFinal) { CloseableReference<CloseableImage> decodedImageRef = CloseableReference.of(decodedImage); try { maybeFinish(isFinal); getConsumer().onNewResult(decodedImageRef, isFinal); } finally { CloseableReference.closeSafely(decodedImageRef); } }
private void setSourceImageRef(CloseableReference<CloseableImage> sourceImageRef) { CloseableReference<CloseableImage> oldSourceImageRef; synchronized (RepeatedPostprocessorConsumer.this) { if (mIsClosed) { return; } oldSourceImageRef = mSourceImageRef; mSourceImageRef = CloseableReference.cloneOrNull(sourceImageRef); } CloseableReference.closeSafely(oldSourceImageRef); }
/** Updates the decode job. */ protected synchronized boolean updateDecodeJob( CloseableReference<PooledByteBuffer> imageBytesRef, boolean isLast) { // ignore invalid intermediate results (should not happen ever, but being defensive) if (!isLast && !CloseableReference.isValid(imageBytesRef)) { return false; } CloseableReference.closeSafely(mImageBytesRef); mImageBytesRef = CloseableReference.cloneOrNull(imageBytesRef); mIsLast = isLast; return true; }
private CloseableReference<CloseableImage> postprocessInternal(CloseableImage sourceImage) { CloseableStaticBitmap staticBitmap = (CloseableStaticBitmap) sourceImage; Bitmap sourceBitmap = staticBitmap.getUnderlyingBitmap(); CloseableReference<Bitmap> bitmapRef = mPostprocessor.process(sourceBitmap, mBitmapFactory); int rotationAngle = staticBitmap.getRotationAngle(); try { return CloseableReference.<CloseableImage>of( new CloseableStaticBitmap(bitmapRef, sourceImage.getQualityInfo(), rotationAngle)); } finally { CloseableReference.closeSafely(bitmapRef); } }
/** * Returns whether the image is stored in the bitmap memory cache. * * @param imageRequest the imageRequest for the image to be looked up. * @return true if the image was found in the bitmap memory cache, false otherwise. */ public boolean isInBitmapMemoryCache(final ImageRequest imageRequest) { if (imageRequest == null) { return false; } final CacheKey cacheKey = mCacheKeyFactory.getBitmapCacheKey(imageRequest, null); CloseableReference<CloseableImage> ref = mBitmapMemoryCache.get(cacheKey); try { return CloseableReference.isValid(ref); } finally { CloseableReference.closeSafely(ref); } }
public void setImageBitmap(CloseableReference<Bitmap> bitmapReference) { // Note: This is not a recommended way to load Bitmap. // This sample is intended to test the internal methods, and show how to use them. Bitmap bitmap = bitmapReference.get(); mImageView.setImageBitmap(bitmap); mImageView.getLayoutParams().width = (int) (bitmap.getWidth() * mConversionFactor); mImageView.getLayoutParams().height = (int) (bitmap.getHeight() * mConversionFactor); if (mCurrentBitmapReference != null && mCurrentBitmapReference.isValid()) { mCurrentBitmapReference.close(); } mCurrentBitmapReference = bitmapReference; }
private void updateInternal() { CloseableReference<CloseableImage> sourceImageRef; synchronized (RepeatedPostprocessorConsumer.this) { if (mIsClosed) { return; } sourceImageRef = CloseableReference.cloneOrNull(mSourceImageRef); } try { getConsumer().onNewResult(sourceImageRef, false /* isLast */); } finally { CloseableReference.closeSafely(sourceImageRef); } }
private CloseableReference<Bitmap> decodeStaticImageFromStream( InputStream inputStream, BitmapFactory.Options options) { Preconditions.checkNotNull(inputStream); int sizeInBytes = BitmapUtil.getSizeInByteForBitmap( options.outWidth, options.outHeight, options.inPreferredConfig); final Bitmap bitmapToReuse = mBitmapPool.get(sizeInBytes); if (bitmapToReuse == null) { throw new NullPointerException("BitmapPool.get returned null"); } options.inBitmap = bitmapToReuse; Bitmap decodedBitmap; ByteBuffer byteBuffer = mDecodeBuffers.acquire(); if (byteBuffer == null) { byteBuffer = ByteBuffer.allocate(DECODE_BUFFER_SIZE); } try { options.inTempStorage = byteBuffer.array(); decodedBitmap = BitmapFactory.decodeStream(inputStream, null, options); } catch (RuntimeException re) { mBitmapPool.release(bitmapToReuse); throw re; } finally { mDecodeBuffers.release(byteBuffer); } if (bitmapToReuse != decodedBitmap) { mBitmapPool.release(bitmapToReuse); decodedBitmap.recycle(); throw new IllegalStateException(); } return CloseableReference.of(decodedBitmap, mBitmapPool); }
/** * Checks if the Bitmap created by Fresco's internal methods is same as the Bitmap created by * Bitmap class' methods. * * @param bitmapReference The Bitmap Reference created to check * @param reference The Bitmap generated from Bitmap class function */ public void checkValid(CloseableReference<Bitmap> bitmapReference, Bitmap reference) { if (Build.VERSION.SDK_INT < 12) { mValidityTextView.setText(R.string.ignoring_check); } else if (bitmapReference.get().sameAs(reference)) { mValidityTextView.setText(R.string.correct_bitmap); } else { mValidityTextView.setText(R.string.incorrect_bitmap); } }
/** * Finishes if not already finished and {@code finish} is specified. * * <p>If just finished, the intermediate image gets released. */ private synchronized void maybeFinish(boolean finish) { if (mIsFinished) { return; } mIsFinished = finish; if (finish) { CloseableReference.closeSafely(mImageBytesRef); mImageBytesRef = null; } }
private synchronized boolean setRunningIfDirtyAndNotRunning() { if (!mIsClosed && mIsDirty && !mIsPostProcessingRunning && CloseableReference.isValid(mSourceImageRef)) { mIsPostProcessingRunning = true; return true; } return false; }
private void updateSourceImageRef( @Nullable CloseableReference<CloseableImage> sourceImageRef, boolean isLast) { CloseableReference<CloseableImage> oldSourceImageRef; boolean shouldSubmit; synchronized (PostprocessorConsumer.this) { if (mIsClosed) { return; } oldSourceImageRef = mSourceImageRef; mSourceImageRef = CloseableReference.cloneOrNull(sourceImageRef); mIsLast = isLast; mIsDirty = true; shouldSubmit = setRunningIfDirtyAndNotRunning(); } CloseableReference.closeSafely(oldSourceImageRef); if (shouldSubmit) { submitPostprocessing(); } }
@Override protected void onNewResultImpl(CloseableReference<CloseableImage> newResult, boolean isLast) { if (!CloseableReference.isValid(newResult)) { // try to propagate if the last result is invalid if (isLast) { maybeNotifyOnNewResult(null, true); } // ignore if invalid return; } updateSourceImageRef(newResult, isLast); }
@Test public void testEncodedMemoryCacheGetNotFoundNextProducerSuccess() { setupEncodedMemoryCacheGetNotFound(); setupNextProducerStreamingSuccess(); mEncodedMemoryCacheProducer.produceResults(mConsumer, mProducerContext); verify(mMemoryCache, never()).cache(mCacheKey, mIntermediateImageReference); ArgumentCaptor<CloseableReference> argumentCaptor = ArgumentCaptor.forClass(CloseableReference.class); verify(mMemoryCache).cache(eq(mCacheKey), argumentCaptor.capture()); CloseableReference<PooledByteBuffer> capturedRef = (CloseableReference<PooledByteBuffer>) argumentCaptor.getValue(); Assert.assertSame( mFinalImageReference.getUnderlyingReferenceTestOnly(), capturedRef.getUnderlyingReferenceTestOnly()); verify(mConsumer).onNewResult(mIntermediateEncodedImage, false); verify(mConsumer).onNewResult(mFinalEncodedImage, true); Assert.assertTrue(EncodedImage.isValid(mFinalEncodedImageClone)); verify(mProducerListener).onProducerStart(mRequestId, PRODUCER_NAME); Map<String, String> extraMap = ImmutableMap.of(EncodedMemoryCacheProducer.VALUE_FOUND, "false"); verify(mProducerListener).onProducerFinishWithSuccess(mRequestId, PRODUCER_NAME, extraMap); }
/** Performs the decode synchronously. */ private void doDecode(long queueTime) { CloseableReference<PooledByteBuffer> bytesRef; boolean isLast; synchronized (ProgressiveDecoder.this) { bytesRef = mImageBytesRef; mImageBytesRef = null; isLast = mIsLast; mIsDecodeSubmitted = false; mLastDecodeTime = SystemClock.uptimeMillis(); } try { if (isFinished() || !CloseableReference.isValid(bytesRef)) { return; } ImageFormat format = isLast ? ImageFormat.UNKNOWN : getImageFormat(bytesRef); int length = isLast ? bytesRef.get().size() : getIntermediateImageEndOffset(bytesRef); QualityInfo quality = isLast ? ImmutableQualityInfo.FULL_QUALITY : getQualityInfo(bytesRef); mProducerListener.onProducerStart(mProducerContext.getId(), PRODUCER_NAME); CloseableImage decodedImage; try { decodedImage = mImageDecoder.decodeImage(bytesRef, format, length, quality, mImageDecodeOptions); } catch (Exception e) { Map<String, String> extraMap = getExtraMap(queueTime, quality, isLast); mProducerListener.onProducerFinishWithFailure( mProducerContext.getId(), PRODUCER_NAME, e, extraMap); handleError(e); return; } Map<String, String> extraMap = getExtraMap(queueTime, quality, isLast); mProducerListener.onProducerFinishWithSuccess( mProducerContext.getId(), PRODUCER_NAME, extraMap); handleResult(decodedImage, isLast); } finally { CloseableReference.closeSafely(bytesRef); } }
private boolean close() { CloseableReference<CloseableImage> oldSourceImageRef; synchronized (RepeatedPostprocessorConsumer.this) { if (mIsClosed) { return false; } oldSourceImageRef = mSourceImageRef; mSourceImageRef = null; mIsClosed = true; } CloseableReference.closeSafely(oldSourceImageRef); return true; }
@Test public void testBitmapMemoryCacheGetSuccessful() { setupBitmapCacheGetSuccess(); when(mProducerContext.getLowestPermittedRequestLevel()) .thenReturn(ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE); mBitmapMemoryCacheGetProducer.produceResults(mConsumer, mProducerContext); verify(mConsumer).onNewResult(mFinalImageReference, true); verify(mProducerListener).onProducerStart(mRequestId, PRODUCER_NAME); Map<String, String> extraMap = ImmutableMap.of(BitmapMemoryCacheProducer.EXTRA_CACHED_VALUE_FOUND, "true"); verify(mProducerListener).onProducerFinishWithSuccess(mRequestId, PRODUCER_NAME, extraMap); Assert.assertTrue(!mFinalImageReference.isValid()); }
@Before public void setUp() { MockitoAnnotations.initMocks(this); mEncodedMemoryCacheProducer = new EncodedMemoryCacheProducer(mMemoryCache, mCacheKeyFactory, mNextProducer); mCacheKey = new SimpleCacheKey("http://dummy.uri"); mPooledByteBuffer1 = mock(PooledByteBuffer.class); mPooledByteBuffer2 = mock(PooledByteBuffer.class); mFinalImageReference = CloseableReference.of(mPooledByteBuffer1); mIntermediateImageReference = CloseableReference.of(mPooledByteBuffer2); mFinalImageReferenceClone = mFinalImageReference.clone(); mFinalEncodedImage = new EncodedImage(mFinalImageReference); mIntermediateEncodedImage = new EncodedImage(mIntermediateImageReference); mFinalEncodedImageClone = new EncodedImage(mFinalImageReferenceClone); when(mMemoryCache.cache(mCacheKey, mFinalImageReference)).thenReturn(mFinalImageReferenceClone); when(mProducerContext.getImageRequest()).thenReturn(mImageRequest); when(mProducerContext.getListener()).thenReturn(mProducerListener); when(mProducerListener.requiresExtraMap(mRequestId)).thenReturn(true); when(mProducerContext.getId()).thenReturn(mRequestId); when(mProducerContext.getLowestPermittedRequestLevel()) .thenReturn(ImageRequest.RequestLevel.FULL_FETCH); when(mCacheKeyFactory.getEncodedCacheKey(mImageRequest)).thenReturn(mCacheKey); }
@Test public void testGet_Realloc() { CloseableReference<byte[]> arrayRef = mArray.get(1); final byte[] smallArray = arrayRef.get(); arrayRef.close(); arrayRef = mArray.get(7); assertEquals(8, arrayRef.get().length); assertSame(mArray.mByteArraySoftRef.get(), arrayRef.get()); assertNotSame(smallArray, arrayRef.get()); }
@Test public void testEncodedMemoryCacheGetSuccessful() { setupEncodedMemoryCacheGetSuccess(); when(mProducerContext.getLowestPermittedRequestLevel()) .thenReturn(ImageRequest.RequestLevel.ENCODED_MEMORY_CACHE); mEncodedMemoryCacheProducer.produceResults(mConsumer, mProducerContext); ArgumentCaptor<EncodedImage> argumentCaptor = ArgumentCaptor.forClass(EncodedImage.class); verify(mConsumer).onNewResult(argumentCaptor.capture(), eq(true)); EncodedImage encodedImage = argumentCaptor.getValue(); Assert.assertSame( mFinalEncodedImage.getUnderlyingReferenceTestOnly(), encodedImage.getUnderlyingReferenceTestOnly()); verify(mProducerListener).onProducerStart(mRequestId, PRODUCER_NAME); Map<String, String> extraMap = ImmutableMap.of(EncodedMemoryCacheProducer.VALUE_FOUND, "true"); verify(mProducerListener).onProducerFinishWithSuccess(mRequestId, PRODUCER_NAME, extraMap); Assert.assertFalse(mFinalImageReference.isValid()); }
@Override protected synchronized boolean updateDecodeJob( CloseableReference<PooledByteBuffer> imageBytesRef, boolean isLast) { boolean ret = super.updateDecodeJob(imageBytesRef, isLast); if (!isLast && CloseableReference.isValid(imageBytesRef)) { if (!mProgressiveJpegParser.parseMoreData(imageBytesRef)) { return false; } int scanNum = mProgressiveJpegParser.getBestScanNumber(); if (scanNum <= mLastScheduledScanNumber || scanNum < mProgressiveJpegConfig.getNextScanNumberToDecode(mLastScheduledScanNumber)) { return false; } mLastScheduledScanNumber = scanNum; } return ret; }
@Before public void setUp() { MockitoAnnotations.initMocks(this); mBitmapMemoryCacheGetProducer = new BitmapMemoryCacheGetProducer(mMemoryCache, mCacheKeyFactory, mInputProducer); mCloseableImage1 = mock(CloseableImage.class); mFinalImageReference = CloseableReference.of(mCloseableImage1); when(mCloseableImage1.getQualityInfo()).thenReturn(ImmutableQualityInfo.FULL_QUALITY); when(mProducerContext.getImageRequest()).thenReturn(mImageRequest); when(mProducerContext.getListener()).thenReturn(mProducerListener); when(mProducerContext.getId()).thenReturn(mRequestId); when(mProducerListener.requiresExtraMap(mRequestId)).thenReturn(true); when(mProducerContext.getLowestPermittedRequestLevel()) .thenReturn(ImageRequest.RequestLevel.FULL_FETCH); when(mProducerContext.getCallerContext()).thenReturn(PRODUCER_NAME); when(mCacheKeyFactory.getBitmapCacheKey(mImageRequest, PRODUCER_NAME)).thenReturn(mCacheKey); }
@Override protected int getIntermediateImageEndOffset( CloseableReference<PooledByteBuffer> imageBytesRef) { return imageBytesRef.get().size(); }