Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 022b9953 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

Re-implement HIDL effect processing using FMQ and IMemory

Result: no hwbinder calls due music processing.

Test: make, use Play Music with effects, check traces
Bug: 30222631
Change-Id: I06d0e94e603688874b31824427f3b0878b5f7c8e
parent e61f9e57
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HARDWARE_EFFECT_BUFFER_HAL_INTERFACE_H
#define ANDROID_HARDWARE_EFFECT_BUFFER_HAL_INTERFACE_H

#include <system/audio_effect.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>

namespace android {

// Abstraction for an audio buffer. It may be a "mirror" for
// a buffer that the effect chain doesn't own, or a buffer owned by
// the effect chain.
class EffectBufferHalInterface : public RefBase
{
  public:
    virtual audio_buffer_t* audioBuffer() = 0;
    virtual void* externalData() const = 0;
    // To be used when interacting with the code that doesn't know about
    // "mirrored" buffers.
    virtual void* ptr() {
        return externalData() != nullptr ? externalData() : audioBuffer()->raw;
    }

    virtual void setExternalData(void* external) = 0;
    virtual void setFrameCount(size_t frameCount) = 0;

    virtual void update() = 0;  // copies data from the external buffer, noop for allocated buffers
    virtual void commit() = 0;  // copies data to the external buffer, noop for allocated buffers

    static status_t allocate(size_t size, sp<EffectBufferHalInterface>* buffer);
    static status_t mirror(void* external, size_t size, sp<EffectBufferHalInterface>* buffer);

  protected:
    // Subclasses can not be constructed directly by clients.
    EffectBufferHalInterface() {}

    virtual ~EffectBufferHalInterface() {}
};

} // namespace android

#endif // ANDROID_HARDWARE_EFFECT_BUFFER_HAL_INTERFACE_H
+12 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H
#define ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H

#include <media/audiohal/EffectBufferHalInterface.h>
#include <system/audio_effect.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -26,14 +27,20 @@ namespace android {
class EffectHalInterface : public RefBase
{
  public:
    // Set the input buffer.
    virtual status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;

    // Set the output buffer.
    virtual status_t setOutBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;

    // Effect process function. Takes input samples as specified
    // in input buffer descriptor and output processed samples as specified
    // in output buffer descriptor.
    virtual status_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) = 0;
    virtual status_t process() = 0;

    // Process reverse stream function. This function is used to pass
    // a reference stream to the effect engine.
    virtual status_t processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) = 0;
    virtual status_t processReverse() = 0;

    // Send a command and receive a response to/from effect engine.
    virtual status_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
@@ -42,6 +49,9 @@ class EffectHalInterface : public RefBase
    // Returns the effect descriptor.
    virtual status_t getDescriptor(effect_descriptor_t *pDescriptor) = 0;

    // Free resources on the remote side.
    virtual status_t close() = 0;

  protected:
    // Subclasses can not be constructed directly by clients.
    EffectHalInterface() {}
+10 −7
Original line number Diff line number Diff line
@@ -3,10 +3,8 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SHARED_LIBRARIES := \
    libbase \
    libcutils   \
    libeffects  \
    libfmq \
    libhardware \
    liblog      \
    libutils
@@ -19,19 +17,23 @@ LOCAL_SRC_FILES := \
    ConversionHelperHidl.cpp   \
    DeviceHalHidl.cpp          \
    DevicesFactoryHalHidl.cpp  \
    EffectBufferHalHidl.cpp    \
    EffectHalHidl.cpp          \
    EffectsFactoryHalHidl.cpp  \
    StreamHalHidl.cpp

LOCAL_SHARED_LIBRARIES += \
    libbase          \
    libfmq           \
    libhwbinder      \
    libhidlbase      \
    libhidlmemory    \
    libhidltransport \
    libbase          \
    android.hardware.audio@2.0             \
    android.hardware.audio.common@2.0      \
    android.hardware.audio.common@2.0-util \
    android.hardware.audio.effect@2.0      \
    android.hidl.memory@1.0                \
    libmedia_helper

