1 /* 2 * Copyright (C) 2013 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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "IDrm" 19 #include <utils/Log.h> 20 21 #include <binder/Parcel.h> 22 #include <media/IDrm.h> 23 #include <media/stagefright/MediaErrors.h> 24 #include <media/stagefright/foundation/ADebug.h> 25 #include <media/stagefright/foundation/AString.h> 26 27 namespace android { 28 29 enum { 30 INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION, 31 IS_CRYPTO_SUPPORTED, 32 CREATE_PLUGIN, 33 DESTROY_PLUGIN, 34 OPEN_SESSION, 35 CLOSE_SESSION, 36 GET_KEY_REQUEST, 37 PROVIDE_KEY_RESPONSE, 38 REMOVE_KEYS, 39 RESTORE_KEYS, 40 QUERY_KEY_STATUS, 41 GET_PROVISION_REQUEST, 42 PROVIDE_PROVISION_RESPONSE, 43 GET_SECURE_STOPS, 44 RELEASE_SECURE_STOPS, 45 GET_PROPERTY_STRING, 46 GET_PROPERTY_BYTE_ARRAY, 47 SET_PROPERTY_STRING, 48 SET_PROPERTY_BYTE_ARRAY, 49 SET_CIPHER_ALGORITHM, 50 SET_MAC_ALGORITHM, 51 ENCRYPT, 52 DECRYPT, 53 SIGN, 54 VERIFY, 55 SET_LISTENER 56 }; 57 58 struct BpDrm : public BpInterface<IDrm> { 59 BpDrm(const sp<IBinder> &impl) 60 : BpInterface<IDrm>(impl) { 61 } 62 63 virtual status_t initCheck() const { 64 Parcel data, reply; 65 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 66 remote()->transact(INIT_CHECK, data, &reply); 67 68 return reply.readInt32(); 69 } 70 71 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) { 72 Parcel data, reply; 73 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 74 data.write(uuid, 16); 75 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); 76 77 return reply.readInt32() != 0; 78 } 79 80 virtual status_t createPlugin(const uint8_t uuid[16]) { 81 Parcel data, reply; 82 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 83 data.write(uuid, 16); 84 85 remote()->transact(CREATE_PLUGIN, data, &reply); 86 87 return reply.readInt32(); 88 } 89 90 virtual status_t destroyPlugin() { 91 Parcel data, reply; 92 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 93 remote()->transact(DESTROY_PLUGIN, data, &reply); 94 95 return reply.readInt32(); 96 } 97 98 virtual status_t openSession(Vector<uint8_t> &sessionId) { 99 Parcel data, reply; 100 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 101 102 remote()->transact(OPEN_SESSION, data, &reply); 103 readVector(reply, sessionId); 104 105 return reply.readInt32(); 106 } 107 108 virtual status_t closeSession(Vector<uint8_t> const &sessionId) { 109 Parcel data, reply; 110 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 111 112 writeVector(data, sessionId); 113 remote()->transact(CLOSE_SESSION, data, &reply); 114 115 return reply.readInt32(); 116 } 117 118 virtual status_t 119 getKeyRequest(Vector<uint8_t> const &sessionId, 120 Vector<uint8_t> const &initData, 121 String8 const &mimeType, DrmPlugin::KeyType keyType, 122 KeyedVector<String8, String8> const &optionalParameters, 123 Vector<uint8_t> &request, String8 &defaultUrl) { 124 Parcel data, reply; 125 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 126 127 writeVector(data, sessionId); 128 writeVector(data, initData); 129 data.writeString8(mimeType); 130 data.writeInt32((uint32_t)keyType); 131 132 data.writeInt32(optionalParameters.size()); 133 for (size_t i = 0; i < optionalParameters.size(); ++i) { 134 data.writeString8(optionalParameters.keyAt(i)); 135 data.writeString8(optionalParameters.valueAt(i)); 136 } 137 remote()->transact(GET_KEY_REQUEST, data, &reply); 138 139 readVector(reply, request); 140 defaultUrl = reply.readString8(); 141 142 return reply.readInt32(); 143 } 144 145 virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId, 146 Vector<uint8_t> const &response, 147 Vector<uint8_t> &keySetId) { 148 Parcel data, reply; 149 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 150 writeVector(data, sessionId); 151 writeVector(data, response); 152 remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply); 153 readVector(reply, keySetId); 154 155 return reply.readInt32(); 156 } 157 158 virtual status_t removeKeys(Vector<uint8_t> const &keySetId) { 159 Parcel data, reply; 160 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 161 162 writeVector(data, keySetId); 163 remote()->transact(REMOVE_KEYS, data, &reply); 164 165 return reply.readInt32(); 166 } 167 168 virtual status_t restoreKeys(Vector<uint8_t> const &sessionId, 169 Vector<uint8_t> const &keySetId) { 170 Parcel data, reply; 171 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 172 173 writeVector(data, sessionId); 174 writeVector(data, keySetId); 175 remote()->transact(RESTORE_KEYS, data, &reply); 176 177 return reply.readInt32(); 178 } 179 180 virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId, 181 KeyedVector<String8, String8> &infoMap) const { 182 Parcel data, reply; 183 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 184 185 writeVector(data, sessionId); 186 remote()->transact(QUERY_KEY_STATUS, data, &reply); 187 188 infoMap.clear(); 189 size_t count = reply.readInt32(); 190 for (size_t i = 0; i < count; i++) { 191 String8 key = reply.readString8(); 192 String8 value = reply.readString8(); 193 infoMap.add(key, value); 194 } 195 return reply.readInt32(); 196 } 197 198 virtual status_t getProvisionRequest(Vector<uint8_t> &request, 199 String8 &defaultUrl) { 200 Parcel data, reply; 201 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 202 203 remote()->transact(GET_PROVISION_REQUEST, data, &reply); 204 205 readVector(reply, request); 206 defaultUrl = reply.readString8(); 207 208 return reply.readInt32(); 209 } 210 211 virtual status_t provideProvisionResponse(Vector<uint8_t> const &response) { 212 Parcel data, reply; 213 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 214 215 writeVector(data, response); 216 remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply); 217 218 return reply.readInt32(); 219 } 220 221 virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) { 222 Parcel data, reply; 223 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 224 225 remote()->transact(GET_SECURE_STOPS, data, &reply); 226 227 secureStops.clear(); 228 uint32_t count = reply.readInt32(); 229 for (size_t i = 0; i < count; i++) { 230 Vector<uint8_t> secureStop; 231 readVector(reply, secureStop); 232 secureStops.push_back(secureStop); 233 } 234 return reply.readInt32(); 235 } 236 237 virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) { 238 Parcel data, reply; 239 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 240 241 writeVector(data, ssRelease); 242 remote()->transact(RELEASE_SECURE_STOPS, data, &reply); 243 244 return reply.readInt32(); 245 } 246 247 virtual status_t getPropertyString(String8 const &name, String8 &value) const { 248 Parcel data, reply; 249 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 250 251 data.writeString8(name); 252 remote()->transact(GET_PROPERTY_STRING, data, &reply); 253 254 value = reply.readString8(); 255 return reply.readInt32(); 256 } 257 258 virtual status_t getPropertyByteArray(String8 const &name, Vector<uint8_t> &value) const { 259 Parcel data, reply; 260 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 261 262 data.writeString8(name); 263 remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply); 264 265 readVector(reply, value); 266 return reply.readInt32(); 267 } 268 269 virtual status_t setPropertyString(String8 const &name, String8 const &value) const { 270 Parcel data, reply; 271 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 272 273 data.writeString8(name); 274 data.writeString8(value); 275 remote()->transact(SET_PROPERTY_STRING, data, &reply); 276 277 return reply.readInt32(); 278 } 279 280 virtual status_t setPropertyByteArray(String8 const &name, 281 Vector<uint8_t> const &value) const { 282 Parcel data, reply; 283 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 284 285 data.writeString8(name); 286 writeVector(data, value); 287 remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply); 288 289 return reply.readInt32(); 290 } 291 292 293 virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId, 294 String8 const &algorithm) { 295 Parcel data, reply; 296 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 297 298 writeVector(data, sessionId); 299 data.writeString8(algorithm); 300 remote()->transact(SET_CIPHER_ALGORITHM, data, &reply); 301 return reply.readInt32(); 302 } 303 304 virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId, 305 String8 const &algorithm) { 306 Parcel data, reply; 307 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 308 309 writeVector(data, sessionId); 310 data.writeString8(algorithm); 311 remote()->transact(SET_MAC_ALGORITHM, data, &reply); 312 return reply.readInt32(); 313 } 314 315 virtual status_t encrypt(Vector<uint8_t> const &sessionId, 316 Vector<uint8_t> const &keyId, 317 Vector<uint8_t> const &input, 318 Vector<uint8_t> const &iv, 319 Vector<uint8_t> &output) { 320 Parcel data, reply; 321 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 322 323 writeVector(data, sessionId); 324 writeVector(data, keyId); 325 writeVector(data, input); 326 writeVector(data, iv); 327 328 remote()->transact(ENCRYPT, data, &reply); 329 readVector(reply, output); 330 331 return reply.readInt32(); 332 } 333 334 virtual status_t decrypt(Vector<uint8_t> const &sessionId, 335 Vector<uint8_t> const &keyId, 336 Vector<uint8_t> const &input, 337 Vector<uint8_t> const &iv, 338 Vector<uint8_t> &output) { 339 Parcel data, reply; 340 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 341 342 writeVector(data, sessionId); 343 writeVector(data, keyId); 344 writeVector(data, input); 345 writeVector(data, iv); 346 347 remote()->transact(DECRYPT, data, &reply); 348 readVector(reply, output); 349 350 return reply.readInt32(); 351 } 352 353 virtual status_t sign(Vector<uint8_t> const &sessionId, 354 Vector<uint8_t> const &keyId, 355 Vector<uint8_t> const &message, 356 Vector<uint8_t> &signature) { 357 Parcel data, reply; 358 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 359 360 writeVector(data, sessionId); 361 writeVector(data, keyId); 362 writeVector(data, message); 363 364 remote()->transact(SIGN, data, &reply); 365 readVector(reply, signature); 366 367 return reply.readInt32(); 368 } 369 370 virtual status_t verify(Vector<uint8_t> const &sessionId, 371 Vector<uint8_t> const &keyId, 372 Vector<uint8_t> const &message, 373 Vector<uint8_t> const &signature, 374 bool &match) { 375 Parcel data, reply; 376 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 377 378 writeVector(data, sessionId); 379 writeVector(data, keyId); 380 writeVector(data, message); 381 writeVector(data, signature); 382 383 remote()->transact(VERIFY, data, &reply); 384 match = (bool)reply.readInt32(); 385 return reply.readInt32(); 386 } 387 388 virtual status_t setListener(const sp<IDrmClient>& listener) { 389 Parcel data, reply; 390 data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 391 data.writeStrongBinder(listener->asBinder()); 392 remote()->transact(SET_LISTENER, data, &reply); 393 return reply.readInt32(); 394 } 395 396 private: 397 void readVector(Parcel &reply, Vector<uint8_t> &vector) const { 398 uint32_t size = reply.readInt32(); 399 vector.insertAt((size_t)0, size); 400 reply.read(vector.editArray(), size); 401 } 402 403 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const { 404 data.writeInt32(vector.size()); 405 data.write(vector.array(), vector.size()); 406 } 407 408 DISALLOW_EVIL_CONSTRUCTORS(BpDrm); 409 }; 410 411 IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm"); 412 413 //////////////////////////////////////////////////////////////////////////////// 414 415 void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const { 416 uint32_t size = data.readInt32(); 417 vector.insertAt((size_t)0, size); 418 data.read(vector.editArray(), size); 419 } 420 421 void BnDrm::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const { 422 reply->writeInt32(vector.size()); 423 reply->write(vector.array(), vector.size()); 424 } 425 426 status_t BnDrm::onTransact( 427 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 428 switch (code) { 429 case INIT_CHECK: 430 { 431 CHECK_INTERFACE(IDrm, data, reply); 432 reply->writeInt32(initCheck()); 433 return OK; 434 } 435 436 case IS_CRYPTO_SUPPORTED: 437 { 438 CHECK_INTERFACE(IDrm, data, reply); 439 uint8_t uuid[16]; 440 data.read(uuid, sizeof(uuid)); 441 reply->writeInt32(isCryptoSchemeSupported(uuid)); 442 return OK; 443 } 444 445 case CREATE_PLUGIN: 446 { 447 CHECK_INTERFACE(IDrm, data, reply); 448 uint8_t uuid[16]; 449 data.read(uuid, sizeof(uuid)); 450 reply->writeInt32(createPlugin(uuid)); 451 return OK; 452 } 453 454 case DESTROY_PLUGIN: 455 { 456 CHECK_INTERFACE(IDrm, data, reply); 457 reply->writeInt32(destroyPlugin()); 458 return OK; 459 } 460 461 case OPEN_SESSION: 462 { 463 CHECK_INTERFACE(IDrm, data, reply); 464 Vector<uint8_t> sessionId; 465 status_t result = openSession(sessionId); 466 writeVector(reply, sessionId); 467 reply->writeInt32(result); 468 return OK; 469 } 470 471 case CLOSE_SESSION: 472 { 473 CHECK_INTERFACE(IDrm, data, reply); 474 Vector<uint8_t> sessionId; 475 readVector(data, sessionId); 476 reply->writeInt32(closeSession(sessionId)); 477 return OK; 478 } 479 480 case GET_KEY_REQUEST: 481 { 482 CHECK_INTERFACE(IDrm, data, reply); 483 Vector<uint8_t> sessionId, initData; 484 485 readVector(data, sessionId); 486 readVector(data, initData); 487 String8 mimeType = data.readString8(); 488 DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32(); 489 490 KeyedVector<String8, String8> optionalParameters; 491 uint32_t count = data.readInt32(); 492 for (size_t i = 0; i < count; ++i) { 493 String8 key, value; 494 key = data.readString8(); 495 value = data.readString8(); 496 optionalParameters.add(key, value); 497 } 498 499 Vector<uint8_t> request; 500 String8 defaultUrl; 501 502 status_t result = getKeyRequest(sessionId, initData, 503 mimeType, keyType, 504 optionalParameters, 505 request, defaultUrl); 506 writeVector(reply, request); 507 reply->writeString8(defaultUrl); 508 reply->writeInt32(result); 509 return OK; 510 } 511 512 case PROVIDE_KEY_RESPONSE: 513 { 514 CHECK_INTERFACE(IDrm, data, reply); 515 Vector<uint8_t> sessionId, response, keySetId; 516 readVector(data, sessionId); 517 readVector(data, response); 518 uint32_t result = provideKeyResponse(sessionId, response, keySetId); 519 writeVector(reply, keySetId); 520 reply->writeInt32(result); 521 return OK; 522 } 523 524 case REMOVE_KEYS: 525 { 526 CHECK_INTERFACE(IDrm, data, reply); 527 Vector<uint8_t> keySetId; 528 readVector(data, keySetId); 529 reply->writeInt32(removeKeys(keySetId)); 530 return OK; 531 } 532 533 case RESTORE_KEYS: 534 { 535 CHECK_INTERFACE(IDrm, data, reply); 536 Vector<uint8_t> sessionId, keySetId; 537 readVector(data, sessionId); 538 readVector(data, keySetId); 539 reply->writeInt32(restoreKeys(sessionId, keySetId)); 540 return OK; 541 } 542 543 case QUERY_KEY_STATUS: 544 { 545 CHECK_INTERFACE(IDrm, data, reply); 546 Vector<uint8_t> sessionId; 547 readVector(data, sessionId); 548 KeyedVector<String8, String8> infoMap; 549 status_t result = queryKeyStatus(sessionId, infoMap); 550 size_t count = infoMap.size(); 551 reply->writeInt32(count); 552 for (size_t i = 0; i < count; ++i) { 553 reply->writeString8(infoMap.keyAt(i)); 554 reply->writeString8(infoMap.valueAt(i)); 555 } 556 reply->writeInt32(result); 557 return OK; 558 } 559 560 case GET_PROVISION_REQUEST: 561 { 562 CHECK_INTERFACE(IDrm, data, reply); 563 Vector<uint8_t> request; 564 String8 defaultUrl; 565 status_t result = getProvisionRequest(request, defaultUrl); 566 writeVector(reply, request); 567 reply->writeString8(defaultUrl); 568 reply->writeInt32(result); 569 return OK; 570 } 571 572 case PROVIDE_PROVISION_RESPONSE: 573 { 574 CHECK_INTERFACE(IDrm, data, reply); 575 Vector<uint8_t> response; 576 readVector(data, response); 577 reply->writeInt32(provideProvisionResponse(response)); 578 return OK; 579 } 580 581 case GET_SECURE_STOPS: 582 { 583 CHECK_INTERFACE(IDrm, data, reply); 584 List<Vector<uint8_t> > secureStops; 585 status_t result = getSecureStops(secureStops); 586 size_t count = secureStops.size(); 587 reply->writeInt32(count); 588 List<Vector<uint8_t> >::iterator iter = secureStops.begin(); 589 while(iter != secureStops.end()) { 590 size_t size = iter->size(); 591 reply->writeInt32(size); 592 reply->write(iter->array(), iter->size()); 593 iter++; 594 } 595 reply->writeInt32(result); 596 return OK; 597 } 598 599 case RELEASE_SECURE_STOPS: 600 { 601 CHECK_INTERFACE(IDrm, data, reply); 602 Vector<uint8_t> ssRelease; 603 readVector(data, ssRelease); 604 reply->writeInt32(releaseSecureStops(ssRelease)); 605 return OK; 606 } 607 608 case GET_PROPERTY_STRING: 609 { 610 CHECK_INTERFACE(IDrm, data, reply); 611 String8 name = data.readString8(); 612 String8 value; 613 status_t result = getPropertyString(name, value); 614 reply->writeString8(value); 615 reply->writeInt32(result); 616 return OK; 617 } 618 619 case GET_PROPERTY_BYTE_ARRAY: 620 { 621 CHECK_INTERFACE(IDrm, data, reply); 622 String8 name = data.readString8(); 623 Vector<uint8_t> value; 624 status_t result = getPropertyByteArray(name, value); 625 writeVector(reply, value); 626 reply->writeInt32(result); 627 return OK; 628 } 629 630 case SET_PROPERTY_STRING: 631 { 632 CHECK_INTERFACE(IDrm, data, reply); 633 String8 name = data.readString8(); 634 String8 value = data.readString8(); 635 reply->writeInt32(setPropertyString(name, value)); 636 return OK; 637 } 638 639 case SET_PROPERTY_BYTE_ARRAY: 640 { 641 CHECK_INTERFACE(IDrm, data, reply); 642 String8 name = data.readString8(); 643 Vector<uint8_t> value; 644 readVector(data, value); 645 reply->writeInt32(setPropertyByteArray(name, value)); 646 return OK; 647 } 648 649 case SET_CIPHER_ALGORITHM: 650 { 651 CHECK_INTERFACE(IDrm, data, reply); 652 Vector<uint8_t> sessionId; 653 readVector(data, sessionId); 654 String8 algorithm = data.readString8(); 655 reply->writeInt32(setCipherAlgorithm(sessionId, algorithm)); 656 return OK; 657 } 658 659 case SET_MAC_ALGORITHM: 660 { 661 CHECK_INTERFACE(IDrm, data, reply); 662 Vector<uint8_t> sessionId; 663 readVector(data, sessionId); 664 String8 algorithm = data.readString8(); 665 reply->writeInt32(setMacAlgorithm(sessionId, algorithm)); 666 return OK; 667 } 668 669 case ENCRYPT: 670 { 671 CHECK_INTERFACE(IDrm, data, reply); 672 Vector<uint8_t> sessionId, keyId, input, iv, output; 673 readVector(data, sessionId); 674 readVector(data, keyId); 675 readVector(data, input); 676 readVector(data, iv); 677 uint32_t result = encrypt(sessionId, keyId, input, iv, output); 678 writeVector(reply, output); 679 reply->writeInt32(result); 680 return OK; 681 } 682 683 case DECRYPT: 684 { 685 CHECK_INTERFACE(IDrm, data, reply); 686 Vector<uint8_t> sessionId, keyId, input, iv, output; 687 readVector(data, sessionId); 688 readVector(data, keyId); 689 readVector(data, input); 690 readVector(data, iv); 691 uint32_t result = decrypt(sessionId, keyId, input, iv, output); 692 writeVector(reply, output); 693 reply->writeInt32(result); 694 return OK; 695 } 696 697 case SIGN: 698 { 699 CHECK_INTERFACE(IDrm, data, reply); 700 Vector<uint8_t> sessionId, keyId, message, signature; 701 readVector(data, sessionId); 702 readVector(data, keyId); 703 readVector(data, message); 704 uint32_t result = sign(sessionId, keyId, message, signature); 705 writeVector(reply, signature); 706 reply->writeInt32(result); 707 return OK; 708 } 709 710 case VERIFY: 711 { 712 CHECK_INTERFACE(IDrm, data, reply); 713 Vector<uint8_t> sessionId, keyId, message, signature; 714 readVector(data, sessionId); 715 readVector(data, keyId); 716 readVector(data, message); 717 readVector(data, signature); 718 bool match; 719 uint32_t result = verify(sessionId, keyId, message, signature, match); 720 reply->writeInt32(match); 721 reply->writeInt32(result); 722 return OK; 723 } 724 725 case SET_LISTENER: { 726 CHECK_INTERFACE(IDrm, data, reply); 727 sp<IDrmClient> listener = 728 interface_cast<IDrmClient>(data.readStrongBinder()); 729 reply->writeInt32(setListener(listener)); 730 return NO_ERROR; 731 } break; 732 733 default: 734 return BBinder::onTransact(code, data, reply, flags); 735 } 736 } 737 738 } // namespace android 739 740