Merge "Calculate the max possible preview frame rate for a session and attach it to CameraSessionStats for consumption by CameraServiceProxy." into tm-dev
diff --git a/METADATA b/METADATA
index aabda36..146bfcb 100644
--- a/METADATA
+++ b/METADATA
@@ -2,22 +2,22 @@
# CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
# DEPENDING ON IT IN YOUR PROJECT. ***
third_party {
- # would be NOTICE save for Widevine Master License Agreement in:
- # drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
- # drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
- # drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
- # drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
- # drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
- # and patent disclaimers in:
- # media/codec2/components/aac/patent_disclaimer.txt
- # media/codec2/components/amr_nb_wb/patent_disclaimer.txt
- # media/codec2/components/mp3/patent_disclaimer.txt
- # media/codec2/components/mpeg4_h263/patent_disclaimer.txt
- # media/codecs/amrnb/patent_disclaimer.txt
- # media/codecs/amrwb/dec/patent_disclaimer.txt
- # media/codecs/amrwb/enc/patent_disclaimer.txt
- # media/codecs/m4v_h263/patent_disclaimer.txt
- # media/codecs/mp3dec/patent_disclaimer.txt
- # media/libstagefright/codecs/aacenc/patent_disclaimer.txt
+ license_note: "would be NOTICE save for Widevine Master License Agreement in:\n"
+ " drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp\n"
+ " drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp\n"
+ " drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h\n"
+ " drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto\n"
+ " drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h\n"
+ " and patent disclaimers in:\n"
+ " media/codec2/components/aac/patent_disclaimer.txt\n"
+ " media/codec2/components/amr_nb_wb/patent_disclaimer.txt\n"
+ " media/codec2/components/mp3/patent_disclaimer.txt\n"
+ " media/codec2/components/mpeg4_h263/patent_disclaimer.txt\n"
+ " media/codecs/amrnb/patent_disclaimer.txt\n"
+ " media/codecs/amrwb/dec/patent_disclaimer.txt\n"
+ " media/codecs/amrwb/enc/patent_disclaimer.txt\n"
+ " media/codecs/m4v_h263/patent_disclaimer.txt\n"
+ " media/codecs/mp3dec/patent_disclaimer.txt\n"
+ " media/libstagefright/codecs/aacenc/patent_disclaimer.txt"
license_type: BY_EXCEPTION_ONLY
}
diff --git a/apex/Android.bp b/apex/Android.bp
index b9abd12..aa9fd89 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -23,7 +23,6 @@
apex_defaults {
name: "com.android.media-defaults",
- updatable: true,
bootclasspath_fragments: ["com.android.media-bootclasspath-fragment"],
systemserverclasspath_fragments: ["com.android.media-systemserverclasspath-fragment"],
multilib: {
@@ -67,14 +66,13 @@
// Use a custom AndroidManifest.xml used for API targeting.
androidManifest: ":com.android.media-androidManifest",
- // IMPORTANT: For the APEX to be installed on Android 10 (API 29),
- // min_sdk_version should be 29. This enables the build system to make
+ // IMPORTANT: q-launched-apex-module enables the build system to make
// sure the package compatible to Android 10 in two ways:
// - build the APEX package compatible to Android 10
// so that the package can be installed.
// - build artifacts (lib/javalib/bin) against Android 10 SDK
// so that the artifacts can run.
- min_sdk_version: "29",
+ defaults: ["q-launched-apex-module"],
// Indicates that pre-installed version of this apex can be compressed.
// Whether it actually will be compressed is controlled on per-device basis.
compressible: true,
@@ -148,7 +146,6 @@
apex_defaults {
name: "com.android.media.swcodec-defaults",
- updatable: true,
binaries: [
"mediaswcodec",
],
@@ -172,14 +169,13 @@
// Use a custom AndroidManifest.xml used for API targeting.
androidManifest: ":com.android.media.swcodec-androidManifest",
- // IMPORTANT: For the APEX to be installed on Android 10 (API 29),
- // min_sdk_version should be 29. This enables the build system to make
+ // IMPORTANT: q-launched-apex-module enables the build system to make
// sure the package compatible to Android 10 in two ways:
// - build the APEX package compatible to Android 10
// so that the package can be installed.
// - build artifacts (lib/javalib/bin) against Android 10 SDK
// so that the artifacts can run.
- min_sdk_version: "29",
+ defaults: ["q-launched-apex-module"],
// Indicates that pre-installed version of this apex can be compressed.
// Whether it actually will be compressed is controlled on per-device basis.
compressible: true,
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
index 7331ded..bae55d0 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
@@ -28,6 +28,7 @@
#include "DrmPlugin.h"
#include "Session.h"
#include "Utils.h"
+#include "AidlClearKeryProperties.h"
namespace {
const std::string kKeySetIdPrefix("ckid");
@@ -81,12 +82,13 @@
void DrmPlugin::initProperties() {
mStringProperties.clear();
- mStringProperties[kVendorKey] = kVendorValue;
+ mStringProperties[kVendorKey] = kAidlVendorValue;
mStringProperties[kVersionKey] = kVersionValue;
- mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
- mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
- mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
- mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue;
+ mStringProperties[kPluginDescriptionKey] = kAidlPluginDescriptionValue;
+ mStringProperties[kAlgorithmsKey] = kAidlAlgorithmsValue;
+ mStringProperties[kListenerTestSupportKey] = kAidlListenerTestSupportValue;
+ mStringProperties[kDrmErrorTestKey] = kAidlDrmErrorTestValue;
+ mStringProperties[kAidlVersionKey] = kAidlVersionValue;
std::vector<uint8_t> valueVector;
valueVector.clear();
@@ -377,6 +379,8 @@
value = mStringProperties[kListenerTestSupportKey];
} else if (name == kDrmErrorTestKey) {
value = mStringProperties[kDrmErrorTestKey];
+ } else if (name == kAidlVersionKey) {
+ value = mStringProperties[kAidlVersionValue];
} else {
ALOGE("App requested unknown string property %s", name.c_str());
status = Status::ERROR_DRM_CANNOT_HANDLE;
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/AidlClearKeryProperties.h b/drm/mediadrm/plugins/clearkey/aidl/include/AidlClearKeryProperties.h
new file mode 100644
index 0000000..8038108
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/AidlClearKeryProperties.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef AIDL_CLEARKEY_PROPERTIES_H
+#define AIDL_CLEARKEY_PROPERTIES_H
+#include <string>
+
+namespace clearkeydrm {
+static const std::string kAidlVendorValue("Google");
+static const std::string kAidlVersionValue("1.0");
+static const std::string kAidlPluginDescriptionValue("ClearKey CDM");
+static const std::string kAidlAlgorithmsValue("");
+static const std::string kAidlListenerTestSupportValue("true");
+
+static const std::string kAidlDrmErrorTestValue("");
+static const std::string kAidlResourceContentionValue("resourceContention");
+static const std::string kAidlLostStateValue("lostState");
+static const std::string kAidlFrameTooLargeValue("frameTooLarge");
+static const std::string kAidlInvalidStateValue("invalidState");
+} // namespace clearkeydrm
+
+#endif
\ No newline at end of file
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
index 9a22633..bfda388 100644
--- a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
@@ -34,6 +34,7 @@
static const std::string kLostStateValue("lostState");
static const std::string kFrameTooLargeValue("frameTooLarge");
static const std::string kInvalidStateValue("invalidState");
+static const std::string kAidlVersionKey("aidlVersion");
static const std::string kDeviceIdKey("deviceId");
static const uint8_t kTestDeviceIdData[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
index bb63e1f..7afea91 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
@@ -225,7 +225,7 @@
work->result = C2_CORRUPTED;
return;
}
- uint64_t outTimeStamp =
+ int64_t outTimeStamp =
mProcessedSamples * 1000000ll / mIntf->getSampleRate();
size_t inPos = 0;
size_t outPos = 0;
@@ -266,7 +266,7 @@
ALOGV("causal sample size %d", mFilledLen);
if (mIsFirst && outPos != 0) {
mIsFirst = false;
- mAnchorTimeStamp = work->input.ordinal.timestamp.peekull();
+ mAnchorTimeStamp = work->input.ordinal.timestamp.peekll();
}
fillEmptyWork(work);
if (outPos != 0) {
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.h b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.h
index 6ab14db..4920b23 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.h
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.h
@@ -54,7 +54,7 @@
bool mIsFirst;
bool mSignalledError;
bool mSignalledOutputEos;
- uint64_t mAnchorTimeStamp;
+ int64_t mAnchorTimeStamp;
uint64_t mProcessedSamples;
int32_t mFilledLen;
int16_t mInputFrame[kNumSamplesPerFrame];
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
index 84728ae..29b1040 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
@@ -307,7 +307,7 @@
work->result = wView.error();
return;
}
- uint64_t outTimeStamp =
+ int64_t outTimeStamp =
mProcessedSamples * 1000000ll / mIntf->getSampleRate();
size_t inPos = 0;
size_t outPos = 0;
@@ -341,7 +341,7 @@
ALOGV("causal sample size %d", mFilledLen);
if (mIsFirst && outPos != 0) {
mIsFirst = false;
- mAnchorTimeStamp = work->input.ordinal.timestamp.peekull();
+ mAnchorTimeStamp = work->input.ordinal.timestamp.peekll();
}
fillEmptyWork(work);
if (outPos != 0) {
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.h b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.h
index 0cc9e9f..72990c3 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.h
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.h
@@ -55,7 +55,7 @@
bool mIsFirst;
bool mSignalledError;
bool mSignalledOutputEos;
- uint64_t mAnchorTimeStamp;
+ int64_t mAnchorTimeStamp;
uint64_t mProcessedSamples;
int32_t mFilledLen;
int16_t mInputFrame[kNumSamplesPerFrame];
diff --git a/media/codec2/components/avc/Android.bp b/media/codec2/components/avc/Android.bp
index 7f82486..a7ae85b 100644
--- a/media/codec2/components/avc/Android.bp
+++ b/media/codec2/components/avc/Android.bp
@@ -18,6 +18,8 @@
static_libs: ["libavcdec"],
srcs: ["C2SoftAvcDec.cpp"],
+
+ export_include_dirs: ["."],
}
cc_library {
@@ -32,6 +34,8 @@
srcs: ["C2SoftAvcEnc.cpp"],
+ export_include_dirs: ["."],
+
cflags: [
"-Wno-unused-variable",
],
diff --git a/media/codec2/components/base/Android.bp b/media/codec2/components/base/Android.bp
index f1669fd..8c7f8db 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -9,6 +9,16 @@
default_applicable_licenses: ["frameworks_av_license"],
}
+cc_library_headers {
+ name: "libcodec2_soft_common_headers",
+ defaults: ["libcodec2-impl-defaults"],
+ vendor_available: true,
+
+ export_include_dirs: [
+ "include",
+ ],
+}
+
cc_library {
name: "libcodec2_soft_common",
defaults: ["libcodec2-impl-defaults"],
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 434246f..5295822 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -45,23 +45,23 @@
if (isMonochrome) {
// Fill with neutral U/V values.
- for (size_t i = 0; i < height / 2; ++i) {
- memset(dstV, kNeutralUVBitDepth8, width / 2);
- memset(dstU, kNeutralUVBitDepth8, width / 2);
+ for (size_t i = 0; i < (height + 1) / 2; ++i) {
+ memset(dstV, kNeutralUVBitDepth8, (width + 1) / 2);
+ memset(dstU, kNeutralUVBitDepth8, (width + 1) / 2);
dstV += dstUVStride;
dstU += dstUVStride;
}
return;
}
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, srcV, width / 2);
+ for (size_t i = 0; i < (height + 1) / 2; ++i) {
+ memcpy(dstV, srcV, (width + 1) / 2);
srcV += srcVStride;
dstV += dstUVStride;
}
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, srcU, width / 2);
+ for (size_t i = 0; i < (height + 1) / 2; ++i) {
+ memcpy(dstU, srcU, (width + 1) / 2);
srcU += srcUStride;
dstU += dstUVStride;
}
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 2ed8541..e5fbe99 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -55,8 +55,8 @@
DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
.withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
.withFields({
- C2F(mSize, width).inRange(2, 4096, 2),
- C2F(mSize, height).inRange(2, 4096, 2),
+ C2F(mSize, width).inRange(2, 4096),
+ C2F(mSize, height).inRange(2, 4096),
})
.withSetter(SizeSetter)
.build());
@@ -650,8 +650,12 @@
}
C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
- c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight, format,
- usage, &block);
+ // We always create a graphic block that is width aligned to 16 and height
+ // aligned to 2. We set the correct "crop" value of the image in the call to
+ // createGraphicBuffer() by setting the correct image dimensions.
+ c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16),
+ align(mHeight, 2), format, usage,
+ &block);
if (err != C2_OK) {
ALOGE("fetchGraphicBlock for Output failed with status %d", err);
diff --git a/media/codec2/sfplugin/utils/Android.bp b/media/codec2/sfplugin/utils/Android.bp
index 674921e..fe63651 100644
--- a/media/codec2/sfplugin/utils/Android.bp
+++ b/media/codec2/sfplugin/utils/Android.bp
@@ -7,6 +7,17 @@
default_applicable_licenses: ["frameworks_av_license"],
}
+cc_library_headers {
+ name: "libsfplugin_ccodec_utils_headers",
+ vendor_available: true,
+ min_sdk_version: "29",
+ apex_available: [ "//apex_available:platform", "com.android.media.swcodec", ],
+
+ export_include_dirs: [
+ ".",
+ ],
+}
+
cc_library {
name: "libsfplugin_ccodec_utils",
vendor_available: true,
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 598500d..4047173 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -100,7 +100,6 @@
"libdmabufheap",
"libfmq",
"libgralloctypes",
- "libhardware",
"libhidlbase",
"libion",
"liblog",
@@ -149,7 +148,6 @@
shared_libs: [
"libui",
"libdl",
- "libhardware",
"libvndksupport",
"libprocessgroup",
],
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 8faecae..aa59a0c 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -65,6 +65,7 @@
"libhidlbase",
"libhidlmemory",
"libjsoncpp",
+ "libmedia_helper",
"libprocessgroup",
"libstagefright_esds",
"libstagefright_foundation_without_imemory",
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index a5fb394..0871365 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -307,6 +307,8 @@
int32_t maxSharedAudioHistoryMs)
{
status_t status = NO_ERROR;
+ LOG_ALWAYS_FATAL_IF(mInitialized, "%s: should not be called twice", __func__);
+ mInitialized = true;
// Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
ALOGV("%s(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
"notificationFrames %u, sessionId %d, transferType %d, flags %#x, attributionSource %s"
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index dd729c4..a7b10b2 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1253,22 +1253,6 @@
return result.value_or(PRODUCT_STRATEGY_NONE);
}
-DeviceTypeSet AudioSystem::getDevicesForStream(audio_stream_type_t stream) {
- const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
- if (aps == 0) return DeviceTypeSet{};
-
- auto result = [&]() -> ConversionResult<DeviceTypeSet> {
- AudioStreamType streamAidl = VALUE_OR_RETURN(
- legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
- std::vector<AudioDeviceDescription> resultAidl;
- RETURN_IF_ERROR(statusTFromBinderStatus(
- aps->getDevicesForStream(streamAidl, &resultAidl)));
- return convertContainer<DeviceTypeSet>(resultAidl,
- aidl2legacy_AudioDeviceDescription_audio_devices_t);
- }();
- return result.value_or(DeviceTypeSet{});
-}
-
status_t AudioSystem::getDevicesForAttributes(const AudioAttributes& aa,
AudioDeviceTypeAddrVector* devices,
bool forVolume) {
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index bceca2d..bec6b10 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -277,10 +277,12 @@
{
mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
- (void)set(streamType, sampleRate, format, channelMask,
- frameCount, flags, callback, notificationFrames,
- 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
- attributionSource, pAttributes, doNotReconnect, maxRequiredSpeed, selectedDeviceId);
+ // make_unique does not aggregate init until c++20
+ mSetParams = std::unique_ptr<SetParams>{
+ new SetParams{streamType, sampleRate, format, channelMask, frameCount, flags, callback,
+ notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/,
+ sessionId, transferType, offloadInfo, attributionSource, pAttributes,
+ doNotReconnect, maxRequiredSpeed, selectedDeviceId}};
}
namespace {
@@ -355,10 +357,11 @@
} else if (user) {
LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
}
- (void)set(streamType, sampleRate, format, channelMask,
- frameCount, flags, mLegacyCallbackWrapper, notificationFrames,
- 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
- attributionSource, pAttributes, doNotReconnect, maxRequiredSpeed, selectedDeviceId);
+ mSetParams = std::unique_ptr<SetParams>{new SetParams{
+ streamType, sampleRate, format, channelMask, frameCount, flags, mLegacyCallbackWrapper,
+ notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId,
+ transferType, offloadInfo, attributionSource, pAttributes, doNotReconnect,
+ maxRequiredSpeed, selectedDeviceId}};
}
AudioTrack::AudioTrack(
@@ -387,10 +390,11 @@
{
mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
- (void)set(streamType, sampleRate, format, channelMask,
- 0 /*frameCount*/, flags, callback, notificationFrames,
- sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
- attributionSource, pAttributes, doNotReconnect, maxRequiredSpeed);
+ mSetParams = std::unique_ptr<SetParams>{
+ new SetParams{streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags,
+ callback, notificationFrames, sharedBuffer, false /*threadCanCallJava*/,
+ sessionId, transferType, offloadInfo, attributionSource, pAttributes,
+ doNotReconnect, maxRequiredSpeed, AUDIO_PORT_HANDLE_NONE}};
}
AudioTrack::AudioTrack(
@@ -424,11 +428,18 @@
} else if (user) {
LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
}
+ mSetParams = std::unique_ptr<SetParams>{new SetParams{
+ streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags,
+ mLegacyCallbackWrapper, notificationFrames, sharedBuffer, false /*threadCanCallJava*/,
+ sessionId, transferType, offloadInfo, attributionSource, pAttributes, doNotReconnect,
+ maxRequiredSpeed, AUDIO_PORT_HANDLE_NONE}};
+}
- (void)set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags,
- mLegacyCallbackWrapper, notificationFrames, sharedBuffer,
- false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, attributionSource,
- pAttributes, doNotReconnect, maxRequiredSpeed);
+void AudioTrack::onFirstRef() {
+ if (mSetParams) {
+ set(*mSetParams);
+ mSetParams.reset();
+ }
}
AudioTrack::~AudioTrack()
@@ -545,7 +556,6 @@
pid_t myPid;
uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(attributionSource.pid));
- sp<IAudioTrackCallback> _callback = callback.promote();
std::string errorMessage;
// Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
ALOGV("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
@@ -608,7 +618,7 @@
case TRANSFER_DEFAULT:
if (sharedBuffer != 0) {
transferType = TRANSFER_SHARED;
- } else if (_callback == nullptr|| threadCanCallJava) {
+ } else if (callback == nullptr|| threadCanCallJava) {
transferType = TRANSFER_SYNC;
} else {
transferType = TRANSFER_CALLBACK;
@@ -616,7 +626,7 @@
break;
case TRANSFER_CALLBACK:
case TRANSFER_SYNC_NOTIF_CALLBACK:
- if (_callback == nullptr || sharedBuffer != 0) {
+ if (callback == nullptr || sharedBuffer != 0) {
errorMessage = StringPrintf(
"%s: Transfer type %s but callback == nullptr || sharedBuffer != 0",
convertTransferToText(transferType), __func__);
@@ -771,7 +781,7 @@
mAuxEffectId = 0;
mCallback = callback;
- if (_callback != nullptr) {
+ if (callback != nullptr) {
mAudioTrackThread = sp<AudioTrackThread>::make(*this);
mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
// thread begins in paused state, and will not reference us until start()
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 748a10b..e2ef772 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -137,8 +137,6 @@
int /* product_strategy_t */ getStrategyForStream(AudioStreamType stream);
- AudioDeviceDescription[] getDevicesForStream(AudioStreamType stream);
-
AudioDevice[] getDevicesForAttributes(in AudioAttributesEx attr, boolean forVolume);
int /* audio_io_handle_t */ getOutputForEffect(in EffectDescriptor desc);
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index faea716..cb05dd9 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -740,6 +740,7 @@
wp<IAudioRecordCallback> mCallback;
sp<IAudioRecordCallback> mLegacyCallbackWrapper;
+ bool mInitialized = false; // Protect against double set
// for notification APIs
uint32_t mNotificationFramesReq; // requested number of frames between each
// notification callback
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index f1fcd3f..e89ce15 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -328,7 +328,6 @@
static status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
static product_strategy_t getStrategyForStream(audio_stream_type_t stream);
- static DeviceTypeSet getDevicesForStream(audio_stream_type_t stream);
static status_t getDevicesForAttributes(const AudioAttributes &aa,
AudioDeviceTypeAddrVector *devices,
bool forVolume);
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 1708cc7..1cf6ef9 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -458,6 +458,38 @@
float maxRequiredSpeed = 1.0f,
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
+ struct SetParams {
+ audio_stream_type_t streamType;
+ uint32_t sampleRate;
+ audio_format_t format;
+ audio_channel_mask_t channelMask;
+ size_t frameCount;
+ audio_output_flags_t flags;
+ wp<IAudioTrackCallback> callback;
+ int32_t notificationFrames;
+ sp<IMemory> sharedBuffer;
+ bool threadCanCallJava;
+ audio_session_t sessionId;
+ transfer_type transferType;
+ // TODO don't take pointers here
+ const audio_offload_info_t *offloadInfo;
+ AttributionSourceState attributionSource;
+ const audio_attributes_t* pAttributes;
+ bool doNotReconnect;
+ float maxRequiredSpeed;
+ audio_port_handle_t selectedDeviceId;
+ };
+ private:
+ // Note: Consumes parameters
+ void set(SetParams& s) {
+ (void)set(s.streamType, s.sampleRate, s.format, s.channelMask, s.frameCount,
+ s.flags, std::move(s.callback), s.notificationFrames,
+ std::move(s.sharedBuffer), s.threadCanCallJava, s.sessionId,
+ s.transferType, s.offloadInfo, std::move(s.attributionSource),
+ s.pAttributes, s.doNotReconnect, s.maxRequiredSpeed, s.selectedDeviceId);
+ }
+ void onFirstRef() override;
+ public:
status_t set(audio_stream_type_t streamType,
uint32_t sampleRate,
audio_format_t format,
@@ -1349,6 +1381,8 @@
wp<IAudioTrackCallback> mCallback; // callback handler for events, or NULL
sp<IAudioTrackCallback> mLegacyCallbackWrapper; // wrapper for legacy callback interface
// for notification APIs
+ std::unique_ptr<SetParams> mSetParams; // Temporary copy of ctor params to allow for
+ // deferred set after first reference.
bool mInitialized = false; // Set after track is initialized
// next 2 fields are const after constructor or set()
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index a433fc6..b9d795d 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -29,6 +29,7 @@
cc_library {
name: "libmedia_helper",
vendor_available: true,
+ min_sdk_version: "29",
vndk: {
enabled: true,
},
@@ -58,4 +59,9 @@
enabled: false,
},
},
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ "test_com.android.media",
+ ],
}
diff --git a/media/libstagefright/data/media_codecs_google_c2_video.xml b/media/libstagefright/data/media_codecs_google_c2_video.xml
index 04041eb..3509ef8 100644
--- a/media/libstagefright/data/media_codecs_google_c2_video.xml
+++ b/media/libstagefright/data/media_codecs_google_c2_video.xml
@@ -79,7 +79,7 @@
</MediaCodec>
<MediaCodec name="c2.android.av1.decoder" type="video/av01">
<Limit name="size" min="96x96" max="1920x1080" />
- <Limit name="alignment" value="2x2" />
+ <Limit name="alignment" value="1x1" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" min="24" max="2073600" />
<Limit name="bitrate" range="1-120000000" />
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index 53ca4e7..d7e2d18 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -184,7 +184,7 @@
</MediaCodec>
<MediaCodec name="c2.android.av1.decoder" type="video/av01" variant="!slow-cpu">
<Limit name="size" min="2x2" max="2048x2048" />
- <Limit name="alignment" value="2x2" />
+ <Limit name="alignment" value="1x1" />
<Limit name="block-size" value="16x16" />
<Limit name="block-count" range="1-16384" />
<Limit name="blocks-per-second" range="1-2073600" />
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index 0a4e598..4334f1e 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -19,6 +19,8 @@
#include <utils/Log.h>
#include <utils/String8.h>
+#include <inttypes.h>
+
#include "ALooperRoster.h"
#include "ADebug.h"
@@ -142,7 +144,7 @@
sp<AHandler> handler = info.mHandler.promote();
if (handler != NULL) {
handler->mVerboseStats = verboseStats;
- s.appendFormat(": %u messages processed", handler->mMessageCounter);
+ s.appendFormat(": %" PRIu64 " messages processed", handler->mMessageCounter);
if (verboseStats) {
for (size_t j = 0; j < handler->mMessages.size(); j++) {
char fourcc[15];
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AHandler.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AHandler.h
index 53d8a9b..337460a 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AHandler.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AHandler.h
@@ -66,7 +66,7 @@
}
bool mVerboseStats;
- uint32_t mMessageCounter;
+ uint64_t mMessageCounter;
KeyedVector<uint32_t, uint32_t> mMessages;
void deliverMessage(const sp<AMessage> &msg);
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 0ccc963..09f947c 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -210,9 +210,6 @@
// return the strategy corresponding to a given stream type
virtual product_strategy_t getStrategyForStream(audio_stream_type_t stream) = 0;
- // return the enabled output devices for the given stream type
- virtual DeviceTypeSet getDevicesForStream(audio_stream_type_t stream) = 0;
-
// retrieves the list of enabled output devices for the given audio attributes
virtual status_t getDevicesForAttributes(const audio_attributes_t &attr,
AudioDeviceTypeAddrVector *devices,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 18cf0c1..f57ac64 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -305,6 +305,7 @@
{
return !devices().isEmpty() ? devices().itemAt(0)->hasGainController() : false;
}
+ bool isRouted() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; }
DeviceVector mDevices; /**< current devices this output is routed to */
wp<AudioPolicyMix> mPolicyMix; // non NULL when used by a dynamic policy
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index dc2403c..6f95012 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -56,7 +56,13 @@
virtual void dump(String8 *dst, int spaces) const;
virtual std::string toShortString() const;
-
+ /**
+ * @brief isInternal
+ * @return true if the client corresponds to an audio patch created from createAudioPatch API or
+ * for call audio routing, or false if the client corresponds to an AudioTrack, AudioRecord or
+ * HW Audio Source.
+ */
+ virtual bool isInternal() const { return false; }
audio_port_handle_t portId() const { return mPortId; }
uid_t uid() const { return mUid; }
audio_session_t session() const { return mSessionId; };
@@ -69,8 +75,16 @@
bool isPreferredDeviceForExclusiveUse() const { return mPreferredDeviceForExclusiveUse; }
virtual void setActive(bool active) { mActive = active; }
bool active() const { return mActive; }
+ /**
+ * @brief hasPreferredDevice Note that as internal clients use preferred device for convenience,
+ * we do hide this internal behavior to prevent from regression (like invalidating track for
+ * clients following same strategies...)
+ * @param activeOnly
+ * @return
+ */
bool hasPreferredDevice(bool activeOnly = false) const {
- return mPreferredDeviceId != AUDIO_PORT_HANDLE_NONE && (!activeOnly || mActive);
+ return !isInternal() &&
+ mPreferredDeviceId != AUDIO_PORT_HANDLE_NONE && (!activeOnly || mActive);
}
private:
@@ -211,6 +225,11 @@
mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
mSinkDevice = nullptr;
}
+ bool belongsToOutput(const sp<SwAudioOutputDescriptor> &swOutput) const {
+ return swOutput != nullptr && mSwOutput.promote() == swOutput;
+ }
+ void setUseSwBridge() { mUseSwBridge = true; }
+ bool useSwBridge() const { return mUseSwBridge; }
bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; }
audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }
sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; }
@@ -229,6 +248,35 @@
sp<DeviceDescriptor> mSinkDevice;
wp<SwAudioOutputDescriptor> mSwOutput;
wp<HwAudioOutputDescriptor> mHwOutput;
+ bool mUseSwBridge = false;
+};
+
+/**
+ * @brief The InternalSourceClientDescriptor class
+ * Specialized Client Descriptor for either a raw patch created from @see createAudioPatch API
+ * or for internal audio patches managed by APM (e.g. phone call patches).
+ * Whatever the bridge created (software or hardware), we need a client to track the activity
+ * and manage volumes.
+ * The Audio Patch requested sink is expressed as a preferred device which allows to route
+ * the SwOutput. Then APM will performs checks on the UID (against UID of Audioserver) of the
+ * requester to prevent rerouting SwOutput involved in raw patches.
+ */
+class InternalSourceClientDescriptor: public SourceClientDescriptor
+{
+public:
+ InternalSourceClientDescriptor(
+ audio_port_handle_t portId, uid_t uid, audio_attributes_t attributes,
+ const struct audio_port_config &config, const sp<DeviceDescriptor>& srcDevice,
+ const sp<DeviceDescriptor>& sinkDevice,
+ product_strategy_t strategy, VolumeSource volumeSource) :
+ SourceClientDescriptor(
+ portId, uid, attributes, config, srcDevice, AUDIO_STREAM_PATCH, strategy,
+ volumeSource)
+ {
+ setPreferredDeviceId(sinkDevice->getId());
+ }
+ bool isInternal() const override { return true; }
+ ~InternalSourceClientDescriptor() override = default;
};
class SourceClientCollection :
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 1132a29..d1655ef 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -100,7 +100,8 @@
TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes,
{config.sample_rate, config.channel_mask, config.format}, AUDIO_PORT_HANDLE_NONE,
stream, strategy, volumeSource, AUDIO_OUTPUT_FLAG_NONE, false,
- {} /* Sources do not support secondary outputs*/, nullptr), mSrcDevice(srcDevice)
+ {} /* Sources do not support secondary outputs*/, nullptr),
+ mSrcDevice(srcDevice)
{
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f981b26..ff4705c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -664,12 +664,8 @@
ALOGV("%s device rxDevice %s txDevice %s", __func__,
rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());
- disconnectTelephonyRxAudioSource();
- // release TX patch if any
- if (mCallTxPatch != 0) {
- releaseAudioPatchInternal(mCallTxPatch->getHandle());
- mCallTxPatch.clear();
- }
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
auto telephonyRxModule =
mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
@@ -727,7 +723,7 @@
closeActiveClients(activeDesc);
}
}
- mCallTxPatch = createTelephonyPatch(false /*isRx*/, txSourceDevice, delayMs);
+ connectTelephonyTxAudioSource(txSourceDevice, txSinkDevice, delayMs);
}
if (waitMs != nullptr) {
*waitMs = muteWaitMs;
@@ -735,36 +731,6 @@
return NO_ERROR;
}
-sp<AudioPatch> AudioPolicyManager::createTelephonyPatch(
- bool isRx, const sp<DeviceDescriptor> &device, uint32_t delayMs) {
- PatchBuilder patchBuilder;
-
- if (device == nullptr) {
- return nullptr;
- }
-
- // @TODO: still ignoring the address, or not dealing platform with multiple telephony devices
- if (isRx) {
- patchBuilder.addSink(device).
- addSource(mAvailableInputDevices.getDevice(
- AUDIO_DEVICE_IN_TELEPHONY_RX, String8(), AUDIO_FORMAT_DEFAULT));
- } else {
- patchBuilder.addSource(device).
- addSink(mAvailableOutputDevices.getDevice(
- AUDIO_DEVICE_OUT_TELEPHONY_TX, String8(), AUDIO_FORMAT_DEFAULT));
- }
-
- audio_patch_handle_t patchHandle = AUDIO_PATCH_HANDLE_NONE;
- status_t status =
- createAudioPatchInternal(patchBuilder.patch(), &patchHandle, mUidCached, delayMs);
- ssize_t index = mAudioPatches.indexOfKey(patchHandle);
- if (status != NO_ERROR || index < 0) {
- ALOGW("%s() error %d creating %s audio patch", __func__, status, isRx ? "RX" : "TX");
- return nullptr;
- }
- return mAudioPatches.valueAt(index);
-}
-
bool AudioPolicyManager::isDeviceOfModule(
const sp<DeviceDescriptor>& devDesc, const char *moduleId) const {
sp<HwModule> module = mHwModules.getModuleFromName(moduleId);
@@ -779,20 +745,55 @@
void AudioPolicyManager::connectTelephonyRxAudioSource()
{
- disconnectTelephonyRxAudioSource();
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
const struct audio_port_config source = {
.role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE,
.ext.device.type = AUDIO_DEVICE_IN_TELEPHONY_RX, .ext.device.address = ""
};
const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
- status_t status = startAudioSource(&source, &aa, &mCallRxSourceClientPort, 0/*uid*/);
- ALOGE_IF(status != NO_ERROR, "%s failed to start Telephony Rx AudioSource", __func__);
+ mCallRxSourceClient = startAudioSourceInternal(&source, &aa, 0/*uid*/);
+ ALOGE_IF(mCallRxSourceClient == nullptr,
+ "%s failed to start Telephony Rx AudioSource", __func__);
}
-void AudioPolicyManager::disconnectTelephonyRxAudioSource()
+void AudioPolicyManager::disconnectTelephonyAudioSource(sp<SourceClientDescriptor> &clientDesc)
{
- stopAudioSource(mCallRxSourceClientPort);
- mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
+ if (clientDesc == nullptr) {
+ return;
+ }
+ ALOGW_IF(stopAudioSource(clientDesc->portId()) != NO_ERROR,
+ "%s error stopping audio source", __func__);
+ clientDesc.clear();
+}
+
+void AudioPolicyManager::connectTelephonyTxAudioSource(
+ const sp<DeviceDescriptor> &srcDevice, const sp<DeviceDescriptor> &sinkDevice,
+ uint32_t delayMs)
+{
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
+ if (srcDevice == nullptr || sinkDevice == nullptr) {
+ ALOGW("%s could not create patch, invalid sink and/or source device(s)", __func__);
+ return;
+ }
+ PatchBuilder patchBuilder;
+ patchBuilder.addSource(srcDevice).addSink(sinkDevice);
+ ALOGV("%s between source %s and sink %s", __func__,
+ srcDevice->toString().c_str(), sinkDevice->toString().c_str());
+ auto callTxSourceClientPortId = PolicyAudioPort::getNextUniqueId();
+ const audio_attributes_t aa = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
+ struct audio_port_config source = {};
+ srcDevice->toAudioPortConfig(&source);
+ mCallTxSourceClient = new InternalSourceClientDescriptor(
+ callTxSourceClientPortId, mUidCached, aa, source, srcDevice, sinkDevice,
+ mCommunnicationStrategy, toVolumeSource(aa));
+ audio_patch_handle_t patchHandle = AUDIO_PATCH_HANDLE_NONE;
+ status_t status = connectAudioSourceToSink(
+ mCallTxSourceClient, sinkDevice, patchBuilder.patch(), patchHandle, mUidCached,
+ delayMs);
+ ALOGE_IF(status != NO_ERROR, "%s() error %d creating TX audio patch", __func__, status);
+ if (status == NO_ERROR) {
+ mAudioSources.add(callTxSourceClientPortId, mCallTxSourceClient);
+ }
}
void AudioPolicyManager::setPhoneState(audio_mode_t state)
@@ -860,11 +861,8 @@
rxDevices = mPrimaryOutput->devices();
}
if (oldState == AUDIO_MODE_IN_CALL) {
- disconnectTelephonyRxAudioSource();
- if (mCallTxPatch != 0) {
- releaseAudioPatchInternal(mCallTxPatch->getHandle());
- mCallTxPatch.clear();
- }
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
}
setOutputDevices(mPrimaryOutput, rxDevices, force, 0);
}
@@ -874,8 +872,10 @@
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
DeviceVector newDevices = getNewOutputDevices(desc, true /*fromCache*/);
- if (state != AUDIO_MODE_IN_CALL || desc != mPrimaryOutput) {
- setOutputDevices(desc, newDevices, !newDevices.isEmpty(), 0 /*delayMs*/);
+ if (state != AUDIO_MODE_IN_CALL || (desc != mPrimaryOutput && !isTelephonyRxOrTx(desc))) {
+ bool forceRouting = !newDevices.isEmpty();
+ setOutputDevices(desc, newDevices, forceRouting, 0 /*delayMs*/, nullptr,
+ true /*requiresMuteCheck*/, !forceRouting /*requiresVolumeCheck*/);
}
}
@@ -1510,6 +1510,27 @@
return msdPatches;
}
+bool AudioPolicyManager::isMsdPatch(const audio_patch_handle_t &handle) const {
+ ssize_t index = mAudioPatches.indexOfKey(handle);
+ if (index < 0) {
+ return false;
+ }
+ const sp<AudioPatch> patch = mAudioPatches.valueAt(index);
+ sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
+ if (msdModule == nullptr) {
+ return false;
+ }
+ const struct audio_port_config *sink = &patch->mPatch.sinks[0];
+ if (getMsdAudioOutDevices().contains(mAvailableOutputDevices.getDeviceFromId(sink->id))) {
+ return true;
+ }
+ index = getMsdOutputPatches().indexOfKey(handle);
+ if (index < 0) {
+ return false;
+ }
+ return true;
+}
+
status_t AudioPolicyManager::getMsdProfiles(bool hwAvSync,
const InputProfileCollection &inputProfiles,
const OutputProfileCollection &outputProfiles,
@@ -1939,8 +1960,7 @@
// force device change if the output is inactive and no audio patch is already present.
// check active before incrementing usage count
- bool force = !outputDesc->isActive() &&
- (outputDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE);
+ bool force = !outputDesc->isActive() && !outputDesc->isRouted();
DeviceVector devices;
sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
@@ -3511,11 +3531,15 @@
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
DeviceVector newDevices = getNewOutputDevices(outputDesc, true /*fromCache*/);
- if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
+ if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) ||
+ (outputDesc != mPrimaryOutput && !isTelephonyRxOrTx(outputDesc))) {
// As done in setDeviceConnectionState, we could also fix default device issue by
// preventing the force re-routing in case of default dev that distinguishes on address.
// Let's give back to engine full device choice decision however.
- waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
+ bool forceRouting = !newDevices.isEmpty();
+ waitMs = setOutputDevices(outputDesc, newDevices, forceRouting, delayMs, nullptr,
+ true /*requiresMuteCheck*/,
+ !forceRouting /*requiresVolumeCheck*/);
// Only apply special touch sound delay once
delayMs = 0;
}
@@ -4064,17 +4088,15 @@
return BAD_VALUE;
}
-status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *patch,
- audio_patch_handle_t *handle,
- uid_t uid, uint32_t delayMs,
- const sp<SourceClientDescriptor>& sourceDesc)
+status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
+ audio_patch_handle_t *handle,
+ uid_t uid)
{
ALOGV("%s", __func__);
if (handle == NULL || patch == NULL) {
return BAD_VALUE;
}
ALOGV("%s num sources %d num sinks %d", __func__, patch->num_sources, patch->num_sinks);
-
if (!audio_patch_is_valid(patch)) {
return BAD_VALUE;
}
@@ -4082,7 +4104,6 @@
if (patch->num_sources > 1) {
return INVALID_OPERATION;
}
-
if (patch->sources[0].role != AUDIO_PORT_ROLE_SOURCE) {
return INVALID_OPERATION;
}
@@ -4092,6 +4113,86 @@
}
}
+ sp<DeviceDescriptor> srcDevice = mAvailableInputDevices.getDeviceFromId(patch->sources[0].id);
+ sp<DeviceDescriptor> sinkDevice = mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id);
+ if (srcDevice == nullptr || sinkDevice == nullptr) {
+ ALOGW("%s could not create patch, invalid sink and/or source device(s)", __func__);
+ return BAD_VALUE;
+ }
+ ALOGV("%s between source %s and sink %s", __func__,
+ srcDevice->toString().c_str(), sinkDevice->toString().c_str());
+ audio_port_handle_t portId = PolicyAudioPort::getNextUniqueId();
+ // Default attributes, default volume priority, not to infer with non raw audio patches.
+ audio_attributes_t attributes = attributes_initializer(AUDIO_USAGE_MEDIA);
+ const struct audio_port_config *source = &patch->sources[0];
+ sp<SourceClientDescriptor> sourceDesc =
+ new InternalSourceClientDescriptor(
+ portId, uid, attributes, *source, srcDevice, sinkDevice,
+ mEngine->getProductStrategyForAttributes(attributes), toVolumeSource(attributes));
+
+ status_t status =
+ connectAudioSourceToSink(sourceDesc, sinkDevice, patch, *handle, uid, 0 /* delayMs */);
+
+ if (status != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+ mAudioSources.add(portId, sourceDesc);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::connectAudioSourceToSink(
+ const sp<SourceClientDescriptor>& sourceDesc, const sp<DeviceDescriptor> &sinkDevice,
+ const struct audio_patch *patch,
+ audio_patch_handle_t &handle,
+ uid_t uid, uint32_t delayMs)
+{
+ status_t status = createAudioPatchInternal(patch, &handle, uid, delayMs, sourceDesc);
+ if (status != NO_ERROR || mAudioPatches.indexOfKey(handle) < 0) {
+ ALOGW("%s patch panel could not connect device patch, error %d", __func__, status);
+ return INVALID_OPERATION;
+ }
+ sourceDesc->connect(handle, sinkDevice);
+ if (isMsdPatch(handle)) {
+ return NO_ERROR;
+ }
+ // SW Bridge? (@todo: HW bridge, keep track of HwOutput for device selection "reconsideration")
+ sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
+ ALOG_ASSERT(swOutput != nullptr, "%s: a swOutput shall always be associated", __func__);
+ if (swOutput->getClient(sourceDesc->portId()) != nullptr) {
+ ALOGW("%s source portId has already been attached to outputDesc", __func__);
+ goto FailurePatchAdded;
+ }
+ status = swOutput->start();
+ if (status != NO_ERROR) {
+ goto FailureSourceAdded;
+ }
+ swOutput->addClient(sourceDesc);
+ status = startSource(swOutput, sourceDesc, &delayMs);
+ if (status != NO_ERROR) {
+ ALOGW("%s failed to start source, error %d", __FUNCTION__, status);
+ goto FailureSourceActive;
+ }
+ if (delayMs != 0) {
+ usleep(delayMs * 1000);
+ }
+ return NO_ERROR;
+
+FailureSourceActive:
+ swOutput->stop();
+ releaseOutput(sourceDesc->portId());
+FailureSourceAdded:
+ sourceDesc->setSwOutput(nullptr);
+FailurePatchAdded:
+ releaseAudioPatchInternal(handle);
+ return INVALID_OPERATION;
+}
+
+status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *patch,
+ audio_patch_handle_t *handle,
+ uid_t uid, uint32_t delayMs,
+ const sp<SourceClientDescriptor>& sourceDesc)
+{
+ ALOGV("%s num sources %d num sinks %d", __func__, patch->num_sources, patch->num_sinks);
sp<AudioPatch> patchDesc;
ssize_t index = mAudioPatches.indexOfKey(*handle);
@@ -4280,7 +4381,7 @@
// in config XML to reach the sink so that is can be declared as available.
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
sp<SwAudioOutputDescriptor> outputDesc = nullptr;
- if (sourceDesc != nullptr) {
+ if (!sourceDesc->isInternal()) {
// take care of dynamic routing for SwOutput selection,
audio_attributes_t attributes = sourceDesc->attributes();
audio_stream_type_t stream = sourceDesc->stream();
@@ -4308,44 +4409,49 @@
return INVALID_OPERATION;
}
sourceDesc->setSwOutput(outputDesc);
+ } else {
+ // Same for "raw patches" aka created from createAudioPatch API
+ SortedVector<audio_io_handle_t> outputs =
+ getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
+ // if the sink device is reachable via an opened output stream, request to
+ // go via this output stream by adding a second source to the patch
+ // description
+ output = selectOutput(outputs);
+ if (output == AUDIO_IO_HANDLE_NONE) {
+ ALOGE("%s no output available for internal patch sink", __func__);
+ return INVALID_OPERATION;
+ }
+ outputDesc = mOutputs.valueFor(output);
+ if (outputDesc->isDuplicated()) {
+ ALOGV("%s output for device %s is duplicated",
+ __func__, sinkDevice->toString().c_str());
+ return INVALID_OPERATION;
+ }
+ sourceDesc->setSwOutput(outputDesc);
}
// create a software bridge in PatchPanel if:
// - source and sink devices are on different HW modules OR
// - audio HAL version is < 3.0
// - audio HAL version is >= 3.0 but no route has been declared between devices
- // - called from startAudioSource (aka sourceDesc != nullptr) and source device does
- // not have a gain controller
+ // - called from startAudioSource (aka sourceDesc is not internal) and source device
+ // does not have a gain controller
if (!srcDevice->hasSameHwModuleAs(sinkDevice) ||
(srcDevice->getModuleVersionMajor() < 3) ||
!srcDevice->getModule()->supportsPatch(srcDevice, sinkDevice) ||
- (sourceDesc != nullptr &&
+ (!sourceDesc->isInternal() &&
srcDevice->getAudioPort()->getGains().size() == 0)) {
// support only one sink device for now to simplify output selection logic
if (patch->num_sinks > 1) {
return INVALID_OPERATION;
}
- if (sourceDesc == nullptr) {
- SortedVector<audio_io_handle_t> outputs =
- getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
- // if the sink device is reachable via an opened output stream, request to
- // go via this output stream by adding a second source to the patch
- // description
- output = selectOutput(outputs);
- if (output != AUDIO_IO_HANDLE_NONE) {
- outputDesc = mOutputs.valueFor(output);
- if (outputDesc->isDuplicated()) {
- ALOGV("%s output for device %s is duplicated",
- __FUNCTION__, sinkDevice->toString().c_str());
- return INVALID_OPERATION;
- }
- }
- }
+ sourceDesc->setUseSwBridge();
if (outputDesc != nullptr) {
audio_port_config srcMixPortConfig = {};
outputDesc->toAudioPortConfig(&srcMixPortConfig, nullptr);
// for volume control, we may need a valid stream
- srcMixPortConfig.ext.mix.usecase.stream = sourceDesc != nullptr ?
- sourceDesc->stream() : AUDIO_STREAM_PATCH;
+ srcMixPortConfig.ext.mix.usecase.stream = !sourceDesc->isInternal() ?
+ mEngine->getStreamTypeForAttributes(sourceDesc->attributes()) :
+ AUDIO_STREAM_PATCH;
patchBuilder.addSource(srcMixPortConfig);
}
}
@@ -4368,11 +4474,9 @@
return NO_ERROR;
}
-status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle,
- uid_t uid)
+status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle, uid_t uid)
{
- ALOGV("releaseAudioPatch() patch %d", handle);
-
+ ALOGV("%s patch %d", __func__, handle);
ssize_t index = mAudioPatches.indexOfKey(handle);
if (index < 0) {
@@ -4384,11 +4488,21 @@
if (patchDesc->getUid() != mUidCached && uid != patchDesc->getUid()) {
return INVALID_OPERATION;
}
- return releaseAudioPatchInternal(handle);
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+ for (size_t i = 0; i < mAudioSources.size(); i++) {
+ sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+ if (sourceDesc != nullptr && sourceDesc->getPatchHandle() == handle) {
+ portId = sourceDesc->portId();
+ break;
+ }
+ }
+ return portId != AUDIO_PORT_HANDLE_NONE ?
+ stopAudioSource(portId) : releaseAudioPatchInternal(handle);
}
status_t AudioPolicyManager::releaseAudioPatchInternal(audio_patch_handle_t handle,
- uint32_t delayMs)
+ uint32_t delayMs,
+ const sp<SourceClientDescriptor>& sourceDesc)
{
ALOGV("%s patch %d", __func__, handle);
if (mAudioPatches.indexOfKey(handle) < 0) {
@@ -4429,26 +4543,29 @@
removeAudioPatch(patchDesc->getHandle());
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
- // SW Bridge
+ // SW or HW Bridge
+ sp<SwAudioOutputDescriptor> outputDesc = nullptr;
+ audio_patch_handle_t patchHandle = AUDIO_PATCH_HANDLE_NONE;
if (patch->num_sources > 1 && patch->sources[1].type == AUDIO_PORT_TYPE_MIX) {
- sp<SwAudioOutputDescriptor> outputDesc =
- mOutputs.getOutputFromId(patch->sources[1].id);
- if (outputDesc == NULL) {
- ALOGW("%s output not found for id %d", __func__, patch->sources[0].id);
- // releaseOutput has already called closeOuput in case of direct output
- return NO_ERROR;
- }
- if (patchDesc->getHandle() != outputDesc->getPatchHandle()) {
- // force SwOutput patch removal as AF counter part patch has already gone.
- ALOGV("%s reset patch handle on Output as different from SWBridge", __func__);
- removeAudioPatch(outputDesc->getPatchHandle());
- }
- outputDesc->setPatchHandle(AUDIO_PATCH_HANDLE_NONE);
+ outputDesc = mOutputs.getOutputFromId(patch->sources[1].id);
+ } else if (patch->num_sources == 1 && sourceDesc != nullptr) {
+ outputDesc = sourceDesc->swOutput().promote();
+ }
+ if (outputDesc == nullptr) {
+ ALOGW("%s no output for id %d", __func__, patch->sources[0].id);
+ // releaseOutput has already called closeOutput in case of direct output
+ return NO_ERROR;
+ }
+ if (!outputDesc->isActive() && !sourceDesc->useSwBridge()) {
+ resetOutputDevice(outputDesc);
+ } else {
+ // Reuse patch handle if still valid / do not force rerouting if still routed
+ patchHandle = outputDesc->getPatchHandle();
setOutputDevices(outputDesc,
getNewOutputDevices(outputDesc, true /*fromCache*/),
- true, /*force*/
+ patchHandle == AUDIO_PATCH_HANDLE_NONE, /*force*/
0,
- NULL);
+ patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle);
}
} else {
return BAD_VALUE;
@@ -4694,6 +4811,18 @@
return status;
}
+sp<SourceClientDescriptor> AudioPolicyManager::startAudioSourceInternal(
+ const struct audio_port_config *source, const audio_attributes_t *attributes, uid_t uid)
+{
+ ALOGV("%s", __FUNCTION__);
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+
+ status_t status = startAudioSource(source, attributes, &portId, uid);
+ ALOGE_IF(status != OK, "%s: failed to start audio source (%d)", __func__, status);
+ return mAudioSources.valueFor(portId);
+}
+
+
status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>& sourceDesc)
{
ALOGV("%s handle %d", __FUNCTION__, sourceDesc->portId());
@@ -4718,52 +4847,9 @@
PatchBuilder patchBuilder;
patchBuilder.addSink(sinkDevice).addSource(srcDevice);
audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
- status_t status =
- createAudioPatchInternal(patchBuilder.patch(), &handle, mUidCached, 0, sourceDesc);
- if (status != NO_ERROR || mAudioPatches.indexOfKey(handle) < 0) {
- ALOGW("%s patch panel could not connect device patch, error %d", __func__, status);
- return INVALID_OPERATION;
- }
- sourceDesc->connect(handle, sinkDevice);
- // SW Bridge? (@todo: HW bridge, keep track of HwOutput for device selection "reconsideration")
- sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
- if (swOutput != 0) {
- status = swOutput->start();
- if (status != NO_ERROR) {
- goto FailureSourceAdded;
- }
- if (swOutput->getClient(sourceDesc->portId()) != nullptr) {
- ALOGW("%s source portId has already been attached to outputDesc", __func__);
- goto FailureReleasePatch;
- }
- swOutput->addClient(sourceDesc);
- uint32_t delayMs = 0;
- status = startSource(swOutput, sourceDesc, &delayMs);
- if (status != NO_ERROR) {
- ALOGW("%s failed to start source, error %d", __FUNCTION__, status);
- goto FailureSourceActive;
- }
- if (delayMs != 0) {
- usleep(delayMs * 1000);
- }
- } else {
- sp<HwAudioOutputDescriptor> hwOutputDesc = sourceDesc->hwOutput().promote();
- if (hwOutputDesc != 0) {
- // create Hwoutput and add to mHwOutputs
- } else {
- ALOGW("%s source has neither SW nor HW output", __FUNCTION__);
- }
- }
- return NO_ERROR;
-FailureSourceActive:
- swOutput->stop();
- releaseOutput(sourceDesc->portId());
-FailureSourceAdded:
- sourceDesc->setSwOutput(nullptr);
-FailureReleasePatch:
- releaseAudioPatchInternal(handle);
- return INVALID_OPERATION;
+ return connectAudioSourceToSink(
+ sourceDesc, sinkDevice, patchBuilder.patch(), handle, mUidCached, 0 /*delayMs*/);
}
status_t AudioPolicyManager::stopAudioSource(audio_port_handle_t portId)
@@ -5089,7 +5175,7 @@
ALOGW("%s source has neither SW nor HW output", __FUNCTION__);
}
}
- status_t status = releaseAudioPatchInternal(sourceDesc->getPatchHandle());
+ status_t status = releaseAudioPatchInternal(sourceDesc->getPatchHandle(), 0, sourceDesc);
sourceDesc->disconnect();
return status;
}
@@ -6061,7 +6147,7 @@
sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
if (sourceDesc != nullptr && followsSameRouting(attr, sourceDesc->attributes())
&& sourceDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE
- && !isCallRxAudioSource(sourceDesc)) {
+ && !isCallRxAudioSource(sourceDesc) && !sourceDesc->isInternal()) {
connectAudioSource(sourceDesc);
}
}
@@ -6174,7 +6260,7 @@
newDevices.types());
}
sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
- if (source != nullptr && !isCallRxAudioSource(source)) {
+ if (source != nullptr && !isCallRxAudioSource(source) && !source->isInternal()) {
connectAudioSource(source);
}
}
@@ -6430,46 +6516,6 @@
return (stream1 == stream2);
}
-DeviceTypeSet AudioPolicyManager::getDevicesForStream(audio_stream_type_t stream) {
- // By checking the range of stream before calling getStrategy, we avoid
- // getOutputDevicesForStream's behavior for invalid streams.
- // engine's getOutputDevicesForStream would fallback on its default behavior (most probably
- // device for music stream), but we want to return the empty set.
- if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_PUBLIC_CNT) {
- return DeviceTypeSet{};
- }
- DeviceVector activeDevices;
- DeviceVector devices;
- for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_PUBLIC_CNT; ++i) {
- const audio_stream_type_t curStream{static_cast<audio_stream_type_t>(i)};
- if (!streamsMatchForvolume(stream, curStream)) {
- continue;
- }
- DeviceVector curDevices = mEngine->getOutputDevicesForStream(curStream, false/*fromCache*/);
- devices.merge(curDevices);
- for (audio_io_handle_t output : getOutputsForDevices(curDevices, mOutputs)) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
- if (outputDesc->isActive(toVolumeSource(curStream, false))) {
- activeDevices.merge(outputDesc->devices());
- }
- }
- }
-
- // Favor devices selected on active streams if any to report correct device in case of
- // explicit device selection
- if (!activeDevices.isEmpty()) {
- devices = activeDevices;
- }
- /*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
- and doesn't really need to.*/
- DeviceVector speakerSafeDevices = devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER_SAFE);
- if (!speakerSafeDevices.isEmpty()) {
- devices.merge(mAvailableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
- devices.remove(speakerSafeDevices);
- }
- return devices.types();
-}
-
// TODO - consider MSD routes b/214971780
status_t AudioPolicyManager::getDevicesForAttributes(
const audio_attributes_t &attr, AudioDeviceTypeAddrVector *devices, bool forVolume) {
@@ -6748,6 +6794,8 @@
muteWaitMs = 0;
}
+ bool outputRouted = outputDesc->isRouted();
+
// no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current
// output profile or if new device is not supported AND previous device(s) is(are) still
// available (otherwise reset device must be done on the output)
@@ -6764,8 +6812,7 @@
// AND force is not specified
// AND the output is connected by a valid audio patch.
// Doing this check here allows the caller to call setOutputDevices() without conditions
- if ((filteredDevices.isEmpty() || filteredDevices == prevDevices) &&
- !force && outputDesc->getPatchHandle() != AUDIO_PATCH_HANDLE_NONE) {
+ if ((filteredDevices.isEmpty() || filteredDevices == prevDevices) && !force && outputRouted) {
ALOGV("%s setting same device %s or null device, force=%d, patch handle=%d", __func__,
filteredDevices.toString().c_str(), force, outputDesc->getPatchHandle());
if (requiresVolumeCheck && !filteredDevices.isEmpty()) {
@@ -6805,6 +6852,9 @@
audio_patch_handle_t *patchHandle)
{
ssize_t index;
+ if (patchHandle == nullptr && !outputDesc->isRouted()) {
+ return INVALID_OPERATION;
+ }
if (patchHandle) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index ac8b625..6f8b897 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -190,9 +190,6 @@
return mEngine->getProductStrategyForAttributes(attributes);
}
- // return the enabled output devices for the given stream type
- virtual DeviceTypeSet getDevicesForStream(audio_stream_type_t stream);
-
/**
* Returns a vector of devices associated with attributes.
*
@@ -266,10 +263,7 @@
virtual status_t getAudioPort(struct audio_port_v7 *port);
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
- uid_t uid) {
- return createAudioPatchInternal(patch, handle, uid);
- }
-
+ uid_t uid);
virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
uid_t uid);
virtual status_t listAudioPatches(unsigned int *num_patches,
@@ -641,13 +635,22 @@
void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
bool isCallRxAudioSource(const sp<SourceClientDescriptor> &source) {
- return mCallRxSourceClientPort != AUDIO_PORT_HANDLE_NONE
- && source == mAudioSources.valueFor(mCallRxSourceClientPort);
+ return mCallRxSourceClient != nullptr && source == mCallRxSourceClient;
}
void connectTelephonyRxAudioSource();
- void disconnectTelephonyRxAudioSource();
+ void disconnectTelephonyAudioSource(sp<SourceClientDescriptor> &clientDesc);
+
+ void connectTelephonyTxAudioSource(const sp<DeviceDescriptor> &srcdevice,
+ const sp<DeviceDescriptor> &sinkDevice,
+ uint32_t delayMs);
+
+ bool isTelephonyRxOrTx(const sp<SwAudioOutputDescriptor>& desc) const {
+ return (mCallRxSourceClient != nullptr && mCallRxSourceClient->belongsToOutput(desc))
+ || (mCallTxSourceClient != nullptr
+ && mCallTxSourceClient->belongsToOutput(desc));
+ }
/**
* @brief updates routing for all inputs.
@@ -854,6 +857,12 @@
status_t connectAudioSource(const sp<SourceClientDescriptor>& sourceDesc);
status_t disconnectAudioSource(const sp<SourceClientDescriptor>& sourceDesc);
+ status_t connectAudioSourceToSink(const sp<SourceClientDescriptor>& sourceDesc,
+ const sp<DeviceDescriptor> &sinkDevice,
+ const struct audio_patch *patch,
+ audio_patch_handle_t &handle,
+ uid_t uid, uint32_t delayMs);
+
sp<SourceClientDescriptor> getSourceForAttributesOnOutput(audio_io_handle_t output,
const audio_attributes_t &attr);
void clearAudioSourcesForOutput(audio_io_handle_t output);
@@ -904,8 +913,6 @@
SoundTriggerSessionCollection mSoundTriggerSessions;
- sp<AudioPatch> mCallTxPatch;
-
HwAudioOutputCollection mHwOutputs;
SourceClientCollection mAudioSources;
@@ -946,7 +953,8 @@
// The port handle of the hardware audio source created internally for the Call RX audio
// end point.
- audio_port_handle_t mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
+ sp<SourceClientDescriptor> mCallRxSourceClient;
+ sp<SourceClientDescriptor> mCallTxSourceClient;
// Support for Multi-Stream Decoder (MSD) module
sp<DeviceDescriptor> getMsdAudioInDevice() const;
@@ -978,7 +986,13 @@
// Called by setDeviceConnectionState()
status_t deviceToAudioPort(audio_devices_t deviceType, const char* device_address,
const char* device_name, media::AudioPort* aidPort);
+ bool isMsdPatch(const audio_patch_handle_t &handle) const;
+
private:
+ sp<SourceClientDescriptor> startAudioSourceInternal(
+ const struct audio_port_config *source, const audio_attributes_t *attributes,
+ uid_t uid);
+
void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
// Add or remove AC3 DTS encodings based on user preferences.
@@ -1123,21 +1137,25 @@
* @param[out] handle patch handle to be provided if patch installed correctly
* @param[in] uid of the client
* @param[in] delayMs if required
- * @param[in] sourceDesc [optional] in case of external source, source client to be
- * configured by the patch, i.e. assigning an Output (HW or SW)
+ * @param[in] sourceDesc source client to be configured when creating the patch, i.e.
+ * assigning an Output (HW or SW) used for volume control.
* @return NO_ERROR if patch installed correctly, error code otherwise.
*/
status_t createAudioPatchInternal(const struct audio_patch *patch,
audio_patch_handle_t *handle,
- uid_t uid, uint32_t delayMs = 0,
- const sp<SourceClientDescriptor>& sourceDesc = nullptr);
+ uid_t uid, uint32_t delayMs,
+ const sp<SourceClientDescriptor>& sourceDesc);
/**
* @brief releaseAudioPatchInternal internal function to remove an audio patch
* @param[in] handle of the patch to be removed
* @param[in] delayMs if required
+ * @param[in] sourceDesc [optional] in case of external source, source client to be
+ * unrouted from the patch, i.e. assigning an Output (HW or SW)
* @return NO_ERROR if patch removed correctly, error code otherwise.
*/
- status_t releaseAudioPatchInternal(audio_patch_handle_t handle, uint32_t delayMs = 0);
+ status_t releaseAudioPatchInternal(audio_patch_handle_t handle,
+ uint32_t delayMs = 0,
+ const sp<SourceClientDescriptor>& sourceDesc = nullptr);
status_t installPatch(const char *caller,
audio_patch_handle_t *patchHandle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 82d28ca..ae4d174 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -485,6 +485,7 @@
status_t status = mAudioPolicyManager->startOutput(portId);
if (status == NO_ERROR) {
client->active = true;
+ onUpdateActiveSpatializerTracks_l();
}
return binderStatusFromStatusT(status);
}
@@ -522,6 +523,7 @@
status_t status = mAudioPolicyManager->stopOutput(portId);
if (status == NO_ERROR) {
client->active = false;
+ onUpdateActiveSpatializerTracks_l();
}
return status;
}
@@ -552,8 +554,10 @@
client->io, client->stream, client->session);
}
Mutex::Autolock _l(mLock);
+ if (client != nullptr && client->active) {
+ onUpdateActiveSpatializerTracks_l();
+ }
mAudioPlaybackClients.removeItem(portId);
-
// called from internal thread: no need to clear caller identity
mAudioPolicyManager->releaseOutput(portId);
}
@@ -1159,30 +1163,6 @@
return Status::ok();
}
-//audio policy: use audio_device_t appropriately
-
-Status AudioPolicyService::getDevicesForStream(
- AudioStreamType streamAidl,
- std::vector<AudioDeviceDescription>* _aidl_return) {
- audio_stream_type_t stream = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioStreamType_audio_stream_type_t(streamAidl));
-
- if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
- *_aidl_return = std::vector<AudioDeviceDescription>{};
- return Status::ok();
- }
- if (mAudioPolicyManager == NULL) {
- return binderStatusFromStatusT(NO_INIT);
- }
- Mutex::Autolock _l(mLock);
- AutoCallerClear acc;
- *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
- convertContainer<std::vector<AudioDeviceDescription>>(
- mAudioPolicyManager->getDevicesForStream(stream),
- legacy2aidl_audio_devices_t_AudioDeviceDescription));
- return Status::ok();
-}
-
Status AudioPolicyService::getDevicesForAttributes(const media::AudioAttributesEx& attrAidl,
bool forVolume,
std::vector<AudioDevice>* _aidl_return)
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 38b58d5..3ee2aa3 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -397,6 +397,7 @@
if (status == NO_ERROR && currentOutput == newOutput) {
return;
}
+ size_t numActiveTracks = countActiveClientsOnOutput_l(newOutput);
mLock.unlock();
// It is OK to call detachOutput() is none is already attached.
mSpatializer->detachOutput();
@@ -404,7 +405,7 @@
mLock.lock();
return;
}
- status = mSpatializer->attachOutput(newOutput);
+ status = mSpatializer->attachOutput(newOutput, numActiveTracks);
mLock.lock();
if (status != NO_ERROR) {
mAudioPolicyManager->releaseSpatializerOutput(newOutput);
@@ -421,6 +422,34 @@
}
}
+size_t AudioPolicyService::countActiveClientsOnOutput_l(audio_io_handle_t output) REQUIRES(mLock) {
+ size_t count = 0;
+ for (size_t i = 0; i < mAudioPlaybackClients.size(); i++) {
+ auto client = mAudioPlaybackClients.valueAt(i);
+ if (client->io == output && client->active) {
+ count++;
+ }
+ }
+ return count;
+}
+
+void AudioPolicyService::onUpdateActiveSpatializerTracks_l() {
+ if (mSpatializer == nullptr) {
+ return;
+ }
+ mOutputCommandThread->updateActiveSpatializerTracksCommand();
+}
+
+void AudioPolicyService::doOnUpdateActiveSpatializerTracks()
+{
+ Mutex::Autolock _l(mLock);
+ if (mSpatializer == nullptr) {
+ return;
+ }
+ mSpatializer->updateActiveTracks(countActiveClientsOnOutput_l(mSpatializer->getOutput()));
+}
+
+
status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
int delayMs)
@@ -1092,7 +1121,6 @@
case TRANSACTION_isStreamActive:
case TRANSACTION_isStreamActiveRemotely:
case TRANSACTION_isSourceActive:
- case TRANSACTION_getDevicesForStream:
case TRANSACTION_registerPolicyMixes:
case TRANSACTION_setMasterMono:
case TRANSACTION_getSurroundFormats:
@@ -1953,8 +1981,8 @@
mLock.lock();
} break;
- case CHECK_SPATIALIZER: {
- ALOGV("AudioCommandThread() processing updateUID states");
+ case CHECK_SPATIALIZER_OUTPUT: {
+ ALOGV("AudioCommandThread() processing check spatializer");
svc = mService.promote();
if (svc == 0) {
break;
@@ -1964,6 +1992,17 @@
mLock.lock();
} break;
+ case UPDATE_ACTIVE_SPATIALIZER_TRACKS: {
+ ALOGV("AudioCommandThread() processing update spatializer tracks");
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnUpdateActiveSpatializerTracks();
+ mLock.lock();
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -2274,11 +2313,19 @@
void AudioPolicyService::AudioCommandThread::checkSpatializerCommand()
{
sp<AudioCommand>command = new AudioCommand();
- command->mCommand = CHECK_SPATIALIZER;
+ command->mCommand = CHECK_SPATIALIZER_OUTPUT;
ALOGV("AudioCommandThread() adding check spatializer");
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::updateActiveSpatializerTracksCommand()
+{
+ sp<AudioCommand>command = new AudioCommand();
+ command->mCommand = UPDATE_ACTIVE_SPATIALIZER_TRACKS;
+ ALOGV("AudioCommandThread() adding update active spatializer tracks");
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index f482886..43b579f 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -134,9 +134,6 @@
int32_t* _aidl_return) override;
binder::Status getStrategyForStream(AudioStreamType stream,
int32_t* _aidl_return) override;
- binder::Status getDevicesForStream(
- AudioStreamType stream,
- std::vector<AudioDeviceDescription>* _aidl_return) override;
binder::Status getDevicesForAttributes(const media::AudioAttributesEx& attr,
bool forVolume,
std::vector<AudioDevice>* _aidl_return) override;
@@ -353,9 +350,13 @@
* by audio policy manager and attach/detach the spatializer effect accordingly.
*/
void onCheckSpatializer() override;
- void onCheckSpatializer_l();
+ void onCheckSpatializer_l() REQUIRES(mLock);
void doOnCheckSpatializer();
+ void onUpdateActiveSpatializerTracks_l() REQUIRES(mLock);
+ void doOnUpdateActiveSpatializerTracks();
+
+
void setEffectSuspended(int effectId,
audio_session_t sessionId,
bool suspended);
@@ -527,7 +528,8 @@
AUDIO_MODULES_UPDATE,
ROUTING_UPDATED,
UPDATE_UID_STATES,
- CHECK_SPATIALIZER
+ CHECK_SPATIALIZER_OUTPUT, // verify if spatializer effect should be created or moved
+ UPDATE_ACTIVE_SPATIALIZER_TRACKS // Update active track counts on spalializer output
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -577,6 +579,8 @@
void routingChangedCommand();
void updateUidStatesCommand();
void checkSpatializerCommand();
+ void updateActiveSpatializerTracksCommand();
+
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
class AudioCommandData;
@@ -1001,6 +1005,8 @@
void loadAudioPolicyManager();
void unloadAudioPolicyManager();
+ size_t countActiveClientsOnOutput_l(audio_io_handle_t output) REQUIRES(mLock);
+
mutable Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing
// device connection state or routing
// Note: lock acquisition order is always mLock > mEffectsLock:
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 54d9094..d9e89aa 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -300,6 +300,7 @@
if (levelChanged && mEngine != nullptr) {
setEffectParameter_l(SPATIALIZER_PARAM_LEVEL, std::vector<SpatializationLevel>{level});
}
+ checkHeadSensor_l();
}
if (levelChanged) {
@@ -374,6 +375,7 @@
if (mPoseController != nullptr) {
mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
+ checkHeadSensor_l();
}
return Status::ok();
@@ -448,7 +450,7 @@
std::lock_guard lock(mLock);
mHeadSensor = sensorHandle;
if (mPoseController != nullptr) {
- mPoseController->setHeadSensor(mHeadSensor);
+ checkHeadSensor_l();
}
return Status::ok();
}
@@ -557,7 +559,6 @@
auto vec = headToStage.toVector();
LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
"%s invalid head to stage vector size %zu", __func__, vec.size());
-
sp<AMessage> msg =
new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
@@ -571,6 +572,9 @@
sp<media::ISpatializerHeadTrackingCallback> callback;
{
std::lock_guard lock(mLock);
+ if (mActualHeadTrackingMode == SpatializerHeadTrackingMode::DISABLED) {
+ return;
+ }
callback = mHeadTrackingCallback;
if (mEngine != nullptr) {
setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
@@ -621,7 +625,7 @@
}
}
-status_t Spatializer::attachOutput(audio_io_handle_t output) {
+status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
std::shared_ptr<SpatializerPoseController> poseController;
bool outputChanged = false;
sp<media::INativeSpatializerCallback> callback;
@@ -634,6 +638,7 @@
// remove FX instance
mEngine->setEnabled(false);
mEngine.clear();
+ mPoseController.reset();
}
// create FX instance on output
AttributionSourceState attributionSource = AttributionSourceState();
@@ -663,7 +668,8 @@
"%s could not allocate pose controller", __func__);
mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
- mPoseController->setHeadSensor(mHeadSensor);
+ mNumActiveTracks = numActiveTracks;
+ checkHeadSensor_l();
mPoseController->setScreenSensor(mScreenSensor);
mPoseController->setDisplayOrientation(mDisplayOrientation);
poseController = mPoseController;
@@ -697,7 +703,6 @@
output = mOutput;
mOutput = AUDIO_IO_HANDLE_NONE;
mPoseController.reset();
-
callback = mSpatializerCallback;
}
@@ -707,6 +712,24 @@
return output;
}
+void Spatializer::updateActiveTracks(size_t numActiveTracks) {
+ std::lock_guard lock(mLock);
+ mNumActiveTracks = numActiveTracks;
+ checkHeadSensor_l();
+}
+
+void Spatializer::checkHeadSensor_l() {
+ if (mSupportsHeadTracking && mPoseController != nullptr) {
+ if(mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
+ && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
+ && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
+ mPoseController->setHeadSensor(mHeadSensor);
+ } else {
+ mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
+ }
+ }
+}
+
void Spatializer::calculateHeadPose() {
ALOGV("%s", __func__);
std::lock_guard lock(mLock);
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index 4d77b78..4ce99d8 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -135,7 +135,7 @@
/** Called by audio policy service when the special output mixer dedicated to spatialization
* is opened and the spatializer engine must be created.
*/
- status_t attachOutput(audio_io_handle_t output);
+ status_t attachOutput(audio_io_handle_t output, size_t numActiveTracks);
/** Called by audio policy service when the special output mixer dedicated to spatialization
* is closed and the spatializer engine must be release.
*/
@@ -143,6 +143,8 @@
/** Returns the output stream the spatializer is attached to. */
audio_io_handle_t getOutput() const { std::lock_guard lock(mLock); return mOutput; }
+ void updateActiveTracks(size_t numActiveTracks);
+
/** Gets the channel mask, sampling rate and format set for the spatializer input. */
audio_config_base_t getAudioInConfig() const;
@@ -274,6 +276,8 @@
void postFramesProcessedMsg(int frames);
+ void checkHeadSensor_l() REQUIRES(mLock);
+
/** Effect engine descriptor */
const effect_descriptor_t mEngineDescriptor;
/** Callback interface to parent audio policy service */
@@ -328,6 +332,8 @@
sp<ALooper> mLooper;
sp<EngineCallbackHandler> mHandler;
+ size_t mNumActiveTracks GUARDED_BY(mLock) = 0;
+
static const std::vector<const char *> sHeadPoseKeys;
};
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 0ba1b28..c576162 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2139,10 +2139,14 @@
id.string());
errorCode = ERROR_CAMERA_IN_USE;
break;
+ case -EINVAL:
+ msg = String8::format("Torch strength level %d is not within the "
+ "valid range.", torchStrength);
+ errorCode = ERROR_ILLEGAL_ARGUMENT;
+ break;
default:
msg = String8::format("Changing torch strength level failed.");
errorCode = ERROR_INVALID_OPERATION;
-
}
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(errorCode, msg.string());