Merge "C2 VTS: Fix St12out_of_range" into rvc-dev
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 8620f36..487b8b0 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -143,6 +143,11 @@
if (data.dataAvail() > 0) {
metadata = new camera_frame_metadata_t;
metadata->number_of_faces = data.readInt32();
+ if (metadata->number_of_faces <= 0 ||
+ metadata->number_of_faces > (int32_t)(INT32_MAX / sizeof(camera_face_t))) {
+ ALOGE("%s: Too large face count: %d", __FUNCTION__, metadata->number_of_faces);
+ return BAD_VALUE;
+ }
metadata->faces = (camera_face_t *) data.readInplace(
sizeof(camera_face_t) * metadata->number_of_faces);
}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
index ccc73b6..1ce8269 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
@@ -91,6 +91,19 @@
return Void();
}
+Return<void> DrmFactory::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /*args*/) {
+ if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
+ ALOGE("%s: missing fd for writing", __FUNCTION__);
+ return Void();
+ }
+
+ FILE* out = fdopen(dup(fd->data[0]), "w");
+ uint32_t currentSessions = SessionLibrary::get()->numOpenSessions();
+ fprintf(out, "current open sessions: %u\n", currentSessions);
+ fclose(out);
+ return Void();
+}
+
} // namespace clearkey
} // namespace V1_3
} // namespace drm
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
index 403a8ec..63234cf 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
@@ -30,6 +30,7 @@
using ::android::hardware::drm::V1_1::SecurityLevel;
using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
@@ -55,6 +56,8 @@
Return<void> getSupportedCryptoSchemes(
getSupportedCryptoSchemes_cb _hidl_cb) override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args);
+
private:
CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DrmFactory);
};
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 6b389d5..e902b5d 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -44,6 +44,7 @@
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/SkipCutBuffer.h>
#include <media/MediaCodecBuffer.h>
+#include <mediadrm/ICrypto.h>
#include <system/window.h>
#include "CCodecBufferChannel.h"
@@ -1084,7 +1085,7 @@
// TODO: handle this without going into array mode
forceArrayMode = true;
} else {
- input->buffers.reset(new GraphicInputBuffers(numInputSlots, mName));
+ input->buffers.reset(new GraphicInputBuffers(mName));
}
} else {
if (hasCryptoOrDescrambler()) {
@@ -1252,7 +1253,7 @@
if (outputSurface || !buffersBoundToCodec) {
output->buffers.reset(new GraphicOutputBuffers(mName));
} else {
- output->buffers.reset(new RawGraphicOutputBuffers(numOutputSlots, mName));
+ output->buffers.reset(new RawGraphicOutputBuffers(mName));
}
} else {
output->buffers.reset(new LinearOutputBuffers(mName));
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index d7cc175..a9120c4 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -23,6 +23,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/SkipCutBuffer.h>
+#include <mediadrm/ICrypto.h>
#include "CCodecBuffers.h"
@@ -121,6 +122,11 @@
// OutputBuffers
+OutputBuffers::OutputBuffers(const char *componentName, const char *name)
+ : CCodecBuffers(componentName, name) { }
+
+OutputBuffers::~OutputBuffers() = default;
+
void OutputBuffers::initSkipCutBuffer(
int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
CHECK(mSkipCutBuffer == nullptr);
@@ -171,8 +177,11 @@
// LocalBufferPool
-std::shared_ptr<LocalBufferPool> LocalBufferPool::Create(size_t poolCapacity) {
- return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(poolCapacity));
+constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
+constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
+
+std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
+ return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
}
sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
@@ -192,6 +201,11 @@
mUsedSize -= mPool.back().capacity();
mPool.pop_back();
}
+ while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
+ ALOGD("Increasing local buffer pool capacity from %zu to %zu",
+ mPoolCapacity, mPoolCapacity * 2);
+ mPoolCapacity *= 2;
+ }
if (mUsedSize + capacity > mPoolCapacity) {
ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
mUsedSize, capacity, mPoolCapacity);
@@ -777,11 +791,10 @@
// GraphicInputBuffers
GraphicInputBuffers::GraphicInputBuffers(
- size_t numInputSlots, const char *componentName, const char *name)
+ const char *componentName, const char *name)
: InputBuffers(componentName, name),
mImpl(mName),
- mLocalBufferPool(LocalBufferPool::Create(
- kMaxLinearBufferSize * numInputSlots)) { }
+ mLocalBufferPool(LocalBufferPool::Create()) { }
bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
sp<Codec2Buffer> newBuffer = createNewBuffer();
@@ -942,7 +955,7 @@
case C2BufferData::GRAPHIC: {
// This is only called for RawGraphicOutputBuffers.
mAlloc = [format = mFormat,
- lbp = LocalBufferPool::Create(kMaxLinearBufferSize * mImpl.arraySize())] {
+ lbp = LocalBufferPool::Create()] {
return ConstGraphicBlockBuffer::AllocateEmpty(
format,
[lbp](size_t capacity) {
@@ -1079,10 +1092,9 @@
// RawGraphicOutputBuffers
RawGraphicOutputBuffers::RawGraphicOutputBuffers(
- size_t numOutputSlots, const char *componentName, const char *name)
+ const char *componentName, const char *name)
: FlexOutputBuffers(componentName, name),
- mLocalBufferPool(LocalBufferPool::Create(
- kMaxLinearBufferSize * numOutputSlots)) { }
+ mLocalBufferPool(LocalBufferPool::Create()) { }
sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
if (buffer == nullptr) {
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index 85ca5d5..6244acd 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -28,6 +28,8 @@
namespace android {
+struct ICrypto;
+class MemoryDealer;
class SkipCutBuffer;
constexpr size_t kLinearBufferSize = 1048576;
@@ -156,9 +158,8 @@
class OutputBuffers : public CCodecBuffers {
public:
- OutputBuffers(const char *componentName, const char *name = "Output")
- : CCodecBuffers(componentName, name) { }
- virtual ~OutputBuffers() = default;
+ OutputBuffers(const char *componentName, const char *name = "Output");
+ virtual ~OutputBuffers();
/**
* Register output C2Buffer from the component and obtain corresponding
@@ -243,11 +244,9 @@
/**
* Create a new LocalBufferPool object.
*
- * \param poolCapacity max total size of buffers managed by this pool.
- *
* \return a newly created pool object.
*/
- static std::shared_ptr<LocalBufferPool> Create(size_t poolCapacity);
+ static std::shared_ptr<LocalBufferPool> Create();
/**
* Return an ABuffer object whose size is at least |capacity|.
@@ -679,8 +678,7 @@
class GraphicInputBuffers : public InputBuffers {
public:
- GraphicInputBuffers(
- size_t numInputSlots, const char *componentName, const char *name = "2D-BB-Input");
+ GraphicInputBuffers(const char *componentName, const char *name = "2D-BB-Input");
~GraphicInputBuffers() override = default;
bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
@@ -892,8 +890,7 @@
class RawGraphicOutputBuffers : public FlexOutputBuffers {
public:
- RawGraphicOutputBuffers(
- size_t numOutputSlots, const char *componentName, const char *name = "2D-BB-Output");
+ RawGraphicOutputBuffers(const char *componentName, const char *name = "2D-BB-Output");
~RawGraphicOutputBuffers() override = default;
sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 5b3a62f..25e7da9 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "Codec2Buffer"
#include <utils/Log.h>
+#include <android/hardware/cas/native/1.0/types.h>
+#include <android/hardware/drm/1.0/types.h>
#include <hidlmemory/FrameworkUtils.h>
#include <media/hardware/HardwareAPI.h>
#include <media/stagefright/CodecBase.h>
@@ -25,6 +27,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
+#include <mediadrm/ICrypto.h>
#include <nativebase/nativebase.h>
#include <ui/Fence.h>
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index ff79946..dc788cd 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -20,16 +20,29 @@
#include <C2Buffer.h>
-#include <android/hardware/cas/native/1.0/types.h>
-#include <android/hardware/drm/1.0/types.h>
#include <binder/IMemory.h>
#include <media/hardware/VideoAPI.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/MediaCodecBuffer.h>
-#include <mediadrm/ICrypto.h>
namespace android {
+namespace hardware {
+class HidlMemory;
+namespace cas {
+namespace native {
+namespace V1_0 {
+struct SharedBuffer;
+} // namespace V1_0
+} // namespace native
+} // namespace cas
+namespace drm {
+namespace V1_0 {
+struct SharedBuffer;
+} // namespace V1_0
+} // namespace drm
+} // namespace hardware
+
/**
* Copies a graphic view into a media image.
*
diff --git a/media/codec2/sfplugin/tests/Android.bp b/media/codec2/sfplugin/tests/Android.bp
index fe5fa68..8d1a9c3 100644
--- a/media/codec2/sfplugin/tests/Android.bp
+++ b/media/codec2/sfplugin/tests/Android.bp
@@ -2,12 +2,13 @@
name: "ccodec_unit_test",
srcs: [
+ "CCodecBuffers_test.cpp",
"CCodecConfig_test.cpp",
"ReflectedParamUpdater_test.cpp",
],
defaults: [
- "libcodec2-hidl-defaults@1.0",
+ "libcodec2-impl-defaults",
"libcodec2-internal-defaults",
],
@@ -16,14 +17,24 @@
],
shared_libs: [
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.c2@1.0",
"libcodec2",
"libcodec2_client",
+ "libhidlbase",
+ "libfmq",
+ "libmedia_omx",
"libsfplugin_ccodec",
"libsfplugin_ccodec_utils",
"libstagefright_foundation",
"libutils",
],
+ static_libs: [
+ "libcodec2_hidl@1.0",
+ "libstagefright_bufferpool@2.0",
+ ],
+
cflags: [
"-Werror",
"-Wall",
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
new file mode 100644
index 0000000..5bee605
--- /dev/null
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CCodecBuffers.h"
+
+#include <gtest/gtest.h>
+
+#include <media/stagefright/MediaCodecConstants.h>
+
+#include <C2PlatformSupport.h>
+
+namespace android {
+
+TEST(RawGraphicOutputBuffersTest, ChangeNumSlots) {
+ constexpr int32_t kWidth = 3840;
+ constexpr int32_t kHeight = 2160;
+
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ std::make_shared<RawGraphicOutputBuffers>("test");
+ sp<AMessage> format{new AMessage};
+ format->setInt32("width", kWidth);
+ format->setInt32("height", kHeight);
+ buffers->setFormat(format);
+
+ std::shared_ptr<C2BlockPool> pool;
+ ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
+
+ // Register 4 buffers
+ std::vector<sp<MediaCodecBuffer>> clientBuffers;
+ auto registerBuffer = [&buffers, &clientBuffers, &pool] {
+ std::shared_ptr<C2GraphicBlock> block;
+ ASSERT_EQ(OK, pool->fetchGraphicBlock(
+ kWidth, kHeight, HAL_PIXEL_FORMAT_YCbCr_420_888,
+ C2MemoryUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
+ std::shared_ptr<C2Buffer> c2Buffer = C2Buffer::CreateGraphicBuffer(block->share(
+ block->crop(), C2Fence{}));
+ size_t index;
+ sp<MediaCodecBuffer> clientBuffer;
+ ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+ ASSERT_NE(nullptr, clientBuffer);
+ while (clientBuffers.size() <= index) {
+ clientBuffers.emplace_back();
+ }
+ ASSERT_EQ(nullptr, clientBuffers[index]) << "index = " << index;
+ clientBuffers[index] = clientBuffer;
+ };
+ for (int i = 0; i < 4; ++i) {
+ registerBuffer();
+ }
+
+ // Release 2 buffers
+ auto releaseBuffer = [&buffers, &clientBuffers, kWidth, kHeight](int index) {
+ std::shared_ptr<C2Buffer> c2Buffer;
+ ASSERT_TRUE(buffers->releaseBuffer(clientBuffers[index], &c2Buffer))
+ << "index = " << index;
+ clientBuffers[index] = nullptr;
+ // Sanity checks
+ ASSERT_TRUE(c2Buffer->data().linearBlocks().empty());
+ ASSERT_EQ(1u, c2Buffer->data().graphicBlocks().size());
+ C2ConstGraphicBlock block = c2Buffer->data().graphicBlocks().front();
+ ASSERT_EQ(kWidth, block.width());
+ ASSERT_EQ(kHeight, block.height());
+ };
+ for (int i = 0, index = 0; i < 2 && index < clientBuffers.size(); ++index) {
+ if (clientBuffers[index] == nullptr) {
+ continue;
+ }
+ releaseBuffer(index);
+ ++i;
+ }
+
+ // Simulate # of slots 4->16
+ for (int i = 2; i < 16; ++i) {
+ registerBuffer();
+ }
+
+ // Release everything
+ for (int index = 0; index < clientBuffers.size(); ++index) {
+ if (clientBuffers[index] == nullptr) {
+ continue;
+ }
+ releaseBuffer(index);
+ }
+}
+
+} // namespace android
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index bdb724b..b8255fc 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -10,7 +10,7 @@
static_libs: [
"libmedia_midiiowrapper",
- "libsonivox",
+ "libsonivoxwithoutjet",
"libstagefright_foundation",
"libwatchdog",
],
diff --git a/media/extractors/tests/Android.bp b/media/extractors/tests/Android.bp
index fa39b64..b3afe2f 100644
--- a/media/extractors/tests/Android.bp
+++ b/media/extractors/tests/Android.bp
@@ -45,7 +45,7 @@
"libstagefright_metadatautils",
"libmedia_midiiowrapper",
- "libsonivox",
+ "libsonivoxwithoutjet",
"libvorbisidec",
"libwebm",
"libFLAC",
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index edc09a9..a47f189 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -406,6 +406,7 @@
* Use this preset for capturing audio meant to be processed in real time
* and played back for live performance (e.g karaoke).
* The capture path will minimize latency and coupling with playback path.
+ * Available since API level 29.
*/
AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE = 10,
};
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 17d389e..0644368 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -106,21 +106,23 @@
}
void AudioStream::logOpen() {
- LOG_ALWAYS_FATAL_IF(mMetricsId.size() == 0, "mMetricsId is empty!");
- android::mediametrics::LogItem(mMetricsId)
- .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
- AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
- .set(AMEDIAMETRICS_PROP_SHARINGMODE,
- AudioGlobal_convertSharingModeToText(getSharingMode()))
- .record();
+ if (mMetricsId.size() > 0) {
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
+ AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
+ .set(AMEDIAMETRICS_PROP_SHARINGMODE,
+ AudioGlobal_convertSharingModeToText(getSharingMode()))
+ .record();
+ }
}
void AudioStream::logBufferState() {
- LOG_ALWAYS_FATAL_IF(mMetricsId.size() == 0, "mMetricsId is empty!");
- android::mediametrics::LogItem(mMetricsId)
- .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, (int32_t) getBufferSize())
- .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t) getXRunCount())
- .record();
+ if (mMetricsId.size() > 0) {
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, (int32_t) getBufferSize())
+ .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t) getXRunCount())
+ .record();
+ }
}
aaudio_result_t AudioStream::systemStart() {
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index cd5eb5a..9c24b2b 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -129,6 +129,7 @@
}
// This is used for exact matching by MediaMetrics. So do not change it.
+ // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_AAUDIO
static constexpr char kCallerName[] = "aaudio";
MonotonicCounter mFramesWritten;
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 1fb03bc..0bbceef 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -172,7 +172,7 @@
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
.set(AMEDIAMETRICS_PROP_CALLERNAME,
mCallerName.empty()
- ? AMEDIAMETRICS_PROP_VALUE_UNKNOWN
+ ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
: mCallerName.c_str())
.set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus)
.record();
@@ -400,6 +400,10 @@
status_t status = NO_ERROR;
mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_CALLERNAME,
+ mCallerName.empty()
+ ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
+ : mCallerName.c_str())
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
.set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index a5bb908..ca80dc4 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -303,7 +303,7 @@
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
.set(AMEDIAMETRICS_PROP_CALLERNAME,
mCallerName.empty()
- ? AMEDIAMETRICS_PROP_VALUE_UNKNOWN
+ ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
: mCallerName.c_str())
.set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
.set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus)
@@ -645,6 +645,10 @@
status_t status = NO_ERROR; // logged: make sure to set this before returning.
mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_CALLERNAME,
+ mCallerName.empty()
+ ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
+ : mCallerName.c_str())
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
.set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
@@ -879,7 +883,7 @@
{
const int64_t beginNs = systemTime();
AutoMutex lock(mLock);
- mediametrics::Defer([&]() {
+ mediametrics::Defer defer([&]() {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_PAUSE)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
@@ -2433,7 +2437,7 @@
{
status_t result = NO_ERROR; // logged: make sure to set this before returning.
const int64_t beginNs = systemTime();
- mediametrics::Defer([&] {
+ mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RESTORE)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 536b00d..050ad65 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1262,7 +1262,9 @@
AUDIO_UID_INVALID,
-1,
&attr);
-
+ // Set caller name so it can be logged in destructor.
+ // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_TONEGENERATOR
+ mpAudioTrack->setCallerName("tonegenerator");
if (status != NO_ERROR) {
ALOGE("AudioTrack(%p) set failed with error %d", mpAudioTrack.get(), status);
mpAudioTrack.clear();
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 62a86e7..be3f995 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -187,7 +187,7 @@
srcs: ["MidiIoWrapper.cpp"],
static_libs: [
- "libsonivox",
+ "libsonivoxwithoutjet",
],
header_libs: [
@@ -312,7 +312,7 @@
"libutils",
"libbinder",
"libbinder_ndk",
- "libsonivox",
+ //"libsonivox",
"libandroidicu",
"libexpat",
"libcamera_client",
@@ -328,7 +328,7 @@
"libaudioclient",
"libbinder",
"libandroidicu",
- "libsonivox",
+ //"libsonivox",
"libmedia_omx",
],
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 315ad62..00da69a 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -86,6 +86,7 @@
// of suppressed in the Time Machine.
#define AMEDIAMETRICS_PROP_SUFFIX_CHAR_DUPLICATES_ALLOWED '#'
+#define AMEDIAMETRICS_PROP_ALLOWUID "_allowUid" // int32_t, allow client uid to post
#define AMEDIAMETRICS_PROP_AUXEFFECTID "auxEffectId" // int32 (AudioTrack)
#define AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES "bufferSizeFrames" // int32
#define AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES "bufferCapacityFrames" // int32
@@ -133,8 +134,6 @@
#define AMEDIAMETRICS_PROP_VOLUME_RIGHT "volume.right" // double (AudioTrack)
#define AMEDIAMETRICS_PROP_WHERE "where" // string value
-#define AMEDIAMETRICS_PROP_VALUE_UNKNOWN "unknown" // string for callerName
-
// Timing values: millisecond values are suffixed with MS and the type is double
// nanosecond values are suffixed with NS and the type is int64.
@@ -159,4 +158,16 @@
#define AMEDIAMETRICS_PROP_EVENT_VALUE_STOP "stop" // AudioTrack, AudioRecord
#define AMEDIAMETRICS_PROP_EVENT_VALUE_UNDERRUN "underrun" // from Thread
+// Possible values for AMEDIAMETRICS_PROP_CALLERNAME
+// Check within the framework for these strings as this header file may not be explicitly
+// included to avoid unnecessary cross-project dependencies.
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_AAUDIO "aaudio" // Native AAudio
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_JAVA "java" // Java API layer
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA "media" // libmedia
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_OPENSLES "opensles" // Open SLES
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_RTP "rtp" // RTP communication
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_SOUNDPOOL "soundpool" // SoundPool
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_TONEGENERATOR "tonegenerator" // dial tones
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN "unknown" // callerName not set
+
#endif // ANDROID_MEDIA_MEDIAMETRICSCONSTANTS_H
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 42a0622..c0da0ce 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2206,7 +2206,9 @@
targetSpeed,
mSelectedDeviceId);
}
-
+ // Set caller name so it can be logged in destructor.
+ // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA
+ t->setCallerName("media");
if ((t == 0) || (t->initCheck() != NO_ERROR)) {
ALOGE("Unable to create audio track");
delete newcbd;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 73d3a0b..63ab654 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2053,17 +2053,34 @@
if (mIsVideo || mIsImage) {
// determine need for software renderer
bool usingSwRenderer = false;
- if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
- usingSwRenderer = true;
- haveNativeWindow = false;
- (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
- } else if (haveNativeWindow && !storingMetadataInDecodedBuffers()) {
- err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
- if (err != OK) {
- return err;
+ if (haveNativeWindow) {
+ bool requiresSwRenderer = false;
+ OMX_PARAM_U32TYPE param;
+ InitOMXParams(¶m);
+ param.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidRequiresSwRenderer,
+ ¶m, sizeof(param));
+
+ if (err == OK && param.nU32 == 1) {
+ requiresSwRenderer = true;
}
+
+ if (mComponentName.startsWith("OMX.google.") || requiresSwRenderer) {
+ usingSwRenderer = true;
+ haveNativeWindow = false;
+ (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
+ } else if (!storingMetadataInDecodedBuffers()) {
+ err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
+ if (err != OK) {
+ return err;
+ }
+ }
+
}
+
if (encoder) {
err = setupVideoEncoder(mime, msg, outputFormat, inputFormat);
} else {
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 00c5b40..4bc861e 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -108,6 +108,9 @@
selectedDeviceId,
selectedMicDirection,
selectedMicFieldDimension);
+ // Set caller name so it can be logged in destructor.
+ // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA
+ mRecord->setCallerName("media");
mInitCheck = mRecord->initCheck();
if (mInitCheck != OK) {
mRecord.clear();
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 94267a1..c6e753d 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -302,6 +302,12 @@
#endif
"/extractors", NULL, *newList);
+ RegisterExtractors("/system_ext/lib"
+#ifdef __LP64__
+ "64"
+#endif
+ "/extractors", NULL, *newList);
+
newList->sort(compareFunc);
gPlugins = newList;
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
index ddc818e..c9c1cd4 100644
--- a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
@@ -337,7 +337,10 @@
st = (Decoder_State *) spd_state;
/* mode verification */
-
+ if (mode < 0 || mode >= NUM_OF_MODES)
+ {
+ return (-1);
+ }
nb_bits = AMR_WB_COMPRESSED[mode];
*frame_length = AMR_WB_PCM_FRAME;
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp
index 8b7a124..47fe0b3 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/FastThread.cpp
@@ -309,7 +309,7 @@
// compute the delta value of clock_gettime(CLOCK_MONOTONIC)
uint32_t monotonicNs = nsec;
if (sec > 0 && sec < 4) {
- monotonicNs += sec * 1000000000;
+ monotonicNs += sec * 1000000000U; // unsigned to prevent signed overflow.
}
// compute raw CPU load = delta value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
uint32_t loadNs = 0;
@@ -325,7 +325,7 @@
}
loadNs = nsec;
if (sec > 0 && sec < 4) {
- loadNs += sec * 1000000000;
+ loadNs += sec * 1000000000U; // unsigned to prevent signed overflow.
}
} else {
// first time through the loop
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 105fa14..5d9c35a 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3051,6 +3051,10 @@
{
if (!mMasterMute) {
char value[PROPERTY_VALUE_MAX];
+ if (mOutDeviceTypeAddrs.empty()) {
+ ALOGD("ro.audio.silent is ignored since no output device is set");
+ return;
+ }
if (isSingleDeviceType(outDeviceTypes(), AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
ALOGD("ro.audio.silent will be ignored for threads on AUDIO_DEVICE_OUT_REMOTE_SUBMIX");
return;
@@ -4227,6 +4231,7 @@
(mPatch.sinks[0].id != sinkPortId);
mPatch = *patch;
mOutDeviceTypeAddrs = deviceTypeAddrs;
+ checkSilentMode_l();
if (mOutput->audioHwDev->supportsAudioPatches()) {
sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
@@ -9153,6 +9158,7 @@
if (isOutput()) {
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
mOutDeviceTypeAddrs = sinkDeviceTypeAddrs;
+ checkSilentMode_l();
} else {
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
mInDeviceTypeAddr = sourceDeviceTypeAddr;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 23d8329..4898d37 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -605,6 +605,7 @@
mediametrics::LogItem(mMetricsId)
.setPid(creatorPid)
.setUid(uid)
+ .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)uid)
.set(AMEDIAMETRICS_PROP_EVENT,
AMEDIAMETRICS_PROP_PREFIX_SERVER AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
.record();
@@ -2165,6 +2166,7 @@
mediametrics::LogItem(mMetricsId)
.setPid(creatorPid)
.setUid(uid)
+ .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)uid)
.set(AMEDIAMETRICS_PROP_EVENT, "server." AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
.record();
}
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index a757551..b82305d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -72,8 +72,8 @@
*/
status_t getOutputForAttr(const audio_attributes_t& attributes, uid_t uid,
audio_output_flags_t flags,
- sp<SwAudioOutputDescriptor> &primaryDesc,
- std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs);
+ sp<AudioPolicyMix> &primaryMix,
+ std::vector<sp<AudioPolicyMix>> *secondaryMixes);
sp<DeviceDescriptor> getDeviceAndMixForInputSource(audio_source_t inputSource,
const DeviceVector &availableDeviceTypes,
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index ed51389..fc1a59f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -150,11 +150,11 @@
status_t AudioPolicyMixCollection::getOutputForAttr(
const audio_attributes_t& attributes, uid_t uid,
audio_output_flags_t flags,
- sp<SwAudioOutputDescriptor> &primaryDesc,
- std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs)
+ sp<AudioPolicyMix> &primaryMix,
+ std::vector<sp<AudioPolicyMix>> *secondaryMixes)
{
ALOGV("getOutputForAttr() querying %zu mixes:", size());
- primaryDesc = 0;
+ primaryMix.clear();
for (size_t i = 0; i < size(); i++) {
sp<AudioPolicyMix> policyMix = itemAt(i);
const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
@@ -169,13 +169,7 @@
return INVALID_OPERATION;
}
- sp<SwAudioOutputDescriptor> policyDesc = policyMix->getOutput();
- if (!policyDesc) {
- ALOGV("%s: Skiping %zu: Mix has no output", __func__, i);
- continue;
- }
-
- if (primaryOutputMix && primaryDesc != 0) {
+ if (primaryOutputMix && primaryMix != nullptr) {
ALOGV("%s: Skiping %zu: Primary output already found", __func__, i);
continue; // Primary output already found
}
@@ -191,18 +185,13 @@
case MixMatchStatus::MATCH:;
}
- policyDesc->mPolicyMix = policyMix;
if (primaryOutputMix) {
- primaryDesc = policyDesc;
+ primaryMix = policyMix;
ALOGV("%s: Mix %zu: set primary desc", __func__, i);
} else {
- if (policyDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) {
- ALOGV("%s: Mix %zu ignored as secondaryOutput because not opened yet", __func__, i);
- } else {
- ALOGV("%s: Add a secondary desc %zu", __func__, i);
- if (secondaryDescs != nullptr) {
- secondaryDescs->push_back(policyDesc);
- }
+ ALOGV("%s: Add a secondary desc %zu", __func__, i);
+ if (secondaryMixes != nullptr) {
+ secondaryMixes->push_back(policyMix);
}
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 886e4c9..d31e443 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -320,7 +320,7 @@
{
String8 devAddress = (address == nullptr || !matchAddress) ? String8("") : String8(address);
// handle legacy remote submix case where the address was not always specified
- if (device_distinguishes_on_address(deviceType) && (devAddress.length() == 0)) {
+ if (audio_is_remote_submix_device(deviceType) && (devAddress.length() == 0)) {
devAddress = String8("0");
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f1c2ab5..13e2093 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -907,7 +907,7 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
bool *isRequestedDeviceForExclusiveUse,
- std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs,
+ std::vector<sp<AudioPolicyMix>> *secondaryMixes,
output_type_t *outputType)
{
DeviceVector outputDevices;
@@ -932,29 +932,44 @@
// The primary output is the explicit routing (eg. setPreferredDevice) if specified,
// otherwise, fallback to the dynamic policies, if none match, query the engine.
// Secondary outputs are always found by dynamic policies as the engine do not support them
- sp<SwAudioOutputDescriptor> policyDesc;
- status = mPolicyMixes.getOutputForAttr(*resultAttr, uid, *flags, policyDesc, secondaryDescs);
+ sp<AudioPolicyMix> primaryMix;
+ status = mPolicyMixes.getOutputForAttr(*resultAttr, uid, *flags, primaryMix, secondaryMixes);
if (status != OK) {
return status;
}
// Explicit routing is higher priority then any dynamic policy primary output
- bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && policyDesc != nullptr;
+ bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && primaryMix != nullptr;
// FIXME: in case of RENDER policy, the output capabilities should be checked
- if ((usePrimaryOutputFromPolicyMixes || !secondaryDescs->empty())
+ if ((usePrimaryOutputFromPolicyMixes
+ || (secondaryMixes != nullptr && !secondaryMixes->empty()))
&& !audio_is_linear_pcm(config->format)) {
ALOGD("%s: rejecting request as dynamic audio policy only support pcm", __func__);
return BAD_VALUE;
}
if (usePrimaryOutputFromPolicyMixes) {
- *output = policyDesc->mIoHandle;
- sp<AudioPolicyMix> mix = policyDesc->mPolicyMix.promote();
- if (mix != nullptr) {
- sp<DeviceDescriptor> deviceDesc =
- mAvailableOutputDevices.getDevice(mix->mDeviceType,
- mix->mDeviceAddress,
- AUDIO_FORMAT_DEFAULT);
+ sp<DeviceDescriptor> deviceDesc =
+ mAvailableOutputDevices.getDevice(primaryMix->mDeviceType,
+ primaryMix->mDeviceAddress,
+ AUDIO_FORMAT_DEFAULT);
+ sp<SwAudioOutputDescriptor> policyDesc = primaryMix->getOutput();
+ if (policyDesc == nullptr || (policyDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
+ audio_io_handle_t newOutput;
+ status = openDirectOutput(
+ *stream, session, config,
+ (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT),
+ DeviceVector(deviceDesc), &newOutput);
+ if (status != NO_ERROR) {
+ policyDesc = nullptr;
+ } else {
+ policyDesc = mOutputs.valueFor(newOutput);
+ primaryMix->setOutput(policyDesc);
+ }
+ }
+ if (policyDesc != nullptr) {
+ policyDesc->mPolicyMix = primaryMix;
+ *output = policyDesc->mIoHandle;
*selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
ALOGV("getOutputForAttr() returns output %d", *output);
@@ -1050,7 +1065,7 @@
const audio_port_handle_t requestedPortId = *selectedDeviceId;
audio_attributes_t resultAttr;
bool isRequestedDeviceForExclusiveUse = false;
- std::vector<sp<SwAudioOutputDescriptor>> secondaryOutputDescs;
+ std::vector<sp<AudioPolicyMix>> secondaryMixes;
const sp<DeviceDescriptor> requestedDevice =
mAvailableOutputDevices.getDeviceFromId(requestedPortId);
@@ -1061,14 +1076,20 @@
status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
config, flags, selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- &secondaryOutputDescs, outputType);
+ secondaryOutputs != nullptr ? &secondaryMixes : nullptr, outputType);
if (status != NO_ERROR) {
return status;
}
std::vector<wp<SwAudioOutputDescriptor>> weakSecondaryOutputDescs;
- for (auto& secondaryDesc : secondaryOutputDescs) {
- secondaryOutputs->push_back(secondaryDesc->mIoHandle);
- weakSecondaryOutputDescs.push_back(secondaryDesc);
+ if (secondaryOutputs != nullptr) {
+ for (auto &secondaryMix : secondaryMixes) {
+ sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput();
+ if (outputDesc != nullptr &&
+ outputDesc->mIoHandle != AUDIO_IO_HANDLE_NONE) {
+ secondaryOutputs->push_back(outputDesc->mIoHandle);
+ weakSecondaryOutputDescs.push_back(outputDesc);
+ }
+ }
}
audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
@@ -1093,6 +1114,118 @@
return NO_ERROR;
}
+status_t AudioPolicyManager::openDirectOutput(audio_stream_type_t stream,
+ audio_session_t session,
+ const audio_config_t *config,
+ audio_output_flags_t flags,
+ const DeviceVector &devices,
+ audio_io_handle_t *output) {
+
+ *output = AUDIO_IO_HANDLE_NONE;
+
+ // skip direct output selection if the request can obviously be attached to a mixed output
+ // and not explicitly requested
+ if (((flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
+ audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
+ audio_channel_count_from_out_mask(config->channel_mask) <= 2) {
+ return NAME_NOT_FOUND;
+ }
+
+ // Do not allow offloading if one non offloadable effect is enabled or MasterMono is enabled.
+ // This prevents creating an offloaded track and tearing it down immediately after start
+ // when audioflinger detects there is an active non offloadable effect.
+ // FIXME: We should check the audio session here but we do not have it in this context.
+ // This may prevent offloading in rare situations where effects are left active by apps
+ // in the background.
+ sp<IOProfile> profile;
+ if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
+ !(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
+ profile = getProfileForOutput(
+ devices, config->sample_rate, config->format, config->channel_mask,
+ flags, true /* directOnly */);
+ }
+
+ if (profile == nullptr) {
+ return NAME_NOT_FOUND;
+ }
+
+ // exclusive outputs for MMAP and Offload are enforced by different session ids.
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ if (!desc->isDuplicated() && (profile == desc->mProfile)) {
+ // reuse direct output if currently open by the same client
+ // and configured with same parameters
+ if ((config->sample_rate == desc->getSamplingRate()) &&
+ (config->format == desc->getFormat()) &&
+ (config->channel_mask == desc->getChannelMask()) &&
+ (session == desc->mDirectClientSession)) {
+ desc->mDirectOpenCount++;
+ ALOGI("%s reusing direct output %d for session %d", __func__,
+ mOutputs.keyAt(i), session);
+ *output = mOutputs.keyAt(i);
+ return NO_ERROR;
+ }
+ }
+ }
+
+ if (!profile->canOpenNewIo()) {
+ return NAME_NOT_FOUND;
+ }
+
+ sp<SwAudioOutputDescriptor> outputDesc =
+ new SwAudioOutputDescriptor(profile, mpClientInterface);
+
+ String8 address = getFirstDeviceAddress(devices);
+
+ // MSD patch may be using the only output stream that can service this request. Release
+ // MSD patch to prioritize this request over any active output on MSD.
+ AudioPatchCollection msdPatches = getMsdPatches();
+ for (size_t i = 0; i < msdPatches.size(); i++) {
+ const auto& patch = msdPatches[i];
+ for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
+ const struct audio_port_config *sink = &patch->mPatch.sinks[j];
+ if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
+ devices.containsDeviceWithType(sink->ext.device.type) &&
+ (address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
+ AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
+ releaseAudioPatch(patch->getHandle(), mUidCached);
+ break;
+ }
+ }
+ }
+
+ status_t status = outputDesc->open(config, devices, stream, flags, output);
+
+ // only accept an output with the requested parameters
+ if (status != NO_ERROR ||
+ (config->sample_rate != 0 && config->sample_rate != outputDesc->getSamplingRate()) ||
+ (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->getFormat()) ||
+ (config->channel_mask != 0 && config->channel_mask != outputDesc->getChannelMask())) {
+ ALOGV("%s failed opening direct output: output %d sample rate %d %d,"
+ "format %d %d, channel mask %04x %04x", __func__, *output, config->sample_rate,
+ outputDesc->getSamplingRate(), config->format, outputDesc->getFormat(),
+ config->channel_mask, outputDesc->getChannelMask());
+ if (*output != AUDIO_IO_HANDLE_NONE) {
+ outputDesc->close();
+ }
+ // fall back to mixer output if possible when the direct output could not be open
+ if (audio_is_linear_pcm(config->format) &&
+ config->sample_rate <= SAMPLE_RATE_HZ_MAX) {
+ return NAME_NOT_FOUND;
+ }
+ *output = AUDIO_IO_HANDLE_NONE;
+ return BAD_VALUE;
+ }
+ outputDesc->mDirectOpenCount = 1;
+ outputDesc->mDirectClientSession = session;
+
+ addOutput(*output, outputDesc);
+ mPreviousOutputs = mOutputs;
+ ALOGV("%s returns new direct output %d", __func__, *output);
+ mpClientInterface->onAudioPortListUpdate();
+ return NO_ERROR;
+}
+
audio_io_handle_t AudioPolicyManager::getOutputForDevices(
const DeviceVector &devices,
audio_session_t session,
@@ -1102,7 +1235,6 @@
bool forceMutingHaptic)
{
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status;
// Discard haptic channel mask when forcing muting haptic channels.
audio_channel_mask_t channelMask = forceMutingHaptic
@@ -1137,112 +1269,13 @@
ALOGV("Set VoIP and Direct output flags for PCM format");
}
-
- sp<IOProfile> profile;
-
- // skip direct output selection if the request can obviously be attached to a mixed output
- // and not explicitly requested
- if (((*flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
- audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
- audio_channel_count_from_out_mask(channelMask) <= 2) {
- goto non_direct_output;
- }
-
- // Do not allow offloading if one non offloadable effect is enabled or MasterMono is enabled.
- // This prevents creating an offloaded track and tearing it down immediately after start
- // when audioflinger detects there is an active non offloadable effect.
- // FIXME: We should check the audio session here but we do not have it in this context.
- // This may prevent offloading in rare situations where effects are left active by apps
- // in the background.
-
- if (((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
- !(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
- profile = getProfileForOutput(devices,
- config->sample_rate,
- config->format,
- channelMask,
- (audio_output_flags_t)*flags,
- true /* directOnly */);
- }
-
- if (profile != 0) {
- // exclusive outputs for MMAP and Offload are enforced by different session ids.
- for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- if (!desc->isDuplicated() && (profile == desc->mProfile)) {
- // reuse direct output if currently open by the same client
- // and configured with same parameters
- if ((config->sample_rate == desc->getSamplingRate()) &&
- (config->format == desc->getFormat()) &&
- (channelMask == desc->getChannelMask()) &&
- (session == desc->mDirectClientSession)) {
- desc->mDirectOpenCount++;
- ALOGI("%s reusing direct output %d for session %d", __func__,
- mOutputs.keyAt(i), session);
- return mOutputs.keyAt(i);
- }
- }
- }
-
- if (!profile->canOpenNewIo()) {
- goto non_direct_output;
- }
-
- sp<SwAudioOutputDescriptor> outputDesc =
- new SwAudioOutputDescriptor(profile, mpClientInterface);
-
- String8 address = getFirstDeviceAddress(devices);
-
- // MSD patch may be using the only output stream that can service this request. Release
- // MSD patch to prioritize this request over any active output on MSD.
- AudioPatchCollection msdPatches = getMsdPatches();
- for (size_t i = 0; i < msdPatches.size(); i++) {
- const auto& patch = msdPatches[i];
- for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
- const struct audio_port_config *sink = &patch->mPatch.sinks[j];
- if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
- devices.containsDeviceWithType(sink->ext.device.type) &&
- (address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
- AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
- releaseAudioPatch(patch->getHandle(), mUidCached);
- break;
- }
- }
- }
-
- status = outputDesc->open(config, devices, stream, *flags, &output);
-
- // only accept an output with the requested parameters
- if (status != NO_ERROR ||
- (config->sample_rate != 0 && config->sample_rate != outputDesc->getSamplingRate()) ||
- (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->getFormat()) ||
- (channelMask != 0 && channelMask != outputDesc->getChannelMask())) {
- ALOGV("%s failed opening direct output: output %d sample rate %d %d,"
- "format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate,
- outputDesc->getSamplingRate(), config->format, outputDesc->getFormat(),
- channelMask, outputDesc->getChannelMask());
- if (output != AUDIO_IO_HANDLE_NONE) {
- outputDesc->close();
- }
- // fall back to mixer output if possible when the direct output could not be open
- if (audio_is_linear_pcm(config->format) &&
- config->sample_rate <= SAMPLE_RATE_HZ_MAX) {
- goto non_direct_output;
- }
- return AUDIO_IO_HANDLE_NONE;
- }
- outputDesc->mDirectOpenCount = 1;
- outputDesc->mDirectClientSession = session;
-
- addOutput(output, outputDesc);
- mPreviousOutputs = mOutputs;
- ALOGV("%s returns new direct output %d", __func__, output);
- mpClientInterface->onAudioPortListUpdate();
+ audio_config_t directConfig = *config;
+ directConfig.channel_mask = channelMask;
+ status_t status = openDirectOutput(stream, session, &directConfig, *flags, devices, &output);
+ if (status != NAME_NOT_FOUND) {
return output;
}
-non_direct_output:
-
// A request for HW A/V sync cannot fallback to a mixed output because time
// stamps are embedded in audio data
if ((*flags & (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) != 0) {
@@ -2146,7 +2179,7 @@
if (!profile->canOpenNewIo()) {
for (size_t i = 0; i < mInputs.size(); ) {
- sp <AudioInputDescriptor> desc = mInputs.valueAt(i);
+ sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
if (desc->mProfile != profile) {
i++;
continue;
@@ -2886,8 +2919,8 @@
}
audio_config_t outputConfig = mix.mFormat;
audio_config_t inputConfig = mix.mFormat;
- // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
- // stereo and let audio flinger do the channel conversion if needed.
+ // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL
+ // in stereo and let audio flinger do the channel conversion if needed.
outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
rSubmixModule->addOutputProfile(address.c_str(), &outputConfig,
@@ -2917,10 +2950,11 @@
}
bool foundOutput = false;
- for (size_t j = 0 ; j < mOutputs.size() ; j++) {
+ // First try to find an already opened output supporting the device
+ for (size_t j = 0 ; j < mOutputs.size() && !foundOutput && res == NO_ERROR; j++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(j);
- if (desc->supportedDevices().contains(device)) {
+ if (!desc->isDuplicated() && desc->supportedDevices().contains(device)) {
if (mPolicyMixes.registerMix(mix, desc) != NO_ERROR) {
ALOGE("Could not register mix RENDER, dev=0x%X addr=%s", type,
address.string());
@@ -2928,10 +2962,26 @@
} else {
foundOutput = true;
}
- break;
}
}
-
+ // If no output found, try to find a direct output profile supporting the device
+ for (size_t i = 0; i < mHwModules.size() && !foundOutput && res == NO_ERROR; i++) {
+ sp<HwModule> module = mHwModules[i];
+ for (size_t j = 0;
+ j < module->getOutputProfiles().size() && !foundOutput && res == NO_ERROR;
+ j++) {
+ sp<IOProfile> profile = module->getOutputProfiles()[j];
+ if (profile->isDirectOutput() && profile->supportsDevice(device)) {
+ if (mPolicyMixes.registerMix(mix, nullptr) != NO_ERROR) {
+ ALOGE("Could not register mix RENDER, dev=0x%X addr=%s", type,
+ address.string());
+ res = INVALID_OPERATION;
+ } else {
+ foundOutput = true;
+ }
+ }
+ }
+ }
if (res != NO_ERROR) {
ALOGE(" Error registering mix %zu for device 0x%X addr %s",
i, type, address.string());
@@ -3014,58 +3064,67 @@
}
}
+// Returns true if all devices types match the predicate and are supported by one HW module
+bool AudioPolicyManager::areAllDevicesSupported(
+ const Vector<AudioDeviceTypeAddr>& devices,
+ std::function<bool(audio_devices_t)> predicate,
+ const char *context) {
+ for (size_t i = 0; i < devices.size(); i++) {
+ sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
+ devices[i].mType, devices[i].mAddress.c_str(), String8(),
+ AUDIO_FORMAT_DEFAULT, false /*allowToCreate*/, true /*matchAddress*/);
+ if (devDesc == nullptr || (predicate != nullptr && !predicate(devices[i].mType))) {
+ ALOGE("%s: device type %#x address %s not supported or not an output device",
+ context, devices[i].mType, devices[i].mAddress.c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
const Vector<AudioDeviceTypeAddr>& devices) {
ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size());
- // uid/device affinity is only for output devices
- for (size_t i = 0; i < devices.size(); i++) {
- if (!audio_is_output_device(devices[i].mType)) {
- ALOGE("setUidDeviceAffinities() device=%08x is NOT an output device",
- devices[i].mType);
- return BAD_VALUE;
- }
+ if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
+ return BAD_VALUE;
}
status_t res = mPolicyMixes.setUidDeviceAffinities(uid, devices);
- if (res == NO_ERROR) {
- // reevaluate outputs for all given devices
- for (size_t i = 0; i < devices.size(); i++) {
- sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
- devices[i].mType, devices[i].mAddress.c_str(), String8(),
- AUDIO_FORMAT_DEFAULT);
- SortedVector<audio_io_handle_t> outputs;
- if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- outputs) != NO_ERROR) {
- ALOGE("setUidDeviceAffinities() error in checkOutputsForDevice for device=%08x"
- " addr=%s", devices[i].mType, devices[i].mAddress.c_str());
- return INVALID_OPERATION;
- }
- }
+ if (res != NO_ERROR) {
+ ALOGE("%s() Could not set all device affinities for uid = %d", __FUNCTION__, uid);
+ return res;
}
- return res;
+
+ checkForDeviceAndOutputChanges();
+ updateCallAndOutputRouting();
+
+ return NO_ERROR;
}
status_t AudioPolicyManager::removeUidDeviceAffinities(uid_t uid) {
ALOGV("%s() uid=%d", __FUNCTION__, uid);
status_t res = mPolicyMixes.removeUidDeviceAffinities(uid);
if (res != NO_ERROR) {
- ALOGE("%s() Could not remove all device affinities fo uid = %d",
+ ALOGE("%s() Could not remove all device affinities for uid = %d",
__FUNCTION__, uid);
return INVALID_OPERATION;
}
+ checkForDeviceAndOutputChanges();
+ updateCallAndOutputRouting();
+
return res;
}
status_t AudioPolicyManager::setPreferredDeviceForStrategy(product_strategy_t strategy,
const AudioDeviceTypeAddr &device) {
- ALOGI("%s() strategy=%d device=%08x addr=%s", __FUNCTION__,
+ ALOGV("%s() strategy=%d device=%08x addr=%s", __FUNCTION__,
strategy, device.mType, device.mAddress.c_str());
- // strategy preferred device is only for output devices
- if (!audio_is_output_device(device.mType)) {
- ALOGE("%s() device=%08x is NOT an output device", __FUNCTION__, device.mType);
+
+ Vector<AudioDeviceTypeAddr> devices;
+ devices.add(device);
+ if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
return BAD_VALUE;
}
-
status_t status = mEngine->setPreferredDeviceForStrategy(strategy, device);
if (status != NO_ERROR) {
ALOGW("Engine could not set preferred device %08x %s for strategy %d",
@@ -3124,17 +3183,10 @@
status_t AudioPolicyManager::setUserIdDeviceAffinities(int userId,
const Vector<AudioDeviceTypeAddr>& devices) {
- ALOGI("%s() userId=%d num devices %zu", __FUNCTION__, userId, devices.size());
- // userId/device affinity is only for output devices
- for (size_t i = 0; i < devices.size(); i++) {
- if (!audio_is_output_device(devices[i].mType)) {
- ALOGE("%s() device=%08x is NOT an output device",
- __FUNCTION__,
- devices[i].mType);
- return BAD_VALUE;
- }
+ ALOGI("%s() userId=%d num devices %zu", __FUNCTION__, userId, devices.size());\
+ if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
+ return BAD_VALUE;
}
-
status_t status = mPolicyMixes.setUserIdDeviceAffinities(userId, devices);
if (status != NO_ERROR) {
ALOGE("%s() could not set device affinity for userId %d",
@@ -3641,12 +3693,11 @@
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
bool isRequestedDeviceForExclusiveUse = false;
- std::vector<sp<SwAudioOutputDescriptor>> secondaryOutputs;
output_type_t outputType;
getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
&stream, sourceDesc->uid(), &config, &flags,
&selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- &secondaryOutputs, &outputType);
+ nullptr, &outputType);
if (output == AUDIO_IO_HANDLE_NONE) {
ALOGV("%s no output for device %s",
__FUNCTION__, sinkDevice->toString().c_str());
@@ -4551,9 +4602,6 @@
mTtsOutputAvailable = true;
}
- if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
- continue;
- }
const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
sp<DeviceDescriptor> supportedDevice = 0;
@@ -4594,12 +4642,16 @@
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
- addOutput(output, outputDesc);
- setOutputDevices(outputDesc,
- DeviceVector(supportedDevice),
- true,
- 0,
- NULL);
+ if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
+ outputDesc->close();
+ } else {
+ addOutput(output, outputDesc);
+ setOutputDevices(outputDesc,
+ DeviceVector(supportedDevice),
+ true,
+ 0,
+ NULL);
+ }
}
// open input streams needed to access attached devices to validate
// mAvailableInputDevices list
@@ -4785,7 +4837,7 @@
if (output != AUDIO_IO_HANDLE_NONE) {
addOutput(output, desc);
- if (device_distinguishes_on_address(deviceType) && address != "0") {
+ if (audio_is_remote_submix_device(deviceType) && address != "0") {
sp<AudioPolicyMix> policyMix;
if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix)
== NO_ERROR) {
@@ -5275,10 +5327,19 @@
for (size_t i = 0; i < mOutputs.size(); i++) {
const sp<SwAudioOutputDescriptor>& outputDescriptor = mOutputs[i];
for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) {
- sp<SwAudioOutputDescriptor> desc;
- std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs;
+ sp<AudioPolicyMix> primaryMix;
+ std::vector<sp<AudioPolicyMix>> secondaryMixes;
status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(),
- client->flags(), desc, &secondaryDescs);
+ client->flags(), primaryMix, &secondaryMixes);
+ std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs;
+ for (auto &secondaryMix : secondaryMixes) {
+ sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput();
+ if (outputDesc != nullptr &&
+ outputDesc->mIoHandle != AUDIO_IO_HANDLE_NONE) {
+ secondaryDescs.push_back(outputDesc);
+ }
+ }
+
if (status != OK ||
!std::equal(client->getSecondaryOutputs().begin(),
client->getSecondaryOutputs().end(),
@@ -5482,21 +5543,17 @@
}
// check dynamic policies but only for primary descriptors (secondary not used for audible
// audio routing, only used for duplication for playback capture)
- sp<SwAudioOutputDescriptor> policyDesc;
+ sp<AudioPolicyMix> policyMix;
status_t status = mPolicyMixes.getOutputForAttr(attr, 0 /*uid unknown here*/,
- AUDIO_OUTPUT_FLAG_NONE, policyDesc, nullptr);
+ AUDIO_OUTPUT_FLAG_NONE, policyMix, nullptr);
if (status != OK) {
return status;
}
- if (policyDesc != nullptr) {
- sp<AudioPolicyMix> mix = policyDesc->mPolicyMix.promote();
- if (mix != nullptr) {
- AudioDeviceTypeAddr device(mix->mDeviceType, mix->mDeviceAddress.c_str());
- devices->push_back(device);
- return NO_ERROR;
- }
+ if (policyMix != nullptr && policyMix->getOutput() != nullptr) {
+ AudioDeviceTypeAddr device(policyMix->mDeviceType, policyMix->mDeviceAddress.c_str());
+ devices->push_back(device);
+ return NO_ERROR;
}
-
DeviceVector curDevices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false);
for (const auto& device : curDevices) {
devices->push_back(device->getDeviceTypeAddr());
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index c142880..b588f89 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -837,7 +837,7 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
bool *isRequestedDeviceForExclusiveUse,
- std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs,
+ std::vector<sp<AudioPolicyMix>> *secondaryMixes,
output_type_t *outputType);
// internal method to return the output handle for the given device and format
audio_io_handle_t getOutputForDevices(
@@ -848,6 +848,16 @@
audio_output_flags_t *flags,
bool forceMutingHaptic = false);
+ // Internal method checking if a direct output can be opened matching the requested
+ // attributes, flags, config and devices.
+ // If NAME_NOT_FOUND is returned, an attempt can be made to open a mixed output.
+ status_t openDirectOutput(
+ audio_stream_type_t stream,
+ audio_session_t session,
+ const audio_config_t *config,
+ audio_output_flags_t flags,
+ const DeviceVector &devices,
+ audio_io_handle_t *output);
/**
* @brief getInputForDevice selects an input handle for a given input device and
* requester context
@@ -926,6 +936,12 @@
int delayMs,
uid_t uid,
sp<AudioPatch> *patchDescPtr);
+
+ bool areAllDevicesSupported(
+ const Vector<AudioDeviceTypeAddr>& devices,
+ std::function<bool(audio_devices_t)> predicate,
+ const char* context);
+
};
};
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index 84da45a..a87de77 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -243,10 +243,15 @@
if (weight == 0) {
continue;
}
- // Top-left is inclusively clamped
- scaleCoordinates(entry.data.i32 + j, 1, zoomRatio, ClampInclusive);
- // Bottom-right is exclusively clamped
- scaleCoordinates(entry.data.i32 + j + 2, 1, zoomRatio, ClampExclusive);
+ // Top left (inclusive)
+ scaleCoordinates(entry.data.i32 + j, 1, zoomRatio, true /*clamp*/);
+ // Bottom right (exclusive): Use adjacent inclusive pixel to
+ // calculate.
+ entry.data.i32[j+2] -= 1;
+ entry.data.i32[j+3] -= 1;
+ scaleCoordinates(entry.data.i32 + j + 2, 1, zoomRatio, true /*clamp*/);
+ entry.data.i32[j+2] += 1;
+ entry.data.i32[j+3] += 1;
}
}
@@ -258,7 +263,7 @@
if (isResult) {
for (auto pts : kResultPointsToCorrectNoClamp) {
entry = metadata->find(pts);
- scaleCoordinates(entry.data.i32, entry.count / 2, zoomRatio, ClampOff);
+ scaleCoordinates(entry.data.i32, entry.count / 2, zoomRatio, false /*clamp*/);
}
}
@@ -282,10 +287,15 @@
if (weight == 0) {
continue;
}
- // Top-left is inclusively clamped
- scaleCoordinates(entry.data.i32 + j, 1, 1.0 / zoomRatio, ClampInclusive);
- // Bottom-right is exclusively clamped
- scaleCoordinates(entry.data.i32 + j + 2, 1, 1.0 / zoomRatio, ClampExclusive);
+ // Top-left (inclusive)
+ scaleCoordinates(entry.data.i32 + j, 1, 1.0 / zoomRatio, true /*clamp*/);
+ // Bottom-right (exclusive): Use adjacent inclusive pixel to
+ // calculate.
+ entry.data.i32[j+2] -= 1;
+ entry.data.i32[j+3] -= 1;
+ scaleCoordinates(entry.data.i32 + j + 2, 1, 1.0 / zoomRatio, true /*clamp*/);
+ entry.data.i32[j+2] += 1;
+ entry.data.i32[j+3] += 1;
}
}
for (auto rect : kRectsToCorrect) {
@@ -295,7 +305,7 @@
if (isResult) {
for (auto pts : kResultPointsToCorrectNoClamp) {
entry = metadata->find(pts);
- scaleCoordinates(entry.data.i32, entry.count / 2, 1.0 / zoomRatio, ClampOff);
+ scaleCoordinates(entry.data.i32, entry.count / 2, 1.0 / zoomRatio, false /*clamp*/);
}
}
@@ -309,28 +319,31 @@
}
void ZoomRatioMapper::scaleCoordinates(int32_t* coordPairs, int coordCount,
- float scaleRatio, ClampMode clamp) {
+ float scaleRatio, bool clamp) {
+ // A pixel's coordinate is represented by the position of its top-left corner.
+ // To avoid the rounding error, we use the coordinate for the center of the
+ // pixel instead:
+ // 1. First shift the coordinate system half pixel both horizontally and
+ // vertically, so that [x, y] is the center of the pixel, not the top-left corner.
+ // 2. Do zoom operation to scale the coordinate relative to the center of
+ // the active array (shifted by 0.5 pixel as well).
+ // 3. Shift the coordinate system back by directly using the pixel center
+ // coordinate.
for (int i = 0; i < coordCount * 2; i += 2) {
float x = coordPairs[i];
float y = coordPairs[i + 1];
- float xCentered = x - mArrayWidth / 2;
- float yCentered = y - mArrayHeight / 2;
+ float xCentered = x - (mArrayWidth - 2) / 2;
+ float yCentered = y - (mArrayHeight - 2) / 2;
float scaledX = xCentered * scaleRatio;
float scaledY = yCentered * scaleRatio;
- scaledX += mArrayWidth / 2;
- scaledY += mArrayHeight / 2;
+ scaledX += (mArrayWidth - 2) / 2;
+ scaledY += (mArrayHeight - 2) / 2;
+ coordPairs[i] = static_cast<int32_t>(std::round(scaledX));
+ coordPairs[i+1] = static_cast<int32_t>(std::round(scaledY));
// Clamp to within activeArray/preCorrectionActiveArray
- coordPairs[i] = static_cast<int32_t>(scaledX);
- coordPairs[i+1] = static_cast<int32_t>(scaledY);
- if (clamp != ClampOff) {
- int32_t right, bottom;
- if (clamp == ClampInclusive) {
- right = mArrayWidth - 1;
- bottom = mArrayHeight - 1;
- } else {
- right = mArrayWidth;
- bottom = mArrayHeight;
- }
+ if (clamp) {
+ int32_t right = mArrayWidth - 1;
+ int32_t bottom = mArrayHeight - 1;
coordPairs[i] =
std::min(right, std::max(0, coordPairs[i]));
coordPairs[i+1] =
@@ -343,25 +356,25 @@
void ZoomRatioMapper::scaleRects(int32_t* rects, int rectCount,
float scaleRatio) {
for (int i = 0; i < rectCount * 4; i += 4) {
- // Map from (l, t, width, height) to (l, t, r, b).
- // [l, t] is inclusive, and [r, b] is exclusive.
+ // Map from (l, t, width, height) to (l, t, l+width-1, t+height-1),
+ // where both top-left and bottom-right are inclusive.
int32_t coords[4] = {
rects[i],
rects[i + 1],
- rects[i] + rects[i + 2],
- rects[i + 1] + rects[i + 3]
+ rects[i] + rects[i + 2] - 1,
+ rects[i + 1] + rects[i + 3] - 1
};
// top-left
- scaleCoordinates(coords, 1, scaleRatio, ClampInclusive);
+ scaleCoordinates(coords, 1, scaleRatio, true /*clamp*/);
// bottom-right
- scaleCoordinates(coords+2, 1, scaleRatio, ClampExclusive);
+ scaleCoordinates(coords+2, 1, scaleRatio, true /*clamp*/);
// Map back to (l, t, width, height)
rects[i] = coords[0];
rects[i + 1] = coords[1];
- rects[i + 2] = coords[2] - coords[0];
- rects[i + 3] = coords[3] - coords[1];
+ rects[i + 2] = coords[2] - coords[0] + 1;
+ rects[i + 3] = coords[3] - coords[1] + 1;
}
}
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.h b/services/camera/libcameraservice/device3/ZoomRatioMapper.h
index aa3d913..698f87f 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.h
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.h
@@ -65,14 +65,8 @@
status_t updateCaptureResult(CameraMetadata *request, bool requestedZoomRatioIs1);
public: // Visible for testing. Do not use concurently.
- enum ClampMode {
- ClampOff,
- ClampInclusive,
- ClampExclusive,
- };
-
void scaleCoordinates(int32_t* coordPairs, int coordCount,
- float scaleRatio, ClampMode clamp);
+ float scaleRatio, bool clamp);
bool isValid() { return mIsValid; }
private:
diff --git a/services/camera/libcameraservice/tests/ZoomRatioTest.cpp b/services/camera/libcameraservice/tests/ZoomRatioTest.cpp
index 300da09..4e94991 100644
--- a/services/camera/libcameraservice/tests/ZoomRatioTest.cpp
+++ b/services/camera/libcameraservice/tests/ZoomRatioTest.cpp
@@ -171,35 +171,35 @@
std::array<int32_t, 16> originalCoords = {
0, 0, // top-left
- width, 0, // top-right
- 0, height, // bottom-left
- width, height, // bottom-right
- width / 2, height / 2, // center
- width / 4, height / 4, // top-left after 2x
- width / 3, height * 2 / 3, // bottom-left after 3x zoom
- width * 7 / 8, height / 2, // middle-right after 1.33x zoom
+ width - 1, 0, // top-right
+ 0, height - 1, // bottom-left
+ width - 1, height - 1, // bottom-right
+ (width - 1) / 2, (height - 1) / 2, // center
+ (width - 1) / 4, (height - 1) / 4, // top-left after 2x
+ (width - 1) / 3, (height - 1) * 2 / 3, // bottom-left after 3x zoom
+ (width - 1) * 7 / 8, (height - 1) / 2, // middle-right after 1.33x zoom
};
// Verify 1.0x zoom doesn't change the coordinates
auto coords = originalCoords;
- mapper.scaleCoordinates(coords.data(), coords.size()/2, 1.0f, ZoomRatioMapper::ClampOff);
+ mapper.scaleCoordinates(coords.data(), coords.size()/2, 1.0f, false /*clamp*/);
for (size_t i = 0; i < coords.size(); i++) {
EXPECT_EQ(coords[i], originalCoords[i]);
}
// Verify 2.0x zoom work as expected (no clamping)
std::array<float, 16> expected2xCoords = {
- - width / 2.0f, - height / 2.0f,// top-left
- width * 3 / 2.0f, - height / 2.0f, // top-right
- - width / 2.0f, height * 3 / 2.0f, // bottom-left
- width * 3 / 2.0f, height * 3 / 2.0f, // bottom-right
- width / 2.0f, height / 2.0f, // center
+ - (width - 1) / 2.0f, - (height - 1) / 2.0f,// top-left
+ (width - 1) * 3 / 2.0f, - (height - 1) / 2.0f, // top-right
+ - (width - 1) / 2.0f, (height - 1) * 3 / 2.0f, // bottom-left
+ (width - 1) * 3 / 2.0f, (height - 1) * 3 / 2.0f, // bottom-right
+ (width - 1) / 2.0f, (height - 1) / 2.0f, // center
0, 0, // top-left after 2x
- width / 6.0f, height - height / 6.0f, // bottom-left after 3x zoom
- width + width / 4.0f, height / 2.0f, // middle-right after 1.33x zoom
+ (width - 1) / 6.0f, (height - 1) * 5.0f / 6.0f, // bottom-left after 3x zoom
+ (width - 1) * 5.0f / 4.0f, (height - 1) / 2.0f, // middle-right after 1.33x zoom
};
coords = originalCoords;
- mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, ZoomRatioMapper::ClampOff);
+ mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, false /*clamp*/);
for (size_t i = 0; i < coords.size(); i++) {
EXPECT_LE(std::abs(coords[i] - expected2xCoords[i]), kMaxAllowedPixelError);
}
@@ -207,16 +207,16 @@
// Verify 2.0x zoom work as expected (with inclusive clamping)
std::array<float, 16> expected2xCoordsClampedInc = {
0, 0, // top-left
- static_cast<float>(width) - 1, 0, // top-right
- 0, static_cast<float>(height) - 1, // bottom-left
- static_cast<float>(width) - 1, static_cast<float>(height) - 1, // bottom-right
- width / 2.0f, height / 2.0f, // center
+ width - 1.0f, 0, // top-right
+ 0, height - 1.0f, // bottom-left
+ width - 1.0f, height - 1.0f, // bottom-right
+ (width - 1) / 2.0f, (height - 1) / 2.0f, // center
0, 0, // top-left after 2x
- width / 6.0f, height - height / 6.0f , // bottom-left after 3x zoom
- static_cast<float>(width) - 1, height / 2.0f, // middle-right after 1.33x zoom
+ (width - 1) / 6.0f, (height - 1) * 5.0f / 6.0f , // bottom-left after 3x zoom
+ width - 1.0f, (height - 1) / 2.0f, // middle-right after 1.33x zoom
};
coords = originalCoords;
- mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, ZoomRatioMapper::ClampInclusive);
+ mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, true /*clamp*/);
for (size_t i = 0; i < coords.size(); i++) {
EXPECT_LE(std::abs(coords[i] - expected2xCoordsClampedInc[i]), kMaxAllowedPixelError);
}
@@ -224,33 +224,33 @@
// Verify 2.0x zoom work as expected (with exclusive clamping)
std::array<float, 16> expected2xCoordsClampedExc = {
0, 0, // top-left
- static_cast<float>(width), 0, // top-right
- 0, static_cast<float>(height), // bottom-left
- static_cast<float>(width), static_cast<float>(height), // bottom-right
+ width - 1.0f, 0, // top-right
+ 0, height - 1.0f, // bottom-left
+ width - 1.0f, height - 1.0f, // bottom-right
width / 2.0f, height / 2.0f, // center
0, 0, // top-left after 2x
- width / 6.0f, height - height / 6.0f , // bottom-left after 3x zoom
- static_cast<float>(width), height / 2.0f, // middle-right after 1.33x zoom
+ (width - 1) / 6.0f, (height - 1) * 5.0f / 6.0f , // bottom-left after 3x zoom
+ width - 1.0f, height / 2.0f, // middle-right after 1.33x zoom
};
coords = originalCoords;
- mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, ZoomRatioMapper::ClampExclusive);
+ mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, true /*clamp*/);
for (size_t i = 0; i < coords.size(); i++) {
EXPECT_LE(std::abs(coords[i] - expected2xCoordsClampedExc[i]), kMaxAllowedPixelError);
}
// Verify 0.33x zoom work as expected
std::array<float, 16> expectedZoomOutCoords = {
- width / 3.0f, height / 3.0f, // top-left
- width * 2 / 3.0f, height / 3.0f, // top-right
- width / 3.0f, height * 2 / 3.0f, // bottom-left
- width * 2 / 3.0f, height * 2 / 3.0f, // bottom-right
- width / 2.0f, height / 2.0f, // center
- width * 5 / 12.0f, height * 5 / 12.0f, // top-left after 2x
- width * 4 / 9.0f, height * 5 / 9.0f, // bottom-left after 3x zoom-in
- width * 5 / 8.0f, height / 2.0f, // middle-right after 1.33x zoom-in
+ (width - 1) / 3.0f, (height - 1) / 3.0f, // top-left
+ (width - 1) * 2 / 3.0f, (height - 1) / 3.0f, // top-right
+ (width - 1) / 3.0f, (height - 1) * 2 / 3.0f, // bottom-left
+ (width - 1) * 2 / 3.0f, (height - 1) * 2 / 3.0f, // bottom-right
+ (width - 1) / 2.0f, (height - 1) / 2.0f, // center
+ (width - 1) * 5 / 12.0f, (height - 1) * 5 / 12.0f, // top-left after 2x
+ (width - 1) * 4 / 9.0f, (height - 1) * 5 / 9.0f, // bottom-left after 3x zoom-in
+ (width - 1) * 5 / 8.0f, (height - 1) / 2.0f, // middle-right after 1.33x zoom-in
};
coords = originalCoords;
- mapper.scaleCoordinates(coords.data(), coords.size()/2, 1.0f/3, ZoomRatioMapper::ClampOff);
+ mapper.scaleCoordinates(coords.data(), coords.size()/2, 1.0f/3, false /*clamp*/);
for (size_t i = 0; i < coords.size(); i++) {
EXPECT_LE(std::abs(coords[i] - expectedZoomOutCoords[i]), kMaxAllowedPixelError);
}
@@ -323,7 +323,8 @@
entry = metadata.find(ANDROID_SCALER_CROP_REGION);
ASSERT_EQ(entry.count, 4U);
for (int i = 0; i < 4; i++) {
- EXPECT_EQ(entry.data.i32[i], testDefaultCropSize[index][i]);
+ EXPECT_LE(std::abs(entry.data.i32[i] - testDefaultCropSize[index][i]),
+ kMaxAllowedPixelError);
}
entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
EXPECT_NEAR(entry.data.f[0], 2.0f, kMaxAllowedRatioError);
@@ -335,7 +336,7 @@
entry = metadata.find(ANDROID_SCALER_CROP_REGION);
ASSERT_EQ(entry.count, 4U);
for (int i = 0; i < 4; i++) {
- EXPECT_EQ(entry.data.i32[i], test2xCropRegion[index][i]);
+ EXPECT_LE(std::abs(entry.data.i32[i] - test2xCropRegion[index][i]), kMaxAllowedPixelError);
}
// Letter boxing crop region, zoomRatio is 1.0
diff --git a/services/mediametrics/TimeMachine.h b/services/mediametrics/TimeMachine.h
index 6861c78..c82778b 100644
--- a/services/mediametrics/TimeMachine.h
+++ b/services/mediametrics/TimeMachine.h
@@ -75,21 +75,30 @@
class KeyHistory {
public:
template <typename T>
- KeyHistory(T key, pid_t pid, uid_t uid, int64_t time)
+ KeyHistory(T key, uid_t allowUid, int64_t time)
: mKey(key)
- , mPid(pid)
- , mUid(uid)
+ , mAllowUid(allowUid)
, mCreationTime(time)
, mLastModificationTime(time)
{
- putValue(BUNDLE_PID, (int32_t)pid, time);
- putValue(BUNDLE_UID, (int32_t)uid, time);
+ // allowUid allows an untrusted client with a matching uid to set properties
+ // in this key.
+ // If allowUid == (uid_t)-1, no untrusted client may set properties in the key.
+ if (allowUid != (uid_t)-1) {
+ // Set ALLOWUID property here; does not change after key creation.
+ putValue(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)allowUid, time);
+ }
}
KeyHistory(const KeyHistory &other) = default;
+ // Return NO_ERROR only if the passed in uidCheck is -1 or matches
+ // the internal mAllowUid.
+ // An external submit will always have a valid uidCheck parameter.
+ // An internal get request within mediametrics will have a uidCheck == -1 which
+ // we allow to proceed.
status_t checkPermission(uid_t uidCheck) const {
- return uidCheck != (uid_t)-1 && uidCheck != mUid ? PERMISSION_DENIED : NO_ERROR;
+ return uidCheck != (uid_t)-1 && uidCheck != mAllowUid ? PERMISSION_DENIED : NO_ERROR;
}
template <typename T>
@@ -199,8 +208,7 @@
}
const std::string mKey;
- const pid_t mPid __unused;
- const uid_t mUid;
+ const uid_t mAllowUid;
const int64_t mCreationTime __unused;
int64_t mLastModificationTime;
@@ -276,10 +284,13 @@
(void)gc(garbage);
+ // We set the allowUid for client access on key creation.
+ int32_t allowUid = -1;
+ (void)item->get(AMEDIAMETRICS_PROP_ALLOWUID, &allowUid);
// no keylock needed here as we are sole owner
// until placed on mHistory.
keyHistory = std::make_shared<KeyHistory>(
- key, item->getPid(), item->getUid(), time);
+ key, allowUid, time);
mHistory[key] = keyHistory;
} else {
keyHistory = it->second;
diff --git a/services/mediametrics/tests/mediametrics_tests.cpp b/services/mediametrics/tests/mediametrics_tests.cpp
index 78eb71c..cf0dceb 100644
--- a/services/mediametrics/tests/mediametrics_tests.cpp
+++ b/services/mediametrics/tests/mediametrics_tests.cpp
@@ -813,6 +813,42 @@
ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
}
+TEST(mediametrics_tests, audio_analytics_permission2) {
+ constexpr int32_t transactionUid = 1010; // arbitrary
+ auto item = std::make_shared<mediametrics::Item>("audio.1");
+ (*item).set("one", (int32_t)1)
+ .set("two", (int32_t)2)
+ .set(AMEDIAMETRICS_PROP_ALLOWUID, transactionUid)
+ .setTimestamp(10);
+
+ // item2 submitted untrusted
+ auto item2 = std::make_shared<mediametrics::Item>("audio.1");
+ (*item2).set("three", (int32_t)3)
+ .setUid(transactionUid)
+ .setTimestamp(11);
+
+ auto item3 = std::make_shared<mediametrics::Item>("audio.2");
+ (*item3).set("four", (int32_t)4)
+ .setTimestamp(12);
+
+ android::mediametrics::AudioAnalytics audioAnalytics;
+
+ // untrusted entities cannot create a new key.
+ ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item, false /* isTrusted */));
+ ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item2, false /* isTrusted */));
+
+ // TODO: Verify contents of AudioAnalytics.
+ // Currently there is no getter API in AudioAnalytics besides dump.
+ ASSERT_EQ(9, audioAnalytics.dump(1000).second /* lines */);
+
+ ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
+ // untrusted entities can add to an existing key
+ ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
+
+ // Check that we have some info in the dump.
+ ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
+}
+
TEST(mediametrics_tests, audio_analytics_dump) {
auto item = std::make_shared<mediametrics::Item>("audio.1");
(*item).set("one", (int32_t)1)
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 044c361..dba9fb9 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -105,6 +105,7 @@
mediametrics::LogItem(mMetricsId)
.setPid(getOwnerProcessId())
.setUid(getOwnerUserId())
+ .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)getOwnerUserId())
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN)
// the following are immutable
.set(AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, (int32_t)getBufferCapacity())