Adding v2 of audiocontrol hal

- Removes deprecated getBusForContext
- Adds APIs for enabling HAL to request and abandon audio focus

Bug: 148098383
Test: vts-tradefed -module VtsHalAudioControlV2_0TargetTest
Change-Id: I353bbd8ea7708ffb59831a8e1008951146798034
This commit is contained in:
Hayden Gomes
2020-01-10 08:49:23 -08:00
parent ec34c7fff7
commit ebebc9c266
15 changed files with 700 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "android.hardware.automotive.audiocontrol@2.0",
root: "android.hardware",
vndk: {
enabled: true,
},
srcs: [
"types.hal",
"IAudioControl.hal",
"ICloseHandle.hal",
"IFocusListener.hal",
],
interfaces: [
"android.hidl.base@1.0",
"android.hardware.audio.common@6.0",
],
gen_java: true,
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2020 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 android.hardware.automotive.audiocontrol@2.0;
import ICloseHandle;
import IFocusListener;
import android.hardware.audio.common@6.0::AudioUsage;
/**
* Interacts with the car's audio subsystem to manage audio sources and volumes
*/
interface IAudioControl {
/**
* Registers focus listener to be used by HAL for requesting and abandoning audio focus.
*
* It is expected that there will only ever be a single focus listener registered. If the
* observer dies, the HAL implementation must unregister observer automatically. If called when
* a listener is already registered, the existing one should be unregistered and replaced with
* the new listener.
*
* @param listener the listener interface
* @return closeHandle A handle to unregister observer.
*/
registerFocusListener(IFocusListener listener) generates (ICloseHandle closeHandle);
/**
* Notifies HAL of changes in audio focus status for focuses requested or abandoned by the HAL.
*
* This will be called in response to IFocusListener's requestAudioFocus and
* abandonAudioFocus, as well as part of any change in focus being held by the HAL due focus
* request from other activities or services.
*
* The HAL is not required to wait for an callback of AUDIOFOCUS_GAIN before playing audio, nor
* is it required to stop playing audio in the event of a AUDIOFOCUS_LOSS callback is received.
*
* @param usage The audio usage associated with the focus change {@code AttributeUsage}
* @param zoneId The identifier for the audio zone that the HAL is playing the stream in
* @param focusChange the AudioFocusChange that has occurred
*/
oneway onAudioFocusChange(bitfield<AudioUsage> usage, int32_t zoneId,
bitfield<AudioFocusChange> focusChange);
/**
* Control the right/left balance setting of the car speakers.
*
* This is intended to shift the speaker volume toward the right (+) or left (-) side of
* the car. 0.0 means "centered". +1.0 means fully right. -1.0 means fully left.
*
* A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1
* range.
*/
oneway setBalanceTowardRight(float value);
/**
* Control the fore/aft fade setting of the car speakers.
*
* This is intended to shift the speaker volume toward the front (+) or back (-) of the car.
* 0.0 means "centered". +1.0 means fully forward. -1.0 means fully rearward.
*
* A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1
* range.
*/
oneway setFadeTowardFront(float value);
};

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2020 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 android.hardware.automotive.audiocontrol@2.0;
/**
* Represents a generic close handle to remove a callback that doesn't need
* active interface.
*
* When close() is called OR when the interface is released, the underlying
* resources must be freed.
*/
interface ICloseHandle {
/**
* Closes the handle.
*
* The call must not fail and must be issued by the client at most once.
* Otherwise, the server must ignore subsequent calls.
*/
close();
};

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2020 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 android.hardware.automotive.audiocontrol@2.0;
import android.hardware.audio.common@6.0::AudioUsage;
/**
* Callback interface for audio focus listener.
*
* For typical configuration, the listener the car audio service.
*/
interface IFocusListener {
/**
* Called whenever HAL is requesting focus as it is starting to play audio of a given usage in a
* specified zone.
*
* In response, IAudioControl#onAudioFocusChange will be called with focusChange status. This
* interaction is oneway to avoid blocking HAL so that it is not required to wait for a response
* before playing audio.
*
* @param usage The audio usage associated with the focus request {@code AttributeUsage}
* @param zoneId The identifier for the audio zone where the HAL is requesting focus
* @param focusGain The AudioFocusChange associated with this request. Should be one of the
* following: GAIN, GAIN_TRANSIENT, GAIN_TRANSIENT_MAY_DUCK, GAIN_TRANSIENT_EXCLUSIVE.
*/
oneway requestAudioFocus(bitfield<AudioUsage> usage, int32_t zoneId,
bitfield<AudioFocusChange> focusGain);
/**
* Called whenever HAL is abandoning focus as it is finished playing audio of a given usage in a
* specific zone.
*
* In response, IAudioControl#onAudioFocusChange will be called with focusChange status. This
* interaction is oneway to avoid blocking HAL so that it is not required to wait for a response
* before stopping audio playback.
*
* @param usage The audio usage for which the HAL is abandoning focus {@code AttributeUsage}
* @param zoneId The identifier for the audio zone that the HAL abandoning focus
*/
oneway abandonAudioFocus(bitfield<AudioUsage> usage, int32_t zoneId);
};

