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