Define new AudioControl HAL for automotive.

This provides a mechanism for Android to interact with a car's
audio subsystem.
It is a partial replacement for the deprecated AUDIO_* properties in VehicleHal.
It also provides control over fade/balance.

Bug: 31623564
Test: build for bat_land.  VTS tests in future CL.
Change-Id: I4344cce3a6aa9a28d1327bf4d16bd080c7fd3f50
This commit is contained in:
Scott Randolph
2017-07-27 18:26:27 -07:00
parent a5f9f8b14f
commit 46bc12867b
12 changed files with 499 additions and 1 deletions

View File

@@ -0,0 +1,23 @@
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "android.hardware.automotive.audiocontrol@1.0",
root: "android.hardware",
vndk: {
enabled: true,
},
srcs: [
"types.hal",
"IAudioControl.hal",
"IAudioControlCallback.hal",
],
interfaces: [
"android.hidl.base@1.0",
],
types: [
"AudioResult",
"ContextNumber",
],
gen_java: true,
}

View File

@@ -0,0 +1,73 @@
/*
* 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.
*/
package android.hardware.automotive.audiocontrol@1.0;
import IAudioControlCallback;
/**
* Interacts with the car's audio subsystem to manage audio sources and volumes
*/
interface IAudioControl {
/**
* Registers the required callback object so that we can be notified when the state
* of the car's audio system changes. This call must be made when the interface is
* initialized.
*/
setCallback(IAudioControlCallback notificationObject)
generates (AudioResult result);
/**
* Called at startup once per context to get the mapping from ContextNumber to
* busAddress. This lets the car tell the framework to which physical output stream
* each context should be routed.
*
* For every context, a valid bus number (0 - num busses-1) must be returned. If an
* unrecognized contextNumber is encountered, then -1 shall be returned.
*
* Any context for which an invalid busNumber is returned must be routed to bus 0.
*/
getBusForContext(uint32_t contextNumber)
generates (int32_t busNumber);
/**
* 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,57 @@
/*
* 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.
*/
package android.hardware.automotive.audiocontrol@1.0;
/**
* Implemented on client (framework) side to receive asynchronous updates from the car.
*/
interface IAudioControlCallback {
/**
* When the HAL makes this call, any apps currently playing must be asked to
* temporarily suspend playback (via an AudioManager::AUDIOFOCUS_LOSS_TRANSIENT event).
*
* This is only a suggestion. Apps may be slow to react or even ignore this message
* entirely. Enforcement, if necessary, must be done at the AudioHAL level as the
* samples are delivered. In most instances, this is the way a car should ask for
* quiet if it needs it for some important situation, such as warning alarms or chimes.
*/
oneway suggestPausePlayers();
/**
* When the HAL makes this case, any apps currently playing must be asked to stop
* playing (via an AudioManager::AUDIOFOCUS_LOSS event). Once stopped, the apps must
* not resume their playback.
*
* It should be noted that not all apps or sound sources honor this request, but this
* at least gives an app the chance to do the right thing.
* Because it premanently stops media, this call is expected to be used only rarely.
* Perhaps in the event of an E-call, where resuming music might be undesirable assuming
* the driver is now dealing with whatever the emergency is?
*/
oneway suggestStopPlayers();
/**
* Receives calls from the HAL when Android should resume normal operations. If the previous
* action was a requestPausePlayers, then things that were paused must be told they may
* resume.
*/
oneway resumePlayers();
};

View File

@@ -0,0 +1,40 @@
// 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.
cc_binary {
name: "android.hardware.automotive.audiocontrol@1.0-service",
defaults: ["hidl_defaults"],
vendor: true,
relative_install_path: "hw",
srcs: [
"AudioControl.cpp",
"AudioControlCallback.cpp",
"service.cpp"
],
init_rc: ["android.hardware.automotive.audiocontrol@1.0-service.rc"],
shared_libs: [
"android.hardware.automotive.audiocontrol@1.0",
"libhidlbase",
"libhidltransport",
"liblog",
"libutils",
],
cflags: [
"-DLOG_TAG=\"AudCntrlDrv\"",
"-O0",
"-g",
],
}

View File

@@ -0,0 +1,86 @@
#include "AudioControl.h"
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
namespace android {
namespace hardware {
namespace automotive {
namespace audiocontrol {
namespace V1_0 {
namespace implementation {
// This is the static map we're using to associate a ContextNumber with a
// bus number from the audio_policy_configuration.xml setup. Every valid context needs
// to be mapped to a bus address that actually exists in the platforms configuration.
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) // Would be nice if this were common...
static int sContextToBusMap[] = {
-1, // INVALID
0, // MUSIC_CONTEXT
1, // NAVIGATION_CONTEXT
2, // VOICE_COMMAND_CONTEXT
3, // CALL_RING_CONTEXT
4, // CALL_CONTEXT
5, // ALARM_CONTEXT
6, // NOTIFICATION_CONTEXT
7, // SYSTEM_SOUND_CONTEXT
};
static const unsigned sContextMapSize = ARRAY_SIZE(sContextToBusMap);
static const unsigned sContextCount = sContextMapSize - 1; // Less one for the INVALID entry
static const unsigned sContextNumberMax = sContextCount; // contextNumber is counted from 1
AudioControl::AudioControl() {
};
// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
Return<AudioResult> AudioControl::setCallback(const sp<IAudioControlCallback>& notificationObject) {
// Hang onto the provided callback object for future use
callback = notificationObject;
return AudioResult::OK;
}
Return<int32_t> AudioControl::getBusForContext(uint32_t contextNumber) {
if (contextNumber > sContextNumberMax) {
ALOGE("Unexpected context number %d (max expected is %d)", contextNumber, sContextCount);
return -1;
} else {
return sContextToBusMap[contextNumber];
}
}
Return<void> AudioControl::setBalanceTowardRight(float value) {
// For completeness, lets bounds check the input...
if ((value > 1.0f) || (value < -1.0f)) {
ALOGE("Balance value out of range -1 to 1 at %0.2f", value);
} else {
// Just log in this default mock implementation
ALOGI("Balance set to %0.2f", value);
}
return Void();
}
Return<void> AudioControl::setFadeTowardFront(float value) {
// For completeness, lets bounds check the input...
if ((value > 1.0f) || (value < -1.0f)) {
ALOGE("Fader value out of range -1 to 1 at %0.2f", value);
} else {
// Just log in this default mock implementation
ALOGI("Fader set to %0.2f", value);
}
return Void();
}
} // namespace implementation
} // namespace V1_0
} // namespace audiocontrol
} // namespace automotive
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,45 @@
#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H
#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H
#include <android/hardware/automotive/audiocontrol/1.0/IAudioControl.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
namespace android {
namespace hardware {
namespace automotive {
namespace audiocontrol {
namespace V1_0 {
namespace implementation {
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
struct AudioControl : public IAudioControl {
public:
// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
Return<AudioResult> setCallback(const sp<IAudioControlCallback>& notificationObject) override;
Return<int32_t> getBusForContext(uint32_t contextNumber) override;
Return<void> setBalanceTowardRight(float value) override;
Return<void> setFadeTowardFront(float value) override;
// Implementation details
AudioControl();
private:
sp<IAudioControlCallback> callback;
};
} // namespace implementation
} // namespace V1_0
} // namespace audiocontrol
} // namespace automotive
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROL_H

View File

@@ -0,0 +1,31 @@
#include "AudioControlCallback.h"
namespace android {
namespace hardware {
namespace automotive {
namespace audiocontrol {
namespace V1_0 {
namespace implementation {
// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
Return<void> AudioControlCallback::suggestPausePlayers() {
// TODO implement in framework (this is called by the HAL implementation when needed)
return Void();
}
Return<void> AudioControlCallback::suggestStopPlayers() {
// TODO implement in framework (this is called by the HAL implementation when needed)
return Void();
}
Return<void> AudioControlCallback::resumePlayers() {
// TODO implement in framework (this is called by the HAL implementation when needed)
return Void();
}
} // namespace implementation
} // namespace V1_0
} // namespace audiocontrol
} // namespace automotive
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,41 @@
#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
#include <android/hardware/automotive/audiocontrol/1.0/IAudioControlCallback.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
namespace android {
namespace hardware {
namespace automotive {
namespace audiocontrol {
namespace V1_0 {
namespace implementation {
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
// TODO: Move this into packages/services/Car...
struct AudioControlCallback : public IAudioControlCallback {
// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
Return<void> suggestPausePlayers() override;
Return<void> suggestStopPlayers() override;
Return<void> resumePlayers() override;
// Methods from ::android::hidl::base::V1_0::IBase follow.
};
} // namespace implementation
} // namespace V1_0
} // namespace audiocontrol
} // namespace automotive
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H

View File

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

View File

@@ -0,0 +1,54 @@
/*
* 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 <unistd.h>
#include <hidl/HidlTransportSupport.h>
#include <log/log.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::V1_0::IAudioControl;
// The namespace in which all our implementation code lives
using namespace android::hardware::automotive::audiocontrol::V1_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) {
ALOGE("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,44 @@
/*
* 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.
*/
package android.hardware.automotive.audiocontrol@1.0;
/**
* Predefined flags to identifying audio contexts
*/
enum ContextNumber : uint32_t {
INVALID = 0, /* Shouldn't be used */
// Sounds from Android (counting from 1 coincidentally lets us match AudioAttributes usages)
MUSIC, /* Music playback */
NAVIGATION, /* Navigation directions */
VOICE_COMMAND, /* Voice command session */
CALL_RING, /* Voice call ringing */
CALL, /* Voice call */
ALARM, /* Alarm sound from Android */
NOTIFICATION, /* Notifications */
SYSTEM_SOUND, /* User interaction sounds (button clicks, etc) */
};
/** Error codes used in AudioControl HAL interface. */
enum AudioResult : uint32_t {
OK = 0,
NOT_AVAILABLE,
INVALID_ARGUMENT,
UNDERLYING_SERVICE_ERROR,
};

View File

@@ -13,7 +13,6 @@ cc_binary {
shared_libs: [
"android.hardware.automotive.evs@1.0",
"libui",
"libbase",
"libbinder",
"libcutils",
@@ -21,6 +20,7 @@ cc_binary {
"libhidlbase",
"libhidltransport",
"liblog",
"libui",
"libutils",
],