Merge "audio policy: fix selected device Id in getOutputForAttr" into sc-dev
diff --git a/apex/Android.bp b/apex/Android.bp
index bf91bf7..d8a0b91 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -15,7 +15,10 @@
apex_defaults {
name: "com.android.media-defaults",
updatable: true,
- java_libs: ["updatable-media"],
+ java_libs: [
+ "updatable-media",
+ "service-media-s",
+ ],
multilib: {
first: {
// Extractor process runs only with the primary ABI.
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 3cf94d0..5e1e43e 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -62,7 +62,7 @@
],
cflags: [
"-fvisibility=hidden",
- "-DEXPORT=__attribute__ ((visibility (\"default\")))",
+ "-DEXPORT=__attribute__((visibility(\"default\")))",
"-Wall",
"-Wextra",
"-Werror",
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 38f7389..b806a25 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -221,6 +221,7 @@
kParamIndexDrcEffectType, // drc, enum
kParamIndexDrcOutputLoudness, // drc, float (dBFS)
kParamIndexDrcAlbumMode, // drc, enum
+ kParamIndexAudioFrameSize, // int
/* ============================== platform-defined parameters ============================== */
@@ -1969,9 +1970,20 @@
/**
* DRC output loudness in dBFS. Retrieved during decoding
*/
- typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcOutputLoudness>
+typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcOutputLoudness>
C2StreamDrcOutputLoudnessTuning;
- constexpr char C2_PARAMKEY_DRC_OUTPUT_LOUDNESS[] = "output.drc.output-loudness";
+constexpr char C2_PARAMKEY_DRC_OUTPUT_LOUDNESS[] = "output.drc.output-loudness";
+
+/**
+ * Audio frame size in samples.
+ *
+ * Audio encoders can expose this parameter to signal the desired audio frame
+ * size that corresponds to a single coded access unit.
+ * Default value is 0, meaning that the encoder accepts input buffers of any size.
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexAudioFrameSize>
+ C2StreamAudioFrameSizeInfo;
+constexpr char C2_PARAMKEY_AUDIO_FRAME_SIZE[] = "raw.audio-frame-size";
/* --------------------------------------- AAC components --------------------------------------- */
diff --git a/media/codec2/hidl/1.0/utils/types.cpp b/media/codec2/hidl/1.0/utils/types.cpp
index 1f0c856..72f7c43 100644
--- a/media/codec2/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hidl/1.0/utils/types.cpp
@@ -895,13 +895,12 @@
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
- // TODO: C2InfoBuffer is not implemented.
- (void)d;
- (void)s;
- (void)bufferPoolSender;
- (void)baseBlocks;
- (void)baseBlockIndices;
- LOG(INFO) << "InfoBuffer not implemented.";
+ d->index = static_cast<ParamIndex>(s.index());
+ Buffer& dBuffer = d->buffer;
+ if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2InfoBuffer::data";
+ return false;
+ }
return true;
}
@@ -1336,6 +1335,68 @@
return true;
}
+// InfoBuffer -> C2InfoBuffer
+bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
+ const std::vector<C2BaseBlock>& baseBlocks) {
+
+ // Currently, a non-null C2InfoBufer must contain exactly 1 block.
+ if (s.buffer.blocks.size() == 0) {
+ return true;
+ } else if (s.buffer.blocks.size() != 1) {
+ LOG(ERROR) << "Invalid InfoBuffer::Buffer "
+ "Currently, a C2InfoBuffer must contain exactly 1 block.";
+ return false;
+ }
+
+ const Block &sBlock = s.buffer.blocks[0];
+ if (sBlock.index >= baseBlocks.size()) {
+ LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
+ "Array index out of range.";
+ return false;
+ }
+ const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
+
+ // Parse meta.
+ std::vector<C2Param*> sBlockMeta;
+ if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
+ LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].meta.";
+ return false;
+ }
+
+ // Copy fence.
+ C2Fence dFence;
+ if (!objcpy(&dFence, sBlock.fence)) {
+ LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].fence.";
+ return false;
+ }
+
+ // Construct a block.
+ switch (baseBlock.type) {
+ case C2BaseBlock::LINEAR:
+ if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
+ sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
+ C2Hidl_RangeInfo *rangeInfo =
+ reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
+ d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
+ s.index,
+ baseBlock.linear->share(
+ rangeInfo->offset, rangeInfo->length, dFence)));
+ return true;
+ }
+ LOG(ERROR) << "Invalid Meta for C2BaseBlock::Linear InfoBuffer.";
+ break;
+ case C2BaseBlock::GRAPHIC:
+ // It's not used now
+ LOG(ERROR) << "Non-Used C2BaseBlock::type for InfoBuffer.";
+ break;
+ default:
+ LOG(ERROR) << "Invalid C2BaseBlock::type for InfoBuffer.";
+ break;
+ }
+
+ return false;
+}
+
// FrameData -> C2FrameData
bool objcpy(C2FrameData* d, const FrameData& s,
const std::vector<C2BaseBlock>& baseBlocks) {
@@ -1370,8 +1431,18 @@
}
}
- // TODO: Implement this once C2InfoBuffer has constructors.
d->infoBuffers.clear();
+ if (s.infoBuffers.size() == 0) {
+ // InfoBuffer is optional
+ return true;
+ }
+ d->infoBuffers.reserve(s.infoBuffers.size());
+ for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
+ if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
+ LOG(ERROR) << "Invalid Framedata::infoBuffers.";
+ return false;
+ }
+ }
return true;
}
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index d9a7804..28549d0 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -14,7 +14,6 @@
],
required: [
- "libaudiohal@2.0",
"libaudiohal@4.0",
"libaudiohal@5.0",
"libaudiohal@6.0",
diff --git a/media/libaudiohal/FactoryHalHidl.cpp b/media/libaudiohal/FactoryHalHidl.cpp
index 7228b22..e420d07 100644
--- a/media/libaudiohal/FactoryHalHidl.cpp
+++ b/media/libaudiohal/FactoryHalHidl.cpp
@@ -35,7 +35,6 @@
"6.0",
"5.0",
"4.0",
- "2.0",
nullptr
};
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index fe47881..0276e4b 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -54,22 +54,6 @@
}
cc_library_shared {
- name: "libaudiohal@2.0",
- defaults: ["libaudiohal_default"],
- shared_libs: [
- "android.hardware.audio.common@2.0",
- "android.hardware.audio.common@2.0-util",
- "android.hardware.audio.effect@2.0",
- "android.hardware.audio@2.0",
- ],
- cflags: [
- "-DMAJOR_VERSION=2",
- "-DMINOR_VERSION=0",
- "-include common/all-versions/VersionMacro.h",
- ]
-}
-
-cc_library_shared {
name: "libaudiohal@4.0",
defaults: ["libaudiohal_default"],
shared_libs: [
diff --git a/media/libmediahelper/tests/typeconverter_tests.cpp b/media/libmediahelper/tests/typeconverter_tests.cpp
index d7bfb89..181d636 100644
--- a/media/libmediahelper/tests/typeconverter_tests.cpp
+++ b/media/libmediahelper/tests/typeconverter_tests.cpp
@@ -182,8 +182,9 @@
audio_format_t format;
EXPECT_TRUE(FormatConverter::fromString(stringVal, format))
<< "Conversion of \"" << stringVal << "\" failed";
- EXPECT_TRUE(audio_is_valid_format(format))
- << "Converted format \"" << stringVal << "\" is invalid";
+ EXPECT_EQ(enumVal != xsd::AudioFormat::AUDIO_FORMAT_DEFAULT,
+ audio_is_valid_format(format))
+ << "Validity of \"" << stringVal << "\" is not as expected";
EXPECT_EQ(stringVal, toString(format));
}
}
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index c2e1dc9..3dfd850 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -7,7 +7,6 @@
name: "libmediametrics",
srcs: [
- "IMediaMetricsService.cpp",
"MediaMetricsItem.cpp",
"MediaMetrics.cpp",
],
@@ -17,6 +16,7 @@
"libcutils",
"liblog",
"libutils",
+ "mediametricsservice-aidl-unstable-cpp",
],
export_include_dirs: ["include"],
@@ -58,3 +58,21 @@
"//frameworks/base/media/jni",
],
}
+
+aidl_interface {
+ name: "mediametricsservice-aidl",
+ unstable: true,
+ local_include_dir: "aidl",
+ vendor_available: true,
+ srcs: [
+ "aidl/android/media/IMediaMetricsService.aidl",
+ ],
+ double_loadable: true,
+ backend: {
+ cpp: {
+ apex_available: [
+ "//apex_available:platform",
+ ],
+ },
+ },
+}
diff --git a/media/libmediametrics/MediaMetricsItem.cpp b/media/libmediametrics/MediaMetricsItem.cpp
index 7cdbe5f..f4371fd 100644
--- a/media/libmediametrics/MediaMetricsItem.cpp
+++ b/media/libmediametrics/MediaMetricsItem.cpp
@@ -31,8 +31,9 @@
#include <utils/SortedVector.h>
#include <utils/threads.h>
+#include <android/media/BnMediaMetricsService.h> // for direct Binder access
+#include <android/media/IMediaMetricsService.h>
#include <binder/IServiceManager.h>
-#include <media/IMediaMetricsService.h>
#include <media/MediaMetricsItem.h>
#include <private/android_filesystem_config.h>
@@ -278,17 +279,18 @@
// calls the appropriate daemon
bool mediametrics::Item::selfrecord() {
ALOGD_IF(DEBUG_API, "%s: delivering %s", __func__, this->toString().c_str());
- sp<IMediaMetricsService> svc = getService();
- if (svc != NULL) {
- status_t status = svc->submit(this);
- if (status != NO_ERROR) {
- ALOGW("%s: failed to record: %s", __func__, this->toString().c_str());
- return false;
- }
- return true;
- } else {
+
+ char *str;
+ size_t size;
+ status_t status = writeToByteString(&str, &size);
+ if (status == NO_ERROR) {
+ status = submitBuffer(str, size);
+ }
+ if (status != NO_ERROR) {
+ ALOGW("%s: failed to record: %s", __func__, this->toString().c_str());
return false;
}
+ return true;
}
//static
@@ -327,7 +329,7 @@
static sp<MediaMetricsDeathNotifier> sNotifier;
// static
-sp<IMediaMetricsService> BaseItem::sMediaMetricsService;
+sp<media::IMediaMetricsService> BaseItem::sMediaMetricsService;
static std::mutex sServiceMutex;
static int sRemainingBindAttempts = SVC_TRIES;
@@ -339,29 +341,67 @@
}
// static
-bool BaseItem::submitBuffer(const char *buffer, size_t size) {
-/*
- mediametrics::Item item;
- status_t status = item.readFromByteString(buffer, size);
- ALOGD("%s: status:%d, size:%zu, item:%s", __func__, status, size, item.toString().c_str());
- return item.selfrecord();
- */
-
+status_t BaseItem::submitBuffer(const char *buffer, size_t size) {
ALOGD_IF(DEBUG_API, "%s: delivering %zu bytes", __func__, size);
- sp<IMediaMetricsService> svc = getService();
- if (svc != nullptr) {
- const status_t status = svc->submitBuffer(buffer, size);
- if (status != NO_ERROR) {
- ALOGW("%s: failed(%d) to record: %zu bytes", __func__, status, size);
- return false;
- }
- return true;
+
+ // Validate size
+ if (size > std::numeric_limits<int32_t>::max()) return BAD_VALUE;
+
+ // Do we have the service available?
+ sp<media::IMediaMetricsService> svc = getService();
+ if (svc == nullptr) return NO_INIT;
+
+ ::android::status_t status = NO_ERROR;
+ if constexpr (/* DISABLES CODE */ (false)) {
+ // THIS PATH IS FOR REFERENCE ONLY.
+ // It is compiled so that any changes to IMediaMetricsService::submitBuffer()
+ // will lead here. If this code is changed, the else branch must
+ // be changed as well.
+ //
+ // Use the AIDL calling interface - this is a bit slower as a byte vector must be
+ // constructed. As the call is one-way, the only a transaction error occurs.
+ status = svc->submitBuffer({buffer, buffer + size}).transactionError();
+ } else {
+ // Use the Binder calling interface - this direct implementation avoids
+ // malloc/copy/free for the vector and reduces the overhead for logging.
+ // We based this off of the AIDL generated file:
+ // out/soong/.intermediates/frameworks/av/media/libmediametrics/mediametricsservice-aidl-unstable-cpp-source/gen/android/media/IMediaMetricsService.cpp
+ // TODO: Create an AIDL C++ back end optimized form of vector writing.
+ ::android::Parcel _aidl_data;
+ ::android::Parcel _aidl_reply; // we don't care about this as it is one-way.
+
+ status = _aidl_data.writeInterfaceToken(svc->getInterfaceDescriptor());
+ if (status != ::android::OK) goto _aidl_error;
+
+ status = _aidl_data.writeInt32(static_cast<int32_t>(size));
+ if (status != ::android::OK) goto _aidl_error;
+
+ status = _aidl_data.write(buffer, static_cast<int32_t>(size));
+ if (status != ::android::OK) goto _aidl_error;
+
+ status = ::android::IInterface::asBinder(svc)->transact(
+ ::android::media::BnMediaMetricsService::TRANSACTION_submitBuffer,
+ _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_ONEWAY);
+
+ // AIDL permits setting a default implementation for additional functionality.
+ // See go/aog/713984. This is not used here.
+ // if (status == ::android::UNKNOWN_TRANSACTION
+ // && ::android::media::IMediaMetricsService::getDefaultImpl()) {
+ // status = ::android::media::IMediaMetricsService::getDefaultImpl()
+ // ->submitBuffer(immutableByteVectorFromBuffer(buffer, size))
+ // .transactionError();
+ // }
}
- return false;
+
+ if (status == NO_ERROR) return NO_ERROR;
+
+ _aidl_error:
+ ALOGW("%s: failed(%d) to record: %zu bytes", __func__, status, size);
+ return status;
}
//static
-sp<IMediaMetricsService> BaseItem::getService() {
+sp<media::IMediaMetricsService> BaseItem::getService() {
static const char *servicename = "media.metrics";
static const bool enabled = isEnabled(); // singleton initialized
@@ -379,7 +419,7 @@
if (sm != nullptr) {
sp<IBinder> binder = sm->getService(String16(servicename));
if (binder != nullptr) {
- sMediaMetricsService = interface_cast<IMediaMetricsService>(binder);
+ sMediaMetricsService = interface_cast<media::IMediaMetricsService>(binder);
sNotifier = new MediaMetricsDeathNotifier();
binder->linkToDeath(sNotifier);
} else {
diff --git a/media/libmediametrics/aidl/android/media/IMediaMetricsService.aidl b/media/libmediametrics/aidl/android/media/IMediaMetricsService.aidl
new file mode 100644
index 0000000..b14962d
--- /dev/null
+++ b/media/libmediametrics/aidl/android/media/IMediaMetricsService.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * MediaMetrics service interface
+ *
+ * {@hide}
+ */
+interface IMediaMetricsService {
+ oneway void submitBuffer(in byte[] buffer);
+}
diff --git a/media/libmediametrics/include/media/IMediaMetricsService.h b/media/libmediametrics/include/media/IMediaMetricsService.h
deleted file mode 100644
index d6871ec..0000000
--- a/media/libmediametrics/include/media/IMediaMetricsService.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IMEDIAANALYTICSSERVICE_H
-#define ANDROID_IMEDIAANALYTICSSERVICE_H
-
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-#include <sys/types.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/RefBase.h>
-#include <utils/List.h>
-
-#include <binder/IServiceManager.h>
-
-#include <media/MediaMetricsItem.h>
-
-namespace android {
-
-class IMediaMetricsService: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(MediaMetricsService);
-
- /**
- * Submits the indicated record to the mediaanalytics service, where
- * it will be merged (if appropriate) with incomplete records that
- * share the same key and sessionID.
- *
- * \param item the item to submit.
- * \return status which is negative if an error is detected (some errors
- may be silent and return 0 - success).
- */
- virtual status_t submit(mediametrics::Item *item) = 0;
-
- virtual status_t submitBuffer(const char *buffer, size_t length) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnMediaMetricsService: public BnInterface<IMediaMetricsService>
-{
-public:
- status_t onTransact(uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0) override;
-
-protected:
- // Internal call where release is true if the service is to delete the item.
- virtual status_t submitInternal(
- mediametrics::Item *item, bool release) = 0;
-};
-
-}; // namespace android
-
-#endif // ANDROID_IMEDIASTATISTICSSERVICE_H
diff --git a/media/libmediametrics/include/media/MediaMetricsItem.h b/media/libmediametrics/include/media/MediaMetricsItem.h
index 303343f..428992c 100644
--- a/media/libmediametrics/include/media/MediaMetricsItem.h
+++ b/media/libmediametrics/include/media/MediaMetricsItem.h
@@ -32,7 +32,8 @@
namespace android {
-class IMediaMetricsService;
+namespace media { class IMediaMetricsService; }
+
class Parcel;
/*
@@ -239,7 +240,10 @@
public:
// are we collecting metrics data
static bool isEnabled();
- static sp<IMediaMetricsService> getService();
+ // returns the MediaMetrics service if active.
+ static sp<media::IMediaMetricsService> getService();
+ // submits a raw buffer directly to the MediaMetrics service - this is highly optimized.
+ static status_t submitBuffer(const char *buffer, size_t len);
protected:
static constexpr const char * const EnabledProperty = "media.metrics.enabled";
@@ -247,10 +251,9 @@
static const int EnabledProperty_default = 1;
// let's reuse a binder connection
- static sp<IMediaMetricsService> sMediaMetricsService;
+ static sp<media::IMediaMetricsService> sMediaMetricsService;
static void dropInstance();
- static bool submitBuffer(const char *buffer, size_t len);
template <typename T>
struct is_item_type {
@@ -573,7 +576,7 @@
bool record() {
return updateHeader()
- && BaseItem::submitBuffer(getBuffer(), getLength());
+ && BaseItem::submitBuffer(getBuffer(), getLength()) == OK;
}
bool isValid () const {
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index e3c0b05..994695f 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -238,7 +238,12 @@
int32_t operatingRate = getDefaultOperatingRate(encoderFormat);
if (operatingRate != -1) {
- SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat, operatingRate);
+ float tmpf;
+ int32_t tmpi;
+ if (!AMediaFormat_getFloat(encoderFormat, AMEDIAFORMAT_KEY_OPERATING_RATE, &tmpf) &&
+ !AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_OPERATING_RATE, &tmpi)) {
+ AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_OPERATING_RATE, operatingRate);
+ }
}
SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
@@ -260,8 +265,8 @@
return AMEDIA_ERROR_INVALID_PARAMETER;
}
- // TODO: replace __ANDROID_API_FUTURE__with 31 when it's official (b/178144708)
- #define __TRANSCODING_MIN_API__ __ANDROID_API_FUTURE__
+// TODO: replace __ANDROID_API_FUTURE__with 31 when it's official (b/178144708)
+#define __TRANSCODING_MIN_API__ __ANDROID_API_FUTURE__
AMediaCodec* encoder;
if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
index e0b2050..42933e6 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
@@ -33,6 +33,7 @@
#include <binder/ProcessState.h>
#include <fcntl.h>
#include <media/MediaTranscoder.h>
+#include <media/NdkCommon.h>
#include <iostream>
@@ -87,6 +88,7 @@
AMediaFormat* videoFormat = AMediaFormat_new();
AMediaFormat_setInt32(videoFormat, AMEDIAFORMAT_KEY_BIT_RATE, kVideoBitRate);
+ AMediaFormat_setString(videoFormat, AMEDIAFORMAT_KEY_MIME, AMEDIA_MIMETYPE_VIDEO_AVC);
return videoFormat;
}
@@ -222,7 +224,7 @@
}
static void SetMaxOperatingRate(AMediaFormat* format) {
- AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_OPERATING_RATE, INT32_MAX);
+ AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_OPERATING_RATE, INT32_MAX);
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_PRIORITY, 1);
}
diff --git a/media/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml b/media/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
index 6d781cd..e40a507 100644
--- a/media/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
+++ b/media/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
@@ -24,6 +24,7 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="{MODULE}" />
+ <option name="native-test-timeout" value="10m" />
</test>
</configuration>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 1f5b8d2..eaf0d10 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2961,7 +2961,10 @@
auto backInserter = std::back_inserter(metadata.tracks);
for (const sp<Track> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- track->copyMetadataTo(backInserter);
+ // Do not forward metadata for PatchTrack with unspecified stream type
+ if (track->streamType() != AUDIO_STREAM_PATCH) {
+ track->copyMetadataTo(backInserter);
+ }
}
sendMetadataToBackend_l(metadata);
}
@@ -8101,6 +8104,10 @@
}
StreamInHalInterface::SinkMetadata metadata;
for (const sp<RecordTrack> &track : mActiveTracks) {
+ // Do not forward PatchRecord metadata to audio HAL
+ if (track->isPatchTrack()) {
+ continue;
+ }
// No track is invalid as this is called after prepareTrack_l in the same critical section
record_track_metadata_v7_t trackMetadata;
trackMetadata.base = {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c0a8f9d..e721a78 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1064,8 +1064,7 @@
*output = AUDIO_IO_HANDLE_NONE;
if (!msdDevices.isEmpty()) {
*output = getOutputForDevices(msdDevices, session, *stream, config, flags);
- sp<DeviceDescriptor> device = outputDevices.isEmpty() ? nullptr : outputDevices.itemAt(0);
- if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(device) == NO_ERROR) {
+ if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatches(&outputDevices) == NO_ERROR) {
ALOGV("%s() Using MSD devices %s instead of devices %s",
__func__, msdDevices.toString().c_str(), outputDevices.toString().c_str());
} else {
@@ -1081,6 +1080,12 @@
}
*selectedDeviceId = getFirstDeviceId(outputDevices);
+ for (auto &outputDevice : outputDevices) {
+ if (outputDevice->getId() == getConfig().getDefaultOutputDevice()->getId()) {
+ *selectedDeviceId = outputDevice->getId();
+ break;
+ }
+ }
if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
*outputType = API_OUTPUT_TELEPHONY_TX;
@@ -1223,24 +1228,9 @@
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;
- }
- }
- }
+ // An MSD patch may be using the only output stream that can service this request. Release
+ // all MSD patches to prioritize this request over any active output on MSD.
+ releaseMsdPatches(devices);
status_t status = outputDesc->open(config, devices, stream, flags, output);
@@ -1414,7 +1404,8 @@
}
AudioProfileVector deviceProfiles;
for (const auto &outProfile : outputProfiles) {
- if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0)) {
+ if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) &&
+ outProfile->supportsDevice(outputDevice)) {
appendAudioProfiles(deviceProfiles, outProfile->getAudioProfiles());
}
}
@@ -1482,40 +1473,85 @@
return patchBuilder;
}
-status_t AudioPolicyManager::setMsdPatch(const sp<DeviceDescriptor> &outputDevice) {
- sp<DeviceDescriptor> device = outputDevice;
- if (device == nullptr) {
+status_t AudioPolicyManager::setMsdPatches(const DeviceVector *outputDevices) {
+ DeviceVector devices;
+ if (outputDevices != nullptr && outputDevices->size() > 0) {
+ devices.add(*outputDevices);
+ } else {
// Use media strategy for unspecified output device. This should only
// occur on checkForDeviceAndOutputChanges(). Device connection events may
// therefore invalidate explicit routing requests.
- DeviceVector devices = mEngine->getOutputDevicesForAttributes(
+ devices = mEngine->getOutputDevicesForAttributes(
attributes_initializer(AUDIO_USAGE_MEDIA), nullptr, false /*fromCache*/);
- LOG_ALWAYS_FATAL_IF(devices.isEmpty(), "no outpudevice to set Msd Patch");
- device = devices.itemAt(0);
+ LOG_ALWAYS_FATAL_IF(devices.isEmpty(), "no output device to set MSD patch");
}
- ALOGV("%s() for device %s", __func__, device->toString().c_str());
- PatchBuilder patchBuilder = buildMsdPatch(device);
- const struct audio_patch* patch = patchBuilder.patch();
- const AudioPatchCollection msdPatches = getMsdPatches();
- if (!msdPatches.isEmpty()) {
- LOG_ALWAYS_FATAL_IF(msdPatches.size() > 1,
- "The current MSD prototype only supports one output patch");
- sp<AudioPatch> currentPatch = msdPatches.valueAt(0);
- if (audio_patches_are_equal(¤tPatch->mPatch, patch)) {
- return NO_ERROR;
+ std::vector<PatchBuilder> patchesToCreate;
+ for (auto i = 0u; i < devices.size(); ++i) {
+ ALOGV("%s() for device %s", __func__, devices[i]->toString().c_str());
+ patchesToCreate.push_back(buildMsdPatch(devices[i]));
+ }
+ // Retain only the MSD patches associated with outputDevices request.
+ // Tear down the others, and create new ones as needed.
+ AudioPatchCollection patchesToRemove = getMsdPatches();
+ for (auto it = patchesToCreate.begin(); it != patchesToCreate.end(); ) {
+ auto retainedPatch = false;
+ for (auto i = 0u; i < patchesToRemove.size(); ++i) {
+ if (audio_patches_are_equal(it->patch(), &patchesToRemove[i]->mPatch)) {
+ patchesToRemove.removeItemsAt(i);
+ retainedPatch = true;
+ break;
+ }
}
+ if (retainedPatch) {
+ it = patchesToCreate.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if (patchesToCreate.size() == 0 && patchesToRemove.size() == 0) {
+ return NO_ERROR;
+ }
+ for (auto i = 0u; i < patchesToRemove.size(); ++i) {
+ auto ¤tPatch = patchesToRemove.valueAt(i);
releaseAudioPatch(currentPatch->getHandle(), mUidCached);
}
- status_t status = installPatch(__func__, -1 /*index*/, nullptr /*patchHandle*/,
- patch, 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
- ALOGE_IF(status != NO_ERROR, "%s() error %d creating MSD audio patch", __func__, status);
- ALOGI_IF(status == NO_ERROR, "%s() Patch created from MSD_IN to "
- "device:%s (format:%#x channels:%#x samplerate:%d)", __func__,
- device->toString().c_str(), patch->sources[0].format,
- patch->sources[0].channel_mask, patch->sources[0].sample_rate);
+ status_t status = NO_ERROR;
+ for (const auto &p : patchesToCreate) {
+ auto currStatus = installPatch(__func__, -1 /*index*/, nullptr /*patchHandle*/,
+ p.patch(), 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
+ char message[256];
+ snprintf(message, sizeof(message), "%s() %s: creating MSD patch from device:IN_BUS to "
+ "device:%#x (format:%#x channels:%#x samplerate:%d)", __func__,
+ currStatus == NO_ERROR ? "Success" : "Error",
+ p.patch()->sinks[0].ext.device.type, p.patch()->sources[0].format,
+ p.patch()->sources[0].channel_mask, p.patch()->sources[0].sample_rate);
+ if (currStatus == NO_ERROR) {
+ ALOGD("%s", message);
+ } else {
+ ALOGE("%s", message);
+ if (status == NO_ERROR) {
+ status = currStatus;
+ }
+ }
+ }
return status;
}
+void AudioPolicyManager::releaseMsdPatches(const DeviceVector& devices) {
+ 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.getDevice(sink->ext.device.type,
+ String8(sink->ext.device.address), AUDIO_FORMAT_DEFAULT) != nullptr) {
+ releaseAudioPatch(patch->getHandle(), mUidCached);
+ break;
+ }
+ }
+ }
+}
+
audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
audio_output_flags_t flags,
audio_format_t format,
@@ -5319,8 +5355,13 @@
}
}
if (!directOutputOpen) {
- ALOGV("no direct outputs open, reset MSD patch");
- setMsdPatch();
+ ALOGV("no direct outputs open, reset MSD patches");
+ // TODO: The MSD patches to be established here may differ to current MSD patches due to
+ // how output devices for patching are resolved. Avoid by caching and reusing the
+ // arguments to mEngine->getOutputDevicesForAttributes() when resolving which output
+ // devices to patch to. This may be complicated by the fact that devices may become
+ // unavailable.
+ setMsdPatches();
}
}
}
@@ -5387,7 +5428,13 @@
if (onOutputsChecked != nullptr && onOutputsChecked()) checkA2dpSuspend();
updateDevicesAndOutputs();
if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
- setMsdPatch();
+ // TODO: The MSD patches to be established here may differ to current MSD patches due to how
+ // output devices for patching are resolved. Nevertheless, AudioTracks affected by device
+ // configuration changes will ultimately be rerouted correctly. We can still avoid
+ // unnecessary rerouting by caching and reusing the arguments to
+ // mEngine->getOutputDevicesForAttributes() when resolving which output devices to patch to.
+ // This may be complicated by the fact that devices may become unavailable.
+ setMsdPatches();
}
// an event that changed routing likely occurred, inform upper layers
mpClientInterface->onRoutingUpdated();
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 3c55b63..d3ceb1b 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -848,13 +848,6 @@
// end point.
audio_port_handle_t mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
-private:
- void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
-
- // Add or remove AC3 DTS encodings based on user preferences.
- void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
- void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
-
// Support for Multi-Stream Decoder (MSD) module
sp<DeviceDescriptor> getMsdAudioInDevice() const;
DeviceVector getMsdAudioOutDevices() const;
@@ -864,7 +857,14 @@
audio_port_config *sourceConfig,
audio_port_config *sinkConfig) const;
PatchBuilder buildMsdPatch(const sp<DeviceDescriptor> &outputDevice) const;
- status_t setMsdPatch(const sp<DeviceDescriptor> &outputDevice = nullptr);
+ status_t setMsdPatches(const DeviceVector *outputDevices = nullptr);
+ void releaseMsdPatches(const DeviceVector& devices);
+private:
+ void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
+
+ // Add or remove AC3 DTS encodings based on user preferences.
+ void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
+ void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
// If any, resolve any "dynamic" fields of an Audio Profiles collection
void updateAudioProfiles(const sp<DeviceDescriptor>& devDesc, audio_io_handle_t ioHandle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 5bb03c8..caf7309 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -596,7 +596,14 @@
bool canCaptureHotword = captureHotwordAllowed(opPackageName, pid, uid);
if ((inputSource == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
- return binderStatusFromStatusT(BAD_VALUE);
+ return binderStatusFromStatusT(PERMISSION_DENIED);
+ }
+
+ if (((flags & AUDIO_INPUT_FLAG_HW_HOTWORD) != 0)
+ && !canCaptureHotword) {
+ ALOGE("%s: permission denied: hotword mode not allowed"
+ " for uid %d pid %d", __func__, uid, pid);
+ return binderStatusFromStatusT(PERMISSION_DENIED);
}
sp<AudioPolicyEffects>audioPolicyEffects;
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index be860e5..ea95364 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -29,6 +29,8 @@
using AudioPolicyManager::getOutputs;
using AudioPolicyManager::getAvailableOutputDevices;
using AudioPolicyManager::getAvailableInputDevices;
+ using AudioPolicyManager::releaseMsdPatches;
+ using AudioPolicyManager::setMsdPatches;
using AudioPolicyManager::setSurroundFormatEnabled;
uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
};
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 3032589..684358f 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -349,7 +349,17 @@
// TODO: Add patch creation tests that involve already existing patch
-class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest {
+enum
+{
+ MSD_AUDIO_PATCH_COUNT_NUM_AUDIO_PATCHES_INDEX = 0,
+ MSD_AUDIO_PATCH_COUNT_NAME_INDEX = 1
+};
+using MsdAudioPatchCountSpecification = std::tuple<size_t, std::string>;
+
+class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest,
+ public ::testing::WithParamInterface<MsdAudioPatchCountSpecification> {
+ public:
+ AudioPolicyManagerTestMsd();
protected:
void SetUpManagerConfig() override;
void TearDown() override;
@@ -357,8 +367,26 @@
sp<DeviceDescriptor> mMsdOutputDevice;
sp<DeviceDescriptor> mMsdInputDevice;
sp<DeviceDescriptor> mDefaultOutputDevice;
+
+ const size_t mExpectedAudioPatchCount;
+ sp<DeviceDescriptor> mSpdifDevice;
};
+AudioPolicyManagerTestMsd::AudioPolicyManagerTestMsd()
+ : mExpectedAudioPatchCount(std::get<MSD_AUDIO_PATCH_COUNT_NUM_AUDIO_PATCHES_INDEX>(
+ GetParam())) {}
+
+INSTANTIATE_TEST_CASE_P(
+ MsdAudioPatchCount,
+ AudioPolicyManagerTestMsd,
+ ::testing::Values(
+ MsdAudioPatchCountSpecification(1u, "single"),
+ MsdAudioPatchCountSpecification(2u, "dual")
+ ),
+ [](const ::testing::TestParamInfo<MsdAudioPatchCountSpecification> &info) {
+ return std::get<MSD_AUDIO_PATCH_COUNT_NAME_INDEX>(info.param); }
+);
+
void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
// TODO: Consider using Serializer to load part of the config from a string.
AudioPolicyManagerTest::SetUpManagerConfig();
@@ -378,6 +406,19 @@
config.addDevice(mMsdOutputDevice);
config.addDevice(mMsdInputDevice);
+ if (mExpectedAudioPatchCount == 2) {
+ // Add SPDIF device with PCM output profile as a second device for dual MSD audio patching.
+ mSpdifDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPDIF);
+ mSpdifDevice->addAudioProfile(pcmOutputProfile);
+ config.addDevice(mSpdifDevice);
+
+ sp<OutputProfile> spdifOutputProfile = new OutputProfile("spdif output");
+ spdifOutputProfile->addAudioProfile(pcmOutputProfile);
+ spdifOutputProfile->addSupportedDevice(mSpdifDevice);
+ config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ addOutputProfile(spdifOutputProfile);
+ }
+
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
HwModuleCollection modules = config.getHwModules();
modules.add(msdModule);
@@ -413,64 +454,88 @@
addOutputProfile(primaryEncodedOutputProfile);
mDefaultOutputDevice = config.getDefaultOutputDevice();
+ if (mExpectedAudioPatchCount == 2) {
+ mSpdifDevice->addAudioProfile(dtsOutputProfile);
+ primaryEncodedOutputProfile->addSupportedDevice(mSpdifDevice);
+ }
}
void AudioPolicyManagerTestMsd::TearDown() {
mMsdOutputDevice.clear();
mMsdInputDevice.clear();
mDefaultOutputDevice.clear();
+ mSpdifDevice.clear();
AudioPolicyManagerTest::TearDown();
}
-TEST_F(AudioPolicyManagerTestMsd, InitSuccess) {
+TEST_P(AudioPolicyManagerTestMsd, InitSuccess) {
ASSERT_TRUE(mMsdOutputDevice);
ASSERT_TRUE(mMsdInputDevice);
ASSERT_TRUE(mDefaultOutputDevice);
}
-TEST_F(AudioPolicyManagerTestMsd, Dump) {
+TEST_P(AudioPolicyManagerTestMsd, Dump) {
dumpToLog();
}
-TEST_F(AudioPolicyManagerTestMsd, PatchCreationOnSetForceUse) {
+TEST_P(AudioPolicyManagerTestMsd, PatchCreationOnSetForceUse) {
const PatchCountCheck patchCount = snapshotPatchCount();
mManager->setForceUse(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, PatchCreationSetReleaseMsdPatches) {
+ const PatchCountCheck patchCount = snapshotPatchCount();
+ DeviceVector devices = mManager->getAvailableOutputDevices();
+ // Remove MSD output device to avoid patching to itself
+ devices.remove(mMsdOutputDevice);
+ ASSERT_EQ(mExpectedAudioPatchCount, devices.size());
+ mManager->setMsdPatches(&devices);
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ // Dual patch: exercise creating one new audio patch and reusing another existing audio patch.
+ DeviceVector singleDevice(devices[0]);
+ mManager->releaseMsdPatches(singleDevice);
+ ASSERT_EQ(mExpectedAudioPatchCount - 1, patchCount.deltaFromSnapshot());
+ mManager->setMsdPatches(&devices);
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ mManager->releaseMsdPatches(devices);
+ ASSERT_EQ(0, patchCount.deltaFromSnapshot());
+}
+
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
@@ -479,7 +544,7 @@
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
// Switch between formats that are supported and not supported by MSD.
{
const PatchCountCheck patchCount = snapshotPatchCount();
@@ -489,9 +554,9 @@
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
nullptr /*output*/, &portId);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
{
const PatchCountCheck patchCount = snapshotPatchCount();
@@ -501,7 +566,7 @@
AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
nullptr /*output*/, &portId);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(-1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(-static_cast<int>(mExpectedAudioPatchCount), patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index b4c0da3..adf8562 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1686,6 +1686,11 @@
client->setRotateAndCropOverride(mOverrideRotateAndCropMode);
}
+ // Set camera muting behavior
+ if (client->supportsCameraMute()) {
+ client->setCameraMute(mOverrideCameraMuteMode);
+ }
+
if (shimUpdateOnly) {
// If only updating legacy shim parameters, immediately disconnect client
mServiceLock.unlock();
@@ -3887,6 +3892,8 @@
return handleSetImageDumpMask(args);
} else if (args.size() >= 1 && args[0] == String16("get-image-dump-mask")) {
return handleGetImageDumpMask(out);
+ } else if (args.size() >= 2 && args[0] == String16("set-camera-mute")) {
+ return handleSetCameraMute(args);
} else if (args.size() == 1 && args[0] == String16("help")) {
printHelp(out);
return NO_ERROR;
@@ -4009,6 +4016,29 @@
return dprintf(out, "Image dump mask: %d\n", mImageDumpMask);
}
+status_t CameraService::handleSetCameraMute(const Vector<String16>& args) {
+ int muteValue = strtol(String8(args[1]), nullptr, 10);
+ if (errno != 0) return BAD_VALUE;
+
+ if (muteValue < 0 || muteValue > 1) return BAD_VALUE;
+ Mutex::Autolock lock(mServiceLock);
+
+ mOverrideCameraMuteMode = (muteValue == 1);
+
+ const auto clients = mActiveClientManager.getAll();
+ for (auto& current : clients) {
+ if (current != nullptr) {
+ const auto basicClient = current->getValue();
+ if (basicClient.get() != nullptr) {
+ if (basicClient->supportsCameraMute()) {
+ basicClient->setCameraMute(mOverrideCameraMuteMode);
+ }
+ }
+ }
+ }
+
+ return OK;
+}
status_t CameraService::printHelp(int out) {
return dprintf(out, "Camera service commands:\n"
@@ -4021,6 +4051,7 @@
" set-image-dump-mask <MASK> specifies the formats to be saved to disk\n"
" Valid values 0=OFF, 1=ON for JPEG\n"
" get-image-dump-mask returns the current image-dump-mask value\n"
+ " set-camera-mute <0/1> enable or disable camera muting\n"
" help print this message\n");
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 43b03e6..bc6ad35 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -278,6 +278,12 @@
// Override rotate-and-crop AUTO behavior
virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop) = 0;
+ // Whether the client supports camera muting (black only output)
+ virtual bool supportsCameraMute() = 0;
+
+ // Set/reset camera mute
+ virtual status_t setCameraMute(bool enabled) = 0;
+
protected:
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
@@ -1044,6 +1050,9 @@
// Get the mask for image dump to disk
status_t handleGetImageDumpMask(int out);
+ // Set the camera mute state
+ status_t handleSetCameraMute(const Vector<String16>& args);
+
// Prints the shell command help
status_t printHelp(int out);
@@ -1088,6 +1097,9 @@
// Current image dump mask
uint8_t mImageDumpMask = 0;
+
+ // Current camera mute mode
+ bool mOverrideCameraMuteMode = false;
};
} // namespace android
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 2494302..1c9e9cf 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -2296,6 +2296,14 @@
static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop));
}
+bool Camera2Client::supportsCameraMute() {
+ return mDevice->supportsCameraMute();
+}
+
+status_t Camera2Client::setCameraMute(bool enabled) {
+ return mDevice->setCameraMute(enabled);
+}
+
status_t Camera2Client::waitUntilCurrentRequestIdLocked() {
int32_t activeRequestId = mStreamingProcessor->getActiveRequestId();
if (activeRequestId != 0) {
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index f8da0b6..4d667e3 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -87,6 +87,9 @@
virtual int32_t getGlobalAudioRestriction();
virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop);
+ virtual bool supportsCameraMute();
+ virtual status_t setCameraMute(bool enabled);
+
/**
* Interface used by CameraService
*/
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 6e1aba9..d47014e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1532,6 +1532,14 @@
static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop));
}
+bool CameraDeviceClient::supportsCameraMute() {
+ return mDevice->supportsCameraMute();
+}
+
+status_t CameraDeviceClient::setCameraMute(bool enabled) {
+ return mDevice->setCameraMute(enabled);
+}
+
binder::Status CameraDeviceClient::switchToOffline(
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
const std::vector<int>& offlineOutputIds,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 57688a0..5588285 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -189,6 +189,9 @@
virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop) override;
+ virtual bool supportsCameraMute();
+ virtual status_t setCameraMute(bool enabled);
+
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t dumpClient(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 62b5479..6765c3b 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -72,6 +72,16 @@
return OK;
}
+bool CameraOfflineSessionClient::supportsCameraMute() {
+ // Offline mode doesn't support muting
+ return false;
+}
+
+status_t CameraOfflineSessionClient::setCameraMute(bool) {
+ return INVALID_OPERATION;
+}
+
+
status_t CameraOfflineSessionClient::dump(int fd, const Vector<String16>& args) {
return BasicClient::dump(fd, args);
}
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index 839c435..5c5fcda 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -76,6 +76,9 @@
status_t setRotateAndCropOverride(uint8_t rotateAndCrop) override;
+ bool supportsCameraMute() override;
+ status_t setCameraMute(bool enabled) override;
+
// permissions management
status_t startCameraOps() override;
status_t finishCameraOps() override;
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 5e46f08..1be46d6 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -399,6 +399,21 @@
camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) = 0;
/**
+ * Whether camera muting (producing black-only output) is supported.
+ *
+ * Calling setCameraMute(true) when this returns false will return an
+ * INVALID_OPERATION error.
+ */
+ virtual bool supportsCameraMute() = 0;
+
+ /**
+ * Mute the camera.
+ *
+ * When muted, black image data is output on all output streams.
+ */
+ virtual status_t setCameraMute(bool enabled) = 0;
+
+ /**
* Get the status tracker of the camera device
*/
virtual wp<camera3::StatusTracker> getStatusTracker() = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 385bfd6..7606d7d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -357,6 +357,15 @@
mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
}
+ camera_metadata_entry_t availableTestPatternModes = mDeviceInfo.find(
+ ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES);
+ for (size_t i = 0; i < availableTestPatternModes.count; i++) {
+ if (availableTestPatternModes.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
+ mSupportCameraMute = true;
+ break;
+ }
+ }
+
return OK;
}
@@ -2388,6 +2397,26 @@
newRequest->mZoomRatioIs1x = false;
}
+ if (mSupportCameraMute) {
+ auto testPatternModeEntry =
+ newRequest->mSettingsList.begin()->metadata.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
+ newRequest->mOriginalTestPatternMode = testPatternModeEntry.count > 0 ?
+ testPatternModeEntry.data.i32[0] :
+ ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;
+
+ auto testPatternDataEntry =
+ newRequest->mSettingsList.begin()->metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
+ if (testPatternDataEntry.count > 0) {
+ memcpy(newRequest->mOriginalTestPatternData, testPatternModeEntry.data.i32,
+ sizeof(newRequest->mOriginalTestPatternData));
+ } else {
+ newRequest->mOriginalTestPatternData[0] = 0;
+ newRequest->mOriginalTestPatternData[1] = 0;
+ newRequest->mOriginalTestPatternData[2] = 0;
+ newRequest->mOriginalTestPatternData[3] = 0;
+ }
+ }
+
return newRequest;
}
@@ -3860,6 +3889,8 @@
mCurrentAfTriggerId(0),
mCurrentPreCaptureTriggerId(0),
mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
+ mCameraMute(false),
+ mCameraMuteChanged(false),
mRepeatingLastFrameNumber(
hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
mPrepareVideoStream(false),
@@ -4484,10 +4515,13 @@
mPrevTriggers = triggerCount;
bool rotateAndCropChanged = overrideAutoRotateAndCrop(captureRequest);
+ bool testPatternChanged = overrideTestPattern(captureRequest);
- // If the request is the same as last, or we had triggers last time
+ // If the request is the same as last, or we had triggers now or last time or
+ // changing overrides this time
bool newRequest =
- (mPrevRequest != captureRequest || triggersMixedIn || rotateAndCropChanged) &&
+ (mPrevRequest != captureRequest || triggersMixedIn ||
+ rotateAndCropChanged || testPatternChanged) &&
// Request settings are all the same within one batch, so only treat the first
// request in a batch as new
!(batchedRequest && i > 0);
@@ -4952,6 +4986,16 @@
return OK;
}
+status_t Camera3Device::RequestThread::setCameraMute(bool enabled) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mTriggerMutex);
+ if (enabled != mCameraMute) {
+ mCameraMute = enabled;
+ mCameraMuteChanged = true;
+ }
+ return OK;
+}
+
nsecs_t Camera3Device::getExpectedInFlightDuration() {
ATRACE_CALL();
std::lock_guard<std::mutex> l(mInFlightLock);
@@ -5504,6 +5548,61 @@
return false;
}
+bool Camera3Device::RequestThread::overrideTestPattern(
+ const sp<CaptureRequest> &request) {
+ ATRACE_CALL();
+
+ Mutex::Autolock l(mTriggerMutex);
+
+ bool changed = false;
+
+ int32_t testPatternMode = request->mOriginalTestPatternMode;
+ int32_t testPatternData[4] = {
+ request->mOriginalTestPatternData[0],
+ request->mOriginalTestPatternData[1],
+ request->mOriginalTestPatternData[2],
+ request->mOriginalTestPatternData[3]
+ };
+
+ if (mCameraMute) {
+ testPatternMode = ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR;
+ testPatternData[0] = 0;
+ testPatternData[1] = 0;
+ testPatternData[2] = 0;
+ testPatternData[3] = 0;
+ }
+
+ CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
+
+ auto testPatternEntry = metadata.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
+ if (testPatternEntry.count > 0) {
+ if (testPatternEntry.data.i32[0] != testPatternMode) {
+ testPatternEntry.data.i32[0] = testPatternMode;
+ changed = true;
+ }
+ } else {
+ metadata.update(ANDROID_SENSOR_TEST_PATTERN_MODE,
+ &testPatternMode, 1);
+ changed = true;
+ }
+
+ auto testPatternColor = metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
+ if (testPatternColor.count > 0) {
+ for (size_t i = 0; i < 4; i++) {
+ if (testPatternColor.data.i32[i] != (int32_t)testPatternData[i]) {
+ testPatternColor.data.i32[i] = testPatternData[i];
+ changed = true;
+ }
+ }
+ } else {
+ metadata.update(ANDROID_SENSOR_TEST_PATTERN_DATA,
+ (int32_t*)testPatternData, 4);
+ changed = true;
+ }
+
+ return changed;
+}
+
/**
* PreparerThread inner class methods
*/
@@ -6129,4 +6228,22 @@
return mRequestThread->setRotateAndCropAutoBehavior(rotateAndCropValue);
}
+bool Camera3Device::supportsCameraMute() {
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ return mSupportCameraMute;
+}
+
+status_t Camera3Device::setCameraMute(bool enabled) {
+ ATRACE_CALL();
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ if (mRequestThread == nullptr || !mSupportCameraMute) {
+ return INVALID_OPERATION;
+ }
+ return mRequestThread->setCameraMute(enabled);
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index b06ce45..567b3ad 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -238,6 +238,21 @@
status_t setRotateAndCropAutoBehavior(
camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue);
+ /**
+ * Whether camera muting (producing black-only output) is supported.
+ *
+ * Calling setCameraMute(true) when this returns false will return an
+ * INVALID_OPERATION error.
+ */
+ bool supportsCameraMute();
+
+ /**
+ * Mute the camera.
+ *
+ * When muted, black image data is output on all output streams.
+ */
+ status_t setCameraMute(bool enabled);
+
// Get the status trackeer for the camera device
wp<camera3::StatusTracker> getStatusTracker() { return mStatusTracker; }
@@ -525,6 +540,11 @@
// overriding of ROTATE_AND_CROP value and adjustment of coordinates
// in several other controls in both the request and the result
bool mRotateAndCropAuto;
+ // Original value of TEST_PATTERN_MODE and DATA so that they can be
+ // restored when sensor muting is turned off
+ int32_t mOriginalTestPatternMode;
+ int32_t mOriginalTestPatternData[4];
+
// Whether this capture request has its zoom ratio set to 1.0x before
// the framework overrides it for camera HAL consumption.
bool mZoomRatioIs1x;
@@ -868,6 +888,7 @@
status_t setRotateAndCropAutoBehavior(
camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue);
+ status_t setCameraMute(bool enabled);
protected:
virtual bool threadLoop();
@@ -889,6 +910,10 @@
// Override rotate_and_crop control if needed; returns true if the current value was changed
bool overrideAutoRotateAndCrop(const sp<CaptureRequest> &request);
+ // Override test_pattern control if needed for camera mute; returns true
+ // if the current value was changed
+ bool overrideTestPattern(const sp<CaptureRequest> &request);
+
static const nsecs_t kRequestTimeout = 50e6; // 50 ms
// TODO: does this need to be adjusted for long exposure requests?
@@ -1011,6 +1036,8 @@
uint32_t mCurrentAfTriggerId;
uint32_t mCurrentPreCaptureTriggerId;
camera_metadata_enum_android_scaler_rotate_and_crop_t mRotateAndCropOverride;
+ bool mCameraMute;
+ bool mCameraMuteChanged;
int64_t mRepeatingLastFrameNumber;
@@ -1276,6 +1303,10 @@
// Whether HAL supports offline processing capability.
bool mSupportOfflineProcessing = false;
+
+ // Whether the HAL supports camera muting via test pattern
+ bool mSupportCameraMute = false;
+
}; // class Camera3Device
}; // namespace android
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index 3bb70f1..b64f726 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -100,6 +100,7 @@
"libmediametricsservice",
"libmediautils",
"libutils",
+ "mediametricsservice-aidl-unstable-cpp",
],
header_libs: [
"libaudioutils_headers",
@@ -142,6 +143,7 @@
},
shared_libs: [
+ "mediametricsservice-aidl-unstable-cpp",
"libbase", // android logging
"libbinder",
"libcutils",
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index bf6e428..9d380ec 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -25,6 +25,7 @@
#include <android/content/pm/IPackageManagerNative.h> // package info
#include <audio_utils/clock.h> // clock conversions
#include <binder/IPCThreadState.h> // get calling uid
+#include <binder/IServiceManager.h> // checkCallingPermission
#include <cutils/properties.h> // for property_get
#include <mediautils/MemoryLeakTrackUtil.h>
#include <memunreachable/memunreachable.h>
diff --git a/services/mediametrics/MediaMetricsService.h b/services/mediametrics/MediaMetricsService.h
index 792b7f0..bcae397 100644
--- a/services/mediametrics/MediaMetricsService.h
+++ b/services/mediametrics/MediaMetricsService.h
@@ -24,7 +24,7 @@
// IMediaMetricsService must include Vector, String16, Errors
#include <android-base/thread_annotations.h>
-#include <media/IMediaMetricsService.h>
+#include <android/media/BnMediaMetricsService.h>
#include <mediautils/ServiceUtilities.h>
#include <utils/String8.h>
@@ -32,12 +32,18 @@
namespace android {
-class MediaMetricsService : public BnMediaMetricsService
+class MediaMetricsService : public media::BnMediaMetricsService
{
public:
MediaMetricsService();
~MediaMetricsService() override;
+ // AIDL interface
+ binder::Status submitBuffer(const std::vector<uint8_t>& buffer) override {
+ status_t status = submitBuffer((char *)buffer.data(), buffer.size());
+ return binder::Status::fromStatusT(status);
+ }
+
/**
* Submits the indicated record to the mediaanalytics service.
*
@@ -45,11 +51,11 @@
* \return status failure, which is negative on binder transaction failure.
* As the transaction is one-way, remote failures will not be reported.
*/
- status_t submit(mediametrics::Item *item) override {
+ status_t submit(mediametrics::Item *item) {
return submitInternal(item, false /* release */);
}
- status_t submitBuffer(const char *buffer, size_t length) override {
+ status_t submitBuffer(const char *buffer, size_t length) {
mediametrics::Item *item = new mediametrics::Item();
return item->readFromByteString(buffer, length)
?: submitInternal(item, true /* release */);
@@ -81,7 +87,7 @@
// Internal call where release is true if ownership of item is transferred
// to the service (that is, the service will eventually delete the item).
- status_t submitInternal(mediametrics::Item *item, bool release) override;
+ status_t submitInternal(mediametrics::Item *item, bool release);
private:
void processExpirations();
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index df4c867..6ac9d20 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -43,6 +43,7 @@
"libstagefright",
"libstatslog",
"libutils",
+ "mediametricsservice-aidl-unstable-cpp",
],
include_dirs: [
diff --git a/services/mediametrics/tests/Android.bp b/services/mediametrics/tests/Android.bp
index c2e0759..94112b0 100644
--- a/services/mediametrics/tests/Android.bp
+++ b/services/mediametrics/tests/Android.bp
@@ -19,6 +19,7 @@
"libmediametricsservice",
"libmediautils",
"libutils",
+ "mediametricsservice-aidl-unstable-cpp",
],
header_libs: [
diff --git a/services/tuner/TunerDemux.cpp b/services/tuner/TunerDemux.cpp
index 0e0cd3b..1f8b70d 100644
--- a/services/tuner/TunerDemux.cpp
+++ b/services/tuner/TunerDemux.cpp
@@ -124,4 +124,17 @@
*_aidl_return = ::ndk::SharedRefBase::make<TunerDvr>(hidlDvr, dvrType);
return Status::ok();
}
+
+Status TunerDemux::close() {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized.");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result res = mDemux->close();
+ if (res != Result::SUCCESS) {
+ return Status::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return Status::ok();
+}
} // namespace android
diff --git a/services/tuner/TunerDemux.h b/services/tuner/TunerDemux.h
index 675bb7c..594fd66 100644
--- a/services/tuner/TunerDemux.h
+++ b/services/tuner/TunerDemux.h
@@ -47,6 +47,7 @@
Status openDvr(
int dvbType, int bufferSize, const shared_ptr<ITunerDvrCallback>& cb,
shared_ptr<ITunerDvr>* _aidl_return) override;
+ Status close() override;
private:
sp<IDemux> mDemux;
diff --git a/services/tuner/TunerFilter.cpp b/services/tuner/TunerFilter.cpp
index 722d36d..edfc291 100644
--- a/services/tuner/TunerFilter.cpp
+++ b/services/tuner/TunerFilter.cpp
@@ -16,16 +16,19 @@
#define LOG_TAG "TunerFilter"
-#include <aidlcommonsupport/NativeHandle.h>
#include "TunerFilter.h"
+using ::android::hardware::hidl_handle;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::Result;
-
namespace android {
-TunerFilter::TunerFilter(sp<IFilter> filter, sp<IFilterCallback> callback) {
+TunerFilter::TunerFilter(
+ sp<IFilter> filter, sp<IFilterCallback> callback) {
mFilter = filter;
mFilter_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(filter);
mFilterCallback = callback;
@@ -103,6 +106,7 @@
break;
}
}
+ halSettings.ts(ts);
break;
}
}
@@ -113,6 +117,44 @@
return Status::ok();
}
+Status TunerFilter::getAvSharedHandleInfo(TunerFilterSharedHandleInfo* _aidl_return) {
+ if (mFilter_1_1 == nullptr) {
+ ALOGE("IFilter_1_1 is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result res;
+ mFilter_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
+ res = r;
+ if (res == Result::SUCCESS) {
+ TunerFilterSharedHandleInfo info{
+ .handle = dupToAidl(hidl_handle(avMemory.getNativeHandle())),
+ .size = static_cast<int64_t>(avMemSize),
+ };
+ *_aidl_return = std::move(info);
+ } else {
+ _aidl_return = NULL;
+ }
+ });
+
+ return Status::fromServiceSpecificError(static_cast<int32_t>(res));
+}
+
+Status TunerFilter::releaseAvHandle(
+ const ::aidl::android::hardware::common::NativeHandle& handle, int64_t avDataId) {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result res = mFilter->releaseAvHandle(hidl_handle(makeFromAidl(handle)), avDataId);
+ if (res != Result::SUCCESS) {
+ return Status::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return Status::ok();
+}
+
+
Status TunerFilter::start() {
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
@@ -149,6 +191,18 @@
return Status::ok();
}
+Status TunerFilter::close() {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+ Result res = mFilter->close();
+ if (res != Result::SUCCESS) {
+ return Status::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return Status::ok();
+}
+
sp<IFilter> TunerFilter::getHalFilter() {
return mFilter;
}
@@ -164,8 +218,8 @@
tunerMedia.streamId = static_cast<int>(mediaEvent.streamId);
tunerMedia.isPtsPresent = mediaEvent.isPtsPresent;
tunerMedia.pts = static_cast<long>(mediaEvent.pts);
- tunerMedia.dataLength = static_cast<long>(mediaEvent.dataLength);
- tunerMedia.offset = static_cast<long>(mediaEvent.offset);
+ tunerMedia.dataLength = static_cast<int>(mediaEvent.dataLength);
+ tunerMedia.offset = static_cast<int>(mediaEvent.offset);
tunerMedia.isSecureMemory = mediaEvent.isSecureMemory;
tunerMedia.avDataId = static_cast<long>(mediaEvent.avDataId);
tunerMedia.mpuSequenceNumber = static_cast<int>(mediaEvent.mpuSequenceNumber);
@@ -187,7 +241,6 @@
}
Return<void> TunerFilter::FilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) {
- ALOGD("FilterCallback::onFilterEvent");
std::vector<DemuxFilterEvent::Event> events = filterEvent.events;
std::vector<TunerFilterEvent> tunerEvent;
@@ -203,7 +256,8 @@
}
}
}
- mTunerFilterCallback->onFilterEvent(&tunerEvent);
+
+ mTunerFilterCallback->onFilterEvent(tunerEvent);
return Void();
}
diff --git a/services/tuner/TunerFilter.h b/services/tuner/TunerFilter.h
index 7f5838c..2f10435 100644
--- a/services/tuner/TunerFilter.h
+++ b/services/tuner/TunerFilter.h
@@ -19,6 +19,7 @@
#include <aidl/android/media/tv/tuner/BnTunerFilter.h>
#include <aidl/android/media/tv/tuner/ITunerFilterCallback.h>
+#include <aidlcommonsupport/NativeHandle.h>
#include <android/hardware/tv/tuner/1.1/IFilter.h>
#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -29,6 +30,7 @@
using ::aidl::android::media::tv::tuner::TunerFilterConfiguration;
using ::aidl::android::media::tv::tuner::TunerFilterEvent;
using ::aidl::android::media::tv::tuner::TunerFilterMediaEvent;
+using ::aidl::android::media::tv::tuner::TunerFilterSharedHandleInfo;
using ::aidl::android::media::tv::tuner::TunerFilterSettings;
using ::android::hardware::Return;
using ::android::hardware::Void;
@@ -39,7 +41,6 @@
using ::android::hardware::tv::tuner::V1_0::IFilter;
using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
-
namespace android {
class TunerFilter : public BnTunerFilter {
@@ -50,9 +51,13 @@
Status getId(int32_t* _aidl_return) override;
Status getId64Bit(int64_t* _aidl_return) override;
Status configure(const TunerFilterConfiguration& config) override;
+ Status getAvSharedHandleInfo(TunerFilterSharedHandleInfo* _aidl_return) override;
+ Status releaseAvHandle(const ::aidl::android::hardware::common::NativeHandle& handle,
+ int64_t avDataId) override;
Status start() override;
Status stop() override;
Status flush() override;
+ Status close() override;
sp<IFilter> getHalFilter();
struct FilterCallback : public IFilterCallback {
diff --git a/services/tuner/TunerFrontend.cpp b/services/tuner/TunerFrontend.cpp
index e92489d..bb8b07d 100644
--- a/services/tuner/TunerFrontend.cpp
+++ b/services/tuner/TunerFrontend.cpp
@@ -66,7 +66,6 @@
using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings;
using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
using ::android::hardware::tv::tuner::V1_0::FrontendScanType;
-using ::android::hardware::tv::tuner::V1_0::FrontendSettings;;
using ::android::hardware::tv::tuner::V1_0::Result;
using ::android::hardware::tv::tuner::V1_1::FrontendModulation;
@@ -80,6 +79,7 @@
TunerFrontend::~TunerFrontend() {
mFrontend = NULL;
+ mFrontend_1_1 = NULL;
mId = -1;
}
@@ -103,12 +103,33 @@
return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
-Status TunerFrontend::tune(const TunerFrontendSettings& /*settings*/) {
- return Status::ok();
+Status TunerFrontend::tune(const TunerFrontendSettings& settings) {
+ if (mFrontend == NULL) {
+ ALOGD("IFrontend is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ FrontendSettings frontendSettings = getHidlFrontendSettings(settings);
+ Result status = mFrontend->tune(frontendSettings);
+ if (status == Result::SUCCESS) {
+ return Status::ok();
+ }
+
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
Status TunerFrontend::stopTune() {
- return Status::ok();
+ if (mFrontend == NULL) {
+ ALOGD("IFrontend is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result status = mFrontend->stopTune();
+ if (status == Result::SUCCESS) {
+ return Status::ok();
+ }
+
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
Status TunerFrontend::scan(const TunerFrontendSettings& settings, int frontendScanType) {
@@ -117,165 +138,7 @@
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
}
- // TODO: extend TunerFrontendSettings to use 1.1 types
- FrontendSettings frontendSettings;
- switch (settings.getTag()) {
- case TunerFrontendSettings::analog:
- frontendSettings.analog({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::analog>().frequency),
- .type = static_cast<FrontendAnalogType>(
- settings.get<TunerFrontendSettings::analog>().signalType),
- .sifStandard = static_cast<FrontendAnalogSifStandard>(
- settings.get<TunerFrontendSettings::analog>().sifStandard),
- });
- break;
- case TunerFrontendSettings::atsc:
- frontendSettings.atsc({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::atsc>().frequency),
- .modulation = static_cast<FrontendAtscModulation>(
- settings.get<TunerFrontendSettings::atsc>().modulation),
- });
- break;
- case TunerFrontendSettings::atsc3:
- frontendSettings.atsc3({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::atsc3>().frequency),
- .bandwidth = static_cast<FrontendAtsc3Bandwidth>(
- settings.get<TunerFrontendSettings::atsc3>().bandwidth),
- .demodOutputFormat = static_cast<FrontendAtsc3DemodOutputFormat>(
- settings.get<TunerFrontendSettings::atsc3>().demodOutputFormat),
- .plpSettings = getAtsc3PlpSettings(settings.get<TunerFrontendSettings::atsc3>()),
- });
- break;
- case TunerFrontendSettings::cable:
- frontendSettings.dvbc({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::cable>().frequency),
- .modulation = static_cast<FrontendDvbcModulation>(
- settings.get<TunerFrontendSettings::cable>().modulation),
- .fec = static_cast<FrontendInnerFec>(
- settings.get<TunerFrontendSettings::cable>().innerFec),
- .symbolRate = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::cable>().symbolRate),
- .outerFec = static_cast<FrontendDvbcOuterFec>(
- settings.get<TunerFrontendSettings::cable>().outerFec),
- .annex = static_cast<FrontendDvbcAnnex>(
- settings.get<TunerFrontendSettings::cable>().annex),
- .spectralInversion = static_cast<FrontendDvbcSpectralInversion>(
- settings.get<TunerFrontendSettings::cable>().spectralInversion),
- });
- break;
- case TunerFrontendSettings::dvbs:
- frontendSettings.dvbs({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::dvbs>().frequency),
- .modulation = static_cast<FrontendDvbsModulation>(
- settings.get<TunerFrontendSettings::dvbs>().modulation),
- .coderate = getDvbsCodeRate(
- settings.get<TunerFrontendSettings::dvbs>().codeRate),
- .symbolRate = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::dvbs>().symbolRate),
- .rolloff = static_cast<FrontendDvbsRolloff>(
- settings.get<TunerFrontendSettings::dvbs>().rolloff),
- .pilot = static_cast<FrontendDvbsPilot>(
- settings.get<TunerFrontendSettings::dvbs>().pilot),
- .inputStreamId = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::dvbs>().inputStreamId),
- .standard = static_cast<FrontendDvbsStandard>(
- settings.get<TunerFrontendSettings::dvbs>().standard),
- .vcmMode = static_cast<FrontendDvbsVcmMode>(
- settings.get<TunerFrontendSettings::dvbs>().vcm),
- });
- break;
- case TunerFrontendSettings::dvbt:
- frontendSettings.dvbt({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::dvbt>().frequency),
- .transmissionMode = static_cast<FrontendDvbtTransmissionMode>(
- settings.get<TunerFrontendSettings::dvbt>().transmissionMode),
- .bandwidth = static_cast<FrontendDvbtBandwidth>(
- settings.get<TunerFrontendSettings::dvbt>().bandwidth),
- .constellation = static_cast<FrontendDvbtConstellation>(
- settings.get<TunerFrontendSettings::dvbt>().constellation),
- .hierarchy = static_cast<FrontendDvbtHierarchy>(
- settings.get<TunerFrontendSettings::dvbt>().hierarchy),
- .hpCoderate = static_cast<FrontendDvbtCoderate>(
- settings.get<TunerFrontendSettings::dvbt>().hpCodeRate),
- .lpCoderate = static_cast<FrontendDvbtCoderate>(
- settings.get<TunerFrontendSettings::dvbt>().lpCodeRate),
- .guardInterval = static_cast<FrontendDvbtGuardInterval>(
- settings.get<TunerFrontendSettings::dvbt>().guardInterval),
- .isHighPriority = settings.get<TunerFrontendSettings::dvbt>().isHighPriority,
- .standard = static_cast<FrontendDvbtStandard>(
- settings.get<TunerFrontendSettings::dvbt>().standard),
- .isMiso = settings.get<TunerFrontendSettings::dvbt>().isMiso,
- .plpMode = static_cast<FrontendDvbtPlpMode>(
- settings.get<TunerFrontendSettings::dvbt>().plpMode),
- .plpId = static_cast<uint8_t>(
- settings.get<TunerFrontendSettings::dvbt>().plpId),
- .plpGroupId = static_cast<uint8_t>(
- settings.get<TunerFrontendSettings::dvbt>().plpGroupId),
- });
- break;
- case TunerFrontendSettings::isdbs:
- frontendSettings.isdbs({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::isdbs>().frequency),
- .streamId = static_cast<uint16_t>(
- settings.get<TunerFrontendSettings::isdbs>().streamId),
- .streamIdType = static_cast<FrontendIsdbsStreamIdType>(
- settings.get<TunerFrontendSettings::isdbs>().streamIdType),
- .modulation = static_cast<FrontendIsdbsModulation>(
- settings.get<TunerFrontendSettings::isdbs>().modulation),
- .coderate = static_cast<FrontendIsdbsCoderate>(
- settings.get<TunerFrontendSettings::isdbs>().codeRate),
- .symbolRate = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::isdbs>().symbolRate),
- .rolloff = static_cast<FrontendIsdbsRolloff>(
- settings.get<TunerFrontendSettings::isdbs>().rolloff),
- });
- break;
- case TunerFrontendSettings::isdbs3:
- frontendSettings.isdbs3({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::isdbs3>().frequency),
- .streamId = static_cast<uint16_t>(
- settings.get<TunerFrontendSettings::isdbs3>().streamId),
- .streamIdType = static_cast<FrontendIsdbsStreamIdType>(
- settings.get<TunerFrontendSettings::isdbs3>().streamIdType),
- .modulation = static_cast<FrontendIsdbs3Modulation>(
- settings.get<TunerFrontendSettings::isdbs3>().modulation),
- .coderate = static_cast<FrontendIsdbs3Coderate>(
- settings.get<TunerFrontendSettings::isdbs3>().codeRate),
- .symbolRate = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::isdbs3>().symbolRate),
- .rolloff = static_cast<FrontendIsdbs3Rolloff>(
- settings.get<TunerFrontendSettings::isdbs3>().rolloff),
- });
- break;
- case TunerFrontendSettings::isdbt:
- frontendSettings.isdbt({
- .frequency = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::isdbt>().frequency),
- .modulation = static_cast<FrontendIsdbtModulation>(
- settings.get<TunerFrontendSettings::isdbt>().modulation),
- .bandwidth = static_cast<FrontendIsdbtBandwidth>(
- settings.get<TunerFrontendSettings::isdbt>().bandwidth),
- .mode = static_cast<FrontendIsdbtMode>(
- settings.get<TunerFrontendSettings::isdbt>().mode),
- .coderate = static_cast<FrontendIsdbtCoderate>(
- settings.get<TunerFrontendSettings::isdbt>().codeRate),
- .guardInterval = static_cast<FrontendIsdbtGuardInterval>(
- settings.get<TunerFrontendSettings::isdbt>().guardInterval),
- .serviceAreaId = static_cast<uint32_t>(
- settings.get<TunerFrontendSettings::isdbt>().serviceAreaId),
- });
- break;
- default:
- break;
- }
+ FrontendSettings frontendSettings = getHidlFrontendSettings(settings);
Result status = mFrontend->scan(
frontendSettings, static_cast<FrontendScanType>(frontendScanType));
if (status == Result::SUCCESS) {
@@ -286,7 +149,17 @@
}
Status TunerFrontend::stopScan() {
- return Status::ok();
+ if (mFrontend == NULL) {
+ ALOGD("IFrontend is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result status = mFrontend->stopScan();
+ if (status == Result::SUCCESS) {
+ return Status::ok();
+ }
+
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
Status TunerFrontend::setLnb(int /*lnbHandle*/) {
@@ -298,7 +171,17 @@
}
Status TunerFrontend::close() {
- return Status::ok();
+ if (mFrontend == NULL) {
+ ALOGD("IFrontend is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result status = mFrontend->close();
+ if (status == Result::SUCCESS) {
+ return Status::ok();
+ }
+
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
Status TunerFrontend::getStatus(const vector<int32_t>& /*statusTypes*/,
@@ -500,4 +383,167 @@
};
return coderate;
}
+
+FrontendSettings TunerFrontend::getHidlFrontendSettings(const TunerFrontendSettings& settings) {
+ // TODO: extend TunerFrontendSettings to use 1.1 types
+ FrontendSettings frontendSettings;
+ switch (settings.getTag()) {
+ case TunerFrontendSettings::analog:
+ frontendSettings.analog({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::analog>().frequency),
+ .type = static_cast<FrontendAnalogType>(
+ settings.get<TunerFrontendSettings::analog>().signalType),
+ .sifStandard = static_cast<FrontendAnalogSifStandard>(
+ settings.get<TunerFrontendSettings::analog>().sifStandard),
+ });
+ break;
+ case TunerFrontendSettings::atsc:
+ frontendSettings.atsc({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::atsc>().frequency),
+ .modulation = static_cast<FrontendAtscModulation>(
+ settings.get<TunerFrontendSettings::atsc>().modulation),
+ });
+ break;
+ case TunerFrontendSettings::atsc3:
+ frontendSettings.atsc3({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::atsc3>().frequency),
+ .bandwidth = static_cast<FrontendAtsc3Bandwidth>(
+ settings.get<TunerFrontendSettings::atsc3>().bandwidth),
+ .demodOutputFormat = static_cast<FrontendAtsc3DemodOutputFormat>(
+ settings.get<TunerFrontendSettings::atsc3>().demodOutputFormat),
+ .plpSettings = getAtsc3PlpSettings(settings.get<TunerFrontendSettings::atsc3>()),
+ });
+ break;
+ case TunerFrontendSettings::cable:
+ frontendSettings.dvbc({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::cable>().frequency),
+ .modulation = static_cast<FrontendDvbcModulation>(
+ settings.get<TunerFrontendSettings::cable>().modulation),
+ .fec = static_cast<FrontendInnerFec>(
+ settings.get<TunerFrontendSettings::cable>().innerFec),
+ .symbolRate = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::cable>().symbolRate),
+ .outerFec = static_cast<FrontendDvbcOuterFec>(
+ settings.get<TunerFrontendSettings::cable>().outerFec),
+ .annex = static_cast<FrontendDvbcAnnex>(
+ settings.get<TunerFrontendSettings::cable>().annex),
+ .spectralInversion = static_cast<FrontendDvbcSpectralInversion>(
+ settings.get<TunerFrontendSettings::cable>().spectralInversion),
+ });
+ break;
+ case TunerFrontendSettings::dvbs:
+ frontendSettings.dvbs({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::dvbs>().frequency),
+ .modulation = static_cast<FrontendDvbsModulation>(
+ settings.get<TunerFrontendSettings::dvbs>().modulation),
+ .coderate = getDvbsCodeRate(
+ settings.get<TunerFrontendSettings::dvbs>().codeRate),
+ .symbolRate = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::dvbs>().symbolRate),
+ .rolloff = static_cast<FrontendDvbsRolloff>(
+ settings.get<TunerFrontendSettings::dvbs>().rolloff),
+ .pilot = static_cast<FrontendDvbsPilot>(
+ settings.get<TunerFrontendSettings::dvbs>().pilot),
+ .inputStreamId = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::dvbs>().inputStreamId),
+ .standard = static_cast<FrontendDvbsStandard>(
+ settings.get<TunerFrontendSettings::dvbs>().standard),
+ .vcmMode = static_cast<FrontendDvbsVcmMode>(
+ settings.get<TunerFrontendSettings::dvbs>().vcm),
+ });
+ break;
+ case TunerFrontendSettings::dvbt:
+ frontendSettings.dvbt({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::dvbt>().frequency),
+ .transmissionMode = static_cast<FrontendDvbtTransmissionMode>(
+ settings.get<TunerFrontendSettings::dvbt>().transmissionMode),
+ .bandwidth = static_cast<FrontendDvbtBandwidth>(
+ settings.get<TunerFrontendSettings::dvbt>().bandwidth),
+ .constellation = static_cast<FrontendDvbtConstellation>(
+ settings.get<TunerFrontendSettings::dvbt>().constellation),
+ .hierarchy = static_cast<FrontendDvbtHierarchy>(
+ settings.get<TunerFrontendSettings::dvbt>().hierarchy),
+ .hpCoderate = static_cast<FrontendDvbtCoderate>(
+ settings.get<TunerFrontendSettings::dvbt>().hpCodeRate),
+ .lpCoderate = static_cast<FrontendDvbtCoderate>(
+ settings.get<TunerFrontendSettings::dvbt>().lpCodeRate),
+ .guardInterval = static_cast<FrontendDvbtGuardInterval>(
+ settings.get<TunerFrontendSettings::dvbt>().guardInterval),
+ .isHighPriority = settings.get<TunerFrontendSettings::dvbt>().isHighPriority,
+ .standard = static_cast<FrontendDvbtStandard>(
+ settings.get<TunerFrontendSettings::dvbt>().standard),
+ .isMiso = settings.get<TunerFrontendSettings::dvbt>().isMiso,
+ .plpMode = static_cast<FrontendDvbtPlpMode>(
+ settings.get<TunerFrontendSettings::dvbt>().plpMode),
+ .plpId = static_cast<uint8_t>(
+ settings.get<TunerFrontendSettings::dvbt>().plpId),
+ .plpGroupId = static_cast<uint8_t>(
+ settings.get<TunerFrontendSettings::dvbt>().plpGroupId),
+ });
+ break;
+ case TunerFrontendSettings::isdbs:
+ frontendSettings.isdbs({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::isdbs>().frequency),
+ .streamId = static_cast<uint16_t>(
+ settings.get<TunerFrontendSettings::isdbs>().streamId),
+ .streamIdType = static_cast<FrontendIsdbsStreamIdType>(
+ settings.get<TunerFrontendSettings::isdbs>().streamIdType),
+ .modulation = static_cast<FrontendIsdbsModulation>(
+ settings.get<TunerFrontendSettings::isdbs>().modulation),
+ .coderate = static_cast<FrontendIsdbsCoderate>(
+ settings.get<TunerFrontendSettings::isdbs>().codeRate),
+ .symbolRate = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::isdbs>().symbolRate),
+ .rolloff = static_cast<FrontendIsdbsRolloff>(
+ settings.get<TunerFrontendSettings::isdbs>().rolloff),
+ });
+ break;
+ case TunerFrontendSettings::isdbs3:
+ frontendSettings.isdbs3({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::isdbs3>().frequency),
+ .streamId = static_cast<uint16_t>(
+ settings.get<TunerFrontendSettings::isdbs3>().streamId),
+ .streamIdType = static_cast<FrontendIsdbsStreamIdType>(
+ settings.get<TunerFrontendSettings::isdbs3>().streamIdType),
+ .modulation = static_cast<FrontendIsdbs3Modulation>(
+ settings.get<TunerFrontendSettings::isdbs3>().modulation),
+ .coderate = static_cast<FrontendIsdbs3Coderate>(
+ settings.get<TunerFrontendSettings::isdbs3>().codeRate),
+ .symbolRate = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::isdbs3>().symbolRate),
+ .rolloff = static_cast<FrontendIsdbs3Rolloff>(
+ settings.get<TunerFrontendSettings::isdbs3>().rolloff),
+ });
+ break;
+ case TunerFrontendSettings::isdbt:
+ frontendSettings.isdbt({
+ .frequency = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::isdbt>().frequency),
+ .modulation = static_cast<FrontendIsdbtModulation>(
+ settings.get<TunerFrontendSettings::isdbt>().modulation),
+ .bandwidth = static_cast<FrontendIsdbtBandwidth>(
+ settings.get<TunerFrontendSettings::isdbt>().bandwidth),
+ .mode = static_cast<FrontendIsdbtMode>(
+ settings.get<TunerFrontendSettings::isdbt>().mode),
+ .coderate = static_cast<FrontendIsdbtCoderate>(
+ settings.get<TunerFrontendSettings::isdbt>().codeRate),
+ .guardInterval = static_cast<FrontendIsdbtGuardInterval>(
+ settings.get<TunerFrontendSettings::isdbt>().guardInterval),
+ .serviceAreaId = static_cast<uint32_t>(
+ settings.get<TunerFrontendSettings::isdbt>().serviceAreaId),
+ });
+ break;
+ default:
+ break;
+ }
+ return frontendSettings;
+}
} // namespace android
diff --git a/services/tuner/TunerFrontend.h b/services/tuner/TunerFrontend.h
index 99cdcdf..431022d 100644
--- a/services/tuner/TunerFrontend.h
+++ b/services/tuner/TunerFrontend.h
@@ -41,6 +41,7 @@
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using ::android::hardware::tv::tuner::V1_0::FrontendSettings;;
using ::android::hardware::tv::tuner::V1_0::IFrontend;
using ::android::hardware::tv::tuner::V1_1::IFrontendCallback;
using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
@@ -85,6 +86,7 @@
hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(
const TunerFrontendAtsc3Settings& settings);
FrontendDvbsCodeRate getDvbsCodeRate(const TunerFrontendDvbsCodeRate& codeRate);
+ FrontendSettings getHidlFrontendSettings(const TunerFrontendSettings& settings);
int mId;
sp<IFrontend> mFrontend;
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerDemux.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerDemux.aidl
index f6de618..fa2c1ff 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerDemux.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerDemux.aidl
@@ -44,4 +44,9 @@
* Open a DVR (Digital Video Record) instance in the demux.
*/
ITunerDvr openDvr(in int dvbType, in int bufferSize, in ITunerDvrCallback cb);
+
+ /**
+ * Releases the ITunerDemux instance.
+ */
+ void close();
}
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl
index 37166aa..1d5544f 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl
@@ -16,7 +16,9 @@
package android.media.tv.tuner;
+import android.hardware.common.NativeHandle;
import android.media.tv.tuner.TunerFilterConfiguration;
+import android.media.tv.tuner.TunerFilterSharedHandleInfo;
/**
* Tuner Filter interface handles tuner related operations.
@@ -40,6 +42,16 @@
void configure(in TunerFilterConfiguration config);
/**
+ * Get the a/v shared memory handle
+ */
+ TunerFilterSharedHandleInfo getAvSharedHandleInfo();
+
+ /**
+ * Release the handle reported by the HAL for AV memory.
+ */
+ void releaseAvHandle(in NativeHandle handle, in long avDataId);
+
+ /**
* Start the filter.
*/
void start();
@@ -53,4 +65,9 @@
* Flush the filter.
*/
void flush();
+
+ /**
+ * Close the filter.
+ */
+ void close();
}
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFilterCallback.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFilterCallback.aidl
index f9f86ac..e7a52a7 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerFilterCallback.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFilterCallback.aidl
@@ -32,5 +32,5 @@
/**
* Notify the client that a new filter event happened.
*/
- void onFilterEvent(out TunerFilterEvent[] filterEvent);
+ void onFilterEvent(in TunerFilterEvent[] filterEvent);
}
diff --git a/services/tuner/aidl/android/media/tv/tuner/TunerFilterSharedHandleInfo.aidl b/services/tuner/aidl/android/media/tv/tuner/TunerFilterSharedHandleInfo.aidl
new file mode 100644
index 0000000..122dfc3
--- /dev/null
+++ b/services/tuner/aidl/android/media/tv/tuner/TunerFilterSharedHandleInfo.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.hardware.common.NativeHandle;
+
+/**
+ * Filter Shared Handle Information.
+ *
+ * {@hide}
+ */
+parcelable TunerFilterSharedHandleInfo {
+ NativeHandle handle;
+ long size;
+}
\ No newline at end of file