Return<void> antDataReceived(const hidl_vec<uint8_t>& event)
   {
      ALOGV("%s:start  ", __func__);
      // Make sure we don't overwrite a message still processing.
      Lock lk(ant_hci.rx_mtx);
      if(ant_hci.rx_processing && ant_hci.state == ANT_RADIO_ENABLED)
      {
         ant_hci.rx_cond.wait(lk);
      }

      memcpy(&aucRxBuffer[0][0], event.data(), event.size());
      iRxBufferLength[0] = event.size();
      std::unique_lock< std::mutex> lock(ant_hci.data_mtx);
      ALOGD("%s:  notify data avail", __func__);
      ant_hci.rx_processing = true;
      ant_hci.data_cond.notify_all();
      ALOGV("%s: exit", __func__);
      return Void();
   }
Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
                                      const hidl_vec<AudioPortConfig>& sinks,
                                      createAudioPatch_cb _hidl_cb) {
    Result retval(Result::NOT_SUPPORTED);
    AudioPatchHandle patch = 0;
    if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
        std::unique_ptr<audio_port_config[]> halSources(
            HidlUtils::audioPortConfigsToHal(sources));
        std::unique_ptr<audio_port_config[]> halSinks(
            HidlUtils::audioPortConfigsToHal(sinks));
        audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
        retval = analyzeStatus(
            "create_audio_patch",
            mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
                                        sinks.size(), &halSinks[0], &halPatch));
        if (retval == Result::OK) {
            patch = static_cast<AudioPatchHandle>(halPatch);
        }
    }
    _hidl_cb(retval, patch);
    return Void();
}
/**
 * Decrypt a list of clear+encrypted subsamples using the specified key
 * in AES-CBC mode
 */
void DrmHalClearkeyDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
        const vector<uint8_t>& key) {
    AES_KEY decryptionKey;
    AES_set_encrypt_key(&key[0], 128, &decryptionKey);

    size_t offset = 0;
    for (size_t i = 0; i < subSamples.size(); i++) {
        memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData);
        offset += subSamples[i].numBytesOfClearData;

        AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData,
                &decryptionKey, iv, 0 /* decrypt */);
        offset += subSamples[i].numBytesOfEncryptedData;
    }
}
uint32_t DrmHalClearkeyDecryptTest::decrypt(Mode mode,
        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
        const Pattern& pattern, Status expectedStatus) {
    const size_t kSegmentIndex = 0;
    const vector<uint8_t> keyId = {0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47,
                                   0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d,
                                   0x1e, 0xd0, 0x0d, 0x1e};
    const vector<uint8_t> contentKey = {0x1a, 0x8a, 0x20, 0x95, 0xe4,
                                        0xde, 0xb2, 0xd2, 0x9e, 0xc8,
                                        0x16, 0xac, 0x7b, 0xae, 0x20, 0x82};
    uint8_t localIv[AES_BLOCK_SIZE];
    memcpy(localIv, iv, AES_BLOCK_SIZE);

    size_t totalSize = 0;
    for (size_t i = 0; i < subSamples.size(); i++) {
        totalSize += subSamples[i].numBytesOfClearData;
        totalSize += subSamples[i].numBytesOfEncryptedData;
    }

    // The first totalSize bytes of shared memory is the encrypted
    // input, the second totalSize bytes is the decrypted output.
    sp<IMemory> sharedMemory =
            getDecryptMemory(totalSize * 2, kSegmentIndex);

    const SharedBuffer sourceBuffer = {
        .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
    fillRandom(sharedMemory);

    const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
                                          {.bufferId = kSegmentIndex,
                                           .offset = totalSize,
                                           .size = totalSize},
                                          .secureMemory = nullptr};
    const uint64_t offset = 0;
    const bool kNotSecure = false;
    uint32_t bytesWritten = 0;
    auto res = cryptoPlugin->decrypt(kNotSecure, toHidlArray(keyId), localIv, mode,
            pattern, subSamples, sourceBuffer, offset, destBuffer,
            [&](Status status, uint32_t count, string detailedError) {
                EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
                detailedError;
                bytesWritten = count;
            });
    EXPECT_OK(res);

    if (bytesWritten != totalSize) {
        return bytesWritten;
    }
    uint8_t* base = static_cast<uint8_t*>(
            static_cast<void*>(sharedMemory->getPointer()));

    // generate reference vector
    vector<uint8_t> reference(totalSize);

    memcpy(localIv, iv, AES_BLOCK_SIZE);
    switch (mode) {
    case Mode::UNENCRYPTED:
        memcpy(&reference[0], base, totalSize);
        break;
    case Mode::AES_CTR:
        aes_ctr_decrypt(&reference[0], base, localIv, subSamples, contentKey);
        break;
    case Mode::AES_CBC:
        aes_cbc_decrypt(&reference[0], base, localIv, subSamples, contentKey);
        break;
    case Mode::AES_CBC_CTS:
        EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
        break;
    }

    // compare reference to decrypted data which is at base + total size
    EXPECT_EQ(0, memcmp(static_cast<void *>(&reference[0]),
                        static_cast<void*>(base + totalSize), totalSize))
            << "decrypt data mismatch";
    return totalSize;
}

/**
 * Decrypt a list of clear+encrypted subsamples using the specified key
 * in AES-CTR mode
 */
void DrmHalClearkeyDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
        const vector<uint8_t>& key) {
    AES_KEY decryptionKey;
    AES_set_encrypt_key(&key[0], 128, &decryptionKey);

    size_t offset = 0;
    unsigned int blockOffset = 0;
    uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
    memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);

    for (size_t i = 0; i < subSamples.size(); i++) {
        const SubSample& subSample = subSamples[i];

        if (subSample.numBytesOfClearData > 0) {
            memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
            offset += subSample.numBytesOfClearData;
        }

        if (subSample.numBytesOfEncryptedData > 0) {
            AES_ctr128_encrypt(src + offset, dest + offset,
                    subSample.numBytesOfEncryptedData, &decryptionKey,
                    iv, previousEncryptedCounter, &blockOffset);
            offset += subSample.numBytesOfEncryptedData;
        }
    }
}
::android::hardware::Return<uint32_t> Nfc::write(const hidl_vec<uint8_t>& data)  {
    if (mDevice == nullptr) {
        return -1;
    }
    return mDevice->write(mDevice, data.size(), &data[0]);
}
inline void copyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
    for (size_t i = 0; i < std::min(dest->size(), src.size()); i++) {
        (*dest)[i] = src[i];
    }
}
void shallowCopyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
    if (src.size() > 0) {
        dest->setToExternal(const_cast<T*>(&src[0]), src.size());
    } else if (dest->size() > 0) {
        dest->resize(0);
    }
}