View File

@@ -0,0 +1,39 @@
// Copyright (C) 2020 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.
cc_binary {
name: "android.hardware.automotive.audiocontrol@2.0-service",
defaults: ["hidl_defaults"],
vendor: true,
relative_install_path: "hw",
srcs: [
"AudioControl.cpp",
"service.cpp",
"CloseHandle.cpp",
],
init_rc: ["android.hardware.automotive.audiocontrol@2.0-service.rc"],
shared_libs: [
"android.hardware.automotive.audiocontrol@2.0",
"libbase",
"libhidlbase",
"liblog",
"libutils",
],
vintf_fragments: ["audiocontrol2_manifest.xml"],
cflags: [
"-O0",
"-g",
],
}

View File

@@ -0,0 +1,60 @@
#include "AudioControl.h"
#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include "CloseHandle.h"
namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
AudioControl::AudioControl() {}
Return<sp<ICloseHandle>> AudioControl::registerFocusListener(const sp<IFocusListener>& listener) {
LOG(DEBUG) << "registering focus listener";
sp<ICloseHandle> closeHandle(nullptr);
if (listener) {
mFocusListener = listener;
closeHandle = new CloseHandle([this, listener]() {
if (mFocusListener == listener) {
mFocusListener = nullptr;
}
});
} else {
LOG(ERROR) << "Unexpected nullptr for listener resulting in no-op.";
}
return closeHandle;
}
Return<void> AudioControl::setBalanceTowardRight(float value) {
// For completeness, lets bounds check the input...
if (isValidValue(value)) {
LOG(ERROR) << "Balance value out of range -1 to 1 at " << value;
} else {
// Just log in this default mock implementation
LOG(INFO) << "Balance set to " << value;
}
return Void();
}
Return<void> AudioControl::setFadeTowardFront(float value) {
// For completeness, lets bounds check the input...
if (isValidValue(value)) {
LOG(ERROR) << "Fader value out of range -1 to 1 at " << value;
} else {
// Just log in this default mock implementation
LOG(INFO) << "Fader set to " << value;
}
return Void();
}
Return<void> AudioControl::onAudioFocusChange(hidl_bitfield<AudioUsage> usage, int zoneId,
hidl_bitfield<AudioFocusChange> focusChange) {
LOG(INFO) << "Focus changed: " << static_cast<int>(focusChange) << " for usage "
<< static_cast<int>(usage) << " in zone " << zoneId;
return Void();
}
} // namespace android::hardware::automotive::audiocontrol::V2_0::implementation

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2020 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_AUTOMOTIVE_AUDIOCONTROL_V2_0_AUDIOCONTROL_H
#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V2_0_AUDIOCONTROL_H
#include <android/hardware/audio/common/6.0/types.h>
#include <android/hardware/automotive/audiocontrol/2.0/IAudioControl.h>
#include <android/hardware/automotive/audiocontrol/2.0/ICloseHandle.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
using android::hardware::audio::common::V6_0::AudioUsage;
namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
class AudioControl : public IAudioControl {
public:
// Methods from ::android::hardware::automotive::audiocontrol::V2_0::IAudioControl follow.
Return<sp<ICloseHandle>> registerFocusListener(const sp<IFocusListener>& listener);
Return<void> onAudioFocusChange(hidl_bitfield<AudioUsage> usage, int zoneId,
hidl_bitfield<AudioFocusChange> focusChange);
Return<void> setBalanceTowardRight(float value) override;
Return<void> setFadeTowardFront(float value) override;
// Implementation details
AudioControl();
private:
sp<IFocusListener> mFocusListener;
static bool isValidValue(float value) { return (value > 1.0f) || (value < -1.0f); }
};
} // namespace android::hardware::automotive::audiocontrol::V2_0::implementation
#endif // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V2_0_AUDIOCONTROL_H

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2020 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 "CloseHandle.h"
namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
CloseHandle::CloseHandle(Callback callback) : mCallback(callback) {}
CloseHandle::~CloseHandle() {
close();
}
Return<void> CloseHandle::close() {
const auto wasClosed = mIsClosed.exchange(true);
if (wasClosed) return {};
if (mCallback) mCallback();
return {};
}
} // namespace android::hardware::automotive::audiocontrol::V2_0::implementation

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2020 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.
*/
#pragma once
#include <android-base/macros.h>
#include <android/hardware/automotive/audiocontrol/2.0/ICloseHandle.h>
namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
/** Generic ICloseHandle implementation ignoring double-close events. */
class CloseHandle : public ICloseHandle {
public:
using Callback = std::function<void()>;
/**
* Create a handle with a callback.
*
* The callback is guaranteed to be called exactly once.
*
* \param callback Called on the first close() call, or on destruction of the handle
*/
CloseHandle(Callback callback = nullptr);
virtual ~CloseHandle();
Return<void> close() override;
private:
const Callback mCallback;
std::atomic<bool> mIsClosed = false;
DISALLOW_COPY_AND_ASSIGN(CloseHandle);
};
} // namespace android::hardware::automotive::audiocontrol::V2_0::implementation

