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