Home | History | Annotate | Download | only in impl
      1 /*
      2  * Copyright (C) 2017 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 #include <atomic>
     18 
     19 #define LOG_TAG "EffectBufferHalHidl"
     20 //#define LOG_NDEBUG 0
     21 
     22 #include <android/hidl/allocator/1.0/IAllocator.h>
     23 #include <hidlmemory/mapping.h>
     24 #include <utils/Log.h>
     25 
     26 #include "ConversionHelperHidl.h"
     27 #include "EffectBufferHalHidl.h"
     28 
     29 using ::android::hardware::Return;
     30 using ::android::hidl::allocator::V1_0::IAllocator;
     31 
     32 namespace android {
     33 namespace effect {
     34 namespace CPP_VERSION {
     35 
     36 // static
     37 uint64_t EffectBufferHalHidl::makeUniqueId() {
     38     static std::atomic<uint64_t> counter{1};
     39     return counter++;
     40 }
     41 
     42 status_t EffectBufferHalHidl::allocate(
     43         size_t size, sp<EffectBufferHalInterface>* buffer) {
     44     return mirror(nullptr, size, buffer);
     45 }
     46 
     47 status_t EffectBufferHalHidl::mirror(
     48         void* external, size_t size, sp<EffectBufferHalInterface>* buffer) {
     49     sp<EffectBufferHalInterface> tempBuffer = new EffectBufferHalHidl(size);
     50     status_t result = static_cast<EffectBufferHalHidl*>(tempBuffer.get())->init();
     51     if (result == OK) {
     52         tempBuffer->setExternalData(external);
     53         *buffer = tempBuffer;
     54     }
     55     return result;
     56 }
     57 
     58 EffectBufferHalHidl::EffectBufferHalHidl(size_t size)
     59         : mBufferSize(size), mFrameCountChanged(false),
     60           mExternalData(nullptr), mAudioBuffer{0, {nullptr}} {
     61     mHidlBuffer.id = makeUniqueId();
     62     mHidlBuffer.frameCount = 0;
     63 }
     64 
     65 EffectBufferHalHidl::~EffectBufferHalHidl() {
     66 }
     67 
     68 status_t EffectBufferHalHidl::init() {
     69     sp<IAllocator> ashmem = IAllocator::getService("ashmem");
     70     if (ashmem == 0) {
     71         ALOGE("Failed to retrieve ashmem allocator service");
     72         return NO_INIT;
     73     }
     74     status_t retval = NO_MEMORY;
     75     Return<void> result = ashmem->allocate(
     76             mBufferSize,
     77             [&](bool success, const hidl_memory& memory) {
     78                 if (success) {
     79                     mHidlBuffer.data = memory;
     80                     retval = OK;
     81                 }
     82             });
     83     if (result.isOk() && retval == OK) {
     84         mMemory = hardware::mapMemory(mHidlBuffer.data);
     85         if (mMemory != 0) {
     86             mMemory->update();
     87             mAudioBuffer.raw = static_cast<void*>(mMemory->getPointer());
     88             memset(mAudioBuffer.raw, 0, mMemory->getSize());
     89             mMemory->commit();
     90         } else {
     91             ALOGE("Failed to map allocated ashmem");
     92             retval = NO_MEMORY;
     93         }
     94     } else {
     95         ALOGE("Failed to allocate %d bytes from ashmem", (int)mBufferSize);
     96     }
     97     return result.isOk() ? retval : FAILED_TRANSACTION;
     98 }
     99 
    100 audio_buffer_t* EffectBufferHalHidl::audioBuffer() {
    101     return &mAudioBuffer;
    102 }
    103 
    104 void* EffectBufferHalHidl::externalData() const {
    105     return mExternalData;
    106 }
    107 
    108 void EffectBufferHalHidl::setFrameCount(size_t frameCount) {
    109     mHidlBuffer.frameCount = frameCount;
    110     mAudioBuffer.frameCount = frameCount;
    111     mFrameCountChanged = true;
    112 }
    113 
    114 bool EffectBufferHalHidl::checkFrameCountChange() {
    115     bool result = mFrameCountChanged;
    116     mFrameCountChanged = false;
    117     return result;
    118 }
    119 
    120 void EffectBufferHalHidl::setExternalData(void* external) {
    121     mExternalData = external;
    122 }
    123 
    124 void EffectBufferHalHidl::update() {
    125     update(mBufferSize);
    126 }
    127 
    128 void EffectBufferHalHidl::commit() {
    129     commit(mBufferSize);
    130 }
    131 
    132 void EffectBufferHalHidl::update(size_t size) {
    133     if (mExternalData == nullptr) return;
    134     mMemory->update();
    135     if (size > mBufferSize) size = mBufferSize;
    136     memcpy(mAudioBuffer.raw, mExternalData, size);
    137     mMemory->commit();
    138 }
    139 
    140 void EffectBufferHalHidl::commit(size_t size) {
    141     if (mExternalData == nullptr) return;
    142     if (size > mBufferSize) size = mBufferSize;
    143     memcpy(mExternalData, mAudioBuffer.raw, size);
    144 }
    145 
    146 } // namespace effect
    147 } // namespace CPP_VERSION
    148 } // namespace android
    149