else  # if !ENABLE_TREBLE
@@ -39,6 +41,7 @@ else # if !ENABLE_TREBLE
LOCAL_SRC_FILES := \
    DeviceHalLocal.cpp          \
    DevicesFactoryHalLocal.cpp  \
    EffectBufferHalLocal.cpp    \
    EffectHalLocal.cpp          \
    EffectsFactoryHalLocal.cpp  \
    StreamHalLocal.cpp
+0 −2
Original line number Diff line number Diff line
@@ -65,8 +65,6 @@ class ConversionHelperHidl {
        const status_t st = ret.isOk() ? analyzeResult(retval) : UNKNOWN_ERROR;
        if (!ret.isOk()) {
            emitError(funcName, ret.description().c_str());
        } else if (st) {
            emitError(funcName, strerror(st));
        }
        return st;
    }
+127 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <atomic>

#define LOG_TAG "EffectBufferHalHidl"
//#define LOG_NDEBUG 0

#include <android/hidl/memory/1.0/IAllocator.h>
#include <hidlmemory/mapping.h>
#include <utils/Log.h>

#include "ConversionHelperHidl.h"
#include "EffectBufferHalHidl.h"

using ::android::hardware::Return;
using ::android::hardware::Status;
using ::android::hidl::memory::V1_0::IAllocator;

namespace android {

// static
uint64_t EffectBufferHalHidl::makeUniqueId() {
    static std::atomic<uint64_t> counter{1};
    return counter++;
}

// static
status_t EffectBufferHalInterface::allocate(
        size_t size, sp<EffectBufferHalInterface>* buffer) {
    return mirror(nullptr, size, buffer);
}

// static
status_t EffectBufferHalInterface::mirror(
        void* external, size_t size, sp<EffectBufferHalInterface>* buffer) {
    sp<EffectBufferHalInterface> tempBuffer = new EffectBufferHalHidl(size);
    status_t result = reinterpret_cast<EffectBufferHalHidl*>(tempBuffer.get())->init();
    if (result == OK) {
        tempBuffer->setExternalData(external);
        *buffer = tempBuffer;
    }
    return result;
}

EffectBufferHalHidl::EffectBufferHalHidl(size_t size)
        : mBufferSize(size), mExternalData(nullptr), mAudioBuffer{0, {nullptr}} {
    mHidlBuffer.id = makeUniqueId();
    mHidlBuffer.frameCount = 0;
}

EffectBufferHalHidl::~EffectBufferHalHidl() {
}

status_t EffectBufferHalHidl::init() {
    sp<IAllocator> ashmem = IAllocator::getService("ashmem");
    if (ashmem == 0) {
        ALOGE("Failed to retrieve ashmem allocator service");
        return NO_INIT;
    }
    status_t retval = NO_MEMORY;
    Return<void> result = ashmem->allocate(
            mBufferSize,
            [&](bool success, const hidl_memory& memory) {
                if (success) {
                    mHidlBuffer.data = memory;
                    retval = OK;
                }
            });
    if (retval == OK) {
        mMemory = hardware::mapMemory(mHidlBuffer.data);
        if (mMemory != 0) {
            mMemory->update();
            mAudioBuffer.raw = static_cast<void*>(mMemory->getPointer());
            memset(mAudioBuffer.raw, 0, mMemory->getSize());
            mMemory->commit();
        } else {
            ALOGE("Failed to map allocated ashmem");
            retval = NO_MEMORY;
        }
    }
    return retval;
}

audio_buffer_t* EffectBufferHalHidl::audioBuffer() {
    return &mAudioBuffer;
}

void* EffectBufferHalHidl::externalData() const {
    return mExternalData;
}

void EffectBufferHalHidl::setFrameCount(size_t frameCount) {
    mHidlBuffer.frameCount = frameCount;
    mAudioBuffer.frameCount = frameCount;
}

void EffectBufferHalHidl::setExternalData(void* external) {
    mExternalData = external;
}

void EffectBufferHalHidl::update() {
    if (mExternalData == nullptr) return;
    mMemory->update();
    memcpy(mAudioBuffer.raw, mExternalData, mBufferSize);
    mMemory->commit();
}

void EffectBufferHalHidl::commit() {
    if (mExternalData == nullptr) return;
    memcpy(mExternalData, mAudioBuffer.raw, mBufferSize);
}

} // namespace android
Loading