ImageModel.java revision 9242286c35743422051d439d7460cd0a1426899c
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.dom.smil.SmilMediaElementImpl;
23import com.android.mms.drm.DrmWrapper;
24import com.android.mms.ui.UriImage;
25import com.android.mms.ui.MessageUtils;
26import com.google.android.mms.MmsException;
27
28import org.w3c.dom.events.Event;
29import org.w3c.dom.smil.ElementTime;
30
31import android.content.Context;
32import android.drm.mobile1.DrmException;
33import android.graphics.Bitmap;
34import android.graphics.BitmapFactory;
35import android.net.Uri;
36import android.text.TextUtils;
37import android.util.Config;
38import android.util.Log;
39
40import java.io.FileNotFoundException;
41import java.io.IOException;
42import java.io.InputStream;
43import java.lang.ref.SoftReference;
44
45
46public class ImageModel extends RegionMediaModel {
47    private static final String TAG = "Mms/image";
48    private static final boolean DEBUG = false;
49    private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
50
51    private static final int THUMBNAIL_BOUNDS_LIMIT = 480;
52
53    private int mWidth;
54    private int mHeight;
55    private SoftReference<Bitmap> mBitmapCache = new SoftReference<Bitmap>(null);
56
57    public ImageModel(Context context, Uri uri, RegionModel region)
58            throws MmsException {
59        super(context, SmilHelper.ELEMENT_TAG_IMAGE, uri, region);
60        initModelFromUri(uri);
61        checkContentRestriction();
62    }
63
64    public ImageModel(Context context, String contentType, String src,
65            Uri uri, RegionModel region) throws DrmException, MmsException {
66        super(context, SmilHelper.ELEMENT_TAG_IMAGE,
67                contentType, src, uri, region);
68        decodeImageBounds();
69    }
70
71    public ImageModel(Context context, String contentType, String src,
72            DrmWrapper wrapper, RegionModel regionModel) throws IOException {
73        super(context, SmilHelper.ELEMENT_TAG_IMAGE, contentType, src,
74                wrapper, regionModel);
75    }
76
77    private void initModelFromUri(Uri uri) throws MmsException {
78        UriImage uriImage = new UriImage(mContext, uri);
79
80        mContentType = uriImage.getContentType();
81        if (TextUtils.isEmpty(mContentType)) {
82            throw new MmsException("Type of media is unknown.");
83        }
84        mSrc = uriImage.getSrc();
85        mWidth = uriImage.getWidth();
86        mHeight = uriImage.getHeight();
87
88        if (LOCAL_LOGV) {
89            Log.v(TAG, "New ImageModel created:"
90                    + " mSrc=" + mSrc
91                    + " mContentType=" + mContentType
92                    + " mUri=" + uri);
93        }
94    }
95
96    private void decodeImageBounds() throws DrmException {
97        UriImage uriImage = new UriImage(mContext, getUriWithDrmCheck());
98        mWidth = uriImage.getWidth();
99        mHeight = uriImage.getHeight();
100
101        if (LOCAL_LOGV) {
102            Log.v(TAG, "Image bounds: " + mWidth + "x" + mHeight);
103        }
104    }
105
106    // EventListener Interface
107    public void handleEvent(Event evt) {
108        if (evt.getType().equals(SmilMediaElementImpl.SMIL_MEDIA_START_EVENT)) {
109            mVisible = true;
110        } else if (mFill != ElementTime.FILL_FREEZE) {
111            mVisible = false;
112        }
113
114        notifyModelChanged(false);
115    }
116
117    public int getWidth() {
118        return mWidth;
119    }
120
121    public int getHeight() {
122        return mHeight;
123    }
124
125    protected void checkContentRestriction() throws ContentRestrictionException {
126        ContentRestriction cr = ContentRestrictionFactory.getContentRestriction();
127        cr.checkImageContentType(mContentType);
128        cr.checkResolution(mWidth, mHeight);
129    }
130
131    public Bitmap getBitmap() {
132        Bitmap bm = mBitmapCache.get();
133        if (bm == null) {
134            bm = createThumbnailBitmap(THUMBNAIL_BOUNDS_LIMIT, getUri());
135            mBitmapCache = new SoftReference<Bitmap>(bm);
136        }
137        return bm;
138    }
139
140    public Bitmap getBitmapWithDrmCheck() throws DrmException {
141        Bitmap bm = mBitmapCache.get();
142        if (bm == null) {
143            bm = createThumbnailBitmap(THUMBNAIL_BOUNDS_LIMIT, getUriWithDrmCheck());
144            mBitmapCache = new SoftReference<Bitmap>(bm);
145        }
146        return bm;
147    }
148
149    private Bitmap createThumbnailBitmap(int thumbnailBoundsLimit, Uri uri) {
150        int outWidth = mWidth;
151        int outHeight = mHeight;
152
153        int s = 1;
154        while ((outWidth / s > thumbnailBoundsLimit)
155                || (outHeight / s > thumbnailBoundsLimit)) {
156            s *= 2;
157        }
158        if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
159            Log.v(TAG, "createThumbnailBitmap: scale=" + s + ", w=" + outWidth / s
160                    + ", h=" + outHeight / s);
161        }
162        BitmapFactory.Options options = new BitmapFactory.Options();
163        options.inSampleSize = s;
164
165        InputStream input = null;
166        try {
167            input = mContext.getContentResolver().openInputStream(uri);
168            return BitmapFactory.decodeStream(input, null, options);
169        } catch (FileNotFoundException e) {
170            Log.e(TAG, e.getMessage(), e);
171            return null;
172        } catch (OutOfMemoryError ex) {
173            MessageUtils.writeHprofDataToFile();
174            throw ex;
175        } finally {
176            if (input != null) {
177                try {
178                    input.close();
179                } catch (IOException e) {
180                    Log.e(TAG, e.getMessage(), e);
181                }
182            }
183        }
184    }
185
186}
187