14bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard/*
24bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * Copyright (C) 2017 The Android Open Source Project
34bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard *
44bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * Licensed under the Apache License, Version 2.0 (the "License");
54bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * you may not use this file except in compliance with the License.
64bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * You may obtain a copy of the License at
74bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard *
84bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard *      http://www.apache.org/licenses/LICENSE-2.0
94bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard *
104bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * Unless required by applicable law or agreed to in writing, software
114bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * distributed under the License is distributed on an "AS IS" BASIS,
124bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * See the License for the specific language governing permissions and
144bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard * limitations under the License.
154bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard */
164bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
174bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard#include <atomic>
184bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
194bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard#define LOG_TAG "EffectBufferHalHidl"
204bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard//#define LOG_NDEBUG 0
214bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
224bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard#include <android/hidl/allocator/1.0/IAllocator.h>
234bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard#include <hidlmemory/mapping.h>
244bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard#include <utils/Log.h>
254bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
264bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard#include "ConversionHelperHidl.h"
274bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard#include "EffectBufferHalHidl.h"
284bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
294bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardusing ::android::hardware::Return;
304bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardusing ::android::hidl::allocator::V1_0::IAllocator;
314bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
324bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardnamespace android {
3351e076a8fc69d4275cabc3e6d54eab44d590280dKevin Rocardnamespace V4_0 {
344bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
354bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard// static
364bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocarduint64_t EffectBufferHalHidl::makeUniqueId() {
374bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    static std::atomic<uint64_t> counter{1};
384bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    return counter++;
394bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
404bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
414bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardstatus_t EffectBufferHalHidl::allocate(
424bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        size_t size, sp<EffectBufferHalInterface>* buffer) {
434bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    return mirror(nullptr, size, buffer);
444bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
454bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
464bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardstatus_t EffectBufferHalHidl::mirror(
474bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        void* external, size_t size, sp<EffectBufferHalInterface>* buffer) {
484bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    sp<EffectBufferHalInterface> tempBuffer = new EffectBufferHalHidl(size);
494bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    status_t result = static_cast<EffectBufferHalHidl*>(tempBuffer.get())->init();
504bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    if (result == OK) {
514bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        tempBuffer->setExternalData(external);
524bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        *buffer = tempBuffer;
534bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    }
544bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    return result;
554bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
564bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
574bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin RocardEffectBufferHalHidl::EffectBufferHalHidl(size_t size)
584bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        : mBufferSize(size), mFrameCountChanged(false),
594bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard          mExternalData(nullptr), mAudioBuffer{0, {nullptr}} {
604bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mHidlBuffer.id = makeUniqueId();
614bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mHidlBuffer.frameCount = 0;
624bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
634bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
644bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin RocardEffectBufferHalHidl::~EffectBufferHalHidl() {
654bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
664bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
674bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardstatus_t EffectBufferHalHidl::init() {
684bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    sp<IAllocator> ashmem = IAllocator::getService("ashmem");
694bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    if (ashmem == 0) {
704bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        ALOGE("Failed to retrieve ashmem allocator service");
714bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        return NO_INIT;
724bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    }
734bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    status_t retval = NO_MEMORY;
744bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    Return<void> result = ashmem->allocate(
754bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            mBufferSize,
764bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            [&](bool success, const hidl_memory& memory) {
774bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard                if (success) {
784bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard                    mHidlBuffer.data = memory;
794bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard                    retval = OK;
804bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard                }
814bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            });
824bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    if (result.isOk() && retval == OK) {
834bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        mMemory = hardware::mapMemory(mHidlBuffer.data);
844bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        if (mMemory != 0) {
854bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            mMemory->update();
864bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            mAudioBuffer.raw = static_cast<void*>(mMemory->getPointer());
874bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            memset(mAudioBuffer.raw, 0, mMemory->getSize());
884bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            mMemory->commit();
894bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        } else {
904bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            ALOGE("Failed to map allocated ashmem");
914bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard            retval = NO_MEMORY;
924bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        }
934bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    } else {
944bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard        ALOGE("Failed to allocate %d bytes from ashmem", (int)mBufferSize);
954bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    }
964bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    return result.isOk() ? retval : FAILED_TRANSACTION;
974bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
984bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
994bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardaudio_buffer_t* EffectBufferHalHidl::audioBuffer() {
1004bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    return &mAudioBuffer;
1014bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1024bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
1034bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardvoid* EffectBufferHalHidl::externalData() const {
1044bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    return mExternalData;
1054bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1064bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
1074bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardvoid EffectBufferHalHidl::setFrameCount(size_t frameCount) {
1084bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mHidlBuffer.frameCount = frameCount;
1094bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mAudioBuffer.frameCount = frameCount;
1104bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mFrameCountChanged = true;
1114bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1124bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
1134bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardbool EffectBufferHalHidl::checkFrameCountChange() {
1144bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    bool result = mFrameCountChanged;
1154bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mFrameCountChanged = false;
1164bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    return result;
1174bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1184bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
1194bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardvoid EffectBufferHalHidl::setExternalData(void* external) {
1204bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mExternalData = external;
1214bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1224bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
1234bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardvoid EffectBufferHalHidl::update() {
1244bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    update(mBufferSize);
1254bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1264bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
1274bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardvoid EffectBufferHalHidl::commit() {
1284bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    commit(mBufferSize);
1294bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1304bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
1314bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardvoid EffectBufferHalHidl::update(size_t size) {
1324bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    if (mExternalData == nullptr) return;
1334bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mMemory->update();
1344bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    if (size > mBufferSize) size = mBufferSize;
1354bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    memcpy(mAudioBuffer.raw, mExternalData, size);
1364bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    mMemory->commit();
1374bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1384bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
1394bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocardvoid EffectBufferHalHidl::commit(size_t size) {
1404bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    if (mExternalData == nullptr) return;
1414bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    if (size > mBufferSize) size = mBufferSize;
1424bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard    memcpy(mExternalData, mAudioBuffer.raw, size);
1434bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard}
1444bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard
14551e076a8fc69d4275cabc3e6d54eab44d590280dKevin Rocard} // namespace V4_0
1464bcd67fbb4eca3654ea929742bdf6ccc7c70daecKevin Rocard} // namespace android
147