OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libdrm / mobile1 / src / jni / drm1_jni.c
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 }