public PduBody toPduBody() {
   if (mPduBodyCache == null) {
     mDocumentCache = SmilHelper.getDocument(this);
     mPduBodyCache = makePduBody(mDocumentCache);
   }
   return mPduBodyCache;
 }
 public SMILDocument toSmilDocument() {
   if (mDocumentCache == null) {
     mDocumentCache = SmilHelper.getDocument(this);
   }
   return mDocumentCache;
 }
 public PduBody makeCopy(Context context) {
   return makePduBody(context, SmilHelper.getDocument(this), true);
 }
  private PduBody makePduBody(Context context, SMILDocument document, boolean isMakingCopy) {
    PduBody pb = new PduBody();

    boolean hasForwardLock = false;
    for (SlideModel slide : mSlides) {
      for (MediaModel media : slide) {
        if (isMakingCopy) {
          if (media.isDrmProtected() && !media.isAllowedToForward()) {
            hasForwardLock = true;
            continue;
          }
        }

        PduPart part = new PduPart();

        if (media.isText()) {
          TextModel text = (TextModel) media;
          // Don't create empty text part.
          if (TextUtils.isEmpty(text.getText())) {
            continue;
          }
          // Set Charset if it's a text media.
          part.setCharset(text.getCharset());
        }

        // Set Content-Type.
        part.setContentType(media.getContentType().getBytes());

        String src = media.getSrc();
        String location;
        boolean startWithContentId = src.startsWith("cid:");
        if (startWithContentId) {
          location = src.substring("cid:".length());
        } else {
          location = src;
        }

        // Set Content-Location.
        part.setContentLocation(location.getBytes());

        // Set Content-Id.
        if (startWithContentId) {
          // Keep the original Content-Id.
          part.setContentId(location.getBytes());
        } else {
          int index = location.lastIndexOf(".");
          String contentId = (index == -1) ? location : location.substring(0, index);
          part.setContentId(contentId.getBytes());
        }

        if (media.isDrmProtected()) {
          DrmWrapper wrapper = media.getDrmObject();
          part.setDataUri(wrapper.getOriginalUri());
          part.setData(wrapper.getOriginalData());
        } else if (media.isText()) {
          part.setData(((TextModel) media).getText().getBytes());
        } else if (media.isImage() || media.isVideo() || media.isAudio()) {
          part.setDataUri(media.getUri());
        } else {
          Log.w(TAG, "Unsupport media: " + media);
        }

        pb.addPart(part);
      }
    }

    if (hasForwardLock && isMakingCopy && context != null) {
      Toast.makeText(context, context.getString(R.string.cannot_forward_drm_obj), Toast.LENGTH_LONG)
          .show();
      document = SmilHelper.getDocument(pb);
    }

    // Create and insert SMIL part(as the first part) into the PduBody.
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    SmilXmlSerializer.serialize(document, out);
    PduPart smilPart = new PduPart();
    smilPart.setContentId("smil".getBytes());
    smilPart.setContentLocation("smil.xml".getBytes());
    smilPart.setContentType(ContentType.APP_SMIL.getBytes());
    smilPart.setData(out.toByteArray());
    pb.addPart(0, smilPart);

    return pb;
  }
  public static SlideshowModel createFromPduBody(Context context, PduBody pb) throws MmsException {
    SMILDocument document = SmilHelper.getDocument(pb);

    // Create root-layout model.
    SMILLayoutElement sle = document.getLayout();
    SMILRootLayoutElement srle = sle.getRootLayout();
    int w = srle.getWidth();
    int h = srle.getHeight();
    if ((w == 0) || (h == 0)) {
      w = LayoutManager.getInstance().getLayoutParameters().getWidth();
      h = LayoutManager.getInstance().getLayoutParameters().getHeight();
      srle.setWidth(w);
      srle.setHeight(h);
    }
    RegionModel rootLayout = new RegionModel(null, 0, 0, w, h);

    // Create region models.
    ArrayList<RegionModel> regions = new ArrayList<RegionModel>();
    NodeList nlRegions = sle.getRegions();
    int regionsNum = nlRegions.getLength();

    for (int i = 0; i < regionsNum; i++) {
      SMILRegionElement sre = (SMILRegionElement) nlRegions.item(i);
      RegionModel r =
          new RegionModel(
              sre.getId(),
              sre.getFit(),
              sre.getLeft(),
              sre.getTop(),
              sre.getWidth(),
              sre.getHeight(),
              sre.getBackgroundColor());
      regions.add(r);
    }
    LayoutModel layouts = new LayoutModel(rootLayout, regions);

    // Create slide models.
    SMILElement docBody = document.getBody();
    NodeList slideNodes = docBody.getChildNodes();
    int slidesNum = slideNodes.getLength();
    ArrayList<SlideModel> slides = new ArrayList<SlideModel>(slidesNum);

    for (int i = 0; i < slidesNum; i++) {
      // FIXME: This is NOT compatible with the SMILDocument which is
      // generated by some other mobile phones.
      SMILParElement par = (SMILParElement) slideNodes.item(i);

      // Create media models for each slide.
      NodeList mediaNodes = par.getChildNodes();
      int mediaNum = mediaNodes.getLength();
      ArrayList<MediaModel> mediaSet = new ArrayList<MediaModel>(mediaNum);

      for (int j = 0; j < mediaNum; j++) {
        SMILMediaElement sme = (SMILMediaElement) mediaNodes.item(j);
        try {
          MediaModel media = MediaModelFactory.getMediaModel(context, sme, layouts, pb);
          SmilHelper.addMediaElementEventListeners((EventTarget) sme, media);
          mediaSet.add(media);
        } catch (DrmException e) {
          Log.e(TAG, e.getMessage(), e);
        } catch (IOException e) {
          Log.e(TAG, e.getMessage(), e);
        } catch (IllegalArgumentException e) {
          Log.e(TAG, e.getMessage(), e);
        }
      }

      SlideModel slide = new SlideModel((int) (par.getDur() * 1000), mediaSet);
      slide.setFill(par.getFill());
      SmilHelper.addParElementEventListeners((EventTarget) par, slide);
      slides.add(slide);
    }

    SlideshowModel slideshow =
        new SlideshowModel(layouts, slides, document, pb, context.getContentResolver());
    slideshow.registerModelChangedObserver(slideshow);
    return slideshow;
  }