ImageModel.java revision 10eed0e3020e3eb0612747fe39e0f6117222dd95
1/* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.mms.model; 19 20import com.android.mms.ContentRestrictionException; 21import com.android.mms.LogTag; 22import com.android.mms.MmsConfig; 23import com.android.mms.dom.smil.SmilMediaElementImpl; 24import com.android.mms.drm.DrmWrapper; 25import com.android.mms.ui.UriImage; 26import com.android.mms.ui.MessageUtils; 27import com.google.android.mms.MmsException; 28import com.google.android.mms.pdu.PduBody; 29import com.google.android.mms.pdu.PduPart; 30import com.google.android.mms.pdu.PduPersister; 31 32import org.w3c.dom.events.Event; 33import org.w3c.dom.smil.ElementTime; 34 35import android.content.ContentUris; 36import android.content.Context; 37import android.drm.mobile1.DrmException; 38import android.graphics.Bitmap; 39import android.graphics.BitmapFactory; 40import android.net.Uri; 41import android.text.TextUtils; 42import android.util.Config; 43import android.util.Log; 44 45import java.io.FileNotFoundException; 46import java.io.IOException; 47import java.io.InputStream; 48import java.lang.ref.SoftReference; 49 50 51public class ImageModel extends RegionMediaModel { 52 private static final String TAG = "Mms/image"; 53 private static final boolean DEBUG = false; 54 private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV; 55 56 private static final int THUMBNAIL_BOUNDS_LIMIT = 480; 57 58 private int mWidth; 59 private int mHeight; 60 private SoftReference<Bitmap> mBitmapCache = new SoftReference<Bitmap>(null); 61 62 public ImageModel(Context context, Uri uri, RegionModel region) 63 throws MmsException { 64 super(context, SmilHelper.ELEMENT_TAG_IMAGE, uri, region); 65 initModelFromUri(uri); 66 checkContentRestriction(); 67 } 68 69 public ImageModel(Context context, String contentType, String src, 70 Uri uri, RegionModel region) throws DrmException, MmsException { 71 super(context, SmilHelper.ELEMENT_TAG_IMAGE, 72 contentType, src, uri, region); 73 decodeImageBounds(); 74 } 75 76 public ImageModel(Context context, String contentType, String src, 77 DrmWrapper wrapper, RegionModel regionModel) throws IOException { 78 super(context, SmilHelper.ELEMENT_TAG_IMAGE, contentType, src, 79 wrapper, regionModel); 80 } 81 82 private void initModelFromUri(Uri uri) throws MmsException { 83 UriImage uriImage = new UriImage(mContext, uri); 84 85 mContentType = uriImage.getContentType(); 86 if (TextUtils.isEmpty(mContentType)) { 87 throw new MmsException("Type of media is unknown."); 88 } 89 mSrc = uriImage.getSrc(); 90 mWidth = uriImage.getWidth(); 91 mHeight = uriImage.getHeight(); 92 93 if (LOCAL_LOGV) { 94 Log.v(TAG, "New ImageModel created:" 95 + " mSrc=" + mSrc 96 + " mContentType=" + mContentType 97 + " mUri=" + uri); 98 } 99 } 100 101 private void decodeImageBounds() throws DrmException { 102 UriImage uriImage = new UriImage(mContext, getUriWithDrmCheck()); 103 mWidth = uriImage.getWidth(); 104 mHeight = uriImage.getHeight(); 105 106 if (LOCAL_LOGV) { 107 Log.v(TAG, "Image bounds: " + mWidth + "x" + mHeight); 108 } 109 } 110 111 // EventListener Interface 112 public void handleEvent(Event evt) { 113 if (evt.getType().equals(SmilMediaElementImpl.SMIL_MEDIA_START_EVENT)) { 114 mVisible = true; 115 } else if (mFill != ElementTime.FILL_FREEZE) { 116 mVisible = false; 117 } 118 119 notifyModelChanged(false); 120 } 121 122 public int getWidth() { 123 return mWidth; 124 } 125 126 public int getHeight() { 127 return mHeight; 128 } 129 130 protected void checkContentRestriction() throws ContentRestrictionException { 131 ContentRestriction cr = ContentRestrictionFactory.getContentRestriction(); 132 cr.checkImageContentType(mContentType); 133 cr.checkResolution(mWidth, mHeight); 134 } 135 136 public Bitmap getBitmap() { 137 return internalGetBitmap(getUri()); 138 } 139 140 public Bitmap getBitmapWithDrmCheck() throws DrmException { 141 return internalGetBitmap(getUriWithDrmCheck()); 142 } 143 144 private Bitmap internalGetBitmap(Uri uri) { 145 Bitmap bm = mBitmapCache.get(); 146 if (bm == null) { 147 try { 148 bm = createThumbnailBitmap(THUMBNAIL_BOUNDS_LIMIT, uri); 149 if (bm != null) { 150 mBitmapCache = new SoftReference<Bitmap>(bm); 151 } 152 } catch (OutOfMemoryError ex) { 153 // fall through and return a null bitmap. The callers can handle a null 154 // result and show R.drawable.ic_missing_thumbnail_picture 155 } 156 } 157 return bm; 158 } 159 160 private Bitmap createThumbnailBitmap(int thumbnailBoundsLimit, Uri uri) { 161 int outWidth = mWidth; 162 int outHeight = mHeight; 163 164 int s = 1; 165 while ((outWidth / s > thumbnailBoundsLimit) 166 || (outHeight / s > thumbnailBoundsLimit)) { 167 s *= 2; 168 } 169 if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 170 Log.v(TAG, "createThumbnailBitmap: scale=" + s + ", w=" + outWidth / s 171 + ", h=" + outHeight / s); 172 } 173 BitmapFactory.Options options = new BitmapFactory.Options(); 174 options.inSampleSize = s; 175 176 InputStream input = null; 177 try { 178 input = mContext.getContentResolver().openInputStream(uri); 179 return BitmapFactory.decodeStream(input, null, options); 180 } catch (FileNotFoundException e) { 181 Log.e(TAG, e.getMessage(), e); 182 return null; 183 } catch (OutOfMemoryError ex) { 184 MessageUtils.writeHprofDataToFile(); 185 throw ex; 186 } finally { 187 if (input != null) { 188 try { 189 input.close(); 190 } catch (IOException e) { 191 Log.e(TAG, e.getMessage(), e); 192 } 193 } 194 } 195 } 196 197 @Override 198 public boolean getMediaResizable() { 199 return true; 200 } 201 202 @Override 203 protected void resizeMedia(int byteLimit, long messageId) throws MmsException { 204 UriImage image = new UriImage(mContext, getUri()); 205 PduPart part = image.getResizedImageAsPart( 206 MmsConfig.getMaxImageWidth(), 207 MmsConfig.getMaxImageHeight(), 208 byteLimit); 209 210 PduPersister persister = PduPersister.getPduPersister(mContext); 211 this.mSize = part.getData().length; 212 Uri newUri = persister.persistPart(part, messageId); 213 setUri(newUri); 214 } 215} 216