View File

@@ -0,0 +1,4 @@
service vendor.audiocontrol-hal-2.0 /vendor/bin/hw/android.hardware.automotive.audiocontrol@2.0-service
class hal
user audioserver
group system

View File

@@ -0,0 +1,11 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.automotive.audiocontrol</name>
<transport>hwbinder</transport>
<version>2.0</version>
<interface>
<name>IAudioControl</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2020 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 <unistd.h>
#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
#include "AudioControl.h"
// libhidl:
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
// Generated HIDL files
using android::hardware::automotive::audiocontrol::V2_0::IAudioControl;
// The namespace in which all our implementation code lives
using namespace android::hardware::automotive::audiocontrol::V2_0::implementation;
using namespace android;
// Main service entry point
int main() {
// Create an instance of our service class
android::sp<IAudioControl> service = new AudioControl();
configureRpcThreadpool(1, true /*callerWillJoin*/);
if (service->registerAsService() != OK) {
LOG(ERROR) << "registerAsService failed";
return 1;
}
// Join (forever) the thread pool we created for the service above
joinRpcThreadpool();
// We don't ever actually expect to return, so return an error if we do get here
return 2;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2020 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 android.hardware.automotive.audiocontrol@2.0;
/**
* Changes in audio focus that can be experienced
*/
enum AudioFocusChange : uint32_t {
NONE = 0,
GAIN = 1,
GAIN_TRANSIENT = 2,
GAIN_TRANSIENT_MAY_DUCK = 3,
GAIN_TRANSIENT_EXCLUSIVE = 4,
LOSS = -1 * GAIN,
LOSS_TRANSIENT = -1 * GAIN_TRANSIENT,
LOSS_TRANSIENT_CAN_DUCK = -1 * GAIN_TRANSIENT_MAY_DUCK,
};

View File

@@ -0,0 +1,29 @@
//
// Copyright (C) 2020 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.
//
cc_test {
name: "VtsHalAudioControlV2_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalAudioControlV2_0TargetTest.cpp"],
static_libs: [
"android.hardware.automotive.audiocontrol@2.0",
"libgmock",
],
test_suites: [
"general-tests",
"vts-core",
],
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2020 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.
*/
#define LOG_TAG "VtsHalAudioControlTest"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <stdio.h>
#include <string.h>
#include <hidl/HidlTransportSupport.h>
#include <hwbinder/ProcessState.h>
#include <log/log.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
#include <android/hardware/audio/common/6.0/types.h>
#include <android/hardware/automotive/audiocontrol/2.0/IAudioControl.h>
#include <android/hardware/automotive/audiocontrol/2.0/types.h>
#include <android/log.h>
using namespace ::android::hardware::automotive::audiocontrol::V2_0;
using ::android::sp;
using ::android::hardware::hidl_bitfield;
using ::android::hardware::hidl_enum_range;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::audio::common::V6_0::AudioUsage;
// The main test class for the automotive AudioControl HAL
class CarAudioControlHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
// Make sure we can connect to the driver
pAudioControl = IAudioControl::getService(GetParam());
ASSERT_NE(pAudioControl.get(), nullptr);
}
virtual void TearDown() override {}
protected:
sp<IAudioControl> pAudioControl; // Every test needs access to the service
};
//
// Tests start here...
//
/*
* Fader exercise test. Note that only a subjective observer could determine if the
* fader actually works. The only thing we can do is exercise the HAL and if the HAL crashes,
* we _might_ get a test failure if that breaks the connection to the driver.
*/
TEST_P(CarAudioControlHidlTest, FaderExercise) {
ALOGI("Fader exercise test (silent)");
// Set the fader all the way to the back
pAudioControl->setFadeTowardFront(-1.0f);
// Set the fader all the way to the front
pAudioControl->setFadeTowardFront(1.0f);
// Set the fader part way toward the back
pAudioControl->setFadeTowardFront(-0.333f);
// Set the fader to a out of bounds value (driver should clamp)
pAudioControl->setFadeTowardFront(99999.9f);
// Set the fader back to the middle
pAudioControl->setFadeTowardFront(0.0f);
}
/*
* Balance exercise test.
*/
TEST_P(CarAudioControlHidlTest, BalanceExercise) {
ALOGI("Balance exercise test (silent)");
// Set the balance all the way to the left
pAudioControl->setBalanceTowardRight(-1.0f);
// Set the balance all the way to the right
pAudioControl->setBalanceTowardRight(1.0f);
// Set the balance part way toward the left
pAudioControl->setBalanceTowardRight(-0.333f);
// Set the balance to a out of bounds value (driver should clamp)
pAudioControl->setBalanceTowardRight(99999.9f);
// Set the balance back to the middle
pAudioControl->setBalanceTowardRight(0.0f);
}
struct FocusListenerMock : public IFocusListener {
MOCK_METHOD(Return<void>, requestAudioFocus,
(hidl_bitfield<AudioUsage> usage, int zoneId,
hidl_bitfield<AudioFocusChange> focusGain));
MOCK_METHOD(Return<void>, abandonAudioFocus, (hidl_bitfield<AudioUsage> usage, int zoneId));
};
/*
* Test focus listener registration.
*
* Verifies that:
* - registerFocusListener succeeds;
* - registering a second listener succeeds in replacing the first;
* - closing handle does not crash;
*/
TEST_P(CarAudioControlHidlTest, FocusListenerRegistration) {
ALOGI("Focus listener test");
sp<FocusListenerMock> listener = new FocusListenerMock();
auto hidlResult = pAudioControl->registerFocusListener(listener);
ASSERT_TRUE(hidlResult.isOk());
sp<FocusListenerMock> listener2 = new FocusListenerMock();
auto hidlResult2 = pAudioControl->registerFocusListener(listener2);
ASSERT_TRUE(hidlResult2.isOk());
const sp<ICloseHandle>& closeHandle = hidlResult2;
closeHandle->close();
};
TEST_P(CarAudioControlHidlTest, FocusChangeExercise) {
ALOGI("Focus Change test");
pAudioControl->onAudioFocusChange(AudioUsage::MEDIA | 0, 0,
AudioFocusChange::GAIN_TRANSIENT | 0);
};
INSTANTIATE_TEST_SUITE_P(
PerInstance, CarAudioControlHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IAudioControl::descriptor)),
android::hardware::PrintInstanceNameToString);