@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);
 }
예제 #2
0
 @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());
 }
예제 #3
0
 @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);
 }
예제 #5
0
 @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);
   }
 }
예제 #7
0
 /** 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);
 }
예제 #9
0
 /** 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);
   }
 }
예제 #11
0
 /**
  * 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);
   }
 }
예제 #12
0
  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);
   }
 }
예제 #14
0
  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);
  }
예제 #15
0
 /**
  * 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);
   }
 }
예제 #16
0
 /**
  * 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);
 }
예제 #21
0
    /** 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);
  }
예제 #25
0
  @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());
 }
예제 #27
0
 @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);
  }
예제 #29
0
 @Override
 protected int getIntermediateImageEndOffset(
     CloseableReference<PooledByteBuffer> imageBytesRef) {
   return imageBytesRef.get().size();
 }