Merge "Include "service-media-s" in media apex" into sc-dev
diff --git a/METADATA b/METADATA
index d97975c..1fbda08 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
+# CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+# DEPENDING ON IT IN YOUR PROJECT. ***
third_party {
- license_type: NOTICE
+ # would be NOTICE save for drm/mediadrm/plugins/clearkey/hidl/
+ license_type: BY_EXCEPTION_ONLY
}
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/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index c697b80..96af7cb 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -159,6 +159,10 @@
output->outputDelay = 0u;
output->numSlots = kSmoothnessFactor;
}
+ {
+ Mutexed<BlockPools>::Locked pools(mBlockPools);
+ pools->outputPoolId = C2BlockPool::BASIC_LINEAR;
+ }
}
CCodecBufferChannel::~CCodecBufferChannel() {
@@ -1092,10 +1096,13 @@
bool graphic = (oStreamFormat.value == C2BufferData::GRAPHIC);
C2BlockPool::local_id_t outputPoolId_;
+ C2BlockPool::local_id_t prevOutputPoolId;
{
Mutexed<BlockPools>::Locked pools(mBlockPools);
+ prevOutputPoolId = pools->outputPoolId;
+
// set default allocator ID.
pools->outputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC
: preferredLinearId;
@@ -1189,6 +1196,15 @@
outputPoolId_ = pools->outputPoolId;
}
+ if (prevOutputPoolId != C2BlockPool::BASIC_LINEAR
+ && prevOutputPoolId != C2BlockPool::BASIC_GRAPHIC) {
+ c2_status_t err = mComponent->destroyBlockPool(prevOutputPoolId);
+ if (err != C2_OK) {
+ ALOGW("Failed to clean up previous block pool %llu - %s (%d)\n",
+ (unsigned long long) prevOutputPoolId, asString(err), err);
+ }
+ }
+
Mutexed<Output>::Locked output(mOutput);
output->outputDelay = outputDelayValue;
output->numSlots = numOutputSlots;
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index dee3bf6..74ef9ea 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -102,16 +102,30 @@
}
static bool using_ion(void) {
- static int cached_result = -1;
-
- if (cached_result == -1) {
+ static int cached_result = []()->int {
struct stat buffer;
- cached_result = (stat("/dev/ion", &buffer) == 0);
- if (cached_result)
+ int ret = (stat("/dev/ion", &buffer) == 0);
+
+ if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
+ /*
+ * Double check that the system heap is present so we
+ * can gracefully fail back to ION if we cannot satisfy
+ * the override
+ */
+ ret = (stat("/dev/dma_heap/system", &buffer) != 0);
+ if (ret)
+ ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
+ else
+ ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
+ }
+
+ if (ret)
ALOGD("Using ION\n");
else
ALOGD("Using DMABUF Heaps\n");
- }
+ return ret;
+ }();
+
return (cached_result == 1);
}
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 431f0fa..a4beaf4 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -56,6 +56,12 @@
ALOGE_IF(mHasThread, "%s() callback thread never join()ed", __func__);
+ if (!mMetricsId.empty()) {
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM)
+ .record();
+ }
+
// If the stream is deleted when OPEN or in use then audio resources will leak.
// This would indicate an internal error. So we want to find this ASAP.
LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
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/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 84388c9..2af7eee 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -170,6 +170,7 @@
#define AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR "ctor"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT "disconnect"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR "dtor"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM "endAAudioStream" // AAudioStream
#define AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP "endAudioIntervalGroup"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH "flush" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_INVALIDATE "invalidate" // server track, record
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/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/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index d78d1e3..3b2de76 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -136,6 +136,25 @@
"connection_count",
};
+// static constexpr const char * const AAudioStreamFields[] {
+// "mediametrics_aaudiostream_reported",
+// "caller_name",
+// "path",
+// "direction",
+// "frames_per_burst",
+// "buffer_size",
+// "buffer_capacity",
+// "channel_count",
+// "total_frames_transferred",
+// "perf_mode_requested",
+// "perf_mode_actual",
+// "sharing",
+// "xrun_count",
+// "device_type",
+// "format_app",
+// "format_device",
+// };
+
/**
* sendToStatsd is a helper method that sends the arguments to statsd
* and returns a pair { result, summary_string }.
@@ -192,6 +211,24 @@
});
}));
+ // Handle legacy aaudio stream statistics
+ mActions.addAction(
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
+ std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
+ std::make_shared<AnalyticsActions::Function>(
+ [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
+ mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
+ }));
+
+ // Handle mmap aaudio stream statistics
+ mActions.addAction(
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." AMEDIAMETRICS_PROP_EVENT,
+ std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
+ std::make_shared<AnalyticsActions::Function>(
+ [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
+ mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_MMAP);
+ }));
+
// Handle device use record statistics
mActions.addAction(
AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
@@ -843,4 +880,109 @@
}
}
+void AudioAnalytics::AAudioStreamInfo::endAAudioStream(
+ const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const {
+ const std::string& key = item->getKey();
+
+ std::string callerNameStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_CALLERNAME, &callerNameStr);
+
+ const auto callerName = types::lookup<types::CALLER_NAME, int32_t>(callerNameStr);
+
+ std::string directionStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr);
+ const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr);
+
+ int32_t framesPerBurst = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst);
+
+ int32_t bufferSizeInFrames = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames);
+
+ int32_t bufferCapacityInFrames = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames);
+
+ int32_t channelCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
+
+ int64_t totalFramesTransferred = -1;
+ // TODO: log and get total frames transferred
+
+ std::string perfModeRequestedStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr);
+ const auto perfModeRequested =
+ types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);
+
+ int32_t perfModeActual = 0;
+ // TODO: log and get actual performance mode
+
+ std::string sharingModeStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeStr);
+ const auto sharingMode = types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeStr);
+
+ int32_t xrunCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount);
+
+ std::string deviceType;
+ // TODO: only routed device id is logged, but no device type
+
+ int32_t formatApp = 0;
+ // TODO: log format from app
+
+ std::string formatDeviceStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr);
+ const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);
+
+ LOG(LOG_LEVEL) << "key:" << key
+ << " caller_name:" << callerName << "(" << callerNameStr << ")"
+ << " path:" << path
+ << " direction:" << direction << "(" << directionStr << ")"
+ << " frames_per_burst:" << framesPerBurst
+ << " buffer_size:" << bufferSizeInFrames
+ << " buffer_capacity:" << bufferCapacityInFrames
+ << " channel_count:" << channelCount
+ << " total_frames_transferred:" << totalFramesTransferred
+ << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
+ << " perf_mode_actual:" << perfModeActual
+ << " sharing:" << sharingMode << "(" << sharingModeStr << ")"
+ << " xrun_count:" << xrunCount
+ << " device_type:" << deviceType
+ << " format_app:" << formatApp
+ << " format_device: " << formatDevice << "(" << formatDeviceStr << ")";
+
+ // TODO: send the metric to statsd when the proto is ready
+ // if (mAudioAnalytics.mDeliverStatistics) {
+ // const auto [ result, str ] = sendToStatsd(AAudioStreamFields,
+ // CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
+ // , callerName
+ // , path
+ // , direction
+ // , framesPerBurst
+ // , bufferSizeInFrames
+ // , bufferCapacityInFrames
+ // , channelCount
+ // , totalFramesTransferred
+ // , perfModeRequested
+ // , perfModeActual
+ // , sharingMode
+ // , xrunCount
+ // , deviceType.c_str()
+ // , formatApp
+ // , formatDevice
+ // );
+ // ALOGV("%s: statsd %s", __func__, str.c_str());
+ // mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+ // }
+}
+
} // namespace android::mediametrics
diff --git a/services/mediametrics/AudioAnalytics.h b/services/mediametrics/AudioAnalytics.h
index df097b1..07872ef 100644
--- a/services/mediametrics/AudioAnalytics.h
+++ b/services/mediametrics/AudioAnalytics.h
@@ -189,6 +189,29 @@
int32_t mA2dpConnectionUnknowns GUARDED_BY(mLock) = 0;
} mDeviceConnection{*this};
+ // AAudioStreamInfo is a nested class which collect aaudio stream info from both client and
+ // server side.
+ class AAudioStreamInfo {
+ public:
+ // All the enum here must be kept the same as the ones defined in atoms.proto
+ enum CallerPath {
+ CALLER_PATH_UNKNOWN = 0,
+ CALLER_PATH_LEGACY = 1,
+ CALLER_PATH_MMAP = 2,
+ };
+
+ explicit AAudioStreamInfo(AudioAnalytics &audioAnalytics)
+ : mAudioAnalytics(audioAnalytics) {}
+
+ void endAAudioStream(
+ const std::shared_ptr<const android::mediametrics::Item> &item,
+ CallerPath path) const;
+
+ private:
+
+ AudioAnalytics &mAudioAnalytics;
+ } mAAudioStreamInfo{*this};
+
AudioPowerUsage mAudioPowerUsage{this};
};
diff --git a/services/mediametrics/AudioTypes.cpp b/services/mediametrics/AudioTypes.cpp
index 5d044bb..44e96ec 100644
--- a/services/mediametrics/AudioTypes.cpp
+++ b/services/mediametrics/AudioTypes.cpp
@@ -154,6 +154,40 @@
return map;
}
+const std::unordered_map<std::string, int32_t>& getAAudioDirection() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_DIRECTION_OUTPUT", 0},
+ {"AAUDIO_DIRECTION_INPUT", 1},
+ };
+ return map;
+}
+
+const std::unordered_map<std::string, int32_t>& getAAudioPerformanceMode() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_PERFORMANCE_MODE_NONE", 10},
+ {"AAUDIO_PERFORMANCE_MODE_POWER_SAVING", 11},
+ {"AAUDIO_PERFORMANCE_MODE_LOW_LATENCY", 12},
+ };
+ return map;
+}
+
+const std::unordered_map<std::string, int32_t>& getAAudioSharingMode() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_SHARING_MODE_EXCLUSIVE", 0},
+ {"AAUDIO_SHARING_MODE_SHARED", 1},
+ };
+ return map;
+}
+
// Helper: Create the corresponding int32 from string flags split with '|'.
template <typename Traits>
int32_t int32FromFlags(const std::string &flags)
@@ -433,4 +467,70 @@
return flagsFromMap(traits, getAudioTrackTraitsMap());
}
+template <>
+std::string lookup<AAUDIO_DIRECTION>(const std::string &direction)
+{
+ auto& map = getAAudioDirection();
+ auto it = map.find(direction);
+ if (it == map.end()) {
+ return "";
+ }
+ return direction;
+}
+
+template <>
+int32_t lookup<AAUDIO_DIRECTION>(const std::string &direction)
+{
+ auto& map = getAAudioDirection();
+ auto it = map.find(direction);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
+template <>
+std::string lookup<AAUDIO_PERFORMANCE_MODE>(const std::string &performanceMode)
+{
+ auto& map = getAAudioPerformanceMode();
+ auto it = map.find(performanceMode);
+ if (it == map.end()) {
+ return "";
+ }
+ return performanceMode;
+}
+
+template <>
+int32_t lookup<AAUDIO_PERFORMANCE_MODE>(const std::string &performanceMode)
+{
+ auto& map = getAAudioPerformanceMode();
+ auto it = map.find(performanceMode);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
+template <>
+std::string lookup<AAUDIO_SHARING_MODE>(const std::string &sharingMode)
+{
+ auto& map = getAAudioSharingMode();
+ auto it = map.find(sharingMode);
+ if (it == map.end()) {
+ return "";
+ }
+ return sharingMode;
+}
+
+template <>
+int32_t lookup<AAUDIO_SHARING_MODE>(const std::string &sharingMode)
+{
+ auto& map = getAAudioSharingMode();
+ auto it = map.find(sharingMode);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
} // namespace android::mediametrics::types
diff --git a/services/mediametrics/AudioTypes.h b/services/mediametrics/AudioTypes.h
index e1deeb1..4394d79 100644
--- a/services/mediametrics/AudioTypes.h
+++ b/services/mediametrics/AudioTypes.h
@@ -40,6 +40,9 @@
// Enumeration for all the string translations to integers (generally int32_t) unless noted.
enum AudioEnumCategory {
+ AAUDIO_DIRECTION,
+ AAUDIO_PERFORMANCE_MODE,
+ AAUDIO_SHARING_MODE,
CALLER_NAME,
CONTENT_TYPE,
ENCODING,
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