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