• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.UnsupportContentTypeException;
21 import com.android.mms.LogTag;
22 import com.android.mms.MmsConfig;
23 import android.drm.mobile1.DrmException;
24 import com.android.mms.drm.DrmWrapper;
25 import com.google.android.mms.ContentType;
26 import com.google.android.mms.MmsException;
27 import com.google.android.mms.pdu.PduBody;
28 import com.google.android.mms.pdu.PduPart;
29 
30 import org.w3c.dom.smil.SMILMediaElement;
31 import org.w3c.dom.smil.SMILRegionElement;
32 import org.w3c.dom.smil.SMILRegionMediaElement;
33 import org.w3c.dom.smil.Time;
34 import org.w3c.dom.smil.TimeList;
35 
36 import android.content.Context;
37 import android.util.Log;
38 
39 import java.io.IOException;
40 
41 public class MediaModelFactory {
42     private static final String TAG = "Mms:media";
43 
getMediaModel(Context context, SMILMediaElement sme, LayoutModel layouts, PduBody pb)44     public static MediaModel getMediaModel(Context context,
45             SMILMediaElement sme, LayoutModel layouts, PduBody pb)
46             throws DrmException, IOException, IllegalArgumentException, MmsException {
47         String tag = sme.getTagName();
48         String src = sme.getSrc();
49         PduPart part = findPart(pb, src);
50 
51         if (sme instanceof SMILRegionMediaElement) {
52             return getRegionMediaModel(
53                     context, tag, src, (SMILRegionMediaElement) sme, layouts, part);
54         } else {
55             return getGenericMediaModel(
56                     context, tag, src, sme, part, null);
57         }
58     }
59 
findPart(PduBody pb, String src)60     private static PduPart findPart(PduBody pb, String src) {
61         PduPart part = null;
62 
63         if (src != null) {
64             src = unescapeXML(src);
65             if (src.startsWith("cid:")) {
66                 part = pb.getPartByContentId("<" + src.substring("cid:".length()) + ">");
67             } else {
68                 part = pb.getPartByName(src);
69                 if (part == null) {
70                     part = pb.getPartByFileName(src);
71                     if (part == null) {
72                         part = pb.getPartByContentLocation(src);
73                     }
74                 }
75             }
76         }
77 
78         if (part != null) {
79             return part;
80         }
81 
82         throw new IllegalArgumentException("No part found for the model.");
83     }
84 
unescapeXML(String str)85     private static String unescapeXML(String str) {
86         return str.replaceAll("&lt;","<")
87             .replaceAll("&gt;", ">")
88             .replaceAll("&quot;","\"")
89             .replaceAll("&apos;","'")
90             .replaceAll("&amp;", "&");
91     }
92 
getRegionMediaModel(Context context, String tag, String src, SMILRegionMediaElement srme, LayoutModel layouts, PduPart part)93     private static MediaModel getRegionMediaModel(Context context,
94             String tag, String src, SMILRegionMediaElement srme,
95             LayoutModel layouts, PduPart part) throws DrmException, IOException, MmsException {
96         SMILRegionElement sre = srme.getRegion();
97         if (sre != null) {
98             RegionModel region = layouts.findRegionById(sre.getId());
99             if (region != null) {
100                 return getGenericMediaModel(context, tag, src, srme, part, region);
101             }
102         } else {
103             String rId = null;
104 
105             if (tag.equals(SmilHelper.ELEMENT_TAG_TEXT)) {
106                 rId = LayoutModel.TEXT_REGION_ID;
107             } else {
108                 rId = LayoutModel.IMAGE_REGION_ID;
109             }
110 
111             RegionModel region = layouts.findRegionById(rId);
112             if (region != null) {
113                 return getGenericMediaModel(context, tag, src, srme, part, region);
114             }
115         }
116 
117         throw new IllegalArgumentException("Region not found or bad region ID.");
118     }
119 
getGenericMediaModel(Context context, String tag, String src, SMILMediaElement sme, PduPart part, RegionModel regionModel)120     private static MediaModel getGenericMediaModel(Context context,
121             String tag, String src, SMILMediaElement sme, PduPart part,
122             RegionModel regionModel) throws DrmException, IOException, MmsException {
123         byte[] bytes = part.getContentType();
124         if (bytes == null) {
125             throw new IllegalArgumentException(
126                     "Content-Type of the part may not be null.");
127         }
128 
129         String contentType = new String(bytes);
130         MediaModel media = null;
131         if (ContentType.isDrmType(contentType)) {
132             DrmWrapper wrapper = new DrmWrapper(
133                     contentType, part.getDataUri(), part.getData());
134             if (tag.equals(SmilHelper.ELEMENT_TAG_TEXT)) {
135                 media = new TextModel(context, contentType, src,
136                         part.getCharset(), wrapper, regionModel);
137             } else if (tag.equals(SmilHelper.ELEMENT_TAG_IMAGE)) {
138                 media = new ImageModel(context, contentType, src,
139                         wrapper, regionModel);
140             } else if (tag.equals(SmilHelper.ELEMENT_TAG_VIDEO)) {
141                 media = new VideoModel(context, contentType, src,
142                         wrapper, regionModel);
143             } else if (tag.equals(SmilHelper.ELEMENT_TAG_AUDIO)) {
144                 media = new AudioModel(context, contentType, src,
145                         wrapper);
146             } else if (tag.equals(SmilHelper.ELEMENT_TAG_REF)) {
147                 String drmContentType = wrapper.getContentType();
148                 if (ContentType.isTextType(drmContentType)) {
149                     media = new TextModel(context, contentType, src,
150                             part.getCharset(), wrapper, regionModel);
151                 } else if (ContentType.isImageType(drmContentType)) {
152                     media = new ImageModel(context, contentType, src,
153                             wrapper, regionModel);
154                 } else if (ContentType.isVideoType(drmContentType)) {
155                     media = new VideoModel(context, contentType, src,
156                             wrapper, regionModel);
157                 } else if (ContentType.isAudioType(drmContentType)) {
158                     media = new AudioModel(context, contentType, src,
159                             wrapper);
160                 } else {
161                     throw new UnsupportContentTypeException(
162                         "Unsupported Content-Type: " + drmContentType);
163                 }
164             } else {
165                 throw new IllegalArgumentException("Unsupported TAG: " + tag);
166             }
167         } else {
168             if (tag.equals(SmilHelper.ELEMENT_TAG_TEXT)) {
169                 media = new TextModel(context, contentType, src,
170                         part.getCharset(), part.getData(), regionModel);
171             } else if (tag.equals(SmilHelper.ELEMENT_TAG_IMAGE)) {
172                 media = new ImageModel(context, contentType, src,
173                         part.getDataUri(), regionModel);
174             } else if (tag.equals(SmilHelper.ELEMENT_TAG_VIDEO)) {
175                 media = new VideoModel(context, contentType, src,
176                         part.getDataUri(), regionModel);
177             } else if (tag.equals(SmilHelper.ELEMENT_TAG_AUDIO)) {
178                 media = new AudioModel(context, contentType, src,
179                         part.getDataUri());
180             } else if (tag.equals(SmilHelper.ELEMENT_TAG_REF)) {
181                 if (ContentType.isTextType(contentType)) {
182                     media = new TextModel(context, contentType, src,
183                             part.getCharset(), part.getData(), regionModel);
184                 } else if (ContentType.isImageType(contentType)) {
185                     media = new ImageModel(context, contentType, src,
186                             part.getDataUri(), regionModel);
187                 } else if (ContentType.isVideoType(contentType)) {
188                     media = new VideoModel(context, contentType, src,
189                             part.getDataUri(), regionModel);
190                 } else if (ContentType.isAudioType(contentType)) {
191                     media = new AudioModel(context, contentType, src,
192                             part.getDataUri());
193                 } else {
194                     throw new UnsupportContentTypeException(
195                         "Unsupported Content-Type: " + contentType);
196                 }
197             } else {
198                 throw new IllegalArgumentException("Unsupported TAG: " + tag);
199             }
200         }
201 
202         // Set 'begin' property.
203         int begin = 0;
204         TimeList tl = sme.getBegin();
205         if ((tl != null) && (tl.getLength() > 0)) {
206             // We only support a single begin value.
207             Time t = tl.item(0);
208             begin = (int) (t.getResolvedOffset() * 1000);
209         }
210         media.setBegin(begin);
211 
212         // Set 'duration' property.
213         int duration = (int) (sme.getDur() * 1000);
214         if (duration <= 0) {
215             tl = sme.getEnd();
216             if ((tl != null) && (tl.getLength() > 0)) {
217                 // We only support a single end value.
218                 Time t = tl.item(0);
219                 if (t.getTimeType() != Time.SMIL_TIME_INDEFINITE) {
220                     duration = (int) (t.getResolvedOffset() * 1000) - begin;
221 
222                     if (duration == 0 &&
223                             (media instanceof AudioModel || media instanceof VideoModel)) {
224                         duration = MmsConfig.getMinimumSlideElementDuration();
225                         if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
226                             Log.d(TAG, "[MediaModelFactory] compute new duration for " + tag +
227                                     ", duration=" + duration);
228                         }
229                     }
230                 }
231             }
232         }
233 
234         media.setDuration(duration);
235 
236         if (!MmsConfig.getSlideDurationEnabled()) {
237             /**
238              * Because The slide duration is not supported by mmsc,
239              * the device has to set fill type as FILL_FREEZE.
240              * If not, the media will disappear while rotating the screen
241              * in the slide show play view.
242              */
243             media.setFill(sme.FILL_FREEZE);
244         } else {
245             // Set 'fill' property.
246             media.setFill(sme.getFill());
247         }
248         return media;
249     }
250 }
251