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

Commit 2bf55fb6 authored by Oscar Azucena's avatar Oscar Azucena
Browse files

Add default implementation to load current XML

Added support to the default configuration to load the current car audio
configuration file. This will load the all the required info for the
configuration.

Bug: 359686069
Test: m -j, presubmit
Flag: EXEMPT HAL interface
Change-Id: Ibe520b468ab145518f56dd26f0cceda970c6f226
parent 2744dea3
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -31,13 +31,19 @@ cc_binary {
        "latest_android_hardware_audio_common_ndk_shared",
        "latest_android_hardware_automotive_audiocontrol_ndk_shared",
        "powerpolicyclient_defaults",
        "car.audio.configuration.xsd.default",
        "car.fade.configuration.xsd.default",
    ],
    shared_libs: [
        "android.hardware.audio.common@7.0-enums",
        "libbase",
        "libbinder_ndk",
        "libcutils",
        "liblog",
        "libbase",
        "libxml2",
        "libutils",
        "android.hardware.audiocontrol.internal",
        "libaudio_aidl_conversion_common_ndk",
    ],
    srcs: [
        "AudioControl.cpp",
+114 −14
Original line number Diff line number Diff line
@@ -28,8 +28,8 @@
#include <android-base/parsebool.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>

#include <android_audio_policy_configuration_V7_0-enums.h>

#include <private/android_filesystem_config.h>

#include <numeric>
@@ -42,16 +42,18 @@ using ::android::base::EqualsIgnoreCase;
using ::android::base::ParseBool;
using ::android::base::ParseBoolResult;
using ::android::base::ParseInt;
using ::android::hardware::audiocontrol::internal::CarAudioConfigurationXmlConverter;
using ::std::shared_ptr;
using ::std::string;

namespace xsd {
using namespace ::android::audio::policy::configuration::V7_0;
namespace converter {
using namespace ::android::hardware::audiocontrol::internal;
}

namespace api = aidl::android::hardware::automotive::audiocontrol;
namespace xsd = ::android::audio::policy::configuration::V7_0;

namespace {
const float kLowerBound = -1.0f;
const float kUpperBound = 1.0f;
bool checkCallerHasWritePermissions(int fd) {
    // Double check that's only called by root - it should be be blocked at debug() level,
    // but it doesn't hurt to make sure...
@@ -63,7 +65,7 @@ bool checkCallerHasWritePermissions(int fd) {
}

bool isValidValue(float value) {
    return (value >= kLowerBound) && (value <= kUpperBound);
    return (value >= -1.0f) && (value <= 1.0f);
}

bool safelyParseInt(string s, int* out) {
@@ -72,6 +74,53 @@ bool safelyParseInt(string s, int* out) {
    }
    return true;
}

std::string formatDump(const std::string& input) {
    const char kSpacer = ' ';
    std::string output;
    int indentLevel = 0;
    bool newLine = false;

    for (char c : input) {
        switch (c) {
            case '{':
                if (!newLine) {
                    output += '\n';
                }
                newLine = true;
                indentLevel++;
                for (int i = 0; i < indentLevel; ++i) {
                    output += kSpacer;
                }
                break;
            case '}':
                if (!newLine) {
                    output += '\n';
                }
                newLine = true;
                indentLevel--;
                for (int i = 0; i < indentLevel; ++i) {
                    output += kSpacer;
                }
                break;
            case ',':
                if (!newLine) {
                    output += '\n';
                }
                newLine = true;
                for (int i = 0; i < indentLevel; ++i) {
                    output += kSpacer;
                }
                break;
            default:
                newLine = false;
                output += c;
        }
    }

    return output;
}

}  // namespace

namespace {
@@ -91,6 +140,9 @@ using ::aidl::android::media::audio::common::AudioPortMixExt;
using ::aidl::android::media::audio::common::AudioProfile;
using ::aidl::android::media::audio::common::PcmType;

const static std::string kAudioConfigFile = "/vendor/etc/car_audio_configuration.xml";
const static std::string kFadeConfigFile = "/vendor/etc/car_audio_fade_configuration.xml";

// reuse common code artifacts
void fillProfile(const std::vector<int32_t>& channelLayouts,
                 const std::vector<int32_t>& sampleRates, AudioProfile* profile) {
@@ -163,6 +215,12 @@ AudioGain createGain(int32_t mode, AudioChannelLayout channelMask, int32_t minVa
}
}  // namespace

AudioControl::AudioControl() : AudioControl(kAudioConfigFile, kFadeConfigFile) {}

AudioControl::AudioControl(const std::string& carAudioConfig, const std::string& audioFadeConfig)
    : mCarAudioConfigurationConverter(std::make_shared<CarAudioConfigurationXmlConverter>(
              carAudioConfig, audioFadeConfig)) {}

ndk::ScopedAStatus AudioControl::registerFocusListener(
        const shared_ptr<IFocusListener>& in_listener) {
    LOG(DEBUG) << "registering focus listener";
@@ -321,22 +379,45 @@ ndk::ScopedAStatus AudioControl::clearModuleChangeCallback() {

ndk::ScopedAStatus AudioControl::getAudioDeviceConfiguration(
        AudioDeviceConfiguration* audioDeviceConfig) {
    LOG(DEBUG) << ":" << __func__ << "audioDeviceConfig" << audioDeviceConfig->toString();
    if (!audioDeviceConfig) {
        LOG(ERROR) << __func__ << "Audio device configuration must not be null";
        return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL);
    }
    if (!mCarAudioConfigurationConverter) {
        return ndk::ScopedAStatus::ok();
    }
    const auto& innerDeviceConfig = mCarAudioConfigurationConverter->getAudioDeviceConfiguration();
    audioDeviceConfig->routingConfig = innerDeviceConfig.routingConfig;
    audioDeviceConfig->useCoreAudioVolume = innerDeviceConfig.useCoreAudioVolume;
    audioDeviceConfig->useCarVolumeGroupMuting = innerDeviceConfig.useCarVolumeGroupMuting;
    audioDeviceConfig->useHalDuckingSignals = innerDeviceConfig.useHalDuckingSignals;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus AudioControl::getOutputMirroringDevices(
        std::vector<AudioPort>* mirroringDevices) {
    for (const auto& mirroringDevice : *mirroringDevices) {
        LOG(DEBUG) << ":" << __func__ << "Mirror device: " << mirroringDevice.toString().c_str();
    if (!mirroringDevices) {
        LOG(ERROR) << __func__ << "Mirroring devices must not be null";
        return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL);
    }
    if (!mCarAudioConfigurationConverter || !mCarAudioConfigurationConverter->getErrors().empty()) {
        return ndk::ScopedAStatus::ok();
    }
    const auto& innerDevice = mCarAudioConfigurationConverter->getOutputMirroringDevices();
    mirroringDevices->insert(mirroringDevices->end(), innerDevice.begin(), innerDevice.end());
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus AudioControl::getCarAudioZones(std::vector<AudioZone>* audioZones) {
    for (const auto& audioZone : *audioZones) {
        LOG(DEBUG) << ":" << __func__ << "Audio zone: " << audioZone.toString().c_str();
    if (!audioZones) {
        LOG(ERROR) << __func__ << "Audio zones must not be null";
        return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL);
    }
    if (!mCarAudioConfigurationConverter || !mCarAudioConfigurationConverter->getErrors().empty()) {
        return ndk::ScopedAStatus::ok();
    }
    const auto& innerZones = mCarAudioConfigurationConverter->getAudioZones();
    audioZones->insert(audioZones->end(), innerZones.begin(), innerZones.end());
    return ndk::ScopedAStatus::ok();
}

@@ -373,6 +454,25 @@ binder_status_t AudioControl::dumpsys(int fd) {
        dprintf(fd, "Focus listener registered\n");
    }
    dprintf(fd, "AudioGainCallback %sregistered\n", (mAudioGainCallback == nullptr ? "NOT " : ""));

    AudioDeviceConfiguration configuration;
    if (getAudioDeviceConfiguration(&configuration).isOk()) {
        dprintf(fd, "AudioDeviceConfiguration: %s\n", configuration.toString().c_str());
    }
    std::vector<AudioZone> audioZones;
    if (getCarAudioZones(&audioZones).isOk()) {
        dprintf(fd, "Audio zones count: %zu\n", audioZones.size());
        for (const auto& zone : audioZones) {
            dprintf(fd, "AudioZone: %s\n", formatDump(zone.toString()).c_str());
        }
    }
    std::vector<AudioPort> mirroringDevices;
    if (getOutputMirroringDevices(&mirroringDevices).isOk()) {
        dprintf(fd, "Mirroring devices count: %zu\n", mirroringDevices.size());
        for (const auto& device : mirroringDevices) {
            dprintf(fd, "Mirroring device: %s\n", formatDump(device.toString()).c_str());
        }
    }
    return STATUS_OK;
}

+8 −1
Original line number Diff line number Diff line
@@ -35,13 +35,17 @@
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>

#include "converter/include/CarAudioConfigurationXmlConverter.h"

namespace aidl::android::hardware::automotive::audiocontrol {

namespace audiohalcommon = ::aidl::android::hardware::audio::common;
namespace audiomediacommon = ::aidl::android::media::audio::common;
namespace audiohalcommon = ::aidl::android::hardware::audio::common;

class AudioControl : public BnAudioControl {
  public:
    AudioControl();
    AudioControl(const std::string& carAudioConfig, const std::string& audioFadeConfig);
    ndk::ScopedAStatus onAudioFocusChange(const std::string& in_usage, int32_t in_zoneId,
                                          AudioFocusChange in_focusChange) override;
    ndk::ScopedAStatus onDevicesToDuckChange(
@@ -86,6 +90,9 @@ class AudioControl : public BnAudioControl {

    std::shared_ptr<IModuleChangeCallback> mModuleChangeCallback = nullptr;

    std::shared_ptr<::android::hardware::audiocontrol::internal::CarAudioConfigurationXmlConverter>
            mCarAudioConfigurationConverter = nullptr;

    binder_status_t cmdHelp(int fd) const;
    binder_status_t cmdRequestFocus(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdAbandonFocus(int fd, const char** args, uint32_t numArgs);
+56 −0
Original line number Diff line number Diff line
// Copyright (C) 2024 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.

package {
    // See: http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // all of the 'license_kinds' from "hardware_interfaces_license"
    // to get the below license kinds:
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["hardware_interfaces_license"],
}

cc_library {
    name: "android.hardware.audiocontrol.internal",
    vendor: true,
    srcs: [
        "src/CarAudioConfigurationXmlConverter.cpp",
        "src/CarAudioConfigurationUtils.cpp",
    ],
    export_include_dirs: [
        "include",
    ],
    defaults: [
        "latest_android_hardware_audio_common_ndk_static",
        "latest_android_hardware_automotive_audiocontrol_ndk_shared",
        "car.audio.configuration.xsd.default",
        "car.fade.configuration.xsd.default",
        "aidlaudioservice_defaults",
        "latest_android_media_audio_common_types_ndk_static",
    ],
    shared_libs: [
        "libbase",
        "libutils",
        "libmedia_helper",
        "car.audio.configuration.xsd.default",
        "car.fade.configuration.xsd.default",
        "liblog",
    ],
    static_libs: [
        "libaudio_aidl_conversion_common_ndk_cpp",
    ],
    header_libs: [
        "libaudio_system_headers",
    ],
}
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H
#define ANDROID_HARDWARE_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H

#include <string>

#include <aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.h>
#include <aidl/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.h>

namespace android {
namespace hardware {
namespace audiocontrol {
namespace internal {

::aidl::android::hardware::automotive::audiocontrol::AudioZoneContext getDefaultCarAudioContext();

}  // namespace internal
}  // namespace audiocontrol
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H
Loading