MediaModel.java revision 07dde49d355fbe188b1ead3276544c4a324ebd11
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.R; 21import com.android.mms.drm.DrmUtils; 22import com.android.mms.drm.DrmWrapper; 23import com.google.android.mms.MmsException; 24 25import org.w3c.dom.events.EventListener; 26 27import android.content.ContentResolver; 28import android.content.Context; 29import android.drm.mobile1.DrmException; 30import android.media.MediaPlayer; 31import android.media.MediaMetadataRetriever; 32import android.net.Uri; 33import android.util.Log; 34 35import java.io.FileInputStream; 36import java.io.FileNotFoundException; 37import java.io.IOException; 38import java.io.InputStream; 39import java.util.ArrayList; 40 41public abstract class MediaModel extends Model implements EventListener { 42 private static final String TAG = "MediaModel"; 43 44 protected Context mContext; 45 protected int mBegin; 46 protected int mDuration; 47 protected String mTag; 48 protected String mSrc; 49 protected String mContentType; 50 private Uri mUri; 51 private byte[] mData; 52 protected short mFill; 53 protected int mSize; 54 protected int mSeekTo; 55 protected DrmWrapper mDrmObjectWrapper; 56 57 private final ArrayList<MediaAction> mMediaActions; 58 public static enum MediaAction { 59 NO_ACTIVE_ACTION, 60 START, 61 STOP, 62 PAUSE, 63 SEEK, 64 } 65 66 public MediaModel(Context context, String tag, String contentType, 67 String src, Uri uri) throws MmsException { 68 mContext = context; 69 mTag = tag; 70 mContentType = contentType; 71 mSrc = src; 72 mUri = uri; 73 initMediaSize(); 74 mMediaActions = new ArrayList<MediaAction>(); 75 } 76 77 public MediaModel(Context context, String tag, String contentType, 78 String src, byte[] data) { 79 if (data == null) { 80 throw new IllegalArgumentException("data may not be null."); 81 } 82 83 mContext = context; 84 mTag = tag; 85 mContentType = contentType; 86 mSrc = src; 87 mData = data; 88 mSize = data.length; 89 mMediaActions = new ArrayList<MediaAction>(); 90 } 91 92 public MediaModel(Context context, String tag, String contentType, 93 String src, DrmWrapper wrapper) throws IOException { 94 mContext = context; 95 mTag = tag; 96 mContentType = contentType; 97 mSrc = src; 98 mDrmObjectWrapper = wrapper; 99 mUri = DrmUtils.insert(context, wrapper); 100 mSize = wrapper.getOriginalData().length; 101 mMediaActions = new ArrayList<MediaAction>(); 102 } 103 104 public int getBegin() { 105 return mBegin; 106 } 107 108 public void setBegin(int begin) { 109 mBegin = begin; 110 notifyModelChanged(true); 111 } 112 113 public int getDuration() { 114 return mDuration; 115 } 116 117 public void setDuration(int duration) { 118 if (isPlayable() && (duration < 0)) { 119 // 'indefinite' duration, we should try to find its exact value; 120 try { 121 initMediaDuration(); 122 } catch (MmsException e) { 123 // On error, keep default duration. 124 Log.e(TAG, e.getMessage(), e); 125 return; 126 } 127 } else { 128 mDuration = duration; 129 } 130 notifyModelChanged(true); 131 } 132 133 public String getTag() { 134 return mTag; 135 } 136 137 public String getContentType() { 138 return mContentType; 139 } 140 141 /** 142 * Get the URI of the media without checking DRM rights. Use this method 143 * only if the media is NOT DRM protected. 144 * 145 * @return The URI of the media. 146 */ 147 public Uri getUri() { 148 return mUri; 149 } 150 151 /** 152 * Get the URI of the media with checking DRM rights. Use this method 153 * if the media is probably DRM protected. 154 * 155 * @return The URI of the media. 156 * @throws DrmException Insufficient DRM rights detected. 157 */ 158 public Uri getUriWithDrmCheck() throws DrmException { 159 if (mUri != null) { 160 if (isDrmProtected() && !mDrmObjectWrapper.consumeRights()) { 161 throw new DrmException("Insufficient DRM rights."); 162 } 163 } 164 return mUri; 165 } 166 167 public byte[] getData() throws DrmException { 168 if (mData != null) { 169 if (isDrmProtected() && !mDrmObjectWrapper.consumeRights()) { 170 throw new DrmException( 171 mContext.getString(R.string.insufficient_drm_rights)); 172 } 173 174 byte[] data = new byte[mData.length]; 175 System.arraycopy(mData, 0, data, 0, mData.length); 176 return data; 177 } 178 return null; 179 } 180 181 /** 182 * @param uri the mUri to set 183 */ 184 void setUri(Uri uri) { 185 mUri = uri; 186 } 187 188 /** 189 * @return the mSrc 190 */ 191 public String getSrc() { 192 return mSrc; 193 } 194 195 /** 196 * @return the mFill 197 */ 198 public short getFill() { 199 return mFill; 200 } 201 202 /** 203 * @param fill the mFill to set 204 */ 205 public void setFill(short fill) { 206 mFill = fill; 207 notifyModelChanged(true); 208 } 209 210 public int getMediaSize() { 211 return mSize; 212 } 213 214 public boolean isText() { 215 return mTag.equals(SmilHelper.ELEMENT_TAG_TEXT); 216 } 217 218 public boolean isImage() { 219 return mTag.equals(SmilHelper.ELEMENT_TAG_IMAGE); 220 } 221 222 public boolean isVideo() { 223 return mTag.equals(SmilHelper.ELEMENT_TAG_VIDEO); 224 } 225 226 public boolean isAudio() { 227 return mTag.equals(SmilHelper.ELEMENT_TAG_AUDIO); 228 } 229 230 public boolean isDrmProtected() { 231 return mDrmObjectWrapper != null; 232 } 233 234 public boolean isAllowedToForward() { 235 return mDrmObjectWrapper.isAllowedToForward(); 236 } 237 238 protected void initMediaDuration() throws MmsException { 239 if (mUri == null) { 240 throw new IllegalArgumentException("Uri may not be null."); 241 } 242 243 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 244 retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); 245 int duration = 0; 246 try { 247 retriever.setDataSource(mContext, mUri); 248 String dur = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); 249 if (dur != null) { 250 duration = Integer.parseInt(dur); 251 } 252 mDuration = duration; 253 } catch (Exception ex) { 254 Log.e(TAG, "MediaMetadataRetriever failed to retrieve duration from the media", ex); 255 throw new MmsException(ex); 256 } finally { 257 retriever.release(); 258 } 259 } 260 261 private void initMediaSize() throws MmsException { 262 ContentResolver cr = mContext.getContentResolver(); 263 InputStream input = null; 264 try { 265 input = cr.openInputStream(mUri); 266 if (input instanceof FileInputStream) { 267 // avoid reading the whole stream to get its length 268 FileInputStream f = (FileInputStream) input; 269 mSize = (int) f.getChannel().size(); 270 } else { 271 while (-1 != input.read()) { 272 mSize++; 273 } 274 } 275 276 } catch (IOException e) { 277 // Ignore 278 Log.e(TAG, "IOException caught while opening or reading stream", e); 279 if (e instanceof FileNotFoundException) { 280 throw new MmsException(e.getMessage()); 281 } 282 } finally { 283 if (null != input) { 284 try { 285 input.close(); 286 } catch (IOException e) { 287 // Ignore 288 Log.e(TAG, "IOException caught while closing stream", e); 289 } 290 } 291 } 292 } 293 294 public static boolean isMmsUri(Uri uri) { 295 return uri.getAuthority().startsWith("mms"); 296 } 297 298 public int getSeekTo() { 299 return mSeekTo; 300 } 301 302 public void appendAction(MediaAction action) { 303 mMediaActions.add(action); 304 } 305 306 public MediaAction getCurrentAction() { 307 if (0 == mMediaActions.size()) { 308 return MediaAction.NO_ACTIVE_ACTION; 309 } 310 return mMediaActions.remove(0); 311 } 312 313 protected boolean isPlayable() { 314 return false; 315 } 316 317 public DrmWrapper getDrmObject() { 318 return mDrmObjectWrapper; 319 } 320} 321