Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.messaging.datamodel.media;
     17 
     18 import android.content.res.Resources;
     19 import android.graphics.Bitmap;
     20 import android.graphics.BitmapFactory;
     21 import android.graphics.drawable.Drawable;
     22 
     23 import com.android.messaging.util.Assert;
     24 import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
     25 
     26 import java.util.Arrays;
     27 import java.util.List;
     28 
     29 /**
     30  * A cache-facing image resource that's much more compact than the raw Bitmap objects stored in
     31  * {@link com.android.messaging.datamodel.media.DecodedImageResource}.
     32  *
     33  * This resource is created from a regular Bitmap-based ImageResource before being pushed to
     34  * {@link com.android.messaging.datamodel.media.MediaCache}, if the image request
     35  * allows for resource encoding/compression.
     36  *
     37  * During resource retrieval on cache hit,
     38  * {@link #getMediaDecodingRequest(MediaRequest)} is invoked to create a async
     39  * decode task, which decodes the compressed byte array back to a regular image resource to
     40  * be consumed by the UI.
     41  */
     42 public class EncodedImageResource extends ImageResource {
     43     private final byte[] mImageBytes;
     44 
     45     public EncodedImageResource(String key, byte[] imageBytes, int orientation) {
     46         super(key, orientation);
     47         mImageBytes = imageBytes;
     48     }
     49 
     50     @Override
     51     @DoesNotRunOnMainThread
     52     public Bitmap getBitmap() {
     53         acquireLock();
     54         try {
     55             // This should only be called during the decode request.
     56             Assert.isNotMainThread();
     57             return BitmapFactory.decodeByteArray(mImageBytes, 0, mImageBytes.length);
     58         } finally {
     59             releaseLock();
     60         }
     61     }
     62 
     63     @Override
     64     public byte[] getBytes() {
     65         acquireLock();
     66         try {
     67             return Arrays.copyOf(mImageBytes, mImageBytes.length);
     68         } finally {
     69             releaseLock();
     70         }
     71     }
     72 
     73     @Override
     74     public Bitmap reuseBitmap() {
     75         return null;
     76     }
     77 
     78     @Override
     79     public boolean supportsBitmapReuse() {
     80         return false;
     81     }
     82 
     83     @Override
     84     public int getMediaSize() {
     85         return mImageBytes.length;
     86     }
     87 
     88     @Override
     89     protected void close() {
     90     }
     91 
     92     @Override
     93     public Drawable getDrawable(Resources resources) {
     94         return null;
     95     }
     96 
     97     @Override
     98     boolean isEncoded() {
     99         return true;
    100     }
    101 
    102     @Override
    103     MediaRequest<? extends RefCountedMediaResource> getMediaDecodingRequest(
    104             final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
    105         Assert.isTrue(isEncoded());
    106         return new DecodeImageRequest();
    107     }
    108 
    109     /**
    110      * A MediaRequest that decodes the encoded image resource. This class is chained to the
    111      * original media request that requested the image, so it inherits the listener and
    112      * properties such as binding.
    113      */
    114     private class DecodeImageRequest implements MediaRequest<ImageResource> {
    115         public DecodeImageRequest() {
    116             // Hold a ref onto the encoded resource before the request finishes.
    117             addRef();
    118         }
    119 
    120         @Override
    121         public String getKey() {
    122             return EncodedImageResource.this.getKey();
    123         }
    124 
    125         @Override
    126         @DoesNotRunOnMainThread
    127         public ImageResource loadMediaBlocking(List<MediaRequest<ImageResource>> chainedTask)
    128                 throws Exception {
    129             Assert.isNotMainThread();
    130             acquireLock();
    131             try {
    132                 final Bitmap decodedBitmap = BitmapFactory.decodeByteArray(mImageBytes, 0,
    133                         mImageBytes.length);
    134                 return new DecodedImageResource(getKey(), decodedBitmap, getOrientation());
    135             } finally {
    136                 releaseLock();
    137                 release();
    138             }
    139         }
    140 
    141         @Override
    142         public MediaCache<ImageResource> getMediaCache() {
    143             // Decoded resource is non-cachable, it's for UI consumption only (for now at least)
    144             return null;
    145         }
    146 
    147         @Override
    148         public int getCacheId() {
    149             return 0;
    150         }
    151 
    152         @Override
    153         public int getRequestType() {
    154             return REQUEST_DECODE_MEDIA;
    155         }
    156 
    157         @Override
    158         public MediaRequestDescriptor<ImageResource> getDescriptor() {
    159             return null;
    160         }
    161     }
    162 }
    163