Home | History | Annotate | Download | only in mobile1
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.drm.mobile1;
     18 
     19 import java.io.*;
     20 
     21 /**
     22  * This class provides interfaces to access the DRM raw content.
     23  */
     24 public class DrmRawContent {
     25     /**
     26      * The "application/vnd.oma.drm.message" mime type.
     27      */
     28     public static final String DRM_MIMETYPE_MESSAGE_STRING = "application/vnd.oma.drm.message";
     29 
     30     /**
     31      * The "application/vnd.oma.drm.content" mime type.
     32      */
     33     public static final String DRM_MIMETYPE_CONTENT_STRING = "application/vnd.oma.drm.content";
     34 
     35     /**
     36      * The DRM delivery type: Forward-Lock
     37      */
     38     public static final int DRM_FORWARD_LOCK = 1;
     39 
     40     /**
     41      * The DRM delivery type: Combined Delivery
     42      */
     43     public static final int DRM_COMBINED_DELIVERY = 2;
     44 
     45     /**
     46      * The DRM delivery type: Separate Delivery
     47      */
     48     public static final int DRM_SEPARATE_DELIVERY = 3;
     49 
     50     /**
     51      * The DRM delivery type: Separate Delivery in DRM message
     52      */
     53     public static final int DRM_SEPARATE_DELIVERY_DM = 4;
     54 
     55     /**
     56      * The DRM media content length is unknown currently
     57      */
     58     public static final int DRM_UNKNOWN_DATA_LEN = -1;
     59 
     60 
     61     /**
     62      * The id of "application/vnd.oma.drm.message" mime type.
     63      */
     64     private static final int DRM_MIMETYPE_MESSAGE = 1;
     65 
     66     /**
     67      * The id of "application/vnd.oma.drm.content" mime type.
     68      */
     69     private static final int DRM_MIMETYPE_CONTENT = 2;
     70 
     71     /**
     72      * Successful operation.
     73      */
     74     private static final int JNI_DRM_SUCCESS = 0;
     75 
     76     /**
     77      * General failure.
     78      */
     79     private static final int JNI_DRM_FAILURE = -1;
     80 
     81     /**
     82      * Indicates the end of the DRM content is reached.
     83      */
     84     private static final int JNI_DRM_EOF = -2;
     85 
     86     /**
     87      * The media content length is unknown from native method
     88      */
     89     private static final int JNI_DRM_UNKNOWN_DATA_LEN = -3;
     90 
     91     /**
     92      * The member to save the original InputStream data.
     93      */
     94     private BufferedInputStream inData;
     95 
     96     /**
     97      * The member to save the original InputStream data length.
     98      */
     99     private int inDataLen;
    100 
    101     /**
    102      * The unique id to this DRM content. It will be initialized
    103      * in constructor by native method. And it will not be changed
    104      * after initialization.
    105      */
    106     private int id;
    107 
    108     /**
    109      * The rights issuer address of this DRM object.
    110      */
    111     private String rightsIssuer;
    112 
    113     /**
    114      * The media content type of this DRM object.
    115      */
    116     private String mediaType;
    117 
    118     /**
    119      * The delivery method type of this DRM object.
    120      */
    121     private int rawType;
    122 
    123 
    124     /**
    125      * Construct a DrmRawContent object.
    126      *
    127      * @param inRawdata     object of DRM raw data stream.
    128      * @param len           the length of raw data can be read.
    129      * @param mimeTypeStr   the mime type of the DRM content.
    130      */
    131     public DrmRawContent(InputStream inRawdata, int len, String mimeTypeStr) throws DrmException, IOException {
    132         int mimeType;
    133 
    134         id = -1;
    135         inData = new BufferedInputStream(inRawdata, 1024);
    136         inDataLen = len;
    137 
    138         if (DRM_MIMETYPE_MESSAGE_STRING.equals(mimeTypeStr))
    139             mimeType = DRM_MIMETYPE_MESSAGE;
    140         else if (DRM_MIMETYPE_CONTENT_STRING.equals(mimeTypeStr))
    141             mimeType = DRM_MIMETYPE_CONTENT;
    142         else
    143             throw new IllegalArgumentException("mimeType must be DRM_MIMETYPE_MESSAGE or DRM_MIMETYPE_CONTENT");
    144 
    145         if (len <= 0)
    146             throw new IllegalArgumentException("len must be > 0");
    147 
    148         /* call native method to initialize this DRM content */
    149         id = nativeConstructDrmContent(inData, inDataLen, mimeType);
    150 
    151         if (JNI_DRM_FAILURE == id)
    152             throw new DrmException("nativeConstructDrmContent() returned JNI_DRM_FAILURE");
    153 
    154         /* init the rights issuer field. */
    155         rightsIssuer = nativeGetRightsAddress();
    156 
    157         /* init the raw content type. */
    158         rawType = nativeGetDeliveryMethod();
    159         if (JNI_DRM_FAILURE == rawType)
    160             throw new DrmException("nativeGetDeliveryMethod() returned JNI_DRM_FAILURE");
    161 
    162         /* init the media content type. */
    163         mediaType = nativeGetContentType();
    164         if (null == mediaType)
    165             throw new DrmException("nativeGetContentType() returned null");
    166     }
    167 
    168     /**
    169      * Get rights address from raw Seperate Delivery content.
    170      *
    171      * @return the string of the rights issuer address,
    172      *         or null if no rights issuer.
    173      */
    174     public String getRightsAddress() {
    175         return rightsIssuer;
    176     }
    177 
    178     /**
    179      * Get the type of the raw DRM content.
    180      *
    181      * @return one of the following delivery type of this DRM content:
    182      *              #DRM_FORWARD_LOCK
    183      *              #DRM_COMBINED_DELIVERY
    184      *              #DRM_SEPARATE_DELIVERY
    185      *              #DRM_SEPARATE_DELIVERY_DM
    186      */
    187     public int getRawType() {
    188         return rawType;
    189     }
    190 
    191     /**
    192      * Get one InputStream object to read decrypted content.
    193      *
    194      * @param rights        the rights object contain decrypted key.
    195      *
    196      * @return the InputStream object of decrypted media content.
    197      */
    198     public InputStream getContentInputStream(DrmRights rights) {
    199         if (null == rights)
    200             throw new NullPointerException();
    201 
    202         return new DrmInputStream(rights);
    203     }
    204 
    205     /**
    206      * Get the type of the decrypted media content.
    207      *
    208      * @return the decrypted media content type of this DRM content.
    209      */
    210     public String getContentType() {
    211         return mediaType;
    212     }
    213 
    214     /**
    215      * Get the length of the decrypted media content.
    216      *
    217      * @param rights        the rights object contain decrypted key.
    218      *
    219      * @return the length of the decrypted media content.
    220      *         #DRM_UNKNOWN_DATA_LEN if the length is unknown currently.
    221      */
    222     public int getContentLength(DrmRights rights) throws DrmException {
    223         /**
    224          * Because currently the media object associate with rights object
    225          * has been handled in native logic, so here it is not need to deal
    226          * the rights. But for the apps, it is mandatory for user to get
    227          * the rights object before get the media content length.
    228          */
    229         if (null == rights)
    230             throw new NullPointerException();
    231 
    232         int mediaLen = nativeGetContentLength();
    233 
    234         if (JNI_DRM_FAILURE == mediaLen)
    235             throw new DrmException("nativeGetContentLength() returned JNI_DRM_FAILURE");
    236 
    237         if (JNI_DRM_UNKNOWN_DATA_LEN == mediaLen)
    238             return DRM_UNKNOWN_DATA_LEN;
    239 
    240         return mediaLen;
    241     }
    242 
    243     /**
    244      * This class provide a InputStream to the DRM media content.
    245      */
    246     class DrmInputStream extends InputStream
    247     {
    248         /**
    249          * The flag to indicate whether this stream is closed or not.
    250          */
    251         private boolean isClosed;
    252 
    253         /**
    254          * The offset of this DRM content to be reset.
    255          */
    256         private int offset;
    257 
    258         /**
    259          * A byte of data to be readed.
    260          */
    261         private byte[] b;
    262 
    263         /**
    264          * Construct a DrmInputStream instance.
    265          */
    266         public DrmInputStream(DrmRights rights) {
    267             /**
    268              * Because currently the media object associate with rights object
    269              * has been handled in native logic, so here it is not need to deal
    270              * the rights. But for the apps, it is mandatory for user to get
    271              * the rights object before get the media content data.
    272              */
    273 
    274             isClosed = false;
    275             offset = 0;
    276             b = new byte[1];
    277         }
    278 
    279         /* Non-javadoc
    280          * @see java.io.InputStream#available()
    281          */
    282         public int available() throws IOException {
    283             /* call native method to get this DRM decrypted media content length */
    284             int len = nativeGetContentLength();
    285 
    286             if (JNI_DRM_FAILURE == len)
    287                 throw new IOException();
    288 
    289             /* if the length is unknown, just return 0 for available value */
    290             if (JNI_DRM_UNKNOWN_DATA_LEN == len)
    291                 return 0;
    292 
    293             int availableLen = len - offset;
    294             if (availableLen < 0)
    295                 throw new IOException();
    296 
    297             return availableLen;
    298         }
    299 
    300         /* Non-javadoc
    301          * @see java.io.InputStream#read()
    302          */
    303         public int read() throws IOException {
    304             int res;
    305 
    306             res = read(b, 0, 1);
    307 
    308             if (-1 == res)
    309                 return -1;
    310 
    311             return b[0] & 0xff;
    312         }
    313 
    314         /* Non-javadoc
    315          * @see java.io.InputStream#read(byte)
    316          */
    317         public int read(byte[] b) throws IOException {
    318             return read(b, 0, b.length);
    319         }
    320 
    321         /* Non-javadoc
    322          * @see java.io.InputStream#read(byte, int, int)
    323          */
    324         public int read(byte[] b, int off, int len) throws IOException {
    325             if (null == b)
    326                 throw new NullPointerException();
    327             if (off < 0 || len < 0 || off + len > b.length)
    328                 throw new IndexOutOfBoundsException();
    329             if (true == isClosed)
    330                 throw new IOException();
    331 
    332             if (0 == len)
    333                 return 0;
    334 
    335             len = nativeReadContent(b, off, len, offset);
    336 
    337             if (JNI_DRM_FAILURE == len)
    338                 throw new IOException();
    339             else if (JNI_DRM_EOF == len)
    340                 return -1;
    341 
    342             offset += len;
    343 
    344             return len;
    345         }
    346 
    347         /* Non-javadoc
    348          * @see java.io.InputStream#markSupported()
    349          */
    350         public boolean markSupported() {
    351             return false;
    352         }
    353 
    354         /* Non-javadoc
    355          * @see java.io.InputStream#mark(int)
    356          */
    357         public void mark(int readlimit) {
    358         }
    359 
    360         /* Non-javadoc
    361          * @see java.io.InputStream#reset()
    362          */
    363         public void reset() throws IOException {
    364             throw new IOException();
    365         }
    366 
    367         /* Non-javadoc
    368          * @see java.io.InputStream#skip()
    369          */
    370         public long skip(long n) throws IOException {
    371             return 0;
    372         }
    373 
    374         /* Non-javadoc
    375          * @see java.io.InputStream#close()
    376          */
    377         public void close() {
    378             isClosed = true;
    379         }
    380     }
    381 
    382     /**
    383      * native method: construct a DRM content according the mime type.
    384      *
    385      * @param data      input DRM content data to be parsed.
    386      * @param len       the length of the data.
    387      * @param mimeType  the mime type of this DRM content. the value of this field includes:
    388      *                      #DRM_MIMETYPE_MESSAGE
    389      *                      #DRM_MIMETYPE_CONTENT
    390      *
    391      * @return #the id of the DRM content if succeed.
    392      *         #JNI_DRM_FAILURE if fail.
    393      */
    394     private native int nativeConstructDrmContent(InputStream data, int len, int mimeType);
    395 
    396     /**
    397      * native method: get this DRM content rights issuer.
    398      *
    399      * @return the address of rights issuer if in case of separate delivery.
    400      *         null if not separete delivery, or otherwise.
    401      */
    402     private native String nativeGetRightsAddress();
    403 
    404     /**
    405      * native method: get this DRM content delivery type.
    406      *
    407      * @return the delivery method, the value may be one of the following:
    408      *              #DRM_FORWARD_LOCK
    409      *              #DRM_COMBINED_DELIVERY
    410      *              #DRM_SEPARATE_DELIVERY
    411      *              #DRM_SEPARATE_DELIVERY_DM
    412      *         #JNI_DRM_FAILURE if fail.
    413      */
    414     private native int nativeGetDeliveryMethod();
    415 
    416     /**
    417      * native method: get a piece of media content data.
    418      *
    419      * @param buf       the buffer to save DRM media content data.
    420      * @param bufOff    the offset of the buffer to start to save data.
    421      * @param len       the number of byte to read.
    422      * @param mediaOff  the offset of the media content data to start to read.
    423      *
    424      * @return the length of the media content data has been read.
    425      *         #JNI_DRM_EOF if reach to end of the media content.
    426      *         #JNI_DRM_FAILURE if fail.
    427      */
    428     private native int nativeReadContent(byte[] buf, int bufOff, int len, int mediaOff);
    429 
    430     /**
    431      * native method: get this DRM content type.
    432      *
    433      * @return the decrypted media content type.
    434      *         null if fail.
    435      */
    436     private native String nativeGetContentType();
    437 
    438     /**
    439      * native method: get this DRM decrypted media content length.
    440      *
    441      * @return the length of decrypted media content.
    442      *         #JNI_DRM_FAILURE if fail.
    443      *         #JNI_DRM_UNKNOWN_DATA_LEN if the length is unknown currently.
    444      */
    445     private native int nativeGetContentLength();
    446 
    447     /**
    448      * The finalizer of the DRMRawContent. Do some cleanup.
    449      */
    450     protected native void finalize();
    451 
    452 
    453     /**
    454      * Load the shared library to link the native methods.
    455      */
    456     static {
    457         try {
    458             System.loadLibrary("drm1_jni");
    459         }
    460         catch (UnsatisfiedLinkError ule) {
    461             System.err.println("WARNING: Could not load libdrm1_jni.so");
    462         }
    463     }
    464 }
    465