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