• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
newItem(void)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  */
freeItem(DrmData * d)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  */
addItem(DrmData * d)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  */
getItem(int32_t id)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  */
removeItem(int32_t id)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 
getInputStreamDataLength(int32_t handle)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 
readInputStreamData(int32_t handle,uint8_t * buf,int32_t bufLen)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 
searchRightsObject(const jbyte * roId,const T_DRM_Rights_Info_Node * pRightsList)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  */
mkgmtime(uint32_t year,uint32_t month,uint32_t day,uint32_t hour,uint32_t minute,uint32_t second)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  */
computeTime(int32_t date,int32_t time)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  */
computeInterval(int32_t date,int32_t time)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 
getObjectIntField(JNIEnv * env,jobject obj,const char * name,jint * value)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 
setObjectIntField(JNIEnv * env,jobject obj,const char * name,jint value)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 
setObjectLongField(JNIEnv * env,jobject obj,const char * name,jlong value)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 
setConstraintFields(JNIEnv * env,jobject constraint,T_DRM_Constraint_Info * pConstraint)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 
setRightsFields(JNIEnv * env,jobject rights,T_DRM_Rights_Info * pRoInfo)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
Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent(JNIEnv * env,jobject rawContent,jobject data,jint len,jint mimeType)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
Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress(JNIEnv * env,jobject rawContent)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
Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod(JNIEnv * env,jobject rawContent)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
Java_android_drm_mobile1_DrmRawContent_nativeReadContent(JNIEnv * env,jobject rawContent,jbyteArray buf,jint bufOff,jint len,jint mediaOff)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
Java_android_drm_mobile1_DrmRawContent_nativeGetContentType(JNIEnv * env,jobject rawContent)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
Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength(JNIEnv * env,jobject rawContent)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
Java_android_drm_mobile1_DrmRawContent_finalize(JNIEnv * env,jobject rawContent)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
Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo(JNIEnv * env,jobject rights,jint permission,jobject constraint)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
Java_android_drm_mobile1_DrmRights_nativeConsumeRights(JNIEnv * env,jobject rights,jint permission)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
Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights(JNIEnv * env,jobject rightsManager,jobject data,jint len,jint mimeType,jobject rights)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
Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights(JNIEnv * env,jobject rightsManager,jobject rawContent,jobject rights)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
Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights(JNIEnv * env,jobject rightsManager)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
Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList(JNIEnv * env,jobject rightsManager,jobjectArray rightsArray,jint num)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
Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights(JNIEnv * env,jobject rightsManager,jobject rights)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  */
registerNativeMethods(JNIEnv * env,const char * className,JNINativeMethod * gMethods,int numMethods)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  */
registerNatives(JNIEnv * env)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 
JNI_OnLoad(JavaVM * vm,void * reserved)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