Merge "Revert "BluetoothAudio HAL: flip to be enabled by default""
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index de40990..359eaed 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -38,6 +38,8 @@
filterDurations(ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
filterDurations(ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS);
filterDurations(ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS);
+ filterDurations(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS);
+ filterDurations(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS);
}
// TODO: filter request/result keys
}
@@ -186,6 +188,16 @@
filteredDurations.push_back(duration);
}
break;
+ case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:
+ case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:
+ if (format == HAL_PIXEL_FORMAT_BLOB) {
+ format = AIMAGE_FORMAT_DEPTH_JPEG;
+ filteredDurations.push_back(format);
+ filteredDurations.push_back(width);
+ filteredDurations.push_back(height);
+ filteredDurations.push_back(duration);
+ }
+ break;
default:
// Should not reach here
ALOGE("%s: Unkown tag 0x%x", __FUNCTION__, tag);
@@ -284,6 +296,32 @@
filteredHeicStreamConfigs.push_back(isInput);
}
mData.update(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, filteredHeicStreamConfigs);
+
+ entry = mData.find(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
+ Vector<int32_t> filteredDynamicDepthStreamConfigs;
+ filteredDynamicDepthStreamConfigs.setCapacity(entry.count);
+
+ for (size_t i = 0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) {
+ int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET];
+ int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET];
+ int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET];
+ int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET];
+ if (isInput == ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT) {
+ // Hide input streams
+ continue;
+ }
+ // Translate HAL formats to NDK format
+ if (format == HAL_PIXEL_FORMAT_BLOB) {
+ format = AIMAGE_FORMAT_DEPTH_JPEG;
+ }
+
+ filteredDynamicDepthStreamConfigs.push_back(format);
+ filteredDynamicDepthStreamConfigs.push_back(width);
+ filteredDynamicDepthStreamConfigs.push_back(height);
+ filteredDynamicDepthStreamConfigs.push_back(isInput);
+ }
+ mData.update(ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
+ filteredDynamicDepthStreamConfigs);
}
bool
diff --git a/include/media/AudioVolumeGroup.h b/include/media/AudioVolumeGroup.h
new file mode 120000
index 0000000..d6f1c99
--- /dev/null
+++ b/include/media/AudioVolumeGroup.h
@@ -0,0 +1 @@
+../../media/libaudioclient/include/media/AudioVolumeGroup.h
\ No newline at end of file
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index dce3222..2d10c67 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -709,6 +709,49 @@
Mutexed<Config>::Locked config(mConfig);
config->mUsingSurface = surface != nullptr;
+ // Enforce required parameters
+ int32_t i32;
+ float flt;
+ if (config->mDomain & Config::IS_AUDIO) {
+ if (!msg->findInt32(KEY_SAMPLE_RATE, &i32)) {
+ ALOGD("sample rate is missing, which is required for audio components.");
+ return BAD_VALUE;
+ }
+ if (!msg->findInt32(KEY_CHANNEL_COUNT, &i32)) {
+ ALOGD("channel count is missing, which is required for audio components.");
+ return BAD_VALUE;
+ }
+ if ((config->mDomain & Config::IS_ENCODER)
+ && !mime.equalsIgnoreCase(MEDIA_MIMETYPE_AUDIO_FLAC)
+ && !msg->findInt32(KEY_BIT_RATE, &i32)
+ && !msg->findFloat(KEY_BIT_RATE, &flt)) {
+ ALOGD("bitrate is missing, which is required for audio encoders.");
+ return BAD_VALUE;
+ }
+ }
+ if (config->mDomain & (Config::IS_IMAGE | Config::IS_VIDEO)) {
+ if (!msg->findInt32(KEY_WIDTH, &i32)) {
+ ALOGD("width is missing, which is required for image/video components.");
+ return BAD_VALUE;
+ }
+ if (!msg->findInt32(KEY_HEIGHT, &i32)) {
+ ALOGD("height is missing, which is required for image/video components.");
+ return BAD_VALUE;
+ }
+ if ((config->mDomain & Config::IS_ENCODER) && (config->mDomain & Config::IS_VIDEO)) {
+ if (!msg->findInt32(KEY_BIT_RATE, &i32)
+ && !msg->findFloat(KEY_BIT_RATE, &flt)) {
+ ALOGD("bitrate is missing, which is required for video encoders.");
+ return BAD_VALUE;
+ }
+ if (!msg->findInt32(KEY_I_FRAME_INTERVAL, &i32)
+ && !msg->findFloat(KEY_I_FRAME_INTERVAL, &flt)) {
+ ALOGD("I frame interval is missing, which is required for video encoders.");
+ return BAD_VALUE;
+ }
+ }
+ }
+
/*
* Handle input surface configuration
*/
@@ -718,13 +761,14 @@
{
config->mISConfig->mMinFps = 0;
int64_t value;
- if (msg->findInt64("repeat-previous-frame-after", &value) && value > 0) {
+ if (msg->findInt64(KEY_REPEAT_PREVIOUS_FRAME_AFTER, &value) && value > 0) {
config->mISConfig->mMinFps = 1e6 / value;
}
- (void)msg->findFloat("max-fps-to-encoder", &config->mISConfig->mMaxFps);
+ (void)msg->findFloat(
+ KEY_MAX_FPS_TO_ENCODER, &config->mISConfig->mMaxFps);
config->mISConfig->mMinAdjustedFps = 0;
config->mISConfig->mFixedAdjustedFps = 0;
- if (msg->findInt64("max-pts-gap-to-encoder", &value)) {
+ if (msg->findInt64(KEY_MAX_PTS_GAP_TO_ENCODER, &value)) {
if (value < 0 && value >= INT32_MIN) {
config->mISConfig->mFixedAdjustedFps = -1e6 / value;
} else if (value > 0 && value <= INT32_MAX) {
@@ -745,7 +789,7 @@
config->mISConfig->mSuspended = false;
config->mISConfig->mSuspendAtUs = -1;
int32_t value;
- if (msg->findInt32("create-input-buffers-suspended", &value) && value) {
+ if (msg->findInt32(KEY_CREATE_INPUT_SURFACE_SUSPENDED, &value) && value) {
config->mISConfig->mSuspended = true;
}
}
@@ -1453,7 +1497,7 @@
*/
if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))
&& (config->mDomain & Config::IS_ENCODER) && config->mInputSurface && config->mISConfig) {
- (void)params->findInt64("time-offset-us", &config->mISConfig->mTimeOffsetUs);
+ (void)params->findInt64(PARAMETER_KEY_OFFSET_TIME, &config->mISConfig->mTimeOffsetUs);
if (params->findInt64("skip-frames-before", &config->mISConfig->mStartAtUs)) {
config->mISConfig->mStopped = false;
@@ -1462,10 +1506,10 @@
}
int32_t value;
- if (params->findInt32("drop-input-frames", &value)) {
+ if (params->findInt32(PARAMETER_KEY_SUSPEND, &value)) {
config->mISConfig->mSuspended = value;
config->mISConfig->mSuspendAtUs = -1;
- (void)params->findInt64("drop-start-time-us", &config->mISConfig->mSuspendAtUs);
+ (void)params->findInt64(PARAMETER_KEY_SUSPEND_TIME, &config->mISConfig->mSuspendAtUs);
}
(void)config->mInputSurface->configure(*config->mISConfig);
diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp
index 736aac5..d22153d 100644
--- a/media/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/codec2/vndk/C2AllocatorIon.cpp
@@ -140,6 +140,7 @@
protected:
class Impl;
+ class ImplV2;
Impl *mImpl;
// TODO: we could make this encapsulate shared_ptr and copiable
@@ -147,7 +148,7 @@
};
class C2AllocationIon::Impl {
-private:
+protected:
/**
* Constructs an ion allocation.
*
@@ -191,11 +192,7 @@
* \return created ion allocation (implementation) which may be invalid if the
* import failed.
*/
- static Impl *Import(int ionFd, size_t capacity, int bufferFd, C2Allocator::id_t id) {
- ion_user_handle_t buffer = -1;
- int ret = ion_import(ionFd, bufferFd, &buffer);
- return new Impl(ionFd, capacity, bufferFd, buffer, id, ret);
- }
+ static Impl *Import(int ionFd, size_t capacity, int bufferFd, C2Allocator::id_t id);
/**
* Constructs an ion allocation by allocating an ion buffer.
@@ -209,24 +206,7 @@
* \return created ion allocation (implementation) which may be invalid if the
* allocation failed.
*/
- static Impl *Alloc(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags, C2Allocator::id_t id) {
- int bufferFd = -1;
- ion_user_handle_t buffer = -1;
- size_t alignedSize = align == 0 ? size : (size + align - 1) & ~(align - 1);
- int ret = ion_alloc(ionFd, alignedSize, align, heapMask, flags, &buffer);
- ALOGV("ion_alloc(ionFd = %d, size = %zu, align = %zu, prot = %d, flags = %d) "
- "returned (%d) ; buffer = %d",
- ionFd, alignedSize, align, heapMask, flags, ret, buffer);
- if (ret == 0) {
- // get buffer fd for native handle constructor
- ret = ion_share(ionFd, buffer, &bufferFd);
- if (ret != 0) {
- ion_free(ionFd, buffer);
- buffer = -1;
- }
- }
- return new Impl(ionFd, alignedSize, bufferFd, buffer, id, ret);
- }
+ static Impl *Alloc(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags, C2Allocator::id_t id);
c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) {
(void)fence; // TODO: wait for fence
@@ -256,32 +236,7 @@
size_t mapSize = size + alignmentBytes;
Mapping map = { nullptr, alignmentBytes, mapSize };
- c2_status_t err = C2_OK;
- if (mMapFd == -1) {
- int ret = ion_map(mIonFd, mBuffer, mapSize, prot,
- flags, mapOffset, (unsigned char**)&map.addr, &mMapFd);
- ALOGV("ion_map(ionFd = %d, handle = %d, size = %zu, prot = %d, flags = %d, "
- "offset = %zu) returned (%d)",
- mIonFd, mBuffer, mapSize, prot, flags, mapOffset, ret);
- if (ret) {
- mMapFd = -1;
- map.addr = *addr = nullptr;
- err = c2_map_errno<EINVAL>(-ret);
- } else {
- *addr = (uint8_t *)map.addr + alignmentBytes;
- }
- } else {
- map.addr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset);
- ALOGV("mmap(size = %zu, prot = %d, flags = %d, mapFd = %d, offset = %zu) "
- "returned (%d)",
- mapSize, prot, flags, mMapFd, mapOffset, errno);
- if (map.addr == MAP_FAILED) {
- map.addr = *addr = nullptr;
- err = c2_map_errno<EINVAL>(errno);
- } else {
- *addr = (uint8_t *)map.addr + alignmentBytes;
- }
- }
+ c2_status_t err = mapInternal(mapSize, mapOffset, alignmentBytes, prot, flags, &(map.addr), addr);
if (map.addr) {
mMappings.push_back(map);
}
@@ -289,7 +244,7 @@
}
c2_status_t unmap(void *addr, size_t size, C2Fence *fence) {
- if (mMapFd < 0 || mMappings.empty()) {
+ if (mMappings.empty()) {
ALOGD("tried to unmap unmapped buffer");
return C2_NOT_FOUND;
}
@@ -307,14 +262,14 @@
*fence = C2Fence(); // not using fences
}
(void)mMappings.erase(it);
- ALOGV("successfully unmapped: %d", mBuffer);
+ ALOGV("successfully unmapped: %d", mHandle.bufferFd());
return C2_OK;
}
ALOGD("unmap failed to find specified map");
return C2_BAD_VALUE;
}
- ~Impl() {
+ virtual ~Impl() {
if (!mMappings.empty()) {
ALOGD("Dangling mappings!");
for (const Mapping &map : mMappings) {
@@ -326,7 +281,9 @@
mMapFd = -1;
}
if (mInit == C2_OK) {
- (void)ion_free(mIonFd, mBuffer);
+ if (mBuffer >= 0) {
+ (void)ion_free(mIonFd, mBuffer);
+ }
native_handle_close(&mHandle);
}
if (mIonFd >= 0) {
@@ -346,11 +303,42 @@
return mId;
}
- ion_user_handle_t ionHandle() const {
+ virtual ion_user_handle_t ionHandle() const {
return mBuffer;
}
-private:
+protected:
+ virtual c2_status_t mapInternal(size_t mapSize, size_t mapOffset, size_t alignmentBytes,
+ int prot, int flags, void** base, void** addr) {
+ c2_status_t err = C2_OK;
+ if (mMapFd == -1) {
+ int ret = ion_map(mIonFd, mBuffer, mapSize, prot,
+ flags, mapOffset, (unsigned char**)base, &mMapFd);
+ ALOGV("ion_map(ionFd = %d, handle = %d, size = %zu, prot = %d, flags = %d, "
+ "offset = %zu) returned (%d)",
+ mIonFd, mBuffer, mapSize, prot, flags, mapOffset, ret);
+ if (ret) {
+ mMapFd = -1;
+ *base = *addr = nullptr;
+ err = c2_map_errno<EINVAL>(-ret);
+ } else {
+ *addr = (uint8_t *)*base + alignmentBytes;
+ }
+ } else {
+ *base = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset);
+ ALOGV("mmap(size = %zu, prot = %d, flags = %d, mapFd = %d, offset = %zu) "
+ "returned (%d)",
+ mapSize, prot, flags, mMapFd, mapOffset, errno);
+ if (*base == MAP_FAILED) {
+ *base = *addr = nullptr;
+ err = c2_map_errno<EINVAL>(errno);
+ } else {
+ *addr = (uint8_t *)*base + alignmentBytes;
+ }
+ }
+ return err;
+ }
+
int mIonFd;
C2HandleIon mHandle;
ion_user_handle_t mBuffer;
@@ -365,6 +353,93 @@
std::list<Mapping> mMappings;
};
+class C2AllocationIon::ImplV2 : public C2AllocationIon::Impl {
+public:
+ /**
+ * Constructs an ion allocation for platforms with new (ion_4.12.h) api
+ *
+ * \note We always create an ion allocation, even if the allocation or import fails
+ * so that we can capture the error.
+ *
+ * \param ionFd ion client (ownership transferred to created object)
+ * \param capacity size of allocation
+ * \param bufferFd buffer handle (ownership transferred to created object). Must be
+ * invalid if err is not 0.
+ * \param err errno during buffer allocation or import
+ */
+ ImplV2(int ionFd, size_t capacity, int bufferFd, C2Allocator::id_t id, int err)
+ : Impl(ionFd, capacity, bufferFd, -1 /*buffer*/, id, err) {
+ }
+
+ virtual ~ImplV2() = default;
+
+ virtual ion_user_handle_t ionHandle() const {
+ return mHandle.bufferFd();
+ }
+
+protected:
+ virtual c2_status_t mapInternal(size_t mapSize, size_t mapOffset, size_t alignmentBytes,
+ int prot, int flags, void** base, void** addr) {
+ c2_status_t err = C2_OK;
+ *base = mmap(nullptr, mapSize, prot, flags, mHandle.bufferFd(), mapOffset);
+ ALOGV("mmapV2(size = %zu, prot = %d, flags = %d, mapFd = %d, offset = %zu) "
+ "returned (%d)",
+ mapSize, prot, flags, mHandle.bufferFd(), mapOffset, errno);
+ if (*base == MAP_FAILED) {
+ *base = *addr = nullptr;
+ err = c2_map_errno<EINVAL>(errno);
+ } else {
+ *addr = (uint8_t *)*base + alignmentBytes;
+ }
+ return err;
+ }
+
+};
+
+C2AllocationIon::Impl *C2AllocationIon::Impl::Import(int ionFd, size_t capacity, int bufferFd,
+ C2Allocator::id_t id) {
+ int ret = 0;
+ if (ion_is_legacy(ionFd)) {
+ ion_user_handle_t buffer = -1;
+ ret = ion_import(ionFd, bufferFd, &buffer);
+ return new Impl(ionFd, capacity, bufferFd, buffer, id, ret);
+ } else {
+ return new ImplV2(ionFd, capacity, bufferFd, id, ret);
+ }
+}
+
+C2AllocationIon::Impl *C2AllocationIon::Impl::Alloc(int ionFd, size_t size, size_t align,
+ unsigned heapMask, unsigned flags, C2Allocator::id_t id) {
+ int bufferFd = -1;
+ ion_user_handle_t buffer = -1;
+ size_t alignedSize = align == 0 ? size : (size + align - 1) & ~(align - 1);
+ int ret;
+
+ if (ion_is_legacy(ionFd)) {
+ ret = ion_alloc(ionFd, alignedSize, align, heapMask, flags, &buffer);
+ ALOGV("ion_alloc(ionFd = %d, size = %zu, align = %zu, prot = %d, flags = %d) "
+ "returned (%d) ; buffer = %d",
+ ionFd, alignedSize, align, heapMask, flags, ret, buffer);
+ if (ret == 0) {
+ // get buffer fd for native handle constructor
+ ret = ion_share(ionFd, buffer, &bufferFd);
+ if (ret != 0) {
+ ion_free(ionFd, buffer);
+ buffer = -1;
+ }
+ }
+ return new Impl(ionFd, alignedSize, bufferFd, buffer, id, ret);
+
+ } else {
+ ret = ion_alloc_fd(ionFd, alignedSize, align, heapMask, flags, &bufferFd);
+ ALOGV("ion_alloc_fd(ionFd = %d, size = %zu, align = %zu, prot = %d, flags = %d) "
+ "returned (%d) ; bufferFd = %d",
+ ionFd, alignedSize, align, heapMask, flags, ret, bufferFd);
+
+ return new ImplV2(ionFd, alignedSize, bufferFd, id, ret);
+ }
+}
+
c2_status_t C2AllocationIon::map(
size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) {
return mImpl->map(offset, size, usage, fence, addr);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 4b4d767..c776c51 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -3021,8 +3021,10 @@
}
unsigned bsid = br.getBits(5);
- if (bsid < 8) {
- ALOGW("Incorrect bsid in EAC3 header. Possibly AC-3?");
+ if (bsid == 9 || bsid == 10) {
+ ALOGW("EAC3 stream (bsid=%d) may be silenced by the decoder", bsid);
+ } else if (bsid > 16) {
+ ALOGE("EAC3 stream (bsid=%d) is not compatible with ETSI TS 102 366 v1.4.1", bsid);
delete[] chunk;
return ERROR_MALFORMED;
}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index b111b78..e9b6fb1 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -10,6 +10,7 @@
"AudioAttributes.cpp",
"AudioPolicy.cpp",
"AudioProductStrategy.cpp",
+ "AudioVolumeGroup.cpp",
],
shared_libs: [
"libaudioutils",
diff --git a/media/libaudioclient/AudioAttributes.cpp b/media/libaudioclient/AudioAttributes.cpp
index 0f327cf..1ee6930 100644
--- a/media/libaudioclient/AudioAttributes.cpp
+++ b/media/libaudioclient/AudioAttributes.cpp
@@ -43,7 +43,7 @@
strcpy(mAttributes.tags, "");
}
mStreamType = static_cast<audio_stream_type_t>(parcel->readInt32());
- mGroupId = parcel->readUint32();
+ mGroupId = static_cast<volume_group_t>(parcel->readUint32());
return NO_ERROR;
}
@@ -60,7 +60,7 @@
parcel->writeUtf8AsUtf16(mAttributes.tags);
}
parcel->writeInt32(static_cast<int32_t>(mStreamType));
- parcel->writeUint32(mGroupId);
+ parcel->writeUint32(static_cast<uint32_t>(mGroupId));
return NO_ERROR;
}
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 01d9b3d..0ce2513 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -792,6 +792,7 @@
int64_t token = IPCThreadState::self()->clearCallingIdentity();
ap->registerClient(apc);
ap->setAudioPortCallbacksEnabled(apc->isAudioPortCbEnabled());
+ ap->setAudioVolumeGroupCallbacksEnabled(apc->isAudioVolumeGroupCbEnabled());
IPCThreadState::self()->restoreCallingIdentity(token);
}
@@ -987,6 +988,38 @@
return aps->getStreamVolumeIndex(stream, index, device);
}
+status_t AudioSystem::setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setVolumeIndexForAttributes(attr, index, device);
+}
+
+status_t AudioSystem::getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getVolumeIndexForAttributes(attr, index, device);
+}
+
+status_t AudioSystem::getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getMaxVolumeIndexForAttributes(attr, index);
+}
+
+status_t AudioSystem::getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getMinVolumeIndexForAttributes(attr, index);
+}
+
uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
@@ -1190,6 +1223,38 @@
return (ret < 0) ? INVALID_OPERATION : NO_ERROR;
}
+status_t AudioSystem::addAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ Mutex::Autolock _l(gLockAPS);
+ if (gAudioPolicyServiceClient == 0) {
+ return NO_INIT;
+ }
+ int ret = gAudioPolicyServiceClient->addAudioVolumeGroupCallback(callback);
+ if (ret == 1) {
+ aps->setAudioVolumeGroupCallbacksEnabled(true);
+ }
+ return (ret < 0) ? INVALID_OPERATION : NO_ERROR;
+}
+
+status_t AudioSystem::removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ Mutex::Autolock _l(gLockAPS);
+ if (gAudioPolicyServiceClient == 0) {
+ return NO_INIT;
+ }
+ int ret = gAudioPolicyServiceClient->removeAudioVolumeGroupCallback(callback);
+ if (ret == 0) {
+ aps->setAudioVolumeGroupCallbacksEnabled(false);
+ }
+ return (ret < 0) ? INVALID_OPERATION : NO_ERROR;
+}
+
status_t AudioSystem::addAudioDeviceCallback(
const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
@@ -1403,12 +1468,16 @@
audio_stream_type_t AudioSystem::attributesToStreamType(const audio_attributes_t &attr)
{
- product_strategy_t strategyId =
- AudioSystem::getProductStrategyFromAudioAttributes(AudioAttributes(attr));
+ product_strategy_t psId;
+ status_t ret = AudioSystem::getProductStrategyFromAudioAttributes(AudioAttributes(attr), psId);
+ if (ret != NO_ERROR) {
+ ALOGE("no strategy found for attributes %s", toString(attr).c_str());
+ return AUDIO_STREAM_MUSIC;
+ }
AudioProductStrategyVector strategies;
listAudioProductStrategies(strategies);
for (const auto &strategy : strategies) {
- if (strategy.getId() == strategyId) {
+ if (strategy.getId() == psId) {
auto attrVect = strategy.getAudioAttributes();
auto iter = std::find_if(begin(attrVect), end(attrVect), [&attr](const auto &refAttr) {
return AudioProductStrategy::attributesMatches(
@@ -1422,11 +1491,27 @@
return AUDIO_STREAM_MUSIC;
}
-product_strategy_t AudioSystem::getProductStrategyFromAudioAttributes(const AudioAttributes &aa)
+status_t AudioSystem::getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
+ product_strategy_t &productStrategy)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
- if (aps == 0) return PRODUCT_STRATEGY_NONE;
- return aps->getProductStrategyFromAudioAttributes(aa);
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getProductStrategyFromAudioAttributes(aa,productStrategy);
+}
+
+status_t AudioSystem::listAudioVolumeGroups(AudioVolumeGroupVector &groups)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->listAudioVolumeGroups(groups);
+}
+
+status_t AudioSystem::getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
+ volume_group_t &volumeGroup)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getVolumeGroupFromAudioAttributes(aa, volumeGroup);
}
// ---------------------------------------------------------------------------
@@ -1478,6 +1563,47 @@
}
}
+// ----------------------------------------------------------------------------
+int AudioSystem::AudioPolicyServiceClient::addAudioVolumeGroupCallback(
+ const sp<AudioVolumeGroupCallback>& callback)
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
+ if (mAudioVolumeGroupCallback[i] == callback) {
+ return -1;
+ }
+ }
+ mAudioVolumeGroupCallback.add(callback);
+ return mAudioVolumeGroupCallback.size();
+}
+
+int AudioSystem::AudioPolicyServiceClient::removeAudioVolumeGroupCallback(
+ const sp<AudioVolumeGroupCallback>& callback)
+{
+ Mutex::Autolock _l(mLock);
+ size_t i;
+ for (i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
+ if (mAudioVolumeGroupCallback[i] == callback) {
+ break;
+ }
+ }
+ if (i == mAudioVolumeGroupCallback.size()) {
+ return -1;
+ }
+ mAudioVolumeGroupCallback.removeAt(i);
+ return mAudioVolumeGroupCallback.size();
+}
+
+void AudioSystem::AudioPolicyServiceClient::onAudioVolumeGroupChanged(volume_group_t group,
+ int flags)
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
+ mAudioVolumeGroupCallback[i]->onAudioVolumeGroupChanged(group, flags);
+ }
+}
+// ----------------------------------------------------------------------------
+
void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(
String8 regId, int32_t state)
{
@@ -1521,6 +1647,9 @@
for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
mAudioPortCallbacks[i]->onServiceDied();
}
+ for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
+ mAudioVolumeGroupCallback[i]->onServiceDied();
+ }
}
{
Mutex::Autolock _l(gLockAPS);
diff --git a/media/libaudioclient/AudioVolumeGroup.cpp b/media/libaudioclient/AudioVolumeGroup.cpp
new file mode 100644
index 0000000..e79a362
--- /dev/null
+++ b/media/libaudioclient/AudioVolumeGroup.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 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 "AudioVolumeGroup"
+
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+
+#include <media/AudioVolumeGroup.h>
+#include <media/AudioAttributes.h>
+
+namespace android {
+
+status_t AudioVolumeGroup::readFromParcel(const Parcel *parcel)
+{
+ status_t ret = parcel->readUtf8FromUtf16(&mName);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ mGroupId = static_cast<volume_group_t>(parcel->readInt32());
+ size_t size = static_cast<size_t>(parcel->readInt32());
+ for (size_t i = 0; i < size; i++) {
+ AudioAttributes attribute;
+ attribute.readFromParcel(parcel);
+ if (ret != NO_ERROR) {
+ mAudioAttributes.clear();
+ return ret;
+ }
+ mAudioAttributes.push_back(attribute.getAttributes());
+ }
+ size = static_cast<size_t>(parcel->readInt32());
+ for (size_t i = 0; i < size; i++) {
+ audio_stream_type_t stream = static_cast<audio_stream_type_t>(parcel->readInt32());
+ mStreams.push_back(stream);
+ }
+ return NO_ERROR;
+}
+
+status_t AudioVolumeGroup::writeToParcel(Parcel *parcel) const
+{
+ parcel->writeUtf8AsUtf16(mName);
+ parcel->writeInt32(static_cast<int32_t>(mGroupId));
+ size_t size = mAudioAttributes.size();
+ size_t sizePosition = parcel->dataPosition();
+ parcel->writeInt32(size);
+ size_t finalSize = size;
+ for (const auto &attributes : mAudioAttributes) {
+ size_t position = parcel->dataPosition();
+ AudioAttributes attribute(attributes);
+ status_t ret = attribute.writeToParcel(parcel);
+ if (ret != NO_ERROR) {
+ parcel->setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = parcel->dataPosition();
+ parcel->setDataPosition(sizePosition);
+ parcel->writeInt32(finalSize);
+ parcel->setDataPosition(position);
+ }
+ parcel->writeInt32(mStreams.size());
+ for (const auto &stream : mStreams) {
+ parcel->writeInt32(static_cast<int32_t>(stream));
+ }
+ return NO_ERROR;
+}
+
+} // namespace android
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 1bce16f..3bac44f 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -51,6 +51,10 @@
INIT_STREAM_VOLUME,
SET_STREAM_VOLUME,
GET_STREAM_VOLUME,
+ SET_VOLUME_ATTRIBUTES,
+ GET_VOLUME_ATTRIBUTES,
+ GET_MIN_VOLUME_FOR_ATTRIBUTES,
+ GET_MAX_VOLUME_FOR_ATTRIBUTES,
GET_STRATEGY_FOR_STREAM,
GET_OUTPUT_FOR_EFFECT,
REGISTER_EFFECT,
@@ -78,6 +82,7 @@
START_AUDIO_SOURCE,
STOP_AUDIO_SOURCE,
SET_AUDIO_PORT_CALLBACK_ENABLED,
+ SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED,
SET_MASTER_MONO,
GET_MASTER_MONO,
GET_STREAM_VOLUME_DB,
@@ -95,6 +100,8 @@
GET_OFFLOAD_FORMATS_A2DP,
LIST_AUDIO_PRODUCT_STRATEGIES,
GET_STRATEGY_FOR_ATTRIBUTES,
+ LIST_AUDIO_VOLUME_GROUPS,
+ GET_VOLUME_GROUP_FOR_ATTRIBUTES
};
#define MAX_ITEMS_PER_LIST 1024
@@ -415,6 +422,70 @@
return static_cast <status_t> (reply.readInt32());
}
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr, int index,
+ audio_devices_t device)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&attr, sizeof(audio_attributes_t));
+ data.writeInt32(index);
+ data.writeInt32(static_cast <uint32_t>(device));
+ status_t status = remote()->transact(SET_VOLUME_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast <status_t> (reply.readInt32());
+ }
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr, int &index,
+ audio_devices_t device)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&attr, sizeof(audio_attributes_t));
+ data.writeInt32(static_cast <uint32_t>(device));
+ status_t status = remote()->transact(GET_VOLUME_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ index = reply.readInt32();
+ return NO_ERROR;
+ }
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&attr, sizeof(audio_attributes_t));
+ status_t status = remote()->transact(GET_MIN_VOLUME_FOR_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ index = reply.readInt32();
+ return NO_ERROR;
+ }
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&attr, sizeof(audio_attributes_t));
+ status_t status = remote()->transact(GET_MAX_VOLUME_FOR_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ index = reply.readInt32();
+ return NO_ERROR;
+ }
virtual uint32_t getStrategyForStream(audio_stream_type_t stream)
{
Parcel data, reply;
@@ -692,6 +763,14 @@
remote()->transact(SET_AUDIO_PORT_CALLBACK_ENABLED, data, &reply);
}
+ virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(enabled ? 1 : 0);
+ remote()->transact(SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED, data, &reply);
+ }
+
virtual status_t acquireSoundTriggerSession(audio_session_t *session,
audio_io_handle_t *ioHandle,
audio_devices_t *device)
@@ -1085,35 +1164,90 @@
return status;
}
status = static_cast<status_t>(reply.readInt32());
- if (status == NO_ERROR) {
- uint32_t numStrategies = static_cast<uint32_t>(reply.readInt32());
- for (size_t i = 0; i < numStrategies; i++) {
- AudioProductStrategy strategy;
- status = strategy.readFromParcel(&reply);
- if (status != NO_ERROR) {
- ALOGE("%s: failed to read strategies", __FUNCTION__);
- strategies.clear();
- return status;
- }
- strategies.push_back(strategy);
- }
+ if (status != NO_ERROR) {
+ return status;
}
- return status;
+ uint32_t numStrategies = static_cast<uint32_t>(reply.readInt32());
+ for (size_t i = 0; i < numStrategies; i++) {
+ AudioProductStrategy strategy;
+ status = strategy.readFromParcel(&reply);
+ if (status != NO_ERROR) {
+ ALOGE("%s: failed to read strategies", __FUNCTION__);
+ strategies.clear();
+ return status;
+ }
+ strategies.push_back(strategy);
+ }
+ return NO_ERROR;
}
- virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa)
+ virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
+ product_strategy_t &productStrategy)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
status_t status = aa.writeToParcel(&data);
if (status != NO_ERROR) {
- return PRODUCT_STRATEGY_NONE;
+ return status;
}
status = remote()->transact(GET_STRATEGY_FOR_ATTRIBUTES, data, &reply);
- if (status == NO_ERROR) {
- return static_cast<product_strategy_t>(reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
}
- return PRODUCT_STRATEGY_NONE;
+ status = static_cast<status_t>(reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ productStrategy = static_cast<product_strategy_t>(reply.readInt32());
+ return NO_ERROR;
+ }
+
+ virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ status_t status = remote()->transact(LIST_AUDIO_VOLUME_GROUPS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast<status_t>(reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ uint32_t numGroups = static_cast<uint32_t>(reply.readInt32());
+ for (size_t i = 0; i < numGroups; i++) {
+ AudioVolumeGroup group;
+ status = group.readFromParcel(&reply);
+ if (status != NO_ERROR) {
+ ALOGE("%s: failed to read volume groups", __FUNCTION__);
+ groups.clear();
+ return status;
+ }
+ groups.push_back(group);
+ }
+ return NO_ERROR;
+ }
+
+ virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
+ volume_group_t &volumeGroup)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ status_t status = aa.writeToParcel(&data);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = remote()->transact(GET_VOLUME_GROUP_FOR_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast<status_t>(reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ volumeGroup = static_cast<volume_group_t>(reply.readInt32());
+ return NO_ERROR;
}
};
@@ -1173,7 +1307,9 @@
case SET_A11Y_SERVICES_UIDS:
case SET_UID_DEVICE_AFFINITY:
case REMOVE_UID_DEVICE_AFFINITY:
- case GET_OFFLOAD_FORMATS_A2DP: {
+ case GET_OFFLOAD_FORMATS_A2DP:
+ case LIST_AUDIO_VOLUME_GROUPS:
+ case GET_VOLUME_GROUP_FOR_ATTRIBUTES: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1433,6 +1569,73 @@
return NO_ERROR;
} break;
+ case SET_VOLUME_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t attributes = {};
+ status_t status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ int index = data.readInt32();
+ audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
+
+ reply->writeInt32(static_cast <uint32_t>(setVolumeIndexForAttributes(attributes,
+ index, device)));
+ return NO_ERROR;
+ } break;
+
+ case GET_VOLUME_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t attributes = {};
+ status_t status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
+
+ int index = 0;
+ status = getVolumeIndexForAttributes(attributes, index, device);
+ reply->writeInt32(static_cast <uint32_t>(status));
+ if (status == NO_ERROR) {
+ reply->writeInt32(index);
+ }
+ return NO_ERROR;
+ } break;
+
+ case GET_MIN_VOLUME_FOR_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t attributes = {};
+ status_t status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ int index = 0;
+ status = getMinVolumeIndexForAttributes(attributes, index);
+ reply->writeInt32(static_cast <uint32_t>(status));
+ if (status == NO_ERROR) {
+ reply->writeInt32(index);
+ }
+ return NO_ERROR;
+ } break;
+
+ case GET_MAX_VOLUME_FOR_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t attributes = {};
+ status_t status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ int index = 0;
+ status = getMaxVolumeIndexForAttributes(attributes, index);
+ reply->writeInt32(static_cast <uint32_t>(status));
+ if (status == NO_ERROR) {
+ reply->writeInt32(index);
+ }
+ return NO_ERROR;
+ } break;
+
case GET_DEVICES_FOR_STREAM: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_stream_type_t stream =
@@ -1681,6 +1884,12 @@
return NO_ERROR;
} break;
+ case SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ setAudioVolumeGroupCallbacksEnabled(data.readInt32() == 1);
+ return NO_ERROR;
+ } break;
+
case ACQUIRE_SOUNDTRIGGER_SESSION: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
@@ -1992,7 +2201,7 @@
status_t status = listAudioProductStrategies(strategies);
reply->writeInt32(status);
if (status != NO_ERROR) {
- return status;
+ return NO_ERROR;
}
size_t size = strategies.size();
size_t sizePosition = reply->dataPosition();
@@ -2021,11 +2230,61 @@
if (status != NO_ERROR) {
return status;
}
- product_strategy_t strategy = getProductStrategyFromAudioAttributes(attributes);
+ product_strategy_t strategy;
+ status = getProductStrategyFromAudioAttributes(attributes, strategy);
+ reply->writeInt32(status);
+ if (status != NO_ERROR) {
+ return NO_ERROR;
+ }
reply->writeUint32(static_cast<int>(strategy));
return NO_ERROR;
}
+ case LIST_AUDIO_VOLUME_GROUPS: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioVolumeGroupVector groups;
+ status_t status = listAudioVolumeGroups(groups);
+ reply->writeInt32(status);
+ if (status != NO_ERROR) {
+ return NO_ERROR;
+ }
+ size_t size = groups.size();
+ size_t sizePosition = reply->dataPosition();
+ reply->writeInt32(size);
+ size_t finalSize = size;
+ for (size_t i = 0; i < size; i++) {
+ size_t position = reply->dataPosition();
+ if (groups[i].writeToParcel(reply) != NO_ERROR) {
+ reply->setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = reply->dataPosition();
+ reply->setDataPosition(sizePosition);
+ reply->writeInt32(finalSize);
+ reply->setDataPosition(position);
+ }
+ return NO_ERROR;
+ }
+
+ case GET_VOLUME_GROUP_FOR_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioAttributes attributes;
+ status_t status = attributes.readFromParcel(&data);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ volume_group_t group;
+ status = getVolumeGroupFromAudioAttributes(attributes, group);
+ reply->writeInt32(status);
+ if (status != NO_ERROR) {
+ return NO_ERROR;
+ }
+ reply->writeUint32(static_cast<int>(group));
+ return NO_ERROR;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/IAudioPolicyServiceClient.cpp b/media/libaudioclient/IAudioPolicyServiceClient.cpp
index 1f9eab7..52d8ccd 100644
--- a/media/libaudioclient/IAudioPolicyServiceClient.cpp
+++ b/media/libaudioclient/IAudioPolicyServiceClient.cpp
@@ -31,7 +31,8 @@
PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION,
PATCH_LIST_UPDATE,
MIX_STATE_UPDATE,
- RECORDING_CONFIGURATION_UPDATE
+ RECORDING_CONFIGURATION_UPDATE,
+ VOLUME_GROUP_CHANGED,
};
// ----------------------------------------------------------------------
@@ -108,6 +109,15 @@
remote()->transact(PATCH_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
}
+ void onAudioVolumeGroupChanged(volume_group_t group, int flags)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
+ data.writeUint32(group);
+ data.writeInt32(flags);
+ remote()->transact(VOLUME_GROUP_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state)
{
Parcel data, reply;
@@ -157,6 +167,13 @@
onAudioPatchListUpdate();
return NO_ERROR;
} break;
+ case VOLUME_GROUP_CHANGED: {
+ CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
+ volume_group_t group = static_cast<volume_group_t>(data.readUint32());
+ int flags = data.readInt32();
+ onAudioVolumeGroupChanged(group, flags);
+ return NO_ERROR;
+ } break;
case MIX_STATE_UPDATE: {
CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
String8 regId = data.readString8();
diff --git a/media/libaudioclient/include/media/AudioAttributes.h b/media/libaudioclient/include/media/AudioAttributes.h
index edf26eb..0a35e9e 100644
--- a/media/libaudioclient/include/media/AudioAttributes.h
+++ b/media/libaudioclient/include/media/AudioAttributes.h
@@ -17,6 +17,7 @@
#pragma once
+#include <media/AudioCommonTypes.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <binder/Parcelable.h>
@@ -28,7 +29,7 @@
public:
AudioAttributes() = default;
AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {}
- AudioAttributes(uint32_t groupId,
+ AudioAttributes(volume_group_t groupId,
audio_stream_type_t stream,
const audio_attributes_t &attributes) :
mAttributes(attributes), mStreamType(stream), mGroupId(groupId) {}
@@ -39,7 +40,7 @@
status_t writeToParcel(Parcel *parcel) const override;
audio_stream_type_t getStreamType() const { return mStreamType; }
- uint32_t getGroupId() const { return mGroupId; }
+ volume_group_t getGroupId() const { return mGroupId; }
private:
audio_attributes_t mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@@ -53,7 +54,7 @@
* @brief mGroupId: for future volume management, define groups within a strategy that follows
* the same curves of volume (extension of stream types to manage volume)
*/
- uint32_t mGroupId = 0;
+ volume_group_t mGroupId = VOLUME_GROUP_NONE;
};
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioCommonTypes.h b/media/libaudioclient/include/media/AudioCommonTypes.h
index 5188da1..8e446ea 100644
--- a/media/libaudioclient/include/media/AudioCommonTypes.h
+++ b/media/libaudioclient/include/media/AudioCommonTypes.h
@@ -27,7 +27,7 @@
const product_strategy_t PRODUCT_STRATEGY_NONE = static_cast<product_strategy_t>(-1);
using AttributesVector = std::vector<audio_attributes_t>;
-using StreamTypes = std::vector<audio_stream_type_t>;
+using StreamTypeVector = std::vector<audio_stream_type_t>;
constexpr bool operator==(const audio_attributes_t &lhs, const audio_attributes_t &rhs)
{
@@ -38,5 +38,9 @@
{
return !(lhs==rhs);
}
+
+enum volume_group_t : uint32_t;
+static const volume_group_t VOLUME_GROUP_NONE = static_cast<volume_group_t>(-1);
+
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index b9ee24a..e64f285 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -21,6 +21,7 @@
#include <media/AudioPolicy.h>
#include <media/AudioProductStrategy.h>
+#include <media/AudioVolumeGroup.h>
#include <media/AudioIoDescriptor.h>
#include <media/IAudioFlingerClient.h>
#include <media/IAudioPolicyServiceClient.h>
@@ -263,6 +264,17 @@
int *index,
audio_devices_t device);
+ static status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device);
+ static status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device);
+
+ static status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
+
+ static status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
+
static uint32_t getStrategyForStream(audio_stream_type_t stream);
static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
@@ -367,13 +379,34 @@
static bool isHapticPlaybackSupported();
static status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
- static product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa);
+ static status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
+ product_strategy_t &productStrategy);
static audio_attributes_t streamTypeToAttributes(audio_stream_type_t stream);
static audio_stream_type_t attributesToStreamType(const audio_attributes_t &attr);
+ static status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups);
+
+ static status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
+ volume_group_t &volumeGroup);
+
// ----------------------------------------------------------------------------
+ class AudioVolumeGroupCallback : public RefBase
+ {
+ public:
+
+ AudioVolumeGroupCallback() {}
+ virtual ~AudioVolumeGroupCallback() {}
+
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0;
+ virtual void onServiceDied() = 0;
+
+ };
+
+ static status_t addAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback);
+ static status_t removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback);
+
class AudioPortCallback : public RefBase
{
public:
@@ -506,12 +539,17 @@
int removeAudioPortCallback(const sp<AudioPortCallback>& callback);
bool isAudioPortCbEnabled() const { return (mAudioPortCallbacks.size() != 0); }
+ int addAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback);
+ int removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback);
+ bool isAudioVolumeGroupCbEnabled() const { return (mAudioVolumeGroupCallback.size() != 0); }
+
// DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
// IAudioPolicyServiceClient
virtual void onAudioPortListUpdate();
virtual void onAudioPatchListUpdate();
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags);
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
virtual void onRecordingConfigurationUpdate(int event,
const record_client_info_t *clientInfo,
@@ -525,6 +563,7 @@
private:
Mutex mLock;
Vector <sp <AudioPortCallback> > mAudioPortCallbacks;
+ Vector <sp <AudioVolumeGroupCallback> > mAudioVolumeGroupCallback;
};
static audio_io_handle_t getOutput(audio_stream_type_t stream);
diff --git a/media/libaudioclient/include/media/AudioVolumeGroup.h b/media/libaudioclient/include/media/AudioVolumeGroup.h
new file mode 100644
index 0000000..9a6ea07
--- /dev/null
+++ b/media/libaudioclient/include/media/AudioVolumeGroup.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 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 <media/AudioProductStrategy.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <binder/Parcelable.h>
+
+namespace android {
+
+class AudioVolumeGroup : public Parcelable
+{
+public:
+ AudioVolumeGroup() {}
+ AudioVolumeGroup(const std::string &name,
+ volume_group_t group,
+ const AttributesVector &attributes,
+ const StreamTypeVector &streams) :
+ mName(name), mGroupId(group), mAudioAttributes(attributes), mStreams(streams) {}
+
+ const std::string &getName() const { return mName; }
+ volume_group_t getId() const { return mGroupId; }
+ AttributesVector getAudioAttributes() const { return mAudioAttributes; }
+ StreamTypeVector getStreamTypes() const { return mStreams; }
+
+ status_t readFromParcel(const Parcel *parcel) override;
+ status_t writeToParcel(Parcel *parcel) const override;
+
+private:
+ std::string mName;
+ volume_group_t mGroupId = VOLUME_GROUP_NONE;
+ AttributesVector mAudioAttributes;
+ StreamTypeVector mStreams;
+};
+
+using AudioVolumeGroupVector = std::vector<AudioVolumeGroup>;
+
+} // namespace android
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index e89a55d..35540f0 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -93,6 +93,17 @@
virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
int *index,
audio_devices_t device) = 0;
+
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device) = 0;
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device) = 0;
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) = 0;
+
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) = 0;
+
virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0;
virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) = 0;
@@ -160,6 +171,8 @@
virtual void setAudioPortCallbacksEnabled(bool enabled) = 0;
+ virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled) = 0;
+
virtual status_t acquireSoundTriggerSession(audio_session_t *session,
audio_io_handle_t *ioHandle,
audio_devices_t *device) = 0;
@@ -198,7 +211,12 @@
virtual bool isHapticPlaybackSupported() = 0;
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
- virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa) = 0;
+ virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
+ product_strategy_t &productStrategy) = 0;
+
+ virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
+ virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
+ volume_group_t &volumeGroup) = 0;
};
diff --git a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
index b3c0381..79008c3 100644
--- a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
+++ b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
@@ -23,6 +23,8 @@
#include <binder/IInterface.h>
#include <system/audio.h>
#include <system/audio_effect.h>
+#include <media/AudioPolicy.h>
+#include <media/AudioVolumeGroup.h>
namespace android {
@@ -45,6 +47,8 @@
public:
DECLARE_META_INTERFACE(AudioPolicyServiceClient);
+ // Notifies a change of volume group
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0;
// Notifies a change of audio port configuration.
virtual void onAudioPortListUpdate() = 0;
// Notifies a change of audio patch configuration.
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index b0597b3..caf575c 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <common/all-versions/VersionUtils.h>
+#include <cutils/native_handle.h>
#include <hwbinder/IPCThreadState.h>
#include <media/EffectsFactoryApi.h>
#include <utils/Log.h>
@@ -280,6 +281,15 @@
return ret.isOk() ? analyzeResult(ret) : FAILED_TRANSACTION;
}
+status_t EffectHalHidl::dump(int fd) {
+ if (mEffect == 0) return NO_INIT;
+ native_handle_t* hidlHandle = native_handle_create(1, 0);
+ hidlHandle->data[0] = fd;
+ Return<void> ret = mEffect->debug(hidlHandle, {} /* options */);
+ native_handle_delete(hidlHandle);
+ return ret.isOk() ? OK : FAILED_TRANSACTION;
+}
+
status_t EffectHalHidl::getConfigImpl(
uint32_t cmdCode, uint32_t *replySize, void *pReplyData) {
if (replySize == NULL || *replySize != sizeof(effect_config_t) || pReplyData == NULL) {
diff --git a/media/libaudiohal/impl/EffectHalHidl.h b/media/libaudiohal/impl/EffectHalHidl.h
index 9d9f707..1f238c0 100644
--- a/media/libaudiohal/impl/EffectHalHidl.h
+++ b/media/libaudiohal/impl/EffectHalHidl.h
@@ -61,6 +61,8 @@
// Whether it's a local implementation.
virtual bool isLocal() const { return false; }
+ virtual status_t dump(int fd);
+
uint64_t effectId() const { return mEffectId; }
static void effectDescriptorToHal(
diff --git a/media/libaudiohal/include/media/audiohal/EffectHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectHalInterface.h
index 92622aa..03165bd 100644
--- a/media/libaudiohal/include/media/audiohal/EffectHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectHalInterface.h
@@ -55,6 +55,8 @@
// Whether it's a local implementation.
virtual bool isLocal() const = 0;
+ virtual status_t dump(int fd) = 0;
+
protected:
// Subclasses can not be constructed directly by clients.
EffectHalInterface() {}
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 5853e4b..9799cad 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -259,6 +259,7 @@
name: "libmedia_player2_util",
srcs: [
+ "AudioParameter.cpp",
"BufferingSettings.cpp",
"DataSourceDesc.cpp",
"MediaCodecBuffer.cpp",
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index cbd64bb..ea0547c 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -96,6 +96,7 @@
static const char *AMediaFormatKeyGroupInt64[] = {
AMEDIAFORMAT_KEY_DURATION,
+ AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER,
AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER,
AMEDIAFORMAT_KEY_TIME_US,
};
@@ -127,6 +128,7 @@
static const char *AMediaFormatKeyGroupFloatInt32[] = {
AMEDIAFORMAT_KEY_FRAME_RATE,
AMEDIAFORMAT_KEY_I_FRAME_INTERVAL,
+ AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER,
AMEDIAFORMAT_KEY_OPERATING_RATE,
};
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index 8dac91a..0301b21 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -415,14 +415,6 @@
OutputDeviceConverter::fromString(literalDevice, device);
}
-bool deviceToString(audio_devices_t device, std::string& literalDevice) {
- if (device & AUDIO_DEVICE_BIT_IN) {
- return InputDeviceConverter::toString(device, literalDevice);
- } else {
- return OutputDeviceConverter::toString(device, literalDevice);
- }
-}
-
SampleRateTraits::Collection samplingRatesFromString(
const std::string &samplingRates, const char *del)
{
diff --git a/media/libmedia/include/media/TypeConverter.h b/media/libmedia/include/media/TypeConverter.h
index 418e09c..3acfe98 100644
--- a/media/libmedia/include/media/TypeConverter.h
+++ b/media/libmedia/include/media/TypeConverter.h
@@ -233,8 +233,6 @@
bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);
-bool deviceToString(audio_devices_t device, std::string& literalDevice);
-
SampleRateTraits::Collection samplingRatesFromString(
const std::string &samplingRates, const char *del = AudioParameter::valueListSeparator);
@@ -255,47 +253,53 @@
OutputChannelTraits::Collection outputChannelMasksFromString(
const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);
-static inline std::string toString(audio_usage_t usage)
+// counting enumerations
+template <typename T, std::enable_if_t<std::is_same<T, audio_content_type_t>::value
+ || std::is_same<T, audio_mode_t>::value
+ || std::is_same<T, audio_source_t>::value
+ || std::is_same<T, audio_stream_type_t>::value
+ || std::is_same<T, audio_usage_t>::value
+ , int> = 0>
+static inline std::string toString(const T& value)
{
- std::string usageLiteral;
- if (!android::UsageTypeConverter::toString(usage, usageLiteral)) {
- ALOGV("failed to convert usage: %d", usage);
- return "AUDIO_USAGE_UNKNOWN";
- }
- return usageLiteral;
+ std::string result;
+ return TypeConverter<DefaultTraits<T>>::toString(value, result)
+ ? result : std::to_string(static_cast<int>(value));
+
}
-static inline std::string toString(audio_content_type_t content)
+// flag enumerations
+template <typename T, std::enable_if_t<std::is_same<T, audio_gain_mode_t>::value
+ || std::is_same<T, audio_input_flags_t>::value
+ || std::is_same<T, audio_output_flags_t>::value
+ , int> = 0>
+static inline std::string toString(const T& value)
{
- std::string contentLiteral;
- if (!android::AudioContentTypeConverter::toString(content, contentLiteral)) {
- ALOGV("failed to convert content type: %d", content);
- return "AUDIO_CONTENT_TYPE_UNKNOWN";
- }
- return contentLiteral;
+ std::string result;
+ TypeConverter<DefaultTraits<T>>::maskToString(value, result);
+ return result;
}
-static inline std::string toString(audio_stream_type_t stream)
+static inline std::string toString(const audio_devices_t& devices)
{
- std::string streamLiteral;
- if (!android::StreamTypeConverter::toString(stream, streamLiteral)) {
- ALOGV("failed to convert stream: %d", stream);
- return "AUDIO_STREAM_DEFAULT";
+ std::string result;
+ if ((devices & AUDIO_DEVICE_BIT_IN) != 0) {
+ InputDeviceConverter::maskToString(devices, result);
+ } else {
+ OutputDeviceConverter::maskToString(devices, result);
}
- return streamLiteral;
+ return result;
}
-static inline std::string toString(audio_source_t source)
+// TODO: Remove when FormatTraits uses DefaultTraits.
+static inline std::string toString(const audio_format_t& format)
{
- std::string sourceLiteral;
- if (!android::SourceTypeConverter::toString(source, sourceLiteral)) {
- ALOGV("failed to convert source: %d", source);
- return "AUDIO_SOURCE_DEFAULT";
- }
- return sourceLiteral;
+ std::string result;
+ return TypeConverter<VectorTraits<audio_format_t>>::toString(format, result)
+ ? result : std::to_string(static_cast<int>(format));
}
-static inline std::string toString(const audio_attributes_t &attributes)
+static inline std::string toString(const audio_attributes_t& attributes)
{
std::ostringstream result;
result << "{ Content type: " << toString(attributes.content_type)
@@ -308,16 +312,6 @@
return result.str();
}
-static inline std::string toString(audio_mode_t mode)
-{
- std::string modeLiteral;
- if (!android::AudioModeConverter::toString(mode, modeLiteral)) {
- ALOGV("failed to convert mode: %d", mode);
- return "AUDIO_MODE_INVALID";
- }
- return modeLiteral;
-}
-
}; // namespace android
#endif /*ANDROID_TYPE_CONVERTER_H_*/
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 22fa495..46a1c24 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -64,8 +64,6 @@
name: "libmediaplayerservice",
- compile_multilib: "32",
-
sanitize: {
cfi: true,
},
diff --git a/media/libmediaplayerservice/tests/Android.bp b/media/libmediaplayerservice/tests/Android.bp
index 4749a8b..f8c89e5 100644
--- a/media/libmediaplayerservice/tests/Android.bp
+++ b/media/libmediaplayerservice/tests/Android.bp
@@ -14,8 +14,6 @@
"android.hardware.drm@1.2",
],
- compile_multilib: "32",
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 9d3338b..1dee4f7 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -37,6 +37,7 @@
#include <media/stagefright/BufferProducerWrapper.h>
#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/PersistentSurface.h>
@@ -1817,20 +1818,19 @@
}
if (!msg->findInt64(
- "repeat-previous-frame-after",
- &mRepeatFrameDelayUs)) {
+ KEY_REPEAT_PREVIOUS_FRAME_AFTER, &mRepeatFrameDelayUs)) {
mRepeatFrameDelayUs = -1LL;
}
// only allow 32-bit value, since we pass it as U32 to OMX.
- if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
+ if (!msg->findInt64(KEY_MAX_PTS_GAP_TO_ENCODER, &mMaxPtsGapUs)) {
mMaxPtsGapUs = 0LL;
} else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < INT32_MIN) {
ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
mMaxPtsGapUs = 0LL;
}
- if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
+ if (!msg->findFloat(KEY_MAX_FPS_TO_ENCODER, &mMaxFps)) {
mMaxFps = -1;
}
@@ -1844,8 +1844,8 @@
}
if (!msg->findInt32(
- "create-input-buffers-suspended",
- (int32_t*)&mCreateInputBuffersSuspended)) {
+ KEY_CREATE_INPUT_SURFACE_SUSPENDED,
+ (int32_t*)&mCreateInputBuffersSuspended)) {
mCreateInputBuffersSuspended = false;
}
}
@@ -7431,7 +7431,7 @@
}
int64_t timeOffsetUs;
- if (params->findInt64("time-offset-us", &timeOffsetUs)) {
+ if (params->findInt64(PARAMETER_KEY_OFFSET_TIME, &timeOffsetUs)) {
if (mGraphicBufferSource == NULL) {
ALOGE("[%s] Invalid to set input buffer time offset without surface",
mComponentName.c_str());
@@ -7467,7 +7467,7 @@
}
int32_t dropInputFrames;
- if (params->findInt32("drop-input-frames", &dropInputFrames)) {
+ if (params->findInt32(PARAMETER_KEY_SUSPEND, &dropInputFrames)) {
if (mGraphicBufferSource == NULL) {
ALOGE("[%s] Invalid to set suspend without surface",
mComponentName.c_str());
@@ -7475,7 +7475,7 @@
}
int64_t suspendStartTimeUs = -1;
- (void) params->findInt64("drop-start-time-us", &suspendStartTimeUs);
+ (void) params->findInt64(PARAMETER_KEY_SUSPEND_TIME, &suspendStartTimeUs);
status_t err = statusFromBinderStatus(
mGraphicBufferSource->setSuspend(dropInputFrames != 0, suspendStartTimeUs));
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 488890d..2bd7288 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -265,9 +265,11 @@
srcs: [
"ClearFileSource.cpp",
"DataURISource.cpp",
+ "DataSourceBase.cpp",
"HTTPBase.cpp",
"HevcUtils.cpp",
"MediaClock.cpp",
+ "MediaSource.cpp",
"NdkUtils.cpp",
"Utils.cpp",
"VideoFrameSchedulerBase.cpp",
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 5d2291f..c3d85ee 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -32,6 +32,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaCodecSource.h>
#include <media/stagefright/MediaErrors.h>
@@ -362,7 +363,7 @@
status_t MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
sp<AMessage> msg = new AMessage(kWhatSetInputBufferTimeOffset, mReflector);
- msg->setInt64("time-offset-us", timeOffsetUs);
+ msg->setInt64(PARAMETER_KEY_OFFSET_TIME, timeOffsetUs);
return postSynchronouslyAndReturnError(msg);
}
@@ -490,7 +491,7 @@
mCodecLooper->start();
if (mFlags & FLAG_USE_SURFACE_INPUT) {
- mOutputFormat->setInt32("create-input-buffers-suspended", 1);
+ mOutputFormat->setInt32(KEY_CREATE_INPUT_SURFACE_SUSPENDED, 1);
}
AString outputMIME;
@@ -677,9 +678,9 @@
CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
if (mEncoder != NULL) {
sp<AMessage> params = new AMessage;
- params->setInt32("drop-input-frames", false);
+ params->setInt32(PARAMETER_KEY_SUSPEND, false);
if (resumeStartTimeUs > 0) {
- params->setInt64("drop-start-time-us", resumeStartTimeUs);
+ params->setInt64(PARAMETER_KEY_SUSPEND_TIME, resumeStartTimeUs);
}
mEncoder->setParameters(params);
}
@@ -799,7 +800,7 @@
if (mFlags & FLAG_USE_SURFACE_INPUT) {
if (mEncoder != NULL) {
sp<AMessage> params = new AMessage;
- params->setInt32("drop-input-frames", false);
+ params->setInt32(PARAMETER_KEY_SUSPEND, false);
if (startTimeUs >= 0) {
params->setInt64("skip-frames-before", startTimeUs);
}
@@ -832,8 +833,8 @@
void MediaCodecSource::onPause(int64_t pauseStartTimeUs) {
if ((mFlags & FLAG_USE_SURFACE_INPUT) && (mEncoder != NULL)) {
sp<AMessage> params = new AMessage;
- params->setInt32("drop-input-frames", true);
- params->setInt64("drop-start-time-us", pauseStartTimeUs);
+ params->setInt32(PARAMETER_KEY_SUSPEND, true);
+ params->setInt64(PARAMETER_KEY_SUSPEND_TIME, pauseStartTimeUs);
mEncoder->setParameters(params);
} else {
CHECK(mPuller != NULL);
@@ -1096,12 +1097,12 @@
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
status_t err = OK;
- CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs));
+ CHECK(msg->findInt64(PARAMETER_KEY_OFFSET_TIME, &mInputBufferTimeOffsetUs));
// Propagate the timestamp offset to GraphicBufferSource.
if (mFlags & FLAG_USE_SURFACE_INPUT) {
sp<AMessage> params = new AMessage;
- params->setInt64("time-offset-us", mInputBufferTimeOffsetUs);
+ params->setInt64(PARAMETER_KEY_OFFSET_TIME, mInputBufferTimeOffsetUs);
err = mEncoder->setParameters(params);
}
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index a938d51..a309ee4 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -23,8 +23,6 @@
#include <binder/PermissionCache.h>
#include <binder/IServiceManager.h>
#include <media/DataSource.h>
-#include <media/MediaAnalyticsItem.h>
-#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaExtractorFactory.h>
@@ -34,7 +32,6 @@
#include <private/android_filesystem_config.h>
#include <cutils/properties.h>
#include <utils/String8.h>
-#include <ziparchive/zip_archive.h>
#include <dirent.h>
#include <dlfcn.h>
@@ -130,13 +127,6 @@
std::shared_ptr<std::list<sp<ExtractorPlugin>>> MediaExtractorFactory::gPlugins;
bool MediaExtractorFactory::gPluginsRegistered = false;
bool MediaExtractorFactory::gIgnoreVersion = false;
-std::string MediaExtractorFactory::gLinkedLibraries;
-
-// static
-void MediaExtractorFactory::SetLinkedLibraries(const std::string& linkedLibraries) {
- Mutex::Autolock autoLock(gPluginMutex);
- gLinkedLibraries = linkedLibraries;
-}
// static
void *MediaExtractorFactory::sniff(
@@ -235,9 +225,11 @@
}
//static
-void MediaExtractorFactory::RegisterExtractorsInSystem(
- const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList) {
+void MediaExtractorFactory::RegisterExtractors(
+ const char *libDirPath, const android_dlextinfo* dlextinfo,
+ std::list<sp<ExtractorPlugin>> &pluginList) {
ALOGV("search for plugins at %s", libDirPath);
+
DIR *libDir = opendir(libDirPath);
if (libDir) {
struct dirent* libEntry;
@@ -246,73 +238,12 @@
continue;
}
String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
- void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
- if (libHandle) {
- GetExtractorDef getDef =
- (GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
- if (getDef) {
- ALOGV("registering sniffer for %s", libPath.string());
- RegisterExtractor(
- new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
- } else {
- ALOGW("%s does not contain sniffer", libPath.string());
- dlclose(libHandle);
- }
- } else {
- ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
- }
- }
-
- closedir(libDir);
- } else {
- ALOGE("couldn't opendir(%s)", libDirPath);
- }
-}
-
-//static
-void MediaExtractorFactory::RegisterExtractorsInApex(
- const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList) {
- ALOGV("search for plugins at %s", libDirPath);
- ALOGV("linked libs %s", gLinkedLibraries.c_str());
-
- std::string libDirPathEx = libDirPath;
- libDirPathEx += "/extractors";
- android_namespace_t *extractorNs = android_create_namespace("extractor",
- nullptr, // ld_library_path
- libDirPath, // default_library_path
- ANDROID_NAMESPACE_TYPE_ISOLATED,
- libDirPathEx.c_str(), // permitted_when_isolated_path
- nullptr); // parent
- if (!android_link_namespaces(extractorNs, nullptr, gLinkedLibraries.c_str())) {
- ALOGE("Failed to link namespace. Failed to load extractor plug-ins in apex.");
- return;
- }
- const android_dlextinfo dlextinfo = {
- .flags = ANDROID_DLEXT_USE_NAMESPACE,
- .library_namespace = extractorNs,
- };
-
- // try extractors subfolder first
- DIR *libDir = opendir(libDirPathEx.c_str());
-
- if (libDir) {
- libDirPath = libDirPathEx.c_str();
- } else {
- libDir = opendir(libDirPath);
- }
- if (libDir) {
- struct dirent* libEntry;
- while ((libEntry = readdir(libDir))) {
- if (libEntry->d_name[0] == '.') {
- continue;
- }
- String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
if (!libPath.contains("extractor.so")) {
continue;
}
void *libHandle = android_dlopen_ext(
libPath.string(),
- RTLD_NOW | RTLD_LOCAL, &dlextinfo);
+ RTLD_NOW | RTLD_LOCAL, dlextinfo);
if (libHandle) {
GetExtractorDef getDef =
(GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
@@ -352,17 +283,27 @@
std::shared_ptr<std::list<sp<ExtractorPlugin>>> newList(new std::list<sp<ExtractorPlugin>>());
- RegisterExtractorsInApex("/apex/com.android.media/lib"
+ android_namespace_t *mediaNs = android_get_exported_namespace("media");
+ if (mediaNs != NULL) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = mediaNs,
+ };
+ RegisterExtractors("/apex/com.android.media/lib"
#ifdef __LP64__
- "64"
+ "64"
#endif
- , *newList);
+ "/extractors", &dlextinfo, *newList);
- RegisterExtractorsInSystem("/system/lib"
+ } else {
+ ALOGE("couldn't find media namespace.");
+ }
+
+ RegisterExtractors("/system/lib"
#ifdef __LP64__
"64"
#endif
- "/extractors", *newList);
+ "/extractors", NULL, *newList);
newList->sort(compareFunc);
gPlugins = newList;
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 4358aac..ea87948 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <unordered_set>
+#include <android/dlext.h>
#include <media/IMediaExtractor.h>
namespace android {
@@ -36,19 +37,16 @@
const sp<DataSource> &source, const char *mime = NULL);
static status_t dump(int fd, const Vector<String16>& args);
static std::unordered_set<std::string> getSupportedTypes();
- static void SetLinkedLibraries(const std::string& linkedLibraries);
private:
static Mutex gPluginMutex;
static std::shared_ptr<std::list<sp<ExtractorPlugin>>> gPlugins;
static bool gPluginsRegistered;
static bool gIgnoreVersion;
- static std::string gLinkedLibraries;
- static void RegisterExtractorsInSystem(
- const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList);
- static void RegisterExtractorsInApex(
- const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList);
+ static void RegisterExtractors(
+ const char *libDirPath, const android_dlextinfo* dlextinfo,
+ std::list<sp<ExtractorPlugin>> &pluginList);
static void RegisterExtractor(
const sp<ExtractorPlugin> &plugin, std::list<sp<ExtractorPlugin>> &pluginList);
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 16c7be9..f01947a 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -21,7 +21,6 @@
"libutils",
"libbinder",
"libandroidicu",
- "android.hardware.media.omx@1.0",
],
static_libs: [
@@ -34,8 +33,6 @@
"frameworks/av/services/mediaresourcemanager",
],
- compile_multilib: "32",
-
init_rc: ["mediaserver.rc"],
cflags: [
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index ad3c068..bd6a6c6 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -47,6 +47,9 @@
constexpr unsigned MAX_FILE_CHUNK_SIZE = AIO_BUFS_MAX * AIO_BUF_LEN;
constexpr uint32_t MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
+// Note: POLL_TIMEOUT_MS = 0 means return immediately i.e. no sleep.
+// And this will cause high CPU usage.
+constexpr int32_t POLL_TIMEOUT_MS = 500;
struct timespec ZERO_TIMEOUT = { 0, 0 };
@@ -305,7 +308,7 @@
int error = 0;
while (num_events < min_events) {
- if (poll(mPollFds, 2, 0) == -1) {
+ if (poll(mPollFds, 2, POLL_TIMEOUT_MS) == -1) {
PLOG(ERROR) << "Mtp error during poll()";
return -1;
}
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index a9254c7..0b274a7 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -76,7 +76,7 @@
"libbinder",
"libmedia",
"libmedia_omx",
- "libmedia_jni",
+ "libmedia_jni_utils",
"libmediadrm",
"libstagefright",
"libstagefright_foundation",
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 20b1667..1883f63 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -23,7 +23,7 @@
#include "NdkImageReaderPriv.h"
#include <android_media_Utils.h>
-#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <private/android/AHardwareBufferHelpers.h>
#include <utils/Log.h>
#include "hardware/camera3.h"
@@ -190,7 +190,7 @@
auto lockedBuffer = std::make_unique<CpuConsumer::LockedBuffer>();
- uint64_t grallocUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(mUsage);
+ uint64_t grallocUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
status_t ret =
lockImageFromBuffer(mBuffer, grallocUsage, mBuffer->mFence->dup(), lockedBuffer.get());
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index c3eb437..b010aa9 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -26,7 +26,7 @@
#include <utils/Log.h>
#include <android_media_Utils.h>
#include <android_runtime/android_view_Surface.h>
-#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <private/android/AHardwareBufferHelpers.h>
#include <grallocusage/GrallocUsageConversion.h>
#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
@@ -70,6 +70,7 @@
case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
case AIMAGE_FORMAT_Y8:
case AIMAGE_FORMAT_HEIC:
+ case AIMAGE_FORMAT_DEPTH_JPEG:
return true;
case AIMAGE_FORMAT_PRIVATE:
// For private format, cpu usage is prohibited.
@@ -98,6 +99,7 @@
case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
case AIMAGE_FORMAT_Y8:
case AIMAGE_FORMAT_HEIC:
+ case AIMAGE_FORMAT_DEPTH_JPEG:
return 1;
case AIMAGE_FORMAT_PRIVATE:
return 0;
@@ -272,7 +274,7 @@
PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
mHalFormat = android_view_Surface_mapPublicFormatToHalFormat(publicFormat);
mHalDataSpace = android_view_Surface_mapPublicFormatToHalDataspace(publicFormat);
- mHalUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(mUsage);
+ mHalUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
sp<IGraphicBufferProducer> gbProducer;
sp<IGraphicBufferConsumer> gbConsumer;
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 26a6238..7cc7f16 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -344,8 +344,10 @@
EXPORT const char* AMEDIAFORMAT_KEY_LYRICIST = "lyricist";
EXPORT const char* AMEDIAFORMAT_KEY_MANUFACTURER = "manufacturer";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_BIT_RATE = "max-bitrate";
+EXPORT const char* AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_HEIGHT = "max-height";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size";
+EXPORT const char* AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER = "max-pts-gap-to-encoder";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width";
EXPORT const char* AMEDIAFORMAT_KEY_MIME = "mime";
EXPORT const char* AMEDIAFORMAT_KEY_MPEG_USER_DATA = "mpeg-user-data";
diff --git a/media/ndk/include/media/NdkImage.h b/media/ndk/include/media/NdkImage.h
index 14d88cb..3e60de0 100644
--- a/media/ndk/include/media/NdkImage.h
+++ b/media/ndk/include/media/NdkImage.h
@@ -535,6 +535,15 @@
* Format as described in ISO/IEC 23008-12.</p>
*/
AIMAGE_FORMAT_HEIC = 0x48454946,
+
+ /**
+ * Depth augmented compressed JPEG format.
+ *
+ * <p>JPEG compressed main image along with XMP embedded depth metadata
+ * following ISO 16684-1:2011(E).</p>
+ */
+ AIMAGE_FORMAT_DEPTH_JPEG = 0x69656963,
+
};
/**
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index ddf5291..56bcaab 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -216,6 +216,8 @@
extern const char* AMEDIAFORMAT_KEY_LYRICIST __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_MANUFACTURER __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_MAX_BIT_RATE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_MPEG2_STREAM_HEADER __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_PSSH __INTRODUCED_IN(29);
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 7bdd3ad..9756926 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -107,8 +107,10 @@
AMEDIAFORMAT_KEY_LYRICIST; # var introduced=29
AMEDIAFORMAT_KEY_MANUFACTURER; # var introduced=29
AMEDIAFORMAT_KEY_MAX_BIT_RATE; # var introduced=29
+ AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER; # var introduced=29
AMEDIAFORMAT_KEY_MAX_HEIGHT; # var introduced=21
AMEDIAFORMAT_KEY_MAX_INPUT_SIZE; # var introduced=21
+ AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER; # var introduced=29
AMEDIAFORMAT_KEY_MAX_WIDTH; # var introduced=21
AMEDIAFORMAT_KEY_MIME; # var introduced=21
AMEDIAFORMAT_KEY_MPEG_USER_DATA; # var introduced=28
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 8455e54..ecaeb52 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1500,6 +1500,11 @@
write(fd, result.string(), result.length());
+ if (mEffectInterface != 0) {
+ dprintf(fd, "\tEffect ID %d HAL dump:\n", mId);
+ (void)mEffectInterface->dump(fd);
+ }
+
if (locked) {
mLock.unlock();
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ff33957..8a45fc2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -457,52 +457,6 @@
}
}
-std::string devicesToString(audio_devices_t devices)
-{
- std::string result;
- if (devices & AUDIO_DEVICE_BIT_IN) {
- InputDeviceConverter::maskToString(devices, result);
- } else {
- OutputDeviceConverter::maskToString(devices, result);
- }
- return result;
-}
-
-std::string inputFlagsToString(audio_input_flags_t flags)
-{
- std::string result;
- InputFlagConverter::maskToString(flags, result);
- return result;
-}
-
-std::string outputFlagsToString(audio_output_flags_t flags)
-{
- std::string result;
- OutputFlagConverter::maskToString(flags, result);
- return result;
-}
-
-const char *sourceToString(audio_source_t source)
-{
- switch (source) {
- case AUDIO_SOURCE_DEFAULT: return "default";
- case AUDIO_SOURCE_MIC: return "mic";
- case AUDIO_SOURCE_VOICE_UPLINK: return "voice uplink";
- case AUDIO_SOURCE_VOICE_DOWNLINK: return "voice downlink";
- case AUDIO_SOURCE_VOICE_CALL: return "voice call";
- case AUDIO_SOURCE_CAMCORDER: return "camcorder";
- case AUDIO_SOURCE_VOICE_RECOGNITION: return "voice recognition";
- case AUDIO_SOURCE_VOICE_COMMUNICATION: return "voice communication";
- case AUDIO_SOURCE_REMOTE_SUBMIX: return "remote submix";
- case AUDIO_SOURCE_UNPROCESSED: return "unprocessed";
- case AUDIO_SOURCE_VOICE_PERFORMANCE: return "voice performance";
- case AUDIO_SOURCE_ECHO_REFERENCE: return "echo reference";
- case AUDIO_SOURCE_FM_TUNER: return "FM tuner";
- case AUDIO_SOURCE_HOTWORD: return "hotword";
- default: return "unknown";
- }
-}
-
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
audio_devices_t outDevice, audio_devices_t inDevice, type_t type, bool systemReady)
: Thread(false /*canCallJava*/),
@@ -717,8 +671,8 @@
event->mStatus = createAudioPatch_l(&data->mPatch, &data->mHandle);
const audio_devices_t newDevice = getDevice();
mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %#x (%s) new device %#x (%s)",
- (unsigned)oldDevice, devicesToString(oldDevice).c_str(),
- (unsigned)newDevice, devicesToString(newDevice).c_str());
+ (unsigned)oldDevice, toString(oldDevice).c_str(),
+ (unsigned)newDevice, toString(newDevice).c_str());
} break;
case CFG_EVENT_RELEASE_AUDIO_PATCH: {
const audio_devices_t oldDevice = getDevice();
@@ -727,8 +681,8 @@
event->mStatus = releaseAudioPatch_l(data->mHandle);
const audio_devices_t newDevice = getDevice();
mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %#x (%s) new device %#x (%s)",
- (unsigned)oldDevice, devicesToString(oldDevice).c_str(),
- (unsigned)newDevice, devicesToString(newDevice).c_str());
+ (unsigned)oldDevice, toString(oldDevice).c_str(),
+ (unsigned)newDevice, toString(newDevice).c_str());
} break;
default:
ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType);
@@ -858,9 +812,9 @@
dprintf(fd, " none\n");
}
// Note: output device may be used by capture threads for effects such as AEC.
- dprintf(fd, " Output device: %#x (%s)\n", mOutDevice, devicesToString(mOutDevice).c_str());
- dprintf(fd, " Input device: %#x (%s)\n", mInDevice, devicesToString(mInDevice).c_str());
- dprintf(fd, " Audio source: %d (%s)\n", mAudioSource, sourceToString(mAudioSource));
+ dprintf(fd, " Output device: %#x (%s)\n", mOutDevice, toString(mOutDevice).c_str());
+ dprintf(fd, " Input device: %#x (%s)\n", mInDevice, toString(mInDevice).c_str());
+ dprintf(fd, " Audio source: %d (%s)\n", mAudioSource, toString(mAudioSource).c_str());
// Dump timestamp statistics for the Thread types that support it.
if (mType == RECORD
@@ -1885,7 +1839,7 @@
AudioStreamOut *output = mOutput;
audio_output_flags_t flags = output != NULL ? output->flags : AUDIO_OUTPUT_FLAG_NONE;
dprintf(fd, " AudioStreamOut: %p flags %#x (%s)\n",
- output, flags, outputFlagsToString(flags).c_str());
+ output, flags, toString(flags).c_str());
dprintf(fd, " Frames written: %lld\n", (long long)mFramesWritten);
dprintf(fd, " Suspended frames: %lld\n", (long long)mSuspendedFrames);
if (mPipeSink.get() != nullptr) {
@@ -7769,7 +7723,7 @@
AudioStreamIn *input = mInput;
audio_input_flags_t flags = input != NULL ? input->flags : AUDIO_INPUT_FLAG_NONE;
dprintf(fd, " AudioStreamIn: %p flags %#x (%s)\n",
- input, flags, inputFlagsToString(flags).c_str());
+ input, flags, toString(flags).c_str());
dprintf(fd, " Frames read: %lld\n", (long long)mFramesRead);
if (mActiveTracks.isEmpty()) {
dprintf(fd, " No active record clients\n");
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index bb5441d..d61188f 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -159,6 +159,19 @@
int *index,
audio_devices_t device) = 0;
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device) = 0;
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device) = 0;
+
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index) = 0;
+
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index) = 0;
+
// return the strategy corresponding to a given stream type
virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
@@ -244,7 +257,13 @@
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
- virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa) = 0;
+ virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
+ product_strategy_t &productStrategy) = 0;
+
+ virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
+
+ virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
+ volume_group_t &volumeGroup) = 0;
};
@@ -341,6 +360,8 @@
virtual void onAudioPatchListUpdate() = 0;
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0;
+
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0;
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index a3b6b36..48b5271 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -21,6 +21,7 @@
#include <math.h>
namespace android {
+
/**
* VolumeSource is the discriminent for volume management on an output.
* It used to be the stream type by legacy, it may be host volume group or a volume curves if
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
index 93022fb..d408446 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
@@ -38,6 +38,8 @@
virtual float volIndexToDb(device_category device, int indexInUi) const = 0;
virtual bool hasVolumeIndexForDevice(audio_devices_t device) const = 0;
virtual status_t initVolume(int indexMin, int indexMax) = 0;
+ virtual std::vector<audio_attributes_t> getAttributes() const = 0;
+ virtual std::vector<audio_stream_type_t> getStreamTypes() const = 0;
virtual void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const = 0;
};
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
index cd1c2f2..3a4db90 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -41,9 +41,7 @@
const audio_port_config &cfg = cfgs[i];
dst->appendFormat("%*s [%s %d] ", spaces, "", prefix, i + 1);
if (cfg.type == AUDIO_PORT_TYPE_DEVICE) {
- std::string device;
- deviceToString(cfg.ext.device.type, device);
- dst->appendFormat("Device ID %d %s", cfg.id, device.c_str());
+ dst->appendFormat("Device ID %d %s", cfg.id, toString(cfg.ext.device.type).c_str());
} else {
dst->appendFormat("Mix ID %d I/O handle %d", cfg.id, cfg.ext.mix.handle);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 2c4695d..23d764e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -66,9 +66,7 @@
RouteFlagTypeConverter::maskToString(mMix.mRouteFlags, routeFlagLiteral);
dst->appendFormat("%*s- Route Flags: %s\n", spaces, "", routeFlagLiteral.c_str());
- std::string deviceLiteral;
- deviceToString(mMix.mDeviceType, deviceLiteral);
- dst->appendFormat("%*s- device type: %s\n", spaces, "", deviceLiteral.c_str());
+ dst->appendFormat("%*s- device type: %s\n", spaces, "", toString(mMix.mDeviceType).c_str());
dst->appendFormat("%*s- device address: %s\n", spaces, "", mMix.mDeviceAddress.string());
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index a3121d1..91961d0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <audio_utils/string.h>
+#include <media/TypeConverter.h>
#include <set>
#include "DeviceDescriptor.h"
#include "TypeConverter.h"
@@ -346,10 +347,9 @@
if (!mTagName.isEmpty()) {
dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.string());
}
- std::string deviceLiteral;
- if (deviceToString(mDeviceType, deviceLiteral)) {
- dst->appendFormat("%*s- type: %-48s\n", spaces, "", deviceLiteral.c_str());
- }
+
+ dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str());
+
if (mAddress.size() != 0) {
dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string());
}
@@ -401,9 +401,8 @@
void DeviceDescriptor::log() const
{
- std::string device;
- deviceToString(mDeviceType, device);
- ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceType, device.c_str(),
+ ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceType,
+ ::android::toString(mDeviceType).c_str(),
mAddress.string());
AudioPort::log(" ");
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index e0b233d..ec7ff57 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -341,7 +341,7 @@
}
}
if (!allowToCreate) {
- ALOGE("%s: could not find HW module for device %s %04x address %s", __FUNCTION__,
+ ALOGV("%s: could not find HW module for device %s %04x address %s", __FUNCTION__,
name, deviceType, address);
return nullptr;
}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index bc027e2..6ff8512 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -19,7 +19,7 @@
#include <EngineConfig.h>
#include <AudioPolicyManagerInterface.h>
#include <ProductStrategy.h>
-#include <StreamVolumeCurves.h>
+#include <VolumeGroup.h>
namespace android {
namespace audio_policy {
@@ -68,9 +68,27 @@
status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) const override;
- VolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) override;
+ VolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) const override;
- VolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) override;
+ VolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) const override;
+
+ IVolumeCurves *getVolumeCurvesForVolumeGroup(volume_group_t group) const override
+ {
+ return mVolumeGroups.find(group) != end(mVolumeGroups) ?
+ mVolumeGroups.at(group)->getVolumeCurves() : nullptr;
+ }
+
+ VolumeGroupVector getVolumeGroups() const override;
+
+ volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const override;
+
+ volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const override;
+
+ StreamTypeVector getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const override;
+
+ AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const override;
+
+ status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const override;
void dump(String8 *dst) const override;
@@ -105,12 +123,11 @@
AudioPolicyManagerObserver *mApmObserver = nullptr;
ProductStrategyMap mProductStrategies;
+ VolumeGroupMap mVolumeGroups;
audio_mode_t mPhoneState = AUDIO_MODE_NORMAL; /**< current phone state. */
/** current forced use configuration. */
audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT] = {};
-
- StreamVolumeCurves mStreamVolumeCurves;
};
} // namespace audio_policy
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 72505b2..767a8ed 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -16,6 +16,8 @@
#pragma once
+#include "VolumeGroup.h"
+
#include <system/audio.h>
#include <AudioPolicyManagerInterface.h>
#include <utils/RefBase.h>
@@ -38,7 +40,7 @@
private:
struct AudioAttributes {
audio_stream_type_t mStream = AUDIO_STREAM_DEFAULT;
- uint32_t mGroupId = 0;
+ volume_group_t mVolumeGroup = VOLUME_GROUP_NONE;
audio_attributes_t mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
};
@@ -85,6 +87,12 @@
audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
+ volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
+
+ volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
+
+ volume_group_t getDefaultVolumeGroup() const;
+
bool isDefault() const;
void dump(String8 *dst, int spaces = 0) const;
@@ -108,6 +116,10 @@
{
public:
/**
+ * @brief initialize: set default product strategy in cache.
+ */
+ void initialize();
+ /**
* @brief getProductStrategyForAttribute. The order of the vector is dimensionning.
* @param attr
* @return applicable product strategy for the given attribute, default if none applicable.
@@ -136,9 +148,16 @@
std::string getDeviceAddressForProductStrategy(product_strategy_t strategy) const;
+ volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
+
+ volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
+
product_strategy_t getDefault() const;
void dump(String8 *dst, int spaces = 0) const;
+
+private:
+ product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
};
} // namespace android
diff --git a/services/audiopolicy/engine/common/include/StreamVolumeCurves.h b/services/audiopolicy/engine/common/include/StreamVolumeCurves.h
deleted file mode 100644
index 5b0b7d6..0000000
--- a/services/audiopolicy/engine/common/include/StreamVolumeCurves.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2018 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 <VolumeCurve.h>
-#include <map>
-
-namespace android {
-
-class StreamVolumeCurves
-{
-public:
- StreamVolumeCurves() = default;
-
- /**
- * @brief switchVolumeCurve control API for Engine, allows to switch the volume curves
- * from one stream type to another.
- * @param src source stream type
- * @param dst destination stream type
- */
- status_t switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst)
- {
- if (!hasCurvesFor(streamSrc) || !hasCurvesFor(streamDst)) {
- ALOGE("%s: No curves defined for streams %d %d", __FUNCTION__, streamSrc, streamDst);
- return NO_INIT;
- }
- const VolumeCurves &sourceCurves = getCurvesFor(streamSrc);
- VolumeCurves &dstCurves = editCurvesFor(streamDst);
- return dstCurves.switchCurvesFrom(sourceCurves);
- }
- void dump(String8 *dst, int spaces = 0) const;
-
- void add(const VolumeCurves &curves, audio_stream_type_t streamType)
- {
- mCurves.emplace(streamType, curves);
- }
-
- bool hasCurvesFor(audio_stream_type_t stream)
- {
- return mCurves.find(stream) != end(mCurves);
- }
-
- VolumeCurves &editCurvesFor(audio_stream_type_t stream)
- {
- ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
- return mCurves[stream];
- }
- const VolumeCurves &getCurvesFor(audio_stream_type_t stream) const
- {
- ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
- return mCurves.at(stream);
- }
- /**
- * @brief getVolumeCurvesForStream
- * @param stream type for which the volume curves interface is requested
- * @return the VolumeCurves for a given stream type.
- */
- VolumeCurves &getVolumeCurvesForStream(audio_stream_type_t stream)
- {
- ALOG_ASSERT(mCurves.find(stream) != end(mCurves), "Invalid stream type for Volume Curve");
- return mCurves[stream];
- }
- /**
- * @brief restoreOriginVolumeCurve helper control API for engine to restore the original volume
- * curves for a given stream type
- * @param stream for which the volume curves will be restored.
- */
- status_t restoreOriginVolumeCurve(audio_stream_type_t stream)
- {
- if (!hasCurvesFor(stream)) {
- ALOGE("%s: No curves defined for streams", __FUNCTION__);
- return NO_INIT;
- }
- return switchVolumeCurve(stream, stream);
- }
-
-private:
- std::map<audio_stream_type_t, VolumeCurves> mCurves;
-};
-
-} // namespace android
diff --git a/services/audiopolicy/engine/common/include/VolumeCurve.h b/services/audiopolicy/engine/common/include/VolumeCurve.h
index 0ec63e1..54314e3 100644
--- a/services/audiopolicy/engine/common/include/VolumeCurve.h
+++ b/services/audiopolicy/engine/common/include/VolumeCurve.h
@@ -18,7 +18,9 @@
#include "IVolumeCurves.h"
#include <policy.h>
+#include <AudioPolicyManagerInterface.h>
#include <utils/RefBase.h>
+#include <HandleGenerator.h>
#include <utils/String8.h>
#include <utils/SortedVector.h>
#include <utils/KeyedVector.h>
@@ -71,18 +73,11 @@
{
public:
VolumeCurves(int indexMin = 0, int indexMax = 100) :
- mIndexMin(indexMin), mIndexMax(indexMax), mStream(AUDIO_STREAM_DEFAULT)
+ mIndexMin(indexMin), mIndexMax(indexMax)
{
addCurrentVolumeIndex(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, 0);
}
- VolumeCurves(audio_stream_type_t stream, int indexMin, int indexMax) :
- mIndexMin(indexMin), mIndexMax(indexMax), mStream(stream)
- {
- addCurrentVolumeIndex(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, 0);
- }
-
- // Once XML has been parsed, must be call first to sanity check table and initialize indexes
- virtual status_t initVolume(int indexMin, int indexMax)
+ status_t initVolume(int indexMin, int indexMax) override
{
mIndexMin = indexMin;
mIndexMax = indexMax;
@@ -174,8 +169,16 @@
return 0.0f;
}
}
-
- audio_stream_type_t getStreamType() const { return mStream; }
+ void addAttributes(const audio_attributes_t &attr)
+ {
+ mAttributes.push_back(attr);
+ }
+ AttributesVector getAttributes() const override { return mAttributes; }
+ void addStreamType(audio_stream_type_t stream)
+ {
+ mStreams.push_back(stream);
+ }
+ StreamTypeVector getStreamTypes() const override { return mStreams; }
void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const override;
@@ -186,7 +189,8 @@
int mIndexMax; /**< max volume index. */
const bool mCanBeMuted = true; /**< true is the stream can be muted. */
- const audio_stream_type_t mStream; /**< Keep it for legacy. */
+ AttributesVector mAttributes;
+ StreamTypeVector mStreams; /**< Keep it for legacy. */
};
} // namespace android
diff --git a/services/audiopolicy/engine/common/include/VolumeGroup.h b/services/audiopolicy/engine/common/include/VolumeGroup.h
new file mode 100644
index 0000000..c34b406
--- /dev/null
+++ b/services/audiopolicy/engine/common/include/VolumeGroup.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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 <AudioPolicyManagerInterface.h>
+#include <VolumeCurve.h>
+#include <system/audio.h>
+#include <utils/RefBase.h>
+#include <HandleGenerator.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <utils/Errors.h>
+
+namespace android {
+
+class VolumeGroup : public virtual RefBase, private HandleGenerator<uint32_t>
+{
+public:
+ VolumeGroup(const std::string &name, int indexMin, int indexMax);
+ std::string getName() const { return mName; }
+ volume_group_t getId() const { return mId; }
+
+ void add(const sp<VolumeCurve> &curve);
+
+ VolumeCurves *getVolumeCurves() { return &mGroupVolumeCurves; }
+
+ void addSupportedAttributes(const audio_attributes_t &attr);
+ AttributesVector getSupportedAttributes() const { return mGroupVolumeCurves.getAttributes(); }
+
+ void addSupportedStream(audio_stream_type_t stream);
+ StreamTypeVector getStreamTypes() const { return mGroupVolumeCurves.getStreamTypes(); }
+
+ void dump(String8 *dst, int spaces = 0) const;
+
+private:
+ const std::string mName;
+ const volume_group_t mId;
+ VolumeCurves mGroupVolumeCurves;
+};
+
+class VolumeGroupMap : public std::map<volume_group_t, sp<VolumeGroup> >
+{
+public:
+ void dump(String8 *dst, int spaces = 0) const;
+};
+
+} // namespace android
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 6e2ab4c..4fe7b42 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "APM::AudioPolicyEngine/Base"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include "EngineBase.h"
#include "EngineDefaultConfig.h"
@@ -96,46 +96,47 @@
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
{
auto loadProductStrategies =
- [](auto& strategyConfigs, auto& productStrategies) {
- uint32_t groupid = 0;
+ [](auto& strategyConfigs, auto& productStrategies, auto& volumeGroups) {
for (auto& strategyConfig : strategyConfigs) {
sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
for (const auto &group : strategyConfig.attributesGroups) {
- for (const auto &attr : group.attributesVect) {
- strategy->addAttributes({group.stream, groupid, attr});
+ const auto &iter = std::find_if(begin(volumeGroups), end(volumeGroups),
+ [&group](const auto &volumeGroup) {
+ return group.volumeGroup == volumeGroup.second->getName(); });
+ ALOG_ASSERT(iter != end(volumeGroups), "Invalid Volume Group Name %s",
+ group.volumeGroup.c_str());
+ if (group.stream != AUDIO_STREAM_DEFAULT) {
+ iter->second->addSupportedStream(group.stream);
}
- groupid += 1;
+ for (const auto &attr : group.attributesVect) {
+ strategy->addAttributes({group.stream, iter->second->getId(), attr});
+ iter->second->addSupportedAttributes(attr);
+ }
}
product_strategy_t strategyId = strategy->getId();
productStrategies[strategyId] = strategy;
}
};
- auto loadVolumeCurves = [](const auto &configVolumes, auto &streamVolumeCollection) {
- for (auto &configVolume : configVolumes) {
- audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT;
- if (configVolume.stream.empty() ||
- !StreamTypeConverter::fromString(configVolume.stream, streamType)) {
- ALOGE("%s: Invalid stream type", __FUNCTION__);
- continue;
- }
- VolumeCurves volumeCurves(streamType, configVolume.indexMin, configVolume.indexMax);
- for (auto &configCurve : configVolume.volumeCurves) {
- device_category deviceCategory = DEVICE_CATEGORY_SPEAKER;
- if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory,
- deviceCategory)) {
+ auto loadVolumeGroups = [](auto &volumeConfigs, auto &volumeGroups) {
+ for (auto &volumeConfig : volumeConfigs) {
+ sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin,
+ volumeConfig.indexMax);
+ volumeGroups[volumeGroup->getId()] = volumeGroup;
+
+ for (auto &configCurve : volumeConfig.volumeCurves) {
+ device_category deviceCat = DEVICE_CATEGORY_SPEAKER;
+ if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {
ALOGE("%s: Invalid %s", __FUNCTION__, configCurve.deviceCategory.c_str());
continue;
}
- sp<VolumeCurve> curve = new VolumeCurve(deviceCategory);
+ sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
for (auto &point : configCurve.curvePoints) {
curve->add({point.index, point.attenuationInMb});
}
- volumeCurves.add(curve);
+ volumeGroup->add(curve);
}
- streamVolumeCollection.add(volumeCurves, streamType);
}
};
-
auto result = engineConfig::parse();
if (result.parsedConfig == nullptr) {
ALOGW("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
@@ -145,8 +146,10 @@
static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
}
ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
- loadProductStrategies(result.parsedConfig->productStrategies, mProductStrategies);
- loadVolumeCurves(result.parsedConfig->volumeGroups, mStreamVolumeCurves);
+ loadVolumeGroups(result.parsedConfig->volumeGroups, mVolumeGroups);
+ loadProductStrategies(result.parsedConfig->productStrategies, mProductStrategies,
+ mVolumeGroups);
+ mProductStrategies.initialize();
return result;
}
@@ -204,30 +207,86 @@
return NO_ERROR;
}
-VolumeCurves *EngineBase::getVolumeCurvesForAttributes(const audio_attributes_t &attr)
+VolumeCurves *EngineBase::getVolumeCurvesForAttributes(const audio_attributes_t &attr) const
{
- return &mStreamVolumeCurves.getVolumeCurvesForStream(getStreamTypeForAttributes(attr));
+ volume_group_t volGr = mProductStrategies.getVolumeGroupForAttributes(attr);
+ const auto &iter = mVolumeGroups.find(volGr);
+ LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s", toString(attr).c_str());
+ return mVolumeGroups.at(volGr)->getVolumeCurves();
}
-VolumeCurves *EngineBase::getVolumeCurvesForStreamType(audio_stream_type_t stream)
+VolumeCurves *EngineBase::getVolumeCurvesForStreamType(audio_stream_type_t stream) const
{
- return &mStreamVolumeCurves.getVolumeCurvesForStream(stream);
+ volume_group_t volGr = mProductStrategies.getVolumeGroupForStreamType(stream);
+ const auto &iter = mVolumeGroups.find(volGr);
+ LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s",
+ toString(stream).c_str());
+ return mVolumeGroups.at(volGr)->getVolumeCurves();
}
status_t EngineBase::switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst)
{
- return mStreamVolumeCurves.switchVolumeCurve(streamSrc, streamDst);;
+ auto srcCurves = getVolumeCurvesForStreamType(streamSrc);
+ auto dstCurves = getVolumeCurvesForStreamType(streamDst);
+
+ if (srcCurves == nullptr || dstCurves == nullptr) {
+ return BAD_VALUE;
+ }
+ return dstCurves->switchCurvesFrom(*srcCurves);
}
status_t EngineBase::restoreOriginVolumeCurve(audio_stream_type_t stream)
{
- return mStreamVolumeCurves.restoreOriginVolumeCurve(stream);
+ VolumeCurves *curves = getVolumeCurvesForStreamType(stream);
+ return curves != nullptr ? curves->switchCurvesFrom(*curves) : BAD_VALUE;
+}
+
+VolumeGroupVector EngineBase::getVolumeGroups() const
+{
+ VolumeGroupVector group;
+ for (const auto &iter : mVolumeGroups) {
+ group.push_back(iter.first);
+ }
+ return group;
+}
+
+volume_group_t EngineBase::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
+{
+ return mProductStrategies.getVolumeGroupForAttributes(attr);
+}
+
+volume_group_t EngineBase::getVolumeGroupForStreamType(audio_stream_type_t stream) const
+{
+ return mProductStrategies.getVolumeGroupForStreamType(stream);
+}
+
+StreamTypeVector EngineBase::getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const
+{
+ // @TODO default music stream to control volume if no group?
+ return (mVolumeGroups.find(volumeGroup) != end(mVolumeGroups)) ?
+ mVolumeGroups.at(volumeGroup)->getStreamTypes() :
+ StreamTypeVector(AUDIO_STREAM_MUSIC);
+}
+
+AttributesVector EngineBase::getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const
+{
+ return (mVolumeGroups.find(volumeGroup) != end(mVolumeGroups)) ?
+ mVolumeGroups.at(volumeGroup)->getSupportedAttributes() : AttributesVector();
+}
+
+status_t EngineBase::listAudioVolumeGroups(AudioVolumeGroupVector &groups) const
+{
+ for (const auto &iter : mVolumeGroups) {
+ groups.push_back({iter.second->getName(), iter.second->getId(),
+ iter.second->getSupportedAttributes(), iter.second->getStreamTypes()});
+ }
+ return NO_ERROR;
}
void EngineBase::dump(String8 *dst) const
{
mProductStrategies.dump(dst, 2);
- mStreamVolumeCurves.dump(dst, 2);
+ mVolumeGroups.dump(dst, 2);
}
} // namespace audio_policy
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index f1642c5..fede0d9 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -25,11 +25,11 @@
const engineConfig::ProductStrategies gOrderedStrategies = {
{"STRATEGY_PHONE",
{
- {"phone", AUDIO_STREAM_VOICE_CALL,
+ {"phone", AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT, 0,
""}},
},
- {"sco", AUDIO_STREAM_BLUETOOTH_SCO,
+ {"sco", AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO,
""}},
}
@@ -37,18 +37,18 @@
},
{"STRATEGY_SONIFICATION",
{
- {"ring", AUDIO_STREAM_RING,
+ {"ring", AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
AUDIO_SOURCE_DEFAULT, 0, ""}}
},
- {"alarm", AUDIO_STREAM_ALARM,
+ {"alarm", AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, 0, ""}},
}
},
},
{"STRATEGY_ENFORCED_AUDIBLE",
{
- {"", AUDIO_STREAM_ENFORCED_AUDIBLE,
+ {"", AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_AUDIBILITY_ENFORCED, ""}}
}
@@ -56,7 +56,7 @@
},
{"STRATEGY_ACCESSIBILITY",
{
- {"", AUDIO_STREAM_ACCESSIBILITY,
+ {"", AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
AUDIO_SOURCE_DEFAULT, 0, ""}}
}
@@ -64,7 +64,7 @@
},
{"STRATEGY_SONIFICATION_RESPECTFUL",
{
- {"", AUDIO_STREAM_NOTIFICATION,
+ {"", AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT, 0, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
@@ -81,7 +81,7 @@
},
{"STRATEGY_MEDIA",
{
- {"music", AUDIO_STREAM_MUSIC,
+ {"music", AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, 0, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_GAME, AUDIO_SOURCE_DEFAULT, 0, ""},
@@ -91,7 +91,7 @@
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}
},
},
- {"system", AUDIO_STREAM_SYSTEM,
+ {"system", AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_SONIFICATION,
AUDIO_SOURCE_DEFAULT, 0, ""}}
}
@@ -99,7 +99,7 @@
},
{"STRATEGY_DTMF",
{
- {"", AUDIO_STREAM_DTMF,
+ {"", AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
AUDIO_SOURCE_DEFAULT, 0, ""}
@@ -109,7 +109,7 @@
},
{"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
{
- {"", AUDIO_STREAM_TTS,
+ {"", AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_BEACON, ""}}
}
@@ -117,14 +117,14 @@
},
{"STRATEGY_REROUTING",
{
- {"", AUDIO_STREAM_REROUTING,
+ {"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
}
},
},
{"STRATEGY_PATCH",
{
- {"", AUDIO_STREAM_PATCH,
+ {"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
}
},
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 71607d1..16e6690 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -44,7 +44,7 @@
{
std::vector<android::AudioAttributes> androidAa;
for (const auto &attr : mAttributesVector) {
- androidAa.push_back({attr.mGroupId, attr.mStream, attr.mAttributes});
+ androidAa.push_back({attr.mVolumeGroup, attr.mStream, attr.mAttributes});
}
return androidAa;
}
@@ -69,7 +69,8 @@
}) != end(mAttributesVector);
}
-audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(const audio_attributes_t &attr) const
+audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
+ const audio_attributes_t &attr) const
{
const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
[&attr](const auto &supportedAttr) {
@@ -110,6 +111,33 @@
return supportedAttr.mStream == streamType; }) != end(mAttributesVector);
}
+volume_group_t ProductStrategy::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
+{
+ for (const auto &supportedAttr : mAttributesVector) {
+ if (AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr)) {
+ return supportedAttr.mVolumeGroup;
+ }
+ }
+ return VOLUME_GROUP_NONE;
+}
+
+volume_group_t ProductStrategy::getVolumeGroupForStreamType(audio_stream_type_t stream) const
+{
+ for (const auto &supportedAttr : mAttributesVector) {
+ if (supportedAttr.mStream == stream) {
+ return supportedAttr.mVolumeGroup;
+ }
+ }
+ return VOLUME_GROUP_NONE;
+}
+
+volume_group_t ProductStrategy::getDefaultVolumeGroup() const
+{
+ const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
+ [](const auto &attr) {return attr.mAttributes == defaultAttr;});
+ return iter != end(mAttributesVector) ? iter->mVolumeGroup : VOLUME_GROUP_NONE;
+}
+
void ProductStrategy::dump(String8 *dst, int spaces) const
{
dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
@@ -121,7 +149,7 @@
deviceLiteral.c_str(), mDeviceAddress.c_str());
for (const auto &attr : mAttributesVector) {
- dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mGroupId,
+ dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mVolumeGroup,
android::toString(attr.mStream).c_str());
dst->appendFormat("%*s Attributes: ", spaces + 3, "");
std::string attStr =
@@ -172,6 +200,9 @@
product_strategy_t ProductStrategyMap::getDefault() const
{
+ if (mDefaultStrategy != PRODUCT_STRATEGY_NONE) {
+ return mDefaultStrategy;
+ }
for (const auto &iter : *this) {
if (iter.second->isDefault()) {
ALOGV("%s: using default %s", __FUNCTION__, iter.second->getName().c_str());
@@ -231,6 +262,42 @@
return at(psId)->getDeviceAddress();
}
+volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
+{
+ for (const auto &iter : *this) {
+ volume_group_t group = iter.second->getVolumeGroupForAttributes(attr);
+ if (group != VOLUME_GROUP_NONE) {
+ return group;
+ }
+ }
+ product_strategy_t defaultStrategy = getDefault();
+ if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
+ return VOLUME_GROUP_NONE;
+ }
+ return at(defaultStrategy)->getDefaultVolumeGroup();
+}
+
+volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(audio_stream_type_t stream) const
+{
+ for (const auto &iter : *this) {
+ volume_group_t group = iter.second->getVolumeGroupForStreamType(stream);
+ if (group != VOLUME_GROUP_NONE) {
+ return group;
+ }
+ }
+ product_strategy_t defaultStrategy = getDefault();
+ if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
+ return VOLUME_GROUP_NONE;
+ }
+ return at(defaultStrategy)->getDefaultVolumeGroup();
+}
+
+void ProductStrategyMap::initialize()
+{
+ mDefaultStrategy = getDefault();
+ ALOG_ASSERT(mDefaultStrategy != PRODUCT_STRATEGY_NONE, "No default product strategy found");
+}
+
void ProductStrategyMap::dump(String8 *dst, int spaces) const
{
dst->appendFormat("%*sProduct Strategies dump:", spaces, "");
diff --git a/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp b/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp
deleted file mode 100644
index fe3b000..0000000
--- a/services/audiopolicy/engine/common/src/StreamVolumeCurves.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2018 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 "APM::Engine::StreamVolumeCurves"
-//#define LOG_NDEBUG 0
-
-#include "StreamVolumeCurves.h"
-#include <TypeConverter.h>
-
-namespace android {
-
-void StreamVolumeCurves::dump(String8 *dst, int spaces) const
-{
- if (mCurves.empty()) {
- return;
- }
- dst->appendFormat("\n%*sStreams dump:\n", spaces, "");
- dst->appendFormat(
- "%*sStream Can be muted Index Min Index Max Index Cur [device : index]...\n", spaces + 2, "");
- for (const auto &streamCurve : mCurves) {
- streamCurve.second.dump(dst, spaces + 2, false);
- }
- dst->appendFormat("\n%*sVolume Curves for Use Cases (aka Stream types) dump:\n", spaces, "");
- for (const auto &streamCurve : mCurves) {
- std::string streamTypeLiteral;
- StreamTypeConverter::toString(streamCurve.first, streamTypeLiteral);
- dst->appendFormat(
- " %s (%02d): Curve points for device category (index, attenuation in millibel)\n",
- streamTypeLiteral.c_str(), streamCurve.first);
- streamCurve.second.dump(dst, spaces + 2, true);
- }
-}
-
-} // namespace android
diff --git a/services/audiopolicy/engine/common/src/VolumeCurve.cpp b/services/audiopolicy/engine/common/src/VolumeCurve.cpp
index be2ca73..c352578 100644
--- a/services/audiopolicy/engine/common/src/VolumeCurve.cpp
+++ b/services/audiopolicy/engine/common/src/VolumeCurve.cpp
@@ -19,13 +19,17 @@
#include "VolumeCurve.h"
#include "TypeConverter.h"
+#include <media/TypeConverter.h>
namespace android {
float VolumeCurve::volIndexToDb(int indexInUi, int volIndexMin, int volIndexMax) const
{
ALOG_ASSERT(!mCurvePoints.isEmpty(), "Invalid volume curve");
-
+ if (volIndexMin < 0 || volIndexMax < 0) {
+ // In order to let AudioService initialize the min and max, convention is to use -1
+ return NAN;
+ }
if (indexInUi < volIndexMin) {
// an index of 0 means mute request when volIndexMin > 0
if (indexInUi == 0) {
@@ -80,8 +84,8 @@
}
dst->append(" {");
for (size_t i = 0; i < mCurvePoints.size(); i++) {
- dst->appendFormat("%*s (%3d, %5d)", spaces, "",
- mCurvePoints[i].mIndex, mCurvePoints[i].mAttenuationInMb);
+ dst->appendFormat("%*s(%3d, %5d)", spaces, "", mCurvePoints[i].mIndex,
+ mCurvePoints[i].mAttenuationInMb);
dst->appendFormat(i == (mCurvePoints.size() - 1) ? " }\n" : ", ");
}
}
@@ -89,19 +93,36 @@
void VolumeCurves::dump(String8 *dst, int spaces, bool curvePoints) const
{
if (!curvePoints) {
- dst->appendFormat("%*s%02d %s %03d %03d ", spaces, "",
- mStream, mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
+// dst->appendFormat("%*s%02d %s %03d %03d ", spaces, "",
+// mStream, mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
+ dst->appendFormat("%*s Can be muted Index Min Index Max Index Cur [device : index]...\n",
+ spaces + 1, "");
+ dst->appendFormat("%*s %s %02d %02d ", spaces + 1, "",
+ mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
for (const auto &pair : mIndexCur) {
- dst->appendFormat("%*s %04x : %02d, ", spaces, "", pair.first, pair.second);
+ dst->appendFormat("%04x : %02d, ", pair.first, pair.second);
}
dst->appendFormat("\n");
return;
}
+ std::string streamNames;
+ for (const auto &stream : mStreams) {
+ streamNames += android::toString(stream) + "("+std::to_string(stream)+") ";
+ }
+ dst->appendFormat("%*sVolume Curves Streams/Attributes, Curve points Streams for device"
+ " category (index, attenuation in millibel)\n", spaces, "");
+ dst->appendFormat("%*s Streams: %s \n", spaces, "", streamNames.c_str());
+ if (!mAttributes.empty()) dst->appendFormat("%*s Attributes:", spaces, "");
+ for (const auto &attributes : mAttributes) {
+ std::string attStr = attributes == defaultAttr ? "{ Any }" : android::toString(attributes);
+ dst->appendFormat("%*s %s\n", attributes == mAttributes.front() ? 0 : spaces + 13, "",
+ attStr.c_str());
+ }
for (size_t i = 0; i < size(); i++) {
std::string deviceCatLiteral;
DeviceCategoryConverter::toString(keyAt(i), deviceCatLiteral);
dst->appendFormat("%*s %s :", spaces, "", deviceCatLiteral.c_str());
- valueAt(i)->dump(dst, 2, true);
+ valueAt(i)->dump(dst, 1, true);
}
}
diff --git a/services/audiopolicy/engine/common/src/VolumeGroup.cpp b/services/audiopolicy/engine/common/src/VolumeGroup.cpp
new file mode 100644
index 0000000..e189807
--- /dev/null
+++ b/services/audiopolicy/engine/common/src/VolumeGroup.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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 "APM::AudioPolicyEngine/VolumeGroup"
+//#define LOG_NDEBUG 0
+
+#include "VolumeGroup.h"
+#include <media/TypeConverter.h>
+#include <utils/String8.h>
+#include <cstdint>
+#include <string>
+
+#include <log/log.h>
+
+
+namespace android {
+
+//
+// VolumeGroup implementation
+//
+VolumeGroup::VolumeGroup(const std::string &name, int indexMin, int indexMax) :
+ mName(name), mId(static_cast<volume_group_t>(HandleGenerator<uint32_t>::getNextHandle())),
+ mGroupVolumeCurves(VolumeCurves(indexMin, indexMax))
+{
+}
+
+void VolumeGroup::dump(String8 *dst, int spaces) const
+{
+ dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
+ mGroupVolumeCurves.dump(dst, spaces + 2, true);
+ mGroupVolumeCurves.dump(dst, spaces + 2, false);
+ dst->appendFormat("\n");
+}
+
+void VolumeGroup::add(const sp<VolumeCurve> &curve)
+{
+ mGroupVolumeCurves.add(curve);
+}
+
+void VolumeGroup::addSupportedAttributes(const audio_attributes_t &attr)
+{
+ mGroupVolumeCurves.addAttributes(attr);
+}
+
+void VolumeGroup::addSupportedStream(audio_stream_type_t stream)
+{
+ mGroupVolumeCurves.addStreamType(stream);
+}
+
+//
+// VolumeGroupMap implementation
+//
+void VolumeGroupMap::dump(String8 *dst, int spaces) const
+{
+ dst->appendFormat("\n%*sVolume Groups dump:", spaces, "");
+ for (const auto &iter : *this) {
+ iter.second->dump(dst, spaces + 2);
+ }
+}
+
+} // namespace android
+
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index a188115..7f5ed5e 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -40,6 +40,7 @@
struct AttributesGroup {
std::string name;
audio_stream_type_t stream;
+ std::string volumeGroup;
AttributesVector attributesVect;
};
@@ -59,7 +60,6 @@
struct VolumeGroup {
std::string name;
- std::string stream;
int indexMin;
int indexMax;
VolumeCurves volumeCurves;
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 00fbac4..1ad7739 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -59,6 +59,7 @@
struct Attributes {
static constexpr const char *name = "name";
static constexpr const char *streamType = "streamType";
+ static constexpr const char *volumeGroup = "volumeGroup";
};
static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &ps);
};
@@ -116,6 +117,7 @@
struct Attributes {
static constexpr const char *deviceCategory = "deviceCategory";
+ static constexpr const char *stream = "stream"; // For legacy volume curves
static constexpr const char *reference = "ref"; /**< For volume curves factorization. */
};
@@ -139,8 +141,6 @@
using xmlCharUnique = std::unique_ptr<xmlChar, decltype(xmlFree)>;
-using xmlCharUnique = std::unique_ptr<xmlChar, decltype(xmlFree)>;
-
std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
{
xmlCharUnique charPtr(xmlGetProp(cur, reinterpret_cast<const xmlChar *>(attribute)), xmlFree);
@@ -304,6 +304,12 @@
}
ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
+ std::string volumeGroup = getXmlAttribute(child, Attributes::volumeGroup);
+ if (volumeGroup.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::volumeGroup);
+ }
+ ALOGV("%s: %s = %s", __FUNCTION__, Attributes::volumeGroup, volumeGroup.c_str());
+
audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT;
std::string streamTypeXml = getXmlAttribute(child, Attributes::streamType);
if (streamTypeXml.empty()) {
@@ -318,7 +324,7 @@
AttributesVector attributesVect;
deserializeAttributesCollection(doc, child, attributesVect);
- attributesGroup.push_back({name, streamType, attributesVect});
+ attributesGroup.push_back({name, streamType, volumeGroup, attributesVect});
return NO_ERROR;
}
@@ -420,7 +426,6 @@
if (deviceCategory.empty()) {
ALOGW("%s: No %s found", __FUNCTION__, Attributes::deviceCategory);
}
-
std::string referenceName = getXmlAttribute(root, Attributes::reference);
const _xmlNode *ref = NULL;
if (!referenceName.empty()) {
@@ -458,9 +463,10 @@
status_t VolumeGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &volumes)
{
std::string name;
- std::string stream = {};
int indexMin = 0;
int indexMax = 0;
+ StreamVector streams = {};
+ AttributesVector attributesVect = {};
for (const xmlNode *child = root->xmlChildrenNode; child != NULL; child = child->next) {
if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::name)) {
@@ -470,13 +476,6 @@
}
name = reinterpret_cast<const char*>(nameXml.get());
}
- if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::stream)) {
- xmlCharUnique streamXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
- if (streamXml == nullptr) {
- return BAD_VALUE;
- }
- stream = reinterpret_cast<const char*>(streamXml.get());
- }
if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::indexMin)) {
xmlCharUnique indexMinXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
if (indexMinXml == nullptr) {
@@ -498,13 +497,23 @@
}
}
}
- ALOGV("%s: group=%s stream=%s indexMin=%d, indexMax=%d",
- __func__, name.c_str(), stream.c_str(), indexMin, indexMax);
+ deserializeAttributesCollection(doc, root, attributesVect);
+
+ std::string streamNames;
+ for (const auto &stream : streams) {
+ streamNames += android::toString(stream) + " ";
+ }
+ std::string attrmNames;
+ for (const auto &attr : attributesVect) {
+ attrmNames += android::toString(attr) + "\n";
+ }
+ ALOGV("%s: group=%s indexMin=%d, indexMax=%d streams=%s attributes=%s",
+ __func__, name.c_str(), indexMin, indexMax, streamNames.c_str(), attrmNames.c_str( ));
VolumeCurves groupVolumeCurves;
size_t skipped = 0;
deserializeCollection<VolumeTraits>(doc, root, groupVolumeCurves, skipped);
- volumes.push_back({ name, stream, indexMin, indexMax, groupVolumeCurves });
+ volumes.push_back({ name, indexMin, indexMax, groupVolumeCurves });
return NO_ERROR;
}
@@ -580,8 +589,16 @@
}
}
for (const auto &volumeMapIter : legacyVolumeMap) {
- volumeGroups.push_back({ volumeMapIter.first, volumeMapIter.first, 0, 100,
- volumeMapIter.second });
+ // In order to let AudioService setting the min and max (compatibility), set Min and Max
+ // to -1 except for private streams
+ audio_stream_type_t streamType;
+ if (!StreamTypeConverter::fromString(volumeMapIter.first, streamType)) {
+ ALOGE("%s: Invalid stream %s", __func__, volumeMapIter.first.c_str());
+ return BAD_VALUE;
+ }
+ int indexMin = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 0 : -1;
+ int indexMax = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 100 : -1;
+ volumeGroups.push_back({ volumeMapIter.first, indexMin, indexMax, volumeMapIter.second });
}
return NO_ERROR;
}
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
index c9e9507..38f3401 100644
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
@@ -18,6 +18,7 @@
#include <AudioPolicyManagerObserver.h>
#include <media/AudioProductStrategy.h>
+#include <media/AudioVolumeGroup.h>
#include <IVolumeCurves.h>
#include <policy.h>
#include <Volume.h>
@@ -32,7 +33,7 @@
using DeviceStrategyMap = std::map<product_strategy_t, DeviceVector>;
using StrategyVector = std::vector<product_strategy_t>;
-
+using VolumeGroupVector = std::vector<volume_group_t>;
/**
* This interface is dedicated to the policy manager that a Policy Engine shall implement.
@@ -182,6 +183,7 @@
/**
* @brief getAttributesForStream get the audio attributes from legacy stream type
+ * Attributes returned might only be used to check upon routing decision, not volume decisions.
* @param stream to consider
* @return audio attributes matching the legacy stream type
*/
@@ -241,14 +243,58 @@
* @param attr to be considered
* @return IVolumeCurves interface pointer if found, nullptr otherwise
*/
- virtual IVolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) = 0;
+ virtual IVolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) const = 0;
/**
* @brief getVolumeCurvesForStreamType retrieves the Volume Curves interface for the stream
* @param stream to be considered
* @return IVolumeCurves interface pointer if found, nullptr otherwise
*/
- virtual IVolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) = 0;
+ virtual IVolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) const = 0;
+
+ /**
+ * @brief getVolumeCurvesForVolumeGroup retrieves the Volume Curves interface for volume group
+ * @param group to be considered
+ * @return IVolumeCurves interface pointer if found, nullptr otherwise
+ */
+ virtual IVolumeCurves *getVolumeCurvesForVolumeGroup(volume_group_t group) const = 0;
+
+ /**
+ * @brief getVolumeGroups retrieves the collection of volume groups.
+ * @return vector of volume groups
+ */
+ virtual VolumeGroupVector getVolumeGroups() const = 0;
+
+ /**
+ * @brief getVolumeGroupForAttributes gets the appropriate volume group to be used for a given
+ * Audio Attributes.
+ * @param attr to be considered
+ * @return volume group associated to the given audio attributes, default group if none
+ * applicable, VOLUME_GROUP_NONE if no default group defined.
+ */
+ virtual volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const = 0;
+
+ /**
+ * @brief getVolumeGroupForStreamType gets the appropriate volume group to be used for a given
+ * legacy stream type
+ * @param stream type to be considered
+ * @return volume group associated to the given stream type, default group if none applicable,
+ * VOLUME_GROUP_NONE if no default group defined.
+ */
+ virtual volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const = 0;
+
+ virtual StreamTypeVector getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const = 0;
+
+ virtual AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const = 0;
+
+ /**
+ * @brief listAudioVolumeGroups introspection API to get the Audio Volume Groups, aka
+ * former stream aliases in Audio Service, defining volume curves attached to one or more
+ * Audio Attributes.
+ * @param groups
+ * @return NO_ERROR if the volume groups were retrieved successfully, error code otherwise
+ */
+ virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const = 0;
virtual void dump(String8 *dst) const = 0;
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index 2b7e4c8..4eff6e6 100644
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -13,7 +13,7 @@
src/Stream.cpp \
src/InputSource.cpp \
../engine/common/src/VolumeCurve.cpp \
- ../engine/common/src/StreamVolumeCurves.cpp \
+ ../engine/common/src/VolumeGroup.cpp \
../engine/common/src/ProductStrategy.cpp \
../engine/common/src/EngineBase.cpp
diff --git a/services/audiopolicy/engineconfigurable/config/example/Android.mk b/services/audiopolicy/engineconfigurable/config/example/Android.mk
index ef476f7..45419f0 100644
--- a/services/audiopolicy/engineconfigurable/config/example/Android.mk
+++ b/services/audiopolicy/engineconfigurable/config/example/Android.mk
@@ -72,7 +72,8 @@
LOCAL_REQUIRED_MODULES := \
audio_policy_engine_product_strategies_automotive.xml \
audio_policy_engine_criteria.xml \
- audio_policy_engine_criterion_types.xml
+ audio_policy_engine_criterion_types.xml \
+ audio_policy_engine_volumes.xml
include $(BUILD_PREBUILT)
@@ -89,6 +90,14 @@
LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE_STEM)
include $(BUILD_PREBUILT)
+include $(CLEAR_VARS)
+LOCAL_MODULE := audio_policy_engine_volumes.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable))
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml
index e2fb02b..28a140a 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml
@@ -19,6 +19,7 @@
<xi:include href="audio_policy_engine_product_strategies.xml"/>
<xi:include href="audio_policy_engine_criterion_types.xml"/>
<xi:include href="audio_policy_engine_criteria.xml"/>
+ <xi:include href="audio_policy_engine_volumes.xml"/>
</configuration>
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
index 543a2f0..c487da9 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
@@ -31,7 +31,7 @@
-->
<ProductStrategy name="oem_traffic_anouncement">
- <AttributesGroup>
+ <AttributesGroup volumeGroup="oem_traffic_anouncement">
<ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
<!-- traffic_annoucement = 1 -->
@@ -39,14 +39,14 @@
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="oem_strategy_1">
- <AttributesGroup>
+ <AttributesGroup volumeGroup="oem_adas_2">
<ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
<Bundle key="oem" value="2"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="oem_strategy_2">
- <AttributesGroup>
+ <AttributesGroup volumeGroup="oem_adas_3">
<ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
<Bundle key="oem" value="3"/>
@@ -70,21 +70,21 @@
( type == CAR_AUDIO_TYPE_RADIO ) )
-->
<ProductStrategy name="radio">
- <AttributesGroup>
+ <AttributesGroup volumeGroup="media_car_audio_type_3">
<ContentType value="AUDIO_CONTENT_TYPE_MUSIC"/>
<Usage value="AUDIO_USAGE_MEDIA"/>
<Bundle key="car_audio_type" value="3"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="ext_audio_source">
- <AttributesGroup>
+ <AttributesGroup volumeGroup="media_car_audio_type_7">
<ContentType value="AUDIO_CONTENT_TYPE_MUSIC"/>
<Usage value="AUDIO_USAGE_MEDIA"/>
<Bundle key="car_audio_type" value="7"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="voice_command">
- <AttributesGroup>
+ <AttributesGroup volumeGroup="speech">
<Attributes>
<ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
@@ -96,7 +96,7 @@
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="safety_alert">
- <AttributesGroup>
+ <AttributesGroup volumeGroup="system">
<ContentType value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
<Usage value="AUDIO_USAGE_NOTIFICATION"/>
<!-- CAR_AUDIO_TYPE_SAFETY_ALERT = 2 -->
@@ -112,7 +112,7 @@
<!-- Generic Usages -->
<ProductStrategy name="music">
- <AttributesGroup streamType="AUDIO_STREAM_MUSIC">
+ <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="media">
<Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
<!-- Default product strategy has empty attributes -->
@@ -121,29 +121,31 @@
</ProductStrategy>
<ProductStrategy name="nav_guidance">
- <AttributesGroup>
+ <AttributesGroup volumeGroup="speech">
<Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="voice_call">
- <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
+ <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="phone">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
+ </AttributesGroup>
+ <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="phone">
<Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="alarm">
- <AttributesGroup streamType="AUDIO_STREAM_ALARM">
+ <AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="ring">
<Usage value="AUDIO_USAGE_ALARM"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="ring">
- <AttributesGroup streamType="AUDIO_STREAM_RING">
+ <AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
<Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="notification">
- <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
+ <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="ring">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/> </Attributes>
@@ -152,10 +154,17 @@
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="system">
- <AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
+ <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
<Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
</AttributesGroup>
</ProductStrategy>
-
+ <ProductStrategy name="tts">
+ <!-- TTS stream MUST BE MANAGED OUTSIDE default product strategy if NO DEDICATED OUTPUT
+ for TTS, otherwise when beacon happens, default strategy is ... muted.
+ If it is media, it is annoying... -->
+ <AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
+ <Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
</ProductStrategies>
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
new file mode 100644
index 0000000..b326b50
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
@@ -0,0 +1,192 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 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.
+ -->
+
+<!-- Volume Groups Tables included by Audio Policy Configuration file -->
+<!-- Note:
+ It is VALID to have a group without attributes if a product strategy is following
+ this group for all attributes.
+ Otherwise, attributes must be specified
+-->
+
+<volumeGroups>
+ <volumeGroup>
+ <name>oem_traffic_anouncement</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+<!-- OEM ADAS is a volume group that has a single port gain (this is the reason why it is a group
+ but may host different streams.
+ A priority must be given among them (either they are multualy excluisve, so the volume
+ will be the one of the currently acitve stream, otherwise a priority must be given by
+ any mean. -->
+ <volumeGroup>
+ <name>oem_adas_2</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+ <volumeGroup>
+ <name>oem_adas_3</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+<!-- MEDIA is a volume group that has a single port gain (this is the reason why it is a group
+ but may host different streams.
+ A priority must be given among them (either they are multualy exclusive, so the volume
+ will be the one of the active stream with highest priority (ORDER MATTERS) unless the curves
+ followed will the the curves for the requested attributes.-->
+ <volumeGroup>
+ <name>media_car_audio_type_3</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+ <volumeGroup>
+ <name>media_car_audio_type_7</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+ <volumeGroup>
+ <name>media</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>speech</name>
+ <indexMin>1</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>system</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>phone</name>
+ <indexMin>1</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>ring</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>tts</name>
+ <indexMin>0</indexMin>
+ <indexMax>15</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-0</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+</volumeGroups>
+
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
index f72e379..9398743 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
@@ -25,37 +25,37 @@
enforced. -->
<ProductStrategy name="STRATEGY_PHONE">
- <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
+ <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="voice_call">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
</AttributesGroup>
- <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO">
+ <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="bluetooth_sco">
<Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_SONIFICATION">
- <AttributesGroup streamType="AUDIO_STREAM_RING">
+ <AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/> </Attributes>
</AttributesGroup>
- <AttributesGroup streamType="AUDIO_STREAM_ALARM">
+ <AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="alarm">
<Attributes> <Usage value="AUDIO_USAGE_ALARM"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_ENFORCED_AUDIBLE">
- <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE">
+ <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE" volumeGroup="enforced_audible">
<Attributes> <Flags value="AUDIO_FLAG_AUDIBILITY_ENFORCED"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_ACCESSIBILITY">
- <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY">
+ <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY" volumeGroup="accessibility">
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_SONIFICATION_RESPECTFUL">
- <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
+ <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="notification">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
@@ -65,20 +65,20 @@
</ProductStrategy>
<ProductStrategy name="STRATEGY_MEDIA">
- <AttributesGroup streamType="AUDIO_STREAM_MUSIC">
+ <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music">
<Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
<Attributes></Attributes>
</AttributesGroup>
- <AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
+ <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_DTMF">
- <AttributesGroup streamType="AUDIO_STREAM_DTMF">
+ <AttributesGroup streamType="AUDIO_STREAM_DTMF" volumeGroup="dtmf">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
@@ -86,21 +86,21 @@
<!-- Used to identify the volume of audio streams exclusively transmitted through the speaker
(TTS) of the device -->
<ProductStrategy name="STRATEGY_TRANSMITTED_THROUGH_SPEAKER">
- <AttributesGroup streamType="AUDIO_STREAM_TTS">
+ <AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
<Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<!-- Routing Strategy rerouting may be removed as following media??? -->
<ProductStrategy name="STRATEGY_REROUTING">
- <AttributesGroup streamType="AUDIO_STREAM_REROUTING">
+ <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
<Attributes></Attributes>
</AttributesGroup>
</ProductStrategy>
<!-- Default product strategy has empty attributes -->
<ProductStrategy name="STRATEGY_PATCH">
- <AttributesGroup streamType="AUDIO_STREAM_PATCH">
+ <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
<Attributes></Attributes>
</AttributesGroup>
</ProductStrategy>
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
index 73bde1f..707a184 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
@@ -16,7 +16,7 @@
<!-- Volume section defines a volume curve for a given use case and device category.
It contains a list of points of this curve expressing the attenuation in Millibels for a given
volume index from 0 to 100.
-<volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
+<volume deviceCategory=””>
<point>0,-9600</point>
<point>100,0</point>
</volume>
@@ -24,7 +24,7 @@
<volumeGroups>
<volumeGroup>
- <stream>AUDIO_STREAM_VOICE_CALL</stream>
+ <name>voice_call</name>
<indexMin>1</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -50,7 +50,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_SYSTEM</stream>
+ <name>system</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -73,7 +73,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_RING</stream>
+ <name>ring</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@@ -84,7 +84,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_MUSIC</stream>
+ <name>music</name>
<indexMin>0</indexMin>
<indexMax>25</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
@@ -95,7 +95,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_ALARM</stream>
+ <name>alarm</name>
<indexMin>1</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE"/>
@@ -106,7 +106,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_NOTIFICATION</stream>
+ <name>notification</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@@ -117,7 +117,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_BLUETOOTH_SCO</stream>
+ <name>bluetooth_sco</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -143,7 +143,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_ENFORCED_AUDIBLE</stream>
+ <name>enforced_audible</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -164,7 +164,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_DTMF</stream>
+ <name>dtmf</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -185,7 +185,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_TTS</stream>
+ <name>tts</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/>
@@ -196,7 +196,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_ACCESSIBILITY</stream>
+ <name>accessibility</name>
<indexMin>1</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
@@ -207,7 +207,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_REROUTING</stream>
+ <name>rerouting</name>
<indexMin>0</indexMin>
<indexMax>1</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
@@ -218,7 +218,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_PATCH</stream>
+ <name>patch</name>
<indexMin>0</indexMin>
<indexMax>1</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index 94fa788..ebf383b 100644
--- a/services/audiopolicy/enginedefault/Android.mk
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -9,9 +9,9 @@
src/Engine.cpp \
src/EngineInstance.cpp \
../engine/common/src/VolumeCurve.cpp \
- ../engine/common/src/StreamVolumeCurves.cpp \
../engine/common/src/ProductStrategy.cpp \
- ../engine/common/src/EngineBase.cpp
+ ../engine/common/src/EngineBase.cpp \
+ ../engine/common/src/VolumeGroup.cpp
audio_policy_engine_includes_common := \
$(LOCAL_PATH)/include
diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
index f72e379..9398743 100644
--- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
@@ -25,37 +25,37 @@
enforced. -->
<ProductStrategy name="STRATEGY_PHONE">
- <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL">
+ <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="voice_call">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
</AttributesGroup>
- <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO">
+ <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="bluetooth_sco">
<Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_SONIFICATION">
- <AttributesGroup streamType="AUDIO_STREAM_RING">
+ <AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/> </Attributes>
</AttributesGroup>
- <AttributesGroup streamType="AUDIO_STREAM_ALARM">
+ <AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="alarm">
<Attributes> <Usage value="AUDIO_USAGE_ALARM"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_ENFORCED_AUDIBLE">
- <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE">
+ <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE" volumeGroup="enforced_audible">
<Attributes> <Flags value="AUDIO_FLAG_AUDIBILITY_ENFORCED"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_ACCESSIBILITY">
- <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY">
+ <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY" volumeGroup="accessibility">
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_SONIFICATION_RESPECTFUL">
- <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION">
+ <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="notification">
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
@@ -65,20 +65,20 @@
</ProductStrategy>
<ProductStrategy name="STRATEGY_MEDIA">
- <AttributesGroup streamType="AUDIO_STREAM_MUSIC">
+ <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music">
<Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
<Attributes></Attributes>
</AttributesGroup>
- <AttributesGroup streamType="AUDIO_STREAM_SYSTEM">
+ <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
<Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<ProductStrategy name="STRATEGY_DTMF">
- <AttributesGroup streamType="AUDIO_STREAM_DTMF">
+ <AttributesGroup streamType="AUDIO_STREAM_DTMF" volumeGroup="dtmf">
<Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
@@ -86,21 +86,21 @@
<!-- Used to identify the volume of audio streams exclusively transmitted through the speaker
(TTS) of the device -->
<ProductStrategy name="STRATEGY_TRANSMITTED_THROUGH_SPEAKER">
- <AttributesGroup streamType="AUDIO_STREAM_TTS">
+ <AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
<Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
<!-- Routing Strategy rerouting may be removed as following media??? -->
<ProductStrategy name="STRATEGY_REROUTING">
- <AttributesGroup streamType="AUDIO_STREAM_REROUTING">
+ <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
<Attributes></Attributes>
</AttributesGroup>
</ProductStrategy>
<!-- Default product strategy has empty attributes -->
<ProductStrategy name="STRATEGY_PATCH">
- <AttributesGroup streamType="AUDIO_STREAM_PATCH">
+ <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
<Attributes></Attributes>
</AttributesGroup>
</ProductStrategy>
diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
index 73bde1f..707a184 100644
--- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
+++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
@@ -16,7 +16,7 @@
<!-- Volume section defines a volume curve for a given use case and device category.
It contains a list of points of this curve expressing the attenuation in Millibels for a given
volume index from 0 to 100.
-<volume stream=”AUDIO_STREAM_MUSIC” deviceCategory=””>
+<volume deviceCategory=””>
<point>0,-9600</point>
<point>100,0</point>
</volume>
@@ -24,7 +24,7 @@
<volumeGroups>
<volumeGroup>
- <stream>AUDIO_STREAM_VOICE_CALL</stream>
+ <name>voice_call</name>
<indexMin>1</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -50,7 +50,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_SYSTEM</stream>
+ <name>system</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -73,7 +73,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_RING</stream>
+ <name>ring</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@@ -84,7 +84,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_MUSIC</stream>
+ <name>music</name>
<indexMin>0</indexMin>
<indexMax>25</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
@@ -95,7 +95,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_ALARM</stream>
+ <name>alarm</name>
<indexMin>1</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE"/>
@@ -106,7 +106,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_NOTIFICATION</stream>
+ <name>notification</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
@@ -117,7 +117,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_BLUETOOTH_SCO</stream>
+ <name>bluetooth_sco</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -143,7 +143,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_ENFORCED_AUDIBLE</stream>
+ <name>enforced_audible</name>
<indexMin>0</indexMin>
<indexMax>7</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -164,7 +164,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_DTMF</stream>
+ <name>dtmf</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET">
@@ -185,7 +185,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_TTS</stream>
+ <name>tts</name>
<indexMin>0</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/>
@@ -196,7 +196,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_ACCESSIBILITY</stream>
+ <name>accessibility</name>
<indexMin>1</indexMin>
<indexMax>15</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
@@ -207,7 +207,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_REROUTING</stream>
+ <name>rerouting</name>
<indexMin>0</indexMin>
<indexMax>1</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
@@ -218,7 +218,7 @@
</volumeGroup>
<volumeGroup>
- <stream>AUDIO_STREAM_PATCH</stream>
+ <name>patch</name>
<indexMin>0</indexMin>
<indexMax>1</indexMax>
<volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b563a04..ce305a4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -377,7 +377,7 @@
(strlen(device_address) != 0)/*matchAddress*/);
if (devDesc == 0) {
- ALOGW("getDeviceConnectionState() undeclared device, type %08x, address: %s",
+ ALOGV("getDeviceConnectionState() undeclared device, type %08x, address: %s",
device, device_address);
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
@@ -2373,16 +2373,13 @@
}
}
-void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream,
- int indexMin,
- int indexMax)
+void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
{
ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
if (indexMin < 0 || indexMax < 0) {
ALOGE("%s for stream %d: invalid min %d or max %d", __func__, stream , indexMin, indexMax);
return;
}
- // @todo: our proposal now use XML to store Indexes Min & Max
getVolumeCurves(stream).initVolume(indexMin, indexMax);
// initialize other private stream volumes which follow this one
@@ -2501,6 +2498,107 @@
return NO_ERROR;
}
+status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device)
+{
+ // Get Volume group matching the Audio Attributes
+ auto volumeGroup = mEngine->getVolumeGroupForAttributes(attr);
+ if (volumeGroup == VOLUME_GROUP_NONE) {
+ ALOGD("%s: could not find group matching with %s", __FUNCTION__, toString(attr).c_str());
+ return BAD_VALUE;
+ }
+ ALOGD("%s: FOUND group %d matching with %s", __FUNCTION__, volumeGroup, toString(attr).c_str());
+ return setVolumeGroupIndex(getVolumeCurves(attr), volumeGroup, index, device, attr);
+}
+
+status_t AudioPolicyManager::setVolumeGroupIndex(IVolumeCurves &curves, volume_group_t group,
+ int index,
+ audio_devices_t device,
+ const audio_attributes_t /*attributes*/)
+{
+ ALOGVV("%s: group=%d", __func__, group);
+ status_t status = NO_ERROR;
+ setVolumeCurveIndex(group, index, device, curves);
+ // update volume on all outputs and streams matching the following:
+ // - The requested stream (or a stream matching for volume control) is active on the output
+ // - The device (or devices) selected by the engine for this stream includes
+ // the requested device
+ // - For non default requested device, currently selected device on the output is either the
+ // requested device or one of the devices selected by the engine for this stream
+ // - For default requested device (AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME), apply volume only if
+ // no specific device volume value exists for currently selected device.
+ // @TODO
+ mpClientInterface->onAudioVolumeGroupChanged(group, 0 /*flags*/);
+ return status;
+}
+
+status_t AudioPolicyManager::setVolumeCurveIndex(volume_group_t volumeGroup,
+ int index,
+ audio_devices_t device,
+ IVolumeCurves &volumeCurves)
+{
+ // VOICE_CALL stream has minVolumeIndex > 0 but can be muted directly by an
+ // app that has MODIFY_PHONE_STATE permission.
+ // If voice is member of the volume group, it will contaminate all the member of this group
+ auto streams = mEngine->getStreamTypesForVolumeGroup(volumeGroup);
+ if (((index < volumeCurves.getVolumeIndexMin()) && !(hasVoiceStream(streams) && index == 0)) ||
+ (index > volumeCurves.getVolumeIndexMax())) {
+ ALOGD("%s: wrong index %d min=%d max=%d", __FUNCTION__, index,
+ volumeCurves.getVolumeIndexMin(), volumeCurves.getVolumeIndexMax());
+ return BAD_VALUE;
+ }
+ if (!audio_is_output_device(device)) {
+ return BAD_VALUE;
+ }
+
+ // Force max volume if stream cannot be muted
+ if (!volumeCurves.canBeMuted()) index = volumeCurves.getVolumeIndexMax();
+
+ ALOGD("%s device %08x, index %d", __FUNCTION__ , device, index);
+ volumeCurves.addCurrentVolumeIndex(device, index);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device)
+{
+ // if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
+ // stream by the engine.
+ if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
+ device = mEngine->getOutputDevicesForAttributes(attr, nullptr, true /*fromCache*/).types();
+ }
+ return getVolumeIndex(getVolumeCurves(attr), index, device);
+}
+
+status_t AudioPolicyManager::getVolumeIndex(const IVolumeCurves &curves,
+ int &index,
+ audio_devices_t device) const
+{
+ if (!audio_is_output_device(device)) {
+ return BAD_VALUE;
+ }
+ device = Volume::getDeviceForVolume(device);
+ index = curves.getVolumeIndex(device);
+ ALOGV("%s: device %08x index %d", __FUNCTION__, device, index);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getMinVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index)
+{
+ index = getVolumeCurves(attr).getVolumeIndexMin();
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getMaxVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index)
+{
+ index = getVolumeCurves(attr).getVolumeIndexMax();
+ return NO_ERROR;
+}
+
audio_io_handle_t AudioPolicyManager::selectOutputForMusicEffects()
{
// select one output among several suitable for global effects.
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 06a1f3e..641a03a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -143,9 +143,17 @@
virtual status_t stopInput(audio_port_handle_t portId);
virtual void releaseInput(audio_port_handle_t portId);
virtual void closeAllInputs();
- virtual void initStreamVolume(audio_stream_type_t stream,
- int indexMin,
- int indexMax);
+ /**
+ * @brief initStreamVolume: even if the engine volume files provides min and max, keep this
+ * api for compatibility reason.
+ * AudioServer will get the min and max and may overwrite them if:
+ * -using property (highest priority)
+ * -not defined (-1 by convention), case when still using apm volume tables XML files
+ * @param stream to be considered
+ * @param indexMin to set
+ * @param indexMax to set
+ */
+ virtual void initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device);
@@ -153,6 +161,27 @@
int *index,
audio_devices_t device);
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device);
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device);
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
+
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
+
+ status_t setVolumeGroupIndex(IVolumeCurves &volumeCurves, volume_group_t group, int index,
+ audio_devices_t device, const audio_attributes_t attributes);
+
+ status_t setVolumeCurveIndex(volume_group_t volumeGroup,
+ int index,
+ audio_devices_t device,
+ IVolumeCurves &volumeCurves);
+
+ status_t getVolumeIndex(const IVolumeCurves &curves, int &index,
+ audio_devices_t device) const;
+
// return the strategy corresponding to a given stream type
virtual uint32_t getStrategyForStream(audio_stream_type_t stream)
{
@@ -260,9 +289,23 @@
return mEngine->listAudioProductStrategies(strategies);
}
- virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa)
+ virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
+ product_strategy_t &productStrategy)
{
- return mEngine->getProductStrategyForAttributes(aa.getAttributes());
+ productStrategy = mEngine->getProductStrategyForAttributes(aa.getAttributes());
+ return productStrategy != PRODUCT_STRATEGY_NONE ? NO_ERROR : BAD_VALUE;
+ }
+
+ virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups)
+ {
+ return mEngine->listAudioVolumeGroups(groups);
+ }
+
+ virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
+ volume_group_t &volumeGroup)
+ {
+ volumeGroup = mEngine->getVolumeGroupForAttributes(aa.getAttributes());
+ return volumeGroup != VOLUME_GROUP_NONE ? NO_ERROR : BAD_VALUE;
}
protected:
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index d826192..5748334 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -222,6 +222,12 @@
clientConfig, clientEffects, deviceConfig, effects, patchHandle, source);
}
+void AudioPolicyService::AudioPolicyClient::onAudioVolumeGroupChanged(volume_group_t group,
+ int flags)
+{
+ mAudioPolicyService->onAudioVolumeGroupChanged(group, flags);
+}
+
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use)
{
return AudioSystem::newAudioUniqueId(use);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index d31ce53..a1b6b0f 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -450,28 +450,14 @@
return NO_ERROR;
}
-// this is replicated from frameworks/av/media/libaudioclient/AudioRecord.cpp
-// XXX -- figure out how to put it into a common, shared location
-
-static std::string audioSourceString(audio_source_t value) {
- std::string source;
- if (SourceTypeConverter::toString(value, source)) {
- return source;
- }
- char rawbuffer[16]; // room for "%d"
- snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
- return rawbuffer;
-}
-
std::string AudioPolicyService::getDeviceTypeStrForPortId(audio_port_handle_t portId) {
- std::string typeStr;
struct audio_port port = {};
port.id = portId;
status_t status = mAudioPolicyManager->getAudioPort(&port);
if (status == NO_ERROR && port.type == AUDIO_PORT_TYPE_DEVICE) {
- deviceToString(port.ext.device.type, typeStr);
+ return toString(port.ext.device.type);
}
- return typeStr;
+ return {};
}
status_t AudioPolicyService::startInput(audio_port_handle_t portId)
@@ -534,7 +520,7 @@
item->setInt32(kAudioPolicyStatus, status);
item->setCString(kAudioPolicyRqstSrc,
- audioSourceString(client->attributes.source).c_str());
+ toString(client->attributes.source).c_str());
item->setInt32(kAudioPolicyRqstSession, client->session);
if (client->opPackageName.size() != 0) {
item->setCString(kAudioPolicyRqstPkg,
@@ -554,7 +540,7 @@
if (other->active) {
// keeps the last of the clients marked active
item->setCString(kAudioPolicyActiveSrc,
- audioSourceString(other->attributes.source).c_str());
+ toString(other->attributes.source).c_str());
item->setInt32(kAudioPolicyActiveSession, other->session);
if (other->opPackageName.size() != 0) {
item->setCString(kAudioPolicyActivePkg,
@@ -703,6 +689,53 @@
device);
}
+status_t AudioPolicyService::setVolumeIndexForAttributes(const audio_attributes_t &attributes,
+ int index, audio_devices_t device)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->setVolumeIndexForAttributes(attributes, index, device);
+}
+
+status_t AudioPolicyService::getVolumeIndexForAttributes(const audio_attributes_t &attributes,
+ int &index, audio_devices_t device)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->getVolumeIndexForAttributes(attributes, index, device);
+}
+
+status_t AudioPolicyService::getMinVolumeIndexForAttributes(const audio_attributes_t &attributes,
+ int &index)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->getMinVolumeIndexForAttributes(attributes, index);
+}
+
+status_t AudioPolicyService::getMaxVolumeIndexForAttributes(const audio_attributes_t &attributes,
+ int &index)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->getMaxVolumeIndexForAttributes(attributes, index);
+}
+
uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
{
if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
@@ -1204,13 +1237,32 @@
return mAudioPolicyManager->listAudioProductStrategies(strategies);
}
-product_strategy_t AudioPolicyService::getProductStrategyFromAudioAttributes(
- const AudioAttributes &aa)
+status_t AudioPolicyService::getProductStrategyFromAudioAttributes(
+ const AudioAttributes &aa, product_strategy_t &productStrategy)
{
if (mAudioPolicyManager == NULL) {
- return PRODUCT_STRATEGY_NONE;
+ return NO_INIT;
}
Mutex::Autolock _l(mLock);
- return mAudioPolicyManager->getProductStrategyFromAudioAttributes(aa);
+ return mAudioPolicyManager->getProductStrategyFromAudioAttributes(aa, productStrategy);
+}
+
+status_t AudioPolicyService::listAudioVolumeGroups(AudioVolumeGroupVector &groups)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ return mAudioPolicyManager->listAudioVolumeGroups(groups);
+}
+
+status_t AudioPolicyService::getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
+ volume_group_t &volumeGroup)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ return mAudioPolicyManager->getVolumeGroupFromAudioAttributes(aa, volumeGroup);
}
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 76ac191..cf9cf71 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -150,6 +150,20 @@
mNotificationClients.valueFor(token)->setAudioPortCallbacksEnabled(enabled);
}
+void AudioPolicyService::setAudioVolumeGroupCallbacksEnabled(bool enabled)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+ int64_t token = ((int64_t)uid<<32) | pid;
+
+ if (mNotificationClients.indexOfKey(token) < 0) {
+ return;
+ }
+ mNotificationClients.valueFor(token)->setAudioVolumeGroupCallbacksEnabled(enabled);
+}
+
// removeNotificationClient() is called when the client process dies.
void AudioPolicyService::removeNotificationClient(uid_t uid, pid_t pid)
{
@@ -200,6 +214,19 @@
}
}
+void AudioPolicyService::onAudioVolumeGroupChanged(volume_group_t group, int flags)
+{
+ mOutputCommandThread->changeAudioVolumeGroupCommand(group, flags);
+}
+
+void AudioPolicyService::doOnAudioVolumeGroupChanged(volume_group_t group, int flags)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onAudioVolumeGroupChanged(group, flags);
+ }
+}
+
void AudioPolicyService::onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state)
{
ALOGV("AudioPolicyService::onDynamicPolicyMixStateUpdate(%s, %d)",
@@ -270,7 +297,7 @@
uid_t uid,
pid_t pid)
: mService(service), mUid(uid), mPid(pid), mAudioPolicyServiceClient(client),
- mAudioPortCallbacksEnabled(false)
+ mAudioPortCallbacksEnabled(false), mAudioVolumeGroupCallbacksEnabled(false)
{
}
@@ -301,6 +328,15 @@
}
}
+void AudioPolicyService::NotificationClient::onAudioVolumeGroupChanged(volume_group_t group,
+ int flags)
+{
+ if (mAudioPolicyServiceClient != 0 && mAudioVolumeGroupCallbacksEnabled) {
+ mAudioPolicyServiceClient->onAudioVolumeGroupChanged(group, flags);
+ }
+}
+
+
void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate(
const String8& regId, int32_t state)
{
@@ -330,6 +366,10 @@
mAudioPortCallbacksEnabled = enabled;
}
+void AudioPolicyService::NotificationClient::setAudioVolumeGroupCallbacksEnabled(bool enabled)
+{
+ mAudioVolumeGroupCallbacksEnabled = enabled;
+}
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
@@ -1058,6 +1098,18 @@
svc->doOnAudioPatchListUpdate();
mLock.lock();
}break;
+ case CHANGED_AUDIOVOLUMEGROUP: {
+ AudioVolumeGroupData *data =
+ static_cast<AudioVolumeGroupData *>(command->mParam.get());
+ ALOGV("AudioCommandThread() processing update audio volume group");
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnAudioVolumeGroupChanged(data->mGroup, data->mFlags);
+ mLock.lock();
+ }break;
case SET_AUDIOPORT_CONFIG: {
SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set port config");
@@ -1302,6 +1354,19 @@
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::changeAudioVolumeGroupCommand(volume_group_t group,
+ int flags)
+{
+ sp<AudioCommand>command = new AudioCommand();
+ command->mCommand = CHANGED_AUDIOVOLUMEGROUP;
+ AudioVolumeGroupData *data= new AudioVolumeGroupData();
+ data->mGroup = group;
+ data->mFlags = flags;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() adding audio volume group changed");
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand(
const struct audio_port_config *config, int delayMs)
{
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 8cd6e81..5888841 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -111,6 +111,17 @@
int *index,
audio_devices_t device);
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device);
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device);
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index);
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index);
+
virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
@@ -192,6 +203,8 @@
virtual void setAudioPortCallbacksEnabled(bool enabled);
+ virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled);
+
virtual status_t acquireSoundTriggerSession(audio_session_t *session,
audio_io_handle_t *ioHandle,
audio_devices_t *device);
@@ -231,7 +244,13 @@
virtual bool isHapticPlaybackSupported();
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
- virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa);
+ virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
+ product_strategy_t &productStrategy);
+
+ virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups);
+
+ virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
+ volume_group_t &volumeGroup);
status_t doStopOutput(audio_port_handle_t portId);
void doReleaseOutput(audio_port_handle_t portId);
@@ -269,6 +288,9 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
+ void onAudioVolumeGroupChanged(volume_group_t group, int flags);
+ void doOnAudioVolumeGroupChanged(volume_group_t group, int flags);
+
private:
AudioPolicyService() ANDROID_API;
virtual ~AudioPolicyService();
@@ -398,6 +420,7 @@
RELEASE_AUDIO_PATCH,
UPDATE_AUDIOPORT_LIST,
UPDATE_AUDIOPATCH_LIST,
+ CHANGED_AUDIOVOLUMEGROUP,
SET_AUDIOPORT_CONFIG,
DYN_POLICY_MIX_STATE_UPDATE,
RECORDING_CONFIGURATION_UPDATE
@@ -429,6 +452,7 @@
int delayMs);
void updateAudioPortListCommand();
void updateAudioPatchListCommand();
+ void changeAudioVolumeGroupCommand(volume_group_t group, int flags);
status_t setAudioPortConfigCommand(const struct audio_port_config *config,
int delayMs);
void dynamicPolicyMixStateUpdateCommand(const String8& regId,
@@ -510,6 +534,12 @@
audio_patch_handle_t mHandle;
};
+ class AudioVolumeGroupData : public AudioCommandData {
+ public:
+ volume_group_t mGroup;
+ int mFlags;
+ };
+
class SetAudioPortConfigData : public AudioCommandData {
public:
struct audio_port_config mConfig;
@@ -642,6 +672,8 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags);
+
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
private:
@@ -660,6 +692,7 @@
void onAudioPatchListUpdate();
void onDynamicPolicyMixStateUpdate(const String8& regId,
int32_t state);
+ void onAudioVolumeGroupChanged(volume_group_t group, int flags);
void onRecordingConfigurationUpdate(
int event,
const record_client_info_t *clientInfo,
@@ -670,6 +703,7 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
void setAudioPortCallbacksEnabled(bool enabled);
+ void setAudioVolumeGroupCallbacksEnabled(bool enabled);
uid_t uid() {
return mUid;
@@ -687,6 +721,7 @@
const pid_t mPid;
const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient;
bool mAudioPortCallbacksEnabled;
+ bool mAudioVolumeGroupCallbacksEnabled;
};
class AudioClient : public virtual RefBase {
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 6ae354b..8854eb2 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -73,6 +73,7 @@
int /*delayMs*/) override { return NO_INIT; }
void onAudioPortListUpdate() override { }
void onAudioPatchListUpdate() override { }
+ void onAudioVolumeGroupChanged(volume_group_t /*group*/, int /*flags*/) override { }
audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t /*use*/) override { return 0; }
void onDynamicPolicyMixStateUpdate(String8 /*regId*/, int32_t /*state*/) override { }
void onRecordingConfigurationUpdate(int event __unused,
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 7654982..65fcf40 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -8,24 +8,6 @@
LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog
LOCAL_MODULE:= libmediaextractorservice
-
-sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\
- $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
- $(UBSAN_RUNTIME_LIBRARY) \
- $(TSAN_RUNTIME_LIBRARY)))
-
-# $(info Sanitizer: $(sanitizer_runtime_libraries))
-
-ndk_libraries := $(call normalize-path-list,$(addprefix lib,$(addsuffix .so,\
- $(NDK_PREBUILT_SHARED_LIBRARIES))))
-
-# $(info NDK: $(ndk_libraries))
-
-LOCAL_CFLAGS += -DLINKED_LIBRARIES='"$(sanitizer_runtime_libraries):$(ndk_libraries)"'
-
-sanitizer_runtime_libraries :=
-ndk_libraries :=
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 0665930..de5c3e4 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -30,9 +30,7 @@
namespace android {
MediaExtractorService::MediaExtractorService()
- : BnMediaExtractorService() {
- MediaExtractorFactory::SetLinkedLibraries(std::string(LINKED_LIBRARIES));
-}
+ : BnMediaExtractorService() { }
sp<IMediaExtractor> MediaExtractorService::makeExtractor(
const sp<IDataSource> &remoteSource, const char *mime) {
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index 1c63f64..f3339a0 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -16,8 +16,6 @@
"liblog",
],
- compile_multilib: "32",
-
include_dirs: ["frameworks/av/include"],
cflags: [