MockDrmCryptoPlugin.cpp revision c0d5f1f8405de861ed6f1725f26cd6601e7103ab
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 "MockDrmCryptoPlugin" 19#include <utils/Log.h> 20 21 22#include "drm/DrmAPI.h" 23#include "MockDrmCryptoPlugin.h" 24#include "media/stagefright/MediaErrors.h" 25 26using namespace android; 27 28// Shared library entry point 29DrmFactory *createDrmFactory() 30{ 31 return new MockDrmFactory(); 32} 33 34// Shared library entry point 35CryptoFactory *createCryptoFactory() 36{ 37 return new MockCryptoFactory(); 38} 39 40const uint8_t mock_uuid[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 41 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; 42 43namespace android { 44 45 // MockDrmFactory 46 bool MockDrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) 47 { 48 return (!memcmp(uuid, mock_uuid, sizeof(uuid))); 49 } 50 51 status_t MockDrmFactory::createDrmPlugin(const uint8_t uuid[16], DrmPlugin **plugin) 52 { 53 *plugin = new MockDrmPlugin(); 54 return OK; 55 } 56 57 // MockCryptoFactory 58 bool MockCryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const 59 { 60 return (!memcmp(uuid, mock_uuid, sizeof(uuid))); 61 } 62 63 status_t MockCryptoFactory::createPlugin(const uint8_t uuid[16], const void *data, 64 size_t size, CryptoPlugin **plugin) 65 { 66 *plugin = new MockCryptoPlugin(); 67 return OK; 68 } 69 70 71 // MockDrmPlugin methods 72 73 status_t MockDrmPlugin::openSession(Vector<uint8_t> &sessionId) 74 { 75 const size_t kSessionIdSize = 8; 76 77 Mutex::Autolock lock(mLock); 78 for (size_t i = 0; i < kSessionIdSize / sizeof(long); i++) { 79 long r = random(); 80 sessionId.appendArray((uint8_t *)&r, sizeof(long)); 81 } 82 mSessions.add(sessionId); 83 84 ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string()); 85 return OK; 86 } 87 88 status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId) 89 { 90 Mutex::Autolock lock(mLock); 91 ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string()); 92 ssize_t index = findSession(sessionId); 93 if (index == kNotFound) { 94 ALOGD("Invalid sessionId"); 95 return BAD_VALUE; 96 } 97 mSessions.removeAt(index); 98 return OK; 99 } 100 101 102 status_t MockDrmPlugin::getKeyRequest(Vector<uint8_t> const &sessionId, 103 Vector<uint8_t> const &initData, 104 String8 const &mimeType, KeyType keyType, 105 KeyedVector<String8, String8> const &optionalParameters, 106 Vector<uint8_t> &request, String8 &defaultUrl) 107 { 108 Mutex::Autolock lock(mLock); 109 ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s" 110 ", keyType=%d, optionalParameters=%s))", 111 vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(), 112 keyType, stringMapToString(optionalParameters).string()); 113 114 ssize_t index = findSession(sessionId); 115 if (index == kNotFound) { 116 ALOGD("Invalid sessionId"); 117 return BAD_VALUE; 118 } 119 120 // Properties used in mock test, set by mock plugin and verifed cts test app 121 // byte[] initData -> mock-initdata 122 // string mimeType -> mock-mimetype 123 // string keyType -> mock-keytype 124 // string optionalParameters -> mock-optparams formatted as {key1,value1},{key2,value2} 125 126 mByteArrayProperties.add(String8("mock-initdata"), initData); 127 mStringProperties.add(String8("mock-mimetype"), mimeType); 128 129 String8 keyTypeStr; 130 keyTypeStr.appendFormat("%d", (int)keyType); 131 mStringProperties.add(String8("mock-keytype"), keyTypeStr); 132 133 String8 params; 134 for (size_t i = 0; i < optionalParameters.size(); i++) { 135 params.appendFormat("%s{%s,%s}", i ? "," : "", 136 optionalParameters.keyAt(i).string(), 137 optionalParameters.valueAt(i).string()); 138 } 139 mStringProperties.add(String8("mock-optparams"), params); 140 141 // Properties used in mock test, set by cts test app returned from mock plugin 142 // byte[] mock-request -> request 143 // string mock-default-url -> defaultUrl 144 145 index = mByteArrayProperties.indexOfKey(String8("mock-request")); 146 if (index < 0) { 147 ALOGD("Missing 'mock-request' parameter for mock"); 148 return BAD_VALUE; 149 } else { 150 request = mByteArrayProperties.valueAt(index); 151 } 152 153 index = mStringProperties.indexOfKey(String8("mock-defaultUrl")); 154 if (index < 0) { 155 ALOGD("Missing 'mock-defaultUrl' parameter for mock"); 156 return BAD_VALUE; 157 } else { 158 defaultUrl = mStringProperties.valueAt(index); 159 } 160 return OK; 161 } 162 163 status_t MockDrmPlugin::provideKeyResponse(Vector<uint8_t> const &sessionId, 164 Vector<uint8_t> const &response, 165 Vector<uint8_t> &keySetId) 166 { 167 Mutex::Autolock lock(mLock); 168 ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)", 169 vectorToString(sessionId).string(), vectorToString(response).string()); 170 ssize_t index = findSession(sessionId); 171 if (index == kNotFound) { 172 ALOGD("Invalid sessionId"); 173 return BAD_VALUE; 174 } 175 if (response.size() == 0) { 176 return BAD_VALUE; 177 } 178 179 // Properties used in mock test, set by mock plugin and verifed cts test app 180 // byte[] response -> mock-response 181 mByteArrayProperties.add(String8("mock-response"), response); 182 183 const size_t kKeySetIdSize = 8; 184 185 for (size_t i = 0; i < kKeySetIdSize / sizeof(long); i++) { 186 long r = random(); 187 keySetId.appendArray((uint8_t *)&r, sizeof(long)); 188 } 189 mKeySets.add(keySetId); 190 191 return OK; 192 } 193 194 status_t MockDrmPlugin::removeKeys(Vector<uint8_t> const &keySetId) 195 { 196 Mutex::Autolock lock(mLock); 197 ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)", 198 vectorToString(keySetId).string()); 199 200 ssize_t index = findKeySet(keySetId); 201 if (index == kNotFound) { 202 ALOGD("Invalid keySetId"); 203 return BAD_VALUE; 204 } 205 mKeySets.removeAt(index); 206 207 return OK; 208 } 209 210 status_t MockDrmPlugin::restoreKeys(Vector<uint8_t> const &sessionId, 211 Vector<uint8_t> const &keySetId) 212 { 213 Mutex::Autolock lock(mLock); 214 ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)", 215 vectorToString(sessionId).string(), 216 vectorToString(keySetId).string()); 217 ssize_t index = findSession(sessionId); 218 if (index == kNotFound) { 219 ALOGD("Invalid sessionId"); 220 return BAD_VALUE; 221 } 222 223 index = findKeySet(keySetId); 224 if (index == kNotFound) { 225 ALOGD("Invalid keySetId"); 226 return BAD_VALUE; 227 } 228 229 return OK; 230 } 231 232 status_t MockDrmPlugin::queryKeyStatus(Vector<uint8_t> const &sessionId, 233 KeyedVector<String8, String8> &infoMap) const 234 { 235 ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)", 236 vectorToString(sessionId).string()); 237 238 ssize_t index = findSession(sessionId); 239 if (index == kNotFound) { 240 ALOGD("Invalid sessionId"); 241 return BAD_VALUE; 242 } 243 244 infoMap.add(String8("purchaseDuration"), String8("1000")); 245 infoMap.add(String8("licenseDuration"), String8("100")); 246 return OK; 247 } 248 249 status_t MockDrmPlugin::getProvisionRequest(Vector<uint8_t> &request, 250 String8 &defaultUrl) 251 { 252 Mutex::Autolock lock(mLock); 253 ALOGD("MockDrmPlugin::getProvisionRequest()"); 254 255 // Properties used in mock test, set by cts test app returned from mock plugin 256 // byte[] mock-request -> request 257 // string mock-default-url -> defaultUrl 258 259 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-request")); 260 if (index < 0) { 261 ALOGD("Missing 'mock-request' parameter for mock"); 262 return BAD_VALUE; 263 } else { 264 request = mByteArrayProperties.valueAt(index); 265 } 266 267 index = mStringProperties.indexOfKey(String8("mock-defaultUrl")); 268 if (index < 0) { 269 ALOGD("Missing 'mock-defaultUrl' parameter for mock"); 270 return BAD_VALUE; 271 } else { 272 defaultUrl = mStringProperties.valueAt(index); 273 } 274 return OK; 275 } 276 277 status_t MockDrmPlugin::provideProvisionResponse(Vector<uint8_t> const &response) 278 { 279 Mutex::Autolock lock(mLock); 280 ALOGD("MockDrmPlugin::provideProvisionResponse(%s)", 281 vectorToString(response).string()); 282 283 // Properties used in mock test, set by mock plugin and verifed cts test app 284 // byte[] response -> mock-response 285 286 mByteArrayProperties.add(String8("mock-response"), response); 287 return OK; 288 } 289 290 status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops) 291 { 292 Mutex::Autolock lock(mLock); 293 ALOGD("MockDrmPlugin::getSecureStops()"); 294 const uint8_t ss1[] = {0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89}; 295 const uint8_t ss2[] = {0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99}; 296 297 Vector<uint8_t> vec; 298 vec.appendArray(ss1, sizeof(ss1)); 299 secureStops.push_back(vec); 300 301 vec.clear(); 302 vec.appendArray(ss2, sizeof(ss2)); 303 secureStops.push_back(vec); 304 return OK; 305 } 306 307 status_t MockDrmPlugin::releaseSecureStops(Vector<uint8_t> const &ssRelease) 308 { 309 Mutex::Autolock lock(mLock); 310 ALOGD("MockDrmPlugin::releaseSecureStops(%s)", 311 vectorToString(ssRelease).string()); 312 return OK; 313 } 314 315 status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const 316 { 317 ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string()); 318 ssize_t index = mStringProperties.indexOfKey(name); 319 if (index < 0) { 320 ALOGD("no property for '%s'", name.string()); 321 return BAD_VALUE; 322 } 323 value = mStringProperties.valueAt(index); 324 return OK; 325 } 326 327 status_t MockDrmPlugin::getPropertyByteArray(String8 const &name, 328 Vector<uint8_t> &value) const 329 { 330 ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string()); 331 ssize_t index = mByteArrayProperties.indexOfKey(name); 332 if (index < 0) { 333 ALOGD("no property for '%s'", name.string()); 334 return BAD_VALUE; 335 } 336 value = mByteArrayProperties.valueAt(index); 337 return OK; 338 } 339 340 status_t MockDrmPlugin::setPropertyString(String8 const &name, 341 String8 const &value) 342 { 343 Mutex::Autolock lock(mLock); 344 ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)", 345 name.string(), value.string()); 346 347 if (name == "mock-send-event") { 348 unsigned code, extra; 349 sscanf(value.string(), "%d %d", &code, &extra); 350 DrmPlugin::EventType eventType = (DrmPlugin::EventType)code; 351 352 Vector<uint8_t> const *pSessionId = NULL; 353 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id")); 354 if (index >= 0) { 355 pSessionId = &mByteArrayProperties[index]; 356 } 357 358 Vector<uint8_t> const *pData = NULL; 359 index = mByteArrayProperties.indexOfKey(String8("mock-event-data")); 360 if (index >= 0) { 361 pData = &mByteArrayProperties[index]; 362 } 363 ALOGD("sending event from mock drm plugin: %d %d %s %s", 364 (int)code, extra, pSessionId ? vectorToString(*pSessionId) : "{}", 365 pData ? vectorToString(*pData) : "{}"); 366 367 sendEvent(eventType, extra, pSessionId, pData); 368 } else { 369 mStringProperties.add(name, value); 370 } 371 return OK; 372 } 373 374 status_t MockDrmPlugin::setPropertyByteArray(String8 const &name, 375 Vector<uint8_t> const &value) 376 { 377 Mutex::Autolock lock(mLock); 378 ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)", 379 name.string(), vectorToString(value).string()); 380 mByteArrayProperties.add(name, value); 381 return OK; 382 } 383 384 status_t MockDrmPlugin::setCipherAlgorithm(Vector<uint8_t> const &sessionId, 385 String8 const &algorithm) 386 { 387 Mutex::Autolock lock(mLock); 388 389 ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)", 390 vectorToString(sessionId).string(), algorithm.string()); 391 392 ssize_t index = findSession(sessionId); 393 if (index == kNotFound) { 394 ALOGD("Invalid sessionId"); 395 return BAD_VALUE; 396 } 397 398 if (algorithm == "AES/CBC/NoPadding") { 399 return OK; 400 } 401 return BAD_VALUE; 402 } 403 404 status_t MockDrmPlugin::setMacAlgorithm(Vector<uint8_t> const &sessionId, 405 String8 const &algorithm) 406 { 407 Mutex::Autolock lock(mLock); 408 409 ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)", 410 vectorToString(sessionId).string(), algorithm.string()); 411 412 ssize_t index = findSession(sessionId); 413 if (index == kNotFound) { 414 ALOGD("Invalid sessionId"); 415 return BAD_VALUE; 416 } 417 418 if (algorithm == "HmacSHA256") { 419 return OK; 420 } 421 return BAD_VALUE; 422 } 423 424 status_t MockDrmPlugin::encrypt(Vector<uint8_t> const &sessionId, 425 Vector<uint8_t> const &keyId, 426 Vector<uint8_t> const &input, 427 Vector<uint8_t> const &iv, 428 Vector<uint8_t> &output) 429 { 430 Mutex::Autolock lock(mLock); 431 ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)", 432 vectorToString(sessionId).string(), 433 vectorToString(keyId).string(), 434 vectorToString(input).string(), 435 vectorToString(iv).string()); 436 437 ssize_t index = findSession(sessionId); 438 if (index == kNotFound) { 439 ALOGD("Invalid sessionId"); 440 return BAD_VALUE; 441 } 442 443 // Properties used in mock test, set by mock plugin and verifed cts test app 444 // byte[] keyId -> mock-keyid 445 // byte[] input -> mock-input 446 // byte[] iv -> mock-iv 447 mByteArrayProperties.add(String8("mock-keyid"), keyId); 448 mByteArrayProperties.add(String8("mock-input"), input); 449 mByteArrayProperties.add(String8("mock-iv"), iv); 450 451 // Properties used in mock test, set by cts test app returned from mock plugin 452 // byte[] mock-output -> output 453 index = mByteArrayProperties.indexOfKey(String8("mock-output")); 454 if (index < 0) { 455 ALOGD("Missing 'mock-request' parameter for mock"); 456 return BAD_VALUE; 457 } else { 458 output = mByteArrayProperties.valueAt(index); 459 } 460 return OK; 461 } 462 463 status_t MockDrmPlugin::decrypt(Vector<uint8_t> const &sessionId, 464 Vector<uint8_t> const &keyId, 465 Vector<uint8_t> const &input, 466 Vector<uint8_t> const &iv, 467 Vector<uint8_t> &output) 468 { 469 Mutex::Autolock lock(mLock); 470 ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)", 471 vectorToString(sessionId).string(), 472 vectorToString(keyId).string(), 473 vectorToString(input).string(), 474 vectorToString(iv).string()); 475 476 ssize_t index = findSession(sessionId); 477 if (index == kNotFound) { 478 ALOGD("Invalid sessionId"); 479 return BAD_VALUE; 480 } 481 482 // Properties used in mock test, set by mock plugin and verifed cts test app 483 // byte[] keyId -> mock-keyid 484 // byte[] input -> mock-input 485 // byte[] iv -> mock-iv 486 mByteArrayProperties.add(String8("mock-keyid"), keyId); 487 mByteArrayProperties.add(String8("mock-input"), input); 488 mByteArrayProperties.add(String8("mock-iv"), iv); 489 490 // Properties used in mock test, set by cts test app returned from mock plugin 491 // byte[] mock-output -> output 492 index = mByteArrayProperties.indexOfKey(String8("mock-output")); 493 if (index < 0) { 494 ALOGD("Missing 'mock-request' parameter for mock"); 495 return BAD_VALUE; 496 } else { 497 output = mByteArrayProperties.valueAt(index); 498 } 499 return OK; 500 } 501 502 status_t MockDrmPlugin::sign(Vector<uint8_t> const &sessionId, 503 Vector<uint8_t> const &keyId, 504 Vector<uint8_t> const &message, 505 Vector<uint8_t> &signature) 506 { 507 Mutex::Autolock lock(mLock); 508 ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)", 509 vectorToString(sessionId).string(), 510 vectorToString(keyId).string(), 511 vectorToString(message).string()); 512 513 ssize_t index = findSession(sessionId); 514 if (index == kNotFound) { 515 ALOGD("Invalid sessionId"); 516 return BAD_VALUE; 517 } 518 519 // Properties used in mock test, set by mock plugin and verifed cts test app 520 // byte[] keyId -> mock-keyid 521 // byte[] message -> mock-message 522 mByteArrayProperties.add(String8("mock-keyid"), keyId); 523 mByteArrayProperties.add(String8("mock-message"), message); 524 525 // Properties used in mock test, set by cts test app returned from mock plugin 526 // byte[] mock-signature -> signature 527 index = mByteArrayProperties.indexOfKey(String8("mock-signature")); 528 if (index < 0) { 529 ALOGD("Missing 'mock-request' parameter for mock"); 530 return BAD_VALUE; 531 } else { 532 signature = mByteArrayProperties.valueAt(index); 533 } 534 return OK; 535 } 536 537 status_t MockDrmPlugin::verify(Vector<uint8_t> const &sessionId, 538 Vector<uint8_t> const &keyId, 539 Vector<uint8_t> const &message, 540 Vector<uint8_t> const &signature, 541 bool &match) 542 { 543 Mutex::Autolock lock(mLock); 544 ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)", 545 vectorToString(sessionId).string(), 546 vectorToString(keyId).string(), 547 vectorToString(message).string(), 548 vectorToString(signature).string()); 549 550 ssize_t index = findSession(sessionId); 551 if (index == kNotFound) { 552 ALOGD("Invalid sessionId"); 553 return BAD_VALUE; 554 } 555 556 // Properties used in mock test, set by mock plugin and verifed cts test app 557 // byte[] keyId -> mock-keyid 558 // byte[] message -> mock-message 559 // byte[] signature -> mock-signature 560 mByteArrayProperties.add(String8("mock-keyid"), keyId); 561 mByteArrayProperties.add(String8("mock-message"), message); 562 mByteArrayProperties.add(String8("mock-signature"), signature); 563 564 // Properties used in mock test, set by cts test app returned from mock plugin 565 // String mock-match "1" or "0" -> match 566 index = mStringProperties.indexOfKey(String8("mock-match")); 567 if (index < 0) { 568 ALOGD("Missing 'mock-request' parameter for mock"); 569 return BAD_VALUE; 570 } else { 571 match = atol(mStringProperties.valueAt(index).string()); 572 } 573 return OK; 574 } 575 576 ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const 577 { 578 ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size()); 579 for (size_t i = 0; i < mSessions.size(); ++i) { 580 if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) { 581 return i; 582 } 583 } 584 return kNotFound; 585 } 586 587 ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const 588 { 589 ALOGD("findKeySet: nkeySets=%d, size=%d", mKeySets.size(), keySetId.size()); 590 for (size_t i = 0; i < mKeySets.size(); ++i) { 591 if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) { 592 return i; 593 } 594 } 595 return kNotFound; 596 } 597 598 599 // Conversion utilities 600 String8 MockDrmPlugin::vectorToString(Vector<uint8_t> const &vector) const 601 { 602 return arrayToString(vector.array(), vector.size()); 603 } 604 605 String8 MockDrmPlugin::arrayToString(uint8_t const *array, size_t len) const 606 { 607 String8 result("{ "); 608 for (size_t i = 0; i < len; i++) { 609 result.appendFormat("0x%02x ", array[i]); 610 } 611 result += "}"; 612 return result; 613 } 614 615 String8 MockDrmPlugin::stringMapToString(KeyedVector<String8, String8> map) const 616 { 617 String8 result("{ "); 618 for (size_t i = 0; i < map.size(); i++) { 619 result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "", 620 map.keyAt(i).string(), map.valueAt(i).string()); 621 } 622 return result + " }"; 623 } 624 625 bool operator<(Vector<uint8_t> const &lhs, Vector<uint8_t> const &rhs) { 626 return lhs.size() < rhs.size() || (memcmp(lhs.array(), rhs.array(), lhs.size()) < 0); 627 } 628 629 // 630 // Crypto Plugin 631 // 632 633 bool MockCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const 634 { 635 ALOGD("MockCryptoPlugin::requiresSecureDecoderComponent(mime=%s)", mime); 636 return false; 637 } 638 639 ssize_t 640 MockCryptoPlugin::decrypt(bool secure, const uint8_t key[16], const uint8_t iv[16], 641 Mode mode, const void *srcPtr, const SubSample *subSamples, 642 size_t numSubSamples, void *dstPtr, AString *errorDetailMsg) 643 { 644 ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, src=%p, " 645 "subSamples=%s, dst=%p)", 646 (int)secure, 647 arrayToString(key, sizeof(key)).string(), 648 arrayToString(iv, sizeof(iv)).string(), 649 (int)mode, srcPtr, 650 subSamplesToString(subSamples, numSubSamples).string(), 651 dstPtr); 652 return OK; 653 } 654 655 // Conversion utilities 656 String8 MockCryptoPlugin::arrayToString(uint8_t const *array, size_t len) const 657 { 658 String8 result("{ "); 659 for (size_t i = 0; i < len; i++) { 660 result.appendFormat("0x%02x ", array[i]); 661 } 662 result += "}"; 663 return result; 664 } 665 666 String8 MockCryptoPlugin::subSamplesToString(SubSample const *subSamples, 667 size_t numSubSamples) const 668 { 669 String8 result; 670 for (size_t i = 0; i < numSubSamples; i++) { 671 result.appendFormat("[%d] {clear:%d, encrypted:%d} ", i, 672 subSamples[i].mNumBytesOfClearData, 673 subSamples[i].mNumBytesOfEncryptedData); 674 } 675 return result; 676 } 677 678}; 679