Home | History | Annotate | Download | only in jni
      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 /**
     18  * @file drm1_jni.c
     19  *
     20  * This file implement the Java Native Interface
     21  * for supporting OMA DRM 1.0
     22  */
     23 
     24 #include <jni/drm1_jni.h>
     25 #include <objmng/svc_drm.h>
     26 #include "log.h"
     27 
     28 
     29 #define MS_PER_SECOND 1000                  /* Milliseconds per second */
     30 #define MS_PER_MINUTE 60 * MS_PER_SECOND    /* Milliseconds per minute */
     31 #define MS_PER_HOUR   60 * MS_PER_MINUTE    /* Milliseconds per hour */
     32 #define MS_PER_DAY    24 * MS_PER_HOUR      /* Milliseconds per day */
     33 
     34 #define SECONDS_PER_MINUTE 60                       /* Seconds per minute*/
     35 #define SECONDS_PER_HOUR   60 * SECONDS_PER_MINUTE  /* Seconds per hour */
     36 #define SECONDS_PER_DAY    24 * SECONDS_PER_HOUR    /* Seconds per day */
     37 
     38 #define DAY_PER_MONTH 30                    /* Days per month */
     39 #define DAY_PER_YEAR  365                   /* Days per year */
     40 
     41 /** Nonzero if 'y' is a leap year, else zero. */
     42 #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
     43 
     44 /** Number of leap years from 1970 to 'y' (not including 'y' itself). */
     45 #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
     46 
     47 /** Accumulated number of days from 01-Jan up to start of current month. */
     48 static const int32_t ydays[] = {
     49     0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
     50 };
     51 
     52 #define int64_const(s)          (s)
     53 #define int64_add(dst, s1, s2)  ((void)((dst) = (s1) + (s2)))
     54 #define int64_mul(dst, s1, s2)  ((void)((dst) = (int64_t)(s1) * (int64_t)(s2)))
     55 
     56 /**
     57  * DRM data structure
     58  */
     59 typedef struct _DrmData {
     60     /**
     61      * The id of the DRM content.
     62      */
     63     int32_t id;
     64 
     65     /**
     66      * The pointer of JNI interface.
     67      */
     68     JNIEnv* env;
     69 
     70     /**
     71      * The pointer of DRM raw content InputStream object.
     72      */
     73     jobject* pInData;
     74 
     75     /**
     76      * The len of the InputStream object.
     77      */
     78     int32_t len;
     79 
     80     /**
     81      * The next DRM data.
     82      */
     83     struct _DrmData *next;
     84 } DrmData;
     85 
     86 /** The table to hold all the DRM data. */
     87 static DrmData *drmTable = NULL;
     88 
     89 /**
     90  * Allocate a new item of DrmData.
     91  *
     92  * \return a pointer to a DrmData item if allocate successfully,
     93  *         otherwise return NULL
     94  */
     95 static DrmData * newItem(void)
     96 {
     97     DrmData *d = (DrmData *)malloc(sizeof(DrmData));
     98 
     99     if (d != NULL) {
    100         d->id = -1;
    101         d->next = NULL;
    102     }
    103 
    104     return d;
    105 }
    106 
    107 /**
    108  * Free the memory of the specified DrmData item <code>d</code>.
    109  *
    110  * \param d - a pointer to DrmData
    111  */
    112 static void freeItem(DrmData *d)
    113 {
    114     assert(d != NULL);
    115 
    116     free(d);
    117 }
    118 
    119 /**
    120  * Insert a DrmData item with given <code>name</code> into the head of
    121  * the DrmData list.
    122  *
    123  * @param d - the pointer of the JNI interface
    124  * @param pInData - the pointer of the DRM content InputStream object.
    125  *
    126  * @return <code>JNI_DRM_SUCCESS</code> if insert successfully, otherwise
    127  *         return <code>JNI_DRM_FAILURE</code>
    128  */
    129 static int32_t addItem(DrmData* d)
    130 {
    131     if (NULL == d)
    132         return JNI_DRM_FAILURE;
    133 
    134     if (NULL == drmTable) {
    135         drmTable = d;
    136         return JNI_DRM_SUCCESS;
    137     }
    138 
    139     d->next = drmTable;
    140     drmTable = d;
    141 
    142     return JNI_DRM_SUCCESS;
    143 }
    144 
    145 /**
    146  * Get the item from the DrmData list by the specified <code>
    147  * id</code>.
    148  *
    149  * @param p - the pointer of the DRM content InputStream object.
    150  *
    151  * @return a pointer to the DrmData item if find it successfuly,
    152  *         otherwise return NULL
    153  */
    154 static DrmData * getItem(int32_t id)
    155 {
    156     DrmData *d;
    157 
    158     if (NULL == drmTable)
    159         return NULL;
    160 
    161     for (d = drmTable; d != NULL; d = d->next) {
    162         if (id == d->id)
    163             return d;
    164     }
    165 
    166     return NULL;
    167 }
    168 
    169 /**
    170  * Remove the specified DrmData item <code>d</code>.
    171  *
    172  * @param p - the pointer of the DRM content InputStream object.
    173  *
    174  * @return <code>JNI_DRM_SUCCESS</code> if remove successfuly,
    175  *         otherwise return <code>JNI_DRM_FAILURE</code>
    176  */
    177 static int32_t removeItem(int32_t id)
    178 {
    179     DrmData *curItem, *preItem, *dstItem;
    180 
    181     if (NULL == drmTable)
    182         return JNI_DRM_FAILURE;
    183 
    184     preItem = NULL;
    185     for (curItem = drmTable; curItem != NULL; curItem = curItem->next) {
    186         if (id == curItem->id) {
    187             if (curItem == drmTable)
    188                 drmTable = curItem->next;
    189             else
    190                 preItem->next = curItem->next;
    191 
    192             freeItem(curItem);
    193 
    194             return JNI_DRM_SUCCESS;
    195         }
    196 
    197         preItem = curItem;
    198     }
    199 
    200     return JNI_DRM_FAILURE;
    201 }
    202 
    203 
    204 static int32_t getInputStreamDataLength(int32_t handle)
    205 {
    206     JNIEnv* env;
    207     jobject* pInputStream;
    208     int32_t len;
    209     DrmData* p;
    210     jclass cls;
    211     jmethodID mid;
    212 
    213     p = (DrmData *)handle;
    214 
    215     if (NULL == p)
    216         return 0;
    217 
    218     env = p->env;
    219     pInputStream = p->pInData;
    220     len = p->len;
    221 
    222     if (NULL == env || p->len <= 0 || NULL == pInputStream)
    223         return 0;
    224 
    225     /* check the original InputStream is available or not */
    226     cls = (*env)->GetObjectClass(env, *pInputStream);
    227     mid = (*env)->GetMethodID(env, cls, "available", "()I");
    228     (*env)->DeleteLocalRef(env, cls);
    229 
    230     if (NULL == mid)
    231         return 0;
    232 
    233     if (0 > (*env)->CallIntMethod(env, *pInputStream, mid))
    234         return 0;
    235 
    236     return len;
    237 }
    238 
    239 static int32_t readInputStreamData(int32_t handle, uint8_t* buf, int32_t bufLen)
    240 {
    241     JNIEnv* env;
    242     jobject* pInputStream;
    243     int32_t len;
    244     DrmData* p;
    245     jclass cls;
    246     jmethodID mid;
    247     jbyteArray tmp;
    248     int tmpLen;
    249     jbyte* pNativeBuf;
    250 
    251     p = (DrmData *)handle;
    252 
    253     if (NULL == p || NULL == buf || bufLen <- 0)
    254         return 0;
    255 
    256     env = p->env;
    257     pInputStream = p->pInData;
    258     len = p->len;
    259 
    260     if (NULL == env || p->len <= 0 || NULL == pInputStream)
    261         return 0;
    262 
    263     cls = (*env)->GetObjectClass(env, *pInputStream);
    264     mid = (*env)->GetMethodID(env, cls, "read", "([BII)I");
    265     tmp = (*env)->NewByteArray(env, bufLen);
    266     bufLen = (*env)->CallIntMethod(env, *pInputStream, mid, tmp, 0, bufLen);
    267 
    268     (*env)->DeleteLocalRef(env, cls);
    269 
    270     if (-1 == bufLen)
    271         return -1;
    272 
    273     pNativeBuf = (*env)->GetByteArrayElements(env, tmp, NULL);
    274     memcpy(buf, pNativeBuf, bufLen);
    275     (*env)->ReleaseByteArrayElements(env, tmp, pNativeBuf, 0);
    276     (*env)->DeleteLocalRef(env, tmp);
    277 
    278     return bufLen;
    279 }
    280 
    281 static const T_DRM_Rights_Info_Node *searchRightsObject(const jbyte* roId, const T_DRM_Rights_Info_Node* pRightsList)
    282 {
    283     const T_DRM_Rights_Info_Node *pTmp;
    284 
    285     if (NULL == roId || NULL == pRightsList)
    286         return NULL;
    287 
    288     pTmp = pRightsList;
    289 
    290     while (NULL != pTmp) {
    291         if(0 == strcmp((char *)roId, (char *)pTmp->roInfo.roId))
    292             break;
    293         pTmp = pTmp->next;
    294     }
    295 
    296     return pTmp;
    297 }
    298 
    299 /**
    300  * Returns the difference in seconds between the given GMT time
    301  * and 1970-01-01 00:00:00 GMT.
    302  *
    303  * \param year the year (since 1970)
    304  * \param month the month (1 - 12)
    305  * \param day the day (1 - 31)
    306  * \param hour the hour (0 - 23)
    307  * \param minute the minute (0 - 59)
    308  * \param second the second (0 - 59)
    309  *
    310  * \return the difference in seconds between the given GMT time
    311  *         and 1970-01-01 00:00:00 GMT.
    312  */
    313 static int64_t mkgmtime(
    314         uint32_t year, uint32_t month, uint32_t day,
    315         uint32_t hour, uint32_t minute, uint32_t second)
    316 {
    317     int64_t result;
    318 
    319     /*
    320      * FIXME: It does not check whether the specified days
    321      *        is valid based on the specified months.
    322      */
    323     assert(year >= 1970
    324             && month > 0 && month <= 12
    325             && day > 0 && day <= 31
    326             && hour < 24 && minute < 60
    327             && second < 60);
    328 
    329     /* Set 'day' to the number of days into the year. */
    330     day += ydays[month - 1] + (month > 2 && leap (year)) - 1;
    331 
    332     /* Now calculate 'day' to the number of days since Jan 1, 1970. */
    333     day = day + 365 * (year - 1970) + nleap(year);
    334 
    335     int64_mul(result, int64_const(day), int64_const(SECONDS_PER_DAY));
    336     int64_add(result, result, int64_const(
    337         SECONDS_PER_HOUR * hour + SECONDS_PER_MINUTE * minute + second));
    338 
    339     return result;
    340 }
    341 
    342 /**
    343  * Compute the milliseconds by the specified <code>date</code>
    344  * and <code>time</code>.
    345  *
    346  * @param date - the specified date,
    347  *               <code>date = year * 10000 + month * 100 + day</code>
    348  * @param time - the specified time,
    349  *               <code>time = hour * 10000 + minute * 100 + second</code>
    350  *
    351  * @return the related milliseconds
    352  */
    353 static int64_t computeTime(int32_t date, int32_t time)
    354 {
    355     int32_t year, month, day, hour, minute, second;
    356 
    357     year = date / 10000;
    358     month = (date / 100) % 100;
    359     day = date % 100;
    360     hour = time / 10000;
    361     minute = (time / 100) % 100;
    362     second = time % 100;
    363 
    364     /* Adjust the invalid parameters. */
    365     if (year < 1970) year = 1970;
    366     if (month < 1) month = 1;
    367     if (month > 12) month = 12;
    368     if (day < 1) day = 1;
    369     if (day > 31) day = 31;
    370     if (hour < 0) hour = 0;
    371     if (hour > 23) hour = 23;
    372     if (minute < 0) minute = 0;
    373     if (minute > 59) minute = 59;
    374     if (second < 0) second = 0;
    375     if (second > 59) second = 59;
    376 
    377     return mkgmtime(year, month, day, hour, minute, second) * 1000;
    378 }
    379 
    380 /**
    381  * Compute the milliseconds by the specified <code>date</code>
    382  * and <code>time</code>.
    383  * Note that here we always treat 1 year as 365 days and 1 month as 30 days
    384  * that is not precise. But it should not be a problem since OMA DRM 2.0
    385  * already restricts the interval representation to be day-based,
    386  * i.e. there will not be an interval with year or month any more in the
    387  * future.
    388  *
    389  * @param date - the specified date,
    390  *               <code>date = year * 10000 + month * 100 + day</code>
    391  * @param time - the specified time,
    392  *               <code>time = hour * 10000 + minute * 100 + second</code>
    393  *
    394  * @return the related milliseconds
    395  */
    396 static int64_t computeInterval(int32_t date, int32_t time)
    397 {
    398     int32_t year, month, day, hour, minute, second;
    399     int64_t milliseconds;
    400 
    401     year = date / 10000;
    402     month = (date / 100) % 100;
    403     day = date % 100;
    404     hour = time / 10000;
    405     minute = (time / 100) % 100;
    406     second = time % 100;
    407 
    408     /* milliseconds = ((((year * 365 + month * 30 + day) * 24
    409      *                + hour) * 60 + minute) * 60 + second) * 1000;
    410      */
    411     int64_mul(milliseconds,
    412         int64_const(year * DAY_PER_YEAR + month * DAY_PER_MONTH + day),
    413         int64_const(MS_PER_DAY));
    414     int64_add(milliseconds, milliseconds,
    415         int64_const(hour * MS_PER_HOUR + minute * MS_PER_MINUTE +
    416             second * MS_PER_SECOND));
    417 
    418     return milliseconds;
    419 }
    420 
    421 static jint getObjectIntField(JNIEnv * env, jobject obj, const char *name, jint * value)
    422 {
    423     jclass clazz;
    424     jfieldID field;
    425 
    426     clazz = (*env)->GetObjectClass(env, obj);
    427     if (NULL == clazz)
    428         return JNI_DRM_FAILURE;
    429 
    430     field = (*env)->GetFieldID(env, clazz, name, "I");
    431     (*env)->DeleteLocalRef(env, clazz);
    432 
    433     if (NULL == field)
    434         return JNI_DRM_FAILURE;
    435 
    436     *value = (*env)->GetIntField(env, obj, field);
    437 
    438     return JNI_DRM_SUCCESS;
    439 }
    440 
    441 static jint setObjectIntField(JNIEnv * env, jobject obj, const char *name, jint value)
    442 {
    443     jclass clazz;
    444     jfieldID field;
    445 
    446     clazz = (*env)->GetObjectClass(env, obj);
    447     if (NULL == clazz)
    448         return JNI_DRM_FAILURE;
    449 
    450     field = (*env)->GetFieldID(env, clazz, name, "I");
    451     (*env)->DeleteLocalRef(env, clazz);
    452 
    453     if (NULL == field)
    454         return JNI_DRM_FAILURE;
    455 
    456     (*env)->SetIntField(env, obj, field, value);
    457 
    458     return JNI_DRM_SUCCESS;
    459 }
    460 
    461 static jint setObjectLongField(JNIEnv * env, jobject obj, const char *name, jlong value)
    462 {
    463     jclass clazz;
    464     jfieldID field;
    465 
    466     clazz = (*env)->GetObjectClass(env, obj);
    467     if (NULL == clazz)
    468         return JNI_DRM_FAILURE;
    469 
    470     field = (*env)->GetFieldID(env, clazz, name, "J");
    471     (*env)->DeleteLocalRef(env, clazz);
    472 
    473     if (NULL == field)
    474         return JNI_DRM_FAILURE;
    475 
    476     (*env)->SetLongField(env, obj, field, value);
    477 
    478     return JNI_DRM_SUCCESS;
    479 }
    480 
    481 static jint setConstraintFields(JNIEnv * env, jobject constraint, T_DRM_Constraint_Info * pConstraint)
    482 {
    483     /* if no this permission */
    484     if (pConstraint->indicator == (uint8_t)DRM_NO_RIGHTS) {
    485         if (JNI_DRM_FAILURE == setObjectIntField(env, constraint, "count", 0))
    486             return JNI_DRM_FAILURE;
    487 
    488         return JNI_DRM_SUCCESS;
    489     }
    490 
    491     /* set count field */
    492     if (pConstraint->indicator & DRM_COUNT_CONSTRAINT) {
    493         if (JNI_DRM_FAILURE == setObjectIntField(env, constraint, "count", pConstraint->count))
    494             return JNI_DRM_FAILURE;
    495     }
    496 
    497     /* set start time field */
    498     if (pConstraint->indicator & DRM_START_TIME_CONSTRAINT) {
    499         int64_t startTime;
    500 
    501         startTime = computeTime(pConstraint->startDate, pConstraint->startTime);
    502 
    503         if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "startDate", startTime))
    504             return JNI_DRM_FAILURE;
    505     }
    506 
    507     /* set end time field */
    508     if (pConstraint->indicator & DRM_END_TIME_CONSTRAINT) {
    509         int64_t endTime;
    510 
    511         endTime = computeTime(pConstraint->endDate, pConstraint->endTime);
    512 
    513         if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "endDate", endTime))
    514             return JNI_DRM_FAILURE;
    515     }
    516 
    517     /* set interval field */
    518     if (pConstraint->indicator & DRM_INTERVAL_CONSTRAINT) {
    519         int64_t interval;
    520 
    521         interval = computeInterval(pConstraint->intervalDate, pConstraint->intervalTime);
    522 
    523         if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "interval", interval))
    524             return JNI_DRM_FAILURE;
    525     }
    526 
    527     return JNI_DRM_SUCCESS;
    528 }
    529 
    530 static jint setRightsFields(JNIEnv * env, jobject rights, T_DRM_Rights_Info* pRoInfo)
    531 {
    532     jclass clazz;
    533     jfieldID field;
    534     jstring str;
    535     jint index;
    536 
    537     clazz = (*env)->GetObjectClass(env, rights);
    538     if (NULL == clazz)
    539         return JNI_DRM_FAILURE;
    540 
    541     /* set roId field */
    542     field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
    543     (*env)->DeleteLocalRef(env, clazz);
    544 
    545     if (NULL == field)
    546         return JNI_DRM_FAILURE;
    547 
    548     str = (*env)->NewStringUTF(env, (char *)pRoInfo->roId);
    549     if (NULL == str)
    550         return JNI_DRM_FAILURE;
    551 
    552     (*env)->SetObjectField(env, rights, field, str);
    553     (*env)->DeleteLocalRef(env, str);
    554 
    555     return JNI_DRM_SUCCESS;
    556 }
    557 
    558 /* native interface */
    559 JNIEXPORT jint JNICALL
    560 Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent
    561   (JNIEnv * env, jobject rawContent, jobject data, jint len, jint mimeType)
    562 {
    563     int32_t id;
    564     T_DRM_Input_Data inData;
    565     DrmData* drmInData;
    566 
    567     switch (mimeType) {
    568     case JNI_DRM_MIMETYPE_MESSAGE:
    569         mimeType = TYPE_DRM_MESSAGE;
    570         break;
    571     case JNI_DRM_MIMETYPE_CONTENT:
    572         mimeType = TYPE_DRM_CONTENT;
    573         break;
    574     default:
    575         return JNI_DRM_FAILURE;
    576     }
    577 
    578     drmInData = newItem();
    579     if (NULL == drmInData)
    580         return JNI_DRM_FAILURE;
    581 
    582     drmInData->env = env;
    583     drmInData->pInData = &data;
    584     drmInData->len = len;
    585 
    586     if (JNI_DRM_FAILURE == addItem(drmInData))
    587         return JNI_DRM_FAILURE;
    588 
    589     inData.inputHandle = (int32_t)drmInData;
    590     inData.mimeType = mimeType;
    591     inData.getInputDataLength = getInputStreamDataLength;
    592     inData.readInputData = readInputStreamData;
    593 
    594     id = SVC_drm_openSession(inData);
    595     if (id < 0)
    596         return JNI_DRM_FAILURE;
    597 
    598     drmInData->id = id;
    599 
    600     return id;
    601 }
    602 
    603 /* native interface */
    604 JNIEXPORT jstring JNICALL
    605 Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress
    606   (JNIEnv * env, jobject rawContent)
    607 {
    608     jint id;
    609     uint8_t rightsIssuer[256] = {0};
    610     jstring str = NULL;
    611 
    612     if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
    613         return NULL;
    614 
    615     if (DRM_SUCCESS == SVC_drm_getRightsIssuer(id, rightsIssuer))
    616         str = (*env)->NewStringUTF(env, (char *)rightsIssuer);
    617 
    618     return str;
    619 }
    620 
    621 /* native interface */
    622 JNIEXPORT jint JNICALL
    623 Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod
    624   (JNIEnv * env, jobject rawContent)
    625 {
    626     jint id;
    627     int32_t res;
    628 
    629     if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
    630         return JNI_DRM_FAILURE;
    631 
    632     res = SVC_drm_getDeliveryMethod(id);
    633 
    634     switch (res) {
    635     case FORWARD_LOCK:
    636         return JNI_DRM_FORWARD_LOCK;
    637     case COMBINED_DELIVERY:
    638         return JNI_DRM_COMBINED_DELIVERY;
    639     case SEPARATE_DELIVERY:
    640         return JNI_DRM_SEPARATE_DELIVERY;
    641     case SEPARATE_DELIVERY_FL:
    642         return JNI_DRM_SEPARATE_DELIVERY_DM;
    643     default:
    644         return JNI_DRM_FAILURE;
    645     }
    646 }
    647 
    648 /* native interface */
    649 JNIEXPORT jint JNICALL
    650 Java_android_drm_mobile1_DrmRawContent_nativeReadContent
    651   (JNIEnv * env, jobject rawContent, jbyteArray buf, jint bufOff, jint len, jint mediaOff)
    652 {
    653     jint id;
    654     jbyte *nativeBuf;
    655     jclass cls;
    656     jmethodID mid;
    657     DrmData* p;
    658     jobject inputStream;
    659     jfieldID field;
    660 
    661     if (NULL == buf) {
    662         jclass newExcCls = (*env)->FindClass(env, "java/lang/NullPointerException");
    663 
    664         if (newExcCls == NULL)
    665             /* Unable to find the exception class, give up. */
    666             return JNI_DRM_FAILURE;
    667 
    668         (*env)->ThrowNew(env, newExcCls, "b is null");
    669     }
    670 
    671     if (len < 0 || bufOff < 0 || len + bufOff > (*env)->GetArrayLength(env, buf)) {
    672         jclass newExcCls = (*env)->FindClass(env, "java/lang/IndexOutOfBoundsException");
    673 
    674         if (newExcCls == NULL)
    675             /* Unable to find the exception class, give up. */
    676             return JNI_DRM_FAILURE;
    677 
    678         (*env)->ThrowNew(env, newExcCls, NULL);
    679     }
    680 
    681     if (mediaOff < 0 || len == 0)
    682         return JNI_DRM_FAILURE;
    683 
    684     if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
    685         return JNI_DRM_FAILURE;
    686 
    687     p = getItem(id);
    688     if (NULL == p)
    689         return JNI_DRM_FAILURE;
    690 
    691     cls = (*env)->GetObjectClass(env, rawContent);
    692     if (NULL == cls)
    693         return JNI_DRM_FAILURE;
    694 
    695     field = (*env)->GetFieldID(env, cls, "inData", "Ljava/io/BufferedInputStream;");
    696     (*env)->DeleteLocalRef(env, cls);
    697 
    698     if (NULL == field)
    699         return JNI_DRM_FAILURE;
    700 
    701     inputStream = (*env)->GetObjectField(env, rawContent, field);
    702 
    703     p->env = env;
    704     p->pInData = &inputStream;
    705 
    706     nativeBuf = (*env)->GetByteArrayElements(env, buf, NULL);
    707 
    708     len = SVC_drm_getContent(id, mediaOff, (uint8_t *)nativeBuf + bufOff, len);
    709 
    710     (*env)->ReleaseByteArrayElements(env, buf, nativeBuf, 0);
    711 
    712     if (DRM_MEDIA_EOF == len)
    713         return JNI_DRM_EOF;
    714     if (len <= 0)
    715         return JNI_DRM_FAILURE;
    716 
    717     return len;
    718 }
    719 
    720 /* native interface */
    721 JNIEXPORT jstring JNICALL
    722 Java_android_drm_mobile1_DrmRawContent_nativeGetContentType
    723   (JNIEnv * env, jobject rawContent)
    724 {
    725     jint id;
    726     uint8_t contentType[64] = {0};
    727     jstring str = NULL;
    728 
    729     if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
    730         return NULL;
    731 
    732     if (DRM_SUCCESS == SVC_drm_getContentType(id, contentType))
    733         str = (*env)->NewStringUTF(env, (char *)contentType);
    734 
    735     return str;
    736 }
    737 
    738 /* native interface */
    739 JNIEXPORT jint JNICALL
    740 Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength
    741   (JNIEnv * env, jobject rawContent)
    742 {
    743     jint id;
    744     int32_t len;
    745 
    746     if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
    747         return JNI_DRM_FAILURE;
    748 
    749     len = SVC_drm_getContentLength(id);
    750 
    751     if (DRM_UNKNOWN_DATA_LEN == len)
    752         return JNI_DRM_UNKNOWN_DATA_LEN;
    753 
    754     if (0 > len)
    755         return JNI_DRM_FAILURE;
    756 
    757     return len;
    758 }
    759 
    760 /* native interface */
    761 JNIEXPORT void JNICALL
    762 Java_android_drm_mobile1_DrmRawContent_finalize
    763   (JNIEnv * env, jobject rawContent)
    764 {
    765     jint id;
    766 
    767     if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
    768         return;
    769 
    770     removeItem(id);
    771 
    772     SVC_drm_closeSession(id);
    773 }
    774 
    775 /* native interface */
    776 JNIEXPORT jint JNICALL
    777 Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo
    778   (JNIEnv * env, jobject rights, jint permission, jobject constraint)
    779 {
    780     jclass clazz;
    781     jfieldID field;
    782     jstring str;
    783     uint8_t *nativeStr;
    784     T_DRM_Rights_Info_Node *pRightsList;
    785     T_DRM_Rights_Info_Node *pCurNode;
    786     T_DRM_Constraint_Info *pConstraint;
    787 
    788     clazz = (*env)->GetObjectClass(env, rights);
    789     if (NULL == clazz)
    790         return JNI_DRM_FAILURE;
    791 
    792     field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
    793     (*env)->DeleteLocalRef(env, clazz);
    794 
    795     if (NULL == field)
    796         return JNI_DRM_FAILURE;
    797 
    798     str = (*env)->GetObjectField(env, rights, field);
    799 
    800     nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
    801     if (NULL == nativeStr)
    802         return JNI_DRM_FAILURE;
    803 
    804     /* this means forward-lock rights */
    805     if (0 == strcmp((char *)nativeStr, "ForwardLock")) {
    806         (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
    807         return JNI_DRM_SUCCESS;
    808     }
    809 
    810     if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList)) {
    811         (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
    812         return JNI_DRM_FAILURE;
    813     }
    814 
    815     pCurNode = searchRightsObject((jbyte *)nativeStr, pRightsList);
    816     if (NULL == pCurNode) {
    817         (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
    818         SVC_drm_freeRightsInfoList(pRightsList);
    819         return JNI_DRM_FAILURE;
    820     }
    821     (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
    822 
    823     switch (permission) {
    824     case JNI_DRM_PERMISSION_PLAY:
    825         pConstraint = &(pCurNode->roInfo.playRights);
    826         break;
    827     case JNI_DRM_PERMISSION_DISPLAY:
    828         pConstraint = &(pCurNode->roInfo.displayRights);
    829         break;
    830     case JNI_DRM_PERMISSION_EXECUTE:
    831         pConstraint = &(pCurNode->roInfo.executeRights);
    832         break;
    833     case JNI_DRM_PERMISSION_PRINT:
    834         pConstraint = &(pCurNode->roInfo.printRights);
    835         break;
    836     default:
    837         SVC_drm_freeRightsInfoList(pRightsList);
    838         return JNI_DRM_FAILURE;
    839     }
    840 
    841     /* set constraint field */
    842     if (JNI_DRM_FAILURE == setConstraintFields(env, constraint, pConstraint)) {
    843         SVC_drm_freeRightsInfoList(pRightsList);
    844         return JNI_DRM_FAILURE;
    845     }
    846 
    847     SVC_drm_freeRightsInfoList(pRightsList);
    848 
    849     return JNI_DRM_SUCCESS;
    850 }
    851 
    852 /* native interface */
    853 JNIEXPORT jint JNICALL
    854 Java_android_drm_mobile1_DrmRights_nativeConsumeRights
    855   (JNIEnv * env, jobject rights, jint permission)
    856 {
    857     jclass clazz;
    858     jfieldID field;
    859     jstring str;
    860     uint8_t *nativeStr;
    861     int32_t id;
    862 
    863     switch (permission) {
    864     case JNI_DRM_PERMISSION_PLAY:
    865         permission = DRM_PERMISSION_PLAY;
    866         break;
    867     case JNI_DRM_PERMISSION_DISPLAY:
    868         permission = DRM_PERMISSION_DISPLAY;
    869         break;
    870     case JNI_DRM_PERMISSION_EXECUTE:
    871         permission = DRM_PERMISSION_EXECUTE;
    872         break;
    873     case JNI_DRM_PERMISSION_PRINT:
    874         permission = DRM_PERMISSION_PRINT;
    875         break;
    876     default:
    877         return JNI_DRM_FAILURE;
    878     }
    879 
    880     clazz = (*env)->GetObjectClass(env, rights);
    881     if (NULL == clazz)
    882         return JNI_DRM_FAILURE;
    883 
    884     field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
    885     (*env)->DeleteLocalRef(env, clazz);
    886 
    887     if (NULL == field)
    888         return JNI_DRM_FAILURE;
    889 
    890     str = (*env)->GetObjectField(env, rights, field);
    891 
    892     nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
    893     if (NULL == nativeStr)
    894         return JNI_DRM_FAILURE;
    895 
    896     if (0 == strcmp("ForwardLock", (char *)nativeStr)) {
    897         (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
    898         return JNI_DRM_SUCCESS;
    899     }
    900 
    901     if (DRM_SUCCESS != SVC_drm_updateRights(nativeStr, permission)) {
    902         (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
    903         return JNI_DRM_FAILURE;
    904     }
    905 
    906     (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
    907 
    908     return JNI_DRM_SUCCESS;
    909 }
    910 
    911 /* native interface */
    912 JNIEXPORT jint JNICALL
    913 Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights
    914   (JNIEnv * env, jobject rightsManager, jobject data, jint len, jint mimeType, jobject rights)
    915 {
    916     int32_t id;
    917     T_DRM_Input_Data inData;
    918     DrmData* drmInData;
    919     jclass cls;
    920     jmethodID mid;
    921     T_DRM_Rights_Info rightsInfo;
    922 
    923     switch (mimeType) {
    924     case JNI_DRM_MIMETYPE_RIGHTS_XML:
    925         mimeType = TYPE_DRM_RIGHTS_XML;
    926         break;
    927     case JNI_DRM_MIMETYPE_RIGHTS_WBXML:
    928         mimeType = TYPE_DRM_RIGHTS_WBXML;
    929         break;
    930     case JNI_DRM_MIMETYPE_MESSAGE:
    931         mimeType = TYPE_DRM_MESSAGE;
    932         break;
    933     default:
    934         return JNI_DRM_FAILURE;
    935     }
    936 
    937     drmInData = newItem();
    938     if (NULL == drmInData)
    939         return JNI_DRM_FAILURE;
    940 
    941     drmInData->env = env;
    942     drmInData->pInData = &data;
    943     drmInData->len = len;
    944 
    945     inData.inputHandle = (int32_t)drmInData;
    946     inData.mimeType = mimeType;
    947     inData.getInputDataLength = getInputStreamDataLength;
    948     inData.readInputData = readInputStreamData;
    949 
    950     memset(&rightsInfo, 0, sizeof(T_DRM_Rights_Info));
    951     if (DRM_FAILURE == SVC_drm_installRights(inData, &rightsInfo))
    952         return JNI_DRM_FAILURE;
    953 
    954     freeItem(drmInData);
    955 
    956     return setRightsFields(env, rights, &rightsInfo);
    957 }
    958 
    959 /* native interface */
    960 JNIEXPORT jint JNICALL
    961 Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights
    962   (JNIEnv * env, jobject rightsManager, jobject rawContent, jobject rights)
    963 {
    964     jint id;
    965     T_DRM_Rights_Info rightsInfo;
    966 
    967     if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
    968         return JNI_DRM_FAILURE;
    969 
    970     memset(&rightsInfo, 0, sizeof(T_DRM_Rights_Info));
    971     if (DRM_SUCCESS != SVC_drm_getRightsInfo(id, &rightsInfo))
    972         return JNI_DRM_FAILURE;
    973 
    974     return setRightsFields(env, rights, &rightsInfo);
    975 }
    976 
    977 /* native interface */
    978 JNIEXPORT jint JNICALL
    979 Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights
    980   (JNIEnv * env, jobject rightsManager)
    981 {
    982     T_DRM_Rights_Info_Node *pRightsList;
    983     T_DRM_Rights_Info_Node *pCurNode;
    984     int32_t num = 0;
    985 
    986     if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList))
    987         return JNI_DRM_FAILURE;
    988 
    989     pCurNode = pRightsList;
    990     while (pCurNode != NULL) {
    991         num++;
    992         pCurNode = pCurNode->next;
    993     }
    994 
    995     SVC_drm_freeRightsInfoList(pRightsList);
    996 
    997     return num;
    998 }
    999 
   1000 /* native interface */
   1001 JNIEXPORT jint JNICALL
   1002 Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList
   1003   (JNIEnv * env, jobject rightsManager, jobjectArray rightsArray, jint num)
   1004 {
   1005     T_DRM_Rights_Info_Node *pRightsList;
   1006     T_DRM_Rights_Info_Node *pCurNode;
   1007     int32_t index;
   1008 
   1009     if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList))
   1010         return JNI_DRM_FAILURE;
   1011 
   1012     pCurNode = pRightsList;
   1013     for (index = 0; NULL != pCurNode; index++) {
   1014         jobject rights = (*env)->GetObjectArrayElement(env, rightsArray, index);
   1015         if (NULL == rights)
   1016             break;
   1017 
   1018         if (JNI_DRM_FAILURE == setRightsFields(env, rights, &(pCurNode->roInfo)))
   1019             break;
   1020 
   1021         (*env)->SetObjectArrayElement(env, rightsArray, index, rights);
   1022 
   1023         pCurNode = pCurNode->next;
   1024     }
   1025 
   1026     SVC_drm_freeRightsInfoList(pRightsList);
   1027 
   1028     return index;
   1029 }
   1030 
   1031 /* native interface */
   1032 JNIEXPORT jint JNICALL
   1033 Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights
   1034   (JNIEnv * env, jobject rightsManager, jobject rights)
   1035 {
   1036     jclass clazz;
   1037     jfieldID field;
   1038     jstring str;
   1039     uint8_t *nativeStr;
   1040 
   1041     clazz = (*env)->GetObjectClass(env, rights);
   1042     if (NULL == clazz)
   1043         return JNI_DRM_FAILURE;
   1044 
   1045     field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
   1046     if (NULL == field)
   1047         return JNI_DRM_FAILURE;
   1048 
   1049     str = (*env)->GetObjectField(env, rights, field);
   1050 
   1051     nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
   1052     if (NULL == nativeStr)
   1053         return JNI_DRM_FAILURE;
   1054 
   1055     if (0 == strcmp("ForwardLock", (char *)nativeStr))
   1056         return JNI_DRM_SUCCESS;
   1057 
   1058     if (DRM_SUCCESS != SVC_drm_deleteRights(nativeStr)) {
   1059         (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
   1060         return JNI_DRM_FAILURE;
   1061     }
   1062 
   1063     (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
   1064     return JNI_DRM_SUCCESS;
   1065 }
   1066 
   1067 /*
   1068  * Table of methods associated with the DrmRawContent class.
   1069  */
   1070 static JNINativeMethod gDrmRawContentMethods[] = {
   1071     /* name, signature, funcPtr */
   1072     {"nativeConstructDrmContent", "(Ljava/io/InputStream;II)I",
   1073         (void*)Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent},
   1074     {"nativeGetRightsAddress", "()Ljava/lang/String;",
   1075         (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress},
   1076     {"nativeGetDeliveryMethod", "()I",
   1077         (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod},
   1078     {"nativeReadContent", "([BIII)I",
   1079         (void*)Java_android_drm_mobile1_DrmRawContent_nativeReadContent},
   1080     {"nativeGetContentType", "()Ljava/lang/String;",
   1081         (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetContentType},
   1082     {"nativeGetContentLength", "()I",
   1083         (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength},
   1084     {"finalize", "()V",
   1085         (void*)Java_android_drm_mobile1_DrmRawContent_finalize},
   1086 };
   1087 
   1088 /*
   1089  * Table of methods associated with the DrmRights class.
   1090  */
   1091 static JNINativeMethod gDrmRightsMethods[] = {
   1092     /* name, signature, funcPtr */
   1093     {"nativeGetConstraintInfo", "(ILandroid/drm/mobile1/DrmConstraintInfo;)I",
   1094         (void*)Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo},
   1095     {"nativeConsumeRights", "(I)I",
   1096         (void*)Java_android_drm_mobile1_DrmRights_nativeConsumeRights},
   1097 };
   1098 
   1099 /*
   1100  * Table of methods associated with the DrmRightsManager class.
   1101  */
   1102 static JNINativeMethod gDrmRightsManagerMethods[] = {
   1103     /* name, signature, funcPtr */
   1104     {"nativeInstallDrmRights", "(Ljava/io/InputStream;IILandroid/drm/mobile1/DrmRights;)I",
   1105         (void*)Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights},
   1106     {"nativeQueryRights", "(Landroid/drm/mobile1/DrmRawContent;Landroid/drm/mobile1/DrmRights;)I",
   1107         (void*)Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights},
   1108     {"nativeGetNumOfRights", "()I",
   1109         (void*)Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights},
   1110     {"nativeGetRightsList", "([Landroid/drm/mobile1/DrmRights;I)I",
   1111         (void*)Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList},
   1112     {"nativeDeleteRights", "(Landroid/drm/mobile1/DrmRights;)I",
   1113         (void*)Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights},
   1114 };
   1115 
   1116 /*
   1117  * Register several native methods for one class.
   1118  */
   1119 static int registerNativeMethods(JNIEnv* env, const char* className,
   1120     JNINativeMethod* gMethods, int numMethods)
   1121 {
   1122     jclass clazz;
   1123 
   1124     clazz = (*env)->FindClass(env, className);
   1125     if (clazz == NULL)
   1126         return JNI_FALSE;
   1127 
   1128     if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
   1129         return JNI_FALSE;
   1130 
   1131     return JNI_TRUE;
   1132 }
   1133 
   1134 /*
   1135  * Register native methods for all classes we know about.
   1136  */
   1137 static int registerNatives(JNIEnv* env)
   1138 {
   1139     if (!registerNativeMethods(env, "android/drm/mobile1/DrmRawContent",
   1140             gDrmRawContentMethods, sizeof(gDrmRawContentMethods) / sizeof(gDrmRawContentMethods[0])))
   1141         return JNI_FALSE;
   1142 
   1143     if (!registerNativeMethods(env, "android/drm/mobile1/DrmRights",
   1144             gDrmRightsMethods, sizeof(gDrmRightsMethods) / sizeof(gDrmRightsMethods[0])))
   1145         return JNI_FALSE;
   1146 
   1147     if (!registerNativeMethods(env, "android/drm/mobile1/DrmRightsManager",
   1148             gDrmRightsManagerMethods, sizeof(gDrmRightsManagerMethods) / sizeof(gDrmRightsManagerMethods[0])))
   1149         return JNI_FALSE;
   1150 
   1151     return JNI_TRUE;
   1152 }
   1153 
   1154 jint JNI_OnLoad(JavaVM* vm, void* reserved)
   1155 {
   1156     JNIEnv* env = NULL;
   1157     jint result = -1;
   1158 
   1159     printf("Entering JNI_OnLoad\n");
   1160 
   1161     if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
   1162         goto bail;
   1163 
   1164     assert(env != NULL);
   1165 
   1166     if (!registerNatives(env))
   1167         goto bail;
   1168 
   1169     /* success -- return valid version number */
   1170     result = JNI_VERSION_1_4;
   1171 
   1172 bail:
   1173     printf("Leaving JNI_OnLoad (result=0x%x)\n", result);
   1174     return result;
   1175 }
   1176