Initial checkin of AOSP Messaging app.
b/23110861 Change-Id: I9aa980d7569247d6b2ca78f5dcb4502e1eaadb8a
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* 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.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.android.messaging.ui.OrientedBitmapDrawable;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
|
||||
import com.android.messaging.util.ImageUtils;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.OsUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Container class for holding a bitmap resource used by the MediaResourceManager. This resource
|
||||
* can both be cached (albeit not very storage-efficiently) and directly used by the UI.
|
||||
*/
|
||||
public class DecodedImageResource extends ImageResource {
|
||||
private static final int BITMAP_QUALITY = 100;
|
||||
private static final int COMPRESS_QUALITY = 50;
|
||||
|
||||
private Bitmap mBitmap;
|
||||
private final int mOrientation;
|
||||
private boolean mCacheable = true;
|
||||
|
||||
public DecodedImageResource(final String key, final Bitmap bitmap, int orientation) {
|
||||
super(key, orientation);
|
||||
mBitmap = bitmap;
|
||||
mOrientation = orientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the contained bitmap.
|
||||
*/
|
||||
@Override
|
||||
public Bitmap getBitmap() {
|
||||
acquireLock();
|
||||
try {
|
||||
return mBitmap;
|
||||
} finally {
|
||||
releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to reuse the bitmap in the image resource and repurpose it for something else.
|
||||
* After this, the image resource will relinquish ownership on the bitmap resource so that
|
||||
* it doesn't try to recycle it when getting closed.
|
||||
*/
|
||||
@Override
|
||||
public Bitmap reuseBitmap() {
|
||||
acquireLock();
|
||||
try {
|
||||
assertSingularRefCount();
|
||||
final Bitmap retBitmap = mBitmap;
|
||||
mBitmap = null;
|
||||
return retBitmap;
|
||||
} finally {
|
||||
releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsBitmapReuse() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
acquireLock();
|
||||
try {
|
||||
return ImageUtils.bitmapToBytes(mBitmap, BITMAP_QUALITY);
|
||||
} catch (final Exception e) {
|
||||
LogUtil.e(LogUtil.BUGLE_TAG, "Error trying to get the bitmap bytes " + e);
|
||||
} finally {
|
||||
releaseLock();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the orientation of the image as one of the ExifInterface.ORIENTATION_* constants
|
||||
*/
|
||||
@Override
|
||||
public int getOrientation() {
|
||||
return mOrientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMediaSize() {
|
||||
acquireLock();
|
||||
try {
|
||||
Assert.notNull(mBitmap);
|
||||
if (OsUtil.isAtLeastKLP()) {
|
||||
return mBitmap.getAllocationByteCount();
|
||||
} else {
|
||||
return mBitmap.getRowBytes() * mBitmap.getHeight();
|
||||
}
|
||||
} finally {
|
||||
releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close() {
|
||||
acquireLock();
|
||||
try {
|
||||
if (mBitmap != null) {
|
||||
mBitmap.recycle();
|
||||
mBitmap = null;
|
||||
}
|
||||
} finally {
|
||||
releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getDrawable(Resources resources) {
|
||||
acquireLock();
|
||||
try {
|
||||
Assert.notNull(mBitmap);
|
||||
return OrientedBitmapDrawable.create(getOrientation(), resources, mBitmap);
|
||||
} finally {
|
||||
releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isCacheable() {
|
||||
return mCacheable;
|
||||
}
|
||||
|
||||
public void setCacheable(final boolean cacheable) {
|
||||
mCacheable = cacheable;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
MediaRequest<? extends RefCountedMediaResource> getMediaEncodingRequest(
|
||||
final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
|
||||
Assert.isFalse(isEncoded());
|
||||
if (getBitmap().hasAlpha()) {
|
||||
// We can't compress images with alpha, as JPEG encoding doesn't support this.
|
||||
return null;
|
||||
}
|
||||
return new EncodeImageRequest((MediaRequest<ImageResource>) originalRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* A MediaRequest that encodes the contained image resource.
|
||||
*/
|
||||
private class EncodeImageRequest implements MediaRequest<ImageResource> {
|
||||
private final MediaRequest<ImageResource> mOriginalImageRequest;
|
||||
|
||||
public EncodeImageRequest(MediaRequest<ImageResource> originalImageRequest) {
|
||||
mOriginalImageRequest = originalImageRequest;
|
||||
// Hold a ref onto the encoded resource before the request finishes.
|
||||
DecodedImageResource.this.addRef();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return DecodedImageResource.this.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DoesNotRunOnMainThread
|
||||
public ImageResource loadMediaBlocking(List<MediaRequest<ImageResource>> chainedRequests)
|
||||
throws Exception {
|
||||
Assert.isNotMainThread();
|
||||
acquireLock();
|
||||
Bitmap scaledBitmap = null;
|
||||
try {
|
||||
Bitmap bitmap = getBitmap();
|
||||
Assert.isFalse(bitmap.hasAlpha());
|
||||
final int bitmapWidth = bitmap.getWidth();
|
||||
final int bitmapHeight = bitmap.getHeight();
|
||||
// The original bitmap was loaded using sub-sampling which was fast in terms of
|
||||
// loading speed, but not optimized for caching, encoding and rendering (since
|
||||
// bitmap resizing to fit the UI image views happens on the UI thread and should
|
||||
// be avoided if possible). Therefore, try to resize the bitmap to the exact desired
|
||||
// size before compressing it.
|
||||
if (bitmapWidth > 0 && bitmapHeight > 0 &&
|
||||
mOriginalImageRequest instanceof ImageRequest<?>) {
|
||||
final ImageRequestDescriptor descriptor =
|
||||
((ImageRequest<?>) mOriginalImageRequest).getDescriptor();
|
||||
final float targetScale = Math.max(
|
||||
(float) descriptor.desiredWidth / bitmapWidth,
|
||||
(float) descriptor.desiredHeight / bitmapHeight);
|
||||
final int targetWidth = (int) (bitmapWidth * targetScale);
|
||||
final int targetHeight = (int) (bitmapHeight * targetScale);
|
||||
// Only try to scale down the image to the desired size.
|
||||
if (targetScale < 1.0f && targetWidth > 0 && targetHeight > 0 &&
|
||||
targetWidth != bitmapWidth && targetHeight != bitmapHeight) {
|
||||
scaledBitmap = bitmap =
|
||||
Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, false);
|
||||
}
|
||||
}
|
||||
byte[] encodedBytes = ImageUtils.bitmapToBytes(bitmap, COMPRESS_QUALITY);
|
||||
return new EncodedImageResource(getKey(), encodedBytes, getOrientation());
|
||||
} catch (Exception ex) {
|
||||
// Something went wrong during bitmap compression, fall back to just using the
|
||||
// original bitmap.
|
||||
LogUtil.e(LogUtil.BUGLE_IMAGE_TAG, "Error compressing bitmap", ex);
|
||||
return DecodedImageResource.this;
|
||||
} finally {
|
||||
if (scaledBitmap != null && scaledBitmap != getBitmap()) {
|
||||
scaledBitmap.recycle();
|
||||
scaledBitmap = null;
|
||||
}
|
||||
releaseLock();
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaCache<ImageResource> getMediaCache() {
|
||||
return mOriginalImageRequest.getMediaCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCacheId() {
|
||||
return mOriginalImageRequest.getCacheId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRequestType() {
|
||||
return REQUEST_ENCODE_MEDIA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaRequestDescriptor<ImageResource> getDescriptor() {
|
||||
return mOriginalImageRequest.getDescriptor();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user